Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Show cherrypick merges on the default timeline. Disable the display of cherrypicks using the "ncp" query parameter. Currently, the only display difference between a normal merge and a cherrypick merges is in the final horizontal segment of the merge line as it moves into the child node. More work is needed on the display logic. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
55ab522ceee25230fb628d9e8cafbdb5 |
User & Date: | drh 2018-12-27 19:39:21.196 |
Context
2018-12-27
| ||
19:55 | Attempt to draw the entire length of a cherrypick merge line using a dashed line. ... (check-in: 236586d6 user: drh tags: trunk) | |
19:39 | Show cherrypick merges on the default timeline. Disable the display of cherrypicks using the "ncp" query parameter. Currently, the only display difference between a normal merge and a cherrypick merges is in the final horizontal segment of the merge line as it moves into the child node. More work is needed on the display logic. ... (check-in: 55ab522c user: drh tags: trunk) | |
16:22 | Omit unused elements of the "rowinfo" JSON element used to generate a timeline graph. ... (check-in: c0a5083e user: drh tags: trunk) | |
Changes
Changes to src/default_css.txt.
︙ | ︙ | |||
156 157 158 159 160 161 162 163 164 165 166 167 168 169 | border-right: 3px solid #000; } .tl-arrow.merge.r { border-left: 3px solid #000; } .tl-line.merge { width: 1px; } .tl-arrow.warp { margin-left: 1px; border-width: 3px 0; border-left: 7px solid #600000; } .tl-line.warp { | > > > > > > > > > > > > > > > | 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | border-right: 3px solid #000; } .tl-arrow.merge.r { border-left: 3px solid #000; } .tl-line.merge { width: 1px; } .tl-arrow.cherrypick { height: 1px; border-width: 2px 0; } .tl-arrow.cherrypick.l { border-right: 3px solid #000; } .tl-arrow.cherrypick.r { border-left: 3px solid #000; } .tl-line.cherrypick { width: 0px; border-top: 1px dashed #000; background: #fff; } .tl-arrow.warp { margin-left: 1px; border-width: 3px 0; border-left: 7px solid #600000; } .tl-line.warp { |
︙ | ︙ |
Changes to src/finfo.c.
︙ | ︙ | |||
501 502 503 504 505 506 507 | if( zBr==0 ) zBr = "trunk"; if( uBg ){ zBgClr = hash_color(zUser); }else if( brBg || zBgClr==0 || zBgClr[0]==0 ){ zBgClr = strcmp(zBr,"trunk")==0 ? "" : hash_color(zBr); } gidx = graph_add_row(pGraph, frid>0 ? frid : fpid+1000000000, | | | 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 | if( zBr==0 ) zBr = "trunk"; if( uBg ){ zBgClr = hash_color(zUser); }else if( brBg || zBgClr==0 || zBgClr[0]==0 ){ zBgClr = strcmp(zBr,"trunk")==0 ? "" : hash_color(zBr); } gidx = graph_add_row(pGraph, frid>0 ? frid : fpid+1000000000, nParent, 0, aParent, zBr, zBgClr, zUuid, 0); if( strncmp(zDate, zPrevDate, 10) ){ sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate); @ <tr><td> @ <div class="divider timelineDate">%s(zPrevDate)</div> @ </td><td></td><td></td></tr> } |
︙ | ︙ |
Changes to src/graph.c.
︙ | ︙ | |||
32 33 34 35 36 37 38 39 40 41 42 43 44 45 | ** ** The nParent field is -1 for entires that do not participate in the graph ** but which are included just so that we can capture their background color. */ struct GraphRow { int rid; /* The rid for the check-in */ i8 nParent; /* Number of parents. -1 for technote lines */ int *aParent; /* Array of parents. 0 element is primary .*/ char *zBranch; /* Branch name */ char *zBgClr; /* Background Color */ char zUuid[HNAME_MAX+1]; /* Check-in for file ID */ GraphRow *pNext; /* Next row down in the list of all rows */ GraphRow *pPrev; /* Previous row */ | > > | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | ** ** The nParent field is -1 for entires that do not participate in the graph ** but which are included just so that we can capture their background color. */ struct GraphRow { int rid; /* The rid for the check-in */ i8 nParent; /* Number of parents. -1 for technote lines */ i8 nCherrypick; /* Subset of aParent that are cherrypicks */ i8 nNonCherrypick; /* Number of non-cherrypick parents */ int *aParent; /* Array of parents. 0 element is primary .*/ char *zBranch; /* Branch name */ char *zBgClr; /* Background Color */ char zUuid[HNAME_MAX+1]; /* Check-in for file ID */ GraphRow *pNext; /* Next row down in the list of all rows */ GraphRow *pPrev; /* Previous row */ |
︙ | ︙ | |||
53 54 55 56 57 58 59 60 61 62 63 64 65 66 | u8 bDescender; /* True if riser from bottom of graph to here. */ i8 iRail; /* Which rail this check-in appears on. 0-based.*/ i8 mergeOut; /* Merge out to this rail. -1 if no merge-out */ u8 mergeIn[GR_MAX_RAIL]; /* Merge in from non-zero rails */ int aiRiser[GR_MAX_RAIL]; /* Risers from this node to a higher row. */ int mergeUpto; /* Draw the mergeOut rail up to this level */ u64 mergeDown; /* Draw merge lines up from bottom of graph */ u64 railInUse; /* Mask of occupied rails at this row */ }; /* Context while building a graph */ struct GraphContext { | > | 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | u8 bDescender; /* True if riser from bottom of graph to here. */ i8 iRail; /* Which rail this check-in appears on. 0-based.*/ i8 mergeOut; /* Merge out to this rail. -1 if no merge-out */ u8 mergeIn[GR_MAX_RAIL]; /* Merge in from non-zero rails */ int aiRiser[GR_MAX_RAIL]; /* Risers from this node to a higher row. */ int mergeUpto; /* Draw the mergeOut rail up to this level */ u64 mergeDown; /* Draw merge lines up from bottom of graph */ u64 cherrypickDown; /* Draw cherrypick lines up from bottom */ u64 railInUse; /* Mask of occupied rails at this row */ }; /* Context while building a graph */ struct GraphContext { |
︙ | ︙ | |||
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | /* ** Add a new row to the graph context. Rows are added from top to bottom. */ int graph_add_row( GraphContext *p, /* The context to which the row is added */ int rid, /* RID for the check-in */ int nParent, /* Number of parents */ int *aParent, /* Array of parents */ const char *zBranch, /* Branch for this check-in */ const char *zBgClr, /* Background color. NULL or "" for white. */ const char *zUuid, /* hash name of the object being graphed */ int isLeaf /* True if this row is a leaf */ ){ GraphRow *pRow; int nByte; static int nRow = 0; if( p->nErr ) return 0; nByte = sizeof(GraphRow); if( nParent>0 ) nByte += sizeof(pRow->aParent[0])*nParent; pRow = (GraphRow*)safeMalloc( nByte ); pRow->aParent = nParent>0 ? (int*)&pRow[1] : 0; pRow->rid = rid; pRow->nParent = nParent; pRow->zBranch = persistBranchName(p, zBranch); if( zUuid==0 ) zUuid = ""; sqlite3_snprintf(sizeof(pRow->zUuid), pRow->zUuid, "%s", zUuid); pRow->isLeaf = isLeaf; memset(pRow->aiRiser, -1, sizeof(pRow->aiRiser)); if( zBgClr==0 ) zBgClr = ""; pRow->zBgClr = persistBranchName(p, zBgClr); | > > > > > > | 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | /* ** Add a new row to the graph context. Rows are added from top to bottom. */ int graph_add_row( GraphContext *p, /* The context to which the row is added */ int rid, /* RID for the check-in */ int nParent, /* Number of parents */ int nCherrypick, /* How many of aParent[] are actually cherrypicks */ int *aParent, /* Array of parents */ const char *zBranch, /* Branch for this check-in */ const char *zBgClr, /* Background color. NULL or "" for white. */ const char *zUuid, /* hash name of the object being graphed */ int isLeaf /* True if this row is a leaf */ ){ GraphRow *pRow; int nByte; static int nRow = 0; if( p->nErr ) return 0; nByte = sizeof(GraphRow); if( nParent>0 ) nByte += sizeof(pRow->aParent[0])*nParent; pRow = (GraphRow*)safeMalloc( nByte ); pRow->aParent = nParent>0 ? (int*)&pRow[1] : 0; pRow->rid = rid; if( nCherrypick>=nParent ){ nCherrypick = nParent-1; /* Safety. Should never happen. */ } pRow->nParent = nParent; pRow->nCherrypick = nCherrypick; pRow->nNonCherrypick = nParent - nCherrypick; pRow->zBranch = persistBranchName(p, zBranch); if( zUuid==0 ) zUuid = ""; sqlite3_snprintf(sizeof(pRow->zUuid), pRow->zUuid, "%s", zUuid); pRow->isLeaf = isLeaf; memset(pRow->aiRiser, -1, sizeof(pRow->aiRiser)); if( zBgClr==0 ) zBgClr = ""; pRow->zBgClr = persistBranchName(p, zBgClr); |
︙ | ︙ | |||
282 283 284 285 286 287 288 | /* ** Create a merge-arrow riser going from pParent up to pChild. */ static void createMergeRiser( GraphContext *p, GraphRow *pParent, | | > | 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 | /* ** Create a merge-arrow riser going from pParent up to pChild. */ static void createMergeRiser( GraphContext *p, GraphRow *pParent, GraphRow *pChild, int isCherrypick ){ int u; u64 mask; GraphRow *pLoop; if( pParent->mergeOut<0 ){ u = pParent->aiRiser[pParent->iRail]; |
︙ | ︙ | |||
309 310 311 312 313 314 315 | mask = BIT(pParent->mergeOut); for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid; pLoop=pLoop->pNext){ pLoop->railInUse |= mask; } } } | | | > > | 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 | mask = BIT(pParent->mergeOut); for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid; pLoop=pLoop->pNext){ pLoop->railInUse |= mask; } } } pChild->mergeIn[pParent->mergeOut] = isCherrypick ? 2 : 1; } /* ** Compute the maximum rail number. */ static void find_max_rail(GraphContext *p){ GraphRow *pRow; p->mxRail = 0; for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ if( pRow->iRail>p->mxRail ) p->mxRail = pRow->iRail; if( pRow->mergeOut>p->mxRail ) p->mxRail = pRow->mergeOut; while( p->mxRail<GR_MAX_RAIL && (pRow->mergeDown|pRow->cherrypickDown)>(BIT(p->mxRail+1)-1) ){ p->mxRail++; } } } /* ** Draw a riser from pRow to the top of the graph |
︙ | ︙ | |||
393 394 395 396 397 398 399 | ** of this graph, then no arrows will be drawn for it, so remove it from ** the aParent[] array. */ if( omitDescenders ){ for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ for(i=1; i<pRow->nParent; i++){ if( hashFind(p, pRow->aParent[i])==0 ){ | > > | > > > > > | | | 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 | ** of this graph, then no arrows will be drawn for it, so remove it from ** the aParent[] array. */ if( omitDescenders ){ for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ for(i=1; i<pRow->nParent; i++){ if( hashFind(p, pRow->aParent[i])==0 ){ memmove(pRow->aParent+i, pRow->aParent+i+1, sizeof(pRow->aParent[0])*(pRow->nParent-i-1)); pRow->nParent--; if( i<pRow->nNonCherrypick ){ pRow->nNonCherrypick--; }else{ pRow->nCherrypick--; } i--; } } } } /* If the primary parent is in a different branch, but there are ** other parents in the same branch, reorder the parents to make ** the parent from the same branch the primary parent. */ for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ if( pRow->isDup ) continue; if( pRow->nNonCherrypick<2 ) continue; /* Not a fork */ pParent = hashFind(p, pRow->aParent[0]); if( pParent==0 ) continue; /* Parent off-screen */ if( pParent->zBranch==pRow->zBranch ) continue; /* Same branch */ for(i=1; i<pRow->nNonCherrypick; i++){ pParent = hashFind(p, pRow->aParent[i]); if( pParent && pParent->zBranch==pRow->zBranch ){ int t = pRow->aParent[0]; pRow->aParent[0] = pRow->aParent[i]; pRow->aParent[i] = t; break; } |
︙ | ︙ | |||
563 564 565 566 567 568 569 | } if( iMrail==-1 ){ iMrail = findFreeRail(p, pRow->idx, p->nRow, 0); if( p->mxRail>=GR_MAX_RAIL ) return; mergeRiserFrom[iMrail] = parentRid; } mask = BIT(iMrail); | > > > > | | > | | | 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 | } if( iMrail==-1 ){ iMrail = findFreeRail(p, pRow->idx, p->nRow, 0); if( p->mxRail>=GR_MAX_RAIL ) return; mergeRiserFrom[iMrail] = parentRid; } mask = BIT(iMrail); if( i>=pRow->nNonCherrypick ){ pRow->mergeIn[iMrail] = 2; pRow->cherrypickDown |= mask; }else{ pRow->mergeIn[iMrail] = 1; pRow->mergeDown |= mask; } for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){ pLoop->railInUse |= mask; } }else{ /* Merge from an on-screen node */ createMergeRiser(p, pDesc, pRow, i>=pRow->nNonCherrypick); if( p->mxRail>=GR_MAX_RAIL ) return; } } } /* ** Insert merge rails from primaries to duplicates. */ if( hasDup ){ int dupRail; int mxRail; find_max_rail(p); mxRail = p->mxRail; dupRail = mxRail+1; if( p->mxRail>=GR_MAX_RAIL ) return; for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ if( !pRow->isDup ) continue; pRow->iRail = dupRail; pDesc = hashFind(p, pRow->rid); assert( pDesc!=0 && pDesc!=pRow ); createMergeRiser(p, pDesc, pRow, 0); if( pDesc->mergeOut>mxRail ) mxRail = pDesc->mergeOut; } if( dupRail<=mxRail ){ dupRail = mxRail+1; for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ if( pRow->isDup ) pRow->iRail = dupRail; } |
︙ | ︙ |
Changes to src/graph.js.
︙ | ︙ | |||
81 82 83 84 85 86 87 | canvasDiv.className = "tl-canvas"; canvasDiv.style.position = "absolute"; parent.appendChild(canvasDiv); var elems = {}; var elemClasses = [ "rail", "mergeoffset", "node", "arrow u", "arrow u sm", "line", | | > > | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | canvasDiv.className = "tl-canvas"; canvasDiv.style.position = "absolute"; parent.appendChild(canvasDiv); var elems = {}; var elemClasses = [ "rail", "mergeoffset", "node", "arrow u", "arrow u sm", "line", "arrow merge r", "line merge", "arrow warp", "line warp", "line cherrypick" ]; for( var i=0; i<elemClasses.length; i++ ){ var cls = elemClasses[i]; var elem = document.createElement("div"); elem.className = "tl-" + cls; if( cls.indexOf("line")==0 ) elem.className += " v"; canvasDiv.appendChild(elem); var k = cls.replace(/\s/g, "_"); var r = elem.getBoundingClientRect(); var w = Math.round(r.right - r.left); var h = Math.round(r.bottom - r.top); elems[k] = {w: w, h: h, cls: cls}; } node = elems.node; arrow = elems.arrow_u; arrowSmall = elems.arrow_u_sm; line = elems.line; mArrow = elems.arrow_merge_r; mLine = elems.line_merge; cpLine = elems.line_cherrypick; wArrow = elems.arrow_warp; wLine = elems.line_warp; var minRailPitch = Math.ceil((node.w+line.w)/2 + mArrow.w + 1); if( window.innerWidth<400 ){ railPitch = minRailPitch; }else{ |
︙ | ︙ | |||
184 185 186 187 188 189 190 191 192 193 | var y0 = from.y + node.h/2; var y1 = Math.ceil(to.y + node.h + arw.h/2); drawLine(line,color,x,y0,null,y1); x = to.x + (node.w-arw.w)/2; var n = drawBox(arw.cls,null,x,y); if(color) n.style.borderBottomColor = color; } function drawMergeLine(x0,y0,x1,y1){ drawLine(mLine,null,x0,y0,x1,y1); } | > > > > > > | < > > > > > > | > | 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | var y0 = from.y + node.h/2; var y1 = Math.ceil(to.y + node.h + arw.h/2); drawLine(line,color,x,y0,null,y1); x = to.x + (node.w-arw.w)/2; var n = drawBox(arw.cls,null,x,y); if(color) n.style.borderBottomColor = color; } /* Draw thin horizontal or vertical lines representing merges */ function drawMergeLine(x0,y0,x1,y1){ drawLine(mLine,null,x0,y0,x1,y1); } function drawCherrypickLine(x0,y0,x1,y1){ drawLine(cpLine,null,x0,y0,x1,y1); } /* Draw an arrow representing an in-bound merge from the "rail"-th rail ** over to the node of "p". Make is a checkpoint merge is "isCP" is true */ function drawMergeArrow(p,rail,isCP){ var x0 = rail*railPitch + node.w/2; if( rail in mergeLines ){ x0 += mergeLines[rail]; if( p.r<rail ) x0 += mLine.w; }else{ x0 += (p.r<rail ? -1 : 1)*line.w/2; } var x1 = mArrow.w ? mArrow.w/2 : -node.w/2; x1 = p.x + (p.r<rail ? node.w + Math.ceil(x1) : -x1); var y = miLineY(p); var x = p.x + (p.r<rail ? node.w : -mArrow.w); var cls; if( isCP ){ drawCherrypickLine(x0,y,x1,null); cls = "arrow cherrypick " + (p.r<rail ? "l" : "r"); }else{ drawMergeLine(x0,y,x1,null); cls = "arrow merge " + (p.r<rail ? "l" : "r"); } drawBox(cls,null,x,y+(mLine.w-mArrow.h)/2); } function drawNode(p, btm){ if( p.bg ){ var e = document.getElementById("mc"+p.id); if(e) e.style.backgroundColor = p.bg; e = document.getElementById("md"+p.id); |
︙ | ︙ | |||
223 224 225 226 227 228 229 | n.id = "tln"+p.id; n.onclick = clickOnNode; n.style.zIndex = 10; if( !tx.omitDescenders ){ if( p.u==0 ) drawUpArrow(p,{x: p.x, y: -node.h},p.fg); if( p.hasOwnProperty('d') ) drawUpArrow({x: p.x, y: btm-node.h/2},p,p.fg); } | | | 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | n.id = "tln"+p.id; n.onclick = clickOnNode; n.style.zIndex = 10; if( !tx.omitDescenders ){ if( p.u==0 ) drawUpArrow(p,{x: p.x, y: -node.h},p.fg); if( p.hasOwnProperty('d') ) drawUpArrow({x: p.x, y: btm-node.h/2},p,p.fg); } if( p.hasOwnProperty('mo') ){ var x0 = p.x + node.w/2; var x1 = p.mo*railPitch + node.w/2; var u = tx.rowinfo[p.mu-tx.iTopRow]; var y1 = miLineY(u); if( p.u<0 || p.mo!=p.r ){ x1 += mergeLines[p.mo] = -mLine.w/2; var y0 = p.y+2; |
︙ | ︙ | |||
276 277 278 279 280 281 282 | var rail = p.mi[i]; if( rail<0 ){ rail = -rail; mergeLines[rail] = -mLine.w/2; var x = rail*railPitch + (node.w-mLine.w)/2; drawMergeLine(x,miLineY(p),null,btm); } | | > > > > > > > > > > > > | 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 | var rail = p.mi[i]; if( rail<0 ){ rail = -rail; mergeLines[rail] = -mLine.w/2; var x = rail*railPitch + (node.w-mLine.w)/2; drawMergeLine(x,miLineY(p),null,btm); } drawMergeArrow(p,rail,0); } } if( p.hasOwnProperty('cpi') ){ for( var i=0; i<p.cpi.length; i++ ){ var rail = p.cpi[i]; if( rail<0 ){ rail = -rail; mergeLines[rail] = -mLine.w/2; var x = rail*railPitch + (node.w-mLine.w)/2; drawMergeLine(x,miLineY(p),null,btm); } drawMergeArrow(p,rail,1); } } } var mergeLines; function renderGraph(){ mergeLines = {}; canvasDiv.innerHTML = ""; |
︙ | ︙ |
Changes to src/timeline.c.
︙ | ︙ | |||
427 428 429 430 431 432 433 434 435 436 437 438 439 440 | }else{ zBgClr = hash_color(zBr); } } } if( zType[0]=='c' && pGraph ){ int nParent = 0; int aParent[GR_MAX_RAIL]; static Stmt qparent; db_static_prepare(&qparent, "SELECT pid FROM plink" " WHERE cid=:rid AND pid NOT IN phantom" " ORDER BY isprim DESC /*sort*/" ); | > | 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 | }else{ zBgClr = hash_color(zBr); } } } if( zType[0]=='c' && pGraph ){ int nParent = 0; int nCherrypick = 0; int aParent[GR_MAX_RAIL]; static Stmt qparent; db_static_prepare(&qparent, "SELECT pid FROM plink" " WHERE cid=:rid AND pid NOT IN phantom" " ORDER BY isprim DESC /*sort*/" ); |
︙ | ︙ | |||
448 449 450 451 452 453 454 455 456 457 | db_static_prepare(&qcherrypick, "SELECT parentid FROM cherrypick" " WHERE childid=:rid AND parentid NOT IN phantom" ); db_bind_int(&qcherrypick, ":rid", rid); while( db_step(&qcherrypick)==SQLITE_ROW && nParent<count(aParent) ){ aParent[nParent++] = db_column_int(&qcherrypick, 0); } db_reset(&qcherrypick); } | > | | | | 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 | db_static_prepare(&qcherrypick, "SELECT parentid FROM cherrypick" " WHERE childid=:rid AND parentid NOT IN phantom" ); db_bind_int(&qcherrypick, ":rid", rid); while( db_step(&qcherrypick)==SQLITE_ROW && nParent<count(aParent) ){ aParent[nParent++] = db_column_int(&qcherrypick, 0); nCherrypick++; } db_reset(&qcherrypick); } gidx = graph_add_row(pGraph, rid, nParent, nCherrypick, aParent, zBr, zBgClr, zUuid, isLeaf); db_reset(&qbranch); @ <div id="m%d(gidx)" class="tl-nodemark"></div> }else if( zType[0]=='e' && pGraph && zBgClr && zBgClr[0] ){ /* For technotes, make a graph node with nParent==(-1). This will ** not actually draw anything on the graph, but it will set the ** background color of the timeline entry */ gidx = graph_add_row(pGraph, rid, -1, 0, 0, zBr, zBgClr, zUuid, 0); @ <div id="m%d(gidx)" class="tl-nodemark"></div> } @</td> if( !isSelectedOrCurrent ){ @ <td class="timeline%s(zStyle)Cell" id='mc%d(gidx)'> }else{ @ <td class="timeline%s(zStyle)Cell"> |
︙ | ︙ | |||
882 883 884 885 886 887 888 889 890 891 892 893 894 895 | ** are no risers, this array does not exist. ** mi: "merge-in". An array of integer rail positions from which ** merge arrows should be drawn into this node. If the value is ** negative, then the rail position is the absolute value of mi[] ** and a thin merge-arrow descender is drawn to the bottom of ** the screen. This array is omitted if there are no inbound ** merges. ** h: The artifact hash of the object being graphed */ for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){ int k = 0; cgi_printf("{\"id\":%d,", pRow->idx); cgi_printf("\"bg\":\"%s\",", pRow->zBgClr); cgi_printf("\"r\":%d,", pRow->iRail); | > > | 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 | ** are no risers, this array does not exist. ** mi: "merge-in". An array of integer rail positions from which ** merge arrows should be drawn into this node. If the value is ** negative, then the rail position is the absolute value of mi[] ** and a thin merge-arrow descender is drawn to the bottom of ** the screen. This array is omitted if there are no inbound ** merges. ** cpi: "cherrypick-in". Like "mi" except for cherrypick merges. ** omitted if there are no cherrypick merges. ** h: The artifact hash of the object being graphed */ for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){ int k = 0; cgi_printf("{\"id\":%d,", pRow->idx); cgi_printf("\"bg\":\"%s\",", pRow->zBgClr); cgi_printf("\"r\":%d,", pRow->iRail); |
︙ | ︙ | |||
918 919 920 921 922 923 924 | cgi_printf("],"); } if( colorGraph && pRow->zBgClr[0]=='#' ){ cgi_printf("\"fg\":\"%s\",", bg_to_fg(pRow->zBgClr)); } /* mi */ for(i=k=0; i<GR_MAX_RAIL; i++){ | | > > > > > > > > > > > > > > > | 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 | cgi_printf("],"); } if( colorGraph && pRow->zBgClr[0]=='#' ){ cgi_printf("\"fg\":\"%s\",", bg_to_fg(pRow->zBgClr)); } /* mi */ for(i=k=0; i<GR_MAX_RAIL; i++){ if( pRow->mergeIn[i]==1 ){ int mi = i; if( (pRow->mergeDown >> i) & 1 ) mi = -mi; if( k==0 ){ cgi_printf("\"mi\":"); cSep = '['; } k++; cgi_printf("%c%d", cSep, mi); cSep = ','; } } if( k ) cgi_printf("],"); /* cpi */ for(i=k=0; i<GR_MAX_RAIL; i++){ if( pRow->mergeIn[i]==2 ){ int mi = i; if( (pRow->cherrypickDown >> i) & 1 ) mi = -mi; if( k==0 ){ cgi_printf("\"cpi\":"); cSep = '['; } k++; cgi_printf("%c%d", cSep, mi); cSep = ','; } } if( k ) cgi_printf("],"); cgi_printf("\"h\":\"%!S\"}%s", |
︙ | ︙ | |||
1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 | ** mionly Limit rel to show ancestors but not descendants ** ms=MATCHSTYLE Set tag match style to EXACT, GLOB, LIKE, REGEXP ** u=USER Only show items associated with USER ** y=TYPE 'ci', 'w', 't', 'e', 'f', or 'all'. ** ss=VIEWSTYLE c: "Compact" v: "Verbose" m: "Modern" j: "Columnar" ** advm Use the "Advanced" or "Busy" menu design. ** ng No Graph. ** nd Do not highlight the focus check-in ** v Show details of files changed ** f=CHECKIN Show family (immediate parents and children) of CHECKIN ** from=CHECKIN Path from... ** to=CHECKIN ... to this ** shortest ... show only the shortest path ** uf=FILE_HASH Show only check-ins that contain the given file version | > | 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 | ** mionly Limit rel to show ancestors but not descendants ** ms=MATCHSTYLE Set tag match style to EXACT, GLOB, LIKE, REGEXP ** u=USER Only show items associated with USER ** y=TYPE 'ci', 'w', 't', 'e', 'f', or 'all'. ** ss=VIEWSTYLE c: "Compact" v: "Verbose" m: "Modern" j: "Columnar" ** advm Use the "Advanced" or "Busy" menu design. ** ng No Graph. ** ncp Omit cherrypick merges ** nd Do not highlight the focus check-in ** v Show details of files changed ** f=CHECKIN Show family (immediate parents and children) of CHECKIN ** from=CHECKIN Path from... ** to=CHECKIN ... to this ** shortest ... show only the shortest path ** uf=FILE_HASH Show only check-ins that contain the given file version |
︙ | ︙ | |||
1583 1584 1585 1586 1587 1588 1589 | if( (zTagSql && db_int(0,"SELECT count(*) " "FROM tagxref NATURAL JOIN tag WHERE %s",zTagSql/*safe-for-%s*/)<=nEntry) ){ nEntry = -1; zCirca = 0; } if( zType[0]=='a' ){ | | | | | > > > | 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 | if( (zTagSql && db_int(0,"SELECT count(*) " "FROM tagxref NATURAL JOIN tag WHERE %s",zTagSql/*safe-for-%s*/)<=nEntry) ){ nEntry = -1; zCirca = 0; } if( zType[0]=='a' ){ tmFlags |= TIMELINE_BRIEF | TIMELINE_GRAPH | TIMELINE_CHPICK; }else{ tmFlags |= TIMELINE_GRAPH | TIMELINE_CHPICK; } if( PB("ncp") ){ tmFlags &= ~TIMELINE_CHPICK; } if( PB("ng") || zSearch!=0 ){ tmFlags &= ~(TIMELINE_GRAPH|TIMELINE_CHPICK); } if( PB("brbg") ){ tmFlags |= TIMELINE_BRCOLOR; } if( PB("unhide") ){ tmFlags |= TIMELINE_UNHIDE; } |
︙ | ︙ | |||
1854 1855 1856 1857 1858 1859 1860 | blob_append_sql(&cond, " AND (EXISTS(SELECT 1 FROM tagxref NATURAL JOIN tag" " WHERE %s AND tagtype>0 AND rid=blob.rid)\n", zTagSql/*safe-for-%s*/); if( related ){ /* The next two blob_appendf() calls add SQL that causes check-ins that ** are not part of the branch which are parents or children of the | | | 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 | blob_append_sql(&cond, " AND (EXISTS(SELECT 1 FROM tagxref NATURAL JOIN tag" " WHERE %s AND tagtype>0 AND rid=blob.rid)\n", zTagSql/*safe-for-%s*/); if( related ){ /* The next two blob_appendf() calls add SQL that causes check-ins that ** are not part of the branch which are parents or children of the ** branch to be included in the report. These related check-ins are ** useful in helping to visualize what has happened on a quiescent ** branch that is infrequently merged with a much more activate branch. */ blob_append_sql(&cond, " OR EXISTS(SELECT 1 FROM plink CROSS JOIN tagxref ON rid=cid" " NATURAL JOIN tag WHERE %s AND tagtype>0 AND pid=blob.rid)\n", zTagSql/*safe-for-%s*/ |
︙ | ︙ | |||
1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 | if( (tmFlags & TIMELINE_UNHIDE)==0 ){ blob_append_sql(&cond, " AND NOT EXISTS(SELECT 1 FROM plink JOIN tagxref ON rid=pid" " WHERE tagid=%d AND tagtype>0 AND cid=blob.rid)\n", TAG_HIDDEN ); } } } blob_append_sql(&cond, ")"); } if( (zType[0]=='w' && !g.perm.RdWiki) || (zType[0]=='t' && !g.perm.RdTkt) || (zType[0]=='e' && !g.perm.RdWiki) | > > > > > > > > > > > > > | 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 | if( (tmFlags & TIMELINE_UNHIDE)==0 ){ blob_append_sql(&cond, " AND NOT EXISTS(SELECT 1 FROM plink JOIN tagxref ON rid=pid" " WHERE tagid=%d AND tagtype>0 AND cid=blob.rid)\n", TAG_HIDDEN ); } } if( !PB("ncp") && db_table_exists("repository","cherrypick") ){ tmFlags |= TIMELINE_CHPICK; blob_append_sql(&cond, " OR EXISTS(SELECT 1 FROM cherrypick CROSS JOIN tagxref" " ON rid=childid NATURAL JOIN tag WHERE %s AND tagtype>0" " AND parentid=blob.rid)\n", zTagSql/*safe-for-%s*/ ); blob_append_sql(&cond, " OR EXISTS(SELECT 1 FROM cherrypick CROSS JOIN tagxref" " ON rid=parentid NATURAL JOIN tag WHERE %s AND tagtype>0" " AND childid=blob.rid)\n", zTagSql/*safe-for-%s*/ ); } } blob_append_sql(&cond, ")"); } if( (zType[0]=='w' && !g.perm.RdWiki) || (zType[0]=='t' && !g.perm.RdTkt) || (zType[0]=='e' && !g.perm.RdWiki) |
︙ | ︙ |