^ctpdZddlZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl ZddlZddlZddlZddlZddlZddlZddlmZddlmZddlmZmZmZmZddlmZddl m!Z!m"Z"m#Z#m$Z$mZm%Z%dd l&m'Z'm(Z(m)Z)m*Z*ej+r dd l,m-Z-m.Z.m/Z/m0Z0e$j1d Z2e$j1d Z3e2j4Z4e2j5Z5ej6Z6ej7Z7ej8Z8ej9Z9ej:Z;e;ZZ>e%j?Z?e%j@Z@ejAZBejCrdd l mDZEnddl mFZEe#jGZGeEjHZHeEjIZIeEjJZJeEjKZKeEjLZLeEjMZMeEjNZNeEjOZOeEjPZPeEjQZQeEjRZReEjSZSeEjTZTeEjUZUe3jVZVeEjWZWeEjXZXeEjYZYeEjZZZeEj[Z[eEj\Z\eEj]Z]eEj^Z^eEj_Z_eEj`Z`eEjaZaeEjbZbeEjcZceEjdZdeEjeZeeEjfZfeEjgZgeEjhZheEjiZieEjjZjeEjkZkeEjlZlee3deEjmZmeEjnZneEjoZoeEjpapeEjqZqeEjrZrdZse'jtZte'juZue'jvZvewZxdZyeze!j{|dZ}e}r9ej~ddedej~ddedej~ddede}r9ej~ddedej~ddedej~ddedddZeje(jejdZgdZeD]ZeevsJ Gdd ZGd!d"Z eZn#e$rdd#ZYnwxYwd$ZGd%d&Zdd'ZGd(d)ZGd*d+eZhd,ZGd-d.ZGd/d0ZGd1d2eZ dd5ZGd6d7eZ dd8Zd9Zdd;Zd<ZGd=d>ZGd?d@ejZGdAdBeeZGdCdDeeZGdEdFZejddGZejddHZGdIdJZGdKdLZdMZGdNdOZdPZddSZdTZdUZdVZejrdWZdXZddYZhdZZ dd[Zdd\Zhd]Zd^Zd_Zeed`dZejCr eZesejZneEjZesejZdaZdbZdcZddZdea ddlZdan #e$rd4aYnwxYwGdfdgZeZ iZdhZdiZdjZdkZddlZGdmdnZGdodpZdqZddrZdsZddtZduZdvZdwZGdxdyZdd{ZGd|d}Zd~ZdZeddeGdfddeGdfddeGdfddeGdfddeGdfddeGdfddQeGdfddQeGdfddQeGdfddeGdf ZGddZejdZdZdZdZejdkreZeZeZnejZejZejZdZdZdZddZeddeGdfddeGdfddeGdfddeGdfddeGdfddeGdfddeGdfddeGdfddeGdfddeGdfddeGdfddeGdfddeGdf ZejGddZejdZde_dZdZdZGddZddZdde)je)jddfdZeZddZdZdZdZejdZdZdS)zMercurial utility functions and platform specific implementations. This contains helper routines that are independent of the SCM core and hide platform-specific details from the core. N)hex)attr)delattrgetattropensetattr)tracing)encodingerrori18npolicypycompat urllibcompat) compressionhashutilprocutil stringutil)IteratorListOptionalTuplebase85osutil)windows)posix statfilescltjrdStj||dzxt_adS)z%updates the umask. used by chg serverNi)r iswindowsosumaskplatform)vals 0/usr/lib/python3/dist-packages/mercurial/util.pysetumaskr%s5HSMMM 5[(HNUUUcd}|D]}||z}|SNr) containerbitsbits r$bitsfromr-s& D   Kr&sHGEMITWARNINGSdefault mercurialhgexthgext3rdignorez bad escapezinvalid escape sequencezthe imp module is deprecatedctrX|d|zz }tjtj|t |dzt jdSdS)zxIssue an python native deprecation warning This is a noop outside of tests, use 'ui.deprecwarn' when possible. sF (compatibility will be dropped after Mercurial-%s, update your code.)rN) _dowarnwarningswarnrsysstrDeprecationWarningsysstderrflush)msgversion stacklevels r$nouideprecwarnr@sl   #    hoc**,> QOOO r&)md5sha1sha512)rCrBrAcBeZdZdZd dZdZdZdZedZ dS) digesterahelper to compute digests. This helper can be used to compute one or more digests given their name. >>> d = digester([b'md5', b'sha1']) >>> d.update(b'foo') >>> [k for k in sorted(d)] ['md5', 'sha1'] >>> d[b'md5'] 'acbd18db4cc2f85cedef654fccc4a4d8' >>> d[b'sha1'] '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33' >>> digester.preferred([b'md5', b'sha1']) 'sha1' r&ci|_|D]K}|tvr$tjt d|zt||j|<L|r||dSdSNsunknown digest type: %s)_hashesDIGESTSr Abort_update)selfdigestssks r$__init__zdigester.__init__s{  + +Ak!$>"?"?!"CDDD%ajllDLOO   KKNNNNN  r&ch|jD]}||dSN)rHvaluesrL)rMdatahs r$rLzdigester.updates:$$&&  A HHTNNNN  r&c|tvr)tjtdtzt |j|SrG)rIr rJrKrPrrHdigest)rMkeys r$ __getitem__zdigester.__getitem__sL g  +a :;;a?@@ @4<$++--...r&c*t|jSrS)iterrHrMs r$__iter__zdigester.__iter__sDL!!!r&c*tD] }||vr|cS dS)z@returns the strongest digest type in both supported and DIGESTS.N)DIGESTS_BY_STRENGTH) supportedrPs r$ preferredzdigester.preferred s/%  AI~~tr&N)r&) __name__ __module__ __qualname____doc__rQrLrZr^ staticmethodrbr)r&r$rErEsz /// """\r&rEc&eZdZdZdZddZdZdS) digestcheckerzfile handle wrapper that additionally checks content against a given size and digests. d = digestchecker(fh, size, {'md5': '...'}) When multiple digests are given, all of them are validated. c||_||_d|_t||_t |j|_dSr()_fh_size_gotdict_digestsrEkeys _digester)rMfhsizerNs r$rQzdigestchecker.__init__sE  W  !$-"4"4"6"677r&c|j|}|j||xjt |z c_|SrS)rkreadrqrLrmlen)rMlengthcontents r$rvzdigestchecker.read%sF(--'' g&&& S\\! r&cJ|j|jkr0tjt d|j|jfz|jD]H\}}||j|kr2tjt d|||j|fzIdS)Ns"size mismatch: expected %d, got %ds %s mismatch: expected %s, got %s)rlrmr rJrKroitemsrqrMrPvs r$validatezdigestchecker.validate+s : " "+788:ty)* M''))  DAqDN1%%%k9::!T^A./0&  r&Nrt)rcrdrerfrQrvr~r)r&r$ririsP888     r&rich|t||||zSt||dSrS) memoryview) sliceableoffsetrxs r$bufferr>s;  i((&6/)AB B)$$VWW--r&iceZdZdZfdZdZedZedZdZ dZ dZ d Z d Z d Zefd ZxZS) bufferedinputpipeaWa manually buffered input pipe Python will not let us use buffered IO and lazy reading with 'polling' at the same time. We cannot probe the buffer state and select will not detect that data are ready to read if they are already buffered. This class let us work around that by implementing its own buffering (allowing efficient readline) while offering a way to know if the buffer is empty from the output (allowing collaboration of the buffer with polling). This class lives in the 'util' module because it makes use of the 'os' module from the python stdlib. ct|trt}tt||SrS) isinstancefileobjectproxyobservedbufferedinputpipesuperr__new__)clsrr __class__s r$rzbufferedinputpipe.__new__Vs; b/ * * ,+C&,,44S999r&c>||_g|_d|_d|_dS)NFr)_input_buffer_eof_lenbuf)rMinputs r$rQzbufferedinputpipe.__init__^s"    r&c*t|jS)zTrue is any data is currently buffered This will be used externally a pre-step for polling IO. If there is already data then no polling should be set in place.)boolrr]s r$ hasbufferzbufferedinputpipe.hasbufferds DL!!!r&c|jjSrS)rclosedr]s r$rzbufferedinputpipe.closedls {!!r&c4|jSrS)rfilenor]s r$rzbufferedinputpipe.filenops{!!###r&c4|jSrS)rcloser]s r$rzbufferedinputpipe.closess{  """r&c|js1|j|kr&||js |j|k&||SrS)rr _fillbuffer _frombufferrMrss r$rvzbufferedinputpipe.readvsV9 4<$#6#6      9 4<$#6#6%%%r&c|js3|jdkr(|t|t|t |j|Sr()rrrmax _chunksizerminrs r$unbufferedreadz bufferedinputpipe.unbufferedread{sVy 4T\Q..   Sz22 3 3 3DL$ 7 7888r&cvt|jdkr?d|jg|_t|jd|_d}|jr |jdd}|jsN|dkrH||jr |jdd}|js|dkH|dz}|dkr|j}n=t|jdkr%||jt|jdz z }||S)Nrr&rrt )rwrjoinrfindrrr)rMargskwargslfirss r$readlinezbufferedinputpipe.readlines1 t|  q  HHT\223DLt|A//DL < /,r"''..C9 3#''      | 3l2&++E229 3#''Qw 77
|dks|jsdS|jd}t|jdkrd|j}|d|}|t|d}|r|g|_t||_ng|_d|_|S)zYreturn at most 'size' data from the buffer The data are removed from the buffer.rr&rN)rrwrr)rMrsbufrUs r$rzbufferedinputpipe._frombuffers 199DL93l1o t|  q ((4<((C5D5z#d))++  5DLs88DLLDLDL r&ctj|j|}|sd|_n7|xjt |z c_|j||S)zread data to the bufferT) r rvrrrrrwrappend)rMrsrUs r$rzbufferedinputpipe._fillbufferscwt{))++T22 &DII LLCII %LL L   % % % r&)rcrdrerfrrQpropertyrrrrrvrrrrr __classcell__rs@r$rrGs  ::::: ""X"""X"$$$###&&& 999 &&&*( *        r&rc|dkrdS|d}tdfd} tj||tjS#t$r"t j|jdkrYdSwxYw)Nrr&rcSrSr)fpsr$zmmapread..srr&)access)rmmap ACCESS_READ ValueErrorr fstatst_size)rrsfds` r$mmapreadrs qyys  *Xzzzz * * , ,ByT$*:;;;;  8B<< 1 $ $33 s A 'A86A8ceZdZdZdZdZdZdZeZdZ dZ dZ d Z d Z d Zd Zd ZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdS)rzA proxy around file objects that tells a watcher when events occur. This type is intended to only be used for testing purposes. Think hard before using it in important code. _orig _observercvt|d|t|d|dSNrrobject __setattr__)rMrrobservers r$rQzfileobjectproxy.__init__s84"---4h77777r&chd}||vrt||Stt|d|S)N>rvseektellrr<read1writedetachrisattyreadallreadablereadintorseekabletruncatewritabler readlines writelinesrr__getattribute__r)rMnameourss r$rz fileobjectproxy.__getattribute__sU   @ 4<<**466 6v..tW==tDDDr&cRtt|dSNrrrrr]s r$ __nonzero__zfileobjectproxy.__nonzero__ F++D'::;;;r&cTtt|d|SrrrrrMrs r$ __delattr__zfileobjectproxy.__delattr__"v..tW==tDDDr&cVtt|d||Srr rrrMrvalues r$rzfileobjectproxy.__setattr__$v..tW==tUKKKr&c\t|dSr)rrr^r]s r$r^zfileobjectproxy.__iter__s$&&tW55>>@@@r&ct|d}t|||i|}t|d}t||d}|r ||g|Ri||SrrrMrrrorigresrfns r$ _observedcallzfileobjectproxy._observedcall &&tW55!gdD!!42622**4== XtT * *  % Bs $T $ $ $V $ $ $ r&cJt|ddg|Ri|S)NrrrrrMrrs r$rzfileobjectproxy.closeA&&t_==     $   r&cJt|ddg|Ri|S)Nrrrrs r$rzfileobjectproxy.filenoA&&t_==     %   r&cJt|ddg|Ri|S)Nrr<rrs r$r<zfileobjectproxy.flush#rr&cJt|ddg|Ri|S)Nrrrrs r$rzfileobjectproxy.isatty(rr&cJt|ddg|Ri|S)Nrrrrs r$rzfileobjectproxy.readable-A&&t_==     !'   r&cJt|ddg|Ri|S)Nrrrrs r$rzfileobjectproxy.readline2rr&cJt|ddg|Ri|S)Nrrrrs r$rzfileobjectproxy.readlines7A&&t_==     "(   r&cJt|ddg|Ri|S)Nrrrrs r$rzfileobjectproxy.seek<A&&t_==     #   r&cJt|ddg|Ri|S)Nrrrrs r$rzfileobjectproxy.seekableArr&cJt|ddg|Ri|S)Nrrrrs r$rzfileobjectproxy.tellFrr&cJt|ddg|Ri|S)Nrrrrs r$rzfileobjectproxy.truncateKrr&cJt|ddg|Ri|S)Nrrrrs r$rzfileobjectproxy.writablePrr&cJt|ddg|Ri|S)Nrrrrs r$rzfileobjectproxy.writelinesUA&&t_==     #)   r&cJt|ddg|Ri|S)Nrrvrrs r$rvzfileobjectproxy.readZrr&cJt|ddg|Ri|S)Nrrrrs r$rzfileobjectproxy.readall_A&&t_==     &   r&cJt|ddg|Ri|S)Nrrrrs r$rzfileobjectproxy.readintodrr&cJt|ddg|Ri|S)Nrrrrs r$rzfileobjectproxy.writeirr&cJt|ddg|Ri|S)Nrrrrs r$rzfileobjectproxy.detachnrr&cJt|ddg|Ri|S)Nrrrrs r$rzfileobjectproxy.read1srr&N) rcrdrerf __slots__rQrr__bool__rrr^rrrr<rrrrrrrrrrrvrrrrrr)r&r$rrs I 888$E$E$EL<<<HEEELLLAAA                                                              r&rc6eZdZdZfdZfdZfdZxZS)raA variation of bufferedinputpipe that is aware of fileobjectproxy. ``bufferedinputpipe`` makes low-level calls to ``os.read()`` that bypass ``fileobjectproxy``. Because of this, we need to make ``bufferedinputpipe`` aware of these operations. This variation of ``bufferedinputpipe`` can notify observers about ``os.read()`` events. It also re-publishes other events, such as ``read()`` and ``readline()``. ctt|}t|jjdd}|r||t |S)Nosread)rrrrrrr)rMrrrs r$rz%observedbufferedinputpipe._fillbuffersT-t44@@BB T[*Hd ; ;  BsJ    r&ctt||}t|jjdd}|r ||||S)N bufferedread)rrrvrrr)rMrsrrrs r$rvzobservedbufferedinputpipe.readsS-t4499$?? T[*ND A A   BsDMMM r&ctt|j|i|}t|jjdd}|r |||S)Nbufferedreadline)rrrrrr)rMrrrrrs r$rz"observedbufferedinputpipe.readlinesV=e-t44=tNvNN T[*,> E E   BsGGG r&)rcrdrerfrrvrrrs@r$rryst  r&r> recvsendsendtosendallmakefilerecvfrom recv_into gettimeout setsockopt settimeout setblocking recvfrom_intoceZdZdZdZdZdZdZdZdZ e Z dZ d Z d Z d Zd Zd ZdZdZdZdZdZdZdZdS) socketproxyzA proxy around a socket that tells a watcher when events occur. This is like ``fileobjectproxy`` except for sockets. This type is intended to only be used for testing purposes. Think hard before using it in important code. rcvt|d|t|d|dSrr)rMsockrs r$rQzsocketproxy.__init__s84$///4h77777r&c|tvrt||Stt|d|Sr)PROXIED_SOCKET_METHODSrrrrs r$rzsocketproxy.__getattribute__sD ) ) )**466 6v..tW==tDDDr&cTtt|d|Srrrs r$rzsocketproxy.__delattr__rr&cVtt|d||Srrrs r$rzsocketproxy.__setattr__rr&cRtt|dSrrr]s r$rzsocketproxy.__nonzero__rr&ct|d}t|||i|}t|d}t||d}|r ||g|Ri||Srrrs r$rzsocketproxy._observedcallrr&c t|ddg|Ri|}t|d}t|j||j|j|j|j|jS)Nrr rreadswriteslogdata logdataapis) rrmakeloggingfileobjectrrrr4r5r6r7)rMrrrrs r$r zsocketproxy.makefiles%%dO<<     !'   **4==$ K  M.?$ ,    r&cJt|ddg|Ri|S)Nrrrrs r$rzsocketproxy.recvrr&cJt|ddg|Ri|S)Nrr!rrs r$r!zsocketproxy.recvfromrr&cJt|ddg|Ri|S)Nrr'rrs r$r'zsocketproxy.recvfrom_intosA&&t_==  "   &,   r&cJt|ddg|Ri|S)Nr recv_inforrs r$r"zsocketproxy.recv_intorr&cJt|ddg|Ri|S)Nrrrrs r$rzsocketproxy.send rr&cJt|ddg|Ri|S)Nrrrrs r$rzsocketproxy.sendallrr&cJt|ddg|Ri|S)Nrrrrs r$rzsocketproxy.sendtorr&cJt|ddg|Ri|S)Nrr&rrs r$r&zsocketproxy.setblockingsA&&t_==      $*   r&cJt|ddg|Ri|S)Nrr%rrs r$r%zsocketproxy.settimeoutr r&cJt|ddg|Ri|S)Nrr#rrs r$r#zsocketproxy.gettimeout#r r&cJt|ddg|Ri|S)Nrr$rrs r$r$zsocketproxy.setsockopt(r r&N)rcrdrerfrrQrrrrrrr rr!r'r"rrrr&r%r#r$r)r&r$r)r)sCI 888EEE EEELLL<<<H      $                                   r&r)ceZdZdZdZdS)baseproxyobserverc>||_||_||_||_dSrS)rrrr6r7)rMrrrr6r7s r$rQzbaseproxyobserver.__init__/s%  &r&c|js<|jr3|jd|jdSd|vr|jr0|jdt j|zn6|jd|jt j|fz|jdS|jr|jd|d}|D]8}|jd|jt j|fz9|jdS)Nrs: %s s %s> %s s: T) r6r7rrrr<r escapestrr splitlines)rMrUlineslines r$ _writedatazbaseproxyobserver._writedata5sS|   e$$$  F     i**>t*D*DDEEEE #ty*2Ft2L2L&MM GMMOOO F   " GMM& ! ! !%%  D GMM49j.B4.H.H"II      r&N)rcrdrerQrMr)r&r$rFrF.s2''' r&rFcTeZdZdZ d fd ZddZddZdZd Zd Z d Z d Z xZ S)fileobjectobserverzLogs file object activity.TFcztt|||||||_||_dSrS)rrOrQr4r5)rMrrrr4r5r6r7rs r$rQzfileobjectobserver.__init__Vs<  $''00T7KPPP  r&rtc|jsdS|d}|dkr|dkrdS|jr2|jd|j|t |fz||dS)Nr&rts%s> read(%d) -> %dr4r7rrrrrwrMrMrrss r$rvzfileobjectobserver.read]sz  F ;C 2::#** F   O GMM/49dCHH2MM N N N r&c|jsdS|jr1|jd|jt |fz||dS)Ns%s> readline() -> %drR)rMrlimits r$rzfileobjectobserver.readlineps\z  F   K GMM1TYC4II J J J r&c"|jsdS|jr2|jd|jt ||fz| |d|nd}t |tr|}| |dS)Ns%s> readinto(%d) -> %rrr&) r4r7rrrrrwrrtobytesrM)rMrdestrUs r$rzfileobjectobserver.readintoysz  F    GMM)TYD 3,GG   "otAcE{{3 dJ ' ' "<<>>D r&c|jsdS||rt|}|jr2|jd|jt||fz||dS)Ns%s> write(%d) -> %r)r5rwr7rrrrrM)rMrrUs r$rzfileobjectobserver.writest{  F ;4;d))C   P GMM0DIs4yy#3NN O O O r&c`|jsdS|jd|j|fzdS)Ns%s> flush() -> %r )r5rrrrrMrs r$r<zfileobjectobserver.flushs8{  F  , 3/??@@@@@r&c|jsdS|jr2|jd|j|t |fz||dS)Ns%s> bufferedread(%d) -> %drRrSs r$rzfileobjectobserver.bufferedreadsez  F    GMM-D#c((0KK    r&c|jsdS|jr1|jd|jt |fz||dS)Ns%s> bufferedreadline() -> %drRr[s r$rz#fileobjectobserver.bufferedreadlinescz  F    GMM/49c#hh2GG    r&TTFTr) rcrdrerfrQrvrrrr<rrrrs@r$rOrOSs$$MQ&$   AAA          r&rOTFcLt||||||}t||S)z.Turn a file object into a logging file object.r3)rOr)loghrrrr4r5r6r7rs r$r8r8s< "   H 2x ( ((r&ceZdZdZ dfd ZddZddZdd Zdd Zdd Z dd Z dd Z ddZ dZ dZdZdZxZS)socketobserverzLogs socket activity.TFctt|||||||_||_||_dSrS)rrbrQr4r5states) rMrrrr4r5rdr6r7rs r$rQzsocketobserver.__init__sB nd##,,Rw LLL   r&Ncb|jsdS|jd|j||fzdS)Ns%s> makefile(%r, %r) rdrrrr)rMrmodebufsizes r$r zsocketobserver.makefiles:{  F  /49dG2LLMMMMMr&rc |jsdS|jr3|jd|j||t |fz||dS)Ns%s> recv(%d, %d) -> %drRrMrrsflagss r$rzsocketobserver.recvsgz  F    GMM)TYeSXX,NN    r&c |jsdS|jr9|jd|j||t |dfz||ddS)Ns%s> recvfrom(%d, %d) -> %drrRrjs r$r!zsocketobserver.recvfromsrz  F    GMM-9dE3s1v;;78    Ar&c|jsdS|jr,|jd|j|||dfz||d|ddS)Ns%s> recvfrom_into(%d, %d) -> %drr4r7rrrrrMrMrrrsrks r$r'zsocketobserver.recvfrom_intostz  F    GMM29dE3q623    AAJ(((((r&c|jsdS|jr&|jd|j|||fz||d|dS)Ns%s> recv_into(%d, %d) -> %drrnros r$r"zsocketobserver.recv_intosiz  F    GMM.$)T5#1NN    AcE #####r&c |jsdS|jd|jt ||t |fz||dS)Ns%s> send(%d, %d) -> %d)r5rrrrrwrMrMrrUrks r$rzsocketobserver.send sb{  F  %CIIuc#hh(O O    r&c|jsdS|jr2|jd|jt ||fz||dS)Ns%s> sendall(%d, %d)r5r7rrrrrwrMrrs r$rzsocketobserver.sendallse{  F    GMM&$)SYY)FF    r&c|jsdS|r|}nd}|jr4|jd|jt ||||fz||dS)Nrs%s> sendto(%d, %d, %r) -> %drt)rMrrUflagsoraddressaddressrks r$rzsocketobserver.sendto!s{  F  "EEE    GMM/9c$ii=>    r&c`|jsdS|jd|j|fzdS)Ns%s> setblocking(%r) rf)rMrflags r$r&zsocketobserver.setblocking2s8{  F  .$)T1BBCCCCCr&c`|jsdS|jd|j|fzdS)Ns%s> settimeout(%r) rf)rMrrs r$r%zsocketobserver.settimeout8s8{  F  -E0BBCCCCCr&c`|jsdS|jd|j|fzdS)Ns%s> gettimeout() -> %f rfr[s r$r#zsocketobserver.gettimeout>s8{  F  1TY4DDEEEEEr&cf|jsdS|jd|j||||fzdS)Ns!%s> setsockopt(%r, %r, %r) -> %r rf)rMrleveloptnamers r$r$zsocketobserver.setsockoptDsK{  F  1y%%5 6     r&TTTFTNNr)rrrS)rcrdrerfrQr rr!r'r"rrrr&r%r#r$rrs@r$rbrbs=       NNNN       ) ) ) ) $ $ $ $    "DDD DDD FFF        r&rbc Nt|||||||}t||S)z$Turn a socket into a logging socket.)r4r5rdr6r7)rbr)) r`rrrr4r5rdr6r7rs r$makeloggingsocketrNs?  H r8 $ $$r&c@ ddlm}|jS#t$rYdSwxYw)z(Return version information if available.r __version__sunknown)r/rr> ImportErrorrs r$r>r>fsD!!!!!!"" zzs  c|st}tjd|}|sd|}}nD|dr|\}}n|dd}}|Jg}|dD]6} |t|&#t$rYnwxYwt|dkr(|dt|dk(|dkr|d|dfS|dkr|d|d|dfS|d kr|d|d|d|fStj d |z) azParses a Mercurial version string into an N-tuple. The version string to be parsed is specified with the ``v`` argument. If it isn't defined, the current Mercurial version string will be parsed. ``n`` can be 2, 3, or 4. Here is how some version strings map to returned values: >>> v = b'3.6.1+190-df9b73d2d444' >>> versiontuple(v, 2) (3, 6) >>> versiontuple(v, 3) (3, 6, 1) >>> versiontuple(v, 4) (3, 6, 1, '190-df9b73d2d444') >>> versiontuple(b'3.6.1+190-df9b73d2d444+20151118') (3, 6, 1, '190-df9b73d2d444+20151118') >>> v = b'3.6' >>> versiontuple(v, 2) (3, 6) >>> versiontuple(v, 3) (3, 6, None) >>> versiontuple(v, 4) (3, 6, None, None) >>> v = b'3.9-rc' >>> versiontuple(v, 2) (3, 9) >>> versiontuple(v, 3) (3, 9, None) >>> versiontuple(v, 4) (3, 9, None, 'rc') >>> v = b'3.9-rc+2-02a8fea4289b' >>> versiontuple(v, 2) (3, 9) >>> versiontuple(v, 3) (3, 9, None) >>> versiontuple(v, 4) (3, 9, None, 'rc+2-02a8fea4289b') >>> versiontuple(b'4.6rc0') (4, 6, None, 'rc0') >>> versiontuple(b'4.6rc0+12-425d55e54f98') (4, 6, None, 'rc0+12-425d55e54f98') >>> versiontuple(b'.1.2.3') (None, None, None, '.1.2.3') >>> versiontuple(b'12.34..5') (12, 34, None, '..5') >>> versiontuple(b'1.2.3.4.5.6') (1, 2, 3, '.4.5.6') s(\d+(?:\.\d+){,2})[+-]?(.*)r&rN.rrs invalid version part request: %d) r>remodmatchgroupgroupssplitrintrrwr ProgrammingError)r}nmvpartsextravintsis r$ versiontuplerpsn  II 3Q77A )Q )  D     E \\$    LLQ     EE  e**q.. T e**q.. Avva%(##Avva%(E!H--Avva%(E!He44  !Dq!H I IIs"B22 C?Cc~jjdkr gfd}|Sijjdkrfd}nfd}|S)z"cache the result of function callsrcttdkrdSr()rwr)func listcachesr$fzcachefunc..fs89~~""  (((Q< r&rc8|vr||<|SrSr))argcachers r$rzcachefunc..fs)%!T#YYc : r&c,|vr||<|SrSr))rrrs r$rzcachefunc..fs'5  "dDkd ; r&)__code__ co_argcount)rrrrs` @@r$ cachefuncrs } A%%        E } A%%              Hr&ceZdZdZdZdZdS)cowz^helper class to make copy-on-write easier Call preparewrite before doing any writes. crt|ddr%|xjdzc_||S|S)z;call this before writes, return self or a copied new object_copiedrr)rrrr]s r$ preparewritezcow.preparewrites= 4A & & ( LLA LL>>$'' ' r&c8t|dddz|_|S)zalways do a cheap copyrrr)rrr]s r$copyzcow.copystY22Q6  r&N)rcrdrerfrrr)r&r$rrs< r&rc<eZdZdZfdZejrdZdZxZ S)sortdicta[a simple sorted dictionary >>> d1 = sortdict([(b'a', 0), (b'b', 1)]) >>> d2 = d1.copy() >>> d2 sortdict([('a', 0), ('b', 1)]) >>> d2.update([(b'a', 2)]) >>> list(d2.keys()) # should still be in last-set order ['b', 'a'] >>> d1.insert(1, b'a.5', 0.5) >>> d1 sortdict([('a', 0), ('a.5', 0.5), ('b', 1)]) ch||vr||=tt|||dSrS)rr __setitem__)rMrYrrs r$rzsortdict.__setitem__ s9 $;;S  h))#u55555r&c t|tr|}|D] \}}|||< |D] }||||<dSrS)rrnr{)rMsrcrrPr}s r$rLzsortdict.updatesg#t$$ "iikk  1Q  A$Q  r&ctt|D]!\}\}}||kr|||<||kr||=|||<"dSrS) enumeratelistr{)rMpositionrYrrrPr}s r$insertzsortdict.insertsg$T$**,,%7%788  KQAH}}!S H}}GQ   r&) rcrdrerfrrispypyrLrrrs@r$rrsl  66666    r&rceZdZdZdS)cowdictacopy-on-write dict Be sure to call d = d.preparewrite() before writing to d. >>> a = cowdict() >>> a is a.preparewrite() True >>> b = a.copy() >>> b is a True >>> c = b.copy() >>> c is a True >>> a = a.preparewrite() >>> b is a False >>> a is a.preparewrite() True >>> c = c.preparewrite() >>> b is c False >>> b is b.preparewrite() True Nrcrdrerfr)r&r$rr!sr&rceZdZdZdS) cowsortdictzZcopy-on-write sortdict Be sure to call d = d.preparewrite() before writing to d. Nrr)r&r$rr<sr&rcleZdZdZejZejdZejdZ dZ dZ dS) transactionalzBBase class for making a transactional type into a context manager.cdS)z$Successfully closes the transaction.Nr)r]s r$rztransactional.closeHr&cdS)zoMarks the end of the transaction. If the transaction has not been closed, it will be aborted. Nr)r]s r$releaseztransactional.releaseLrr&c|SrSr)r]s r$ __enter__ztransactional.__enter__S r&c |||dS#|wxYwrS)rr)rMexc_typeexc_valexc_tbs r$__exit__ztransactional.__exit__Vs=  LLNNNNNDLLNNNNs .AN) rcrdrerfabcABCMeta __metaclass__abstractmethodrrrrr)r&r$rrCs{LLKM333    r&rc#K|sdVdS dV|n(#tj$r|wxYw |dS#|wxYw)zA context manager that closes the transaction on InterventionRequired If no transaction was provided, this simply runs the body and returns N)rr InterventionRequiredr)trs r$acceptinterventionr^s      %      s%A$%A  A$$A:c#K|VdSrSr)) enter_results r$nullcontextmanagerrqs r&c"eZdZdZdZdZdZdS) _lrucachenodezA node in a doubly linked list. Holds a reference to nodes on either side as well as a key-value pair for the dictionary entry. )nextprevrYrcostcV||_||_t|_d|_d|_dSr()rr_notsetrYrrr]s r$rQz_lrucachenode.__init__s)    r&c:t|_d|_d|_dS)zMark the node as emptied.Nr)rrYrrr]s r$ markemptyz_lrucachenode.markemptys  r&N)rcrdrerfrrQrr)r&r$rrvsC 9Ir&rceZdZdZddZdZdZdZdZddZ d Z d Z e fd Z dd Ze fdZdZddZdZdZdZdZd S) lrucachedictaDict that caches most recent accesses and sets. The dict consists of an actual backing dict - indexed by original key - and a doubly linked circular list defining the order of entries in the cache. The head node is the newest entry in the cache. If the cache is full, we recycle head.prev and make it the new head. Cache accesses result in the node being moved to before the existing head and being marked as the new head node. Items in the cache can be inserted with an optional "cost" value. This is simply an integer that is specified by the caller. The cache can be queried for the total cost of all items presently in the cache. The cache can also define a maximum cost. If a cache insertion would cause the total cost of the cache to go beyond the maximum cost limit, nodes will be evicted to make room for the new code. This can be used to e.g. set a max memory limit and associate an estimated bytes size cost to each item in the cache. By default, no maximum cost is enforced. rcri|_t|_d|_||_d|_||_dS)Nrr)_cacher_headrlcapacity totalcostmaxcost)rMrrs r$rQzlrucachedict.__init__s4 "__    r&c*t|jSrS)rwrr]s r$__len__zlrucachedict.__len__s4;r&c||jvSrS)rrMrPs r$ __contains__zlrucachedict.__contains__sDKr&c#K|j}tt|jD]}|jV|j}dSrS)rrangerwrrYr)rMrrs r$r^zlrucachedict.__iter__sL Js4;''((  A%KKKAA  r&cT|j|}|||jSrS)r _movetoheadr)rMrPnodes r$rZzlrucachedict.__getitem__s){1~ zr&cp|j|}|e|xj|jzc_||_||_|xj|z c_|||jr|dS|j|j kr| }n |j j }|j tur"|xj|jzc_|j|j =||_ ||_||_|xj|z c_||j|<||_ |jr|dSdS)z8Insert a new item in the cache with optional cost value.N)rgetrrrrr_enforcecostlimitrlr _addcapacityrrrYr)rMrPr}rrs r$rzlrucachedict.inserts?{q!!   NNdi 'NNDJDI NNd "NN   T " " "| )&&((( F : % %$$&&DD:?D 87 " " NNdi 'NN DH%   $ A < %  " " $ $ $ $ $ % %r&c2|||dSrS)rr|s r$rzlrucachedict.__setitem__s Aqr&c0||dSrS)poprs r$ __delitem__zlrucachedict.__delitem__s  r&c  |j|}n#t$r|tur|cYSwxYw|J|j}|xj|jzc_||||j |_ |SrS) rrKeyErrorrrrrrrrr)rMrPr.rrs r$rzlrucachedict.pops ;??1%%DD   '!!NNN    $)#  Y  s 66NcR ||S#t$r|cYSwxYwrS)rZr)rMrPr.s r$rzlrucachedict.gets? ##A&& &   NNN   &&cl |j|}|J|jS#t$r|tur|cYSwxYw)zGet the specified item without moving it to the head Unlike get(), this doesn't mutate the internal state. But be aware that it doesn't mean peek() is thread safe. )rrrr)rMrPr.rs r$peekzlrucachedict.peek sX  ;q>D###:    '!!NNN s 33c|j}|jtur>|xj|jzc_||j}|jtu>|jdSrS) rrYrrrrrrclear)rMrs r$rzlrucachedict.clearsg Je7"" NNaf $NN KKMMMAe7"" r&cr|p|j}|p|j}t||}|jj}|jt ur'||jur|j}|jt ur ||jutt|j D]0}| |j|j |j |j}1|S)a8Create a new cache as a copy of the current one. By default, the new cache has the same capacity as the existing one. But, the cache capacity can be changed as part of performing the copy. Items in the copy have an insertion/access order matching this instance. )r)r) rrrrrrYrrrwrrrr)rMrrresultrrs r$rzlrucachedict.copy!s,t})T\h888 JOew1DJ#6#6Aew1DJ#6#6 s4;''((  A MM!%qvM 6 6 6AA r&c|jsdS|jj}|J|jtur|j}|jtu|J|j|j}}|j|j=|xj|jzc_|||fS)zuRemove the oldest item from the cache. Returns the (key, value) describing the removed cache entry. N) rrrrYrrrrr)rMrrYrs r$ popoldestzlrucachedict.popoldest@s {  F JO}}}ewAew}}}UAGU K  !&  Ezr&c|j}|j|j_|j|j_|j|_|jj|_||j_||j_||_dS)aqMark a node as the newest, making it the new head. When a node is accessed, it becomes the freshest entry in the LRU list, which is denoted by self._head. Visually, let's make ``N`` the new head node (* denotes head): previous/oldest <-> head <-> next/next newest ----<->--- A* ---<->----- | | E <-> D <-> N <-> C <-> B To: ----<->--- N* ---<->----- | | E <-> D <-> C <-> B <-> A This requires the following moves: C.next = D (node.prev.next = node.next) D.prev = C (node.next.prev = node.prev) E.next = N (head.prev.next = node) N.prev = E (node.prev = head.prev) N.next = A (node.next = head) A.prev = N (head.prev = node) N)rrr)rMrheads r$rzlrucachedict._movetohead\sT:z  I IN    r&c|j}t}||j_|j|_||_||_|xjdz c_|S)zhAdd a node to the circular linked list. The new node is inserted before the head node. r)rrrrrl)rMrrs r$rzlrucachedict._addcapacitysH z I    a  r&ct|dks|j|jkrdSt|jdz}|jj}|jtur|j}|jtut|dkrh|j|kra|j|j=|xj|j zc_| |j}t|dkr|j|k[dSdSdSdS)Nrg?) rwrrrrrrYrrrr)rM targetcostrs r$rzlrucachedict._enforcecostlimits t99>>T^t|;; F,-- JOewAew$ii!mm ; ; AE" NNaf $NN KKMMMA $ii!mm ; ; ; ;mmmm ; ;r&rrSr()rcrdrerfrQrrr^rZrrrrrrrrrrrrrr)r&r$rrsG,       %%%%%%%%N%, &    >8---^   r&rctitjjjdkrfd}nfd}|S)z+cache most recent results of function callsrc|vr7tdkr=||<n|||SNrwpopleftremover)rrrorders r$rzlrucachefunc..fsn%u::??emmoo.!T#YYc  S!!! LL   : r&c|vr1tdkr=||<n|||Srr)rrrrs r$rzlrucachefunc..fsl5  u::??emmoo."dDkd  T""" LL   ; r&) collectionsdequerr)rrrrs` @@r$ lrucachefuncrsz E    E } A%%                Hr&c"eZdZdZddZdZdS) propertycachec,||_|j|_dSrS)rrcr)rMrs r$rQzpropertycache.__init__s M r&Nc\||}||||SrS)r cachevalue)rMobjtypers r$__get__zpropertycache.__get__s*3 V$$$ r&c$||j|j<dSrS)__dict__r)rMrrs r$rzpropertycache.cachevalues"' TYr&rS)rcrdrerQrrr)r&r$rrsF""" (((((r&rcTtj|}||jvr |j|=dSdS)z2clear a cached property value, if one has been setN)rr8r!)rprops r$clearcachedpropertyr$s6 ?4 D s| L   r&c#:Kd}g}d}|D]s}|||t|z }||krD||kr#|dz}d||z}||kr|}||kr|}d|Vd}g}t|rd|VdSdS)zrreturn no less than min bytes per chunk while data remains, doubling min after each chunk until it reaches maxc4|sdSd}|r |dz}|dz }| |dz S)Nrrr))xrs r$log2zincreasingchunks..log2sC 1   !GA FA 1u r&rrr&N)rrwr)sourcerrr*rblenchunknmins r$increasingchunksr/s C D   5 E  3;;SyyQhDDJJ#::C99C((3--   DC hhsmmr&cdS)NTr)rs r$alwaysr2s 4r&cdSNFr)r1s r$neverr5s 5r&cfd}|S)a disable garbage collector Python's garbage collector triggers a GC each time a certain number of container objects (the number being defined by gc.get_threshold()) are allocated even when marked not to be tracked by the collector. Tracking has no effect on when GCs are triggered, only on what objects the GC looks into. As a workaround, disable GC while building complex (huge) containers. This garbage collector issue have been fixed in 2.7. But it still affect CPython's performance. ctj}tj |i||rtjSS#|rtjwwxYwrS)gc isenableddisableenable)rr gcenabledrs r$wrapperznogc..wrapper&sgLNN   4(((   y   s AAr)rr=s` r$nogcr?s# Nr&c|SrSr)r)s r$rr4sQr&cn|st|Stj|rtj|dtj|dkr-tj|t|Sdt ||f}t||d}}| | |rR|rP|d|dkr>| | |r|r|d|dk>| tj dgt|z|zpdS)aareturn the relative path from one place to another. root should use os.sep to separate directories n1 should use os.sep to separate directories n2 should use "/" to separate directories returns an os.sep-separated path. If n1 is a relative path, it's assumed it's relative to root. n2 should always be relative to root. r/rt..r) localpathr pathisabs splitdriverpconvert splitpathrreverserrosseprw)rootn1n2abs r$pathtorR7sd }} w}}R- 7  d # #A &"'*<*  #a&& 0A5 6 6 >$>r&cfd}|S)z5wrap a function with code to check for calling errorsc |i|S#t$rJttjt jdkr t jwxYw)Nr) TypeErrorrw traceback extract_tbr:exc_infor SignatureError)rrdepthrs r$checkzchecksignature..checkVsm 4((( (   9' q(9::;;uDD**  s  AAr))rrZr[s`` r$checksignaturer\Ss) Lr&> hfsjfsufsxfszfsNTFSapfsext2ext3ext4btrfstmpfsreiserfscZ|r|rJd}tj|r-|r|ot|}t ||rY|rW t tj|} n#t$rd} YnwxYw| tvr| |d}|rj t|||d} tj | dS#ttf$r+} | jtjkr | |Yd} ~ nd} ~ wwxYwtj|rAtjtj|||d} tj | dS t'j|||rt'j||nt'j|||rj|jrct|} | |r4|jt.jdzdz} tj|| | f|At7|d5}||ddddS#1swxYwYdSdS#t&j$r+}tjt?j |d}~wwxYw) afcopy a file, preserving mode and optionally other stat info like atime/mtime checkambig argument is used with filestat, and is useful only if destination file is guarded by any lock (e.g. repo.lock or repo.wlock). copystat and checkambig should be exclusive. nb_bytes: if set only copy the first `nb_bytes` of the source file. NFz7the `nb_bytes` argument is incompatible with `hardlink`z"cannot use `nb_bytes` on a symlinkrzr+)rg)!r rFlexistsfilestatfrompathunlink getfstypedirnameOSError_hardlinkfswhitelistoslinkr rIOErrorerrnoEEXISTislinksymlinkreadlinkshutilcopyfilecopystatcopymodestatisambigST_MTIMEutimerrErrorrJr forcebytestr)rrXhardlinkr} checkambignb_bytesno_hardlink_cbcheck_fs_hardlinkoldstatfstyperexcnewstatadvancedrinsts r$r|r|ss?*(Z(((G wt  = I! I0!I%%I0(I%)I00J*?&J%%J*c0d}fd}tj|rQtj|jtjtj|jk|tj|t|D]_\}}tj||}tj||} t|| \} || z }`nntjtj|jtjtj|jk|r\ t||n_#ttf$r6} | j tjkrdtj||Yd} ~ nd} ~ wwxYwtj|||dz }r|fS)z2Copy a directory tree using hardlinks if possible.rcZr'rtdntd_dSdS)Nslinkingscopying)rKtopic)rprogresssr$settopiczcopyfiles..settopics8  J.6IQz]]]AjMMHNNN J Jr&NFr)r rFisdirrst_devrqmkdirlistdirr copyfilesrtrurrrvrwr{r increment) rdstrrnumrrkindsrcnamedstnamerrs `` r$rrs CJJJJJJ w}}S !   #rwrws/C/C'D'D'KK     !#,,  JD$gll3--Ggll3--G#GWhIIKHa 1HCC    ,,--4727??3//0078    " &sC    W% & & &9 ,,$H C%%%%%%%%  & KS ! ! ! q  !    S=s FG!+,GG!>auxconnulprncom1com2com3com4com5com6com7com8com9lpt1lpt2lpt3lpt4lpt5lpt6lpt7lpt8lpt9s:*?"<>|c|drtdSd|vrtdS|dddD]}|st |D]\}|t vrtd|zccSt |dkr(tdtj|zccS]|d d }|r/| tvrtd|zcS|d d }|d vr|dvrtd|zcSd S)aUCheck that the base-relative path is a valid filename on Windows. Returns None if the path is ok, or a UI string describing the problem. >>> checkwinfilename(b"just/a/normal/path") >>> checkwinfilename(b"foo/bar/con.xml") "filename contains 'con', which is reserved on Windows" >>> checkwinfilename(b"foo/con.xml/bar") "filename contains 'con', which is reserved on Windows" >>> checkwinfilename(b"foo/bar/xml.con") >>> checkwinfilename(b"foo/bar/AUX/bla.txt") "filename contains 'AUX', which is reserved on Windows" >>> checkwinfilename(b"foo/bar/bla:.txt") "filename contains ':', which is reserved on Windows" >>> checkwinfilename(b"foo/bar/b\07la.txt") "filename contains '\\x07', which is invalid on Windows" >>> checkwinfilename(b"foo/bar/bla ") "filename ends with ' ', which is not allowed on Windows" >>> checkwinfilename(b"../bar") >>> checkwinfilename(b"foo\\") "filename ends with '\\', which is invalid on Windows" >>> checkwinfilename(b"foo\\/bar") "directory name ends with '\\', which is invalid on Windows" \s3filename ends with '\', which is invalid on Windowss\/s9directory name ends with '\', which is invalid on WindowsrCs4filename contains '%s', which is reserved on Windowss3filename contains '%s', which is invalid on WindowsrrrtNs. rDs8filename ends with '%s', which is not allowed on Windows) endswithrKreplacer_filenamebytestr_winreservedcharsordrrIlower_winreservednames)rFrcbasets r$checkwinfilenamer s2 }}UJHIII ~~NOOO \\% & & , ,T 2 2  !!$$ , ,A%%%& 1vv||J(++,,,,,,wwt}}Q  DJJLL$555IJJ    bccF ::!5.."    1r& perf_counterc tj||S#t$r }|jtjkrYd}~nd}~wt $rYnwxYwtjtjztjzttddz}tj ||}tj ||tj |dS)zCreate a lock file atomically if possible This may leave a stale lock file if symlink isn't supported and signal interrupt is enabled. NO_BINARYr) r ryrrrvrwAttributeErrorO_CREATO_WRONLYO_EXCLrrrr)infopathnamewhyrklds r$makelockrVs  z$)))  9 $ $  % $ $ $ $       J $ry 072z13M3M ME 5 ! !BHRHRLLLLLs A < A  A c" t|S#t$r*}|jtjtjfvrYd}~nd}~wt $rYnwxYwt |d5}|cdddS#1swxYwYdSNrb)rzrrrvEINVALENOSYSr posixfilerv)rrrs r$readlockrjs !!!  9U\5<8 8 8  9 8 8 8 8      8U # #rwwyys, A A AA#BB Bc tj|S#t$rtj|jcYSwxYw)z1stat file object that may not have fileno method.)r rrrrrrs r$rrwsR x $$$    wrw s%(#A Acztj|}tj|\}}|}||kr|}||krdStj||} tj|}||krdSdS#t$rYdSwxYw)z Return true if the given path is on a case-sensitive filesystem Requires a path (like /foo/.hg) ending with a foldable final directory component. TF)r lstatrFrupperrrrr)rFs1drQb2p2s2s r$fscasesensitivers $B 7==  DAq BBww WWYY 774 a  B Xb\\ 885t ttsB,, B:9B:c|SrSr)rAs r$rrsqr&c2eZdZdZddZedZdS)_rec>d}d} ttj||adS#t$rdaYdSt $rZt j|}t j|}ttj||at jaYdSwxYw)Ns \[([^\[]+)\]s[ui]F) rre2r_re2rrUrr8 _re2_input)rM check_pattern check_inputs r$ _checkre2z _re._checkre2s)   ) -==>>DDD   DDDD ) ) )%OM::M"/+66K -==>>D!JJJJ  )s"* BABBrcpt|tr|tjtjzzdkr_|tjzrd|z}|tjzrd|z} t jt|S#t j$rYnwxYwtj||S)zCompile a regular expression, using re2 if possible For best performance, use only re2-compatible regexp features. The only flags from the re module that are re2-compatible are IGNORECASE and MULTILINE.Nrs(?i)s(?m)) rrr IGNORECASE MULTILINErcompilerr )rMpatrks r$rz _re.compiles < NN     Uu/%/ABBqHHu'' $mu& $m {:c??3339    }S%(((s- BB B cvt|tr tjStjS)zReturn the version of escape corresponding to self.compile. This is imperfect because whether re2 or re is used for a particular function depends on the flags, etc, but it's the best we can do. )rrrescaperr]s r$rz _re.escapes1 < NN     : < r&Nr)rcrdrerrrrr)r&r$rrsR)))&))))&   ]    r&rcd}tj}tjr|tjz}|ddt jd||fz}t j|}g}| |D]\}}|r| ||tvr||t|<t|} | |} | s*||xt|<} | |} | | p|t j ||}d |S)a4Get name in the case stored in the filesystem The name should be relative to root, and be normcase-ed for efficiency. Note that this function is unnecessary, and should not be called, for case-sensitive filesystems (simply because it's expensive). The root should be normcase-ed, too. c>dtj|DS)Nc.i|]}t||Sr))normcase).0rs r$ z9fspath.._makefspathcacheentry..s 8881 Q888r&)r r)dirs r$_makefspathcacheentryz%fspath.._makefspathcacheentrys88 38888r&rs\\s([^%s]+)|([%s]+)r&)rrLosaltseprrrr rFnormpathfindallr _fspathcacherr) rrMrsepspatternrrpartsepcontentsfounds r$fspathrse999 >D(h''LL   m0D$<?@@G '  4 C F__T**&& c   MM#     l " " 5 5c : :L $ T"" ',A+@+E+E EL LL&&E emt$$$gll3%% 88F  r&c(d\}}} tjdtj|zdtj|\}}tj|d|ddz}t||t|}t|dk||||fD])} |tj |#t$rY&wxYwS#t$rHY||||fD])} |tj |#t$rY&wxYwd SwxYw#||||fD])} |tj |#t$rY&wxYwwxYw) z5check whether hardlink count reporting works properly)NNN.%s-s1~prefixsuffixrs%s2~NrF) rmkstempr rFbasenamerqrrtrnlinksrorr)testfilef1f2rrrs r$ checknlinkr s "JBB!RW--h777))   B  r#2#w r2r]]bzzA~ > HHJJJb  A =IaLLL        > HHJJJb  A =IaLLL         > HHJJJb  A =IaLLL      slB)C6C%% C21C26 EE D55 EEEE F)F?F F F F Fct|tjp*tjo|tjS)z)Check path ends with os.sep or os.altsep.)rrrrLrrFs r$ endswithsepr/ sI  hn%% -   - MM(+ , ,  r&c@|tjS)zSplit path by os.sep. Note that this function does not use os.altsep because this is an alternative of simple "xxx.split(os.sep)". It is recommended to use os.path.normpath() before using this function if need.)rrrLrs r$rJrJ9 s ::hn % %%r&ctj|\}}tjd|zd|\}}tj|t |||||r|S t|d}nG#t$r:} | j tj kr|cYd} ~ St| dds|| _ d} ~ wwxYwt|d} t|D]} | | || n,# tj|n#t $rYnwxYwxYw|S)aCreate a temporary file with the same contents from name The permission bits are copied from the original file. If the temporary file is going to be truncated immediately, you can use emptyok=True as an optimization. Returns the name of the temporary file. r~rrNfilenamewb)r rFrrr rr~rrurvENOENTrr filechunkiterrrorr) remptyok createmodeenforcewritablerrrtempifprofpr-s r$ mktempcopyr"C s~ GMM$  EArw|DaHHHHBHRLLL T4_555  D%((CC   zU\)) 4T22 % $    e$$"3''  E IIe        IdOOOO    D  Ksa,A=<D$= CB<CD$#B<<CA"D$$E 'D<;E < E E E  E cjeZdZdZdZedZedZej Z dZ dZ dZ dZ d S) rmzhelp to exactly detect change of a file 'stat' attribute is result of 'os.stat()' if specified 'path' exists. Otherwise, it is None. This can avoid preparative 'exists()' examination on client side of this class. c||_dSrS)r)rMrs r$rQzfilestat.__init__v s  r&ch tj|}n#t$rd}YnwxYw||SrS)r rFileNotFoundError)rrFrs r$rnzfilestat.frompathy sH 74==DD    DDD s4yyrcdtj|}||SrS)r rr)rrrs r$fromfpzfilestat.fromfp s'x $$s4yyr&c` |jj|jjko_|jtj|jtjko/|jtj|jtjkS#t$rYnwxYw |jduo|jduS#t$rYdSwxYwr4)rrST_CTIMErrrMolds r$__eq__zfilestat.__eq__ s   !SX%55HIdm,0GGHIdm,0GG      D  9$9T)9 9   55 s$A9A<< B B  B B-,B-c |jtj|jtjkS#t$rYdSwxYw)aExamine whether new (= self) stat is ambiguous against old one "S[N]" below means stat of a file at N-th change: - S[n-1].ctime < S[n].ctime: can detect change of a file - S[n-1].ctime == S[n].ctime - S[n-1].ctime < S[n].mtime: means natural advancing (*1) - S[n-1].ctime == S[n].mtime: is ambiguous (*2) - S[n-1].ctime > S[n].mtime: never occurs naturally (don't care) - S[n-1].ctime > S[n].ctime: never occurs naturally (don't care) Case (*2) above means that a file was changed twice or more at same time in sec (= S[n-1].ctime), and comparison of timestamp is ambiguous. Base idea to avoid such ambiguity is "advance mtime 1 sec, if timestamp is ambiguous". But advancing mtime only in case (*2) doesn't work as expected, because naturally advanced S[n].mtime in case (*1) might be equal to manually advanced S[n-1 or earlier].mtime. Therefore, all "S[n-1].ctime == S[n].ctime" cases should be treated as ambiguous regardless of mtime, to avoid overlooking by confliction between such mtime. Advancing mtime "if isambig(oldstat)" ensures "S[n-1].mtime != S[n].mtime", even if size of a file isn't changed. F)rr*rr+s r$rzfilestat.isambig sF< 9T]+sx /FF F   55 s/2 AAc|jtjdzdz} tj|||fn#t$rYdSwxYwdS)aLChange file stat of specified path to avoid ambiguity 'old' should be previous filestat of 'path'. This skips avoiding ambiguity, if a process doesn't have appropriate privileges for 'path'. This returns False in this case. Otherwise, this returns True, as "ambiguity is avoided". rrkFT)rrr rPermissionError)rMrFr,rs r$ avoidambigzfilestat.avoidambig sfHT]+a/:=  HTHh/ 0 0 0 0   55 ts7 AAc||k SrSr))rMothers r$__ne__zfilestat.__ne__ s5=  r&N)rcrdrerfrQ classmethodrnr(r__hash__r-rr1r4r)r&r$rmrmn s[[H"!!!F(!!!!!r&rmc8eZdZdZd dZdZdZdZd Zd Z dS) atomictempfileawritable file object that atomically updates a file All writes will go to a temporary copy of the original file. Call close() when you are done writing, and atomictempfile will rename the temporary copy to the original name, making the changes visible. If the object is destroyed without being closed, all your writes are discarded. checkambig argument of constructor is used with filestat, and is useful only if target file is guarded by any lock (e.g. repo.lock or repo.wlock). w+bNFc8||_t|d|v|d|v|_t|j||_||_|jj|_|jj|_|jj|_|jj |_ |jj |_ dS)Nw)rrr) _atomictempfile__namer" _tempnamer_fp _checkambigrvrrrr)rMrrgrrs r$rQzatomictempfile.__init__ s # T\!!T\    T^T22%HM X^ HM HM ho r&c|jjs|jt|j}|jot |}|r|jr|t|j |t |}| |r6|jtj dzdz}tj|||fdSdSt|j |dSdS)Nrrk)r>rrrEr<r?rmrnrrenamer=rrr r)rMrrrrs r$rzatomictempfile.close sx 1 HNN    --H&F8+<+rr ror=rrrr]s r$discardzatomictempfile.discard sjx   $.))))     HNN        s ( 55cRt|dr|dSdS)Nr>) safehasattrrCr]s r$__del__zatomictempfile.__del__ s/ tU # #  LLNNNNN  r&c|SrSr)r]s r$rzatomictempfile.__enter__ rr&c^||dS|dSrS)rCr)rMexctypeexcvaluerVs r$rzatomictempfile.__exit__ s*   LLNNNNN JJLLLLLr&)r9NF) rcrdrerfrQrrCrFrrr)r&r$r8r8 s}  &&&&& 1 1 1r&r8c t|dS#t$r<}|jtjkr|jtjkrYd}~dSYd}~dSd}~wwxYwrS) removedirsrrrvr ENOTEMPTY)res r$tryrmdirrO s{1  7el " "qw%/'A'A  # " " " " "'A'A'A'A'A'As A+AAc|rt|nt||r@ ttj|dS#t $rYdSwxYwdS)z.unlink and remove the directory if it is emptyN) tryunlinkrorLr rFrqrr)r ignoremissingrmdirs r$ unlinkpathrT" s! q    rwq)) * * * * *    DD  s,A A! A!cH t|dS#t$rYdSwxYw)z5Attempt to remove a file, ignoring FileNotFoundError.N)ror&)rs r$rQrQ1 s8 q      s  !!c t||n#t$r}|jtjkrYd}~dS|jtjks|st jt|}||krt||| t||n2#t$r%}|jtjkr Yd}~Yd}~dSd}~wwxYwYd}~nd}~wwxYw|t j ||dSdS)zrecursive directory creation with parent mode inheritance Newly created directories are marked as "not to be indexed by the content indexing service", if ``notindexed`` is specified for "write" mode access. N) makedirrrrvrwrr rFrqabspathmakedirschmod)rrg notindexederrparents r$rYrY: s:j!!!!  9 $ $ FFFFF 9 $ $D $ // T>> z***  D* % % % %   yEL((    & % % % %   tsJ C"CACB&%C& C0CCCCCC"c~t|d5}|cdddS#1swxYwYdSr)rrv)rFrs r$readfiler_X s~ dE  bwwyys 266ct|d5}||ddddS#1swxYwYdS)NrrrrFtextrs r$ writefilerd^ dE  b  488ct|d5}||ddddS#1swxYwYdS)Nsabrarbs r$ appendfilerhd rerfc eZdZdZdZddZdS) chunkbufferzoAllow arbitrary sized chunks of data to be efficiently read from an iterator over chunks of arbitrary size.cjd}|||_tj|_d|_dS)z?in_iter is the iterator that's iterating over the input chunks.c3K|D]U}t|dkr.splitbigq s  u::''CE **!Gm#CGn,,,!E **  KKKK  r&rN)r\rr_queue _chunkoffset)rMin_iterrss r$rQzchunkbuffer.__init__n sB HW%% !')) r&Nc|d|jS|}g}|j}|dkr|s>d}|jD]1}|||t |z}|dkrn2|sn|d}t |}|j}|dkr5||kr/||z}|||||z } || kr>|| z}||||dd|_n5|||||z|xj|z c_|| z}|dkd|S)zRead L bytes of data from the iterator of chunks of data. Returns less than L bytes if the iterator runs dry. If size parameter is omitted, read everythingNr&rrn)rr\rtrrwrur) rMlleftrqueuetargetr-chunklrchunkremainings r$rvzchunkbuffer.read s 988DI&& & Qhh  !YELL'''c%jj(F{{#!HEZZF&F{{tv~~  5!!!#f_N~%%&  5>***$%!! 5&4-!78999!!T)!!&[Qhh^xx}}r&rS)rcrdrerfrQrvr)r&r$rjrjj sA//$::::::r&rjc#K|dksJ||dksJ ||}nt||}|o||}|sdS|r|t|z}|VI)aYCreate a generator that produces the data in the file size (default 131072) bytes at a time, up to optional limit (default is to read all data). Chunks may be less than size bytes if the chunk is the last chunk in the file, or the file is a socket or some other type of file that sometimes reads less data than is requested.rN)rrvrw)rrsrUnbytesrOs r$rr s 19999 =EQJJJJ  =FF%%F  %qvvf~~  E   SVVOE r&c&eZdZdZdZddZdZdS) cappedreaderaA file object proxy that allows reading up to N bytes. Given a source file object, instances of this type allow reading up to N bytes from that source file object. Attempts to read past the allowed limit are treated as EOF. It is assumed that I/O is not performed on the original file object in addition to I/O that is performed by this instance. If there is, state tracking will get out of sync and unexpected results will ensue. c"||_||_dS)z,Allow reading up to bytes from .N)rk_left)rMrrrUs r$rQzcappedreader.__init__ s r&rtc|jsdS|dkr|j}|jt||j}|xjt |zc_|jdksJ|S)Nr&r)rrkrvrrw)rMrrUs r$rvzcappedreader.read sjz 3 q55 Ax}}SDJ//00 c$ii zQ r&c|t|}|dS||dt|<t|Sr()rvrw)rMrQrs r$rzcappedreader.readinto sAiiA ;4!c#hh,3xxr&Nr)rcrdrerfrQrvrr)r&r$rr sP      r&rcfd}|S)z@return a function that renders a readable count of some quantitycD]3\}}}t|||zkr||t|z zcS4dd|zS)Nrtr)absfloat)count multiplierdivisorformat unittables r$gozunitcountfn..go sd+4 9 9 'J5zzWz111w!788882}Q%''r&r))rrs` r$ unitcountfnr s#((((( Ir&c||z dkr!tjtd|dkr!tjtd|dz |fS)aCheck that linerange : makes sense and return a 0-based range. >>> processlinerange(10, 20) (9, 20) >>> processlinerange(2, 1) Traceback (most recent call last): ... ParseError: line range must be positive >>> processlinerange(0, 5) Traceback (most recent call last): ... ParseError: fromline must be strictly positive rsline range must be positivers"fromline must be strictly positive)r ParseErrorrK)fromlinetolines r$processlineranger s` 1q!?@@AAA!||q!FGGHHH a< r&d@s%.0f GB s%.1f GBs%.2f GBrms%.0f MBs%.1f MBs%.2f MBs%.0f KBs%.1f KBs%.2f KBs %.0f bytesc*eZdZdZdZdZdZdZdS)transformingwriterz3Writable file wrapper to transform data by functionc"||_||_dSrS)r>_encode)rMrencodes r$rQztransformingwriter.__init__. s r&c8|jdSrS)r>rr]s r$rztransformingwriter.close2  r&c8|jdSrS)r>r<r]s r$r<ztransformingwriter.flush5 rr&c\|j||SrS)r>rr)rMrUs r$rztransformingwriter.write8 s"x~~dll400111r&N)rcrdrerfrQrr<rr)r&r$rr+ sV==22222r&rs\r*\nc8td|S)Nr_eolresubrOs r$tolfrB s ::eQ  r&c8td|S)N rrs r$tocrlfrG s ::gq ! !!r&c,t|tSrS)rrrs r$ _crlfwriterrL s b& ) ))r&rc|SrSr)rs r$iterfiler[ s Ir&c#JK|D]}|D]}|VdSrS)rJ)iteratorr-rLs r$ iterlinesr_ sJ$$&&  DJJJJ r&cztjtj|SrS)r rF expanduser expandvarsrs r$ expandpathrf s( 7  bg0066 7 77r&c"pdd}|r-|d|zz }t|dkr |dd}n|}||<tjd||fz}|fd|S)aReturn the result of interpolating items in the mapping into string s. prefix is a single character string, or a two character string with a backslash as the first character if the prefix needs to be escaped in a regular expression. fn is an optional function that will be applied to the replacement text just before replacement. escape_prefix is an optional flag that allows using doubled prefix for its escaping. c|SrSr)rs r$rzinterpolate..x s!r&|rNs%s(%s)cZ|ddS)Nr)r)r)rmappings r$rzinterpolate.. s&22gaggiim455r&)rrprwrrr)rrrOr escape_prefixpatterns prefix_charrs ` ` r$ interpolaterk s  Byy((H+D6M! v;;?? *KK K*  jFH#5566A 5555555q 9 99r&g@@s%.0f ss%.1f ss%.2f ss%.3f sgMbP?s%.1f mss%.2f mss%.3f msgư>s%.1f uss%.2f uss%.3f usg& .>s%.1f nss%.2f nss%.3f nsceZdZdZejejdZejdZejdZ dZ e j e Z dS) timedcmstatszFStats information produced by the timedcm context manager on entering.ctSrS)timerr)r&r$rztimedcmstats. s r&)r.rrc<|jrt|jndS)Ns )elapsed timecountr]s r$ __bytes__ztimedcmstats.__bytes__ s*.,Hy&&&LHr&N)rcrdrerfribFactorystartrr}rr strmethod__str__r)r&r$rr sPP DGLDL99 : : :Edga   G DGA   EIII!h ++GGGr&rc'Ktxjdz c_ttj} tj|g|R5|Vdddn #1swxYwYt |jz |_txjdzc_dS#t |jz |_txjdzc_wxYw)zA context manager that produces timing information for a given context. On entering a timedcmstats instance is produced. This context manager is reentrant. r)r}N)timedcm_nestedrr logrrr) whencefmt whenceargs timing_statss r$rr s OOqOOgo666L [ 0Z 0 0 0                     %ww);; 1 %ww);; 1s/BA BABAB2Ccfd}|S)zReport the execution time of a function call to stderr. During development, use as a decorator when you need to measure the cost of a function, e.g. as follows: @util.timed def foo(a, b, c): pass c&ttjj5}|i|}dddn #1swxYwYtj}|dd|jzdztjj|fz|S)Ns %s%s: %s  r)rrbytestrrcrr;rr})rr time_statsrr;rs r$r=ztimed..wrapper s X%dm44 5 5 +T4*6**F + + + + + + + + + + + + + + + z''!+ //     s =AAr)r>s` r$timedr s#      Nr&))mrm)kr%)gr)skbr%)smbrm)sgbr)brc |} tD]Q\}}||r7t t |dt | |zcSRt |S#t$r%tj td|zwxYw)zConvert a space specifier to a byte count. >>> sizetoint(b'30') 30 >>> sizetoint(b'2.2kb') 2252 >>> sizetoint(b'6M') 6291456 Nscouldn't parse size: %s) stripr _sizeunitsrrrrwrr rrK)rOrrPus r$ sizetointr s  AB 4 4DAqzz!}} 459c!ffW9..233333 41vv BBBq!;<|j||fdSrS)rr)rMr+hooks r$addz hooks.add s" FD>*****r&c|jdg}|jD]\}}||||S)Nc|dSr(r)rAs r$rz hooks.__call__.. s qtr&)rY)rsortr)rMrresultsr+rs r$__call__zhooks.__call__ sW ^^,,, K ( (LFD NN44; ' ' ' 'r&N)rcrdrerfrQrrr)r&r$rr sK,,+++r&r %-*s in %s %s:%dc#Kfdtjd| dz D| d}|r5td|D}|D]\}}||||fV||||fzVdSdS)aYields lines for a nicely formatted stacktrace. Skips the 'skip' last entries, then return the last 'depth' entries. Each file+linenumber is formatted according to fileline. Each line is formatted according to line. If line is None, it yields: length of longest filepath+line number, filepath+linenumber, function Not be used in production code but very convenient while developing. ctg|]4\}}}}tj||fztj|f5Sr))rsysbytes)rrlnr_textfilelines r$ z"getstackframes.. sV BD% X&r**B/ /1B41H1HIr&Nrc3@K|]}t|dVdSrNro)rentrys r$ z!getstackframes.. s,77eCaMM777777r&)rV extract_stackr)skiprLrrZentriesfnmaxfnlnrs ` r$getstackframesr s#,#:#<#<[uqy[#I fggG177w77777! 1 1JD$|dD)))))eT4000000 11 1 1r&s stacktracer&c|r||d||fzt|dz|D]}|||z|dS)aWWrites a message to f (stderr) with a nicely formatted stacktrace. Skips the 'skip' entries closest to the call, then show 'depth' entries. By default it will flush stdout first. It can be used everywhere and intentionally does not require an ui object. Not be used in production code but very convenient while developing. s %s%s at: r)rZN)r<rrstripr)r=rrotherfrZrrLs r$debugstacktracer( s GGMVSZZ\\2 2333taxu555  GGIIIIIr&c|t}d||fz}||vr||vr|StjdD]}d|||fz}||vr||vr|cSdS)a Generate a name that it is safe to rename f to in the given context. f: filename to rename tag: a string tag that will be included in the new name ctx: a context, in which the new name must not exist others: a set of other filenames that the new name must not be in Returns a file name of the form oldname~tag[~number] which does not exist in the provided context and is not in the set of other names. Ns%s~%srs%s~%s~%s)set itertoolsr)rtagctxothersrrs r$safenamer B s~ QH B }}6)) _Q   AsA; & S==Rv--IIIr&c||}t||kr3tjt dt||fz|S)z=read n bytes from stream.read and abort if less was availables5stream ended unexpectedly (got %d bytes, expected %d))rvrwr rJrK)streamrrOs r$ readexactlyrZ sY AA 1vvzzk F G G1vvqk     Hr&c<|dkrtjd|z|dz}|dz}g}|r6|tjd|z|dz}|dz}|6|tj|d|S)aiEncode an unsigned integer value to a varint. A varint is a variable length integer of 1 or more bytes. Each byte except the last has the most significant bit set. The lower 7 bits of each byte store the 2's complement representation, least significant group first. >>> uvarintencode(0) '\x00' >>> uvarintencode(1) '\x01' >>> uvarintencode(127) '\x7f' >>> uvarintencode(1337) '\xb9\n' >>> uvarintencode(65536) '\x80\x80\x04' >>> uvarintencode(-1) Traceback (most recent call last): ... ProgrammingError: negative value for uvarint: -1 rsnegative value for uvarint: %dr&)r rrrbytechrr)rr+bytess r$ uvarintencodere s. qyy$%F%NOOO 4>> try: ... from StringIO import StringIO as BytesIO ... except ImportError: ... from io import BytesIO >>> uvarintdecodestream(BytesIO(b'\x00')) 0 >>> uvarintdecodestream(BytesIO(b'\x01')) 1 >>> uvarintdecodestream(BytesIO(b'\x7f')) 127 >>> uvarintdecodestream(BytesIO(b'\xb9\n')) 1337 >>> uvarintdecodestream(BytesIO(b'\x80\x80\x04')) 65536 >>> uvarintdecodestream(BytesIO(b'\x80')) Traceback (most recent call last): ... Abort: stream ended unexpectedly (got 0 bytes, expected 1) rTrrrr)rr)rrrshiftbytes r$uvarintdecodestreamr s\0F E;r1%%&&4$;5((t  M   r&c#\Ktjtjd}|dkr tjtjdn#tj$rYnwxYwdVtjtj|dS#tjtj|wxYwdVdS)NCr/)locale setlocaleLC_CTYPEr)oldlocs r$ with_lc_ctyper" s  fot 4 4F }} 6  "5555<     EEE  V_f 5 5 5 5 5F V_f 5 5 5 5 s)A B ABAB!B%c tjdriddlmm ddlm}m}m }m }G fdd|}|}|||_ |j |||jS tjtjd}tjtjd}||zS#t$$rYd St&$rYd SwxYw) zProvide an estimate for the available system memory in Bytes. If no estimate can be provided on the platform, returns None. swinr)c_long c_ulonglong) Structurebyrefsizeofwindllc JeZdZdfdfdfdfdfdfdfdfd fg Zd S) '_estimatememory..MEMORYSTATUSEXdwLength dwMemoryLoad ullTotalPhys ullAvailPhysullTotalPageFileullAvailPageFileullTotalVirtualullAvailVirtualullExtendedVirtualN)rcrdre_fields_)DWORD DWORDLONGsr$MEMORYSTATUSEXr+ s^U#'++#Y/#Y/"I."I.%y1 HHHr&r8 SC_PAGE_SIZE SC_PHYS_PAGESN)r sysplatform startswithctypesr$r%ctypes.wintypesr&r'r(r)r,kernel32GlobalMemoryStatusExr/r sysconf sysconf_namesrrr) r&r'r(r)r8r)pagesizepagesr6r7s @@r$_estimatememoryrE si &&v..DDDDDDDD                    Y    N  VAYY ,,UU1XX666~  :b.~>?? 2+O<==%           s A C C3& C32C3)rrrSr^r)Nr)r%r&)FFFNNTr)FNF)FTr4)r~N)rrrr)rfrr contextlibrvr8hashlibior rrr picklererr{rr:timerVr6rr thirdpartyrrrrrr hgdemandimportr r/r r r rrutilsrrrr TYPE_CHECKINGtypingrrrr importmodrr b85decode b85encode cookielibhttplibrE socketserverBytesIObytesiostringio xmlrpclib httpserverurlerrurlreqrrrrr"rrKrXbindunixsocket cachestat checkexec checklinkr~ expandglobsgetfsmountpointrp get_password groupmembers groupnameisexecisownerrrE lookupregrWr rr normcasespecnormcasefallback openhardlinksrtparsepatchoutputrIpollrrzrArL samedevicesamefilesamestatsetflagsrr statisexec statislinkr!rousernamer% compengines SERVERROLE CLIENTROLErrr-renvironrr5filterwarningsr9r@md5sha1sha512rIr`rPrErir NameErrorrrrrrr-r)rFrOr8rbrr>rrr OrderedDictrrnrrrcontextmanagerrrrrrrr$r/r2r5r?rrRr\rsr|rrrrrcheckosfilenameclockrrrrrrrrrrrrrrJr"rmr8rOrTrQrYr_rdrhrjrrrr bytecountrrrrrr oslinesep tonativeeol fromnativeeolnativeeolwriteridentityrrrrrrOrrrrrrrrr;stdoutrrr rrrr"rEr)r&r$rs      #"""""   ( # #  ( # #        " $ *     $    # $%%%%%%%######F  (        " *   $ $      .           $ ,& ,  }              GFK); < <      )))%  #  #  &(( $x##$566 7 7 KHIr+={KKKHIr+=wGGGHIr+=zJJJ H, 2KH+-?H&      K ]~   322 A <<<<<--------`""""""""J. FF.......... kkkkkkkk\$o o o o o o o o d''''' 1'''T    x x x x x x x x v""""""""Jaaaaa*aaaJIM ) ) ) ) D D D D D &D D D V    %%%%0TJTJTJTJn   >($$$$${&$$$Nc46#x6 $ 0iiiiiiiiX    > ( ( ( ( ( ( ( (B4 ? ;D???8    (  M=M=M=M=`****Z0;;;| nd++ &O  .O  (      2[ JJJ DD DDD4 4 4 4 4 4 4 4 n SUU ***ZD&&&((((Vc!c!c!c!c!c!c!c!LCCCCCCCCL       <   PPPPPPPPf,$$$$$$$$N      . K'11Z==!!!J-- :'11Z==!!!J-- :'11Z==!!!J-- :11]     22222222( y ! !   """ ***   KM!OO#K%M'O888 ::::4 KQQy\\!QQy\\AAiLL11Y<<%:* qq}}(AAjMM"11Z==!!!J-- +qq}}%aa mm$ QQz]]#   ",,,,,,,,$ &8 BBB*&11114  o ?  .0   """JZ ", , , , , s$&M)) M54M5 TTT