$Jc*@s[dZddklZddkZddkZddkZddkZddkZddkZddk Z ddk Z ddk Z ddk Z ddk Z ddkZddkZddkZddkZddkZdadaddkZe idjZdZdZd ZdqZedrZd&Zd'Zd(efd)YZ d*Z!d+Z"he"d,<e!d-Z5d?Z6dd@Z7dAefdBYZ8dCZ9e:e dDo e i;Z<n dEZ<dddFZ=e idGjoddHk>Tn ddHk?TdIZ@dJZAdKZBdLZChZDdMZEdNZFdOZGdPZHdQZIdRZJdSZKeLddTZMdUefdVYZNddWZOdXefdYYZPdZefd[YZQd1dd\ZRd]ZSdd^d_ZTdd`ZUgdaZVdddbZWdcZXddZYdeZZdfdgZ[eLdeLdhZ\da]diZ^djZ_dkZ`dlZadmZbdnZcddoZddpZedS(ssMercurial utility functions and platform specfic implementations. This contains helper routines that are independent of the SCM core and hide platform-specific details from the core. i(t_NcCs t|S(N(t _fastsha1(ts((s./mercurial/util.pytsha1scCsNyddkl}Wn#tj oddkl}nX|aa||S(Ni(R(tsha(thashlibRt ImportErrorRR(Rt_sha1((s./mercurial/util.pyRs  tposixc CsCti|dtdddtdtidti}|i|ifS(Ntshelltbufsizeit close_fdststdintstdout(t subprocesstPopentTruetclosefdstPIPER R (tcmdtp((s./mercurial/util.pytpopen2)scCsRti|dtdddtdtidtidti}|i|i|ifS(NR R iR R R tstderr(RRRRRR R R(RR((s./mercurial/util.pytpopen31s  cCs5yddk}|iSWntj o dSnXdS(s(Return version information if available.iNtunknown(t __version__tversionR(R((s./mercurial/util.pyR8s   s%Y-%m-%d %H:%M:%Ss%Y-%m-%d %I:%M:%S%ps%Y-%m-%d %H:%Ms%Y-%m-%d %I:%M%ps%Y-%m-%ds%m-%ds%m/%ds%m/%d/%ys%m/%d/%Ys%a %b %d %H:%M:%S %Ys%a %b %d %I:%M:%S%p %Ys%a, %d %b %Y %H:%M:%Ss%b %d %H:%M:%S %Ys%b %d %I:%M:%S%p %Ys%b %d %H:%M:%Ss%b %d %I:%M:%S%ps %b %d %H:%Ms %b %d %I:%M%ps%b %d %Ys%b %ds%H:%M:%Ss %I:%M:%SPs%H:%Ms%I:%M%ps%Ys%Y-%ms%bs%b %YcsEhiidjofd}nfd}|S(s"cache the result of function callsics)|jo||}d||>}||jo |}n||jo |}qndi|Vd}g}qqW|odi|VndS(srreturn no less than min bytes per chunk while data remains, doubling min after each chunk until it reaches maxcSs@|pdSnd}x |o|dL}|d7}qW|dS(Nii((txti((s./mercurial/util.pytlog2s  iitN(R&R#tjoin(tsourcetmintmaxR`tbuftblentchunktnmin((s./mercurial/util.pytincreasingchunkss(        cCstS(N(R(RY((s./mercurial/util.pytalwaysscCstS(N(tFalse(RY((s./mercurial/util.pytneverscCs2|pt|Sntii|oitii|dtii|djotii|t|Sndit||f}nt||id}}|i |i x<|o4|o-|d|djo|i |i qW|i ti idgt ||pdS(sareturn 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. it/is..t.( t localpathRAtpathtisabst splitdriveRbtpconvertt splitpathtsplittreverseR$tsepR#(troottn1tn2tatb((s./mercurial/util.pytpathtos -  &  c Cs|tijo ti}n%t|o |}n|ti}|}tii|ptii|||}ntii|}t|}||jo8|i|o(|t |}||t |Sn||jodSnti |}g}xt oyti |}Wnt j oPnXt||oC|pdSn|itii|}||t |Sntii|\} } |i| | |joPn| }qWtd|dS(s7return the canonical path of myname, given cwd and rootRas%s not under rootN(RARxt endswithsepRqRrRbtnormpatht path_auditorRWR#RttstatRtOSErrortsamestatRwRvR&RI( RytcwdtmynametrootsepR+t audit_pathtroot_sttreltname_sttdirnametbasename((s./mercurial/util.pyt canonpath sH             cCs-ttdpttdp tidS(sreturn True if we are a frozen executable. The code supports py2exe (most common, Windows only) and tools/freeze (portable, not much used). tfrozent importerst__main__(thasattrRGtimpt is_frozen(((s./mercurial/util.pytmain_is_frozen>scCsntdjo]tiid}|ot|qjtottiqjtt dpdntS(s]return location of the 'hg' executable. Defaults to $HG or 'hg' in the search path. tHGthgN( t _hgexecutableR4RAtenvirontgettset_hgexecutableRRGt executabletfind_exe(R((s./mercurial/util.pyt hgexecutableHs  cCs |adS(s#set location of the 'hg' executableN(R(Rq((s./mercurial/util.pyRWsc Cs0d}h}x$|D]}tii|||tj o2}|itititi fjoqnXt i |i o t td|fnVt i|i oBtiitii|do t td|fndS(Ns"path %r traverses symbolic link %rs.hgspath %r is inside repo %r(RARqRbRyRRRtENOENTtENOTDIRtEINVALRtS_ISLNKtst_modeRIRtS_ISDIRR(R9tcurpathtstR(R,Rq(s./mercurial/util.pyRs"  " (s.hgs.hg.Ra(s.hgs.hg.(RRARqtnormcaseRuRstlowertpardirRIRtindexRbR$RxRR&taddtupdate( R,RqRtpartst_[1]RtlpartstpostbaseRtprefixesR9((R,Rqs./mercurial/util.pyt__call__s8 '(    (R*R3t__doc__R-R(((s./mercurial/util.pyRs cCsti|iS(s.Return number of hardlinks for the given file.(RARtst_nlink(tpathname((s./mercurial/util.pytnlinks0stlinkcCstdtddS(NisHardlinks not supported(RR(RR((s./mercurial/util.pyR7scCsdS(N(R4(tkeyR+tscope((s./mercurial/util.pyt lookup_reg:sR(t*cCsyti||SWnAtj o#}|itijoqXntj onXti|titiBti B}ti ||ti |dS(N( RARRRRRRKtO_CREATtO_WRONLYtO_EXCLRCRD(tinfoRtwhytld((s./mercurial/util.pytmakelockBs #cCsnyti|SWnJtj o,}|ititifjoq^ntj onXt|iS(N( RARRRRtENOSYSRt posixfileRL(RR((s./mercurial/util.pytreadlockOs cCsAyti|iSWn#tj oti|iSnXdS(s1stat file object that may not have fileno method.N(RAtfstattfilenoRRR+(RQ((s./mercurial/util.pyR YscCsti|}tii|\}}tii||i}||jotii||i}ny,ti|}||jotSntSWn tSnXdS(s Check whether the given path is on a case-sensitive filesystem Requires a path (like /foo/.hg) ending with a foldable final directory component. N( RARRqRvRbtupperRRlR(Rqts1tdR}tp2ts2((s./mercurial/util.pyt checkcasebs  c Cs|ii|ioPt|}||tijp||tijo|d}n||}ntiitii||pdSnti}tio|ti}n|i ddt i d||f}tii tii|}g}x|i|D]\}}|o|i|qn|tjoti|t| ("          c CsytitiBtiB}tidd|\}}zati|ti|id@}||@}ti |||Ati|id@|j}Wdti |XWnt t fj o t SnX|p| S(s} Check whether the given path is on a filesystem with UNIX-like exec flags Requires a directory (like /foo/.hg) RaiN(RtS_IXUSRtS_IXGRPtS_IXOTHR?R@RARDRtchmodRMRRRl(Rqt EXECFLAGStfhRYtmtnew_file_has_exectexec_flags_cannot_flip((s./mercurial/util.pyt checkexecs     cCs[tid|}y%tid|ti|tSWnttfj o tSnXdS(s?check whether the given path is on a symlink-capable filesystemRRoN( R?tmktempRARRMRRRRl(RqR+((s./mercurial/util.pyt checklinks cCs tidjS(sCreturn True if patches should be applied in binary mode by default.R(RAR+(((s./mercurial/util.pytneedbinarypatchscCs-|itiptio|itiS(s)Check path ends with os.sep or os.altsep.(tendswithRARxR(Rq((s./mercurial/util.pyRscCs|itiS(sSplit 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.(RvRARx(Rq((s./mercurial/util.pyRuscCs0tidjp tidjptiidS(sAre we running in a GUI?RtmactDISPLAY(RAR+RR(((s./mercurial/util.pytguisc Cstii|\}}tidd|d|\}}ti|yti|id@}WnWtj oK}|i t i jon|}|d jo t }n|dM}nXti |||o|Snyyt|d} WnStj oG}|i t i jo|Snt|dd p ||_nnXt|d} x!t| D]} | i| qbW| i| iWn%yti|WnnXnX|S( sCreate 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. R9s.%s-RiiR>RR:N(RARqRvR?R@RDRRRRRR4tumaskR&R RtgetattrRt filechunkiterRCRM( R+temptyokt createmodeRRYtfdRRRtifptofpRh((s./mercurial/util.pyt mktempcopysF "      tatomictempfilecBs2eZdZdZdZdZdZRS(sfile-like object that atomically updates a file All writes will be redirected to a temporary copy of the original file. When rename is called, the copy is renamed to the original name, making the changes visible. cCsL||_d|_t|dd|jd||_t|i||_dS(NR7twR8(t_atomictempfile__nameR4t_fpR<RR (R,R+tmodeR8((s./mercurial/util.pyR-s    cCst|i|S(N(R5R@(R,R+((s./mercurial/util.pyt __getattr__scCs;|iip*|iit|it|indS(N(R@tclosedRDRRRpR?(R,((s./mercurial/util.pyR!s  cCsR|ipdSn|iip/yti|iWnnX|iindS(N(R@RCRARMRRD(R,((s./mercurial/util.pyt__del__&s  (R*R3RR-RBRRD(((s./mercurial/util.pyR=s    cCsy6ti||dj oti||ndSWnJtj o>}|itijodSn|itijoqnXtii tii |}t ||t ||dS(s9recursive directory creation with parent mode inheritanceN( RARR4R&RRRRRqtabspathRtmakedirs(R+RARtparent((s./mercurial/util.pyRF/s    topenercBsMeZdZedZedZdZdeedZ dZ RS(sOpen files relative to a base directory This class is used to hide the details of COW semantics and remote file access from higher level code. cCs9||_|ot||_n t|_d|_dS(N(RRRRkR4R8(R,Rtaudit((s./mercurial/util.pyR-Es   cCs t|iS(N(R.R(R,((s./mercurial/util.pyt _can_symlinkMscCs3|idjodSnti||id@dS(Ni(R8R4RAR&(R,R+((s./mercurial/util.pyt _fixfilemodeQstrc Cs7|i|tii|i|}| od|jo|d7}nd}|djoyt|}WnRtj oFd}tii|}tii|pt ||i qnX|ot |||i Sn|djot t ||qnt||}|djo|i|n|S(NR}iRLR>ii(RLsrb(RRARqRbRRRRRRFR8R=RR<R RK( R,RqRAttextt atomictempRtnlinkRRQ((s./mercurial/util.pyRVs*    c Cs|i|tii|i|}yti|Wntj onXtii|}tii|pt ||i n|i oXyti ||Wqtj o1}t|i td||if|qXn4||d}|i||i|i|dS(Nscould not symlink to %r: %sR>(RRARqRbRRMRRRRFR8RJRRRtstrerrorRCRDRK(R,RRtlinknameRRR((s./mercurial/util.pyRos&    ( R*R3RRR-R)RJRKRlRR(((s./mercurial/util.pyRH?s   t chunkbuffercBs eZdZdZdZRS(soAllow arbitrary sized chunks of data to be efficiently read from an iterator over chunks of arbitrary size.cCs%t||_d|_d|_dS(szin_iter is the iterator that's iterating over the input chunks. targetsize is how big a buffer to try to maintain.RaiiNi(titerRft targetsize(R,tin_iter((s./mercurial/util.pyR-s cCs'|t|ijo|iot||i}ti}|i|it|i}x@|iD]5}|i||t|7}||joPqgqgW||jo t|_n|i |_nt|i|jot |id}|_n$|i| t |i|}|_|S(suRead L bytes of data from the iterator of chunks of data. Returns less than L bytes if the iterator runs dry.Ra( R#RfRSReRTt cStringIOtStringIORCRltgetvalueRtbuffer(R,RRTt collectort collectedRhR((s./mercurial/util.pyRLs$        #(R*R3RR-RL(((s./mercurial/util.pyRRs ccs|djpt|djp|djptxttol|djo |}nt||}|o |i|}|pPn|o|t|8}n|Vq8WdS(sXCreate a generator that produces the data in the file size (default 65536) 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.iN(tAssertionErrorR4RRdRLR#(RtsizetlimittnbytesR((s./mercurial/util.pyR6s!  cCsPti}|ddjotio ti}n ti}ti||fS(Nii(ttimet localtimetdaylighttaltzonettimezonetmktime(tltttz((s./mercurial/util.pytmakedates    s%a %b %d %H:%M:%S %Y %1%2cCs|pt\}}d|jp d|joh|djodpd}t|d}|idd||df}|idd|d}nti|tit||}|S( srepresent a (unixtime, offset) tuple as a localized time. unixtime is seconds since the epoch, and offset is the time zone's number of seconds away from UTC. if timezone is false, do not append time zone to string.s%1s%2it-t+i<s%c%02ds%02d(RhtabsRER`tstrftimetgmtimetfloat(tdatetformatttRgtsigntminutesR((s./mercurial/util.pytdatestrs %cCst|ddS(s1turn (timestamp, tzoff) tuple into iso 8631 date.Rps%Y-%m-%d(Rt(Ro((s./mercurial/util.pyt shortdatesc Cs'd}|||}}|djodi|id }nxs|D]k}g}|D]"}d||jo |tq^q^~} | p(|d||7}|d|d7}qMqMWti||} tti| } |djo#tti | } | | }n | |} | |fS( s~parse a localized time string and return a (unixtime, offset) tuple. if the string cannot be parsed, ValueError is raised.cSs|id}|ddjot|djon|dio]|ddjodpd}t|dd!}t|dd!}| |d|dSn|d jp |d jodSndS( Niis+-iiRjii<tGMTtUTC(RvR#tisdigittintR4(tstringRgRrthoursRs((s./mercurial/util.pyRds5t it%t@s@%iN( R4RbRvRR`tstrptimeRytcalendarttimegmRe( RzRptdefaultsRdtoffsetRoRRRtfoundt timetuplet localunixtimetunixtime((s./mercurial/util.pytstrdates"  6  c Cs|pdSnt|tot|djo|Sn|p t}n|i}y"tt|id\}}Wntj o|p h}nt }x_diD]Q}||jo>|ddjod||{date}' on or after a given date cSs)tdddd}t|t|dS(NtmbRRi(tdictRtextendeddateformats(RoR((s./mercurial/util.pyR3sc Sstdddddddd}x@diD]2}y"||d Est>cs |jS(((R^(R(s./mercurial/util.pyRHsRisinvalid day spec: %siics |jS(((R^(R(s./mercurial/util.pyROss to cs|jo |jS(((R^(tstoptstart(s./mercurial/util.pyRSscs|jo |jS(((R^(RR(s./mercurial/util.pyRVsN(RRyRRIRRhRv(RoRRRR|R}((RRRs./mercurial/util.pyt matchdate&s,   cCs|id}|djo|| }n|id}|djo||d}n|id}|djo|| }n|id}|djo|| }n|S(s>Return a short representation of a user name or email address.R~iRiR|Ro(tfind(tuserR((s./mercurial/util.pyt shortuserXs    cCs>|id}|djo d}n||idd|!S(sget email of author.RiRiN(RR4(tauthorRL((s./mercurial/util.pytemailhsicCs/t||jo|Snd||d SdS(s;Trim string to at most maxlength (default: 400) characters.s%s...iN(R#(RMt maxlength((s./mercurial/util.pytellipsisnsc#sfd}|o ttido d}nt}|djo|og}||nx<tidtd|D]\}}}d|jok|Vtii|dd} tiitii| do | Vn|o|i dqg|(q|og} x}|D]u} tii|| } ||| oJtii | o&x0t | t|D] } | VqoWq| i | qqW| |(qqWdS( s2yield every hg repository under path, recursively.cs|ijo |ndS(N(R(R(Rq(s./mercurial/util.pyt errhandlerwsRcSsjt}tii}ti|}x)|D]!}|||o t}Pq(q(W|p|i|n| S(N(RlRARqRRRR&(tdirlstRtmatchRtdirstatt lstdirstat((s./mercurial/util.pyt_add_dir_if_not_there{s  ttopdowntonerrors.hgtpatchesN( RRARqRlR4twalkRRbRR%Rt walkreposR&(Rqt followsymt seen_dirstrecurseRRRytdirstfilestqroottnewdirsRtfnamethgname((Rqs./mercurial/util.pyRus:  "   cCsJt}|itg}|D]}|tii|q$~}|S(s+return default os-specific hgrc search path(t system_rcpathtextendt user_rcpathRARqR(RqRR((s./mercurial/util.pyt os_rcpaths -cCstdjodtijogaxtiditiD]}|pq=ntii|oTx^ti |D]<\}}|i do ti tii ||qtqtWq=ti |q=Wqt antS(sreturn hgrc search path. if env var HGRCPATH is set, use it. for each item in path, if directory, use files ending in .rc, else use item. make HGRCPATH empty to only look in .hg/hgrc of current repo. if no HGRCPATH, use default os-specific path.tHGRCPATHs.rcN(t_rcpathR4RARRvtpathsepRqRRRR0R&RbR(RRR((s./mercurial/util.pytrcpaths  ( c Cs ddtdfddtdfddtdfddtd fddtd fddtd fddtd fddtd fddtdfddtdff }x>|D]6\}}}|||jo||t|SqqW|dd|S(s:return byte count formatted as readable string, with unitsidiis%.0f GBi s%.1f GBs%.2f GBis%.0f MBs%.1f MBs%.2f MBs%.0f KBs%.1f KBs%.2f KBs %.0f bytesiii@i@i@iiiiii(RRn(R_tunitst multipliertdivisorRp((s./mercurial/util.pyt bytecountscCsP|d}|i|o2|t|}|ido|d}qLn|S(Nt:s//i(RWR#(tschemeRqtsc((s./mercurial/util.pyt drop_schemes  cCst|iddS(Ns\\s\(treprRE(R((s./mercurial/util.pytuireprscCs$dtijo/yttidSWq?tj oq?Xnyddk}ddk}ddk}xtiti fD]}ypy|i }Wnt j o wynXti |pwyn|i ||id}|id|dSWqytj oqyXqyWWntj onXdS( NtCOLUMNSiR[ithiiPt(RARRyRttermiostarraytfcntlRGR R RRtisattytioctlt TIOCGWINSZR(RRRtdevR9tarri((s./mercurial/util.pyt termwidths. $ cCsL|djotd}ndd|}|iti|d||S(Nis R|twidth(R4RRbttextwraptwrap(tlinet hangindentRtpadding((s./mercurial/util.pyRs ccs1x*|D]"}x|iD] }|VqWqWdS(N(t splitlines(titeratorRhR((s./mercurial/util.pyt iterliness  (s%Y-%m-%d %H:%M:%Ss%Y-%m-%d %I:%M:%S%ps%Y-%m-%d %H:%Ms%Y-%m-%d %I:%M%ps%Y-%m-%ds%m-%ds%m/%ds%m/%d/%ys%m/%d/%Ys%a %b %d %H:%M:%S %Ys%a %b %d %I:%M:%S%p %Ys%a, %d %b %Y %H:%M:%Ss%b %d %H:%M:%S %Ys%b %d %I:%M:%S%p %Ys%b %d %H:%M:%Ss%b %d %I:%M:%S%ps %b %d %H:%Ms %b %d %I:%M%ps%b %d %Ys%b %ds%H:%M:%Ss %I:%M:%SPs%H:%Ms%I:%M%p(s%Ys%Y-%ms%bs%b %Y(fRti18nRRRRVRRRRGR?RRARR`RRRRRRRR+RRRRRRR"R(tobjectR)R8RTRURZR]RjRIRkRmR~RR4RRRRRFRRRRMRRRRRRRRtwindowsRR R R RRR"R,R.R/RRuR3RlR<R=RFRHRRR6RhRtRuRRRRRRRRRRRRRRRR(((s./mercurial/util.pyssTH                   1  2    ?      .     0 H"   $. 2   .