^cU<pddlZddlZddlmZddlmZmZddlmZdZ d d Z d d Z dS) N)_)errorpycompat) stringutilc#nK|sdStjtjtjziddfdtj|fdfdfdfd}}|d kr|tjtjvr*}|tjtjv*|d krd gffVd z }n<|d krgtjtj\}}t|}td|D]}d gffVd z n|dvrw|dkr }||\}}|g}|dkr1|\}}| ||dk1fd|D}d |ffVd z nT|dkr#|\}} | n+|dkr%|\}} | <d| ffVn|dkr|\}} d| fVn|dkrO}|dkr*d} }|dvr| |z } }|dvd| fVn||\}} d| fVn|dkr|dvr}|dvno|dkr d}n\|d krdSd} d}|d kr&|dkr | |z } |d z }}|d kr|dk tj td| z|d kdSdS) a#parses a DAG from a concise textual description; generates events "+n" is a linear run of n nodes based on the current default parent "." is a single node based on the current default parent "$" resets the default parent to -1 (implied at the start); otherwise the default parent is always the last node created ">> len(list(parsedag(b""" ... ... +3 # 3 nodes in linear run ... :forkhere # a label for the last of the 3 nodes from above ... +5 # 5 more nodes on one branch ... :mergethis # label again ... >> list(parsedag(b"")) [] A simple linear run: >>> list(parsedag(b"+3")) [('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [1]))] Some non-standard ways to define such runs: >>> list(parsedag(b"+1+2")) [('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [1]))] >>> list(parsedag(b"+1*1*")) [('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [1]))] >>> list(parsedag(b"*")) [('n', (0, [-1]))] >>> list(parsedag(b"...")) [('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [1]))] A fork and a join, using numeric back references: >>> list(parsedag(b"+2*2*/2")) [('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [0])), ('n', (3, [2, 1]))] >>> list(parsedag(b"+2<2+1/2")) [('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [0])), ('n', (3, [2, 1]))] Placing a label: >>> list(parsedag(b"+1 :mylabel +1")) [('n', (0, [-1])), ('l', (0, 'mylabel')), ('n', (1, [0]))] An empty label (silly, really): >>> list(parsedag(b"+1:+1")) [('n', (0, [-1])), ('l', (0, '')), ('n', (1, [0]))] Fork and join, but with labels instead of numeric back references: >>> list(parsedag(b"+1:f +1:p2 *f */p2")) [('n', (0, [-1])), ('l', (0, 'f')), ('n', (1, [0])), ('l', (1, 'p2')), ('n', (2, [0])), ('n', (3, [2, 1]))] >>> list(parsedag(b"+1:f +1:p2 >> list(parsedag(b"+1 $ +1")) [('n', (0, [-1])), ('n', (1, [-1]))] Annotations, which are meant to introduce sticky state for subsequent nodes: >>> list(parsedag(b"+1 @ann +1")) [('n', (0, [-1])), ('a', 'ann'), ('n', (1, [0]))] >>> list(parsedag(b'+1 @"my annotation" +1')) [('n', (0, [-1])), ('a', 'my annotation'), ('n', (1, [0]))] Commands, which are meant to operate on the most recently created node: >>> list(parsedag(b"+1 !cmd +1")) [('n', (0, [-1])), ('c', 'cmd'), ('n', (1, [0]))] >>> list(parsedag(b'+1 !"my command" +1')) [('n', (0, [-1])), ('c', 'my command'), ('n', (1, [0]))] >>> list(parsedag(b'+1 !!my command line\n +1')) [('n', (0, [-1])), ('C', 'my command line'), ('n', (1, [0]))] Comments, which extend to the end of the line: >>> list(parsedag(b'+1 # comment\n+1')) [('n', (0, [-1])), ('n', (1, [0]))] Error: >>> try: list(parsedag(b'+1 bad')) ... except Exception as e: print(pycompat.sysstr(bytes(e))) invalid character in dag description: bad... Nrc|sS|dtjtjvrt |z S|S)Nr)rbytestrstringdigitsint)reflabelsp1rs 5/usr/lib/python3/dist-packages/mercurial/dagparser.pyresolvezparsedag..resolvesF I Vx' 66 6 6s3xx< #; c$tdS)N)next)chitersrnextchzparsedag..nextchsFE"""rc>d}||vr||z }}||v||fSNr)callowsrs rnextrunzparsedag..nextruns; 5jj FAA5jj!t rcvd}||kr%||kr }||z }}||k%|fSrr)rlimitescaper rs r nextdelimitedzparsedag..nextdelimitedsV 5jjF{{FHH FAA 5jj vxx{rcR|dkrddS|S)N"\r)rrr%r! wordcharss r nextstringzparsedag..nextstrings8 99 =477 771i(( (rr.nr+s*/*/c&g|] }|Srr).0rrs r zparsedag..s!0003''#,,000r<:l@a!rs Cc#$ s+invalid character in dag description: %s...) rr r ascii_lettersr iterbytestr whitespacerrangeappendrAbortr)descr*rdigsniprefprefspsrnametextcmdr rrrr%r!rrrr)s @@@@@@@@@rparsedagrNsf  !5 !EFFIF B A !$ ' 'F#####)))))))) A u**8#F$56666A8#F$56666 99RD / ! ! !B FAAA $YYgffhh(8(G(GHHGAtD A1a[[  QIo%%%Q %ZZDyyFHH jmmGAtFEt))$*VVXX..4 T"""t))1000%000BB-   B FAA $YYZ))FAsBB $YY j**GAtF4LT " " " " " $YY j**GAt*     $YYADyyFHHy((1HCAy((Ci#A3Ci $YY9$$FHH9$$ $YYBAA %ZZ FAAu**RQQFHHu**R+@AAAE I u******rTFFc# Kd  fd}d} |D]O} | dkr | r| Vd} t| t| z|kr| Vd} n|r | r | dkr| dz } | | z } P| r| VdSdS)z$generates single lines for dagtext()ctjd|r|Sd|ddddzdzS)Ns ^[0-9a-z]*$r'r(s\\)rematchreplace)rLs r wrapstringz dagtextlines..wrapstring-sI 8ND ) ) Kdll5'22::4GGG$NNrc3Ki}d}d}d} D]E\}}|dkrd|\}}||kr&tjtd||fz|sdg}n1|D].}||kr&tjtd||fz/|dz }|dz } t|dkr(|ddkr|r|r d|zVd}rd Vd Vd} nd }t|dkr|d| kr rd V|dz }|r d|zVd}rd Vg} |D]Y}|| kr| d ||vr| ||>| d||z zZdd| zVq|r d|zVd}|dkr|\} } | || <d| zVrd V|dkrd|zVrd V|dkr d|zVd V|dkrrd Vd|zV|dkr d|zVd Vtjtdt j|t j|fz|r d|zVdSdS)NrFr,sexpected id %i, got %ir s)parent id %i is larger than current id %irs+%d r<Tr+rs%dr.r/r5r4r:r8r9s!!r7r6r;s'invalid event type in dag: ('%s', '%s'))rrCrlenrBjoinr escapestr)rrunwantrneedrootkinddatarrJprrIridrKeventsusedotswrapannotations wrapcommands wraplabels wrapnonlinearrUs rgenzdagtextlines..gen2s U U JD$t||2::+a(A&B&BeQZ&OPPP BB66"'+ !%5!"!"$%a& !)##" Ur77a<>> dagtext([(b'n', (0, [-1])), (b'n', (1, [0]))]) '+2' Two roots: >>> dagtext([(b'n', (0, [-1])), (b'n', (1, [-1]))]) '+1 $ +1' Fork and join: >>> dagtext([(b'n', (0, [-1])), (b'n', (1, [0])), (b'n', (2, [0])), ... (b'n', (3, [2, 1]))]) '+2 *2 */2' Fork and join with labels: >>> dagtext([(b'n', (0, [-1])), (b'l', (0, b'f')), (b'n', (1, [0])), ... (b'l', (1, b'p2')), (b'n', (2, [0])), (b'n', (3, [2, 1]))]) '+1 :f +1 :p2 *f */p2' Annotations: >>> dagtext([(b'n', (0, [-1])), (b'a', b'ann'), (b'n', (1, [0]))]) '+1 @ann +1' >>> dagtext([(b'n', (0, [-1])), ... (b'a', b'my annotation'), ... (b'n', (1, [0]))]) '+1 @"my annotation" +1' Commands: >>> dagtext([(b'n', (0, [-1])), (b'c', b'cmd'), (b'n', (1, [0]))]) '+1 !cmd +1' >>> dagtext([(b'n', (0, [-1])), ... (b'c', b'my command'), ... (b'n', (1, [0]))]) '+1 !"my command" +1' >>> dagtext([(b'n', (0, [-1])), ... (b'C', b'my command line'), ... (b'n', (1, [0]))]) '+1 !!my command line\n+1' Comments: >>> dagtext([(b'n', (0, [-1])), (b'#', b' comment'), (b'n', (1, [0]))]) '+1 # comment\n+1' >>> dagtext([]) '' Combining parsedag and dagtext: >>> dagtext(parsedag(b'+1 :f +1 :p2 *f */p2')) '+1 :f +1 :p2 *f */p2' rW)rYrn)dagrjrfrdrergrcrks rdagtextrqs@n ::            r)TFFFFFrO) rRr i18nrrrutilsrrNrnrqrrrrus JJJ^ }}}}D bbbbbbr