a
    &0É_ÉV  ã                   @   s  d dl mZ d dlZd dlZddlmZ ddlmZ ddlm	Z	m
Z
 ddlmZmZmZmZmZmZmZmZ ddlmZmZ dd	lmZ ejZd
d„ ZG dd„ deƒZdd„ ZG dd„ dejj ƒZ!e "ej#¡G dd„ deƒƒZ$e "ej%ej&¡G dd„ dej'ƒƒZ(dS )é    )Úabsolute_importNé   )Ú_)Úbin)ÚgetattrÚsetattr)Úbundle2ÚchangegroupÚencodingÚerrorÚpushkeyÚpycompatÚutilÚwireprototypes)Ú
repositoryr   )Úhashutilc                    s*   ‡ fdd„}t |dˆ ƒ t |dˆ jƒ |S )aU  annotation for batchable methods

    Such methods must implement a coroutine as follows:

    @batchable
    def sample(self, one, two=None):
        # Build list of encoded arguments suitable for your wire protocol:
        encargs = [('one', encode(one),), ('two', encode(two),)]
        # Create future for injection of encoded result:
        encresref = future()
        # Return encoded arguments and future:
        yield encargs, encresref
        # Assuming the future to be filled with the result from the batched
        # request now. Decode it:
        yield decode(encresref.value)

    The decorator returns a function which wraps this coroutine as a plain
    method, but adds the original method as an attribute called "batchable",
    which is used by remotebatch to split the call into separate encoding and
    decoding phases.
    c                     sP   ˆ | i |¤Ž}t |ƒ\}}|s"|S | d }t ˆ j¡}| | ||¡¡ t |ƒS )Nr   )Únextr   ZbytesurlÚ__name__ÚsetÚ
_submitone)ÚargsÚoptsÚ	batchableÚencargsorresZ	encresrefÚselfÚcmd©Úf© ú;/usr/lib/python3/dist-packages/mercurial/wireprotov1peer.pyÚplain=   s    zbatchable.<locals>.plainr   r   )r   r   )r   r    r   r   r   r   &   s    
r   c                   @   s   e Zd ZdZdd„ ZdS )Úfuturez'placeholder for a value to be set laterc                 C   s    t  | d¡rt d¡‚|| _d S )Ns   values   future is already set)r   Úsafehasattrr   Ú	RepoErrorÚvalue)r   r$   r   r   r   r   O   s    
z
future.setN)r   Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   r   r!   L   s   r!   c                    sl   t j‰ g }| D ]R\}}t‡ fdd„|D ƒƒs0J ‚d ‡ fdd„t |¡D ƒ¡}| d||f ¡ qd |¡S )z;Return a ``cmds`` argument value for the ``batch`` command.c                 3   s   | ]}ˆ |ƒ|kV  qd S ©Nr   )Ú.0Úk©Z	escapeargr   r   Ú	<genexpr>^   ó    z"encodebatchcmds.<locals>.<genexpr>ó   ,c                 3   s&   | ]\}}d ˆ |ƒˆ |ƒf V  qdS )s   %s=%sNr   )r)   r*   Úvr+   r   r   r,   `   s   ÿs   %s %só   ;)r   ZescapebatchargÚallÚjoinr   Ú	iteritemsÚappend)ÚreqÚcmdsÚopZargsdictr   r   r+   r   ÚencodebatchcmdsU   s    þr8   c                   @   s   e Zd ZdZddd„ZdS )Úunsentfuturea0  A Future variation to represent an unsent command.

    Because we buffer commands and don't submit them immediately, calling
    ``result()`` on an unsent future could deadlock. Futures for buffered
    commands are represented by this type, which wraps ``result()`` to
    call ``sendcommands()``.
    Nc                 C   s,   |   ¡ rtjj | |¡S | j ¡  |  |¡S r(   )Údoner   ÚfuturesÚFutureÚresultÚ_peerexecutorÚsendcommands)r   Ztimeoutr   r   r   r=   r   s    
zunsentfuture.result)N)r   r%   r&   r'   r=   r   r   r   r   r9   i   s   r9   c                   @   sD   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	d
„ Zdd„ Zdd„ Z	dS )Úpeerexecutorc                 C   s2   || _ d| _d| _g | _t ¡ | _d | _d | _d S )NF)	Ú_peerÚ_sentÚ_closedÚ_callsÚweakrefÚWeakSetÚ_futuresÚ_responseexecutorÚ
_responsef)r   Úpeerr   r   r   Ú__init__€   s    
zpeerexecutor.__init__c                 C   s   | S r(   r   ©r   r   r   r   Ú	__enter__‰   s    zpeerexecutor.__enter__c                 C   s   |   ¡  d S r(   )Úclose)r   ÚexctypeZexcvaleeÚexctbr   r   r   Ú__exit__Œ   s    zpeerexecutor.__exit__c                    sž   ˆj rt d¡‚ˆjr t d¡‚tˆjt ˆ¡d ƒ‰ˆsFt dˆ ¡‚‡ ‡‡‡fdd„}tˆddƒrx|ƒ }t|_	ˆ|_
n"ˆjrŒt dˆ ¡‚|ƒ }ˆ ¡  |S )	Ns4   callcommand() cannot be used after commands are sents*   callcommand() cannot be used after close()sA   cannot call command %s: method of same name not available on peerc                     s.   t j ¡ } ˆj | ¡ ˆj ˆˆ ˆ| f¡ | S r(   )r   r;   r<   rG   ÚaddrD   r4   r   ©r   ÚcommandÚfnr   r   r   Úaddcallª   s    
z)peerexecutor.callcommand.<locals>.addcallr   FsX   %s is not batchable and cannot be called on a command executor along with other commands)rB   r   ÚProgrammingErrorrC   r   rA   r   Zsysstrr9   Ú	__class__r>   rD   r?   )r   rT   r   rV   r   r   rS   r   Úcallcommand   s:    ÿÿÿÿÿÿzpeerexecutor.callcommandc              
   C   sê  | j r
d S | jsd S d| _ | jD ]}t|tƒr tjj|_d |_	q | j}d | _t
|ƒdkrÆ|d \}}}}| ¡ std S z|f i t |¡¤Ž}W n* ty¶   t |t ¡ dd … ¡ Y n0 | |¡ d S g }g }|D ]Ú\}}}}| ¡ sèqÒz|j|jfi t |¡¤Ž}	W n0 ty6   t |t ¡ dd … ¡ Y  d S 0 zt|	ƒ\}
}W n0 tyx   t |t ¡ dd … ¡ Y  d S 0 |sŒ| |
¡ qÒ| ||
f¡ | |||	|f¡ qÒ|s¸d S | j |¡}tj d¡| _| j | j||¡| _d S )NTr   r   )rB   rD   rG   Ú
isinstancer9   r   r;   r<   rX   r>   ÚlenZset_running_or_notify_cancelÚ	strkwargsÚ	ExceptionÚfuture_set_exception_infoÚsysÚexc_infoÚ
set_resultr   Ú__self__r   r4   rA   Ú_submitbatchZThreadPoolExecutorrH   ZsubmitÚ_readbatchresponserI   )r   r   ZcallsrT   r   rU   r=   ZrequestsÚstatesr   r   ÚfremoteÚwireresultsr   r   r   r?   Æ   sf    



	ÿÿ


ÿzpeerexecutor.sendcommandsc                 C   sÈ   |   ¡  | jrd S d| _| js"d S zV| j ¡  W | jjdd d | _d | _| jD ] }| ¡ sP| t	 
tdƒ¡¡ qPd | _nJ| jjdd d | _d | _| jD ] }| ¡ sš| t	 
tdƒ¡¡ qšd | _0 d S )NT)Úwaits"   unfulfilled batch command response)r?   rC   rI   r=   rH   ZshutdownrG   r:   Zset_exceptionr   ÚResponseErrorr   )r   r   r   r   r   rN     s<    
ÿÿò
ÿÿzpeerexecutor.closec           	   
   C   sj   |D ]`\}}}}t |ƒ}| |¡ zt |ƒ}W n* tyX   t |t ¡ dd … ¡ Y q0 | |¡ qd S )Nr   )r   r   r]   r   r^   r_   r`   ra   )	r   re   rg   rT   r   r   rf   Zremoteresultr=   r   r   r   rd   ?  s    
zpeerexecutor._readbatchresponseN)
r   r%   r&   rK   rM   rQ   rY   r?   rN   rd   r   r   r   r   r@   ~   s   	7Y r@   c                   @   sê   e Zd ZdZdd„ Zdd„ Zedd„ ƒZedd	„ ƒZed
d„ ƒZ	edd„ ƒZ
edd„ ƒZedd„ ƒZdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd d!„ Zd"d#„ Zd3d%d&„Zd'd(„ Zd)d*„ Zd+d,„ Zd-d.„ Zd/d0„ Zd1d2„ Zd$S )4ÚwirepeerzîClient-side interface for communicating with a peer repository.

    Methods commonly call wire protocol commands of the same name.

    See also httppeer.py and sshpeer.py for protocol-specific
    implementations of this interface.
    c                 C   s   t | ƒS r(   )r@   rL   r   r   r   Úcommandexecutor]  s    zwirepeer.commandexecutorc                 C   s   |   dtdƒ¡ |  d¡S )Ns   clonebundless   clone bundles)Ú
requirecapr   Ú_callrL   r   r   r   Úclonebundlesb  s    zwirepeer.clonebundlesc                 c   sp   |   dtdƒ¡ tƒ }dt |¡i|fV  |j}|d d…  dd¡\}}t|ƒr\t|ƒV  n|  	t
 |¡¡ d S )Ns   lookups   look up remote revisionó   keyéÿÿÿÿó    r   )rl   r   r!   r
   Ú	fromlocalr$   ÚsplitÚintr   Ú_abortr   r#   )r   Úkeyr   ÚdZsuccessÚdatar   r   r   Úlookupf  s    zwirepeer.lookupc              	   c   s\   t ƒ }i |fV  |j}zt |d d… ¡V  W n( tyV   |  t tdƒ|¡¡ Y n0 d S )Nrp   ó   unexpected response:)	r!   r$   r   Ú
decodelistÚ
ValueErrorru   r   ri   r   )r   r   rw   r   r   r   Úheadsr  s    
zwirepeer.headsc              	   c   sh   t ƒ }dt |¡i|fV  |j}zdd„ t |¡D ƒV  W n( tyb   |  t 	t
dƒ|¡¡ Y n0 d S )Nó   nodesc                 S   s   g | ]}t t|ƒƒ‘qS r   )Úboolrt   ©r)   Úbr   r   r   Ú
<listcomp>‚  r-   z"wirepeer.known.<locals>.<listcomp>rz   )r!   r   Ú
encodelistr$   r   Ziterbytestrr|   ru   r   ri   r   )r   Únodesr   rw   r   r   r   Úknown|  s    zwirepeer.knownc              	   c   s’   t ƒ }i |fV  |j}zNi }| ¡ D ]6}| dd¡\}}t t |¡¡}t 	|¡}|||< q$|V  W n( t
yŒ   |  t tdƒ|¡¡ Y n0 d S )Nrq   r   rz   )r!   r$   Ú
splitlinesrs   r
   ZtolocalÚurlreqZunquoter   r{   Ú	TypeErrorru   r   ri   r   )r   r   rw   Ú	branchmapZ
branchpartZ
branchnameZbranchheadsr   r   r   r‰   †  s    



zwirepeer.branchmapc                 c   sl   |   d¡si d fV  tƒ }| j d| ¡ dt |¡i|fV  |j}| j d|t|ƒf ¡ t 	|¡V  d S )Nó   pushkeys   preparing listkeys for "%s"
ó	   namespaces$   received listkey for "%s": %i bytes
)
Úcapabler!   ÚuiÚdebugr
   rr   r$   r[   Ú
pushkeymodZ
decodekeys)r   Ú	namespacer   rw   r   r   r   Úlistkeys–  s    

ÿzwirepeer.listkeysc           	      c   sÌ   |   d¡sdV  tƒ }| j d||f ¡ t |¡t |¡t |¡t |¡dœ|fV  |j}| dd¡\}}ztt	|ƒƒ}W n" t
yž   t tdƒ|¡‚Y n0 | d¡D ]}| j td	ƒ|¡ qª|V  d S )
NrŠ   )FNs   preparing pushkey for "%s:%s"
)r‹   ro   s   olds   newó   
r   ó"   push failed (unexpected response):Tó   remote: )rŒ   r!   r   rŽ   r
   rr   r$   rs   r   rt   r|   r   ri   r   r†   Ústatus)	r   r   rv   ÚoldÚnewr   rw   ÚoutputÚlr   r   r   r   £  s,    
üûÿ
zwirepeer.pushkeyc                 C   s
   |   d¡S )Ns
   stream_out)Ú_callstreamrL   r   r   r   Ú
stream_out»  s    zwirepeer.stream_outc           	      K   s*  t  |¡}|  dtdƒ¡ i }| d¡p,tƒ }t  |¡D ]¨\}}|d u rJq8tj |¡}|d u rnt	 
d| ¡‚nj|dkr‚t |¡}nV|dkr–d |¡}nB|dkr®d t|ƒ¡}n*|d	krÄd
t|ƒ }n|dkrØtd| ƒ‚|||< q8| jdi t  |¡¤Ž}tdd„ |D ƒƒrt | j|¡S t |d¡S d S )Nó	   getbundleó   look up remote changess
   bundlecapss$   Unexpectedly None keytype for key %sr~   s   csvr.   s   scsvs   booleans   %is   plains    unknown getbundle option type %sc                 s   s   | ]}|  d ¡V  qdS )s   HG2N)Ú
startswith)r)   Zcapr   r   r   r,   ×  r-   z%wirepeer.getbundle.<locals>.<genexpr>ó   UN)rœ   )r   Zbyteskwargsrl   r   Úgetr   r3   r   ZGETBUNDLE_ARGUMENTSr   rW   rƒ   r2   Úsortedr   ÚKeyErrorÚ_callcompressabler\   Úanyr   Úgetunbundlerr   ÚchangegroupmodÚcg1unpacker)	r   ÚsourceÚkwargsr   Z
bundlecapsrv   r$   Zkeytyper   r   r   r   Ú	getbundle¾  s6    
ÿ
zwirepeer.getbundlec              	   C   sð   |dgkr8|   d¡r8t dt d t|ƒ¡¡ ¡ g¡}n
t |¡}t 	|d¡rÎ| j
d||d\}}|dkrzt tdƒ|¡‚zt|ƒ}W n" ty¨   t td	ƒ|¡‚Y n0 | d
¡D ]}| j tdƒ|¡ q´n| jd||d}t | j|¡}|S )aÈ  Send cg (a readable file-like object representing the
        changegroup to push, typically a chunkbuffer object) to the
        remote server as a bundle.

        When pushing a bundle10 stream, return an integer indicating the
        result of the push (see changegroup.apply()).

        When pushing a bundle20 stream, return a bundle20 stream.

        `url` is the url the client thinks it's pushing to, which is
        visible to hooks.
        s   forces   unbundlehashs   hashedr-   s   deltaheaders   unbundle)r}   s   push failed:r“   Tr”   )rŒ   r   rƒ   r   Zsha1r2   r¡   Zdigestr   r"   Ú	_callpushr   ri   r   rt   r|   r†   r   r•   Ú_calltwowaystreamr   r¥   )r   Zbundler}   ZurlZretr˜   r™   Ústreamr   r   r   ÚunbundleÜ  s(    ÿ
ÿ
zwirepeer.unbundlec              	   C   s^   t  |¡}| jd|d}zdd„ | ¡ D ƒ}|W S  tyX   |  t tdƒ|¡¡ Y n0 d S )Ns   branches)r„   c                 S   s   g | ]}t t |¡ƒ‘qS r   )Útupler   r{   r€   r   r   r   r‚     r-   z%wirepeer.branches.<locals>.<listcomp>rz   )	r   rƒ   rm   r†   r|   ru   r   ri   r   )r   r„   Únrw   Úbrr   r   r   Úbranches	  s    
zwirepeer.branchesc              
   C   s˜   d}g }t  dt|ƒ|¡D ]x}d dd„ |||| … D ƒ¡}| jd|d}z| dd	„ | ¡ D ƒ¡ W q ty   |  t	 
td
ƒ|¡¡ Y q0 q|S )Né   r   rq   c                 S   s   g | ]}t  |d ¡‘qS )ó   -)r   rƒ   )r)   Úpr   r   r   r‚     s   ÿz$wirepeer.between.<locals>.<listcomp>s   between)Úpairsc                 s   s    | ]}|rt  |¡pg V  qd S r(   )r   r{   )r)   r™   r   r   r   r,     s   ÿz#wirepeer.between.<locals>.<genexpr>rz   )r   Zxranger[   r2   rm   Úextendr†   r|   ru   r   ri   r   )r   r¶   ZbatchÚrÚir°   rw   r   r   r   Úbetween  s     þÿ
þzwirepeer.betweenc                 C   s$   t  |¡}| jd|d}t |d¡S )Ns   changegroup)ÚrootsrŸ   )r   rƒ   r£   r¦   r§   )r   r„   r¨   r°   r   r   r   r   r	   &  s    
zwirepeer.changegroupc                 C   s@   |   dtdƒ¡ t |¡}t |¡}| jd||d}t |d¡S )Ns   changegroupsubsetr   )Úbasesr}   rŸ   )rl   r   r   rƒ   r£   r¦   r§   )r   r¼   r}   r¨   r   r   r   r   Úchangegroupsubset+  s    

ÿzwirepeer.changegroupsubsetc                 c   sî   | j }|jrJ| dd¡rJ| d¡ |D ]"\}}d}| ||t|ƒf ¡ q&tj}| jdt|ƒd}| 	d¡}|g}	|rÚd|vr˜|r˜| 	d¡}|	 
|¡ qvd	 |	¡}
d|
v rÆ|
 dd
¡\}}
||ƒV  q¢| 	d¡}|
|g}	qr|d	 |	¡ƒV  dS )zqrun batch request <req> on the server

        Returns an iterator of the raw responses from the server.
        s   devels   debug.peer-requests$   devel-peer-request: batched-content
s+   devel-peer-request:    - %s (%d arguments)
s   batch)r6   i   r0   r-   r   N)r   Z	debugflagZ
configboolrŽ   r[   r   Zunescapebatchargrš   r8   Úreadr4   r2   rs   )r   r5   r   r7   r   ÚmsgZunescapeargZrspÚchunkZworkZmergedÚoner   r   r   rc   6  s*    





zwirepeer._submitbatchc                 C   s   | j |fi t |¡¤ŽS r(   )rm   r   r\   )r   r7   r   r   r   r   r   S  s    zwirepeer._submitoneNc                 C   s:   i }|d ur||d< |d ur$||d< | j d||dœ|¤ŽS )NÚthreeÚfouró   debugwireargs)rÁ   Útwo)rÄ   )rm   )r   rÁ   rÅ   rÂ   rÃ   Zfiver   r   r   r   ÚdebugwireargsV  s    zwirepeer.debugwireargsc                 K   s
   t ƒ ‚dS )z†execute <cmd> on the server

        The command is expected to return a simple string.

        returns the server reply as a string.N©ÚNotImplementedError©r   r   r   r   r   r   rm   _  s    zwirepeer._callc                 K   s
   t ƒ ‚dS )a  execute <cmd> on the server

        The command is expected to return a stream. Note that if the
        command doesn't return a stream, _callstream behaves
        differently for ssh and http peers.

        returns the server reply as a file like object.
        NrÇ   rÉ   r   r   r   rš   g  s    	zwirepeer._callstreamc                 K   s
   t ƒ ‚dS )aE  execute <cmd> on the server

        The command is expected to return a stream.

        The stream may have been compressed in some implementations. This
        function takes care of the decompression. This is the only difference
        with _callstream.

        returns the server reply as a file like object.
        NrÇ   rÉ   r   r   r   r£   r  s    zwirepeer._callcompressablec                 K   s
   t ƒ ‚dS )züexecute a <cmd> on server

        The command is expected to be related to a push. Push has a special
        return method.

        returns the server reply as a (ret, output) tuple. ret is either
        empty (error) or a stringified int.
        NrÇ   ©r   r   Úfpr   r   r   r   r«     s    	zwirepeer._callpushc                 K   s
   t ƒ ‚dS )zqexecute <cmd> on server

        The command will send a stream to the server and get a stream in reply.
        NrÇ   rÊ   r   r   r   r¬   Š  s    zwirepeer._calltwowaystreamc                 C   s
   t ƒ ‚dS )zKclearly abort the wire protocol connection and raise the exception
        NrÇ   )r   Z	exceptionr   r   r   ru   ‘  s    zwirepeer._abort)NNN)r   r%   r&   r'   rk   rn   r   ry   r}   r…   r‰   r‘   r   r›   rª   r®   r²   rº   r	   r½   rc   r   rÆ   rm   rš   r£   r«   r¬   ru   r   r   r   r   rj   Q  s>   

	
	


-	
	rj   ))Z
__future__r   r_   rE   Zi18nr   Znoder   r   r   r   Ú r   r	   r¦   r
   r   r   r   r   r   Z
interfacesr   ZinterfaceutilZutilsr   r‡   r   Úobjectr!   r8   r;   r<   r9   ZimplementerZipeercommandexecutorr@   ZipeercommandsZipeerlegacycommandsrJ   rj   r   r   r   r   Ú<module>   s(   (
&	
 Sÿ