�t�c@s}ddlZddlZddlZddlmZd�Zeeeeeedd�Zeeeeeedd�Z dS(i�N(t_c#s|s
dStjtj�i�d�d����fd�}d�|D���fd���fd���fd������fd �}��}xr|d
krx|tjkr���}q�W|dkr d��gffV���d
7���}q�|dkr}���tj�\}}t|�}x�td|�D]*}d��gffV���d
7�qLWq�|dkr4|dkr���}n||�\}}|g}x2|dkr����\}}|j|�q�Wg|D]} || �^q�d�|
ffV���d
7�q�|dkrd|���\}} || ��q�|dkr�|���\}}��|<d�|ffVq�|dkr�|���\}}d|fVq�|dkrV��}|dkr6d}
��}x#|dkr'|
|7}
��}qWd|
fVq||�\}}
d|
fVq�|dkr�x�|dkr}��}qeWq�|dkr�d���}q�|d
kr�dSd}d}x9|d
kr�dkr�|7}|d
7}��}q�Wtjt d�|��q�WdS( s�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
"<p" sets the default parent to the backref p
"*p" is a fork at parent p, where p is a backref
"*p1/p2/.../pn" is a merge of parents p1..pn, where the pi are backrefs
"/p2/.../pn" is a merge of the preceding node and p2..pn
":name" defines a label for the preceding node; labels can be redefined
"@text" emits an annotation event for text
"!command" emits an action event for the current node
"!!my command
" is like "!", but to the end of the line
"#...
" is a comment up to the end of the line
Whitespace between the above elements is ignored.
A backref is either
* a number n, which references the node curr-n, where curr is the current
node, or
* the name of a label you placed earlier using ":name", or
* empty to denote the default parent.
All string valued-elements are either strictly alphanumeric, or must
be enclosed in double quotes ("..."), with "" as escape character.
Generates sequence of
('n', (id, [parentids])) for node creation
('l', (id, labelname)) for labels on nodes
('a', text) for annotations
('c', command) for actions (!)
('C', command) for line actions (!!)
Examples
--------
Example of a complex graph (output not shown for brevity):
>>> len(list(parsedag("""
...
... +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
... <forkhere # set default parent to labeled fork node
... +10 # 10 more nodes on a parallel branch
... @stable # following nodes will be annotated as "stable"
... +5 # 5 nodes in stable
... !addfile # custom command; could trigger new file in next node
... +2 # two more nodes
... /mergethis # merge last node with labeled node
... +4 # 4 more nodes descending from merge node
...
... """)))
34
Empty list:
>>> list(parsedag(""))
[]
A simple linear run:
>>> list(parsedag("+3"))
[('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [1]))]
Some non-standard ways to define such runs:
>>> list(parsedag("+1+2"))
[('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [1]))]
>>> list(parsedag("+1*1*"))
[('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [1]))]
>>> list(parsedag("*"))
[('n', (0, [-1]))]
>>> list(parsedag("..."))
[('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [1]))]
A fork and a join, using numeric back references:
>>> list(parsedag("+2*2*/2"))
[('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [0])), ('n', (3, [2, 1]))]
>>> list(parsedag("+2<2+1/2"))
[('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [0])), ('n', (3, [2, 1]))]
Placing a label:
>>> list(parsedag("+1 :mylabel +1"))
[('n', (0, [-1])), ('l', (0, 'mylabel')), ('n', (1, [0]))]
An empty label (silly, really):
>>> list(parsedag("+1:+1"))
[('n', (0, [-1])), ('l', (0, '')), ('n', (1, [0]))]
Fork and join, but with labels instead of numeric back references:
>>> list(parsedag("+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("+1:f +1:p2 <f +1 /p2"))
[('n', (0, [-1])), ('l', (0, 'f')), ('n', (1, [0])), ('l', (1, 'p2')),
('n', (2, [0])), ('n', (3, [2, 1]))]
Restarting from the root:
>>> list(parsedag("+1 $ +1"))
[('n', (0, [-1])), ('n', (1, [-1]))]
Annotations, which are meant to introduce sticky state for subsequent nodes:
>>> list(parsedag("+1 @ann +1"))
[('n', (0, [-1])), ('a', 'ann'), ('n', (1, [0]))]
>>> list(parsedag('+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("+1 !cmd +1"))
[('n', (0, [-1])), ('c', 'cmd'), ('n', (1, [0]))]
>>> list(parsedag('+1 !"my command" +1'))
[('n', (0, [-1])), ('c', 'my command'), ('n', (1, [0]))]
>>> list(parsedag('+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('+1 # comment\n+1'))
[('n', (0, [-1])), ('n', (1, [0]))]
Error:
>>> try: list(parsedag('+1 bad'))
... except Exception, e: print e
invalid character in dag description: bad...
Ni�ics7|s
�S|dtjkr+�t|�S�|SdS(Ni(tstringtdigitstint(tref(tlabelstp1tr(s7/sys/lib/python2.7/site-packages/mercurial/dagparser.pytresolve�s
css|]}|VqdS(N((t.0tc((s7/sys/lib/python2.7/site-packages/mercurial/dagparser.pys <genexpr>�scs'y�j�SWntk
r"dSXdS(Nt(tnextt
StopIteration((tchiter(s7/sys/lib/python2.7/site-packages/mercurial/dagparser.pytnextch�s
cs6d}x#||kr+||7}��}q W||fS(Nt((R
tallowts(R(s7/sys/lib/python2.7/site-packages/mercurial/dagparser.pytnextrun�s
csQd}x;||krC||kr-��}n||7}��}q W��|fS(NR((R
tlimittescapeR(R(s7/sys/lib/python2.7/site-packages/mercurial/dagparser.pyt
nextdelimited�s
cs0|dkr���dd�S�|��SdS(Nt"s\((R
(RRRt wordchars(s7/sys/lib/python2.7/site-packages/mercurial/dagparser.pyt
nextstring�sRt.tnit+s*/t*t/t<t:tlt@tat!Rs
tCR
t#t$i
s+invalid character in dag description: %s...(
Rt
ascii_lettersRt
whitespaceRtxrangetappendtutiltAbortR(tdescRRR
tdigsRtitpreftprefsRtpstnamettexttcmdR((RRRRRRRRs7/sys/lib/python2.7/site-packages/mercurial/dagparser.pytparsedags��
iFc#s�d���������fd�}d} x�|�D]�}
|
dkrc| r�| Vd} q�q:t| �t|
�|kr�| Vd} n%|r�| r�|
dkr�| d7} n| |
7} q:W| r�| VndS(s$generates single lines for dagtext()cSs:tjd|�r|Sd|jdd�jdd�dS(Ns^[0-9a-z]*$Rs\s\\(tretmatchtreplace(R5((s7/sys/lib/python2.7/site-packages/mercurial/dagparser.pyt
wrapstringsc
3sZi}d}d}t}x#�D]\}}|dkr)|\}}||krqtjtd�||f��n|s�dg}n?x<|D]4}||kr�tjtd�||f��q�q�W|d7}|d} t|�dkrA|ddkrA|r8|rdt|�Vd}n�r*dVnd Vd} qAt}nt|�dkr~|d| kr~�rqd
Vq&|d7}q:|r�dt|�Vd}n�r�dVng}
xa|D]Y}|| kr�|
jd�q�||kr�j||�q�|
jt||��q�Wdd
j|
�Vq|rGdt|�Vd}n|dkr�|\}}|||<d|V�r:dVq:q|dkr�d�|�V�r:dVq:q|dkr�d|VdVq|dkr�r�Vnd�|�Vq|dkrd|VdVqtjtd�tt |f���qW|rVdt|�VndS(NiRsexpected id %i, got %ii�s)parent id %i is larger than current id %iiRs
R'RRRRR!R R
R$R%s!!R#R"R&sinvalid event type in dag: %s(
tFalseR,R-RtlentstrtTrueR+tjointtype(
RtruntwantrtneedroottkindtdataRR3tpRR2tridR4(teventstusedotstwrapannotationstwrapcommandst
wraplabelst
wrapnonlinearR;(s7/sys/lib/python2.7/site-packages/mercurial/dagparser.pytgen!s�"
" "
Rs
Rt N(R=(RIt addspacesRMRKRLRNRJtmaxlinewidthROtlinetpart((RIRJRKRLRMRNR;s7/sys/lib/python2.7/site-packages/mercurial/dagparser.pytdagtextliness
!T
c
Cs(djt||||||||��S(sgenerates lines of a textual representation for a dag event stream
events should generate what parsedag() does, so:
('n', (id, [parentids])) for node creation
('l', (id, labelname)) for labels on nodes
('a', text) for annotations
('c', text) for commands
('C', text) for line commands ('!!')
('#', text) for comment lines
Parent nodes must come before child nodes.
Examples
--------
Linear run:
>>> dagtext([('n', (0, [-1])), ('n', (1, [0]))])
'+2'
Two roots:
>>> dagtext([('n', (0, [-1])), ('n', (1, [-1]))])
'+1 $ +1'
Fork and join:
>>> dagtext([('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [0])),
... ('n', (3, [2, 1]))])
'+2 *2 */2'
Fork and join with labels:
>>> dagtext([('n', (0, [-1])), ('l', (0, 'f')), ('n', (1, [0])),
... ('l', (1, 'p2')), ('n', (2, [0])), ('n', (3, [2, 1]))])
'+1 :f +1 :p2 *f */p2'
Annotations:
>>> dagtext([('n', (0, [-1])), ('a', 'ann'), ('n', (1, [0]))])
'+1 @ann +1'
>>> dagtext([('n', (0, [-1])),
... ('a', 'my annotation'),
... ('n', (1, [0]))])
'+1 @"my annotation" +1'
Commands:
>>> dagtext([('n', (0, [-1])), ('c', 'cmd'), ('n', (1, [0]))])
'+1 !cmd +1'
>>> dagtext([('n', (0, [-1])), ('c', 'my command'), ('n', (1, [0]))])
'+1 !"my command" +1'
>>> dagtext([('n', (0, [-1])),
... ('C', 'my command line'),
... ('n', (1, [0]))])
'+1 !!my command line\n+1'
Comments:
>>> dagtext([('n', (0, [-1])), ('#', ' comment'), ('n', (1, [0]))])
'+1 # comment\n+1'
>>> dagtext([])
''
Combining parsedag and dagtext:
>>> dagtext(parsedag('+1 :f +1 :p2 *f */p2'))
'+1 :f +1 :p2 *f */p2'
s
(R@RU(tdagRQRMRKRLRNRJRR((s7/sys/lib/python2.7/site-packages/mercurial/dagparser.pytdagtext�sS(
R8RR,ti18nRR7R?R<RURW(((s7/sys/lib/python2.7/site-packages/mercurial/dagparser.pyt<module>s$ �m
|