Ë ë.«G'Aãó„—ddlZddlZddlZddlZddlZddlmZmZmZm Z ddl m Z ddl m Z mZmZmZmZej$dd«Zej(d«Zd „ZGd „d «Zdd „Zd „Zd„Zdedeefd„ZGd„d«Zej<ed«r ej:Ze�eZej>Zej@Z y)éN)ÚAnyÚCallableÚIteratorÚOptionalé)Ú_)ÚencodingÚerrorÚpolicyÚpycompatÚutilÚdirstateÚDirsÚparserscóH—tj|j««S©N)r ÚhfsignorecleanÚlower)Úss ú6usr/lib/python3.12/site-packages/mercurial/pathutil.pyÚ _lowercleanrs€ä × "Ñ " 1§7¡7£9Ó -Ð-óc ó~—eZdZdZd d„Zd d„Ze d dededee ege ffd„«Z d „Z e jd „«Zy) Ú 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. Ncó—t«|_t«|_||_||_||_||_tjj|«r+tj|«stj|_ yd„|_ y)Ncó—|Sr©)Úxs rÚz&pathauditor.__init__..As€¡ar)ÚsetÚauditedÚdictÚ auditeddirÚrootÚ_realfsÚ_cachedÚcallbackÚosÚpathÚlexistsr ÚfscasesensitiveÚnormcase)Úselfr$r'ÚrealfsÚcacheds rÚ__init__zpathauditor.__init__7s_€Ü“uˆŒ Ü›&ˆŒØˆŒ ؈Œ ؈Œ Ø ˆŒ Ü �7‰7�?‰?˜4Ô ¬×)=Ñ)=¸dÔ)CÜ ŸM™MˆD�Má'ˆD�Mrcó—tj|«}||jvrytj|«r!t j t d«|z«‚tj|«}tjj|«ds"t|d«dvstj|vr!t j t d«|z«‚d|vre|D]`}d|vsŒ|jdd«\}}|j«sŒ.|j!«dvsŒAt j t d«|z«‚d t|«vrŒ|D�cgc] }t|«‘Œ}}d D]o}||ddvsŒ |j#|«}tjj$|d|Ž} t j t d «|tj&| «fz«‚|j(ryt+|«D]k} | |j,vr|j,| } nGt.j1|j2| ||j4«} |j6r| |j,| <| rŒkn|j6r|jj9|«yycc}w) 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)sHGsHG8B6Cr2)r2r3ó"path '%s' is inside nested repo %r)r Ú localpathr!Ú endswithsepr Ú InputErrorrÚ splitpathr(r)Ú splitdriverr ÚospardirÚsplitÚisdigitÚupperÚindexÚjoinÚbytestrr%Úfinddirs_rev_norootr#rÚ_checkfs_existsr$r'r&Úadd) r-r)ÚmodeÚpartsÚpÚfirstÚlastÚlpartsÚposÚbaseÚprefixÚress rÚ__call__zpathauditor.__call__CsL€ô �~‰~˜dÓ#ˆØ �4—<‘<Ñ Ø ä × Ñ ˜DÔ !Ü×"Ñ"ÜÐ9Ó:¸TÑAóð ô—‘˜tÓ$ˆä �G‰G× Ñ ˜tÓ $ QÒ 'ܘ5 ™8Ó$Ð(>Ñ>Ü× Ñ  EÑ)ä×"Ñ"ÜÐ8Ó9¸DÑ@óð ð �4‰<Û�ؘ1’9Ø"#§'¡'¨$°Ó"2‘K�E˜4Ø—|‘|•~¨%¯+©+«-Ð;MÒ*MÜ#×.Ñ.ÜÐDÓEÈÑLóðð ð ”[ Ó&Ñ &Ù.3Ó4©e¨”k !•n¨eˆFÐ4Û$�ؘ˜q˜r˜ ’?Ø Ÿ,™, q›/�CÜŸ7™7Ÿ<™<¨¨t°¨Ð5�DÜ×*Ñ*ÜÐ?Ó@ؤ×!1Ñ!1°$Ó!7Ð8ñ9óðð %ð �<Š<ô .¨dÖ3�ؘTŸ_™_Ñ,ØŸ/™/¨&Ñ1‘Cä%×5Ñ5ØŸ ™  6¨4°·±ó�Cð—|’|Ø25˜Ÿ™¨Ñ/ÚÙð4ð �<Š<Ø �L‰L× Ñ ˜TÕ "ð ùò95sÅJrMr)r'cóh—tjj||«} tj|«}t j |j «rKtd«tj|«tj|«fz}tj|«‚t j|j «rtjjtjj|d««rB|r||«s8td«}tj||tj|«fz«‚y#t$rh}|jtj k(rYd}~y|jtj tj"tj$fvr‚Yd}~yd}~wwxYw)zraise exception if a file system backed check fails. Return a bool that indicates that the directory (or file) exists.s"path %r traverses symbolic link %rr2r5NFT)r(r)r@ÚlstatÚstatÚS_ISLNKÚst_moderr rAr ÚAbortÚS_ISDIRÚisdirÚOSErrorÚerrnoÚENOENTÚENOTDIRÚEINVAL)r$rMr)r'ÚcurpathÚstÚmsgÚerrs rrCzpathauditor._checkfs_exists‚sD€ô—'‘'—,‘,˜t VÓ,ˆð NÜ—‘˜'Ó"ˆBô�|‰|˜BŸJ™JÔ'ÜÐ=Ó>Ü×$Ñ$ TÓ*Ü×$Ñ$ VÓ,ðBñ�ô—k‘k #Ó&Ð&Ü—‘˜bŸj™jÔ)¬b¯g©g¯m©mÜ—‘— ‘ ˜W fÓ-ô/ñ ¡x°Ô'8ÜÐAÓB�CÜŸ+™+ c¨T´8×3CÑ3CÀFÓ3KÐ,LÑ&LÓMÐMØøô)ò Ø�y‰yœEŸL™LÒ(Üð�y‰y¤§¡¬u¯}©}¼e¿l¹lÐ KÑKØóLðûð) ús¢EÅ F1Å F,Å+>> 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' NrFéÿÿÿÿsconsider using '--cwd %s's%s not under root '%s')Úhint)r r7r Úossepr(r)Úisabsr@ÚnormpathrÚ startswithÚlenÚpconvertÚsamefilerXÚreverser<ÚappendÚ canonpathÚpathtoÚendswithrr rU) r$ÚcwdÚmynameÚauditorÚrootsepÚnameÚrelrÚdirnameÚbasenamerrÚrelpaths rr|r|»sø€ôV ×Ñ˜ÔØ‰àœŸ™Ñ'ˆØ €DÜ �7‰7�=‰=˜Ô Ü�w‰w�|‰|˜D # tÓ,ˆÜ �7‰7× Ñ ˜DÓ !€D؀ܘdÓ#ˆØ ˆw‚˜4Ÿ?™?¨7Ô3Ø”C˜“L�NÐ#ˆÙ�Œ Ü�}‰}˜TÓ"Ð"Ø �ŠØðˆØð Ü—M‘M $¨Ó-�ñÙàØ— ‘ ” Ü—w‘w—|‘| SÐ)�Ù˜” Ü—}‘} TÓ*Ð*Ü $§ ¡ ¨4Ó 0Ñ ˆG�XØ �J‰J�xÔ Ø˜$ŠØØˆDð#ð*ˆð Ø�dŠ{ܘ$  f¨gÔ6ÜŸ+™+ d¨C°Ó5�Ø×#Ñ#¤H§N¡NÔ3Ø% c r˜l�GÜÐ5Ó6¸Ñ@�ô�k‰kÜ Ð'Ó (¨F°D¨>Ñ 9Àô ð øô;ò Ø“ð ûô4�{‰{ò Ù ð ús%Ã%G?Å>AHÇ? HÈ HÈH'È&H'cóº—tjj|«\}}t|«ttj «k7r|tj zS|S)aìnormalize 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:rwr rs)r)ÚdrGs rÚ normasprefixrŠ"sE€ô" �7‰7× Ñ ˜dÓ #�D€A€qÜ ˆ1ƒv””X—^‘^Ó$Ò$Ø”h—n‘nÑ$Ð$àˆ rc#ó€K—|jd«}|dk7r |d|–—|jdd|«}|dk7rŒ d–—y­w)Nó/rqrr)Úrfind©r)rKs rÚfinddirsr�:sIèø€à �*‰*�TÓ €CØ �Š)Ø�4�CˆjÒØ�j‰j˜˜q #Ó&ˆð �‹)ð ƒIùs‚6>¹>r)Úreturnc#ó¶K—|jtj«}|dk7r1|d|–—|jtj|dz«}|dk7rŒ0yy­w)Nrqr)Úfindr rsrŽs rrBrBCsLèø€Ø �)‰)”H—N‘NÓ #€CØ �Š)Ø�4�CˆjÒØ�i‰iœŸ™¨¨a©Ó0ˆð ��)ùs ‚AAÁAcó0—eZdZdZdd„Zd„Zd„Zd„Zd„Zy) Údirsz6a multiset of directory names from a set of file pathscó—i|_|j}t|t«r3|r1|j «D]\}}|j dk7sŒ||«Œy|rd}t j|«‚|D] }||«Œ y)zS a dict map indicates a dirstate while a list indicates a manifest órs3`only_tracked` is only supported with a dict sourceN)Ú_dirsÚaddpathÚ isinstancer"ÚitemsÚstater ÚProgrammingError)r-ÚmapÚ only_trackedr˜Úfrr_s rr0z dirs.__init__Msr€ðˆŒ Ø—,‘,ˆÜ �cœ4Ô ¡\ØŸ ™ ž ‘��1Ø—7‘7˜d“?Ù˜A•Jñ$ñØHˆCÜ×(Ñ(¨Ó-Ð -ã�Ù˜• ñrcóª—|j}t|«D]9}|jd«rtd|z«‚||vr||xxdz cc<yd||<Œ;y)NrŒz-found invalid consecutive slashes in path: %rr)r—r�r~Ú ValueError©r-r)r”rLs rr˜z dirs.addpath^s\€à�z‰zˆÜ˜T–NˆDØ�}‰}˜TÔ"Ü ØCÀdÑJóðð�t‰|Ø�T“ ˜a‘“ ÙØˆD�ŠJñ#rcóp—|j}t|«D]}||dkDr||xxdzcc<y||=Œy)Nr)r—r�r¢s rÚdelpathz dirs.delpathks;€à�z‰zˆÜ˜T–NˆDØ�D‰z˜AŠ~Ø�T“ ˜a‘“ ÙØ�T‘ ñ #rcó,—t|j«Sr)Úiterr—rfs rÚ__iter__z dirs.__iter__ts€Ü�D—J‘JÓÐrcó—||jvSr)r—)r-r‰s rÚ __contains__zdirs.__contains__ws€à�D—J‘JˆÐrN)F) rgrhrirjr0r˜r¤r§r©rrrr”r”Js„Ù@óò" òò órr”r)!rnrYr(Ú posixpathrRÚtypingrrrrÚi18nrÚr r r r r Ú importrustÚrustdirsÚ importmodrrrr|rŠr�rlrBr”Ú safehasattrr@r…rrrÚr²sØðÛÛ Û ÛÛ ÷óõ÷õð ˆ6× Ñ ˜Z¨Ó 0€Ø ˆ&× Ñ ˜9Ó %€ò.÷ X%ñX%óvd òNò0ð1˜eð1¨°©ó1÷/ñ/ðd€4×Ñ�G˜VÔ$Ø �<‰<€Dà ÐØ €Dð ‡~�~€Ø × Ñ �r