o
    Uhɯ                     @   sf  d 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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mZmZmZ ddlmZ ddl m!Z!m"Z"m#Z# ddl$m%Z%m&Z&m'Z' ddl(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z?m@Z@mAZAmBZBmCZCmDZDmEZEmFZFmZmGZGmHZHmIZImJZJmKZKmLZLmMZMmNZNmOZOmPZP ddlQmRZRmSZSmTZT ddlUmVZV eWeXZYG dd dZZG dd deZ[G dd deZZ\G dd deZZ]G dd dZ^G dd de^Z_G dd de_Z`dd  Zad!e%fd"d#Zbd!e%d$ecfd%d&Zdd!e%d$ecfd'd(ZeG d)d* d*ZfG d+d, d,Zge9e8dfZhG d-d. d.efZiG d/d0 d0efZjG d1d2 d2efZkG d3d4 d4e_ZlG d5d6 d6e^Zme`elemd7ZnG d8d9 d9ejoZpG d:d; d;ejqZrejsfdGd<d=Ztejsdejuejvfd$ewfd>d?Zxd@dA ZydBdC ZzdGdDdEZ{eXdFkret  dS dS )Ha  Git smart network protocol server implementation.

For more detailed implementation on the network protocol, see the
Documentation/technical directory in the cgit distribution, and in particular:

* Documentation/technical/protocol-capabilities.txt
* Documentation/technical/pack-protocol.txt

Currently supported capabilities:

 * include-tag
 * thin-pack
 * multi_ack_detailed
 * multi_ack
 * side-band-64k
 * ofs-delta
 * no-progress
 * report-status
 * delete-refs
 * shallow
 * symref
    N)IterableIterator)partial)Optionalcast)Protocol)	log_utils   )
tar_stream)ApplyDeltaErrorChecksumMismatchGitProtocolError	HookErrorNotGitRepositoryObjectFormatExceptionUnexpectedCommandError)peel_sha)CommitObjectIDvalid_hexsha)ObjectContainerPackedObjectContainerwrite_pack_from_container))CAPABILITIES_REFCAPABILITY_AGENTCAPABILITY_DELETE_REFSCAPABILITY_INCLUDE_TAGCAPABILITY_MULTI_ACKCAPABILITY_MULTI_ACK_DETAILEDCAPABILITY_NO_DONECAPABILITY_NO_PROGRESSCAPABILITY_OFS_DELTACAPABILITY_QUIETCAPABILITY_REPORT_STATUSCAPABILITY_SHALLOWCAPABILITY_SIDE_BAND_64KCAPABILITY_THIN_PACKCOMMAND_DEEPENCOMMAND_DONECOMMAND_HAVECOMMAND_SHALLOWCOMMAND_UNSHALLOWCOMMAND_WANT	MULTI_ACKMULTI_ACK_DETAILEDNAK_LINESIDE_BAND_CHANNEL_DATASIDE_BAND_CHANNEL_FATALSIDE_BAND_CHANNEL_PROGRESS
SINGLE_ACKTCP_GIT_PORTZERO_SHABufferedPktLineWriterr   ReceivableProtocolack_typecapability_agentextract_capabilitiesextract_want_line_capabilitiesformat_ack_lineformat_ref_lineformat_shallow_lineformat_unshallow_linesymref_capabilities)PEELED_TAG_SUFFIXRefsContainerwrite_info_refs)Repoc                   @   s   e Zd ZdZdddZdS )Backendz2A backend for the Git smart server implementation.returnBackendRepoc                 C   
   t | j)zOpen the repository at a path.

        Args:
          path: Path to the repository
        Raises:
          NotGitRepository: no git repository was found at path
        Returns: Instance of BackendRepo
        )NotImplementedErroropen_repository)selfpath rM   b/var/www/html/construction_image-detection-poc/venv/lib/python3.10/site-packages/dulwich/server.pyrJ   }   s   
	zBackend.open_repositoryN)rF   rG   )__name__
__module____qualname____doc__rJ   rM   rM   rM   rN   rE   z   s    rE   c                   @   sd   e Zd ZU dZeed< eed< deeef fddZ	dede
e fdd	Z	
ddee fddZd
S )rG   zRepository abstraction used by the Git server.

    The methods required here are a subset of those provided by
    dulwich.repo.Repo.
    object_storerefsrF   c                 C      t )zRGet all the refs in the repository.

        Returns: dict of name -> sha
        rI   rK   rM   rM   rN   get_refs   s   zBackendRepo.get_refsnamec                 C   s   dS )a  Return the cached peeled value of a ref, if available.

        Args:
          name: Name of the ref to peel
        Returns: The peeled value of the ref. If the ref is known not point to
            a tag, this will be the SHA the ref refers to. If no cached
            information about a tag is available, this method may return None,
            but it should attempt to peel the tag if possible.
        NrM   )rK   rY   rM   rM   rN   
get_peeled      
zBackendRepo.get_peeledNc                 C   rU   )a  Yield the objects required for a list of commits.

        Args:
          progress: is a callback to send progress messages to the client
          get_tagged: Function that returns a dict of pointed-to sha ->
            tag sha for including tags.
        rV   )rK   determine_wantsgraph_walkerprogress
get_taggedrM   rM   rN   find_missing_objects   r[   z BackendRepo.find_missing_objectsN)rO   rP   rQ   rR   r   __annotations__rB   dictbytesrX   r   rZ   r   r   r`   rM   rM   rM   rN   rG      s   
 rG   c                   @   s,   e Zd ZdZd	ddZdedefddZdS )
DictBackendz?Trivial backend that looks up Git repositories in a dictionary.rF   Nc                 C   
   || _ d S ra   )repos)rK   rg   rM   rM   rN   __init__      
zDictBackend.__init__rL   c              
   C   sN   t d| z| j| W S  ty& } ztdjdi t|d|d }~ww )NzOpening repository at %sz%No git repository was found at {path})rL   rM   )loggerdebugrg   KeyErrorr   formatrc   )rK   rL   excrM   rM   rN   rJ      s   zDictBackend.open_repositoryrF   N)rO   rP   rQ   rR   rh   strrG   rJ   rM   rM   rM   rN   re      s    
re   c                       s0   e Zd ZdZejfd fddZdd Z  ZS )	FileSystemBackendzDSimple backend looking up Git repositories in the local file system.rF   Nc                    s2   t    tj|tj tjd tj| _d S )N   )superrh   osrL   abspathsepreplaceroot)rK   rx   	__class__rM   rN   rh      s   
(zFileSystemBackend.__init__c                 C   sl   t d| tjtj| j|tj }tj|}tj| j}|	|s2t
d|d| jt|S )Nzopening repository at %szPath z not inside root )rj   rk   rt   rL   ru   joinrx   rv   normcase
startswithr   rD   )rK   rL   ru   normcase_abspathnormcase_rootrM   rM   rN   rJ      s   
z!FileSystemBackend.open_repositoryro   )	rO   rP   rQ   rR   rt   rv   rh   rJ   __classcell__rM   rM   ry   rN   rq      s    rq   c                   @   s&   e Zd ZdZd	d
ddZd
ddZdS )Handlerz*Smart protocol command handler base class.FrF   Nc                 C   s   || _ || _|| _d S ra   )backendprotostateless_rpcrK   r   r   r   rM   rM   rN   rh         
zHandler.__init__c                 C   rH   ra   )rI   handlerW   rM   rM   rN   r      ri   zHandler.handleFro   )rO   rP   rQ   rR   rh   r   rM   rM   rM   rN   r      s    r   c                       s   e Zd ZdZdd fddZedee fddZedee fd	d
Z	edee fddZ
dee ddfddZdedefddZdddZ  ZS )PackHandlerzProtocol handler for packs.FrF   Nc                    s    t  ||| d | _d| _d S NF)rs   rh   _client_capabilities_done_receivedr   ry   rM   rN   rh      s   
zPackHandler.__init__c                 C   rH   ra   )rI   capabilitiesclsrM   rM   rN   r      s   
zPackHandler.capabilitiesc                 C   s   t tttt gS ra   )r   r&   r    r!   r9   r   rM   rM   rN   innocuous_capabilities   s   z"PackHandler.innocuous_capabilitiesc                 C   s   g S )zAReturn a list of capabilities that we require the client to have.rM   r   rM   rM   rN   required_capabilities   s   z!PackHandler.required_capabilitiescapsc                 C   s   t |  }||   |D ]}|td rq||vr%td|dq|  D ]}||vr8td|dq*t || _t	
d| d S )N   =zClient asked for capability z that was not advertised.z,Client does not support required capability .zClient capabilities: %s)setr   updater   r}   r   r   r   r   rj   info)rK   r   allowable_capscaprM   rM   rN   set_client_capabilities   s$   


z#PackHandler.set_client_capabilitiesr   c                 C   s$   | j d u rtd|d|| j v S )Nz&Server attempted to access capability z before asking client)r   r   )rK   r   rM   rM   rN   has_capability  s
   


zPackHandler.has_capabilityc                 C   s
   d| _ d S )NT)r   rW   rM   rM   rN   notify_done  ri   zPackHandler.notify_doner   ro   )rO   rP   rQ   rR   rh   classmethodr   rd   r   r   r   r   boolr   r   r   rM   rM   ry   rN   r      s    	r   c                       s~   e Zd ZdZ	d	d fddZedd Zed	d
 ZdeddfddZ	dddZ
ddeeef fddZdddZ  ZS )UploadPackHandlerz4Protocol handler for uploading a pack to the client.FrF   Nc                    s8   t  j|||d ||d | _d | _|| _d| _d S )Nr   r   F)rs   rh   rJ   repo_graph_walkeradvertise_refs_processing_have_linesrK   r   argsr   r   r   ry   rM   rN   rh     s
   
zUploadPackHandler.__init__c              	   C   s   t ttttttttg	S ra   )	r   r   r%   r&   r!   r    r   r$   r   r   rM   rM   rN   r   (  s   zUploadPackHandler.capabilitiesc                 C   s
   t ttfS ra   )r%   r&   r!   r   rM   rM   rN   r   6  s   z'UploadPackHandler.required_capabilitiesmessagec                 C      d S ra   rM   )rK   r   rM   rM   rN   r^   >     zUploadPackHandler.progressc                 C   sF   |  tr|  tst| jjt| _t| jjt| _	d S | jj
| _	d S ra   )r   r%   r    r   r   write_sidebandr2   r^   r0   write_pack_datawriterW   rM   rM   rN   _start_pack_send_phaseA  s   


z(UploadPackHandler._start_pack_send_phasec                 C   sv   |  tsi S |du r| j }|du r!t| jdd}|du r!i S i }| D ]\}}||}||kr8|||< q'|S )a  Get a dict of peeled values of tags to their original tag shas.

        Args:
          refs: dict of refname -> sha of possible tags; defaults to all
            of the backend's refs.
          repo: optional Repo instance for getting peeled refs; defaults
            to the backend's repo, if available
        Returns: dict of peeled_sha -> tag_sha, where tag_sha is the sha of a
            tag whose peeled value is peeled_sha.
        Nr   )r   r   r   rX   getattritemsrZ   )rK   rT   r   taggedrY   sha
peeled_sharM   rM   rN   r_   P  s   


zUploadPackHandler.get_taggedc                    s   d| _ t| | jj| jj| jjj g  fdd}| jj| | j| j	d}t
|}tdkr2d S  | t | js?d S |   | dt| dd t| j| jj| | jd  d S )	NTc                    s     j| fi | S ra   )extendr\   )rT   kwargsr]   wantsrM   rN   wants_wrapper~  s   z/UploadPackHandler.handle.<locals>.wants_wrapper)r_   r   zcounting objects: z, done.
ascii)r   _ProtocolGraphWalkerr   rS   rZ   rT   get_symrefsr`   r^   r_   listlenhandle_doner   r   r   r   encoder   r   r   write_pkt_line)rK   r   missing_objects
object_idsrM   r   rN   r   p  s8   zUploadPackHandler.handleFFro   )NN)rO   rP   rQ   rR   rh   r   r   r   rd   r^   r   rc   r   r_   r   r   rM   rM   ry   rN   r     s    


 r   c                 C   s   | sdg}n	|  ddd}|d }|dur||vrt|t|dkr/|tdfv r/|dfS t|dkrW|ttttfv rKt	|d sGt
dt|S |tkrW|t|d fS t
d| )	ac  Split a line read from the wire.

    Args:
      line: The line read from the wire.
      allowed: An iterable of command names that should be allowed.
        Command names not listed below as possible return values will be
        ignored.  If None, any commands from the possible return values are
        allowed.
    Returns: a tuple having one of the following forms:
        ('want', obj_id)
        ('have', obj_id)
        ('done', None)
        (None, None)  (for a flush-pkt)

    Raises:
      UnexpectedCommandError: if the line cannot be parsed into one of the
        allowed return values.
    N   
    r	   r   rr   zInvalid shaz#Received invalid line from client: )rstripsplitr   r   r(   r,   r)   r*   r+   r   r   tupler'   int)lineallowedfieldscommandrM   rM   rN   _split_proto_line  s*   r   storec                    s   i fdd}g }|D ]}t |\}}t|tr#||jdf qt }t }	|rU| \}
}||k rN||
 |d  | fdd||
D  n|	|
 |s,|	|fS )a  Find shallow commits according to a given depth.

    Args:
      store: An ObjectStore for looking up objects.
      heads: Iterable of head SHAs to start walking from.
      depth: The depth of ancestors to include. A depth of one includes
        only the heads themselves.
    Returns: A tuple of (shallow, not_shallow), sets of SHAs that should be
        considered shallow and unshallow according to the arguments. Note that
        these sets may overlap if a commit is reachable along multiple paths.
    c                    s&     | d }|s|  j}| | < |S ra   )getparents)r   result)r   r   rM   rN   get_parents  s
   
z"_find_shallow.<locals>.get_parentsr	   c                 3   s    | ]}| fV  qd S ra   rM   ).0p)	new_depthrM   rN   	<genexpr>  s    z _find_shallow.<locals>.<genexpr>)	r   
isinstancer   appendidr   popaddr   )r   headsdepthr   todohead_sha	_unpeeledpeelednot_shallowshallowr   	cur_depthrM   )r   r   r   rN   _find_shallow  s&   


	r   rF   c           
      C   s   | | }t |g}|h}|rG| }|j|v rdS t|ts q|jD ]!}||v r*q#|| | | }	t|	ts:J |	j|krD|	|	 q#|sdS )NTF)
collectionsdequepopleftr   r   r   r   r   commit_timer   )
r   haveswantearliestopendingknowncommitparent
parent_objrM   rM   rN   _want_satisfied  s(   





r   c                    sX   t |}|r fdd|D }tdd |D }nd}|D ]}t |||s) dS qdS )a~  Check whether all the current wants are satisfied by a set of haves.

    Args:
      store: Object store to retrieve objects from
      haves: A set of commits we know the client has.
      wants: A set of commits the client wants
    Note: Wants are specified with set_wants rather than passed in since
        in the current interface they are determined outside this class.
    c                    s   g | ]} | qS rM   rM   r   hr   rM   rN   
<listcomp>  s    z(_all_wants_satisfied.<locals>.<listcomp>c                 S   s   g | ]
}t |tr|jqS rM   )r   r   r   r   rM   rM   rN   r     s    r   FT)r   minr   )r   r   r   	have_objsr   r   rM   r   rN   _all_wants_satisfied  s   
r   c                   @   s&   e Zd Zdd ZdeddfddZdS )AckGraphWalkerImplc                 C   rU   ra   rV   )rK   r]   rM   rM   rN   rh   &  r   zAckGraphWalkerImpl.__init__have_refrF   Nc                 C   rU   ra   rV   rK   r   rM   rM   rN   ack)  r   zAckGraphWalkerImpl.ack)rO   rP   rQ   rh   r   r   rM   rM   rM   rN   r   %  s    r   c                   @   s   e Zd ZdZdeddfddZd&ddZd'd	d
Zd'ddZdd Z	d'ddZ
dd ZeZdd Zd'ddZd'ddZd(d'ddZd'ddZdd Zd'd d!Zd"d# Zd'd$d%ZdS ))r   a7  A graph walker that knows the git protocol.

    As a graph walker, this class implements ack(), next(), and reset(). It
    also contains some base methods for interacting with the wire and walking
    the commit tree.

    The work of determining which acks to send is passed on to the
    implementation instance stored in _impl. The reason for this is that we do
    not know at object creation time what ack level the protocol requires. A
    call to set_ack_type() is required to set up the implementation, before
    any calls to next() or ack() are made.
    rS   rF   Nc                 C   sj   || _ || _|| _|| _|j| _|j| _|j| _g | _t | _	t | _
t | _d| _g | _d| _d | _d S )NFr   )handlerr   rZ   r   r   r   r   _wantsr   r   client_shallow	unshallow_cached_cache_cache_index_impl)rK   r   rS   rZ   r   rM   rM   rN   rh   ;  s   
z_ProtocolGraphWalker.__init__c              	   C   s  |   }t| }| js| jsrtt| D ]N\}\}}z| |}W n	 t	y.   Y qw |dkrLt
d| j  t||| j t|  }	nt||}	| j|	 ||krf| jt|t | q| jd | jrrg S | j }
|
s{g S t|
\}	}| j| | t| tttdf}t|	|\}}g }|tkr||vrtd| || | |\}}|tks| | |ttfv r|  || | !| | jr| j" rg S |S )a-  Determine the wants for a set of heads.

        The given heads are advertised to the client, who then specifies which
        refs they want using 'want' lines. This portion of the protocol is the
        same regardless of ack type, and in fact is used to set the ack type of
        the ProtocolGraphWalker.

        If the client has the 'shallow' capability, this method also reads and
        responds to the 'shallow' and 'deepen' lines from the client. These are
        not part of the wants per se, but they set up necessary state for
        walking the graph. Additionally, later code depends on this method
        consuming everything up to the first 'have' line.

        Args:
          heads: a dict of refname->SHA1 to advertise
        Returns: a list of SHA1s requested by the client
        r   Sending capabilities: %sNzClient wants invalid object )#r   r   valuesr   r   	enumeratesortedr   rZ   rl   rj   r   r   r   r=   r@   r   r   rA   read_pkt_liner;   r   set_ack_typer8   r,   r*   r'   r   r   r   read_proto_line	set_wantsunread_proto_line_handle_shallow_requesteof)rK   r   r   symrefsr  irefr   r   r   r   r   r   r   	want_revsrM   rM   rN   r\   N  sd   





z$_ProtocolGraphWalker.determine_wantsc                 C   s0   t |trt|d}| j|d |  d S )Nr   r   )r   r   rp   r   r   unread_pkt_line)rK   r   valuerM   rM   rN   r    s   
z&_ProtocolGraphWalker.unread_proto_linec                 C   r   ra   rM   rW   rM   rM   rN   nak  r   z_ProtocolGraphWalker.nakc                 C   s&   t |dkrtd|| j|S )N(   zinvalid sha )r   
ValueErrorr  r   r   rM   rM   rN   r     s   z_ProtocolGraphWalker.ackc                 C   s   d| _ d| _d S )NTr   )r  r  rW   rM   rM   rN   reset     
z_ProtocolGraphWalker.resetc                 C   sN   | j s| js| jrd S t| jS |  jd7  _| jt| jkr!d S | j| j S )Nr	   )r  r  r   nextr  r   r  rW   rM   rM   rN   r    s   
z_ProtocolGraphWalker.nextc                 C   s   t | j |S )a  Read a line from the wire.

        Args:
          allowed: An iterable of command names that should be allowed.
        Returns: A tuple of (command, value); see _split_proto_line.

        Raises:
          UnexpectedCommandError: If an error occurred reading the line.
        )r   r   r  )rK   r   rM   rM   rN   r    s   
z$_ProtocolGraphWalker.read_proto_linec           
      C   s   	 |  ttf\}}|tkr|}n| j| q|  d t| j||\}}| j||  | j| j }|| j@  }| _	t
|D ]
}	| jt|	 q@t
|D ]
}	| jt|	 qO| jd  d S )NTra   )r  r'   r*   r  r   r   r   r   r   r  r
  r   r   r>   r?   )
rK   r   r   valr   r   r   new_shallowr  r   rM   rM   rN   r    s"   
z,_ProtocolGraphWalker._handle_shallow_requestc                 C   s   | j   d S ra   )r   r   rW   rM   rM   rN   r        z _ProtocolGraphWalker.notify_done    c                 C   s   | j t|| d S ra   )r   r   r<   )rK   r   r8   rM   rM   rN   send_ack  s   z_ProtocolGraphWalker.send_ackc                 C   s   | j t d S ra   )r   r   r/   rW   rM   rM   rN   send_nak  s   z_ProtocolGraphWalker.send_nakc                 C   s   | j ||S ra   )r  r   rK   done_requireddone_receivedrM   rM   rN   r     r   z _ProtocolGraphWalker.handle_donec                 C   rf   ra   )r   )rK   r   rM   rM   rN   r    ri   z_ProtocolGraphWalker.set_wantsc                 C   s   t | j|| jS )a0  Check whether all the current wants are satisfied by a set of haves.

        Args:
          haves: A set of commits we know the client has.
        Note: Wants are specified with set_wants rather than passed in since
            in the current interface they are determined outside this class.
        )r   r   r   )rK   r   rM   rM   rN   all_wants_satisfied  s   z(_ProtocolGraphWalker.all_wants_satisfiedc                 C   s"   t ttttti}|| | | _d S ra   )r-   MultiAckGraphWalkerImplr.   MultiAckDetailedGraphWalkerImplr3   SingleAckGraphWalkerImplr  )rK   r8   impl_classesrM   rM   rN   r    s
   z!_ProtocolGraphWalker.set_ack_typera   ro   )r!  )rO   rP   rQ   rR   r   rh   r\   r  r  r   r  r  __next__r  r  r   r"  r#  r   r  r'  r  rM   rM   rM   rN   r   -  s.    


R







r   c                   @   >   e Zd ZdZdddZdddZdd	 ZeZdefd
dZ	dS )r*  z@Graph walker implementation that speaks the single-ack protocol.rF   Nc                 C      || _ g | _d S ra   walker_commonrK   r0  rM   rM   rN   rh     r  z!SingleAckGraphWalkerImpl.__init__c                 C   s&   | j s| j| | j | d S d S ra   )r1  r0  r"  r   r   rM   rM   rN   r     s   zSingleAckGraphWalkerImpl.ackc                 C   s:   | j t\}}|d tfv r| j   d S |tkr|S d S ra   )r0  r  _GRAPH_WALKER_COMMANDSr(   r   r)   rK   r   r   rM   rM   rN   r    s   
zSingleAckGraphWalkerImpl.nextc                 C   s.   | j s| j  |r|sdS |s| j sdS dS )NFT)r1  r0  r#  r$  rM   rM   rN   r     s   

z$SingleAckGraphWalkerImpl.handle_donero   
rO   rP   rQ   rR   rh   r   r  r,  r   r   rM   rM   rM   rN   r*    s    

	r*  c                   @   r-  )r(  z?Graph walker implementation that speaks the multi-ack protocol.rF   Nc                 C   s   || _ d| _g | _d S r   )r0  _found_baser1  r2  rM   rM   rN   rh   7  r   z MultiAckGraphWalkerImpl.__init__c                 C   s@   | j | | js| j|d | j| j rd| _d S d S d S )N   continueT)r1  r   r6  r0  r"  r'  r   rM   rM   rN   r   <  s   
zMultiAckGraphWalkerImpl.ackc                 C   s^   	 | j t\}}|d u r| j   q |tkr| j   d S |tkr.| jr,| j |d |S q)NTr7  )	r0  r  r3  r#  r(   r   r)   r6  r"  r4  rM   rM   rN   r  D  s   

zMultiAckGraphWalkerImpl.nextc                 C   D   |r|sdS |s| j sdS | j r| j| j d  dS | j  dS NFTr1  r0  r"  r#  r$  rM   rM   rN   r   W     

z#MultiAckGraphWalkerImpl.handle_donero   r5  rM   rM   rM   rN   r(  4  s    

r(  c                   @   r-  )r)  zEGraph walker implementation speaking the multi-ack-detailed protocol.rF   Nc                 C   r.  ra   r/  r2  rM   rM   rN   rh   r  r  z(MultiAckDetailedGraphWalkerImpl.__init__c                 C   s   | j | | j|d d S )Ns   common)r1  r   r0  r"  r   rM   rM   rN   r   v  s   z#MultiAckDetailedGraphWalkerImpl.ackc                 C   sx   	 | j t\}}|d u r*| j | jr| j | jd d | j   | j jr)d S n|tkr5| j 	  d S |t
kr;|S q)NTr:  s   ready)r0  r  r3  r'  r1  r"  r#  r   r(   r   r)   r4  rM   rM   rN   r  {  s   
	
z$MultiAckDetailedGraphWalkerImpl.nextc                 C   r8  r9  r;  r$  rM   rM   rN   r     r<  z+MultiAckDetailedGraphWalkerImpl.handle_donero   r5  rM   rM   rM   rN   r)  o  s    

r)  c                       s   e Zd ZdZ	d	d fddZedee fddZd	e	e
eeef  de	e
eef  fd
dZde	e
eef  ddfddZdddZdddZ  ZS )ReceivePackHandlerz8Protocol handler for downloading a pack from the client.FrF   Nc                    s,   t  j|||d ||d | _|| _d S )Nr   r   )rs   rh   rJ   r   r   r   ry   rM   rN   rh     s   
zReceivePackHandler.__init__c                 C   s   t tttttgS ra   )r#   r   r"   r!   r%   r   r   rM   rM   rN   r     s   zReceivePackHandler.capabilitiesrT   c              
   C   sv  t tttttjtjtf}g }d}|D ]
}|d t	krd}q|rZzt
| jdd }| jj| jj| |d W n' |yY } z|dt|ddd	f W Y d }~n
d }~ww |d |D ]W\}}	}
d
}z=|	t	krt|  vrwtdz
| jj|
| W n" |y   d}Y nw z| jj|
||	 W n |y   d}Y nw W n ty   d}Y nw ||
|f qa|S )NFr	   Trecv)   unpack   okr?  
 utf-8r@  z8Attempted to delete refs without delete-refs capability.s   failed to deletes   failed to writes   bad ref)IOErrorOSErrorr   r   AssertionErrorsocketerrorzlibr   r5   r   r   r   rS   add_thin_packreadr   rp   rw   r   r   r   r   rT   remove_if_equalsset_if_equalsrl   )rK   rT   all_exceptionsstatuswill_send_packr   r>  eoldshar   r  
ref_statusrM   rM   rN   _apply_pack  sb   
,
zReceivePackHandler._apply_packrO  c                    s     trt fddj}d fdd}n	 jj}ddd}|D ]*\}}|dkr5|d| d	  q$|d
krB|d| d	  q$|d| d | d	  q$|d  |  d S )Nc                        j t| S ra   r   r   r0   )drW   rM   rN   <lambda>  s    z3ReceivePackHandler._report_status.<locals>.<lambda>rF   c                      s       jd  d S ra   )flushr   r   rM   rK   writerrM   rN   rY    s   z0ReceivePackHandler._report_status.<locals>.flushc                   S   r   ra   rM   rM   rM   rM   rN   rY    r   r?  s   unpack r   r@  s   ok s   ng r   ro   )r   r%   r6   r   r   r   )rK   rO  r   rY  rY   msgrM   rZ  rN   _report_status   s    



z!ReceivePackHandler._report_statusc              
   C   s   | j jdd }|sd S z||}|r| jt| W d S W d S  ty? } z| jtt	|
d W Y d }~d S d }~ww )Nzpost-receiverC  )r   hooksr   executer   r   r2   r   r1   rp   r   )rK   client_refshookoutputerrrM   rM   rN   _on_post_receive  s   
&z#ReceivePackHandler._on_post_receivec                 C   sL  | j s| jsft| j  }t| jj  }|s tt	fg}t
d|   | jt|d d |d d |  t|  tdt|D ]}|| }| jt|d |d  qG| jd  | j rfd S g }| j }|d u rsd S t|\}}| | |r||  | j }|s| |}| | | tr| | d S d S )Nr  r   r	   )r   r   r
  r   rX   r   rT   r   r   r5   rj   r   r   r   r   r=   r@   ranger   r  r:   r   r   r   rT  rd  r   r#   r]  )rK   rT   r  r  r  r`  r   rO  rM   rM   rN   r   &  sD   








zReceivePackHandler.handler   ro   )rO   rP   rQ   rR   rh   r   r   rd   r   r   r   rT  r]  rd  r   r   rM   rM   ry   rN   r=    s     

;
r=  c                       s*   e Zd Zdd	 fddZd	ddZ  ZS )
UploadArchiveHandlerFrF   Nc                    s$   t  ||| ||d | _d S )Nr   )rs   rh   rJ   r   )rK   r   r   r   r   ry   rM   rN   rh   X  s   zUploadArchiveHandler.__init__c                    s8   fdd}g } j  D ]}|dd\}}|dkr"td| ||d qd}d	}d
} jj}	|t|k rv|| }
|
dkrL|d7 }|| }n |
dkr\|d7 }|| 	d}n jj
|
 }|	tt|	| j }|d7 }|t|k s; j d  j d  t|	|t ||dD ]}|| q j d  d S )Nc                    rU  ra   rV  )xrW   rM   rN   r   ]  s   z*UploadArchiveHandler.handle.<locals>.writer   r	   s   argumentzunknown command r   r!  tarr   s   --prefixs   --formatr   s   ACK)mtimeprefixrm   )r   read_pkt_seqr   r   r   r   r   rS   r   decoderT   r   r   treer   r
   time)rK   r   	argumentspktkeyr  rj  rm   r  r   argument
commit_sharm  chunkrM   rW   rN   r   \  s<   


zUploadArchiveHandler.handler   ro   )rO   rP   rQ   rh   r   r   rM   rM   ry   rN   rf  W  s    rf  )s   git-upload-packs   git-receive-packs   git-upload-archivec                   @   s    e Zd ZdddZdddZdS )TCPGitRequestHandlerrF   Nc                 O   s$   || _ tjj| g|R i | d S ra   )handlerssocketserverStreamRequestHandlerrh   )rK   rv  r   r   rM   rM   rN   rh     s   zTCPGitRequestHandler.__init__c                 C   sl   t | jj| jj}| \}}td|| | j	|d }t
|s(td| || jj||}|  d S )NzHandling %s request, args=%szInvalid service )r7   
connectionr>  wfiler   read_cmdrj   r   rv  r   callabler   serverr   r   )rK   r   r   r   r   r   rM   rM   rN   r     s   zTCPGitRequestHandler.handlero   )rO   rP   rQ   rh   r   rM   rM   rM   rN   ru    s    
ru  c                   @   sH   e Zd ZdZejjZdd Ze	dfdddZ
defdd	Zdd
dZdS )TCPGitServerTc                 O   s   t | jg|R i |S ra   )ru  rv  )rK   r   r   rM   rM   rN   _make_handler  s   zTCPGitServer._make_handlerNrF   c                 C   sL   t t| _|d ur| j| || _td|| tj	| ||f| j
 d S )Nz&Listening for TCP connections on %s:%d)rc   DEFAULT_HANDLERSrv  r   r   rj   r   rw  	TCPServerrh   r  )rK   r   listen_addrportrv  rM   rM   rN   rh     s   
zTCPGitServer.__init__c                 C   s   t d| dS )NzHandling request from %sT)rj   r   rK   requestclient_addressrM   rM   rN   verify_request  s   zTCPGitServer.verify_requestc                 C   s   t d| d S )Nz7Exception happened during processing of request from %s)rj   	exceptionr  rM   rM   rN   handle_error  s   zTCPGitServer.handle_errorro   )rO   rP   rQ   allow_reuse_addressrw  r  serve_foreverserver  r4   rh   r   r  r  rM   rM   rM   rN   r~    s    r~  c                 C   s   ddl }| }|jdddddd |jd	d
dttdd || \}}t  t|dkr3|d }nd}t	|}t
||j|j}|  dS )z*Entry point for starting a TCP git server.r   Nz-lz--listen_addresslisten_address	localhostzBinding IP address.)destdefaulthelpz-pz--portr  zBinding TCP port.)r  typer  r  r	   r   )optparseOptionParser
add_optionr   r4   
parse_argsr   default_logging_configr   rq   r~  r  r  r  )argvr  parseroptionsr   gitdirr   r}  rM   rM   rN   main  s2   
r  c                    sH   |du rt  }d fdd}t|j|}| ||dd |}|  dS )a  Serve a single command.

    This is mostly useful for the implementation of commands used by e.g.
    git+ssh.

    Args:
      handler_cls: `Handler` class to use for the request
      argv: execv-style command-line arguments. Defaults to sys.argv.
      backend: `Backend` to use
      inf: File-like object to read from, defaults to standard input.
      outf: File-like object to write to, defaults to standard output.
    Returns: Exit code for use with sys.exit. 0 on success, 1 on failure.
    NrF   c                    s     |     d S ra   )r   rY  )dataoutfrM   rN   send_fn  s   
zserve_command.<locals>.send_fnr	   r   ro   )rq   r   rK  r   )handler_clsr  r   infr  r  r   r   rM   r  rN   serve_command  s   r  c                 C   s   |   }t|| jS )zGenerate an info refs file.)rX   rC   rS   )r   rT   rM   rM   rN   generate_info_refs  s   r  c                 c   s,    | j jD ]}dt|jj d V  qdS )z Generate an index for for packs.s   P r   N)rS   packsrt   fsencoder  filename)r   packrM   rM   rN   generate_objects_info_packs  s   r  c                 C   sF   |  tjdddt|  |  tjddddt|  dS )zGenerate server info for dumb file access.

    This generates info/refs and objects/info/packs,
    similar to "git update-server-info".
    r   rT   r!  objectsr  N)_put_named_filert   rL   r{   r  r  )r   rM   rM   rN   update_server_info  s   r  __main__ro   )|rR   r   rt   rG  rw  sysrn  rI  collections.abcr   r   	functoolsr   typingr   r   r   TypingProtocoldulwichr   archiver
   errorsr   r   r   r   r   r   r   rS   r   r  r   r   r   r  r   r   r   protocolr   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   r@   rT   rA   rB   rC   r   rD   	getLoggerrO   rj   rE   rG   re   rq   r   r   r   r   r   r   r   r   r   r   r3  r*  r(  r)  r=  rf  r  rx  ru  r  r~  r  r  stdinstdoutr   r  r  r  r  rM   rM   rM   rN   <module>   sz   $	+
*9 +) 
Y,;A (*"



