Fossil SCM

For the graph drawing routines, make the graph row identifier a 64-bit integer type to avoid the possibility of integer overflow in /finfo where the row ids are a composite of the blob.rid and filename.fnid and hence might become large for repositories with many files and many check-ins.

drh 2020-10-20 00:20 trunk
Commit ab71d95a9f3263699fc4e64e2f8a6ea9dfa6afffbec8e611d21bff6e77bfadc0
3 files changed +8 -8 +24 -12 +1 -1
+8 -8
--- src/finfo.c
+++ src/finfo.c
@@ -578,17 +578,17 @@
578578
int fnid = db_column_int(&q, 13);
579579
const char *zFName = db_column_text(&q,14);
580580
int gidx;
581581
char zTime[10];
582582
int nParent = 0;
583
- int aParent[GR_MAX_RAIL];
583
+ GraphRowId aParent[GR_MAX_RAIL];
584584
585585
db_bind_int(&qparent, ":fid", frid);
586586
db_bind_int(&qparent, ":mid", fmid);
587587
db_bind_int(&qparent, ":fnid", fnid);
588588
while( db_step(&qparent)==SQLITE_ROW && nParent<count(aParent) ){
589
- aParent[nParent] = db_column_int(&qparent, 0);
589
+ aParent[nParent] = db_column_int64(&qparent, 0);
590590
nParent++;
591591
}
592592
db_reset(&qparent);
593593
if( zBr==0 ) zBr = "trunk";
594594
if( uBg ){
@@ -595,13 +595,13 @@
595595
zBgClr = hash_color(zUser);
596596
}else if( brBg || zBgClr==0 || zBgClr[0]==0 ){
597597
zBgClr = strcmp(zBr,"trunk")==0 ? "" : hash_color(zBr);
598598
}
599599
gidx = graph_add_row(pGraph,
600
- frid>0 ? frid*(mxfnid+1)+fnid : fpid+1000000000,
601
- nParent, 0, aParent, zBr, zBgClr,
602
- zUuid, 0);
600
+ frid>0 ? (GraphRowId)frid*(mxfnid+1)+fnid : fpid+1000000000,
601
+ nParent, 0, aParent, zBr, zBgClr,
602
+ zUuid, 0);
603603
if( strncmp(zDate, zPrevDate, 10) ){
604604
sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
605605
@ <tr><td>
606606
@ <div class="divider timelineDate">%s(zPrevDate)</div>
607607
@ </td><td></td><td></td></tr>
@@ -719,17 +719,17 @@
719719
}
720720
if( fDebug & FINFO_DEBUG_MLINK ){
721721
int ii;
722722
char *zAncLink;
723723
@ <br />fid=%d(frid) \
724
- @ graph-id=%d(frid>0 ? frid*(mxfnid+1)+fnid : fpid+1000000000) \
724
+ @ graph-id=%lld(frid>0?(GraphRowId)frid*(mxfnid+1)+fnid:fpid+1000000000) \
725725
@ pid=%d(fpid) mid=%d(fmid) fnid=%d(fnid) \
726726
@ pfnid=%d(pfnid) mxfnid=%d(mxfnid)
727727
if( nParent>0 ){
728
- @ parents=%d(aParent[0])
728
+ @ parents=%lld(aParent[0])
729729
for(ii=1; ii<nParent; ii++){
730
- @ %d(aParent[ii])
730
+ @ %lld(aParent[ii])
731731
}
732732
}
733733
zAncLink = href("%R/finfo?name=%T&from=%!S&debug=1",zFName,zCkin);
734734
@ %z(zAncLink)[ancestry]</a>
735735
}
736736
--- src/finfo.c
+++ src/finfo.c
@@ -578,17 +578,17 @@
578 int fnid = db_column_int(&q, 13);
579 const char *zFName = db_column_text(&q,14);
580 int gidx;
581 char zTime[10];
582 int nParent = 0;
583 int aParent[GR_MAX_RAIL];
584
585 db_bind_int(&qparent, ":fid", frid);
586 db_bind_int(&qparent, ":mid", fmid);
587 db_bind_int(&qparent, ":fnid", fnid);
588 while( db_step(&qparent)==SQLITE_ROW && nParent<count(aParent) ){
589 aParent[nParent] = db_column_int(&qparent, 0);
590 nParent++;
591 }
592 db_reset(&qparent);
593 if( zBr==0 ) zBr = "trunk";
594 if( uBg ){
@@ -595,13 +595,13 @@
595 zBgClr = hash_color(zUser);
596 }else if( brBg || zBgClr==0 || zBgClr[0]==0 ){
597 zBgClr = strcmp(zBr,"trunk")==0 ? "" : hash_color(zBr);
598 }
599 gidx = graph_add_row(pGraph,
600 frid>0 ? frid*(mxfnid+1)+fnid : fpid+1000000000,
601 nParent, 0, aParent, zBr, zBgClr,
602 zUuid, 0);
603 if( strncmp(zDate, zPrevDate, 10) ){
604 sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
605 @ <tr><td>
606 @ <div class="divider timelineDate">%s(zPrevDate)</div>
607 @ </td><td></td><td></td></tr>
@@ -719,17 +719,17 @@
719 }
720 if( fDebug & FINFO_DEBUG_MLINK ){
721 int ii;
722 char *zAncLink;
723 @ <br />fid=%d(frid) \
724 @ graph-id=%d(frid>0 ? frid*(mxfnid+1)+fnid : fpid+1000000000) \
725 @ pid=%d(fpid) mid=%d(fmid) fnid=%d(fnid) \
726 @ pfnid=%d(pfnid) mxfnid=%d(mxfnid)
727 if( nParent>0 ){
728 @ parents=%d(aParent[0])
729 for(ii=1; ii<nParent; ii++){
730 @ %d(aParent[ii])
731 }
732 }
733 zAncLink = href("%R/finfo?name=%T&from=%!S&debug=1",zFName,zCkin);
734 @ %z(zAncLink)[ancestry]</a>
735 }
736
--- src/finfo.c
+++ src/finfo.c
@@ -578,17 +578,17 @@
578 int fnid = db_column_int(&q, 13);
579 const char *zFName = db_column_text(&q,14);
580 int gidx;
581 char zTime[10];
582 int nParent = 0;
583 GraphRowId aParent[GR_MAX_RAIL];
584
585 db_bind_int(&qparent, ":fid", frid);
586 db_bind_int(&qparent, ":mid", fmid);
587 db_bind_int(&qparent, ":fnid", fnid);
588 while( db_step(&qparent)==SQLITE_ROW && nParent<count(aParent) ){
589 aParent[nParent] = db_column_int64(&qparent, 0);
590 nParent++;
591 }
592 db_reset(&qparent);
593 if( zBr==0 ) zBr = "trunk";
594 if( uBg ){
@@ -595,13 +595,13 @@
595 zBgClr = hash_color(zUser);
596 }else if( brBg || zBgClr==0 || zBgClr[0]==0 ){
597 zBgClr = strcmp(zBr,"trunk")==0 ? "" : hash_color(zBr);
598 }
599 gidx = graph_add_row(pGraph,
600 frid>0 ? (GraphRowId)frid*(mxfnid+1)+fnid : fpid+1000000000,
601 nParent, 0, aParent, zBr, zBgClr,
602 zUuid, 0);
603 if( strncmp(zDate, zPrevDate, 10) ){
604 sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
605 @ <tr><td>
606 @ <div class="divider timelineDate">%s(zPrevDate)</div>
607 @ </td><td></td><td></td></tr>
@@ -719,17 +719,17 @@
719 }
720 if( fDebug & FINFO_DEBUG_MLINK ){
721 int ii;
722 char *zAncLink;
723 @ <br />fid=%d(frid) \
724 @ graph-id=%lld(frid>0?(GraphRowId)frid*(mxfnid+1)+fnid:fpid+1000000000) \
725 @ pid=%d(fpid) mid=%d(fmid) fnid=%d(fnid) \
726 @ pfnid=%d(pfnid) mxfnid=%d(mxfnid)
727 if( nParent>0 ){
728 @ parents=%lld(aParent[0])
729 for(ii=1; ii<nParent; ii++){
730 @ %lld(aParent[ii])
731 }
732 }
733 zAncLink = href("%R/finfo?name=%T&from=%!S&debug=1",zFName,zCkin);
734 @ %z(zAncLink)[ancestry]</a>
735 }
736
+24 -12
--- src/graph.c
+++ src/graph.c
@@ -41,10 +41,22 @@
4141
** the rails used for merge arrows.
4242
*/
4343
4444
#if INTERFACE
4545
46
+/*
47
+** The type of integer identifiers for rows of the graph.
48
+**
49
+** For a normal /timeline graph, the identifiers are never that big
50
+** an an ordinary 32-bit int will work fine. But for the /finfo page,
51
+** the identifier is a combination of the BLOB.RID and the FILENAME.FNID
52
+** values, and so it can become quite large for repos that have both many
53
+** check-ins and many files. For this reason, we make the identifier
54
+** a 64-bit integer, to dramatically reduce the risk of an overflow.
55
+*/
56
+typedef sqlite3_int64 GraphRowId;
57
+
4658
#define GR_MAX_RAIL 40 /* Max number of "rails" to display */
4759
4860
/* The graph appears vertically beside a timeline. Each row in the
4961
** timeline corresponds to a row in the graph. GraphRow.idx is 0 for
5062
** the top-most row and increases moving down. Hence (in the absence of
@@ -52,16 +64,16 @@
5264
**
5365
** The nParent field is -1 for entires that do not participate in the graph
5466
** but which are included just so that we can capture their background color.
5567
*/
5668
struct GraphRow {
57
- int rid; /* The rid for the check-in */
69
+ GraphRowId rid; /* The rid for the check-in */
5870
i8 nParent; /* Number of parents. */
5971
i8 nCherrypick; /* Subset of aParent that are cherrypicks */
6072
i8 nNonCherrypick; /* Number of non-cherrypick parents */
6173
u8 nMergeChild; /* Number of merge children */
62
- int *aParent; /* Array of parents. 0 element is primary .*/
74
+ GraphRowId *aParent; /* Array of parents. 0 element is primary .*/
6375
char *zBranch; /* Branch name */
6476
char *zBgClr; /* Background Color */
6577
char zUuid[HNAME_MAX+1]; /* Check-in for file ID */
6678
6779
GraphRow *pNext; /* Next row down in the list of all rows */
@@ -176,11 +188,11 @@
176188
}
177189
178190
/*
179191
** Look up the row with rid.
180192
*/
181
-static GraphRow *hashFind(GraphContext *p, int rid){
193
+static GraphRow *hashFind(GraphContext *p, GraphRowId rid){
182194
int h = rid % p->nHash;
183195
while( p->apHash[h] && p->apHash[h]->rid!=rid ){
184196
h++;
185197
if( h>=p->nHash ) h = 0;
186198
}
@@ -212,14 +224,14 @@
212224
/*
213225
** Add a new row to the graph context. Rows are added from top to bottom.
214226
*/
215227
int graph_add_row(
216228
GraphContext *p, /* The context to which the row is added */
217
- int rid, /* RID for the check-in */
229
+ GraphRowId rid, /* RID for the check-in */
218230
int nParent, /* Number of parents */
219231
int nCherrypick, /* How many of aParent[] are actually cherrypicks */
220
- int *aParent, /* Array of parents */
232
+ GraphRowId *aParent, /* Array of parents */
221233
const char *zBranch, /* Branch for this check-in */
222234
const char *zBgClr, /* Background color. NULL or "" for white. */
223235
const char *zUuid, /* hash name of the object being graphed */
224236
int isLeaf /* True if this row is a leaf */
225237
){
@@ -229,11 +241,11 @@
229241
230242
if( p->nErr ) return 0;
231243
nByte = sizeof(GraphRow);
232244
if( nParent>0 ) nByte += sizeof(pRow->aParent[0])*nParent;
233245
pRow = (GraphRow*)safeMalloc( nByte );
234
- pRow->aParent = nParent>0 ? (int*)&pRow[1] : 0;
246
+ pRow->aParent = nParent>0 ? (GraphRowId*)&pRow[1] : 0;
235247
pRow->rid = rid;
236248
if( nCherrypick>=nParent ){
237249
nCherrypick = nParent-1; /* Safety. Should never happen. */
238250
}
239251
pRow->nParent = nParent;
@@ -440,11 +452,11 @@
440452
441453
/* If mergeRiserFrom[X]==Y that means rail X holds a merge riser
442454
** coming up from the bottom of the graph from off-screen check-in Y
443455
** where Y is the RID. There is no riser on rail X if mergeRiserFrom[X]==0.
444456
*/
445
- int mergeRiserFrom[GR_MAX_RAIL];
457
+ GraphRowId mergeRiserFrom[GR_MAX_RAIL];
446458
447459
if( p==0 || p->pFirst==0 || p->nErr ) return;
448460
p->nErr = 1; /* Assume an error until proven otherwise */
449461
450462
/* Initialize all rows */
@@ -514,11 +526,11 @@
514526
iBest = i;
515527
}
516528
}
517529
i = pRow->nNonCherrypick;
518530
if( iBest>i ){
519
- int x = pRow->aParent[i];
531
+ GraphRowId x = pRow->aParent[i];
520532
pRow->aParent[i] = pRow->aParent[iBest];
521533
pRow->aParent[iBest] = x;
522534
}
523535
}
524536
if( pRow->nNonCherrypick>2 ){
@@ -534,11 +546,11 @@
534546
iDeepest = pParent->idx;
535547
iBest = i;
536548
}
537549
}
538550
if( iBest>1 ){
539
- int x = pRow->aParent[1];
551
+ GraphRowId x = pRow->aParent[1];
540552
pRow->aParent[1] = pRow->aParent[iBest];
541553
pRow->aParent[iBest] = x;
542554
}
543555
}
544556
}
@@ -554,11 +566,11 @@
554566
if( pParent==0 ) continue; /* Parent off-screen */
555567
if( pParent->zBranch==pRow->zBranch ) continue; /* Same branch */
556568
for(i=1; i<pRow->nNonCherrypick; i++){
557569
pParent = hashFind(p, pRow->aParent[i]);
558570
if( pParent && pParent->zBranch==pRow->zBranch ){
559
- int t = pRow->aParent[0];
571
+ GraphRowId t = pRow->aParent[0];
560572
pRow->aParent[0] = pRow->aParent[i];
561573
pRow->aParent[i] = t;
562574
break;
563575
}
564576
}
@@ -652,11 +664,11 @@
652664
}
653665
654666
/* Assign rails to all rows that are still unassigned.
655667
*/
656668
for(pRow=p->pLast; pRow; pRow=pRow->pPrev){
657
- int parentRid;
669
+ GraphRowId parentRid;
658670
659671
if( pRow->iRail>=0 ){
660672
if( pRow->pChild==0 && !pRow->timeWarp ){
661673
if( !omitDescenders && count_nonbranch_children(pRow->rid)!=0 ){
662674
riser_to_top(pRow);
@@ -726,11 +738,11 @@
726738
for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
727739
int iReuseIdx = -1;
728740
int iReuseRail = -1;
729741
int isCherrypick = 0;
730742
for(i=1; i<pRow->nParent; i++){
731
- int parentRid = pRow->aParent[i];
743
+ GraphRowId parentRid = pRow->aParent[i];
732744
if( i==pRow->nNonCherrypick ){
733745
/* Because full merges are laid out before cherrypicks,
734746
** it is ok to use a full-merge raise for a cherrypick.
735747
** See the graph on check-in 8ac66ef33b464d28 for example
736748
** iReuseIdx = -1;
737749
--- src/graph.c
+++ src/graph.c
@@ -41,10 +41,22 @@
41 ** the rails used for merge arrows.
42 */
43
44 #if INTERFACE
45
 
 
 
 
 
 
 
 
 
 
 
 
46 #define GR_MAX_RAIL 40 /* Max number of "rails" to display */
47
48 /* The graph appears vertically beside a timeline. Each row in the
49 ** timeline corresponds to a row in the graph. GraphRow.idx is 0 for
50 ** the top-most row and increases moving down. Hence (in the absence of
@@ -52,16 +64,16 @@
52 **
53 ** The nParent field is -1 for entires that do not participate in the graph
54 ** but which are included just so that we can capture their background color.
55 */
56 struct GraphRow {
57 int rid; /* The rid for the check-in */
58 i8 nParent; /* Number of parents. */
59 i8 nCherrypick; /* Subset of aParent that are cherrypicks */
60 i8 nNonCherrypick; /* Number of non-cherrypick parents */
61 u8 nMergeChild; /* Number of merge children */
62 int *aParent; /* Array of parents. 0 element is primary .*/
63 char *zBranch; /* Branch name */
64 char *zBgClr; /* Background Color */
65 char zUuid[HNAME_MAX+1]; /* Check-in for file ID */
66
67 GraphRow *pNext; /* Next row down in the list of all rows */
@@ -176,11 +188,11 @@
176 }
177
178 /*
179 ** Look up the row with rid.
180 */
181 static GraphRow *hashFind(GraphContext *p, int rid){
182 int h = rid % p->nHash;
183 while( p->apHash[h] && p->apHash[h]->rid!=rid ){
184 h++;
185 if( h>=p->nHash ) h = 0;
186 }
@@ -212,14 +224,14 @@
212 /*
213 ** Add a new row to the graph context. Rows are added from top to bottom.
214 */
215 int graph_add_row(
216 GraphContext *p, /* The context to which the row is added */
217 int rid, /* RID for the check-in */
218 int nParent, /* Number of parents */
219 int nCherrypick, /* How many of aParent[] are actually cherrypicks */
220 int *aParent, /* Array of parents */
221 const char *zBranch, /* Branch for this check-in */
222 const char *zBgClr, /* Background color. NULL or "" for white. */
223 const char *zUuid, /* hash name of the object being graphed */
224 int isLeaf /* True if this row is a leaf */
225 ){
@@ -229,11 +241,11 @@
229
230 if( p->nErr ) return 0;
231 nByte = sizeof(GraphRow);
232 if( nParent>0 ) nByte += sizeof(pRow->aParent[0])*nParent;
233 pRow = (GraphRow*)safeMalloc( nByte );
234 pRow->aParent = nParent>0 ? (int*)&pRow[1] : 0;
235 pRow->rid = rid;
236 if( nCherrypick>=nParent ){
237 nCherrypick = nParent-1; /* Safety. Should never happen. */
238 }
239 pRow->nParent = nParent;
@@ -440,11 +452,11 @@
440
441 /* If mergeRiserFrom[X]==Y that means rail X holds a merge riser
442 ** coming up from the bottom of the graph from off-screen check-in Y
443 ** where Y is the RID. There is no riser on rail X if mergeRiserFrom[X]==0.
444 */
445 int mergeRiserFrom[GR_MAX_RAIL];
446
447 if( p==0 || p->pFirst==0 || p->nErr ) return;
448 p->nErr = 1; /* Assume an error until proven otherwise */
449
450 /* Initialize all rows */
@@ -514,11 +526,11 @@
514 iBest = i;
515 }
516 }
517 i = pRow->nNonCherrypick;
518 if( iBest>i ){
519 int x = pRow->aParent[i];
520 pRow->aParent[i] = pRow->aParent[iBest];
521 pRow->aParent[iBest] = x;
522 }
523 }
524 if( pRow->nNonCherrypick>2 ){
@@ -534,11 +546,11 @@
534 iDeepest = pParent->idx;
535 iBest = i;
536 }
537 }
538 if( iBest>1 ){
539 int x = pRow->aParent[1];
540 pRow->aParent[1] = pRow->aParent[iBest];
541 pRow->aParent[iBest] = x;
542 }
543 }
544 }
@@ -554,11 +566,11 @@
554 if( pParent==0 ) continue; /* Parent off-screen */
555 if( pParent->zBranch==pRow->zBranch ) continue; /* Same branch */
556 for(i=1; i<pRow->nNonCherrypick; i++){
557 pParent = hashFind(p, pRow->aParent[i]);
558 if( pParent && pParent->zBranch==pRow->zBranch ){
559 int t = pRow->aParent[0];
560 pRow->aParent[0] = pRow->aParent[i];
561 pRow->aParent[i] = t;
562 break;
563 }
564 }
@@ -652,11 +664,11 @@
652 }
653
654 /* Assign rails to all rows that are still unassigned.
655 */
656 for(pRow=p->pLast; pRow; pRow=pRow->pPrev){
657 int parentRid;
658
659 if( pRow->iRail>=0 ){
660 if( pRow->pChild==0 && !pRow->timeWarp ){
661 if( !omitDescenders && count_nonbranch_children(pRow->rid)!=0 ){
662 riser_to_top(pRow);
@@ -726,11 +738,11 @@
726 for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
727 int iReuseIdx = -1;
728 int iReuseRail = -1;
729 int isCherrypick = 0;
730 for(i=1; i<pRow->nParent; i++){
731 int parentRid = pRow->aParent[i];
732 if( i==pRow->nNonCherrypick ){
733 /* Because full merges are laid out before cherrypicks,
734 ** it is ok to use a full-merge raise for a cherrypick.
735 ** See the graph on check-in 8ac66ef33b464d28 for example
736 ** iReuseIdx = -1;
737
--- src/graph.c
+++ src/graph.c
@@ -41,10 +41,22 @@
41 ** the rails used for merge arrows.
42 */
43
44 #if INTERFACE
45
46 /*
47 ** The type of integer identifiers for rows of the graph.
48 **
49 ** For a normal /timeline graph, the identifiers are never that big
50 ** an an ordinary 32-bit int will work fine. But for the /finfo page,
51 ** the identifier is a combination of the BLOB.RID and the FILENAME.FNID
52 ** values, and so it can become quite large for repos that have both many
53 ** check-ins and many files. For this reason, we make the identifier
54 ** a 64-bit integer, to dramatically reduce the risk of an overflow.
55 */
56 typedef sqlite3_int64 GraphRowId;
57
58 #define GR_MAX_RAIL 40 /* Max number of "rails" to display */
59
60 /* The graph appears vertically beside a timeline. Each row in the
61 ** timeline corresponds to a row in the graph. GraphRow.idx is 0 for
62 ** the top-most row and increases moving down. Hence (in the absence of
@@ -52,16 +64,16 @@
64 **
65 ** The nParent field is -1 for entires that do not participate in the graph
66 ** but which are included just so that we can capture their background color.
67 */
68 struct GraphRow {
69 GraphRowId rid; /* The rid for the check-in */
70 i8 nParent; /* Number of parents. */
71 i8 nCherrypick; /* Subset of aParent that are cherrypicks */
72 i8 nNonCherrypick; /* Number of non-cherrypick parents */
73 u8 nMergeChild; /* Number of merge children */
74 GraphRowId *aParent; /* Array of parents. 0 element is primary .*/
75 char *zBranch; /* Branch name */
76 char *zBgClr; /* Background Color */
77 char zUuid[HNAME_MAX+1]; /* Check-in for file ID */
78
79 GraphRow *pNext; /* Next row down in the list of all rows */
@@ -176,11 +188,11 @@
188 }
189
190 /*
191 ** Look up the row with rid.
192 */
193 static GraphRow *hashFind(GraphContext *p, GraphRowId rid){
194 int h = rid % p->nHash;
195 while( p->apHash[h] && p->apHash[h]->rid!=rid ){
196 h++;
197 if( h>=p->nHash ) h = 0;
198 }
@@ -212,14 +224,14 @@
224 /*
225 ** Add a new row to the graph context. Rows are added from top to bottom.
226 */
227 int graph_add_row(
228 GraphContext *p, /* The context to which the row is added */
229 GraphRowId rid, /* RID for the check-in */
230 int nParent, /* Number of parents */
231 int nCherrypick, /* How many of aParent[] are actually cherrypicks */
232 GraphRowId *aParent, /* Array of parents */
233 const char *zBranch, /* Branch for this check-in */
234 const char *zBgClr, /* Background color. NULL or "" for white. */
235 const char *zUuid, /* hash name of the object being graphed */
236 int isLeaf /* True if this row is a leaf */
237 ){
@@ -229,11 +241,11 @@
241
242 if( p->nErr ) return 0;
243 nByte = sizeof(GraphRow);
244 if( nParent>0 ) nByte += sizeof(pRow->aParent[0])*nParent;
245 pRow = (GraphRow*)safeMalloc( nByte );
246 pRow->aParent = nParent>0 ? (GraphRowId*)&pRow[1] : 0;
247 pRow->rid = rid;
248 if( nCherrypick>=nParent ){
249 nCherrypick = nParent-1; /* Safety. Should never happen. */
250 }
251 pRow->nParent = nParent;
@@ -440,11 +452,11 @@
452
453 /* If mergeRiserFrom[X]==Y that means rail X holds a merge riser
454 ** coming up from the bottom of the graph from off-screen check-in Y
455 ** where Y is the RID. There is no riser on rail X if mergeRiserFrom[X]==0.
456 */
457 GraphRowId mergeRiserFrom[GR_MAX_RAIL];
458
459 if( p==0 || p->pFirst==0 || p->nErr ) return;
460 p->nErr = 1; /* Assume an error until proven otherwise */
461
462 /* Initialize all rows */
@@ -514,11 +526,11 @@
526 iBest = i;
527 }
528 }
529 i = pRow->nNonCherrypick;
530 if( iBest>i ){
531 GraphRowId x = pRow->aParent[i];
532 pRow->aParent[i] = pRow->aParent[iBest];
533 pRow->aParent[iBest] = x;
534 }
535 }
536 if( pRow->nNonCherrypick>2 ){
@@ -534,11 +546,11 @@
546 iDeepest = pParent->idx;
547 iBest = i;
548 }
549 }
550 if( iBest>1 ){
551 GraphRowId x = pRow->aParent[1];
552 pRow->aParent[1] = pRow->aParent[iBest];
553 pRow->aParent[iBest] = x;
554 }
555 }
556 }
@@ -554,11 +566,11 @@
566 if( pParent==0 ) continue; /* Parent off-screen */
567 if( pParent->zBranch==pRow->zBranch ) continue; /* Same branch */
568 for(i=1; i<pRow->nNonCherrypick; i++){
569 pParent = hashFind(p, pRow->aParent[i]);
570 if( pParent && pParent->zBranch==pRow->zBranch ){
571 GraphRowId t = pRow->aParent[0];
572 pRow->aParent[0] = pRow->aParent[i];
573 pRow->aParent[i] = t;
574 break;
575 }
576 }
@@ -652,11 +664,11 @@
664 }
665
666 /* Assign rails to all rows that are still unassigned.
667 */
668 for(pRow=p->pLast; pRow; pRow=pRow->pPrev){
669 GraphRowId parentRid;
670
671 if( pRow->iRail>=0 ){
672 if( pRow->pChild==0 && !pRow->timeWarp ){
673 if( !omitDescenders && count_nonbranch_children(pRow->rid)!=0 ){
674 riser_to_top(pRow);
@@ -726,11 +738,11 @@
738 for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
739 int iReuseIdx = -1;
740 int iReuseRail = -1;
741 int isCherrypick = 0;
742 for(i=1; i<pRow->nParent; i++){
743 GraphRowId parentRid = pRow->aParent[i];
744 if( i==pRow->nNonCherrypick ){
745 /* Because full merges are laid out before cherrypicks,
746 ** it is ok to use a full-merge raise for a cherrypick.
747 ** See the graph on check-in 8ac66ef33b464d28 for example
748 ** iReuseIdx = -1;
749
+1 -1
--- src/timeline.c
+++ src/timeline.c
@@ -484,11 +484,11 @@
484484
}
485485
}
486486
if( zType[0]=='c' && pGraph ){
487487
int nParent = 0;
488488
int nCherrypick = 0;
489
- int aParent[GR_MAX_RAIL];
489
+ GraphRowId aParent[GR_MAX_RAIL];
490490
static Stmt qparent;
491491
db_static_prepare(&qparent,
492492
"SELECT pid FROM plink"
493493
" WHERE cid=:rid AND pid NOT IN phantom"
494494
" ORDER BY isprim DESC /*sort*/"
495495
--- src/timeline.c
+++ src/timeline.c
@@ -484,11 +484,11 @@
484 }
485 }
486 if( zType[0]=='c' && pGraph ){
487 int nParent = 0;
488 int nCherrypick = 0;
489 int aParent[GR_MAX_RAIL];
490 static Stmt qparent;
491 db_static_prepare(&qparent,
492 "SELECT pid FROM plink"
493 " WHERE cid=:rid AND pid NOT IN phantom"
494 " ORDER BY isprim DESC /*sort*/"
495
--- src/timeline.c
+++ src/timeline.c
@@ -484,11 +484,11 @@
484 }
485 }
486 if( zType[0]=='c' && pGraph ){
487 int nParent = 0;
488 int nCherrypick = 0;
489 GraphRowId aParent[GR_MAX_RAIL];
490 static Stmt qparent;
491 db_static_prepare(&qparent,
492 "SELECT pid FROM plink"
493 " WHERE cid=:rid AND pid NOT IN phantom"
494 " ORDER BY isprim DESC /*sort*/"
495

Keyboard Shortcuts

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