��c@sdZddlZddlmZmZmZmZmZddlm Z ddl
Z
ddlZed�Z
\ZZZe
dZddd gZdd
�Zdefd��YZd
�Zd�Zd�Zd�Zd�Zd�Zd�Zd�ZdS(s� Mercurial phases support code
---
Copyright 2011 Pierre-Yves David <pierre-yves.david@ens-lyon.org>
Logilab SA <contact@logilab.fr>
Augie Fackler <durin42@gmail.com>
This software may be used and distributed according to the terms
of the GNU General Public License version 2 or any later version.
---
This module implements most phase logic in mercurial.
Basic Concept
=============
A 'changeset phase' is an indicator that tells us how a changeset is
manipulated and communicated. The details of each phase is described
below, here we describe the properties they have in common.
Like bookmarks, phases are not stored in history and thus are not
permanent and leave no audit trail.
First, no changeset can be in two phases at once. Phases are ordered,
so they can be considered from lowest to highest. The default, lowest
phase is 'public' - this is the normal phase of existing changesets. A
child changeset can not be in a lower phase than its parents.
These phases share a hierarchy of traits:
immutable shared
public: X X
draft: X
secret:
Local commits are draft by default.
Phase Movement and Exchange
===========================
Phase data is exchanged by pushkey on pull and push. Some servers have
a publish option set, we call such a server a "publishing server".
Pushing a draft changeset to a publishing server changes the phase to
public.
A small list of fact/rules define the exchange of phase:
* old client never changes server states
* pull never changes server states
* publish and old server changesets are seen as public by client
* any secret changeset seen in another repository is lowered to at
least draft
Here is the final table summing up the 49 possible use cases of phase
exchange:
server
old publish non-publish
N X N D P N D P
old client
pull
N - X/X - X/D X/P - X/D X/P
X - X/X - X/D X/P - X/D X/P
push
X X/X X/X X/P X/P X/P X/D X/D X/P
new client
pull
N - P/X - P/D P/P - D/D P/P
D - P/X - P/D P/P - D/D P/P
P - P/X - P/D P/P - P/D P/P
push
D P/X P/X P/P P/P P/P D/D D/D P/P
P P/X P/X P/P P/P P/P P/P P/P P/P
Legend:
A/B = final state on client / state on server
* N = new/not present,
* P = public,
* D = draft,
* X = not tracked (i.e., the old client or server has no internal
way of recording the phase.)
passive = only pushes
A cell here can be read like this:
"When a new client pushes a draft changeset (D) to a publishing
server where it's not present (N), it's marked public on both
sides (P/P)."
Note: old client behave as a publishing server with draft only content
- other people see it as public
- content is pushed as draft
i�N(tnullidtnullrevtbinthextshort(t_iitpublictdrafttsecretc
Cs�|j�}t}gtD]}t�^q}ye|jd�}zDx=|D]5}|j�\}}|t|�jt|��qJWWd|j �XWnZt
k
r�} | jtjkr��n|r� |D]}|||�}q�Wnt
}nX||fS(s�Read phase roots from disk
phasedefaults is a list of fn(repo, roots) callable, which are
executed if the phase roots file does not exist. When phases are
being initialized on an existing repository, this could be used to
set selected changesets phase to something else than public.
Return (roots, dirty) where dirty is true if roots differ from
what is being stored.
t
phaserootsN(t
unfilteredtFalset allphasestsettsopenertsplittinttaddRtclosetIOErrorterrnotENOENTtTrue(
trepot
phasedefaultstdirtytitrootstftlinetphasetnhtinst((s4/sys/lib/python2.7/site-packages/mercurial/phases.pyt
_readrootsps$
%
t
phasecachecBsheZed�Zd�Zd�Zed�Zd�Zd�Z d�Z
d�Zd�Zd �Z
RS(
cCsJ|rFt||�\|_|_d|_|j|�|j|_ndS(N(R!R RtNonet
_phaserevst
filterunknownRtopener(tselfRRt_load((s4/sys/lib/python2.7/site-packages/mercurial/phases.pyt__init__�s
cCsJtdddt�}|j|_|j|_|j|_|j|_|S(NR((R"R#RR RR&R$(R'tph((s4/sys/lib/python2.7/site-packages/mercurial/phases.pytcopy�s
cCs4x-dj�D]}t||t||��q
WdS(Ns"phaseroots dirty opener _phaserevs(Rtsetattrtgetattr(R'tphcacheta((s4/sys/lib/python2.7/site-packages/mercurial/phases.pytreplace�scCs�|s|jdkr�|j�}tgt|j�}xutD]m}t|jj|j |�}|r>x|D]}|||<qmWx'|jj
|�D]}|||<q�Wq>q>W||_n|jS(N(R$R#R
Rtlent changelogt
trackedphasestmaptrevR tdescendants(R'RtrebuildtrevsRRR5((s4/sys/lib/python2.7/site-packages/mercurial/phases.pytgetphaserevs�s
cCsZ|tkrtS|jdks4|t|j�krO|j|dt�|_n|j|S(NR7(RRR$R#R1R9R(R'RR5((s4/sys/lib/python2.7/site-packages/mercurial/phases.pyR�s
$cCs�|js
dS|jdddt�}zRxKt|j�D]:\}}x+|D]#}|jd|t|�f�qKWq8WWd|j�Xt|_dS(NR twt
atomictemps%i %s
( RR&Rt enumerateR twriteRRR(R'RRRth((s4/sys/lib/python2.7/site-packages/mercurial/phases.pyR=�s
)cCs#||j|<d|_t|_dS(N(R R#R$RR(R'Rtnewroots((s4/sys/lib/python2.7/site-packages/mercurial/phases.pyt_updateroots�s
c Cs|j�}g}x�|dtt��D]�}g|D].}|j|||j��|kr9|^q9}|swPn|j|}td�|jd|||�D��}||kr�|j||�|j ||�n|dkr,|j
|||�q,q,W|j�dS(Nicss|]}|j�VqdS(N(tnode(t.0tctx((s4/sys/lib/python2.7/site-packages/mercurial/phases.pys <genexpr>�ssroots((%ln::) - (%ln::%ln))i(R
txrangeR1RRR5R R
R@textendtretractboundarytinvalidatevolatilesets( R'RttargetphasetnodestdelrootsRtntoldsR((s4/sys/lib/python2.7/site-packages/mercurial/phases.pytadvanceboundary�s
.
cCs�|j�}|j|}g|D].}|j|||j��|kr |^q }|r�t|kr~tjtd���n|j�}|j |�|j
d|�}|jd�|D��|j||�n|j
�dS(Ns!cannot change null revision phasesroots(%ln::)css|]}|j�VqdS(N(RA(RBRC((s4/sys/lib/python2.7/site-packages/mercurial/phases.pys <genexpr>�s(R
R RR5RtutiltAbortRR+tupdateR
tintersection_updateR@RG(R'RRHRItcurrentrootsRKR?tctxs((s4/sys/lib/python2.7/site-packages/mercurial/phases.pyRF�s
.
c Cs�t}|jj}x�t|j�D]~\}}g|D]}||kr5|^q5}|r"x.|D]&}|jjdt|�|f�q`W|j|�t }q"q"W|r�t |_
nd|_dS(s�remove unknown nodes from the phase boundary
Nothing is lost as unknown nodes only hold data for their descendants.
s0removing unknown node %s from %i-phase boundary
N(
RR2tnodemapR<R tuitdebugRtsymmetric_difference_updateRRR#R$( R'RtfilteredRTRRIRAtmissingtmnode((s4/sys/lib/python2.7/site-packages/mercurial/phases.pyR%�s%
(t__name__t
__module__RR)R+R0RR9RR=R@RMRFR%(((s4/sys/lib/python2.7/site-packages/mercurial/phases.pyR"�s
cCs6|jj�}|j|||�|jj|�dS(s�Add nodes to a phase changing other nodes phases if necessary.
This function move boundary *forward* this means that all nodes
are set in the target phase or kept in a *lower* phase.
Simplify boundary to contains phase roots only.N(t_phasecacheR+RMR0(RRHRIR.((s4/sys/lib/python2.7/site-packages/mercurial/phases.pyRMscCs6|jj�}|j|||�|jj|�dS(s�Set nodes back to a phase changing other nodes phases if
necessary.
This function move boundary *backward* this means that all nodes
are set in the target phase or kept in a *higher* phase.
Simplify boundary to contains phase roots only.N(R]R+RFR0(RRHRIR.((s4/sys/lib/python2.7/site-packages/mercurial/phases.pyRF"scCsdi}dt}x(|jjtD]}||t|�<q!W|jjddt�r`d|d<n|S(s/List phases root for serialization over pushkeys%itphasestpublishRt
publishing(RR]R RRUt
configboolR(Rtkeystvaluetroot((s4/sys/lib/python2.7/site-packages/mercurial/phases.pyt
listphases.s
cCs�|j�}|j�}z�||j�}tt|��}tt|��}||kr�||kr�t||t|�g�dS||kr�dSdSWd|j�XdS(s/List phases root for serialization over pushkeyiiN(R
tlockRtabsRRMRtrelease(RtnhextoldphasestrtnewphasestrRftcurrentphasetnewphasetoldphase((s4/sys/lib/python2.7/site-packages/mercurial/phases.pyt pushphaseIsc Cs|j�}g}|jj}x�|j�D]�\}}|dkrIq+nt|�}t|�}|dkr�|tkr�jjt d�|�q�+|dkr�||kr�j
|�q�+|jjt d�||f�q+Wt|||�}||fS(s�Compute phases heads and root in a subset of node from root dict
* subset is heads of the subset
* roots is {<nodeid> => phase} mapping. key and value are string.
Accept unknown element input
R`is2ignoring inconsistent public root from remote: %s
is,ignoring unexpected root from remote: %i %s
(R
R2RTt iteritemsRRRRUtwarnRtappendtnewheads( RtsubsetRt
draftrootsRTRiRRAtpublicheads((s4/sys/lib/python2.7/site-packages/mercurial/phases.pytanalyzeremotephases\s&cCsD|j�}|jd||||�}g|D]}|j�^q.S(s�compute new head of a subset minus another
* `heads`: define the first subset
* `roots`: define the second we subtract from the firsts(heads((%ln + parents(%ln)) - (%ln::%ln))(R
R
RA(RtheadsRtrevsettc((s4/sys/lib/python2.7/site-packages/mercurial/phases.pyRs{s cCs|jddt�}ytj|�SWnRtk
rzyt|�SWq{tk
rvtd�}tj||��q{XnXdS(suhelper to get the target phase of new commit
Handle all possible values for the phases.new-commit options.
R^s
new-commits0phases.new-commit: not a valid phase name ('%s')N( tconfigRt
phasenamestindext
ValueErrorRRterrortConfigError(RUtvtmsg((s4/sys/lib/python2.7/site-packages/mercurial/phases.pytnewcommitphase�s
cCst|jjd�S(s@utility function that check if a repo have any secret changeset.i(tboolR]R (R((s4/sys/lib/python2.7/site-packages/mercurial/phases.pyt hassecret�s(t__doc__RRARRRRRti18nRRNRtrangeRRRRR3R|R#R!tobjectR"RMRFReRoRwRsR�R�(((s4/sys/lib/python2.7/site-packages/mercurial/phases.pyt<module>es"(
�
|