a
    &0_g                  
   @   s@  d dl mZ d dlZddlmZmZmZmZ ddlm	Z	m
Z
mZmZmZ ddlmZmZ ejrd dlmZmZmZmZmZmZmZmZmZ eeeeeeeeeef	sJ ejZejZejZej Z G dd	 d	e!Z"d
d Z#dd Z$G dd de!Z%G dd de%Z&dZ'de' Z(de' Z)dZ*ee*Z+dZ,dZ-dZ.G dd de!Z/dS )    )absolute_importN   )binhexnullidnullrev)encodingerrorpycompatscmutilutil)repoviewutil
stringutil)	AnyCallableDictIterableListOptionalSetTupleUnionc                   @   s8   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdS )BranchMapCachez8mapping of filtered views of repo with their branchcachec                 C   s
   i | _ d S N)_per_filterself r   5/usr/lib/python3/dist-packages/mercurial/branchmap.py__init__9   s    zBranchMapCache.__init__c                 C   s   |  | | j|j S r   )updatecacher   
filternamer   repor   r   r   __getitem__<   s    
zBranchMapCache.__getitem__c                    s   |j }|j}| j|  du s* |s4t| g } du rt|}|dur||}| | 	  |j j
|j
 }| fdd|D  nt  ||j jd d |r ||  |sJ | | j|j< dS )z<Update the cache for the given filtered view on a repositoryNc                 3   s   | ]}| j kr|V  qd S r   )tiprev).0rbcacher   r   	<genexpr>W       z-BranchMapCache.updatecache.<locals>.<genexpr>r   )start)	changelogr!   r   getvalidforbranchcachefromfilesubsettablefilteredcopyZfilteredrevsextendrevsr%   update)r   r#   clr!   r6   Z
subsetnameZsubsetZ	extrarevsr   r(   r   r    @   s&    


zBranchMapCache.updatecachec                    s   |j }|j |j}g }t }t|D ]8}||7 }|D ]&} |}	||	\}
}|r6|| q6q&|rt fdd|D }t||| 	 ||d}dD ]2}|
|}||r|| j|< ||  dS qdS )zReplace the branchmap cache for a repo with a branch mapping.

        This is likely only called during clone with a branch map from a
        remote.

        c                 3   s   | ]}t  |V  qd S r   )intr&   nodeZclrevr   r   r*   x   r+   z)BranchMapCache.replace.<locals>.<genexpr>)closednodes)s   bases	   immutables   servedN)r-   rev
branchinfosetr
   
itervaluesaddmaxr0   r;   r3   r/   r   write)r   r#   Zremotebranchmapr8   ZclbranchinfoZrbheadsclosedbheadshr'   bcZrtiprevcache	candidateZrviewr   r<   r   replacec   s4    
	



zBranchMapCache.replacec                 C   s   | j   d S r   )r   clearr   r   r   r   rM      s    zBranchMapCache.clearN)	__name__
__module____qualname____doc__r   r$   r    rL   rM   r   r   r   r   r   6   s   #&r   c                 C   s   t dtt|  dS )zK raises ValueError when branchcache found a node which does not exists
    znode %s does not existN)
ValueErrorr
   Zsysstrr   r;   r   r   r   _unknownnode   s    rT   c                 C   s   | j d urd| j  S dS d S )Ns   branch cache (%s)s   branch cacher!   )r#   r   r   r   _branchcachedesc   s    

rV   c                   @   s   e Zd ZdZdeedddf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eZdd Zedd Zdd Zedd Zdd Zd d! Zd"d# Zd$d% Zd3d'd(Zd)d* Zd+d, Zd-d. Zd/d0 Zd1d2 ZdS )4r0   a/  A dict like object that hold branches heads cache.

    This cache is used to avoid costly computations to determine all the
    branch heads of a repo.

    The cache is serialized on disk in the following format:

    <tip hex node> <tip rev number> [optional filtered repo hex hash]
    <branch head hex node> <open/closed state> <branch name>
    <branch head hex node> <open/closed state> <branch name>
    ...

    The first line is used to check if the cache is still valid. If the
    branch cache is for a filtered repo view, an optional third hash is
    included that hashes the hashes of all filtered revisions.

    The open/closed state is represented by a single letter 'o' or 'c'.
    This field can be used to avoid changelog reads when determining if a
    branch head closes a branch or not.
    r   Nc                 C   s`   || _ || _|| _|du r$t | _n|| _t|| _d| _t | _|| _	| j	du r\dd | _	dS )z hasnode is a function which can be used to verify whether changelog
        has a given node or not. If it's not provided, we assume that every node
        we have exists in changelog NFc                 S   s   dS )NTr   )xr   r   r   <lambda>   r+   z&branchcache.__init__.<locals>.<lambda>)
tipnoder%   filteredhashr@   _closednodesdict_entries_closedverified_verifiedbranches_hasnode)r   entriesrY   r%   rZ   r=   hasnoder   r   r   r      s    


zbranchcache.__init__c                 C   s2   | j r
dS | jD ]}| |st| qd| _ dS )z! verify the closed nodes we have NT)r^   r[   r`   rT   )r   r;   r   r   r   _verifyclosed   s    


zbranchcache._verifyclosedc                 C   sJ   || j vs|| jv rdS | j | D ]}| |s"t| q"| j| dS )z) verify head nodes for the given branch. N)r]   r_   r`   rT   rB   )r   branchnr   r   r   _verifybranch   s    

zbranchcache._verifybranchc                 C   s,   t | j | j }|D ]}| | qdS )z$ verifies nodes of all the branches N)r@   r]   keysr_   rf   )r   ZneedverificationrH   r   r   r   
_verifyall   s    zbranchcache._verifyallc                 C   s
   t | jS r   )iterr]   r   r   r   r   __iter__   s    zbranchcache.__iter__c                 C   s   || j |< d S r   )r]   )r   keyvaluer   r   r   __setitem__   s    zbranchcache.__setitem__c                 C   s   |  | | j| S r   rf   r]   r   rk   r   r   r   r$      s    
zbranchcache.__getitem__c                 C   s   |  | || jv S r   rn   ro   r   r   r   __contains__   s    
zbranchcache.__contains__c                 c   s.   t | jD ]\}}| | ||fV  qd S r   )r
   	iteritemsr]   rf   )r   kvr   r   r   rq      s    
zbranchcache.iteritemsc                 C   s   |  | || jv S )z4 checks whether a branch of this name exists or not rn   )r   labelr   r   r   	hasbranch   s    
zbranchcache.hasbranchc              
   C   sP  d }z4z| | |}t|}t|ddd}|d d \}}t|t| }}d }|jj	}t
|dkr~t|d }| ||||d}	|	|std|	|| W nz ttfy   Y W |r|  d S  ty( }
 z<|jjrd}|j|t|t|
f  d }	W Y d }
~
n
d }
~
0 0 W |rL|  n|rJ|  0 |	S )N   
       )rY   r%   rZ   rb   ztip differss   invalid %s: %s
)cachevfs	_filenameri   nextrstripsplitr   r9   r-   rb   lenr/   rR   loadIOErrorOSErrorclose	ExceptionuiZ	debugflagdebugrV   r
   Zbytestr)clsr#   flineitercachekeyZlastZlrevrZ   rb   r)   instmsgr   r   r   r1     sV    

	

zbranchcache.fromfilec                 C   s~   |D ]t}| d}|sq|dd\}}}|dvr:tdt| }t|}| j|g 	| |dkr| j
| qdS )z\ fully loads the branchcache by reading from the file using the line
        iterator passedrv   rw   rx   s   oczinvalid branch state   cN)r|   r}   rR   r   tolocalstripr   r]   
setdefaultappendr[   rB   )r   r#   r   liner;   statert   r   r   r   r   2  s    
zbranchcache.loadc                 C   s   d}| j rd|| j f }|S )z7name of a branchcache file for a given repo or repoviews   branch2s   %s-%srU   )r#   filenamer   r   r   rz   B  s    zbranchcache._filenamec                 C   sD   z*| j |j| jko(| jt|| jkW S  ty>   Y dS 0 dS )zIs the cache content valid regarding a repo

        - False when cached tipnode is unknown or if we detect a strip.
        - True when cache is up to date or a subset of current repo.FN)rY   r-   r;   r%   rZ   r   
IndexErrorr"   r   r   r   r/   J  s    zbranchcache.validforc                 C   s8   |d }d}t |D ]}|| jvr|}d} q0q||fS )zhReturn tuple with last open head in heads and false,
        otherwise return last closed head and true.TF)reversedr[   )r   headsZtiprE   rG   r   r   r   
_branchtipV  s    
zbranchcache._branchtipc                 C   s   |  | | d S )zReturn the tipmost open head on branch head, otherwise return the
        tipmost closed head on branch.
        Raise KeyError for unknown branch.r   )r   )r   rd   r   r   r   	branchtipb  s    zbranchcache.branchtipc                    s    fdd|D S )Nc                 3   s   | ]}| j vr|V  qd S r   )r[   )r&   re   r   r   r   r*   i  r+   z'branchcache.iteropen.<locals>.<genexpr>r   )r   nodesr   r   r   iteropenh  s    zbranchcache.iteropenFc                 C   s*   |  | | j| }|s&t| |}|S r   )rf   r]   listr   )r   rd   rE   r   r   r   r   branchheadsk  s
    

zbranchcache.branchheadsc                 c   s,   t | D ]\}}||f| | V  q
d S r   )r
   rq   r   )r   bnr   r   r   r   iterbranchesr  s    zbranchcache.iterbranchesc                 C   s   |    t| jS )z returns all the heads )rh   r
   rA   r]   r   r   r   r   	iterheadsv  s    zbranchcache.iterheadsc                 C   s   t | | j| j| j| j| jS )z-return an deep copy of the branchcache object)typer]   rY   r%   rZ   r[   r   r   r   r   r4   {  s    zbranchcache.copyc           
   
   C   s2  z|j | |ddd}t| jd| j g}| jd urF|t| j |d|d  d}t	t
| jD ]P\}}t|}|D ]8}|d7 }|| jv rd	}nd
}|dt|||f  qqn|  |jddt|t| j| W nD tttjfy, }	 z"|jdt|	  W Y d }	~	n
d }	~	0 0 d S )N   wT)Z
atomictemps   %drw   rv   r   r   r      os	   %s %s %s
   branchcaches%   wrote %s with %d labels and %d nodes
s    couldn't write branch cache: %s
)ry   rz   r   rY   r%   rZ   r   rD   joinsortedr
   rq   r]   r   	fromlocalr[   r   r   logrV   r~   r   r   r	   Abortr   r   forcebytestr)
r   r#   r   r   Z	nodecountrt   r   r;   r   r   r   r   r   rD     s:    


zbranchcache.writec                    s  t  }|j i }| j}|D ]8}||\}}||g | |r | j 	| q t
  }	| j}
t|D ]\}}| j|g } fdd|D }|| ||	 }|rt|}t
 ||}||8 }t|} fdd|D | |< |d }||
krv|}
qv|
| jkr&|
| _ 	|
| _| |st| _t| _|  D ]:}t fdd|D }|| jkrF 	|| _|| _qFt|| j| _t  | }|jdd	t|| | | d
S )zGiven a branchhead cache, self, that may have extra nodes or be
        missing heads, and a generator of nodes that are strictly a superset of
        heads missing, this function updates self to be correct.
        c                    s   h | ]}  |qS r   r>   r:   r8   r   r   	<setcomp>  r+   z%branchcache.update.<locals>.<setcomp>c                    s   g | ]}  |qS r   rS   )r&   r>   r   r   r   
<listcomp>  r+   z&branchcache.update.<locals>.<listcomp>r   c                 3   s   | ]}  |V  qd S r   r   r:   r   r   r   r*     r+   z%branchcache.update.<locals>.<genexpr>r   s   updated %s in %.4f seconds
N) r   Ztimerr-   revbranchcacher?   r   r   r[   rB   r;   r@   Zheadrevsr%   r
   rq   r]   r7   min	ancestorsr   rY   r/   r   r   r   rC   r   rZ   r   r   rV   rD   )r   r#   ZrevgenZ	starttimeZnewbranchesZgetbranchinfor'   rd   ZclosesbranchZ	topoheadsZntiprevZnewheadrevsrF   ZbheadsetZ	uncertainZfloorrevr   Z	bheadrevsr%   r   Zdurationr   r   r   r7     sZ    


zbranchcache.update)F) rN   rO   rP   rQ   r   r   r   rc   rf   rh   rj   rm   r$   rp   rq   itemsru   classmethodr1   r   staticmethodrz   r/   r   r   r   r   r   r   r4   rD   r7   r   r   r   r   r0      sB   
 


-


 r0   c                   @   s   e Zd ZdZdd ZdS )remotebranchcachez@Branchmap info for a remote connection, should not write locallyc                 C   s   d S r   r   r"   r   r   r   rD     s    zremotebranchcache.writeN)rN   rO   rP   rQ   rD   r   r   r   r   r     s   r   s   -v1s	   rbc-namess   rbc-revss   >4sI   il        c                   @   sj   e Zd ZdZdddZdd Zej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S )r   a  Persistent cache, mapping from revision number to branch name and close.
    This is a low level cache, independent of filtering.

    Branch names are stored in rbc-names in internal encoding separated by 0.
    rbc-names is append-only, and each branch name is only stored once and will
    thus have a unique index.

    The branch info for each revision is stored in rbc-revs as constant size
    records. The whole file is read into memory, but it is only 'parsed' on
    demand. The file is usually append-only but will be truncated if repo
    modification is detected.
    The record for each revision contains the first 4 bytes of the
    corresponding node hash, and the record is only used if it still matches.
    Even a completely trashed rbc-revs fill thus still give the right result
    while converging towards full recovery ... assuming no incorrectly matching
    node hashes.
    The record also contains 4 bytes where 31 bits contains the index of the
    branch and the last bit indicate that it is a branch close commit.
    The usage pattern for rbc-revs is thus somewhat similar to 00changelog.i
    and will grow with it but be 1/8th of its size.
    Tc              
   C   s"  |j d u sJ || _g | _t | _d| _z4|jt}t	|| _|rZdd |
dD | _W n" ttfy~   |rz| j| _Y n0 | jrz|jt}|| jd d < W n> ttfy } z"|jdt|  W Y d }~n
d }~0 0 tt	| jt t	|j| _| jdkrg | _t	| j| _d S )Nr   c                 S   s   g | ]}t |qS r   )r   r   )r&   r   r   r   r   r   %  s   z+revbranchcache.__init__.<locals>.<listcomp>    s(   couldn't read revision branch cache: %s
)r!   _repo_names	bytearray_rbcrevs_rbcsnameslenry   read	_rbcnamesr~   r}   r   r   _branchinfor?   r   r   r   r   r   _rbcrecsizer-   _rbcrevslen_rbcnamescount)r   r#   readonlyZbndatadatar   r   r   r   r     s>    
zrevbranchcache.__init__c                 C   sF   d| _ | jd d = d| _t| jj| _t| jt | _	t
| d d S )Nr   s   _namesreverse)r   r   r   r~   r   r-   r   r   r   r   r   Zclearcachedpropertyr   r   r   r   _clear?  s    zrevbranchcache._clearc                 C   s   dd t | jD S )Nc                 S   s   i | ]\}}||qS r   r   )r&   r'   rH   r   r   r   
<dictcomp>I  r+   z0revbranchcache._namesreverse.<locals>.<dictcomp>)	enumerater   r   r   r   r   _namesreverseG  s    zrevbranchcache._namesreversec           	      C   s  | j j}|t }|tkr"||S t| j|t k r>| |S ||dt	 }t
tt| j|\}}t|t@ }|r|tM }|dkrnx||krz| j| |fW S  ty   | j jd |   Y n0 n4| j jd|  |t }| j|d= t| j|| _| |S )zWReturn branch name and close flag for rev, using and updating
        persistent cache.Ns       sR   referenced branch names not found - rebuilding revision branch cache from scratch
sP   history modification detected - truncating revision branch cache to revision %d
)r   r-   r   r   r?   r~   r   r   r;   _rbcnodelenunpack_from
_rbcrecfmtr   bufferbool_rbccloseflag_rbcbranchidxmaskr   r   r   r   r   r   r   )	r   r>   r-   	rbcrevidxreponodeZ	cachenode	branchidxr   truncater   r   r   r?   K  s@    

zrevbranchcache.branchinfoc                 C   sx   | j j}||\}}|| jv r,| j| }n t| j}| j| || j|< ||}|rb|tO }| 	||| ||fS )z7Retrieve branch info from changelog and update _rbcrevs)
r   r-   r?   r   r~   r   r   r;   r   _setcachedata)r   r>   r-   rH   r   r   r   r   r   r   r   z  s    



zrevbranchcache._branchinfoc                 C   sd   || j v r| j | }n t| j}| j| || j |< |rB|tO }| ||| dt| v r`| `dS )z%add new data information to the cacher?   N)r   r~   r   r   r   r   varsr?   )r   rd   r>   r;   r   r   r   r   r   setdata  s    


zrevbranchcache.setdatac                 C   s   |t krdS |t }t| j|t k rL| jdt| jjt t| j   tt| j||| t	| j
|| _
| j }|r|d| j dS )z:Writes the node's branch data to the in-memory cache data.Nr   s   write-revbranchcache)r   r   r~   r   r5   r   r-   	pack_intor   r   r   ZcurrenttransactionZaddfinalizerD   )r   r>   r;   r   r   trr   r   r   r     s    
zrevbranchcache._setcachedataNc                 C   s   | j }d}d}zzj| jt| jk r<|jdd}d}| | | jt }|t| jkrxd}|du rl|jdd}| 	|| W nJ t
ttjtjfy } z&|jd|t|f  W Y d}~n
d}~0 0 W |dur|  n|dur|  0 dS )z!Save branch cache if it is dirty.Nr+   F)waits    namess+   couldn't write revision branch cache%s: %s
)r   r   r~   r   wlock_writenamesr   r   r   
_writerevsr   r   r	   r   Z	LockErrorr   r   r   r   release)r   r   r#   r   stepr,   r   r   r   r   rD     s0    


zrevbranchcache.writec                 C   s   | j dkrV|jtd}| | jkr2|d n$|  |j	dt  d| _ d| _
| j dkr~|jjtdd |jtd}|ddd	 | j| j d
 D  | | _|  t| j| _ d
S )z. write the new branch names to revbranchcache r      abr   s   %s changed - rewriting it
T)Zignoremissings   wbc                 s   s   | ]}t |V  qd S r   )r   r   )r&   rH   r   r   r   r*     s   z-revbranchcache._writenames.<locals>.<genexpr>N)r   ry   openr   tellr   rD   r   r   r   r   Z
unlinkpathr   r   r   r~   )r   r#   r   r   r   r   r     s&    



zrevbranchcache._writenamesc                 C   s   t t|jt| jt }|jtdx}| |krv|j	dt|f  |
| | |krnd}|
| |  |t }|| j||  W d   n1 s0    Y  || _dS )z& write the new revs to revbranchcache r   s   truncating cache/%s to %d
r   N)r   r~   r-   r   r   ry   r   r   r   r   seekr   rD   r   )r   r#   r,   r6   r   endr   r   r   r     s    


2zrevbranchcache._writerevs)T)N)rN   rO   rP   rQ   r   r   r   Zpropertycacher   r?   r   r   r   rD   r   r   r   r   r   r   r     s   
$
/
r   )0Z
__future__r   Zstructr;   r   r   r   r    r   r	   r
   r   r   Zutilsr   r   TYPE_CHECKINGtypingr   r   r   r   r   r   r   r   r   anyr2   Zcalcsizer   r   objectr   rT   rV   r0   r   Z_rbcversionr   r   r   r   r   r   r   r   r   r   r   r   <module>   s:   ,W  X	