B
    Mœt\{9  ã               @   s¢   d Z ddlZddlZddlZddlZddlZddlmZmZ ddlm	Z	 ddlm
Z ddlmZmZ dZG dd	„ d	ejƒZG d
d„ dƒZdd„ ZG dd„ dƒZdS )zµ
module defining a subversion path object based on the external
command 'svn'. This modules aims to work with svn 1.3 and higher
but might also interact well with earlier versions.
é    N)ÚpathÚprocess)Úcommon)Úsvnwc)ÚBuildcostAccessCacheÚ
AgingCacheFc               @   sô   e Zd ZdZeddZedddZd>dd	„Zd
d„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd?dd„Zdd „ Zd!d"„ Zd@d$d%„ZdAd'd(„ZdBd+d,„Zd-d.„ Zd/d0„ Zd1d2„ Zd3d4„ Zd5d6„ Zd7d8„ ZdCd9d:„ZdDd<d=„ZdS )EÚSvnCommandPathzZ path implementation that offers access to (possibly remote) subversion
    repositories. é€   )Ú
maxentriesiè  g      N@)r
   Z
maxsecondsNc             C   sP   t  | ¡}t|| ƒr&|j}|j}|j}t |¡ | d¡}||_||_||_|S )Nú/)	ÚobjectÚ__new__Ú
isinstanceÚrevÚauthÚstrpathÚ	svncommonZcheckbadcharsÚrstrip)Úclsr   r   r   Úself© r   ú.lib/python3.7/site-packages/py/_path/svnurl.pyr      s    



zSvnCommandPath.__new__c             C   s(   | j dkrd| j S d| j| j f S d S )Néÿÿÿÿz
svnurl(%r)zsvnurl(%r, %r))r   r   )r   r   r   r   Ú__repr__$   s    

zSvnCommandPath.__repr__c             G   s@   | j dkr| j|f|žŽ S d| j gt|ƒ }| j|f|žŽ S dS )z9 execute an svn command, append our own url and revision Nz-r)r   Ú	_svnwriteÚlist)r   ÚcmdÚargsr   r   r   Ú_svnwithrev*   s    
zSvnCommandPath._svnwithrevc                s`   d| g}‡ fdd„|D ƒ}|  |¡ | dˆ  ¡  ¡ d |¡}trRtd| ƒ ˆ  |¡}|S )z, execute an svn command, append our own url zsvn %sc                s   g | ]}d ˆ   |¡ ‘qS )z"%s")Ú_escape)Ú.0Úitem)r   r   r   ú
<listcomp>5   s    z,SvnCommandPath._svnwrite.<locals>.<listcomp>z"%s"ú z
execing %s)ÚextendÚappendÚ_encodedurlÚjoinÚDEBUGÚprintÚ_svncmdexecauth)r   r   r   ÚlÚstringÚoutr   )r   r   r   2   s    



zSvnCommandPath._svnwritec             C   s2   t  ¡ | }| jdk	r(|d| j ¡  7 }|  |¡S )z  execute an svn command 'as is' Nr#   )r   Ú	fixlocaler   ÚmakecmdoptionsÚ_cmdexec)r   r   r   r   r   r*   ?   s    
zSvnCommandPath._svncmdexecauthc             C   sh   yt  |¡}W nT tj jjk
rb   t ¡ d }|j d¡dksP|j d¡dkr\tj 	| ¡‚‚ Y nX |S )Né   zFile Existsr   zFile already exists)
r   ÚcmdexecÚpyÚErrorÚsysÚexc_infoÚerrÚfindÚerrorZEEXIST)r   r   r-   Úer   r   r   r0   F   s    zSvnCommandPath._cmdexecc             C   s2   t  ¡ | }| jdk	r(|d| j ¡  7 }|  |¡S )z9 execute an svn command, return a pipe for reading stdin Nr#   )r   r.   r   r/   Ú_popen)r   r   r   r   r   Ú_svnpopenauthQ   s    
zSvnCommandPath._svnpopenauthc             C   s
   t  |¡S )N)ÚosÚpopen)r   r   r   r   r   r;   X   s    zSvnCommandPath._popenc             C   s   |   | j¡S )N)r   r   )r   r   r   r   r&   [   s    zSvnCommandPath._encodedurlc             C   s,   | j r| j  ¡ pd }| j t|ƒ|f¡ d S )N)r   r/   Ú_lsnorevcacheZdelentryÚstr)r   r   r   r   r   r   Ú_norev_delentry^   s    zSvnCommandPath._norev_delentryÚrc             C   sh   |dkrt d|f ƒ‚| jdds&t‚| jdkrH|  d|  | j¡f ¡S |  d| j|  | j¡f ¡S dS )z, return an opened file with the given mode. )rB   ZrUzmode %r not supportedr1   )ÚfileNzsvn cat "%s"zsvn cat -r %s "%s")Ú
ValueErrorÚcheckÚAssertionErrorr   r<   r   r   )r   Úmoder   r   r   Úopenb   s    
zSvnCommandPath.openc             O   sZ   | j  | j¡}t|ƒdk r*tj | d¡‚n,t|ƒdkrB| j||ŽS | jddj||ŽS dS )zi return the directory path of the current path joined
            with any given path arguments.
        é   zbase is not validÚ )ÚbasenameN)	r   ÚsplitÚsepÚlenr3   r9   ÚEINVALr'   Únew)r   r   Úkwargsr+   r   r   r   Údirpathn   s    zSvnCommandPath.dirpathc             O   s6   |  dd¡}| j|Ž }| dd|¡ |  | ¡ ¡ |S )zz create & return the directory joined with args.
        pass a 'msg' keyword argument to set the commit message.
        Úmsgzmkdir by py lib invocationÚmkdirz-m)Úgetr'   r   rA   rR   )r   r   rQ   Z
commit_msgZ
createpathr   r   r   rT   {   s
    
zSvnCommandPath.mkdirúcopied by py lib invocationc             C   sP   t |ddƒdk	rtj |d¡‚|  d||  | ¡|  |¡f ¡ |  | ¡ ¡ dS )z. copy path to target with checkin message msg.r   Nzrevisions are immutablezsvn copy -m "%s" "%s" "%s")Úgetattrr3   r9   rO   r*   r   rA   rR   )r   ÚtargetrS   r   r   r   Úcopy…   s
    zSvnCommandPath.copyúrenamed by py lib invocationc             C   sZ   t | ddƒdk	rtj | d¡‚|  d||  | ¡|  |¡f ¡ |  |  ¡ ¡ |  | ¡ dS )z6 rename this path to target with checkin message msg. r   Nzrevisions are immutablez"svn move -m "%s" --force "%s" "%s")rW   r3   r9   rO   r*   r   rA   rR   )r   rX   rS   r   r   r   Úrename   s    zSvnCommandPath.renamer1   úremoved by py lib invocationc             C   sB   | j dk	rtj | d¡‚|  d||  | ¡f ¡ |  |  ¡ ¡ dS )zT remove a file or directory (or a directory tree if rec=1) with
checkin message msg.Nzrevisions are immutablezsvn rm -m "%s" "%s")r   r3   r9   rO   r*   r   rA   rR   )r   ZrecrS   r   r   r   Úremove–   s    
zSvnCommandPath.removec             C   sb   t j |¡}d|  | ¡f d|  |¡f g}| jdk	rHdt| jƒg| }|  dd |¡f ¡ |S )z‰ export to a local path

            topath should not exist prior to calling this, returns a
            py.path.local instance
        z"%s"Nz-rzsvn export %sr#   )r3   r   Úlocalr   r   r@   r*   r'   )r   Ztopathr   r   r   r   Úexportž   s    
zSvnCommandPath.exportc       
      O   s"  t | ddƒdk	rtj | d¡‚| j|Ž }| dd¡}x,|jddD ]}| ¡ rBP qBW tj |d¡‚||kr–|j|d	s’|r†tj 	|¡ptj 
|¡‚|S | |¡}| | jd
¡d }tjj ¡ }zT|j||d	 dd|  |¡ |  | |¡¡| |¡ ¡ f }	|  |	¡ |  |¡ W d| ¡  X |S )z½ ensure that an args-joined path exists (by default as
            a file). If you specify a keyword argument 'dir=True'
            then the path is forced to be a directory path.
        r   Nzrevisions are immutableÚdirr   T)Úreversezhas not any valid base!)r`   r1   zsvn import -m "%s" "%s" "%s"z	ensure %s)rW   r3   r9   rO   r'   rU   ÚpartsrE   ÚENOENTÚENOTDIRZEISDIRZreltorL   rM   r   r^   ZmkdtempÚensurer   r&   r*   rA   r]   )
r   r   rQ   rX   r`   ÚxZtocreaterK   Ztempdirr   r   r   r   re   ¬   s2    



zSvnCommandPath.ensurec             C   s   |   d|¡}|d d… S )NZpropgetr   )r   )r   ÚnameÚresr   r   r   Ú_propgetÎ   s    zSvnCommandPath._propgetc             C   s6   |   d¡}| d¡}dd„ |dd … D ƒ}t | |¡S )NZproplistÚ
c             S   s   g | ]}|  ¡ ‘qS r   )Ústrip)r    rf   r   r   r   r"   Õ   s    z,SvnCommandPath._proplist.<locals>.<listcomp>r1   )r   rL   r   ZPropListDict)r   rh   Úlinesr   r   r   Ú	_proplistÒ   s    

zSvnCommandPath._proplistc             C   sD   |   ¡ }| ¡ }| j}x|D ]\}}||kr|S qW tj | ¡‚dS )z9 return an Info structure with svn-provided information. N)rR   Ú_listdir_nameinforK   r3   r9   rc   )r   ÚparentÚnameinfo_seqZbnrg   Úinfor   r   r   rq   Ø   s    zSvnCommandPath.infoc                sZ   ‡ fdd„}ˆ j rˆ j  ¡ pd}ˆ jdk	rBˆ j ˆ jˆ j|f|¡S ˆ j ˆ j|f|¡S dS )z8 return sequence of name-info directory entries of self c                 sl  yˆ   dd¡} W n tjjk
r   t ¡ d }|j d¡dkrVtj	 
ˆ |j¡‚n®|j d¡dkrxtj	 
ˆ |j¡‚nŒ|j d¡dkrštj	 
ˆ |j¡‚nj|j d¡dkr¼tj	 
ˆ |j¡‚nH|j d	¡dkrÞtj	 
ˆ |j¡‚n&|j ¡  d
¡dkrtj	 ˆ |j¡‚tj	 |j¡‚Y nX |  d¡}g }x8|D ]0}|r,t|ƒ}|jdkr,| |j|f¡ q,W | ¡  |S )NZlsz-vr1   znon-existent in that revisionr   zE200009:zFile not foundznot part of a repositoryzUnable to openzmethod not allowedrj   Ú.)r   r   r2   r4   r5   r6   r7   r8   r3   r9   rc   ÚlowerZEACCESrL   ÚInfoSvnCommandÚ_namer%   Úsort)rh   r:   rl   rp   Zlslinerq   )r   r   r   Úbuilderå   s4    

z1SvnCommandPath._listdir_nameinfo.<locals>.builderN)r   r/   r   Ú_lsrevcacheZ
getorbuildr   r?   )r   rw   r   r   )r   r   rn   ã   s    
z SvnCommandPath._listdir_nameinfoc                sŒ   t ˆ tƒrt ˆ ¡‰ ˆ ¡ }t|ƒdkrT|d \}}|ˆjkrT|jdkrTtj	 
ˆ¡‚‡fdd„|D ƒ}ˆ r|‡ fdd„|D ƒ}ˆ ||¡ |S )zi list directory contents, possibly filter by the given fil func
            and possibly sorted.
        r1   r   rC   c                s   g | ]\}}ˆ   |¡‘qS r   )r'   )r    rg   rq   )r   r   r   r"     s    z*SvnCommandPath.listdir.<locals>.<listcomp>c                s   g | ]}ˆ |ƒr|‘qS r   r   )r    rf   )Úfilr   r   r"     s    )r   r@   r   Z	FNMatcherrn   rN   rK   Úkindr3   r9   rd   Z	_sortlist)r   ry   rv   rp   rg   rq   Úpathsr   )ry   r   r   Úlistdir  s    

zSvnCommandPath.listdirFc             C   sÂ   |   ¡ st‚|dkrdp|}|dkr(dp*|}|dkrB|dkrBd}nd||f }|rVdpXd}|  d||| jf ¡}dd	lm} | |¡}g }	x2td|jj	ƒD ] }
|
j
|
jkrš|	 t |
¡¡ qšW |	S )
zø return a list of LogEntry instances for this path.
rev_start is the starting revision (defaulting to the first one).
rev_end is the last revision (defaulting to HEAD).
if verbose is True, then the LogEntry instances also know which files changed.
NZHEADr1   rJ   z-r %s:%sz-vzsvn log --xml %s %s "%s"r   )Úminidom)rE   rF   r<   r   Zxml.domr}   ÚparseÚfilterÚ
firstChildZ
childNodesZnodeTypeZELEMENT_NODEr%   r   ZLogEntry)r   Z	rev_startZrev_endÚverboseZrev_optZverbose_optZxmlpiper}   ZtreeÚresultZlogentryr   r   r   Úlog  s     
zSvnCommandPath.log)NN)rB   )rV   )rZ   )r1   r\   )NN)Nr1   F) Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   rx   r   r?   r   r   r   r   r*   r0   r<   r;   r&   rA   rH   rR   rT   rY   r[   r]   r_   re   ri   rm   rq   rn   r|   rƒ   r   r   r   r   r      s6   





	
"%
r   c               @   s&   e Zd Ze d¡Zdd„ Zdd„ ZdS )rt   zc^ *(?P<rev>\d+) +(?P<author>.+?) +(0? *(?P<size>\d+))? *(?P<date>\w+ +\d{2} +[\d:]+) +(?P<file>.*)$c             C   sš   | j  |¡}| ¡ }|d | _| jd dkrD| jd d… | _d| _nd| _t|d ƒ| _|d | _|d rvt|d ƒpxd| _t	|d	 ƒ| _
| j
d
 | _d S )NrC   r   r   r`   r   ZauthorÚsizer   Zdatei@B )Ú	lspatternÚmatchÚ	groupdictru   rz   ÚintZcreated_revZlast_authorrˆ   Úparse_time_with_missing_yearÚmtimeÚtime)r   ÚlinerŠ   Údatar   r   r   Ú__init__?  s    

zInfoSvnCommand.__init__c             C   s   | j |j kS )N)Ú__dict__)r   Úotherr   r   r   Ú__eq__Q  s    zInfoSvnCommand.__eq__N)r„   r…   r†   ÚreÚcompiler‰   r’   r•   r   r   r   r   rt   9  s   rt   c             C   sô   ddl }t ¡ }|  ¡ }t | d¡d¡d }t | d¡d¡d }| d¡}y*d|kr^tƒ ‚t |d¡d }d }}	W nZ tk
rÒ   t |d	¡d
d… \}}	|d }|||||	ddddf	}
|
|krÎ|d8 }Y nX |||||	ddddf	}
| |
¡S )zˆ analyze the time part from a single line of "svn ls -v"
    the svn output doesn't show the year makes the 'timestr'
    ambigous.
    r   Nz%br1   z%dé   ú:z%Yz%H:%Mé   é   )Úcalendarr   ZgmtimerL   ZstrptimeÚpoprD   Ztimegm)Ztimestrrœ   Zt_nowZtpartsZmonthZdayZlastZyearZhourZminuteZt_resultr   r   r   r   Y  s&    
r   c               @   s   e Zd Zdd„ ZdS )Ú	PathEntryc             C   sX   |j j d¡| _| d¡ d¡| _| jdkrT| d¡ d¡| _| jrTt| d¡ƒ| _d S )NzUTF-8ÚactionÚAzcopyfrom-pathzcopyfrom-rev)	r€   Z	nodeValueÚencoder   ZgetAttributerŸ   Zcopyfrom_pathrŒ   Zcopyfrom_rev)r   Zppartr   r   r   r’   u  s    
zPathEntry.__init__N)r„   r…   r†   r’   r   r   r   r   rž   t  s   rž   )r‡   r=   r5   r   r–   r3   r   r   Zpy._pathr   r   r   Zpy._path.cacheutilr   r   r(   ZSvnPathBaser   rt   r   rž   r   r   r   r   Ú<module>   s      + 