mercurial/phases.py
changeset 16725 b0fb4f57d076
parent 16724 00535da82faf
child 16867 1093ad1e8903
equal deleted inserted replaced
16724:00535da82faf 16725:b0fb4f57d076
     4 
     4 
     5     Copyright 2011 Pierre-Yves David <pierre-yves.david@ens-lyon.org>
     5     Copyright 2011 Pierre-Yves David <pierre-yves.david@ens-lyon.org>
     6                    Logilab SA        <contact@logilab.fr>
     6                    Logilab SA        <contact@logilab.fr>
     7                    Augie Fackler     <durin42@gmail.com>
     7                    Augie Fackler     <durin42@gmail.com>
     8 
     8 
     9     This software may be used and distributed according to the terms of the
     9     This software may be used and distributed according to the terms
    10     GNU General Public License version 2 or any later version.
    10     of the GNU General Public License version 2 or any later version.
    11 
    11 
    12     ---
    12     ---
    13 
    13 
    14 This module implements most phase logic in mercurial.
    14 This module implements most phase logic in mercurial.
    15 
    15 
    16 
    16 
    17 Basic Concept
    17 Basic Concept
    18 =============
    18 =============
    19 
    19 
    20 A 'changeset phase' is an indicator that tells us how a changeset is
    20 A 'changeset phase' is an indicator that tells us how a changeset is
    21 manipulated and communicated. The details of each phase is described below,
    21 manipulated and communicated. The details of each phase is described
    22 here we describe the properties they have in common.
    22 below, here we describe the properties they have in common.
    23 
    23 
    24 Like bookmarks, phases are not stored in history and thus are not permanent and
    24 Like bookmarks, phases are not stored in history and thus are not
    25 leave no audit trail.
    25 permanent and leave no audit trail.
    26 
    26 
    27 First, no changeset can be in two phases at once. Phases are ordered, so they
    27 First, no changeset can be in two phases at once. Phases are ordered,
    28 can be considered from lowest to highest. The default, lowest phase is 'public'
    28 so they can be considered from lowest to highest. The default, lowest
    29 - this is the normal phase of existing changesets. A child changeset can not be
    29 phase is 'public' - this is the normal phase of existing changesets. A
    30 in a lower phase than its parents.
    30 child changeset can not be in a lower phase than its parents.
    31 
    31 
    32 These phases share a hierarchy of traits:
    32 These phases share a hierarchy of traits:
    33 
    33 
    34             immutable shared
    34             immutable shared
    35     public:     X        X
    35     public:     X        X
    39 Local commits are draft by default.
    39 Local commits are draft by default.
    40 
    40 
    41 Phase Movement and Exchange
    41 Phase Movement and Exchange
    42 ===========================
    42 ===========================
    43 
    43 
    44 Phase data is exchanged by pushkey on pull and push. Some servers have a
    44 Phase data is exchanged by pushkey on pull and push. Some servers have
    45 publish option set, we call such a server a "publishing server". Pushing a
    45 a publish option set, we call such a server a "publishing server".
    46 draft changeset to a publishing server changes the phase to public.
    46 Pushing a draft changeset to a publishing server changes the phase to
       
    47 public.
    47 
    48 
    48 A small list of fact/rules define the exchange of phase:
    49 A small list of fact/rules define the exchange of phase:
    49 
    50 
    50 * old client never changes server states
    51 * old client never changes server states
    51 * pull never changes server states
    52 * pull never changes server states
    52 * publish and old server changesets are seen as public by client
    53 * publish and old server changesets are seen as public by client
    53 * any secret changeset seen in another repository is lowered to at least draft
    54 * any secret changeset seen in another repository is lowered to at
    54 
    55   least draft
    55 Here is the final table summing up the 49 possible use cases of phase exchange:
    56 
       
    57 Here is the final table summing up the 49 possible use cases of phase
       
    58 exchange:
    56 
    59 
    57                            server
    60                            server
    58                   old     publish      non-publish
    61                   old     publish      non-publish
    59                  N   X    N   D   P    N   D   P
    62                  N   X    N   D   P    N   D   P
    60     old client
    63     old client
    77     A/B = final state on client / state on server
    80     A/B = final state on client / state on server
    78 
    81 
    79     * N = new/not present,
    82     * N = new/not present,
    80     * P = public,
    83     * P = public,
    81     * D = draft,
    84     * D = draft,
    82     * X = not tracked (i.e., the old client or server has no internal way of
    85     * X = not tracked (i.e., the old client or server has no internal
    83           recording the phase.)
    86           way of recording the phase.)
    84 
    87 
    85     passive = only pushes
    88     passive = only pushes
    86 
    89 
    87 
    90 
    88     A cell here can be read like this:
    91     A cell here can be read like this:
    89 
    92 
    90     "When a new client pushes a draft changeset (D) to a publishing server
    93     "When a new client pushes a draft changeset (D) to a publishing
    91     where it's not present (N), it's marked public on both sides (P/P)."
    94     server where it's not present (N), it's marked public on both
       
    95     sides (P/P)."
    92 
    96 
    93 Note: old client behave as a publishing server with draft only content
    97 Note: old client behave as a publishing server with draft only content
    94 - other people see it as public
    98 - other people see it as public
    95 - content is pushed as draft
    99 - content is pushed as draft
    96 
   100 
   258             self._updateroots(targetphase, currentroots)
   262             self._updateroots(targetphase, currentroots)
   259 
   263 
   260 def advanceboundary(repo, targetphase, nodes):
   264 def advanceboundary(repo, targetphase, nodes):
   261     """Add nodes to a phase changing other nodes phases if necessary.
   265     """Add nodes to a phase changing other nodes phases if necessary.
   262 
   266 
   263     This function move boundary *forward* this means that all nodes are set
   267     This function move boundary *forward* this means that all nodes
   264     in the target phase or kept in a *lower* phase.
   268     are set in the target phase or kept in a *lower* phase.
   265 
   269 
   266     Simplify boundary to contains phase roots only."""
   270     Simplify boundary to contains phase roots only."""
   267     phcache = repo._phasecache.copy()
   271     phcache = repo._phasecache.copy()
   268     phcache.advanceboundary(repo, targetphase, nodes)
   272     phcache.advanceboundary(repo, targetphase, nodes)
   269     repo._phasecache.replace(phcache)
   273     repo._phasecache.replace(phcache)
   270 
   274 
   271 def retractboundary(repo, targetphase, nodes):
   275 def retractboundary(repo, targetphase, nodes):
   272     """Set nodes back to a phase changing other nodes phases if necessary.
   276     """Set nodes back to a phase changing other nodes phases if
   273 
   277     necessary.
   274     This function move boundary *backward* this means that all nodes are set
   278 
   275     in the target phase or kept in a *higher* phase.
   279     This function move boundary *backward* this means that all nodes
       
   280     are set in the target phase or kept in a *higher* phase.
   276 
   281 
   277     Simplify boundary to contains phase roots only."""
   282     Simplify boundary to contains phase roots only."""
   278     phcache = repo._phasecache.copy()
   283     phcache = repo._phasecache.copy()
   279     phcache.retractboundary(repo, targetphase, nodes)
   284     phcache.retractboundary(repo, targetphase, nodes)
   280     repo._phasecache.replace(phcache)
   285     repo._phasecache.replace(phcache)
   285     value = '%i' % draft
   290     value = '%i' % draft
   286     for root in repo._phasecache.phaseroots[draft]:
   291     for root in repo._phasecache.phaseroots[draft]:
   287         keys[hex(root)] = value
   292         keys[hex(root)] = value
   288 
   293 
   289     if repo.ui.configbool('phases', 'publish', True):
   294     if repo.ui.configbool('phases', 'publish', True):
   290         # Add an extra data to let remote know we are a publishing repo.
   295         # Add an extra data to let remote know we are a publishing
   291         # Publishing repo can't just pretend they are old repo. When pushing to
   296         # repo. Publishing repo can't just pretend they are old repo.
   292         # a publishing repo, the client still need to push phase boundary
   297         # When pushing to a publishing repo, the client still need to
       
   298         # push phase boundary
   293         #
   299         #
   294         # Push do not only push changeset. It also push phase data. New
   300         # Push do not only push changeset. It also push phase data.
   295         # phase data may apply to common changeset which won't be push (as they
   301         # New phase data may apply to common changeset which won't be
   296         # are common).  Here is a very simple example:
   302         # push (as they are common). Here is a very simple example:
   297         #
   303         #
   298         # 1) repo A push changeset X as draft to repo B
   304         # 1) repo A push changeset X as draft to repo B
   299         # 2) repo B make changeset X public
   305         # 2) repo B make changeset X public
   300         # 3) repo B push to repo A. X is not pushed but the data that X as now
   306         # 3) repo B push to repo A. X is not pushed but the data that
   301         #    public should
   307         #    X as now public should
   302         #
   308         #
   303         # The server can't handle it on it's own as it has no idea of client
   309         # The server can't handle it on it's own as it has no idea of
   304         # phase data.
   310         # client phase data.
   305         keys['publishing'] = 'True'
   311         keys['publishing'] = 'True'
   306     return keys
   312     return keys
   307 
   313 
   308 def pushphase(repo, nhex, oldphasestr, newphasestr):
   314 def pushphase(repo, nhex, oldphasestr, newphasestr):
   309     """List phases root for serialisation over pushkey"""
   315     """List phases root for serialisation over pushkey"""