hgext/states.py
changeset 59 02fba620d139
parent 57 62f2fe22bd42
child 60 14a4499d2cd6
equal deleted inserted replaced
58:2ba7355f6e11 59:02fba620d139
     7 # This software may be used and distributed according to the terms of the
     7 # This software may be used and distributed according to the terms of the
     8 # GNU General Public License version 2 or any later version.
     8 # GNU General Public License version 2 or any later version.
     9 
     9 
    10 '''introduce the state concept for mercurial changeset
    10 '''introduce the state concept for mercurial changeset
    11 
    11 
    12 Change can be in the following state:
    12 (see http://mercurial.selenic.com/wiki/StatesPlan)
    13 
    13 
    14 0 immutable
    14 General concept
    15 1 mutable
    15 ===============
    16 2 private
    16 
    17 
    17 This extension adds the state concept. A changeset are now in a specific state
    18 name are not fixed yet.
    18 that control they mutability and they exchange.
       
    19 
       
    20 States properties
       
    21 .................
       
    22 
       
    23 The states extension currently alter two property for changeset
       
    24 
       
    25 :mutability:  history rewritten tool should refuse to work on immutable changeset
       
    26 :sharing:     shared changeset are exchanged during pull and push. other are not
       
    27 
       
    28 Here is a small summary of the current property of state existing state::
       
    29 
       
    30     ||           || mutable || shared ||
       
    31     || published ||         ||   x    ||
       
    32     || ready     ||    x    ||   x    ||
       
    33     || draft     ||    x    ||        ||
       
    34 
       
    35 States consistency and ordering
       
    36 ...............................
       
    37 
       
    38 States of changesets have to be consistent with each other. A changeset can only have ancestors of it's state (or a compatible states)
       
    39 
       
    40 Example:
       
    41 
       
    42     A ``published`` changeset can't have a ``draft`` parent.
       
    43 
       
    44 a state is compatible with itself and all "smaller" states. Order is as follow::
       
    45 
       
    46     published < ready < draft
       
    47 
       
    48 
       
    49 .. note:
       
    50 
       
    51     This section if probably far too conceptual for people. The result is just
       
    52     that: A ``published`` changeset can only have ``published`` ancestors. A
       
    53     ``ready`` changeset can only have ``published`` or ``ready`` ancestors.
       
    54 
       
    55     Moreover There is a need for a nice word to refer to "a state smaller than another"
       
    56 
       
    57 
       
    58 States details
       
    59 ==============
       
    60 
       
    61 
       
    62 published
       
    63     Changesets in the ``published`` state are the core of the history.  They are
       
    64     changesets that you published to the world. People can expect them to always
       
    65     exist. They are changesets as you know them. **By default all changesets
       
    66     are published**
       
    67 
       
    68     - They are exchanged with other repositories (included in pull//push).
       
    69 
       
    70     - They are not mutable, extensions rewriting history should refuse to
       
    71       rewrite them.
       
    72 
       
    73 ready
       
    74     Changesets in the ``ready`` state have not yet been accepted in the
       
    75     immutable history. You can share them with others for review, testing or
       
    76     improvement. Any ``ready`` changeset can either be included in the
       
    77     published history (and become immutable) or be rewritten and never make it
       
    78     to the published history.
       
    79 
       
    80     - They are exchanged with other repositories (included in pull//push).
       
    81 
       
    82     - They are mutable, extensions rewriting history accept to work on them.
       
    83 
       
    84 draft
       
    85 
       
    86     Changesets in the ``draft`` state are heavy work in progress you are not
       
    87     yet willing to share with others.
       
    88 
       
    89     - They are not exchanged with other repositories. pull//push do not see them.
       
    90     - They are mutable, extensions rewriting history accept to work on them.
       
    91 
       
    92 --
       
    93 
       
    94 .. note:
       
    95 
       
    96     The Dead states mentionned in on the wiki page are missing. There is two main reason for it:
       
    97 
       
    98     1. The ``dead`` state has a different behaviour that requires more work to be
       
    99        implemented.
       
   100 
       
   101     2. I believe that the use cases of ``dead changeset`` are better covered by
       
   102        the ``obsolete`` extension.
       
   103 
       
   104 --
       
   105 
       
   106 .. note:
       
   107 
       
   108     I'm tempted to add a state with the same property that ``ready`` for review
       
   109     workflow.::
       
   110 
       
   111         ||           || mutable || shared ||
       
   112         || published ||         ||   x    ||
       
   113         || ready     ||    x    ||   x    ||
       
   114         || inprogress||    x    ||   x    ||
       
   115         || draft     ||    x    ||        ||
       
   116 
       
   117     The ``ready`` state would be for changeset that wait review of someone that
       
   118     can "publish" them.
       
   119 
       
   120 
       
   121 
       
   122 Current Feature and usage
       
   123 =========================
       
   124 
       
   125 
       
   126 Enabling states
       
   127 ...............
       
   128 
       
   129 The extension adds a :hg:`hg states` command to display and choose which states
       
   130 are used by a repository, see :hg:`hg states` for details.
       
   131 
       
   132 By default all changesets in the repository are ``published``. Other states
       
   133 must be explicitly activated. Changeset in a remote repository that doesn't
       
   134 support states are all seen as ``published``.
       
   135 
       
   136 .. note:
       
   137 
       
   138     When a state is not activated, changesets in this state are handled as
       
   139     changesets of the previous state it (``draft`` are handled as ``ready``,
       
   140     ``ready`` are handled as ``published``).
       
   141 
       
   142 TODO:
       
   143 
       
   144 - have a configuration in hgrc::
       
   145 
       
   146     [states]
       
   147     ready=(off|on)(-inherit)?
       
   148     <state>=(off|on)(-inherit)?
       
   149 
       
   150  :off:     state disabled for new repo
       
   151  :on:      state enabled  for new repo
       
   152  :inherit: if present, inherit states of source on :hg:`clone`.
       
   153 
       
   154 -  have a switch to select if changesets do change state on state activation.
       
   155 
       
   156 - display the number of changesets that change state when activating a state.
       
   157 
       
   158 
       
   159 
       
   160 State transition
       
   161 ................
       
   162 
       
   163 Changeset you create locally will be in the ``draft`` state. (or any previous
       
   164 state if draft isn't enabled)
       
   165 
       
   166 There is some situation where the state of a changeset will change
       
   167 automatically. Automatic movement always go in the same direction.: ``draft ->
       
   168 ``ready`` -> ``published``
       
   169 
       
   170 1. When you pull or push boundary move. Common changeset that are ``published`` in
       
   171 one of the two repository are set to ``published``. Same goes for ``ready`` etc
       
   172 (states are evaluated from in increasing order XXX I bet no one understand this
       
   173 parenthesis. Pull operation alter the local repository. push alter both local
       
   174 and remote repository.
       
   175 
       
   176 .. note:
       
   177 
       
   178     As Repository without any specific state have all their changeset
       
   179     ``published``, Pushing to such repo will ``publish`` all common changeset. 
       
   180 
       
   181 2. Tagged changeset get automatically Published. The tagging changeset is
       
   182 tagged too... This doesn't apply to local tag.
       
   183 
       
   184 
       
   185 You can also manually change changeset state with a dedicated command for each
       
   186 state. See :hg:`published`, :hg:`ready` and :hg:`draft` for details.
       
   187 
       
   188 XXX maybe we can details the general behaviour here
       
   189 
       
   190 :hg <state> revs:                 move boundary of state so it includes revs
       
   191                                   ( revs included in ::<state>heads())
       
   192 :hg --exact <state> revs:         move boundary so that revs are exactly in state
       
   193                                   <state> ( all([rev.state == <state> for rev in
       
   194                                   revs]))
       
   195 :hg --exact --force <state> revs: move boundary event if it create inconsistency
       
   196                                   (with tag for example)
       
   197 
       
   198 TODO:
       
   199 
       
   200 - implement --exact
       
   201 
       
   202 - implement consistency check
       
   203 
       
   204 - implement --force
       
   205 
       
   206 
       
   207 Existing command change
       
   208 .......................
       
   209 
       
   210 As said in the previous section:
       
   211 
       
   212 :commit:    Create draft changeset (or the first enabled previous changeset).
       
   213 :tag:       Move tagged and tagging changeset in the ``published`` state.
       
   214 :incoming:  Exclude ``draft`` changeset of remote repository.
       
   215 :outgoing:  Exclude ``draft`` changeset of local repository.
       
   216 :pull:      As :hg:`in`  + change state of local changeset according to remote side.
       
   217 :push:      As :hg:`out` + sync state of common changeset on both side
       
   218 
       
   219 Template
       
   220 ........
       
   221 
       
   222 A new template keyword ``{state}`` has been added.
       
   223 
       
   224 Revset
       
   225 ......
       
   226 
       
   227     We add new ``readyheads()`` and ``publishedheads()`` revset directives. This
       
   228     returns the heads of each state **as if all of them were activated**.
       
   229 
       
   230     XXX TODO - I would like to
       
   231 
       
   232     - move the current ``<state>heads()`` directives to
       
   233       _``<state>heads()``
       
   234 
       
   235     - add ``<state>heads()`` directives to that return the currently in used heads
       
   236 
       
   237     - add ``<state>()`` directives that 
       
   238 
       
   239 implementation
       
   240 =========================
       
   241 
       
   242 To be completed
       
   243 
       
   244 Why to you store activate state outside ``.hg/hgrc``? :
       
   245 
       
   246     ``.hg/hgrc`` might be ignored for trust reason. We don't want the trust
       
   247     issue to interfer with enabled state information.
       
   248 
       
   249 
    19 '''
   250 '''
    20 import os
   251 import os
    21 from functools import partial
   252 from functools import partial
    22 
   253 
    23 from mercurial.i18n import _
   254 from mercurial.i18n import _