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 _ |