o ]Lbq @sddlmZddlZddlmZddlmZddlmZddl m Z m Z mZm Z m Z ddlmZid d d d d ddddddddddddddddddddd d!d d"d#d$d%d&d%d%d'd(d)d)d*d+d)d,Zhd-ZiZd.d/hZeed0Zeeeejeejd1eeejed2d3BZeeed4BZdd5d6Ze Z!d7d8Z"d9d:Z#e!fd;d<Z$d=d>Z%d?d@Z&dAdBZ'e!e!fdCdDZ(dEdFZ)dGdHZ*iZ+dIdJZ,dKdLZ-dMdNZ.dOdPZ/dQdRZ0dSdTZ1dUdVZ2dWdXZ3dYdZZ4ed[hBZ5dd\d]Z6Gd^d_d_e j7Z8dd`daZ9dbdcZ:ddddeZ;dfdgZdldmZ?dndoZ@e>e@dpZAdqdrZBdsdtZCdudvZDdwdxZEdydzZFd{d|ZGe jHId}ZJd~dZKddZLdS))absolute_importN)_)getattrhex)errorparserpycompatsmartsetutil) stringutil()N)groupr))funcrrN[)rNN) subscriptr]N#)rNN)relationrN##)NN)_concatrN~)NN)ancestorrN^)rNN)parentr parentpost-)N)negate)minusr"N::) dagrangeall) dagrangeprer')dagranger' dagrangepost..:)rangeall)rangeprer.)ranger. rangepostnot) N)r3r4NN!and)r"NN)r6r"N&%)r"NN)onlyr"onlypostor)NN)r;r<N|)NN)keyvaluer>N)NN)listr@N)rNNNN)rsymbolNNN)rstringNNN)+=,rrrBrCend>r;r6r3"'s()[]#:=,-|&+!~^%s._@s-/c #st|ts td|t|}|durt}|durt}|riri|dd}t fdd|Dri|dr?d|ddfVt |dkr_t |d}dd|fV|dr_d|d|dfVd dt |fVdSdt |}}||kr||}| rng|dkr|||d d krd d|fV|d7}nM|d kr|||d d krd d|fV|d7}n3|dkr|||d dkrdd|fV|d7}n|t vr|d|fVn |t vs|dkr?|||d dvr?|dkr|d7}||}dd} ntj} |d7}|}||kr6||} | dkr|d 7}q| |kr-d| ||||fVn|d7}||ks ttd|n||vr|}|d7}||kru||} | |vrYn| d krl||dd krl|d8}n |d7}||ksO|||} | tvr| d|fVnPd| vrшr| rd| |fVn<| d}|ddD]} | rd| |fV|t | 7}dd|fV|d7}q|drd|d|fVnd| |fV|d8}n ttd|||d7}||ksud d|fVdS)a Parse a revset statement into a stream of tokens ``syminitletters`` is the set of valid characters for the initial letter of symbols. By default, character ``c`` is recognized as valid for initial letter of symbols, if ``c.isalnum() or c in '._@' or ord(c) > 127``. ``symletters`` is the set of valid characters for non-initial letters of symbols. By default, character ``c`` is recognized as valid for non-initial letters of symbols, if ``c.isalnum() or c in '-._/@' or ord(c) > 127``. Check that @ is a valid unquoted token character (issue3686): >>> list(tokenize(b"@::")) [('symbol', '@', 0), ('::', None, 1), ('end', None, 3)] s&revset statement must be bytes, got %rNr-rc3s|] }|r|VqdSN).0symlookuprM6/usr/lib/python3/dist-packages/mercurial/revsetlang.py xztokenize..rrBrGr@r&.r,rrr)sr'sr"cSs|SrLrMxrMrMrRsztokenize..\rCsunterminated stringr!ssyntax error in revset '%s') isinstancebytesrProgrammingErrorr bytestr_syminitletters _symletterssplitalllenisspace_simpleopletters _quotelettersr unescapestr ParseErrorrkeywords) programrQsyminitletters symletterspartssposlcdecodedrOprMrPrRtokenizeUs                                  VrvcCs&|r |ddkr |dSttd)NrrBrs not a symbol)rrirrWrMrMrR getsymbolsrwcCs.|r|ddks|ddkr|dSt|)NrrCrBrrri)rXerrrMrMrR getstrings rzcCs:|s|tur|Sztt||WStyt|wrL)_notsetintrz ValueErrorrri)rXrydefaultrMrMrR getintegers   rcCs$tt|}|dur |St|rL)r parseboolrwrri)rXryvaluerMrMrR getbooleans rcCs*|sgS|ddkrt|ddS|gS)NrrAr)listrWrMrMrRgetlists  rcCsl|st||d}|dkr|d|dfS|dkr!d|dfS|dkr+|ddfS|dkr1dSt|) Nrr1rr@r0r2r/NNrx)rXryoprMrMrRgetranges    rcCsT|r|ddks|ddkrt||}||fSt||\}}t|||t|||fS)zGet [first, last] integer range (both inclusive) from a parsed tree If any of the sides omitted, and if no default provided, ParseError will be raised. rrCrB)rr)rXerr1err2deffirstdeflastnabrMrMrR getintranges  rcCs6t|}t||ks|dkrt||krt||S)Nr)rrdrri)rXminmaxryrqrMrMrRgetargs"s  rcCstjt||t|dddS)Nr?rB) keyvaluenodekeynode)r buildargsdictr splitargspec)rXfuncnamekeysrMrMrR getargsdict)srcCs&t|}|durt|t|<}|SrL) _treecachegetparse)spectreerMrMrR _cachedtree7s rcGst|}tj|dg|RS)zCreate raw parsed tree from a template revset statement >>> _build(b'f(_) and _', (b'string', b'1'), (b'symbol', b'2')) ('and', ('func', ('symbol', 'f'), ('string', '1')), ('symbol', '2')) rB_)rr buildtree)tmplspecreplstemplaterMrMrR_build?srcCst|}t||dddhS)aTest if a tree matches the given pattern statement; return the matches >>> _match(b'f(_)', parse(b'f()')) >>> _match(b'f(_)', parse(b'f(1)')) [('func', ('symbol', 'f'), ('symbol', '1')), ('symbol', '1')] >>> _match(b'f(_)', parse(b'f(1, 2)')) rr?rA)rr matchtree)patspecrpatternrMrMrR_matchIs rcCstdd||fS)Ns!ancestors(_) and not ancestors(_)r6)r)revsbasesrMrMrR _matchonlyWsrcCs,t|ts|S|d}|dkrXd|df}|dddkr(td||ddfS|dddkr6td |fS|ddd krItd ||ddfS|ddd krWtd |fSn.|dkrh|td|ddfS|dkr|dddkrtd|dd|dd|dfS|ftdd|ddDS)zrRewrite raw parsed tree to resolve ambiguous syntax which cannot be handled well by our simple top-down parserrrr rr@r)r*r(r+r0r1r/r2r;rANrr relsubscriptcs|]}t|VqdSrL)_fixopsrNyrMrMrRrSvz_fixops..)r\tupler)rXrpostrMrMrRr[s&    $ rcCs|dur|S|d}|dkrttdg|ddRS|dkr.ttdg|ddRS|dkr;ttd|dS|d krFttd |d krSttd |dS|d kr`ttd|dS|dkrut|dtd}tdd|fS|dvr{|S|dkr|dfS|dvr|t|dfS|dkrt|dS|dvrt|d}t|d}|||fS|dkrt|d}t|d}t|d}||||fS|dkr|ftdd|ddDS|dkr||dt|dfS|dkr||dt|dfStd |)!Nrr%s _ and not _rr9 only(_, _)r:sonly(_)r(scan't use '::' in this contextr)s ancestors(_)r+sdescendants(_)r#scan't negate thatrCr!rCrBsmartsetr/>r;r3r0r2r r>r6r1rrr*rrr@rr>rAcsrrL_analyzerrMrMrRrSrz_analyze..r?rinvalid operator %r)rrrrirrzrr})rXrrotatbtcrMrMrRrysT         rcCst|S)zTransform raw parsed tree to evaluatable tree which can be fed to optimize() or getset() All pseudo operations should be mapped to real operations or functions defined in methods or symbols table respectively. rrWrMrMrRanalyzesrc s|durd|fS|d}|dvrd|fS|dkrt|d\}}t|d\}}t||}tdd||f}|rKt|ddvrK|td |d|dfSt||pTt||}|re|td g|ddRfStd |}|ru|d ||dffS||kr{d }||||ffS|dkrgggfdd}t|dD]-} t| \}} | dur| ddks| ddkr|| fq||| q|tdkrۈddfSt |dt ffS|dkrtd|drttd} | d| dfSt|d} | d|| dffS|dkrd|fS|dvr0t|d} | d|| dffS|dvrNt|d\}}t|d\}}|||||ffS|dvrdt|d\}} ||| |dffS|dkr}t|d\}} ||| |d|dffS|dkrt dd|ddD\t |ffS|d krt|d\}} |||d| ffS|d!krt|d} t|d\}}t t| d"d}td#|}| d$kr|r||td%|dfS||||d|ffStd&|)'Nrrg?r6rr@s_() & ancestors(_)>draftsecret _notpublics_phaseandancestors(_, _)rsnot _s differences andsmallyr;csrsdStdkrd\}}ndddD}tdd|f}t|\}}||dd=dS)Nrrcss|] \}}|dVqdS)rNrM)rNwtrMrMrRrSrTz-_optimize..flushss..s_list(_)rC)rdjoinr _optimizeappend)rrrorsstswsrMrRflushsss    z_optimize..flushssrCrBrr3spublic()s _notpublic()r/)r0r2r )r*r1)rrrrrr>rAcsrrLrrrMrMrRrS rz_optimize..r?r_weightscommonancestors(_)sheadss_commonancestorheads(_)r)rrrrwrrrrrdrrzipsumrsymbolsrr}) rXrwarwbrrmrrrofrMrrRrs                      rcCst|\}}|S)z[Optimize evaluatable tree All pseudo operations should be transformed beforehand. r)rrnewtreerMrMrRoptimizes r$cCsj|r|dr|drd}tt}|t|||d\}}|t|kr-tt d|t t |dS)aQGenerate a parse tree of given spec with given tokenizing options >>> _parsewith(b'foo($1)', syminitletters=_aliassyminitletters) ('func', ('symbol', 'foo'), ('symbol', '$1')) >>> from . import error >>> from . import pycompat >>> try: ... _parsewith(b'$1') ... except error.ParseError as e: ... pycompat.sysstr(e.message) ... e.location "syntax error in revset '$1'" 0 >>> try: ... _parsewith(b'foo bar') ... except error.ParseError as e: ... pycompat.sysstr(e.message) ... e.location 'invalid token' 4 srevset(rN)rQrls invalid token)rAr;) startswithendswithr elementsrrvrdrrirrsimplifyinfixops)rrQrlrurrprMrMrR _parsewith,s   rc@s0eZdZdZedZeddZeddZdS) _aliasrulesz0Parsing and expansion rule set of revset aliasess revset aliascCs t|tdS)aParse alias declaration/definition ``spec`` This allows symbol names to use also ``$`` as an initial letter (for backward compatibility), and callers of this function should examine whether ``$`` is used also for unexpected symbols or not. rl)r_aliassyminitletters)rrMrMrR_parseRs z_aliasrules._parsecCs<|ddkr|dddkr|ddt|dfSdSdS)NrrrrBr@)rrrMrMrR _trygetfunc\sz_aliasrules._trygetfuncN) __name__ __module__ __qualname____doc__r_section staticmethodrrrMrMrMrRrMs  rcCs^t|}t||}|dur-tt|D]\}}|jr,|js,|td|jd|_q|S)zCExpand aliases in a tree, aliases is a list of (name, value) tuplesNs warning: %s T) rbuildmapexpandsortedr iteritemsrwarnedr)raliaseswarnnamealiasrMrMrR expandaliasesbs   rcCst|tr |ddvr |S|ddkrT|g}g}|rM|}|ddkr0|t|ddn|ddvr>||dn td|d}t||sdd |fStd d |DS) z(Fold elements to be concatenated by `##`rrrrNrCrBs#"##" can't concatenate "%s" elementrCcsrrL) foldconcat)rNrrMrMrRrSrzfoldconcat..) r\rpopextendreversedrrrrir)rpendingrqemsgrMrMrRros      rc Csjzt||dWStjy4}z |jdur/|j}|dd}|dd|ddtd|_d}~ww)NrP  rs^ shere)rrrilocationreplacerhint)rrQinstlocrMrMrRrs  "rcCsdtt|S)zQuote a value in order to make it safe for the revset engine. >>> _quote(b'asdf') "'asdf'" >>> _quote(b"asdf'\"") '\'asdf\\\'"\'' >>> _quote(b'asdf\'') "'asdf\\''" >>> _quote(1) "'1'" s'%s')r escapestrr r_)rorMrMrR_quotes rcCs|dkr dt|S|dkrt|S|dkr%t|tstt|d|S|dkr/tt|S|dkrDzt|WStyCtwt t d|) Nds_rev(%d)srVs(%s)nbs&unexpected revspec format character %s) r|rr\r] TypeErrorrrbranchAttributeErrorrrir)rrargrMrMrR_formatargtypes$    rcCst|}|dkr dS|dkrt||dS|dkrt|S|dkr*dtd|S|dkr:d dd d |DS|d krUz d ddd |DWStyTtw|d}dt|d||t||d|fS)Nr _list('')rr r s _list(%s)rr s_hexlist('%s')csrrLrrNrrMrMrRrSrz!_formatlistexp..r s _list('%s')css|]}|VqdSrL)rrrMrMrRrSrr@s (%s or %s))rdr_formatintlistrrrr _formatlistexp)rorrqrrMrMrRrs& (rc Csjz$t|}|dkr WdS|dkrtd|dWSdddd|DWSttfy4ttd w) Nrrrr s_intlist('%s')rcss|] }dt|VqdS)s%dN)r|rrMrMrRrSrTz!_formatintlist..invalid argument for revspec)rdrrr r}rrir)datarqrMrMrRrsrcsdfdd|DS)Ns, c3s|]}t|VqdSrL)rrrrMrRrSsz"_formatparamexp..)r)argsrrMrrR_formatparamexpsr)lpcGstt||}g}|D]+\}}|dur||q |dkr.t|tr$t|}|tt|q td|d |S)a; This is a convenience function for using revsets internally, and escapes arguments appropriately. Aliases are intentionally ignored so that intended expression behavior isn't accidentally subverted. Supported arguments: %r = revset expression, parenthesized %d = rev(int(arg)), no quoting %s = string(arg), escaped and single-quoted %b = arg.branch(), escaped and single-quoted %n = hex(arg), single-quoted %% = a literal '%' Prefixing the type with 'l' specifies a parenthesized list of that type, and 'p' specifies a list of function parameters of that type. >>> formatspec(b'%r:: and %lr', b'10 or 11', (b"this()", b"that()")) '(10 or 11):: and ((this()) or (that()))' >>> formatspec(b'%d:: and not %d::', 10, 20) '_rev(10):: and not _rev(20)::' >>> formatspec(b'%ld or %ld', [], [1]) "_list('') or _rev(1)" >>> formatspec(b'keyword(%s)', b'foo\xe9') "keyword('foo\\xe9')" >>> b = lambda: b'default' >>> b.branch = b >>> formatspec(b'branch(%b)', b) "branch('default')" >>> formatspec(b'root(%ls)', [b'a', b'b', b'c', b'd']) "root(_list('a\\x00b\\x00c\\x00d'))" >>> formatspec(b'sort(%r, %ps)', b':', [b'desc', b'user']) "sort((:), 'desc', 'user')" >>> formatspec(b'%ls', [b'a', b"'"]) "_list('a\\x00\\'')" Nbasesetunknown revspec item type: %rr) _parseargsrr\setrrrrr^r)exprrparsedretrrrMrMrR formatspecs %    r$c Gst||}g}g}|D]*\}}|dur||q |dkr/dt|f}|||dq td|d|}t|td}t j |dg|R}t |}t |}t |}|S) z>> gethashlikesymbols(parse(b'3::abe3ff')) ['3', 'abe3ff'] >>> gethashlikesymbols(parse(b'precursors(.)')) [] >>> gethashlikesymbols(parse(b'precursors(34)')) ['34'] >>> gethashlikesymbols(parse(b'abe3ffZ')) [] rrBrr>N)r:rdgethashlikesymbols)rresultssubtreerMrMrRr;s     r;)NNNrrL)M __future__rstringi18nrr rnoderrr r r utilsr rrjrrgr  iterbytestrrfsysbytes ascii_lettersdigitsr2bytechrxranger`rarvobjectr{rwrzrrrrrrrrrrrrrrrrrrrbasealiasrulesrrrrrrrrrr-r$r'rr1r3r4recompiler7r:r;rMrMrMrRs      )         6 e !   3G