
    	^cU                        d dl Z d dlZd dlm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
 Zd Z G d dej                  Z ej        ej                    G d d                      Z! ej        ej"        ej#                   G d dej$                              Z%dS )    N)futures   )_)bin)getattrsetattr)bundle2changegroupencodingerrorpushkeypycompatutilwireprototypes)
repositoryr   )hashutilc                 `      fd}t          |d            t          |d j                   |S )a  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:
        encoded_args = [('one', encode(one),), ('two', encode(two),)]
        # Return it, along with a function that will receive the result
        # from the batched request.
        return encoded_args, decode

    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                       | i |\  }}|s|S | d         }t          j        j                  }|                    ||          } ||          S )Nr   )r   bytesurl__name__
_submitone)argsoptsencoded_args_or_resdecodeselfcmdencoded_resfs          ;/usr/lib/python3/dist-packages/mercurial/wireprotov1peer.pyplainzbatchable.<locals>.plain9   sj    &'a&6&6&6#V 	'&&Aw
++ooc+>??vk"""    	batchabler   )r   r   )r   r!   s   ` r    r#   r#   &   sI    &# # # # # E;"""E:qz***Lr"   c                 .   t           j        g }| D ]o\  }}t          fd|D                       sJ d                    fd|                                D                       }|                    d||fz             pd                    |          S )z;Return a ``cmds`` argument value for the ``batch`` command.c              3   6   K   | ]} |          |k    V  d S N ).0k	escapeargs     r    	<genexpr>z"encodebatchcmds.<locals>.<genexpr>P   s0      7799Q<<1$777777r"      ,c              3   P   K   | ] \  }}d  |           |          fz  V  !dS )s   %s=%sNr'   )r(   r)   vr*   s      r    r+   z"encodebatchcmds.<locals>.<genexpr>R   sR       
 
8<1H		!iill33
 
 
 
 
 
r"   s   %s %s   ;)r   escapebatchargalljoinitemsappend)reqcmdsopargsdictr   r*   s        @r    encodebatchcmdsr9   G   s    -ID 	+ 	+H 7777h77777777yy 
 
 
 
@H@P@P
 
 
 
 
 	HDz)****99T??r"   c                       e Zd ZdZ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                     |                                  r t          j                            | |          S | j                                         |                     |          S r&   )doner   Futureresult_peerexecutorsendcommands)r   timeouts     r    r?   zunsentfuture.resultc   sS    99;; 	8>((w777'')))
 {{7###r"   r&   )r   
__module____qualname____doc__r?   r'   r"   r    r;   r;   Z   s2         	$ 	$ 	$ 	$ 	$ 	$r"   r;   c                   8    e Zd Zd Zd Zd Zd Zd Zd Zd Z	dS )	peerexecutorc                     || _         d| _        d| _        g | _        t	          j                    | _        d | _        d | _        d S )NF)	_peer_sent_closed_callsweakrefWeakSet_futures_responseexecutor
_responsef)r   peers     r    __init__zpeerexecutor.__init__q   s@    

))!%r"   c                     | S r&   r'   r   s    r    	__enter__zpeerexecutor.__enter__z   s    r"   c                 .    |                                   d S r&   )close)r   exctypeexcvaleeexctbs       r    __exit__zpeerexecutor.__exit__}   s    

r"   c                      j         rt          j        d           j        rt          j        d          t	           j        t          j                  d           st          j        dz             fd}t	          dd          r |            }t          |_	         |_
        n< j        rt          j        dz             |            }                                  |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                      t          j                    } j                            |            j                            | f           | S r&   )r   r>   rO   addrL   r4   )r   r   commandfnr   s    r    addcallz)peerexecutor.callcommand.<locals>.addcall   sJ      AMa   Kr15666Hr"   r#   FsX   %s is not batchable and cannot be called on a command executor along with other commands)rJ   r   ProgrammingErrorrK   r   rI   r   sysstrr;   	__class__r@   rL   rA   )r   r`   r   rb   r   ra   s   ```  @r    callcommandzpeerexecutor.callcommand   sC   : 	(G   < 	(=  
 TZ!9!94@@ 	($%  	 	 	 	 	 	 	 	 2{E** 	 		A 'AK"AOO{ ,:<CD  
 		A r"   c                 ~   | j         rd S | j        sd S d| _         | j        D ]/}t          |t                    rt
          j        |_        d |_        0| j        }d | _        t          |          dk    r|d         \  }}}}|
                                sd S 	  |di t          j        |          }|                    |           n># t          $ r1 t          j        |t!          j                    dd                     Y nw xY wd S g }g }|D ]\  }}}}|
                                s	  |j        |j        fi t          j        |          \  }	}
n@# t          $ r3 t          j        |t!          j                    dd                     Y  d S w xY w|
s|                    |	           |                    ||	f           |                    ||t$          |
f           |sd S | j                            |          }t          j        d          | _        | j                            | j        ||          | _        d S )NTr   r   r'   )rJ   rL   rO   
isinstancer;   r   r>   re   r@   lenset_running_or_notify_cancelr   	strkwargs
set_result	Exceptionfuture_set_exception_infosysexc_infor#   __self__r4   rI   _submitbatchThreadPoolExecutorrP   submit_readbatchresponserQ   )r   r   callsr`   r   ra   r?   requestsstatesr   r   wireresultss               r    rA   zpeerexecutor.sendcommands   s   : 	F{ 	F
  	' 	'A!\** '%n"& u::??#(8 GT2q 1133 %77h06677 V$$$$  J J J21clnnQRR6HIIIIIJ
 F $) 	? 	? GT2q1133 .:blK/ /#+#5d#;#;/ /+#VV    21clnnQRR6HIII  ?01111*= >???w9f=>>>> 	F j--h77 ")!;A!>!>077#V[
 
s$   C 8D D)(E8FFc           
         |                                   | j        rd S d| _        | j        sd S 	 | j                                         | j                            d           d | _        d | _        | j        D ]K}|                                s5|                    t          j
        t          d          d                      Ld | _        d S # | j                            d           d | _        d | _        | j        D ]K}|                                s5|                    t          j
        t          d          d                      Ld | _        w xY w)NT)wait"   unfulfilled batch command response)rA   rK   rQ   r?   rP   shutdownrO   r=   set_exceptionr   ResponseErrorr   )r   r   s     r    rX   zpeerexecutor.close	  sy   < 	F 	F	!O""$$$"+++666"DO%)D" ]  vvxx OO+CDDd    !DMMM "+++666"DO%)D" ]  vvxx OO+CDDd    !DM    s   C BEc           	         |D ]\  }}}}	 t          |          }	  ||          }|                    |           9# t          $ r1 t          j        |t          j                    dd                     Y sw xY w# t          $ r8 |                    t          j
        t          d          d                      Y w xY wd S )Nr   r|   )nextrl   rm   r   rn   ro   rp   StopIterationr~   r   r   r   )	r   rx   ry   r`   r   r#   r   remoteresultr?   s	            r    ru   zpeerexecutor._readbatchresponse)  s	    .4 	) 	))GQ	6)#K00)#VL11F LL(((( ! N N N6q#,..:LMMMMMN !    '?@@$     		) 	)s    A:<8A76A7:?B<;B<N)
r   rC   rD   rS   rV   r\   rf   rA   rX   ru   r'   r"   r    rG   rG   o   s              5 5 5nP
 P
 P
d! ! !@) ) ) ) )r"   rG   c                      e Zd ZdZd Zd Zed             Zed             Zed             Z	ed             Z
ed             Zed	             Zd
 Zd Zd Zd Zd Zd Zd Zd Zd ZddZd Zd Zd Zd Zd Zd ZdS )wirepeerzClient-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                      t          |           S r&   )rG   rU   s    r    commandexecutorzwirepeer.commandexecutorO  s    D!!!r"   c                 r    |                      dt          d                     |                     d          S )Ns   clonebundless   clone bundles)
requirecapr   _callrU   s    r    clonebundleszwirepeer.clonebundlesT  s1    +;)<)<===zz/***r"   c                                            dt          d                      fd}dt          j        |          i|fS )Ns   lookups   look up remote revisionc                     | d d                              dd          \  }}t          |          rt          |          S                     t	          j        |                     d S )N    r   )splitintr   _abortr   	RepoError)dsuccessdatar   s      r    r   zwirepeer.lookup.<locals>.decode\  s^    crcFLLq11MGT7|| 34yy EOD1122222r"      key)r   r   r   	fromlocal)r   keyr   s   `  r    lookupzwirepeer.lookupX  sV    	1%?#@#@AAA	3 	3 	3 	3 	3 *3//0&88r"   c                       fd}i |fS )Nc                     	 t          j        | d d                   S # t          $ r9                     t	          j        t          d          |                      Y d S w xY w)Nr      unexpected response:)r   
decodelist
ValueErrorr   r   r   r   r   r   s    r    r   zwirepeer.heads.<locals>.decodeg  sr    P%03B3888 P P PE/2I0J0JANNOOOOOOPs    ?A"!A"r'   r   r   s   ` r    headszwirepeer.headse  s-    	P 	P 	P 	P 	P 6zr"   c                 >      fd}dt          j        |          i|fS )Nc                     	 d t          j        |           D             S # t          $ r9                     t	          j        t          d          |                      Y d S w xY w)Nc                 F    g | ]}t          t          |                    S r'   )boolr   r(   bs     r    
<listcomp>z2wirepeer.known.<locals>.decode.<locals>.<listcomp>s  s$    FFFSVVFFFr"   r   )r   iterbytestrr   r   r   r   r   r   s    r    r   zwirepeer.known.<locals>.decodeq  sx    PFFh.B1.E.EFFFF P P PE/2I0J0JANNOOOOOOPs   ! ?A$#A$   nodesr   
encodelist)r   nodesr   s   `  r    knownzwirepeer.knowno  s>    	P 	P 	P 	P 	P .3E::;VCCr"   c                       fd}i |fS )Nc                    	 i }|                                  D ]`}|                    dd          \  }}t          j        t                              |                    }t          j        |          }|||<   a|S # t          $ r9 	                    t          j        t          d          |                      Y d S w xY w)Nr   r   r   )
splitlinesr   r   tolocalurlrequnquoter   r   	TypeErrorr   r   r   r   )r   	branchmap
branchpart
branchnamebranchheadsr   s        r    r   z"wirepeer.branchmap.<locals>.decode{  s    	P	"#,,.. 8 8J.8.>.>tQ.G.G+J!)!1&..2L2L!M!MJ"0";K"H"HK,7Ij))   P P PE/2I0J0JANNOOOOOOPs   A8A< <?B?>B?r'   r   s   ` r    r   zwirepeer.branchmapy  s-    
	P 
	P 
	P 
	P 
	P 6zr"   c                                            d          si d fS  j                            dz              fd}dt          j                  i|fS )N   pushkeys   preparing listkeys for "%s"
c                     j                             dt          |           fz             t          j        |           S )Ns$   received listkey for "%s": %i bytes
)uidebugri   
pushkeymod
decodekeys)r   	namespacer   s    r    r   z!wirepeer.listkeys.<locals>.decode  sA    GMM8Is1vv;NN   (+++r"   	   namespacecapabler   r   r   r   )r   r   r   s   `` r    listkeyszwirepeer.listkeys  sv    ||J'' 	t8O6BCCC	, 	, 	, 	, 	, 	, h0;;<fDDr"   c                                           d          sdS  j                            d||fz              fd}t          j        |          t          j        |          t          j        |          t          j        |          d|fS )Nr   )FNs   preparing pushkey for "%s:%s"
c                 V   |                      dd          \  } }	 t          t          |                     } n0# t          $ r# t	          j        t          d          |           w xY w|                    d          D ]*}j        	                    t          d          |           +| S )N   
r   "   push failed (unexpected response):T   remote: )
r   r   r   r   r   r   r   r   r   status)r   outputlr   s      r    r   z wirepeer.pushkey.<locals>.decode  s    q))IAvQLL   );<<a   &&t,, 2 2q~~q1111Hs	   9 -A&)r   r   s   olds   newr   )r   r   r   oldnewr   s   `     r    r   zwirepeer.pushkey  s    ||J'' 	;8Is;KKLLL
	 
	 
	 
	 
	 #,Y77&s++&s++&s++	
 

  	r"   c                 ,    |                      d          S )Ns
   stream_out)_callstreamrU   s    r    
stream_outzwirepeer.stream_out  s    ...r"   c                 ^   t          j        |          }|                     dt          d                     i }|                    d          pt                      }|                                D ]\  }}|t          j                            |          }|t          j
        d|z            |dk    rt          j        |          }nv|dk    rd                    |          }nZ|dk    r#d                    t          |                    }n1|d	k    rd
t          |          z  }n|dk    rt          d|z            |||<    | j        di t          j        |          }t%          d |D                       rt'          j        | j        |          S t-          j        |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              3   @   K   | ]}|                     d           V  dS )s   HG2N)
startswith)r(   caps     r    r+   z%wirepeer.getbundle.<locals>.<genexpr>  s.      ==3v&&======r"      UN)r   )r   byteskwargsr   r   getsetr3   r   GETBUNDLE_ARGUMENTSr   rc   r   r2   sortedr   KeyError_callcompressablerk   anyr	   getunbundlerr   changegroupmodcg1unpacker)	r   sourcekwargsr   
bundlecapsr   valuekeytyper   s	            r    	getbundlezwirepeer.getbundle  s   %f--a(A&B&BCCCZZ..7#%%
 ,,.. 	 	JC}$8<<SAAG,;cA   H$$&1%88F""		%((G##		&--00J&&U+H$$BWLMMMDII"D"LL83Ed3K3KLL==*===>> 	8'333!-a777r"   c           
      4   |dgk    rp|                      d          r[t          j        dt          j        d                    t          |                                                              g          }nt          j        |          }t          j	        |d          r| 
                    d||          \  }}|dk    r"t          j        t          d          |          	 t          |          }n0# t          $ r# t          j        t          d	          |          w xY w|                    d
          D ]*}| j                            t          d          |           +n2|                     d||          }t)          j        | 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   sha1r2   r   digestr   safehasattr	_callpushr   r   r   r   r   r   r   r   _calltwowaystreamr	   r   )r   bundler   urlretr   r   streams           r    unbundlezwirepeer.unbundle  s    XJ4<<#@#@"-HM#((6%==*A*ABBIIKKL EE #-e44EFN33 	8..fE.JJKCczz)!O*<*<fEEE#hh   );<<c  
 &&t,, 2 2q~~q11112 ++Ku+MMF&tw77C
s   %C5 5-D"c                 &   t          j        |          }|                     d|          }	 d |                                D             }|S # t          $ r9 |                     t          j        t          d          |                     Y d S w xY w)Ns   branches)r   c                 P    g | ]#}t          t          j        |                    $S r'   )tupler   r   r   s     r    r   z%wirepeer.branches.<locals>.<listcomp>  s+    NNN!%1!4455NNNr"   r   )	r   r   r   r   r   r   r   r   r   )r   r   nr   brs        r    brancheszwirepeer.branches  s    %e,,JJ{!J,,	LNNq||~~NNNBI 	L 	L 	LKK+A.E,F,FJJKKKKKK	Ls   A ?BBc           	         d}g }t          dt          |          |          D ]}d                    d ||||z            D                       }|                     d|          }	 |                    d |                                D                        v# t          $ r8 |                     t          j	        t          d          |                     Y w xY w|S )	N   r   r   c                 8    g | ]}t          j        |d           S )   -r   )r(   ps     r    r   z$wirepeer.between.<locals>.<listcomp>  s5        #-a66  r"   s   between)pairsc              3   F   K   | ]}|rt          j        |          pg V  d S r&   )r   r   )r(   r   s     r    r+   z#wirepeer.between.<locals>.<genexpr>  sK         6.3A66<"     r"   r   )rangeri   r2   r   extendr   r   r   r   r   r   )r   r  batchrir   r   s          r    betweenzwirepeer.between  s   q#e**e,, 	P 	PA		 "1q5y=1   A 

:Q
//AP  \\^^        P P PE/2I0J0JANNOOOOOPs   '1B?CCc                     t          j        |          }|                     d|          }t          j        |d          S )Ns   changegroup)rootsr   )r   r   r   r   r   )r   r   r   r   r   s        r    r
   zwirepeer.changegroup  s=    %e,,"">";;)!U333r"   c                     |                      dt          d                     t          j        |          }t          j        |          }|                     d||          }t          j        |d          S )Ns   changegroupsubsetr   )basesr   r   )r   r   r   r   r   r   r   )r   r  r   r   r   s        r    changegroupsubsetzwirepeer.changegroupsubset   sv    ,a0I.J.JKKK)%00)%00"" U # 
 
 )!U333r"   c              #     K   | j         }|j        r\|                    dd          rF|                    d           |D ].\  }}d}|                    ||t	          |          fz             /t
          j        }|                     dt          |                    }|	                    d          }|g}	|rd|vr2|r0|	                    d          }|	
                    |           d|vr|0d	                    |	          }
d|
v r*|
                    dd
          \  }}
 ||          V  d|
v *|	                    d          }|
|g}	| |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   r/   r"   r   N)r   	debugflag
configboolr   ri   r   unescapebatchargr   r9   readr4   r2   r   )r   r5   r   r7   r   msgunescapeargrspchunkworkmergedones               r    rr   zwirepeer._submitbatch+  s     
 W< 	0BMM(4IJJ 	0HH=>>> 0 0DECII.////$5xoc.B.BCCw 		#e###E""" e### XXd^^F&..$ll433V!k#&&&&& &.. HHTNNEE?D  		# k#((4..)))))))r"   c                 B     | j         |fi t          j        |          S r&   )r   r   rk   )r   r7   r   s      r    r   zwirepeer._submitoneH  s'    tz"99 24 8 8999r"   Nc                 B    i }|||d<   |||d<    | j         d||d|S )Nthreefour   debugwireargs)r  two)r  )r   )r   r  r   r  r  fiver   s          r    debugwireargszwirepeer.debugwireargsK  sD    !DMDLtzEEEEEEr"   c                     t                      )zexecute <cmd> on the server

        The command is expected to return a simple string.

        returns the server reply as a string.NotImplementedErrorr   r   r   s      r    r   zwirepeer._callT  s     "###r"   c                     t                      )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.
        r$  r&  s      r    r   zwirepeer._callstream\       "###r"   c                     t                      )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.
        r$  r&  s      r    r   zwirepeer._callcompressableg  s     "###r"   c                     t                      )zexecute 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.
        r$  r   r   fpr   s       r    r   zwirepeer._callpusht  r(  r"   c                     t                      )zqexecute <cmd> on server

        The command will send a stream to the server and get a stream in reply.
        r$  r+  s       r    r   zwirepeer._calltwowaystream  s    
 "###r"   c                     t                      )zBclearly abort the wire protocol connection and raise the exceptionr$  )r   	exceptions     r    r   zwirepeer._abort  s    !###r"   )NNN)r   rC   rD   rE   r   r   r#   r   r   r   r   r   r   r   r   r   r   r	  r
   r  rr   r   r"  r   r   r   r   r   r   r'   r"   r    r   r   C  s        " " "
+ + + 
9 
9 Y
9   Y D D YD   Y E E YE   Y0/ / /8 8 8<' ' 'ZL L L  (4 4 4
4 4 4* * *:: : :F F F F$ $ $	$ 	$ 	$$ $ $	$ 	$ 	$$ $ $$ $ $ $ $r"   r   )&ro   rM   
concurrentr   i18nr   noder   r   r   r    r	   r
   r   r   r   r   r   r   r   
interfacesr   interfaceutilutilsr   r   r#   r9   r>   r;   implementeripeercommandexecutorrG   ipeercommandsipeerlegacycommandsrR   r   r'   r"   r    <module>r;     s    


                          	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	             	  B  &$ $ $ $ $7> $ $ $* ::;;P) P) P) P) P) P) P) <;P)f j< B$ B$ B$ B$ B$z B$ B$ B$ B$ B$r"   