o ]Lbo@srddlmZmZmZddlZddlZddlZddlZddlZddl Z ddl m Z m Z m Z mZz ddl mZejWneyHddl mZYnwejdkrddlZddlZejZdZd Zd Zd Zed jZd Zd ZdZ dZ!dZ"dZ#dZ$dZ%dZ&ejj'Z(Gdddej)Z*e+ej,Z-ej.j/j0Z1ej2ej,ej,ej3ej,ej,ej4ge1_5ej4e1_6ej.j/j7Z7ej4ge7_5ej8e7_6ej.j/j9Z9ej4ej3ej,e-e+e*ge9_5ej8e9_6ej.j/j:Z:ej4ej3ej,e-e+e*ge:_5ej8e:_6ej.j/j;Z;ge;_5ej,e;_6ej.j/jej,ej3ej,ej,e+ej2ej,ej3ge>_5ej,e>_6ej.j/j?Z?ej.j/j@Z@ej4e+e*e-ej8ge@_5ej8e@_6eAej.j/ddZBeBdurRej4e+e*e-ej,ej8geB_5ej8eB_6ej.j/jCZCej4ej,ej8geC_5ej,eC_6ej.j/jDZEe-ej8ej8ej2geE_5ej4eE_6ej.j/jFZFej4e+e*geF_5ej8eF_6dZGdZHeHrddZInddZIddZJGdddeKZLGdd d eLZMGd!d"d"eLZNGd#d$d$eLZOGd%d&d&eLZPGd'd(d(eLZQGd)d*d*eLZRGd+d,d,eSZTGd-d.d.eSZUGd/d0d0eTZVd1d2ZWGd3d4d4eTZXdEd5d6ZYGd7d8d8eTZZGd9d:d:eUZ[Gd;d<dd>e[Z]Gd?d@d@e]e\Z^GdAdBdBeUZ_GdCdDdDeSZ`dS)F)absolute_importdivisionprint_functionN) capabilitiescompatencodingload)bser)pybserntli@iliic@s<eZdZdefdefdejfdejfdejfgZddZdS) OVERLAPPEDInternal InternalHighOffset OffsetHighhEventcCs"d|_d|_d|_d|_d|_dSNr)rrrrrselfrE/usr/lib/python3/dist-packages/hgext/fsmonitor/pywatchman/__init__.py__init__Ys  zOVERLAPPED.__init__N) __name__ __module__ __qualname__ ULONG_PTRwintypesDWORDHANDLE_fields_rrrrrrPs rGetOverlappedResultEx FcGs,tdtdt||ddfdS)Nz[%s] %sz%a, %d %b %Y %H:%M:%S)printtimestrftimegmtimefmtargsrrrlogsr/cGdSNrr,rrrr/cCs@t}tttBtBd|d|ddz|jWt|St|w)z7expand a win32 error code into a human readable messageNr)ctypesc_char_p FormatMessageFORMAT_MESSAGE_FROM_SYSTEMFORMAT_MESSAGE_ALLOCATE_BUFFERFORMAT_MESSAGE_IGNORE_INSERTSvalue LocalFree)errbufrrr_win32_strerrors" r=c@s&eZdZdddZddZddZdS) WatchmanErrorNcCs||_||_dSr1)msgcmdrr?r@rrrrs zWatchmanError.__init__cC ||_dSr1)r@)rr@rrr setCommand zWatchmanError.setCommandcCs|jr d|j|jfS|jS)Nz%s, while executing %s)r@r?rrrr__str__szWatchmanError.__str__NN)rrr rrCrErrrrr>s  r>c@ eZdZdS)BSERv1UnsupportedNrrr rrrrrHrHc@rG) UseAfterForkNrIrrrrrKrJrKcseZdZdfdd ZZS)WatchmanEnvironmentErrorNcs tt|d||||dS)Nz{0}: errno={1} errmsg={2})superrLrformat)rr?errnoerrmsgr@ __class__rrr s z!WatchmanEnvironmentError.__init__r1rrr r __classcell__rrrQrrL srLcseZdZfddZZS)SocketConnectErrorcs(tt|d||f||_||_dS)Nzunable to connect to %s: %s)rMrUrsockpathexc)rrVrWrQrrrs   zSocketConnectError.__init__rSrrrQrrUsrUc@eZdZdZdS) SocketTimeoutaA specialized exception raised for socket timeouts during communication to/from watchman. This makes it easier to implement non-blocking loops as callers can easily distinguish between a routine timeout and an actual error condition. Note that catching WatchmanError will also catch this as it is a super-class, so backwards compatibility in exception handling is preserved. Nrrr __doc__rrrrrYsrYcs"eZdZdZdfdd ZZS) CommandErrorzRerror returned by watchman self.msg is the message returned by watchman. Ncstt|d|f|dS)Nzwatchman command error: %s)rMr\rrArQrrr+s  zCommandError.__init__r1)rrr r[rrTrrrQrr\%sr\c@<eZdZdZdZddZddZddZd d Zd d Z dS) Transportz.communication transport to the watchman serverNcCt)z tear it downNotImplementedErrorrrrrclose6zTransport.closecCr_)zread size bytesr`)rsizerrr readBytes:rczTransport.readBytescCr_)zwrite some datar`)rr<rrrwrite>rczTransport.writecCr0r1rrr9rrr setTimeoutBr2zTransport.setTimeoutcCs|jdurg|_t|jdkr'd|jdvr'|jddd\}}|g|_|S |d}d|vrGd|j}|dd\}}|g|_||S|j|q()zread a line Maintains its own buffer, callers of the transport should not mix calls to readBytes and readLine. Nr rTr)r<lensplitrejoinappend)rlinebresultrrrreadLineEs    zTransport.readLine) rrr r[r<rbrerfrhrrrrrrr^1s r^c@s4eZdZdZdZddZddZddZd d ZdS) Codecz.communication encoding for the watchman serverNcCrBr1 transport)rrurrrrcrDzCodec.__init__cCr_r1r`rrrrreceivefz Codec.receivecGr_r1r`rr.rrrsendirwz Codec.sendcCs|j|dSr1)rurhrgrrrrhlzCodec.setTimeout) rrr r[rurrvryrhrrrrrs^s rsc@r]) UnixSocketTransportz"local unix domain socket transportNc Csp||_||_ttjtj}z||j||j||_WdStjy7}z | t |j|d}~wwr1) rVtimeoutsocketAF_UNIX SOCK_STREAM settimeoutconnectsockerrorrbrU)rrVr|rerrrrus    zUnixSocketTransport.__init__cCs|jr |jd|_dSdSr1)rrbrrrrrbs  zUnixSocketTransport.closecCs||_|j|jdSr1)r|rrrgrrrrhszUnixSocketTransport.setTimeoutcCsBz|j|g}|dstd|dWStjy tdw)Nrempty watchman responseztimed out waiting for response)rrecvr>r}r|rY)rrdr<rrrres zUnixSocketTransport.readBytescCs,z |j|WdStjytdw)Nztimed out sending query command)rsendallr}r|rY)rdatarrrrfs zUnixSocketTransport.write) rrr r[rrrbrhrerfrrrrr{ps  r{cCstd||dkrDt|j||}|tkrn/|tkrttn&|tkr(ttdS|tkr8t}tdt |dSt}tdt |dSt |||dS)aWindows 7 and earlier does not support GetOverlappedResultEx. The alternative is to use GetOverlappedResult and wait for read or write operation to complete. This is done be using CreateEvent and WaitForSingleObjectEx. CreateEvent, WaitForSingleObjectEx and GetOverlappedResult are all part of Windows API since WindowsXP. This is the exact same implementation that can be found in the watchman source code (see get_overlapped_result_ex_impl in stream_win.c). This way, maintenance should be simplified. z"Preparing to wait for maximum %dmsrFz WaitForSingleObjectEx failed: %szUnexpected error: %s) r/WaitForSingleObjectExr WAIT_OBJECT_0WAIT_IO_COMPLETION SetLastError WAIT_TIMEOUT WAIT_FAILED GetLastErrorr=GetOverlappedResult)pipeolapnbytesmillis alertablewaitReturnCoder;rrr_get_overlapped_result_ex_impls& rc@sHeZdZdZddZddZddZdd Zd d Zd d Z ddZ dS)WindowsNamedPipeTransportzconnect to a named pipecCs||_tt|d|_d|_tjrt |}t |t t Bddt td|_t}|jtks2|jdkr?d|_t|j|d|tdddd|_t}|jdurU|d|t|_tddksd|jdurit|_dSdS) NrTFzCreateEvent failedWATCHMAN_WIN7_COMPAT1)rVintmathceilr|_iobufrPYTHON3osfsencode CreateFile GENERIC_READ GENERIC_WRITE OPEN_EXISTINGFILE_FLAG_OVERLAPPEDrrINVALID_HANDLE_VALUErU _make_win_err CreateEvent _waitable_raise_win_errr&_get_overlapped_result_exgetenvr)rrVr|r;rrrrs6      z"WindowsNamedPipeTransport.__init__cCs |||r1)rrr?r;rrrr z(WindowsNamedPipeTransport._raise_win_errcCstd||t|fS)Nz%s win32 error code: %d %s)IOErrorr=rrrrrsz'WindowsNamedPipeTransport._make_win_errcCs<|jr tdt|jd|_|jdurt|jd|_dS)Nz Closing pipe)rr/ CloseHandlerrrrrrbs    zWindowsNamedPipeTransport.closecCst|d|_dS)Nr)rr|rgrrrrhsz$WindowsNamedPipeTransport.setTimeoutc Csf|jr#|t|jkr|j}d|_|S|jd|}|j|d|_|St|}t}|j|_td|t |j ||d|}|sNt }|t krN| d||t}||j |||r\dn|jdst }t|j ||tkrytdtd|jtd|| d ||j}|dkrt|j |td |d|}t||}||kr|S||d|_|d|S) zA read can block for an unbounded amount of time, even if the kernel reports that the pipe handle is signalled, so we need to always perform our reads asynchronously Nzmade read buff of size %dzfailed to read %d bytesrTzGetOverlappedResultEx timedoutz%timed out after waiting %dms for readz&GetOverlappedResultEx reports error %dzerror while waiting for readz'Async read yielded 0 bytes; unpossible!)rrkr<r3create_string_bufferrrrr/ReadFilerrERROR_IO_PENDINGrr"r#rr| CancelIoExrrYr9rmin) rrdresr<r immediater;nread returned_sizerrrresP         z#WindowsNamedPipeTransport.readBytescCst}|j|_t|jt|t|d|}|s+t}|t kr+| dt||jf|t }| |j|||r9dn|jdrGtd|j|jSt}t|j||tkr[td|j| dt||dS)Nz%failed to write %d bytes to handle %rrTzmade write of %d bytesz&timed out after waiting %dms for writez)error while waiting for write of %d bytes)rrr WriteFilerr3r4rkrrrr"r#rr|r/r9rrrY)rrrrr;nwroterrrrfDs:    zWindowsNamedPipeTransport.writeN) rrr r[rrrrbrhrerfrrrrrs#  DrcCs|r|StjddS)NWATCHMAN_BINARYwatchman)renvironget)binpathrrr_default_binpathlsrc@sBeZdZdZdZdZdddZddZdd Zd d Z d d Z dS)CLIProcessTransporta"open a pipe to the cli to talk to the service This intended to be used only in the test harness! The CLI is an oddball because we only support JSON input and cannot send multiple commands through the same instance, so we spawn a new process for each command. We disable server spawning for this implementation, again, because it is intended to be used only in our test harness. You really should not need to use the CLI transport for anything real. While the CLI can output in BSER, our Transport interface doesn't support telling this instance that it should do so. That effectively limits this implementation to JSON input and output only at this time. It is the responsibility of the caller to set the send and receive codecs appropriately. NTcCs||_||_t||_dSr1)rVr|rr)rrVr|rrrrrszCLIProcessTransport.__init__cCsL|jr$|jjdur|j|jj|jj|jd|_dSdSr1)procpidkillstdinrbstdoutwaitrrrrrbs      zCLIProcessTransport.closecCsF|jr|jS|jd|jddddddg}tj|tjtjd|_|jS) Nz--sockname={0}z--logfile=/BOGUSz--statefile=/BOGUSz --no-spawnz --no-localz --no-prettyz-j)rr)rrrNrV subprocessPopenPIPErxrrr_connects  zCLIProcessTransport._connectcCs&||jj|}|std|S)NzEOF on CLI process transport)rrrreadr>)rrdrrrrres zCLIProcessTransport.readBytescCs@|jr |d|_||jj|}|jjd|_|S)NFT)closedrbrrrrf)rrrrrrrfs zCLIProcessTransport.writer1) rrr r[rrrrbrrerfrrrrrus   rcs8eZdZdZfddZddZddZdd ZZS) BserCodeczr pdu_inforkrnrmr ValueError) rr<_1_2elenrlenrrrrrrrvs"    zBserCodec.receivecGstj|}|j|dSr1)r dumpsrurfrr.r@rrrrys zBserCodec.send) rrr r[rrrvryrTrrrQrrs  rc@seZdZdZddZdS)ImmutableBserCodecSuse the BSER encoding, decoding values using the newer immutable object supportcCstj|d|j|jdS)NFrrrrrrrs zImmutableBserCodec._loadsN)rrr r[rrrrrrs rcs0eZdZdZfddZddZddZZS)Bser2WithFallbackCodeczuse BSER v2 encodingcs|tt||||tjrd}nd}|d|dgig|}d|vr(td|ddr6d|_d |_ dSd |_d |_ dS) Nrequiredoptionalversionzbser-v2rz[The watchman server version does not support Python 3. Please upgrade your watchman server.rrr) rMrrrrryrvrH bser_versionbser_capabilities)rrurr bserv2_keyrrQrrrs"    zBser2WithFallbackCodec.__init__c Cs|jtg}|dstdt|d\}}}t|dr+t|j||_|j |@|_ t |d}||krL| |j|||t |d7}||ks5d |}z||}|WStyk}ztd|d}~ww)Nrrrrrjr)rurerr>r rhasattrmaxrrrrkrnrmrr) rr<recv_bser_versionrecv_bser_capabilitiesrrrrrrrrrvs(      zBser2WithFallbackCodec.receivecGs<t|drtj||j|jd}ntj|}|j|dS)Nr)rr)rr rrrrurfrrrrry's  zBser2WithFallbackCodec.send)rrr r[rrvryrTrrrQrrs  rc@rX)ImmutableBser2CodecrNrZrrrrr3srcs4eZdZdZdZfddZddZddZZS) JsonCodeczstr_parseEncoding recvCodec sendCodecrrrget_local_encoding valueEncodingdefault_local_errors valueErrors) rrVr|ru sendEncoding recvEncodingrr rrrrrrpsJ         zclient.__init__csfdd}|S)Ncs|jjSr1)r rrtcodecrrr make_codecrzz)client._makeBSERCodec..make_codecr)rrrrrr_makeBSERCodecszclient._makeBSERCodeccCsj|dkr|jr |tS|tS|dkr)tjrtd|jr$|tS|tS|dkr/t St d|)Nr zbser-v1zrPython 3 does not support the BSER v1 encoding: specify "bser" or omit the sendEncoding and recvEncoding argumentsrzinvalid encoding %s) rrrrrrrHrrrr>)rencrrrr s     zclient._parseEncodingcCs|jrt||S||vSr1)rr)rrqrrrr_hasprops zclient._haspropc Cstd}|r |S|jddg}z(ttjtjd}tjdkr-t}|jtj O_||d<tj |fi|}Wnt yI}zt d|d}~ww| \}}|} | r\t d| t|} d | vrmt d | d | d S) N WATCHMAN_SOCKz--output-encoding=bserz get-sockname)rstderrr startupinfoz&"watchman" executable not in PATH (%s)zwatchman exited with code %drzget-sockname error: %ssockname)rrrdictrrr STARTUPINFOdwFlagsSTARTF_USESHOWWINDOWrOSErrorr> communicatepollr r) rpathr@r.rprrrexitcoderqrrr_resolvesocknames2       zclient._resolvesocknamecCs|jr|jtkrtddS|jdur||_i}|jtkr&|j |d<|j|j|j fi||_ | |j |_ ||j |_t|_dS)zestablish transport connectionz@do not re-use a connection after fork; open a new client insteadNr)recvConnrrgetpidrKrVr&rurrr|tportr sendConnr )rkwargsrrrrs    zclient._connectcC |dSr1rbrrrr__del__ rzclient.__del__cCs ||Sr1)rrrrr __enter__szclient.__enter__cCr,r1r-)rexc_type exc_value exc_tracebackrrr__exit__rzclient.__exit__cCs*|jr|jd|_d|_d|_dSdSr1)r)rbr'r*rrrrrbs   z client.closecCs||j}||drt|d||dr#|j|d||drm|d}||jvr7g|j|<|j||tj tj |d}||j vrUi|j |<||j |vrcg|j ||<|j ||||S)areceive the next PDU from the watchman service If the client has activated subscriptions or logs then this PDU may be a unilateral PDU sent by the service to inform the client of a log event or subscription change. It may also simply be the response portion of a request initiated by query. There are clients in production that subscribe and call this in a loop to retrieve all subscription responses, so care should be taken when making changes here. rr/rroot) rr'rvrr\logsrnsubsrr#normpathnormcase sub_by_root)rrqsubr4rrrrvs$         zclient.receivecCs2d|vr |dr dS|jD] }||vrdSq dS)N unilateralTF)r;)rrkrrrisUnilateralResponseCs zclient.isUnilateralResponseTcCs|j}|rg|_|S)zRetrieve buffered log data If remove is true the data will be removed from the buffer. Otherwise it will be left in the buffer )r5)rremoverrrrgetLogLsz client.getLogcCs|dur8tjtj|}||jvrdS||j|vrdS|j||}|r6|j||=||jvr6|j|=|S||jvr?dS|j|}|rJ|j|=|S)aRetrieve the data associated with a named subscription If remove is True (the default), the subscription data is removed from the buffer. Otherwise the data is returned but left in the buffer. Returns None if there is no data associated with `name` If root is not None, then only return the subscription data that matches both root and name. When used in this way, remove processing impacts both the unscoped and scoped stores for the subscription data. N)rr#r7r8r9r6)rrr>r4r:rrrgetSubscriptionWs$     zclient.getSubscriptionc Gstd|z|j||}||r!|}||s|WSty8}z td|j|j |d}~wt yI}z| |d}~ww)a?Send a query to the watchman service and return the response This call will block until the response is returned. If any unilateral responses are sent by the service in between the request-response they will be buffered up in the client object and NOT returned via this method. zcalling client.queryz,I/O error communicating with watchman daemonN) r/rr*ryrvr=EnvironmentErrorrLrOstrerrorr>rC)rr.reeexrrrqueryzs,     z client.querycCsJ|d|pg|p gd}||ds#t||d|vr#t|d|S)z!Perform a server capability checkr)rrrr)rErr synthesizer\)rrrrrrrcapabilityChecks   zclient.capabilityCheckcCs|j||j|dSr1)r'rhr*rgrrrrhs zclient.setTimeout) NrNNNFFFN)T)TNrF)"rrr r[rVrur r r*r'r6r9r5r;r)rrrrr rr&rr.r/r3rbrvr=r?r@rErGrhrrrrr_sR @&' # rr1)a __future__rrrrrrr}rr)rrrrr r r ImportErrorr rr3ctypes.wintypesr"rrrrc_void_pr9rr6r7r8rrrrINFINITErWPARAMr! StructurerPOINTERr#LPDWORDwindllkernel32 CreateFileArLPSTRLPVOIDr$argtypesrestyperBOOLrrrrFormatMessageAr5r:rgetattrr&r CreateEventArrr _debuggingr/r=rr>rHrKrLrUrYr\objectr^rsr{rrrrrrrrrrrrrrs                            -+( * I' A%