Fossil SCM

Improved graph display when a single checkin is the parent of both a normal and a cherrypick merge.

drh 2018-12-28 16:21 trunk
Commit 30aec47aa0cf8d2c6dcc1da8534eb8022c67ef66fb41df14083323886e5b6129
+10 -4
--- src/graph.c
+++ src/graph.c
@@ -57,10 +57,11 @@
5757
i8 iRail; /* Which rail this check-in appears on. 0-based.*/
5858
i8 mergeOut; /* Merge out to this rail. -1 if no merge-out */
5959
u8 mergeIn[GR_MAX_RAIL]; /* Merge in from non-zero rails */
6060
int aiRiser[GR_MAX_RAIL]; /* Risers from this node to a higher row. */
6161
int mergeUpto; /* Draw the mergeOut rail up to this level */
62
+ int cherrypickUpto; /* Continue the mergeOut rail up to here */
6263
u64 mergeDown; /* Draw merge lines up from bottom of graph */
6364
u64 cherrypickDown; /* Draw cherrypick lines up from bottom */
6465
6566
u64 railInUse; /* Mask of occupied rails at this row */
6667
};
@@ -308,26 +309,31 @@
308309
if( u>=0 && u<pChild->idx ){
309310
/* The thick arrow up to the next primary child of pDesc goes
310311
** further up than the thin merge arrow riser, so draw them both
311312
** on the same rail. */
312313
pParent->mergeOut = pParent->iRail;
313
- pParent->mergeUpto = pChild->idx;
314
- }else{
314
+ }else{
315315
/* The thin merge arrow riser is taller than the thick primary
316316
** child riser, so use separate rails. */
317317
int iTarget = pParent->iRail;
318318
pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1, iTarget);
319
- pParent->mergeUpto = pChild->idx;
320319
mask = BIT(pParent->mergeOut);
321320
for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid;
322321
pLoop=pLoop->pNext){
323322
pLoop->railInUse |= mask;
324323
}
325324
}
326325
}
327
- if( !isCherrypick ){
326
+ if( isCherrypick ){
327
+ if( pParent->cherrypickUpto==0 || pParent->cherrypickUpto > pChild->idx ){
328
+ pParent->cherrypickUpto = pChild->idx;
329
+ }
330
+ }else{
328331
pParent->hasNormalOutMerge = 1;
332
+ if( pParent->mergeUpto==0 || pParent->mergeUpto > pChild->idx ){
333
+ pParent->mergeUpto = pChild->idx;
334
+ }
329335
}
330336
pChild->mergeIn[pParent->mergeOut] = isCherrypick ? 2 : 1;
331337
}
332338
333339
/*
334340
--- src/graph.c
+++ src/graph.c
@@ -57,10 +57,11 @@
57 i8 iRail; /* Which rail this check-in appears on. 0-based.*/
58 i8 mergeOut; /* Merge out to this rail. -1 if no merge-out */
59 u8 mergeIn[GR_MAX_RAIL]; /* Merge in from non-zero rails */
60 int aiRiser[GR_MAX_RAIL]; /* Risers from this node to a higher row. */
61 int mergeUpto; /* Draw the mergeOut rail up to this level */
 
62 u64 mergeDown; /* Draw merge lines up from bottom of graph */
63 u64 cherrypickDown; /* Draw cherrypick lines up from bottom */
64
65 u64 railInUse; /* Mask of occupied rails at this row */
66 };
@@ -308,26 +309,31 @@
308 if( u>=0 && u<pChild->idx ){
309 /* The thick arrow up to the next primary child of pDesc goes
310 ** further up than the thin merge arrow riser, so draw them both
311 ** on the same rail. */
312 pParent->mergeOut = pParent->iRail;
313 pParent->mergeUpto = pChild->idx;
314 }else{
315 /* The thin merge arrow riser is taller than the thick primary
316 ** child riser, so use separate rails. */
317 int iTarget = pParent->iRail;
318 pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1, iTarget);
319 pParent->mergeUpto = pChild->idx;
320 mask = BIT(pParent->mergeOut);
321 for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid;
322 pLoop=pLoop->pNext){
323 pLoop->railInUse |= mask;
324 }
325 }
326 }
327 if( !isCherrypick ){
 
 
 
 
328 pParent->hasNormalOutMerge = 1;
 
 
 
329 }
330 pChild->mergeIn[pParent->mergeOut] = isCherrypick ? 2 : 1;
331 }
332
333 /*
334
--- src/graph.c
+++ src/graph.c
@@ -57,10 +57,11 @@
57 i8 iRail; /* Which rail this check-in appears on. 0-based.*/
58 i8 mergeOut; /* Merge out to this rail. -1 if no merge-out */
59 u8 mergeIn[GR_MAX_RAIL]; /* Merge in from non-zero rails */
60 int aiRiser[GR_MAX_RAIL]; /* Risers from this node to a higher row. */
61 int mergeUpto; /* Draw the mergeOut rail up to this level */
62 int cherrypickUpto; /* Continue the mergeOut rail up to here */
63 u64 mergeDown; /* Draw merge lines up from bottom of graph */
64 u64 cherrypickDown; /* Draw cherrypick lines up from bottom */
65
66 u64 railInUse; /* Mask of occupied rails at this row */
67 };
@@ -308,26 +309,31 @@
309 if( u>=0 && u<pChild->idx ){
310 /* The thick arrow up to the next primary child of pDesc goes
311 ** further up than the thin merge arrow riser, so draw them both
312 ** on the same rail. */
313 pParent->mergeOut = pParent->iRail;
314 }else{
 
315 /* The thin merge arrow riser is taller than the thick primary
316 ** child riser, so use separate rails. */
317 int iTarget = pParent->iRail;
318 pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1, iTarget);
 
319 mask = BIT(pParent->mergeOut);
320 for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid;
321 pLoop=pLoop->pNext){
322 pLoop->railInUse |= mask;
323 }
324 }
325 }
326 if( isCherrypick ){
327 if( pParent->cherrypickUpto==0 || pParent->cherrypickUpto > pChild->idx ){
328 pParent->cherrypickUpto = pChild->idx;
329 }
330 }else{
331 pParent->hasNormalOutMerge = 1;
332 if( pParent->mergeUpto==0 || pParent->mergeUpto > pChild->idx ){
333 pParent->mergeUpto = pChild->idx;
334 }
335 }
336 pChild->mergeIn[pParent->mergeOut] = isCherrypick ? 2 : 1;
337 }
338
339 /*
340
+48 -16
--- src/graph.js
+++ src/graph.js
@@ -21,34 +21,44 @@
2121
** The rowinfo field is an array of structures, one per entry in the timeline,
2222
** where each structure has the following fields:
2323
**
2424
** id: The id of the <div> element for the row. This is an integer.
2525
** to get an actual id, prepend "m" to the integer. The top node
26
-** is iTopRow and numbers increase moving down the graph.
26
+** is iTopRow and numbers increase moving down the timeline.
2727
** bg: The background color for this row
2828
** r: The "rail" that the node for this row sits on. The left-most
2929
** rail is 0 and the number increases to the right.
30
-** d: True if there is a "descender" - an arrow coming from the bottom
31
-** of the page straight up to this node.
32
-** mo: "merge-out". If non-negative, this is the rail position
30
+** d: If exists and true then there is a "descender" - an arrow
31
+** coming from the bottom of the page straight up to this node.
32
+** mo: "merge-out". If it exists, this is the rail position
3333
** for the upward portion of a merge arrow. The merge arrow goes up
34
-** to the row identified by mu:. If this value is negative then
34
+** to the row identified by mu:. If this value is omitted then
3535
** node has no merge children and no merge-out line is drawn.
3636
** mu: The id of the row which is the top of the merge-out arrow.
37
+** Only exists if "mo" exists.
38
+** cu: The id of the top row of the merge-out arrow for a cherrypick
39
+** merge arrow that extends beyond the main merge arrow. Only
40
+** exists if "mo" exists and if there is a cherrpick merge that is
41
+** higher than "mu".
3742
** u: Draw a thick child-line out of the top of this node and up to
3843
** the node with an id equal to this value. 0 if it is straight to
3944
** the top of the page, -1 if there is no thick-line riser.
4045
** f: 0x01: a leaf node.
46
+** 0x02: all output merges are cherrypicks
4147
** au: An array of integers that define thick-line risers for branches.
4248
** The integers are in pairs. For each pair, the first integer is
4349
** is the rail on which the riser should run and the second integer
44
-** is the id of the node upto which the riser should run.
50
+** is the id of the node upto which the riser should run. If there
51
+** are no risers, this array does not exist.
4552
** mi: "merge-in". An array of integer rail positions from which
4653
** merge arrows should be drawn into this node. If the value is
4754
** negative, then the rail position is the absolute value of mi[]
4855
** and a thin merge-arrow descender is drawn to the bottom of
49
-** the screen.
56
+** the screen. This array is omitted if there are no inbound
57
+** merges.
58
+** ci: "cherrypick-in". Like "mi" except for cherrypick merges.
59
+** omitted if there are no cherrypick merges.
5060
** h: The artifact hash of the object being graphed
5161
*/
5262
var amendCssOnce = 1; // Only change the CSS one time
5363
function amendCss(circleNodes,showArrowheads){
5464
if( !amendCssOnce ) return;
@@ -244,20 +254,36 @@
244254
if( p.hasOwnProperty('mo') ){
245255
var x0 = p.x + node.w/2;
246256
var x1 = p.mo*railPitch + node.w/2;
247257
var u = tx.rowinfo[p.mu-tx.iTopRow];
248258
var y1 = miLineY(u);
249
- var drawMethod = (p.f&2) ? drawCherrypickLine : drawMergeLine;
250259
if( p.u<0 || p.mo!=p.r ){
251260
x1 += mergeLines[p.mo] = -mLine.w/2;
252261
var y0 = p.y+2;
253
- if( p.r!=p.mo ) drawMethod(x0,y0,x1+(x0<x1 ? mLine.w : 0),null);
254
- drawMethod(x1,y0+mLine.w,null,y1);
262
+ if( p.mu==p.id ){
263
+ drawCherrypickLine(x0,y0,x1+(x0<x1 ? mLine.w : 0),null);
264
+ y1 = y0;
265
+ }else{
266
+ drawMergeLine(x0,y0,x1+(x0<x1 ? mLine.w : 0),null);
267
+ drawMergeLine(x1,y0+mLine.w,null,y1);
268
+ }
269
+ if( p.hasOwnProperty('cu') ){
270
+ var u2 = tx.rowinfo[p.cu-tx.iTopRow];
271
+ var y2 = miLineY(u2);
272
+ drawCherrypickLine(x1,y1,null,y2);
273
+ }
255274
}else if( mergeOffset ){
256275
mergeLines[p.mo] = u.r<p.r ? -mergeOffset-mLine.w : mergeOffset;
257276
x1 += mergeLines[p.mo];
258
- drawMethod(x1,p.y+node.h/2,null,y1);
277
+ if( p.mo<p.id ){
278
+ drawMergeLine(x1,p.y+node.h/2,null,y1);
279
+ }
280
+ if( p.hasOwnProperty('cu') ){
281
+ var u2 = tx.rowinfo[p.cu-tx.iTopRow];
282
+ var y2 = miLineY(u2);
283
+ drawCherrypickLine(x1,y1,null,y2);
284
+ }
259285
}else{
260286
delete mergeLines[p.mo];
261287
}
262288
}
263289
if( p.hasOwnProperty('au') ){
@@ -291,29 +317,34 @@
291317
var rail = p.mi[i];
292318
if( rail<0 ){
293319
rail = -rail;
294320
mergeLines[rail] = -mLine.w/2;
295321
var x = rail*railPitch + (node.w-mLine.w)/2;
296
- drawMergeLine(x,miLineY(p),null,btm);
322
+ var y = miLineY(p);
323
+ drawMergeLine(x,y,null,mergeBtm[rail]);
324
+ mergeBtm[rail] = y;
297325
}
298326
drawMergeArrow(p,rail,0);
299327
}
300328
}
301
- if( p.hasOwnProperty('cpi') ){
302
- for( var i=0; i<p.cpi.length; i++ ){
303
- var rail = p.cpi[i];
329
+ if( p.hasOwnProperty('ci') ){
330
+ for( var i=0; i<p.ci.length; i++ ){
331
+ var rail = p.ci[i];
304332
if( rail<0 ){
305333
rail = -rail;
306334
mergeLines[rail] = -mLine.w/2;
307335
var x = rail*railPitch + (node.w-mLine.w)/2;
308
- drawCherrypickLine(x,miLineY(p),null,btm);
336
+ var y = miLineY(p);
337
+ drawCherrypickLine(x,y,null,mergeBtm[rail]);
338
+ mergeBtm[rail] = y;
309339
}
310340
drawMergeArrow(p,rail,1);
311341
}
312342
}
313343
}
314344
var mergeLines;
345
+ var mergeBtm = new Array;
315346
function renderGraph(){
316347
mergeLines = {};
317348
canvasDiv.innerHTML = "";
318349
var canvasY = absoluteY(canvasDiv);
319350
for(var i=0; i<tx.rowinfo.length; i++ ){
@@ -324,10 +355,11 @@
324355
var tlBtm = document.querySelector(".timelineBottom");
325356
if( tlBtm.offsetHeight<node.h ){
326357
tlBtm.style.height = node.h + "px";
327358
}
328359
var btm = absoluteY(tlBtm) - canvasY + tlBtm.offsetHeight;
360
+ for( var i=0; i<tx.nrail; i++) mergeBtm[i] = btm;
329361
for( var i=tx.rowinfo.length-1; i>=0; i-- ){
330362
drawNode(tx.rowinfo[i], btm);
331363
}
332364
}
333365
var selRow;
334366
--- src/graph.js
+++ src/graph.js
@@ -21,34 +21,44 @@
21 ** The rowinfo field is an array of structures, one per entry in the timeline,
22 ** where each structure has the following fields:
23 **
24 ** id: The id of the <div> element for the row. This is an integer.
25 ** to get an actual id, prepend "m" to the integer. The top node
26 ** is iTopRow and numbers increase moving down the graph.
27 ** bg: The background color for this row
28 ** r: The "rail" that the node for this row sits on. The left-most
29 ** rail is 0 and the number increases to the right.
30 ** d: True if there is a "descender" - an arrow coming from the bottom
31 ** of the page straight up to this node.
32 ** mo: "merge-out". If non-negative, this is the rail position
33 ** for the upward portion of a merge arrow. The merge arrow goes up
34 ** to the row identified by mu:. If this value is negative then
35 ** node has no merge children and no merge-out line is drawn.
36 ** mu: The id of the row which is the top of the merge-out arrow.
 
 
 
 
 
37 ** u: Draw a thick child-line out of the top of this node and up to
38 ** the node with an id equal to this value. 0 if it is straight to
39 ** the top of the page, -1 if there is no thick-line riser.
40 ** f: 0x01: a leaf node.
 
41 ** au: An array of integers that define thick-line risers for branches.
42 ** The integers are in pairs. For each pair, the first integer is
43 ** is the rail on which the riser should run and the second integer
44 ** is the id of the node upto which the riser should run.
 
45 ** mi: "merge-in". An array of integer rail positions from which
46 ** merge arrows should be drawn into this node. If the value is
47 ** negative, then the rail position is the absolute value of mi[]
48 ** and a thin merge-arrow descender is drawn to the bottom of
49 ** the screen.
 
 
 
50 ** h: The artifact hash of the object being graphed
51 */
52 var amendCssOnce = 1; // Only change the CSS one time
53 function amendCss(circleNodes,showArrowheads){
54 if( !amendCssOnce ) return;
@@ -244,20 +254,36 @@
244 if( p.hasOwnProperty('mo') ){
245 var x0 = p.x + node.w/2;
246 var x1 = p.mo*railPitch + node.w/2;
247 var u = tx.rowinfo[p.mu-tx.iTopRow];
248 var y1 = miLineY(u);
249 var drawMethod = (p.f&2) ? drawCherrypickLine : drawMergeLine;
250 if( p.u<0 || p.mo!=p.r ){
251 x1 += mergeLines[p.mo] = -mLine.w/2;
252 var y0 = p.y+2;
253 if( p.r!=p.mo ) drawMethod(x0,y0,x1+(x0<x1 ? mLine.w : 0),null);
254 drawMethod(x1,y0+mLine.w,null,y1);
 
 
 
 
 
 
 
 
 
 
255 }else if( mergeOffset ){
256 mergeLines[p.mo] = u.r<p.r ? -mergeOffset-mLine.w : mergeOffset;
257 x1 += mergeLines[p.mo];
258 drawMethod(x1,p.y+node.h/2,null,y1);
 
 
 
 
 
 
 
259 }else{
260 delete mergeLines[p.mo];
261 }
262 }
263 if( p.hasOwnProperty('au') ){
@@ -291,29 +317,34 @@
291 var rail = p.mi[i];
292 if( rail<0 ){
293 rail = -rail;
294 mergeLines[rail] = -mLine.w/2;
295 var x = rail*railPitch + (node.w-mLine.w)/2;
296 drawMergeLine(x,miLineY(p),null,btm);
 
 
297 }
298 drawMergeArrow(p,rail,0);
299 }
300 }
301 if( p.hasOwnProperty('cpi') ){
302 for( var i=0; i<p.cpi.length; i++ ){
303 var rail = p.cpi[i];
304 if( rail<0 ){
305 rail = -rail;
306 mergeLines[rail] = -mLine.w/2;
307 var x = rail*railPitch + (node.w-mLine.w)/2;
308 drawCherrypickLine(x,miLineY(p),null,btm);
 
 
309 }
310 drawMergeArrow(p,rail,1);
311 }
312 }
313 }
314 var mergeLines;
 
315 function renderGraph(){
316 mergeLines = {};
317 canvasDiv.innerHTML = "";
318 var canvasY = absoluteY(canvasDiv);
319 for(var i=0; i<tx.rowinfo.length; i++ ){
@@ -324,10 +355,11 @@
324 var tlBtm = document.querySelector(".timelineBottom");
325 if( tlBtm.offsetHeight<node.h ){
326 tlBtm.style.height = node.h + "px";
327 }
328 var btm = absoluteY(tlBtm) - canvasY + tlBtm.offsetHeight;
 
329 for( var i=tx.rowinfo.length-1; i>=0; i-- ){
330 drawNode(tx.rowinfo[i], btm);
331 }
332 }
333 var selRow;
334
--- src/graph.js
+++ src/graph.js
@@ -21,34 +21,44 @@
21 ** The rowinfo field is an array of structures, one per entry in the timeline,
22 ** where each structure has the following fields:
23 **
24 ** id: The id of the <div> element for the row. This is an integer.
25 ** to get an actual id, prepend "m" to the integer. The top node
26 ** is iTopRow and numbers increase moving down the timeline.
27 ** bg: The background color for this row
28 ** r: The "rail" that the node for this row sits on. The left-most
29 ** rail is 0 and the number increases to the right.
30 ** d: If exists and true then there is a "descender" - an arrow
31 ** coming from the bottom of the page straight up to this node.
32 ** mo: "merge-out". If it exists, this is the rail position
33 ** for the upward portion of a merge arrow. The merge arrow goes up
34 ** to the row identified by mu:. If this value is omitted then
35 ** node has no merge children and no merge-out line is drawn.
36 ** mu: The id of the row which is the top of the merge-out arrow.
37 ** Only exists if "mo" exists.
38 ** cu: The id of the top row of the merge-out arrow for a cherrypick
39 ** merge arrow that extends beyond the main merge arrow. Only
40 ** exists if "mo" exists and if there is a cherrpick merge that is
41 ** higher than "mu".
42 ** u: Draw a thick child-line out of the top of this node and up to
43 ** the node with an id equal to this value. 0 if it is straight to
44 ** the top of the page, -1 if there is no thick-line riser.
45 ** f: 0x01: a leaf node.
46 ** 0x02: all output merges are cherrypicks
47 ** au: An array of integers that define thick-line risers for branches.
48 ** The integers are in pairs. For each pair, the first integer is
49 ** is the rail on which the riser should run and the second integer
50 ** is the id of the node upto which the riser should run. If there
51 ** are no risers, this array does not exist.
52 ** mi: "merge-in". An array of integer rail positions from which
53 ** merge arrows should be drawn into this node. If the value is
54 ** negative, then the rail position is the absolute value of mi[]
55 ** and a thin merge-arrow descender is drawn to the bottom of
56 ** the screen. This array is omitted if there are no inbound
57 ** merges.
58 ** ci: "cherrypick-in". Like "mi" except for cherrypick merges.
59 ** omitted if there are no cherrypick merges.
60 ** h: The artifact hash of the object being graphed
61 */
62 var amendCssOnce = 1; // Only change the CSS one time
63 function amendCss(circleNodes,showArrowheads){
64 if( !amendCssOnce ) return;
@@ -244,20 +254,36 @@
254 if( p.hasOwnProperty('mo') ){
255 var x0 = p.x + node.w/2;
256 var x1 = p.mo*railPitch + node.w/2;
257 var u = tx.rowinfo[p.mu-tx.iTopRow];
258 var y1 = miLineY(u);
 
259 if( p.u<0 || p.mo!=p.r ){
260 x1 += mergeLines[p.mo] = -mLine.w/2;
261 var y0 = p.y+2;
262 if( p.mu==p.id ){
263 drawCherrypickLine(x0,y0,x1+(x0<x1 ? mLine.w : 0),null);
264 y1 = y0;
265 }else{
266 drawMergeLine(x0,y0,x1+(x0<x1 ? mLine.w : 0),null);
267 drawMergeLine(x1,y0+mLine.w,null,y1);
268 }
269 if( p.hasOwnProperty('cu') ){
270 var u2 = tx.rowinfo[p.cu-tx.iTopRow];
271 var y2 = miLineY(u2);
272 drawCherrypickLine(x1,y1,null,y2);
273 }
274 }else if( mergeOffset ){
275 mergeLines[p.mo] = u.r<p.r ? -mergeOffset-mLine.w : mergeOffset;
276 x1 += mergeLines[p.mo];
277 if( p.mo<p.id ){
278 drawMergeLine(x1,p.y+node.h/2,null,y1);
279 }
280 if( p.hasOwnProperty('cu') ){
281 var u2 = tx.rowinfo[p.cu-tx.iTopRow];
282 var y2 = miLineY(u2);
283 drawCherrypickLine(x1,y1,null,y2);
284 }
285 }else{
286 delete mergeLines[p.mo];
287 }
288 }
289 if( p.hasOwnProperty('au') ){
@@ -291,29 +317,34 @@
317 var rail = p.mi[i];
318 if( rail<0 ){
319 rail = -rail;
320 mergeLines[rail] = -mLine.w/2;
321 var x = rail*railPitch + (node.w-mLine.w)/2;
322 var y = miLineY(p);
323 drawMergeLine(x,y,null,mergeBtm[rail]);
324 mergeBtm[rail] = y;
325 }
326 drawMergeArrow(p,rail,0);
327 }
328 }
329 if( p.hasOwnProperty('ci') ){
330 for( var i=0; i<p.ci.length; i++ ){
331 var rail = p.ci[i];
332 if( rail<0 ){
333 rail = -rail;
334 mergeLines[rail] = -mLine.w/2;
335 var x = rail*railPitch + (node.w-mLine.w)/2;
336 var y = miLineY(p);
337 drawCherrypickLine(x,y,null,mergeBtm[rail]);
338 mergeBtm[rail] = y;
339 }
340 drawMergeArrow(p,rail,1);
341 }
342 }
343 }
344 var mergeLines;
345 var mergeBtm = new Array;
346 function renderGraph(){
347 mergeLines = {};
348 canvasDiv.innerHTML = "";
349 var canvasY = absoluteY(canvasDiv);
350 for(var i=0; i<tx.rowinfo.length; i++ ){
@@ -324,10 +355,11 @@
355 var tlBtm = document.querySelector(".timelineBottom");
356 if( tlBtm.offsetHeight<node.h ){
357 tlBtm.style.height = node.h + "px";
358 }
359 var btm = absoluteY(tlBtm) - canvasY + tlBtm.offsetHeight;
360 for( var i=0; i<tx.nrail; i++) mergeBtm[i] = btm;
361 for( var i=tx.rowinfo.length-1; i>=0; i-- ){
362 drawNode(tx.rowinfo[i], btm);
363 }
364 }
365 var selRow;
366
+13 -8
--- src/timeline.c
+++ src/timeline.c
@@ -866,20 +866,22 @@
866866
** r: The "rail" that the node for this row sits on. The left-most
867867
** rail is 0 and the number increases to the right.
868868
** d: If exists and true then there is a "descender" - an arrow
869869
** coming from the bottom of the page straight up to this node.
870870
** mo: "merge-out". If it exists, this is the rail position
871
- ** for the upward portion of a merge arrow. The merge arrow goes up
872
- ** to the row identified by mu:. If this value is omitted then
873
- ** node has no merge children and no merge-out line is drawn.
871
+ ** for the upward portion of a merge arrow. The merge arrow goes as
872
+ ** a solid normal merge line up to the row identified by "mu" and
873
+ ** then as a dashed cherrypick merge line up further to "cu".
874
+ ** If this value is omitted if there are no merge children.
874875
** mu: The id of the row which is the top of the merge-out arrow.
875876
** Only exists if "mo" exists.
877
+ ** cu: Extend the mu merge error on up to this row as a cherrypick
878
+ ** merge line, if this value exists.
876879
** u: Draw a thick child-line out of the top of this node and up to
877880
** the node with an id equal to this value. 0 if it is straight to
878881
** the top of the page, -1 if there is no thick-line riser.
879882
** f: 0x01: a leaf node.
880
- ** 0x02: all output merges are cherrypicks
881883
** au: An array of integers that define thick-line risers for branches.
882884
** The integers are in pairs. For each pair, the first integer is
883885
** is the rail on which the riser should run and the second integer
884886
** is the id of the node upto which the riser should run. If there
885887
** are no risers, this array does not exist.
@@ -887,11 +889,11 @@
887889
** merge arrows should be drawn into this node. If the value is
888890
** negative, then the rail position is the absolute value of mi[]
889891
** and a thin merge-arrow descender is drawn to the bottom of
890892
** the screen. This array is omitted if there are no inbound
891893
** merges.
892
- ** cpi: "cherrypick-in". Like "mi" except for cherrypick merges.
894
+ ** ci: "cherrypick-in". Like "mi" except for cherrypick merges.
893895
** omitted if there are no cherrypick merges.
894896
** h: The artifact hash of the object being graphed
895897
*/
896898
for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){
897899
int k = 0;
@@ -901,16 +903,19 @@
901903
if( pRow->bDescender ){
902904
cgi_printf("\"d\":%d,", pRow->bDescender);
903905
}
904906
if( pRow->mergeOut>=0 ){
905907
cgi_printf("\"mo\":%d,", pRow->mergeOut);
908
+ if( pRow->mergeUpto==0 ) pRow->mergeUpto = pRow->idx;
906909
cgi_printf("\"mu\":%d,", pRow->mergeUpto);
910
+ if( pRow->cherrypickUpto>0 && pRow->cherrypickUpto<pRow->mergeUpto ){
911
+ cgi_printf("\"cu\":%d,", pRow->cherrypickUpto);
912
+ }
907913
}
908914
cgi_printf("\"u\":%d,", pRow->aiRiser[pRow->iRail]);
909915
k = 0;
910916
if( pRow->isLeaf ) k |= 1;
911
- if( !pRow->hasNormalOutMerge ) k |= 2;
912917
cgi_printf("\"f\":%d,",k);
913918
for(i=k=0; i<GR_MAX_RAIL; i++){
914919
if( i==pRow->iRail ) continue;
915920
if( pRow->aiRiser[i]>0 ){
916921
if( k==0 ){
@@ -941,17 +946,17 @@
941946
cgi_printf("%c%d", cSep, mi);
942947
cSep = ',';
943948
}
944949
}
945950
if( k ) cgi_printf("],");
946
- /* cpi */
951
+ /* ci */
947952
for(i=k=0; i<GR_MAX_RAIL; i++){
948953
if( pRow->mergeIn[i]==2 ){
949954
int mi = i;
950955
if( (pRow->cherrypickDown >> i) & 1 ) mi = -mi;
951956
if( k==0 ){
952
- cgi_printf("\"cpi\":");
957
+ cgi_printf("\"ci\":");
953958
cSep = '[';
954959
}
955960
k++;
956961
cgi_printf("%c%d", cSep, mi);
957962
cSep = ',';
958963
--- src/timeline.c
+++ src/timeline.c
@@ -866,20 +866,22 @@
866 ** r: The "rail" that the node for this row sits on. The left-most
867 ** rail is 0 and the number increases to the right.
868 ** d: If exists and true then there is a "descender" - an arrow
869 ** coming from the bottom of the page straight up to this node.
870 ** mo: "merge-out". If it exists, this is the rail position
871 ** for the upward portion of a merge arrow. The merge arrow goes up
872 ** to the row identified by mu:. If this value is omitted then
873 ** node has no merge children and no merge-out line is drawn.
 
874 ** mu: The id of the row which is the top of the merge-out arrow.
875 ** Only exists if "mo" exists.
 
 
876 ** u: Draw a thick child-line out of the top of this node and up to
877 ** the node with an id equal to this value. 0 if it is straight to
878 ** the top of the page, -1 if there is no thick-line riser.
879 ** f: 0x01: a leaf node.
880 ** 0x02: all output merges are cherrypicks
881 ** au: An array of integers that define thick-line risers for branches.
882 ** The integers are in pairs. For each pair, the first integer is
883 ** is the rail on which the riser should run and the second integer
884 ** is the id of the node upto which the riser should run. If there
885 ** are no risers, this array does not exist.
@@ -887,11 +889,11 @@
887 ** merge arrows should be drawn into this node. If the value is
888 ** negative, then the rail position is the absolute value of mi[]
889 ** and a thin merge-arrow descender is drawn to the bottom of
890 ** the screen. This array is omitted if there are no inbound
891 ** merges.
892 ** cpi: "cherrypick-in". Like "mi" except for cherrypick merges.
893 ** omitted if there are no cherrypick merges.
894 ** h: The artifact hash of the object being graphed
895 */
896 for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){
897 int k = 0;
@@ -901,16 +903,19 @@
901 if( pRow->bDescender ){
902 cgi_printf("\"d\":%d,", pRow->bDescender);
903 }
904 if( pRow->mergeOut>=0 ){
905 cgi_printf("\"mo\":%d,", pRow->mergeOut);
 
906 cgi_printf("\"mu\":%d,", pRow->mergeUpto);
 
 
 
907 }
908 cgi_printf("\"u\":%d,", pRow->aiRiser[pRow->iRail]);
909 k = 0;
910 if( pRow->isLeaf ) k |= 1;
911 if( !pRow->hasNormalOutMerge ) k |= 2;
912 cgi_printf("\"f\":%d,",k);
913 for(i=k=0; i<GR_MAX_RAIL; i++){
914 if( i==pRow->iRail ) continue;
915 if( pRow->aiRiser[i]>0 ){
916 if( k==0 ){
@@ -941,17 +946,17 @@
941 cgi_printf("%c%d", cSep, mi);
942 cSep = ',';
943 }
944 }
945 if( k ) cgi_printf("],");
946 /* cpi */
947 for(i=k=0; i<GR_MAX_RAIL; i++){
948 if( pRow->mergeIn[i]==2 ){
949 int mi = i;
950 if( (pRow->cherrypickDown >> i) & 1 ) mi = -mi;
951 if( k==0 ){
952 cgi_printf("\"cpi\":");
953 cSep = '[';
954 }
955 k++;
956 cgi_printf("%c%d", cSep, mi);
957 cSep = ',';
958
--- src/timeline.c
+++ src/timeline.c
@@ -866,20 +866,22 @@
866 ** r: The "rail" that the node for this row sits on. The left-most
867 ** rail is 0 and the number increases to the right.
868 ** d: If exists and true then there is a "descender" - an arrow
869 ** coming from the bottom of the page straight up to this node.
870 ** mo: "merge-out". If it exists, this is the rail position
871 ** for the upward portion of a merge arrow. The merge arrow goes as
872 ** a solid normal merge line up to the row identified by "mu" and
873 ** then as a dashed cherrypick merge line up further to "cu".
874 ** If this value is omitted if there are no merge children.
875 ** mu: The id of the row which is the top of the merge-out arrow.
876 ** Only exists if "mo" exists.
877 ** cu: Extend the mu merge error on up to this row as a cherrypick
878 ** merge line, if this value exists.
879 ** u: Draw a thick child-line out of the top of this node and up to
880 ** the node with an id equal to this value. 0 if it is straight to
881 ** the top of the page, -1 if there is no thick-line riser.
882 ** f: 0x01: a leaf node.
 
883 ** au: An array of integers that define thick-line risers for branches.
884 ** The integers are in pairs. For each pair, the first integer is
885 ** is the rail on which the riser should run and the second integer
886 ** is the id of the node upto which the riser should run. If there
887 ** are no risers, this array does not exist.
@@ -887,11 +889,11 @@
889 ** merge arrows should be drawn into this node. If the value is
890 ** negative, then the rail position is the absolute value of mi[]
891 ** and a thin merge-arrow descender is drawn to the bottom of
892 ** the screen. This array is omitted if there are no inbound
893 ** merges.
894 ** ci: "cherrypick-in". Like "mi" except for cherrypick merges.
895 ** omitted if there are no cherrypick merges.
896 ** h: The artifact hash of the object being graphed
897 */
898 for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){
899 int k = 0;
@@ -901,16 +903,19 @@
903 if( pRow->bDescender ){
904 cgi_printf("\"d\":%d,", pRow->bDescender);
905 }
906 if( pRow->mergeOut>=0 ){
907 cgi_printf("\"mo\":%d,", pRow->mergeOut);
908 if( pRow->mergeUpto==0 ) pRow->mergeUpto = pRow->idx;
909 cgi_printf("\"mu\":%d,", pRow->mergeUpto);
910 if( pRow->cherrypickUpto>0 && pRow->cherrypickUpto<pRow->mergeUpto ){
911 cgi_printf("\"cu\":%d,", pRow->cherrypickUpto);
912 }
913 }
914 cgi_printf("\"u\":%d,", pRow->aiRiser[pRow->iRail]);
915 k = 0;
916 if( pRow->isLeaf ) k |= 1;
 
917 cgi_printf("\"f\":%d,",k);
918 for(i=k=0; i<GR_MAX_RAIL; i++){
919 if( i==pRow->iRail ) continue;
920 if( pRow->aiRiser[i]>0 ){
921 if( k==0 ){
@@ -941,17 +946,17 @@
946 cgi_printf("%c%d", cSep, mi);
947 cSep = ',';
948 }
949 }
950 if( k ) cgi_printf("],");
951 /* ci */
952 for(i=k=0; i<GR_MAX_RAIL; i++){
953 if( pRow->mergeIn[i]==2 ){
954 int mi = i;
955 if( (pRow->cherrypickDown >> i) & 1 ) mi = -mi;
956 if( k==0 ){
957 cgi_printf("\"ci\":");
958 cSep = '[';
959 }
960 k++;
961 cgi_printf("%c%d", cSep, mi);
962 cSep = ',';
963
--- test/graph-test-1.wiki
+++ test/graph-test-1.wiki
@@ -84,10 +84,14 @@
8484
Cherrypick merge arrows</a>
8585
* <a href="../../../timeline?r=branch-1.37" target="testwindow">Branch
8686
1.37 with cherry-pick merges from trunk.</a>
8787
* <a href="../../../timeline?f=68bd2e7bedb8d05a" target="testwindow">
8888
Single check-in takes both a full merge and a cherrypick merge</a>
89
+ * <a href="../../../timeline?b=?b=dc81ac70&n=14" target="testwindow">
90
+ Mixed merge arrow, partly fully and partly cherrypick</a>
91
+ * <a href="../../../timeline?b=?b=dc81ac70&n=13" target="testwindow">
92
+ Mixed merge arrow to bottom of screen.</a>
8993
9094
External:
9195
9296
* <a href="http://www.sqlite.org/src/timeline?c=2010-09-29&nd"
9397
target="testwindow">Timewarp due to a mis-configured system clock.</a>
9498
--- test/graph-test-1.wiki
+++ test/graph-test-1.wiki
@@ -84,10 +84,14 @@
84 Cherrypick merge arrows</a>
85 * <a href="../../../timeline?r=branch-1.37" target="testwindow">Branch
86 1.37 with cherry-pick merges from trunk.</a>
87 * <a href="../../../timeline?f=68bd2e7bedb8d05a" target="testwindow">
88 Single check-in takes both a full merge and a cherrypick merge</a>
 
 
 
 
89
90 External:
91
92 * <a href="http://www.sqlite.org/src/timeline?c=2010-09-29&nd"
93 target="testwindow">Timewarp due to a mis-configured system clock.</a>
94
--- test/graph-test-1.wiki
+++ test/graph-test-1.wiki
@@ -84,10 +84,14 @@
84 Cherrypick merge arrows</a>
85 * <a href="../../../timeline?r=branch-1.37" target="testwindow">Branch
86 1.37 with cherry-pick merges from trunk.</a>
87 * <a href="../../../timeline?f=68bd2e7bedb8d05a" target="testwindow">
88 Single check-in takes both a full merge and a cherrypick merge</a>
89 * <a href="../../../timeline?b=?b=dc81ac70&n=14" target="testwindow">
90 Mixed merge arrow, partly fully and partly cherrypick</a>
91 * <a href="../../../timeline?b=?b=dc81ac70&n=13" target="testwindow">
92 Mixed merge arrow to bottom of screen.</a>
93
94 External:
95
96 * <a href="http://www.sqlite.org/src/timeline?c=2010-09-29&nd"
97 target="testwindow">Timewarp due to a mis-configured system clock.</a>
98

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button