^cddlZddlZddlZddlZddlZddlmZddlmZddl m Z m Z m Z m Z mZmZddlmZe jdZdZd ZejZd ZdBd Zd ZdZ dBdZ dCdZdDdZdDdZdDdZdZdEdZ GddZ!Gdde!Z"Gdde!Z#Gdde!Z$dZ%Gd d!e!Z&Gd"d#Z'Gd$d%e!Z(Gd&d'e!Z)Gd(d)e!Z*d*Z+Gd+d,e!Z,Gd-d.e!Z-Gd/d0e!Z.Gd1d2e!Z/dDd3Z0d4Z1d5Z2ej3d6Z4d7Z5d8Z6d9Z7d:Z8d;Z9d<Z:d=Z;d>Zda?dFdAZ@dS)GN)_)open)encodingerrorpathutilpolicypycompatutil) stringutildirstate) reglobpathrelglobrelpathrelrerootgloblistfile listfile0setinclude subinclude rootfilesinrrc~tj|} |jS#t$r |jcYSwxYw)zZcompile the regexp with the best available regexp engine and return a matcher function)r recompile test_matchAttributeErrormatch)regexms 1/usr/lib/python3/dist-packages/mercurial/match.py _rematcherr%1sJ A| ws (<<Fcg}g}|D]\}}} |dkr|tjd||||||r\|jD]T} || |||} t | | |} || U|||| f||fS)zFReturns the kindpats list with the 'set' patterns expanded to matchersrNs"fileset expression with no contextbadfn)rProgrammingErrorappend matchfilesetsubstatesubprefixdirmatcher) cwdkindpatsctx listsubreposr(matchersotherkindpatsourcesubpathsmpms r$ _expandsetsr;<sH E%**c6 6>>{,9 OOC,,S#U,CC D D D ("|((G))66sCu6MMB)'2UCCCBOOB''''  dC()))) U?cg}g}|D]\}}}|dkrtjtj|}tj|}tj||}tj|} | dgd|zgf} tj||| } | r| dz } || | f||||f||fS)z_Returns the list of subinclude matcher args and the kindpats without the subincludes in it.rr<s include:%s/)rdirnamer normpathpconvertjoin canonpathr*) r0root relmatchersr4r5r6r7 sourcerootpathnewroot matcherargsprefixs r$_expandsubincluderKTsK E%..c6 = !)$-*?*?@@J-$$C=S11D&t,,G"Cmd.B-CDK'dG<' - a glob relative to cwd 're:' - a regular expression 'path:' - a path relative to repository root, which is matched recursively 'rootfilesin:' - a path relative to repository root, which is matched non-recursively (will not match subdirectories) 'relglob:' - an unrooted glob (*.c matches C files in all dirs) 'relpath:' - a path relative to cwd 'relre:' - a regexp that needn't match the start of a name 'set:' - a fileset expression 'include:' - a file of patterns to read and include 'subinclude:' - a file of patterns to match against files under the same directory '' - a pattern of the specified default type >>> def _match(root, *args, **kwargs): ... return match(util.localpath(root), *args, **kwargs) Usually a patternmatcher is returned: >>> _match(b'/foo', b'.', [b're:.*\.c$', b'path:foo/a', b'*.py']) Combining 'patterns' with 'include' (resp. 'exclude') gives an intersectionmatcher (resp. a differencematcher): >>> type(_match(b'/foo', b'.', [b're:.*\.c$'], include=[b'path:lib'])) >>> type(_match(b'/foo', b'.', [b're:.*\.c$'], exclude=[b'path:build'])) Notice that, if 'patterns' is empty, an alwaysmatcher is returned: >>> _match(b'/foo', b'.', []) The 'default' argument determines which kind of pattern is assumed if a pattern has no prefix: >>> _match(b'/foo', b'.', [b'.*\.c$'], default=b're') >>> _match(b'/foo', b'.', [b'main.py'], default=b'relpath') >>> _match(b'/foo', b'.', [b'main.py'], default=b're') The primary use of matchers is to check whether a value (usually a file name) matches againset one of the patterns given at initialization. There are two ways of doing this check. >>> m = _match(b'/foo', b'', [b're:.*\.c$', b'relpath:a']) 1. Calling the matcher with a file name returns True if any pattern matches that file name: >>> m(b'a') True >>> m(b'main.c') True >>> m(b'test.py') False 2. Using the exact() method only returns True if the file name matches one of the exact patterns (i.e. not re: or glob: patterns): >>> m.exact(b'a') True >>> m.exact(b'main.c') False ct||||||}g}|D]Q\}} } |dvr/| }  | } | | kr| vr||| | f||| | fR|S)N)rr) _donormalizer*)patternsdefaultrDr/auditorwarnkpr0r5patsr7pr dsnormalizes r$ normalizezmatch..normalizeshsGTJJBH&( 6 6"dF000A&;t,,DDyyQ(]] q&(9:::tV 45555Or<rQrN)osrGisabsrBr localpathr[repor rdrO alwaysmatcherrXpatternmatcherincludematcherintersectmatchersdifferencematcher)rDr/r\includeexcluder]r^r1r2r_r(icasefsrdr0r#imemr rcs @@r$r!r!s@ 7==   ',,tT^C00 1 1CI88::&(       !9Xwc7DII  ) ) e$$AA%)AA %  %9WgtS'4HH "    %    a $ $ %9WgtS'4HH "    %    a $ $ Hr<c$t||S)Nr') exactmatcher)filesr(s r$exactrv8s U + + ++r<c t|SN)rir's r$alwaysry<s   r<c t|Srx)rSr's r$neverr{@s   r<c<tj|}||_|S)zWMake a copy of the given matcher, replacing its bad method with the given one. )copybad)r!r(r#s r$badmatchrDs %A AE Hr<c Vg}fd|DD]\}}|tvrtj||||}n|dvrtj|}n|dvr tj|} |dkr| d} n| } d| D} n2#t$r%tj td|zwxYwt| ||||D]\} } } | | | |f|d kr tj|tj|} t%| |}t|||||D] \} } } | | | | p|f!n}#tj $r#}tj d ||jfzd }~wt($r@}|r4|td |t+j|jfzYd }~nd }~wwxYw| ||d f|S)zConvert 'kind:pat' from the patterns list to tuples with kind and normalized and rooted patterns and with listfiles expanded.c0g|]}t|SrM _patsplit).0rbr]s r$ z _donormalize..Qs#>>>i7++>>>r<)r^)rrrr)rrrcg|]}||SrMrM)rfs r$rz _donormalize..]s///qQ////r<sunable to read file list (%s)rs%s: %sNs*skipping unreadable pattern file '%s': %s r<)cwdrelativepatternkindsrrCr r@readfilesplit splitlinesEnvironmentErrorrAbortrr[r*rerGrBrgreadpatternfilemessageIOErrorr forcebytestrstrerror)r\r]rDr/r^r_r0r5r6rukrbr7fullpath includepatsinsts ` r$r[r[MsH>>>>X>>>,*,* c * * *$T3WEEECC G G G-$$CC 0 0 0 M c**<''!KK..EE!,,..E//E///# M M Mk!$D"E"E"KLLL M ,wc7D!! - - 1fAs ,,,,  Z   7<<dnS.A.ABB-h== $0$Wd%%;;LAq&OOQ6=S$9::::;;   k    DHII 7 F FGH  sC()))) Os2AB++/CA7FH F== H  6HH ceZdZddZdZdZdZedZdZ edZ dZ d Z d Z d Zd Zd ZdZdZdS) basematcherNc| ||_dSdSrx)r~)selfr(s r$__init__zbasematcher.__init__s  DHHH  r<c,||Srx)matchfn)rfns r$__call__zbasematcher.__call__s||Br<cdS)zoCallback from dirstate.walk for each explicit file that can't be found/accessed, with an error message.NrMrrmsgs r$r~zbasematcher.badsr<cgSrxrMrs r$_fileszbasematcher._filess r<c|jS)zExplicitly listed files or patterns or roots: if no patterns or .always(): empty list, if exact: list exact files, if not .anypats(): list all files and dirs, else: optimal rootsrrs r$ruzbasematcher.filess {r<c*t|jSrx)setrrs r$_filesetzbasematcher._filesets4;r<c||jvS)z!Returns True if f is in .files().)rrrs r$rvzbasematcher.exactsDM!!r<cdSNFrMrs r$rzbasematcher.matchfnur<cdS)aDecides whether a directory should be visited based on whether it has potential matches in it or one of its subdirectories. This is based on the match's primary, included, and excluded patterns. Returns the string 'all' if the given directory and all subdirectories should be visited. Otherwise returns True or False indicating whether the given directory should be visited. TrMrdirs r$visitdirzbasematcher.visitdirs tr<cdS)a]Decides whether a directory should be visited based on whether it has potential matches in it or one of its subdirectories, and potentially lists which subdirectories of that directory should be visited. This is based on the match's primary, included, and excluded patterns. This function is very similar to 'visitdir', and the following mapping can be applied: visitdir | visitchildrenlist ----------+------------------- False | set() 'all' | 'all' True | 'this' OR non-empty set of subdirs -or files- to visit Example: Assume matchers ['path:foo/bar', 'rootfilesin:qux'], we would return the following values (assuming the implementation of visitchildrenset is capable of recognizing this; some implementations are not). '' -> {'foo', 'qux'} 'baz' -> set() 'foo' -> {'bar'} # Ideally this would be 'all', but since the prefix nature of matchers # is applied to the entire matcher, we have to downgrade this to # 'this' due to the non-prefix 'rootfilesin'-kind matcher being mixed # in. 'foo/bar' -> 'this' 'qux' -> 'this' Important: Most matchers do not know if they're representing files or directories. They see ['path:dir/f'] and don't know whether 'f' is a file or a directory, so visitchildrenset('dir') for most matchers will return {'f'}, but if the matcher knows it's a file (like exactmatcher does), it may return 'this'. Do not rely on the return being a set indicating that there are no files in this dir to investigate (or equivalently that if there are files to investigate in 'dir' that it will always return 'this'). thisrMrs r$visitchildrensetzbasematcher.visitchildrensets Rwr<cdS)zcMatcher will match everything and .files() will be empty -- optimization might be possible.FrMrs r$ryzbasematcher.always ur<cdS)zcMatcher will match exactly the list of files in .files() -- optimization might be possible.FrMrs r$isexactzbasematcher.isexactrr<cdS)z_Matcher will match the paths in .files() recursively -- optimization might be possible.FrMrs r$rJzbasematcher.prefixrr<c| o)| o| S)z`None of .always(), .isexact(), and .prefix() is true -- optimizations will be difficult.)ryrrJrs r$anypatszbasematcher.anypatss5;;== M%7M rMrs r$__repr__zalwaysmatcher.__repr__s!!r<rx) rrr__doc__rryrrrr __classcell__rs@r$riris333333"""""""r<ricBeZdZdZd fd ZdZdZdZdZdZ xZ S) rSzMatches nothing.NcXtt||dSrx)rrSrrs r$rznevermatcher.__init__s' lD!!**511111r<cdSrrMrs r$rznevermatcher.isexactrr<cdSrrMrs r$rJznevermatcher.prefixrr<cdSrrMrs r$rznevermatcher.visitdirrr<ctSrx)rrs r$rznevermatcher.visitchildrensets uu r<cdS)NzrMrs r$rznevermatcher.__repr__"s  r<rx) rrrrrrrJrrrrrs@r$rSrS s222222!!!!!!!r<rScDeZdZdZdfd ZejdZxZS)predicatematcherz/A matcher adapter for a simple boolean functionNcttt||||_||_dSrx)rrrr _predrepr)rpredfnpredreprr(rs r$rzpredicatematcher.__init__)s4 %%..u555 !r<cptj|jptj|j}d|zS)Ns)r buildreprrr bytereprr)rss r$rzpredicatematcher.__repr__.s:   0 0 H4E L5 5 .11r<NN) rrrrrr strmethodrrrs@r$rr&sb99"""""" 2222222r<rc t}|dkrdSvrdS|dkr-tfdtjDSdvrdSt dtfdDS) zDReturns True if `path` (or any parent of `path`) is in `prefix_set`.rFTc3 K|]}|vV dSrxrM)r parentdir prefix_sets r$ z)path_or_parents_in_set..As9  (1I #      r<r<r>c3tK|]2}|ot|kV3dSrx startswithrT)rpfrGsls r$rz)path_or_parents_in_set..NsCPPrtr"":tCGG}':PPPPPPr<)rTanyrfinddirsord)rGrlrs`` @r$path_or_parents_in_setr6s JAAvvu zt 1uu    5=5Ft5L5L       jt TB PPPPPZPPP P PPr<cleZdZdZd fd ZedZdZdZdZ e j dZ xZ S) rja(Matches a set of (kind, pat, source) against a 'root' directory. >>> kindpats = [ ... (b're', br'.*\.c$', b''), ... (b'path', b'foo/a', b''), ... (b'relpath', b'b', b''), ... (b'glob', b'*.h', b''), ... ] >>> m = patternmatcher(b'foo', kindpats) >>> m(b'main.c') # matches re:.*\.c$ True >>> m(b'b.txt') False >>> m(b'foo/a') # matches path:foo/a True >>> m(b'a') # does not match path:b, since 'root' is 'foo' False >>> m(b'b') # matches relpath:b, since 'root' is 'foo' True >>> m(b'lib.h') # matches glob:*.h True >>> m.files() ['', 'foo/a', 'b', ''] >>> m.exact(b'foo/a') True >>> m.exact(b'b') True >>> m.exact(b'lib.h') # exact matches are for (rel)path kinds False Nctt||t||_t ||_t |d|\|_|_dS)N$) rrjr_explicitfilesr_prefix _buildmatch_patsr)rrDr0r(rs r$rzpatternmatcher.__init__rs] nd##,,U333$X.. x(( #.xt#D#D  DLLLr<cNttj|jSrxrrdirsrrs r$_dirszpatternmatcher._dirsy8=//000r<cb|jr ||jvrdS||jvpt||jSr)rrrrrs r$rzpatternmatcher.visitdir}s< < C4=006dj N$:3 $N$NNr<cl||}|durdS|stS|dksJdS)NTrr)rr)rrrets r$rzpatternmatcher.visitchildrensetsDmmC   $;;7 55Lf}}}}vr<c|jSrx)rrs r$rJzpatternmatcher.prefix |r<c:dtj|jzS)Nsr bytestrrrs r$rzpatternmatcher.__repr__.1A$*1M1MMMr<rx)rrrrrrrrrrJrrrrrs@r$rjrjQs@EEEEEE11]1OOO NNNNNNNr<rjc8eZdZddZdZedZdZdS) _dirchildrenNcTi|_|pg|_|j}|D] }||dSrx)r _onlyincludeaddpath)rpaths onlyincluderrs r$rz_dirchildren.__init__sE '-2,  A GAJJJJ  r<c|dkrdS|j}tj}||D]D\}}||jvr||t |EdSNr<)rr_findsplitdirsr setdefaultradd)rrGr findsplitdirsdbs r$rz_dirchildren.addpaths 3;; Fz$3 !M$'' - -DAq))) OOAsuu % % ) )! , , , , - -r<c#Kt|}|d}|dkr8|d|||dz|fV|}|dd|}|dk8d|d|fVdS)Nr>rrr<)rTrfind)rGoldposposs r$rz_dirchildren._findsplitdirssTjjRiitt*d37V#344 4 4 4F**T1c**CRii4=      r<cP|j|tSrx)rgetr)rrGs r$r$z_dirchildren.getsz~~dCEE***r<rx)rrrrr staticmethodrr$rMr<r$rrsa--- ! !\ !+++++r<rcbeZdZdfd ZdZedZdZej dZ xZ S)rkNc\tt||t||_t |d|\|_|_t||_t|\}}}t||_ t||_ ||_ dS)N(?:/|$))rrkrrustmod _kindpatsrrrr_rootsdirsandparentsr_rootsr_parents)rrDr0r(rootsrparentsrs r$rzincludematcher.__init__s nd##,,U333  &DN#.xT#J#J  DLx(( 3H==tW%jj YY   r<ct|jr ||jvrdS||jvp||jvpt ||jSr)rr,rr-rrs r$rzincludematcher.visitdirsO < C4;..6 4:  8dm# 8%c4;77 r<ctttj|j|j|j|jS)N)r)r itertoolschainrr,r-rs r$_allparentschildrenz"includematcher._allparentschildrens7 ODJ T] C C     r<c|jr ||jvrdSd|jvs||jvst||jrdS||jvr(|j|p tStS)Nrr<r)rr,rrr-r4r$rrs r$rzincludematcher.visitchildrensets < C4;..6 4;  dj  %c4;77!7 $-  +//44= =uu r<c:dtj|jzS)Nsr rs r$rzincludematcher.__repr__rr<rx) rrrrrrr4rrrrrrs@r$rkrks      "      ]   NNNNNNNr<rkceZdZdZd fd ZejZedZ dZ edZ edZ dZ d Zejd ZxZS) rtaMatches the input files exactly. They are interpreted as paths, not patterns (so no kind-prefixes). >>> m = exactmatcher([b'a.txt', br're:.*\.c$']) >>> m(b'a.txt') True >>> m(b'b.txt') False Input files that would be matched are exactly those returned by .files() >>> m.files() ['a.txt', 're:.*\\.c$'] So pattern 're:.*\.c$' is not considered as a regex, but as a file name >>> m(b'main.c') False >>> m(br're:.*\.c$') True Nctt||t|tr ||_dSt ||_dSrx)rrtr isinstancelistr)rrur(rs r$rzexactmatcher.__init__ sO lD!!**5111 eT " " &DKKKu++DKKKr<cNttj|jSrxrrs r$rzexactmatcher._dirsrr<c||jvSrx)rrs r$rzexactmatcher.visitdirsdj  r<c(|j|jdhz zS)z2A memoized set of candidates for visitchildrenset.r<)rrrs r$_visitchildrenset_candidatesz)exactmatcher._visitchildrenset_candidatess}tzSE111r<c*t|jS)z:A memoized sorted list of candidates for visitchildrenset.)sortedr>rs r$#_sorted_visitchildrenset_candidatesz0exactmatcher._sorted_visitchildrenset_candidates#sd7888r<c|jr ||jvrtS|dkr|j}n|j}|dz}t j||}|tjttddzz}t j|||}t|fd|||D}d|D}|sJ|S)Nr<r>r)loc$h|] }|d SrxrM)rcdlens r$ z0exactmatcher.visitchildrenset..=s!CCCq!DEE(CCCr<ch|]}d|v| S)r>rM)rrEs r$rGz0exactmatcher.visitchildrenset..Cs666QA q r<) rrrr>rAbisect bisect_leftr strtolocalchrrrT) rr candidatesrfirstdnextlastrrFs @r$rzexactmatcher.visitchildrenset(s} 4: 5 555L #:::JJAJd A&z155E (-c#d))a-.@.@AAAE%j%EBBBDq66DCCCCJuTz,BCCCJ 76*666  r<cdSrrMrs r$rzexactmatcher.isexactIrr<cd|jzS)Nsrrs r$rzexactmatcher.__repr__Ls)DK77r<rx)rrrrrrrvrrrrr>rArrrrrrrs@r$rtrts(&&&&&&G11]1!!!22]299]9B8888888r<rtcpeZdZdZfdZdZedZdZdZ dZ e j dZ xZS) rmzComposes two matchers by matching if the first matches and the second does not. The second matcher's non-matching-attributes (bad, traversedir) are ignored. ctt|||_||_|j|_|j|_dSrx)rrmr_m1_m2r~rrm1m2rs r$rzdifferencematcher.__init__XsG &&//1116>r<cX||o|| SrxrUrVrs r$rzdifferencematcher.matchfn_s#xx{{.488A;;.r<cr%fdjDSjS)Nc*g|]}| |SrMrMrrrs r$rz,differencematcher._files..es&;;;!4477;A;;;r<)rrUrurs`r$rzdifferencematcher._filesbsM <<>> <;;;;tx~~//;;; ; x~~r<c|j|dkrdS|j|s|j|St|j|S)NrF)rVrrUboolrs r$rzdifferencematcher.visitdirmsn 8  S ! !V + +5""3'' *8$$S)) )DH%%c**+++r<c|j|}|dkrtS|j|}|s|S|dvrdS|S)Nr)rrr)rVrrrU)rrm2_setm1_sets r$rz"differencematcher.visitchildrensetusi**3// V  55L**3//  M & & &7 r<c4|jSrx)rUrrs r$rzdifferencematcher.isexactsx!!!r<c$d|j|jfzS)Ns r[rs r$rzdifferencematcher.__repr__s2dh5IIIr<)rrrrrrrrrrrrrrrrs@r$rmrmQs *****///  ] ,,,2"""JJJJJJJr<rmc |||p|S|r.tj|}|j|_|j|_|S|rtj|}|St ||S)zComposes two matchers by matching if both of them match. The second matcher's non-matching-attributes (bad, traversedir) are ignored. )ryr}r~rintersectionmatcher)rXrYr#s r$rlrls~  zRZxR yy{{ IbMM  yy{{ IbMM r2 & &&r<creZdZfdZedZdZdZdZdZ dZ e j dZ xZS) rgctt|||_||_|j|_|j|_dSrx)rrgrrUrVr~rrWs r$rzintersectionmatcher.__init__sG !4((113336>r<c"|rH|j|jc}|s|c}fd|DS|j|jzS)Nc*g|]}| |SrMrM)rrrYs r$rz.intersectionmatcher._files..s&333!RRUU3A333r<)rrUrVru)rrXrYs @r$rzintersectionmatcher._filess <<>> 4XtxFB::<< RB3333rxxzz333 3 x~~$(.."2"222r<cV||o||Srxr[rs r$rzintersectionmatcher.matchfns!xx{{*txx{{*r<c|j|}|dkr|j|St|o|j|Sr)rUrrVr`)rrvisit1s r$rzintersectionmatcher.visitdirs[""3'' V  8$$S)) )F5tx0055666r<ch|j|}|stS|j|}|stS|dkr|S|dkr|S|dks|dkrdSt |trt |tsJ||S)Nrr)rUrrrVr9 intersection)rrrcrbs r$rz$intersectionmatcher.visitchildrensets**3// 55L**3// 55L V  M v  M W  ' 1 17&#&&B:fc+B+BBBB""6***r<cf|jo|jSrx)rUryrVrs r$ryzintersectionmatcher.alwayss%x  6TX__%6%66r<cf|jp|jSrx)rUrrVrs r$rzintersectionmatcher.isexacts)x!!7TX%5%5%7%77r<c$d|j|jfzS)Ns"r[rs r$rzintersectionmatcher.__repr__s4$(7KKKr<)rrrrrrrrrryrrrrrrs@r$rgrgs***** 3 3] 3+++777+++&777888LLLLLLLr<rgcfeZdZdZfdZdZdZdZdZdZ dZ e j d Z xZS) subdirmatcheraAdapt a matcher to work on a subdirectory only. The paths are remapped to remove/insert the path as needed: >>> from . import pycompat >>> m1 = match(util.localpath(b'/root'), b'', [b'a.txt', b'sub/b.txt'], auditor=lambda name: None) >>> m2 = subdirmatcher(b'sub', m1) >>> m2(b'a.txt') False >>> m2(b'b.txt') True >>> m2.matchfn(b'a.txt') False >>> m2.matchfn(b'b.txt') True >>> m2.files() ['b.txt'] >>> m2.exact(b'b.txt') True >>> def bad(f, msg): ... print(pycompat.sysstr(b"%s: %s" % (f, msg))) >>> m1.bad = bad >>> m2.bad(b'x.txt', b'No such file') sub/x.txt: No such file cLtt||_||_||_fd|jD|_|r'tfd|jD|_dSdS)Nctg|]4}|dz|tdzd5S)r>rNrrrrGs r$rz*subdirmatcher.__init__..sR   ||D4K(( c$ii!moo    r<c3$K|] }|kV dSrxrMrxs r$rz)subdirmatcher.__init__..s'AAQqDyAAAAAAr<) rrur_path_matcherry_alwaysrrJr)rrGmatcherrs ` r$rzsubdirmatcher.__init__s mT""++---  ~~''     ^     >>   BAAAA'.AAAAADLLL B Br<cR|j|jdz|z|dSNr>)r{r~rzrs r$r~zsubdirmatcher.bads, $*t+a/55555r<cL|j|jdz|zSr)r{rrzrs r$rzsubdirmatcher.matchfns& }$$TZ$%6%:;;;r<cl|dkr|j}n |jdz|z}|j|SNr<r>)rzr{rrs r$rzsubdirmatcher.visitdirs; #::*CC*t#c)C}%%c***r<cl|dkr|j}n |jdz|z}|j|Sr)rzr{rrs r$rzsubdirmatcher.visitchildrenset$s; #::*CC*t#c)C}--c222r<c|jSrx)r|rs r$ryzsubdirmatcher.always+r r<cD|jo|j Srx)r{rJr|rs r$rJzsubdirmatcher.prefix.s }##%%:dl*::r<c$d|j|jfzS)Ns#)rzr{rs r$rzsubdirmatcher.__repr__1s5 J M9   r<)rrrrrr~rrrryrJrrrrrs@r$rurus4BBBBB"666<<<+++333;;;       r<ruceZdZdZd fd ZedZdZedZdZ dZ d Z d Z e jd ZxZS) r.aAdapt a matcher to work on a parent directory. The matcher's non-matching-attributes (bad, traversedir) are ignored. The prefix path should usually be the relative path from the root of this matcher to the root of the wrapped matcher. >>> m1 = match(util.localpath(b'/root/d/e'), b'f', [b'../a.txt', b'b.txt'], auditor=lambda name: None) >>> m2 = prefixdirmatcher(b'd/e', m1) >>> m2(b'a.txt') False >>> m2(b'd/e/a.txt') True >>> m2(b'd/e/b.txt') False >>> m2.files() ['d/e/a.txt', 'd/e/f/b.txt'] >>> m2.exact(b'd/e/a.txt') True >>> m2.visitdir(b'd') True >>> m2.visitdir(b'd/e') True >>> m2.visitdir(b'd/e/f') True >>> m2.visitdir(b'd/e/g') False >>> m2.visitdir(b'd/ef') False Nctt|||stjd||_|dz|_||_dS)Nsprefix path must not be emptyr>)rr.rrr)rz _pathprefixr{)rrGr}r(rs r$rzprefixdirmatcher.__init__Ys[ %%..u555 K()IJJ J $; r<c4fdjjDS)Nc$g|] }j|z SrM)rr^s r$rz+prefixdirmatcher._files..cs!CCC 1$CCCr<)r{rrs`r$rzprefixdirmatcher._filesas"CCCCdm.BCCCCr<c||jsdS|j|t |jdSr)rrr{rrTrs r$rzprefixdirmatcher.matchfnesJ||D,-- 5}$$Qs4+;'<'<'>'>%?@@@r<cNttj|jSrx)rrrrzrs r$ _pathdirszprefixdirmatcher._pathdirsjs8$TZ00111r<c||jkr|jdS||jr4|j|t |jdS||jvSr)rzr{rrrrTrrs r$rzprefixdirmatcher.visitdirnsv $*  =))#.. . >>$* + + H=))#c$2B.C.C.E.E*FGG Gdn$$r<c||jkr|jdS||jr4|j|t |jdS||jvrdStS)Nr<r)rzr{rrrrTrrrs r$rz!prefixdirmatcher.visitchildrensetus $*  =11#66 6 >>$* + + P=11#c$:J6K6K6M6M2NOO O $. 7uu r<c4|jSrx)r{rrs r$rzprefixdirmatcher.isexact~s}$$&&&r<c4|jSrx)r{rJrs r$rJzprefixdirmatcher.prefixs}##%%%r<cHdtj|j|jfzS)Ns&)r r rzr{rs r$rzprefixdirmatcher.__repr__s)8  TZ ( ( M<   r<rx)rrrrrrrrrrrrrJrrrrrs@r$r.r.9s>      DD]DAAA 22]2%%%'''&&&       r<r.cTeZdZdZfdZdZdZdZej dZ xZ S)rUzA matcher that is the union of several matchers. The non-matching-attributes (bad, traversedir) are taken from the first matcher. c|d}tt||j|_||_dS)Nr)rrUrr _matchers)rr3rXrs r$rzunionmatcher.__init__s= a[ lD!!**,,,>!r<c6|jD]}||rdSdSNTFr)rrr!s r$rzunionmatcher.matchfns4^  EuQxx tt ur<cfd}|jD]&}||}|dkr|cS||z}'|S)NFr)rr)rrrr#vs r$rzunionmatcher.visitdirsI   A 3AF{{ FAAr<ct}d}|jD][}||}|s|dkr|cS|s|dkrd}/t|tsJ||}\|rdS|S)NFrrT)rrrr9union)rrrthisr#rs r$rzunionmatcher.visitchildrensets EE  A""3''A F{{ qG||a%% % % % AA  7r<cd|jzS)Nsrrs r$rzunionmatcher.__repr__s,t~==r<) rrrrrrrrrrrrrs@r$rUrUs """""  &>>>>>>>r<rUc.t||dS)aIf pattern is 'kind:pat' with a known kind, return kind. >>> patkind(br're:.*\.c$') 're' >>> patkind(b'glob:*.c') 'glob' >>> patkind(b'relpath:test.py') 'relpath' >>> patkind(b'main.py') >>> patkind(b'main.py', default=b're') 're' rr)patternr]s r$patkindrs Wg & &q ))r<c^d|vr&|dd\}}|tvr||fS||fS)zPSplit a string into the optional pattern kind prefix and the actual pattern.:r)rallpatternkinds)rr]r5r6s r$rrsD wMM$** c ? " "9  G r<c dtc d}d}tjjj} fd} kr dz} dz |dvr||||z }n|dkr;|dkr& dz |dkr dz |dz }nN|d z }nG|d z }n@|d kr|d z }n3|d kr }| kr||dzdvr|dz }| kr-||dzdkr|dz }| kr||dzdk| kr|dz }n҉ |dd}|dz |dddkrd|ddz}n|dddkrd|z}d||fz}nx|dkr |dz }|dz }ng|dkr |r |dz }|dz}nT|dkr|r|dz }nF|dkr1|}|r dz ||||z }n||||z }n||||z } k|S)a Convert an extended glob string to a regexp string. >>> from . import pycompat >>> def bprint(s): ... print(pycompat.sysstr(s)) >>> bprint(_globre(br'?')) . >>> bprint(_globre(br'*')) [^/]* >>> bprint(_globre(br'**')) .* >>> bprint(_globre(br'**/a')) (?:.*/)?a >>> bprint(_globre(br'a/**/b')) a/(?:.*/)?b >>> bprint(_globre(br'[a*?!^][^b][!c]')) [a*?!^][\^b][^c] >>> bprint(_globre(br'{a,b}')) (?:a|b) >>> bprint(_globre(br'.\*\?')) \.\*\? rr<c*ko dzS)NrrM)inr6sr$peekz_globre..peeks1u'QQY'r<rs*?[{},\*r>s(?:.*/)?.*[^/]*?.[s!]]s\[\s\\!^Ns%s[%s]{s(?:}),|)rTr r regexbytesescapemapr$replace) r6resgroupescaperrEjstuffrbrrs ` @@r$_globrers. c#hhDAq C E _ 0 4F((((((( a%% AE N Q K   66!Q<< CC $YYtvv~~Q466T>>FA;&CC5LCCx $YY 4KCC $YYA1uuQQY500Qa%%CAE Nd22Qa%%CAE Nd22Avvv AaC((88E1:%% 59,EE1Q3Z4''!EME3,. $YY QJE 6MCC $YY5Y 4KC QJEE $YY5Y 4KCC %ZZA $Qvva||#vva||# 66!Q<< Cc a%%d Jr<s^\(\?([aiLmsux]+)\)(.*)c|s|dvrdS|dkr|S|dvr*|dkrdStj|dzS|dkr0|dkrd}n"tj|dz}|d zS|d krIt|}|d rd |t d d z|zSd|z|zS|dkrZd }t |}|r|\}}|dsd |z}|d||fz}|S|dvrt||zStj d||fz)z|Convert a (normalized) pattern of any kind into a regular expression. globsuffix is appended to the regexp of globs.)rrr<rrrrr(rr>s[^/]+$rrrNs(?:|.*/)rrs(?%s:%s)rrsnot a regex pattern: %s:%s) r r reescaperrrTFLAG_REr!groupsrr))r5r6 globsuffixescapedglobreflagr#s r$_regexr1s 4000s u}}  $$$ $;;3'',,z99 ~ $;;GGo..s33d:G"" z   X & & @6#h--//22Z? ?V#j00 x MM#    # ID#~~d## #+C  $,C  %%%s||j((  !>$!L M MMr<c gt||\}ri  fd}|d}|rtd|DrXd|Dfd}dtjt t z}|n(t||\}}|tdkr |dfS|fd fS) zlReturn regexp string and a matcher function for kindpats. globsuffix is appended to the regexp of globs.cD]b\}}||rH|}|t|}||<||t|drdScdSr)rr$r!rT)rrJrImf subincludes submatcherss r$matchsubincludez$_buildmatch..matchsubincludeds'2 $ $# <<''$$00Bz"K0.0 F+r!CKKMM*++$#tt5r<r<c3*K|]\}}}|dkVdS)rNrMrrrbrs r$rz_buildmatch..ts-;;wq!QqN";;;;;;r<ch|]\}}}| SrMrMrs r$rGz_buildmatch..us...'!QA...r<c\|d}|dkr |d|}nd}|vS)Nr>rr)r )rrrrs r$rz_buildmatch..mfws9GGDMM66BQB%CCCd{"r<srootfilesin: %srrc<tfdDS)Nc3.K|]}|VdSrxrM)rrrs r$rz0_buildmatch....s+#?#?bBBqEE#?#?#?#?#?#?r<r)r matchfuncss`r$z_buildmatch..s%#?#?#?#?J#?#?#? ? ?r<) rKr*allr pprintr:r@_buildregexmatchrT) r0rrDrr"rrrrrs @@@@r$rr[sRJ-h==K+        /*** E" ;;(;;; ; ; "..X...D # # # # #'):4t ;M;M)N)NNE   b ! ! ! !(:>>IE2   b ! ! ! :!jm##??????r<i Nc,d|S)z5gather multiple regular expressions into a single oner)rB)regexpss r$ _joinregexesrs 99W  r<c  g}fd|D}t|}d}d}t|D]\}}t|} | tkr&t d| z} t j| || ztkr0|||} |t| |}d}|| dzz }|dkrt|fd} n=||d} |t| d|Dfd} || fS#tj$r|D]\} }} tt| |&#tj$rP|r't jt d || |fzt jt d | |fzwxYwt jt d wxYw) aKBuild a match function from a list of kinds and kindpats, return regexp string and a matcher function. Test too large input >>> _buildregexmatch([ ... (b'relglob', b'?' * MAX_RE_SIZE, b'') ... ], b'$') Traceback (most recent call last): ... Abort: matcher pattern is too long (20009 bytes) c:g|]\}}}t||SrM)r)rrrbrrs r$rz$_buildregexmatch..s+FFF Aq6!Q ++FFFr<rs&matcher pattern is too long (%d bytes)rc4t|Srx)r`)rr}s r$rz"_buildregexmatch..sT''!**--r<Nc,g|]}t|SrM)r%)rgs r$rz$_buildregexmatch..s<<...s+ ; ;!1 ; ; ; ; ; ;r<r)r allmatcherss`r$rz"_buildregexmatch..s%S ; ; ; ;{ ; ; ;;;r<s%s: invalid pattern (%s): %ssinvalid pattern (%s): %ssinvalid pattern) r enumeraterT MAX_RE_SIZErrrr*r%rr)r0r allgroupsr fullregexpstartidx groupsizeidxr piecesizerrfuncrrbrrr}s ` @@r$rrsN'1 FFFFXFFF!'**  (( ' 'FCAI;&&ABBYNk#&&&i';66 -  e!4!4555 Q &II q== ,,G----DDHII&E   \%00 1 1 1<<)<<rrrr)rrrr<r)rr*rB)r0rrr5r6r7rDrbs r$_patternrootsanddirsrs A A%c6 ) ) )DYYt__  199 TQYY$!))E A HHTYYt__ % % % % * * *d{{ HHSMMMM & & &d{{ HHSMMMM HHSMMMM a4Kr<c*t|\}}|S)zFReturns root directories to match recursively from the given patterns.)r)r0r.rs r$r,r,s&x00KE4 Lr<ct|\}}t}|tj||tj||||fS)aReturns roots and exact directories from patterns. `roots` are directories to match recursively, `dirs` should be matched non-recursively, and `parents` are the implicitly required directories to walk to items in either roots or dirs. Returns a tuple of (roots, dirs, parents). >>> r = _rootsdirsandparents( ... [(b'glob', b'g/h/*', b''), (b'glob', b'g/h', b''), ... (b'glob', b'g*', b'')]) >>> print(r[0:2], sorted(r[2])) # the set has an unstable output (['g/h', 'g/h', ''], []) ['', 'g'] >>> r = _rootsdirsandparents( ... [(b'rootfilesin', b'g/h', b''), (b'rootfilesin', b'', b'')]) >>> print(r[0:2], sorted(r[2])) # the set has an unstable output ([], ['g/h', '']) ['', 'g'] >>> r = _rootsdirsandparents( ... [(b'relpath', b'r', b''), (b'path', b'p/p', b''), ... (b'path', b'', b'')]) >>> print(r[0:2], sorted(r[2])) # the set has an unstable output (['r', 'p/p', ''], []) ['', 'p'] >>> r = _rootsdirsandparents( ... [(b'relglob', b'rg*', b''), (b're', b're/', b''), ... (b'relre', b'rr', b'')]) >>> print(r[0:2], sorted(r[2])) # the set has an unstable output (['', '', ''], []) [''] )rrupdaterr)r0rrrbs r$r+r+se:  ) )DAq AHHX]1  HHX]1   a7Nr<c8d|D}t|S)zReturns the potential explicit filenames from the patterns. >>> _explicitfiles([(b'path', b'foo/bar', b'')]) ['foo/bar'] >>> _explicitfiles([(b'rootfilesin', b'foo/bar', b'')]) [] c&g|]}|ddv |S)rrrM)rr`s r$rz"_explicitfiles..$s'GGGb15F(F(Fr(F(F(Fr<)r,)r0filables r$rrs$HGHGGGG '??r<c&|D] \}}}|dvrdSdS)z:Whether all the patterns match a prefix (i.e. recursively)rFTrMrNs r$rr(s5%c6 , , ,55 - 4r<cddddddd}d}g}t|d}t|d D]\}}d |vrutstjd at|} | r|d | d}|d d }| }|s| drW|dd  } || }n/#t$r"|r|td|| fzYnwxYw|} |D]k\} } | | r| } |t| d }n7| | dzr| } |t| dzd }nl|r|| |z||f|| |z||S)a.parse a pattern file, returning a list of patterns. These patterns should be given to compile() to be validated and converted into a match function. trailing white space is dropped. the escape character is backslash. comments start with #. empty lines are skipped. lines can be of the following formats: syntax: regexp # defaults following lines to non-rooted regexps syntax: glob # defaults following lines to non-rooted globs re:pattern # non-rooted regular expression glob:pattern # non-rooted glob rootglob:pat # rooted glob (same root as ^ in regexps) pattern # pattern of the current default type if sourceinfo is set, returns a list of tuples: (pattern, lineno, originalline). This is useful to debug ignore patterns. srelre:srelglob:s rootglob:rr)rsregexprrrrsrbr)start#s((?:^|[^\\])(?:\\\\)*)#.*Ns\#ssyntax:s!%s: ignoring invalid syntax '%s' r)rr _commentrer rrsearchendrrstriprstripKeyErrorritemsrTr*close) filepathr_ sourceinfosyntaxessyntaxr\fplinenoliner#r linesyntaxrelss r$rr3sY2!$ HFH h  B!"A...'/'/  4<< L!W__-JKK !!$''A (JaeeAhhJ'<<--D{{}}   ??: & & QRR  A !!   D?@@Ha=P   ~~''  GAtt$$ ! CIIKK(T** ! CFFQJLL)   / OOZ$.= > > > > OOJ- . . . .HHJJJ Os7D)D,+D,)NFN) NNNrNNFNNFrxr)F)ArIr}r2reri18nrr rrrrr r utilsr importrustr)rrrr%r;rKrOrXr!rvryr{rr[rrirSrrrjrrkrtrmrlrgrur.rUrrrrrrrrrrrr,r+rrrrrMr<r$rs   & J ' '0" 02  """"@       a a a a H,,,,       1111hqNqNqNqNqNqNqNqNh"""""K""",!!!!!;!!!6 2 2 2 2 2{ 2 2 2 QQQ6?N?N?N?N?N[?N?N?NJ"+"+"+"+"+"+"+"+J:N:N:N:N:N[:N:N:NzV8V8V8V8V8;V8V8V8rBJBJBJBJBJ BJBJBJJ'''(:L:L:L:L:L+:L:L:LzO O O O O KO O O dP P P P P {P P P f1>1>1>1>1>;1>1>1>h * * * * QQQh '//5 6 6'N'N'NT-@-@-@`  313131l> )))X    MMMMMMr<