^c0`ddlZddlZddlZddlZddlZddlmZddlmZm Z m Z m Z m Z e j r ddlmZmZmZmZe jddZe jdZd ZGd d Zdd Zd ZdZGddZe jedrejZeeZejZejZdS)N)_)encodingerrorpolicypycompatutil)AnyCallableIteratorOptionaldirstateDirsparserscNtj|SN)rhfsignorecleanlower)ss 4/usr/lib/python3/dist-packages/mercurial/pathutil.py _lowercleanrs  "17799 - --cNeZdZdZd dZd dZdZdZej d Z dS) pathauditora^ensure that a filesystem path contains no banned components. the following properties of a path are checked: - ends with a directory separator - under top-level .hg - starts at the root of a windows drive - contains ".." More check are also done about the file system states: - traverses a symlink (e.g. a/symlink_here/b) - inside a nested repository (a callback can be used to approve some nested repositories, e.g., subrepositories) The file system checks are only done when 'realfs' is set to True (the default). They should be disable then we are auditing path for operation on stored history. If 'cached' is set to True, audited paths and sub-directories are cached. Be careful to not keep the cache of unmanaged directories for long because audited paths may be replaced with symlinks. NTFc&t|_t|_||_||_||_||_tj |r'tj |stj |_ dSd|_ dS)Nc|Sr)xs rz&pathauditor.__init__..Csar) setaudited auditeddirroot_realfs_cachedcallbackospathlexistsr fscasesensitivenormcase)selfr#r&realfscacheds r__init__zpathauditor.__init__9svuu %%     7??4  ()=d)C)C ( MDMMM'KDMMMrcftj|}||}||jvrdStj|r$t jtd|ztj|}tj |ds%t|ddvstj|vr$t jtd|z|D]m}d|vrg|dd\}}|r:|dvr$t jtd|znd t|vrd |D}d D]v}||ddvrh||} tj j|d| } t jtd |tj| fzwtj|} t+|t+| ksJ|| t/t+|D]} tj|d| dz} tj| d| dz}||jvr`|jr|| ||jr|j||jr|j|dSdS) zPCheck the relative path. path may contain a pattern (e.g. foodir/**.txt)Ns$path ends in directory separator: %sr).hg.hg.rs#path contains illegal component: %s~r)sHGsHG8B6Cr1c,g|]}t|Sr)r).0ps r z(pathauditor.__call__..es444k!nn444r)r1r2"path '%s' is inside nested repo %r)r localpathr+r! endswithsepr InputErrorr splitpathr'r( splitdriverrospardirsplitisdigitupperindexjoinbytestrlenpoprangeossepr"r$_checkfsr%add)r,r(modenormpathpartsr6firstlastlpartsposbase normpartsiprefix normprefixs r__call__zpathauditor.__call__Es8 ~d##==&& t| # # F  D ! ! "9::TA t$$ G  t $ $Q ' 58$$(>>> E))"899D@   AqyyggdA.. t<<>>ekkmm7I&I&I*@AADH [&& & &44e444F$  qrr ?? ,,q//C7<tt5D*?@@!1$!7!789#N8,, 5zzS^^++++   s5zz"" 0 0A^((wQw88F!,,YwQw-?@@JT_,,| , fd+++| 0##J/// < ' L  X & & & & & ' 'rc*tj|j|} tj|}t j|jrLtdtj |tj |fz}tj |t j |jrtjtj|drX|jr||s>td}tj ||tj |fzdSdSdS#t $r6}|jt"jt"jt"jfvrYd}~dSd}~wwxYw)z3raise exception if a file system backed check failss"path %r traverses symbolic link %rr1r8N)r'r(rCr#lstatstatS_ISLNKst_moderrrDrAbortS_ISDIRisdirr&OSErrorerrnoENOENTENOTDIREINVAL)r,rUr(curpathstmsgerrs rrIzpathauditor._checkfss',,ty&11 N'""B|BJ'' N=>>$T**$V,,Bk#&&&bj)) Nbgmm Wf--// N}NDMM',B,BNABBC+cT83CF3K3K,L&LMMM  N N N NNN   yu}el KKKLKKKKK sE F+F  FcX ||dS#ttjf$rYdSwxYwNTF)r`rr])r,r(s rcheckzpathauditor.checksB  DJJJ4%   55 s ))c#*K|jrdVdS d|_dV|j|jd|_dS#|j|jd|_wxYwrj)r%r!clearr"r,s rr.zpathauditor.cacheds < % EEEEE %#  ""$$$%%'''$  ""$$$%%'''$ $$$$s A;Brjr) __name__ __module__ __qualname____doc__r/rWrIrk contextlibcontextmanagerr.rrrrr"s, ( ( ( (?'?'?'?'BNNN2 % % % % %rrctj|r|}n|tjz}|}tj|s!tj|||}tj|}|t|}||krK| |r6|t|d}||tj |S||krdSg} tj ||}n#t$rd}YnwxYw|rJ|sdS|t jj|}||tj |Stj|\}} || ||krn|}d} ||krct%||||tj||d} | tjr | dd} t+d| z} n#t,j$rYnwxYwt-jt+d||fz| ) areturn the canonical path of myname, given cwd and root >>> def check(root, cwd, myname): ... a = pathauditor(root, realfs=False) ... try: ... return canonpath(root, cwd, myname, a) ... except error.Abort: ... return 'aborted' >>> def unixonly(root, cwd, myname, expected='aborted'): ... if pycompat.iswindows: ... return expected ... return check(root, cwd, myname) >>> def winonly(root, cwd, myname, expected='aborted'): ... if not pycompat.iswindows: ... return expected ... return check(root, cwd, myname) >>> winonly(b'd:\\repo', b'c:\\dir', b'filename') 'aborted' >>> winonly(b'c:\\repo', b'c:\\dir', b'filename') 'aborted' >>> winonly(b'c:\\repo', b'c:\\', b'filename') 'aborted' >>> winonly(b'c:\\repo', b'c:\\', b'repo\\filename', ... b'filename') 'filename' >>> winonly(b'c:\\repo', b'c:\\repo', b'filename', b'filename') 'filename' >>> winonly(b'c:\\repo', b'c:\\repo\\subdir', b'filename', ... b'subdir/filename') 'subdir/filename' >>> unixonly(b'/repo', b'/dir', b'filename') 'aborted' >>> unixonly(b'/repo', b'/', b'filename') 'aborted' >>> unixonly(b'/repo', b'/', b'repo/filename', b'filename') 'filename' >>> unixonly(b'/repo', b'/repo', b'filename', b'filename') 'filename' >>> unixonly(b'/repo', b'/repo/subdir', b'filename', b'subdir/filename') 'subdir/filename' NrTFsconsider using '--cwd %s's%s not under root '%s')hint)r r:rrHr'r(isabsrCrLr startswithrEpconvertsamefiler`reverser?append canonpathpathtoendswithrrr]) r#cwdmynameauditorrootsepnamerelrdirnamebasenamerwrelpaths rr~r~svV (' D 7==  -w||D#t,, 7  D ! !Dd## w4??733CLLNN# }T""" s  M$--     +3 w|S) }T*** $ 4 0 0 GX JJx $D# * d{{$fg666+dC55##HN33+%crclG566@{    D k ' ( (FD> 9    s%6D DD#A)H HHctj|\}}t|ttjkr|tjzS|S)anormalize the specified path as path prefix Returned value can be used safely for "p.startswith(prefix)", "p[len(prefix):]", and so on. For efficiency, this expects "path" argument to be already normalized by "os.path.normpath", "os.path.realpath", and so on. See also issue3033 for detail about need of this function. >>> normasprefix(b'/foo/bar').replace(pycompat.ossep, b'/') '/foo/bar/' >>> normasprefix(b'/').replace(pycompat.ossep, b'/') '/' )r'r(r=rErrH)r(dr6s r normasprefixrsJ" 7  d # #DAq 1vvX^$$$$hn$$ rc#K|d}|dkr)|d|V|dd|}|dk)dVdS)N/rvrr)rfind)r(rQs rfinddirsr4sc **T  C ))4C4jjjq#&& )) IIIIIrc2eZdZdZd dZdZdZdZdZdS) dirsz6a multiset of directory names from a set of file pathsFci|_|j}t|tr4|r2|D]\}}|jdkr ||dS|rd}t j||D] }||dS)zS a dict map indicates a dirstate while a list indicates a manifest rs3`only_tracked` is only supported with a dict sourceN)_dirsaddpath isinstancedictitemsstaterProgrammingError)r,map only_trackedrfrrgs rr/z dirs.__init__@s , c4 \    17d??GAJJJ   HC(-- -     rc|j}t|D]E}|drtd|z||vr||xxdz cc<dSd||<FdS)Nrz-found invalid consecutive slashes in path: %rr)rrr ValueErrorr,r(rrRs rrz dirs.addpathQszTNN  D}}T""  CdJt||T a DJJ  rc||j}t|D]$}||dkr||xxdzcc<dS||=%dS)Nr)rrrs rdelpathz dirs.delpath^sZzTNN  DDzA~~T a T   rc*t|jSr)iterrrns r__iter__z dirs.__iter__gsDJrc||jvSr)r)r,rs r __contains__zdirs.__contains__jsDJrN)F) rorprqrrr/rrrrrrrrr=sj@@"      rrr) rsrar' posixpathrZi18nrrrrrr TYPE_CHECKINGtypingr r r r importrustrustdirs importmodrrrr~rrr safehasattrrCrrrrrs    6 Z 0 0 & 9 % %... P%P%P%P%P%P%P%P%fd d d d N0////////d4GV$$