chiark / gitweb /
strategy: traversal wip proofs
[topbloke-formulae.git] / strategy.tex
1 Here we describe the update algorithm.  This is responsible for
2 refreshing patches against updated versions of their dependencies,
3 for merging different versions of the various braches created by
4 distributed development, and for implementing decisions to add and
5 remove dependencies from patches.
6
7 Broadly speaking the update proceeds as follows: during the Ranking
8 phase we construct the intended graph of dependencies between patches
9 (and incidentally select a merge order for the base branch of each
10 patch).  Then during the Traversal phase we walk that graph from the
11 bottom up, constructing for each patch by a series of merges and other
12 operations first a new base branch head commit and then a new tip
13 branch head commit.  These new head commits are maximums - that is,
14 each has as ancestors all of its branches' sources and indeed all
15 relevant commits in that branch.
16
17 We have two possible strategies for constructing new base branch
18 heads: we can either Merge (works incrementally even if there the
19 patch has multiple dependencies, but may sometimes not be possible) or
20 we can Regenerate (trivial if there is a single dependency, and is
21 always possible, but may involve the user re-resolving conflicts if
22 there are multiple dependencies).
23
24 \section{Notation}
25
26 \begin{basedescript}{
27 \desclabelwidth{5em}
28 \desclabelstyle{\nextlinelabel}
29 }
30 \item[ $\depsreqof{K}$ ]
31 The set of direct dependencies (in the form $\py$)
32 requested in the commit $K$ ($K \in \pn$) for the patch $\p$.
33
34 \item[ $\pc \hasdirdep \p$ ]
35 The patch $\pc$ has as a direct dependency the
36 patch $\p$.  This is an acyclic relation.
37
38 \item[ $\p \hasdep \pq$ ]
39 The patch $\p$ has as direct or indirect dependency the
40 patch $\pq$.
41 Acyclic; the completion of $\hasdirdep$ into a
42 partial order.
43
44 \item[ $\pendsof{\set J}{\p}$ ]
45 Convenience notation for
46 the $\le$-maximal elements of $\bigcup_{J \in \set J} \pendsof{J}{\p}$
47 (where $\set J$ is some set of commits).
48
49 \item[ $\pendsof{\set X}{\p} \le T$ ]
50 Convenience notation for
51 $\bigforall_{E \in \pendsof{\set X}{\p}} E \le T$
52
53 %\item[ $\set E_{\pc}$ ]
54 %$ \bigcup_i \pendsof{S_{\pc,i}}{\pc} $.
55 %All the ends of $\pc$ in the sources.
56
57 %\item[ $ \tipzc, \tipcc, \tipuc, \tipfc $ ]
58 %The git ref for the Topbloke commit set $\pc$: respectively,
59 %the original, current, updated, and final values.
60
61 \end{basedescript}
62
63 \stdsection{Inputs to the update algorithm}
64
65 \begin{basedescript}{
66 \desclabelwidth{5em}
67 \desclabelstyle{\nextlinelabel}
68 }
69 \item[ $\pc_0$ ]
70 The topmost patch which we are trying to update.  This and
71 all of its dependencies will be updated.
72
73 \item[ $h : \pc^{+/-} \mapsto \set H_{\pc^{+/-}}$ ]
74 Function for getting the existing heads $\set H$ of the branch $\pc^{+/-}$.
75 These are the heads which will be merged and used in this update.
76 This will include the current local and remote git refs, as desired.
77
78 \item[ $g : \pc, \Gamma \mapsto \Gamma'$ ]
79 Function to allow explicit adjustment of the direct dependencies
80 of $\pc$.  It is provided with a putative set of direct dependencies
81 $\Gamma$ computed as an appropriate merge of the dependencies requested by the
82 sources and should return the complete actual set $\Gamma'$ of direct
83 dependencies to use.  This allows the specification of any desired
84 (acyclic) relations $\hasdirdep$ and $\hasdep$.
85
86 \end{basedescript}
87
88 \stdsection{Important variables and values in the update algorithm}
89
90 \begin{basedescript}{
91 \desclabelwidth{5em}
92 \desclabelstyle{\nextlinelabel}
93 }
94 \item[ $\Gamma_{\pc}$ ]
95 The desired direct dependencies of $\pc$, a set of patches.
96
97 \item[ $\allpatches$ ]
98 The set of all the patches we are dealing with (constructed
99 during the update algorithm).
100
101 \item[ $\tipcn, \tipcy$ ]
102 The new tips of the git branches $\pcn$ and $\pcy$, containing
103 all the correct commits (and the correct other patches), as
104 generated by the Traversal phase of the update algorithm.
105
106 \end{basedescript}
107
108 \section{Ranking phase}
109
110 We run the following algorithm:
111 \begin{enumerate}
112 \item Set $\allpatches = \{ \}$.
113 \item Repeatedly:
114 \begin{enumerate}
115 \item Clear out the graph $\hasdirdep$ so it has no edges.
116 \item Execute $\alg{Rank-Recurse}(\pc_0)$
117 \item Until $\allpatches$ remains unchanged.
118 \end{enumerate}
119 \end{enumerate}
120
121 $\alg{Rank-Recurse}(\pc)$ is:
122 \begin{enumerate}
123
124 \item If we have already done $\alg{Rank-Recurse}(\pc)$ in this
125 ranking iteration, do nothing.  Otherwise:
126
127 \item Add $\pc$ to $\allpatches$ if it is not there already.
128
129 \item Set
130 $$
131   \set S \iassign h(\pcn)
132      \cup 
133         \bigcup_{\p \in \allpatches}
134         \bigcup_{H \in h(\pn) \lor H \in h(\py)}
135          \{ \baseof{E} \; | \; E \in \pendsof{H}{\pcy} \}
136 $$
137
138 and $W \iassign w(h(\pcn))$
139
140 \item While $\exists_{S \in \set S} S \ge W$,
141 update $W \assign S$ and $\set S \assign \set S \, \backslash \{ S \}$
142
143 (This will often remove $W$ from $\set S$.  Afterwards, $\set S$
144 is a collection of heads to be merged into $W$.)
145
146 \item Choose an ordering of $\set S$, $S_i$ for $i=1 \ldots n$.
147
148 \item For each $S_i$ in turn, choose a corresponding $M_i$
149 such that $$
150    M_i \le S_i \land \left[
151    M_i \le W \lor \bigexists_{j<i} M_i \le S_j
152    \right]
153 $$
154
155 \item Set $\Gamma \iassign \depsreqof{W}$.
156
157 If there are multiple candidates we prefer $M_i \in \pcn$
158 if available.
159
160 \item For each $i \ldots 1..n$, update our putative direct
161 dependencies:
162 $$
163 \Gamma \assign \setmergeof{
164     \Gamma
165   }{
166     \begin{cases}
167      M_i \in \pcn :     & \depsreqof{M_i} \\
168      M_i \not\in \pcn : & \{ \}
169     \end{cases}
170   }{
171     \depsreqof{S_i}
172   }
173 $$
174
175 TODO define $\setmerge$
176
177 \item Finalise our putative direct dependencies
178 $
179 \Gamma \assign g(\pc, \Gamma)
180 $
181
182 \item For each direct dependency $\pd \in \Gamma$,
183
184 \begin{enumerate}
185 \item Add an edge $\pc \hasdirdep \pd$ to the digraph (adding nodes
186 as necessary).
187 If this results in a cycle, abort entirely (as the function $g$ is
188 inappropriate; a different $g$ could work).
189 \item Run $\alg{Rank-Recurse}(\pd)$.
190 \end{enumerate}
191
192 \end{enumerate}
193
194 \subsection{Results of the ranking phase}
195
196 By the end of the ranking phase, we have recorded the following
197 information:
198
199 \begin{itemize}
200 \item
201 $ \allpatches, \hasdirdep $ and hence the completion of $\hasdirdep$
202 into the partial order $\hasdep$.
203
204 \item
205 For each $\pc \in \allpatches$,
206 the base branch starting point commit $W^{\pcn} = W$.
207
208 \item
209 For each $\pc$,
210 the direct dependencies $\Gamma^{\pc} = \Gamma$.
211
212 \item
213 For each $\pc$,
214 the ordered set of base branch sources $\set S^{\pcn} = \set S,
215 S^{\pcn}_i = S_i$
216 and corresponding merge bases $M^{\pcn}_i = M_i$.
217
218 \end{itemize}
219
220 \subsection{Proof of termination}
221
222 $\alg{Rank-Recurse}(\pc)$ recurses but only downwards through the
223 finite graph $\hasdirdep$, so it must terminate.  
224
225 The whole ranking algorithm iterates but each iteration involves
226 adding one or more patches to $\allpatches$.  Since there are
227 finitely many patches and we never remove anything from $\allpatches$
228 this must complete eventually.
229
230 $\qed$
231
232 \section{Traversal phase --- algorithm}
233
234 (In general, unless stated otherwise below, when we generate a new
235 commit $C$ using one of the commit kind algorith, we update
236 $W \assign C$.  In any such case where we say we're going to Merge
237 with $L = W$, if $R \ge W$ we do not Merge but instead simply set
238 $W \assign R$.)
239
240
241 For each patch $\pc \in \allpatches$ in topological order by $\hasdep$,
242 lowest first:
243
244 \begin{enumerate}
245
246 \item Optionally, attempt
247  $\alg{Merge-Base}(\pc)$.  This may or may not succeed.
248
249 \item If this didn't succeed, or was not attempted, execute
250  $\alg{Recreate-Base}(\pc)$.
251
252 \item Then in any case, execute
253  $\alg{Merge-Tip}(\pc)$.
254
255 \end{enumerate}
256
257 After processing each $\pc$ we will have created:
258
259 \begin{itemize}
260
261 \item $\tipcn$ and $\tipcy$ such that $\baseof{\tipcy} = \tipcn$.
262
263 \end{itemize}
264
265 \subsection{$\alg{Merge-Base}(\pc)$}
266
267 This algorithm attempts to construct a suitably updated version of the
268 base branch $\pcn$ using some existing version of $\pcn$ as a starting
269 point.
270
271 It should be executed noninteractively.  Specifically, if any step
272 fails with a merge conflict, the whole thing should be abandoned.
273 This avoids asking the user to resolve confusing conflicts.  It also
274 avoids asking the user to pointlessly resolve conflicts in situations
275 where we will later discover that $\alg{Merge-Base}$ wasn't feasible
276 after all.
277
278 If $\pc$ has only one direct dependency, this algorithm should not be
279 used as in that case $\alg{Recreate-Base}$ is trivial and guaranteed
280 to generate a perfect answer, whereas this algorithm might involve
281 merges and therefore might not produce a perfect answer if the
282 situation is complicated.
283
284 Initially, set $W \iassign W^{\pcn}$.
285
286 \subsubsection{Bases and sources}
287
288 In some order, perhaps interleaving the two kinds of merge:
289
290 \begin{enumerate}
291
292 \item For each $\pd \isdirdep \pc$, find a merge base
293 $M \le W,\; \le \tipdy$ and merge $\tipdy$ into $W$.
294 That is, use $\alg{Merge}$ with $L = W,\; R = \tipdy$.
295 (Dependency Merge.)
296
297 \item For each $S \in S^{\pcn}_i$, merge it into $W$.
298 That is, use $\alg{Merge}$ with $L = W,\; R = S,\; M = M^{\pcn}_i$.
299 (Base Sibling Merge.)
300
301 \end{enumerate}
302
303 \subsubsection{Fixup}
304
305 Execute $\alg{Fixup-Base}(W,\pc)$.
306
307
308 \subsection{$\alg{Recreate-Base}(\pc)$}
309
310 \begin{enumerate}
311
312 \item
313
314 Choose a $\hasdep$-maximal direct dependency $\pd$ of $\pc$.
315
316 \item
317
318 Use $\alg{Create Base}$ with $L$ = $\pdy,\; \pq = \pc$ to generate $C$
319 and set $W \iassign C$.  (Recreate Base Beginning.)
320
321 \item
322
323 Execute the subalgorithm $\alg{Recreate-Recurse}(\pc)$.
324
325 \item
326
327 Declare that we contain all of the relevant information from the
328 sources.  That is, use $\alg{Pseudo-merge}$ with $L = W, \;
329 \set R = \{ W \} \cup \set S^{\pcn}$.
330 (Recreate Base Final Declaration.)
331
332 \end{enumerate}
333
334 \subsubsection{$\alg{Recreate-Recurse}(\pd)$}
335
336 \begin{enumerate}
337
338 \item Is $W \haspatch \pd$ ?  If so, there is nothing to do: return.
339
340 \item TODO what about non-Topbloke base branches
341
342 \item Use $\alg{Pseudo-Merge}$ with $L = W,\; \set R = \{ \tipdn \}$.
343 (Recreate Base Dependency Base Declaration.)
344
345 \item For all $\hasdep$-maximal $\pd' \isdirdep \pd$,
346 execute $\alg{Recreate-Recurse}(\pd')$.
347
348 \item Use $\alg{Merge}$ to apply $\pd$ to $W$.  That is,
349 $L = W, \; R = \tipdy, \; M = \baseof{R} = \tipdn$.
350 (Recreate Reapply.)
351
352 \end{enumerate}
353
354
355 \subsection{$\alg{Merge-Tip}(\pc)$}
356
357 \begin{enumerate}
358
359 \item TODO CHOOSE/REFINE W AND S as was done during Ranking for bases
360
361 \item $\alg{Merge}$ from $\tipcn$.  That is, $L = W, \;
362 R = \tipcn$ and choose any suitable $M$.  (Tip Base Merge.)
363
364 \item For each source $S \in \set S^{\pcy}$,
365 $\alg{Merge}$ with $L = W, \; R = S$ and any suitable $M$.
366 (Tip Source Merge.)
367
368 \end{enumerate}
369
370
371 \section{Traversal phase --- proofs}
372
373 For each operation called for by the traversal algorithms, we prove
374 that the commit generation preconditions are met.
375
376 \subsection{Tip Base Merge}
377