Fossil SCM

In the /timeline page, add support for (from,ft) and (from,bt) query parameter pairs.

drh 2024-02-08 14:03 trunk
Commit 793c492415496a03edb8054c4603f3237754bff73d139f14d1c3740e3a1fbec9
1 file changed +135 -6
+135 -6
--- src/timeline.c
+++ src/timeline.c
@@ -1568,10 +1568,97 @@
15681568
15691569
/* It looks like this may be a date. Return it with punctuation added. */
15701570
return zEDate;
15711571
}
15721572
1573
+/*
1574
+** Find the first check-in encountered with a particular tag
1575
+** when moving either forwards are backwards in time from a
1576
+** particular starting point (iFrom). Return the rid of that
1577
+** first check-in. If there are no check-ins in the decendent
1578
+** or ancestor set of check-in iFrom that match the tag, then
1579
+** return 0.
1580
+*/
1581
+static int timeline_endpoint(
1582
+ int iFrom, /* Starting point */
1583
+ const char *zEnd, /* Tag we are searching for */
1584
+ int bForward /* 1: forwards in time (descendents) 0: backwards */
1585
+){
1586
+ int tagId;
1587
+ int endId = 0;
1588
+ Stmt q;
1589
+ int ans = 0;
1590
+
1591
+ tagId = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'", zEnd);
1592
+ if( tagId==0 ){
1593
+ endId = symbolic_name_to_rid(zEnd, "ci");
1594
+ if( endId==0 ) return 0;
1595
+ }
1596
+ if( bForward ){
1597
+ if( tagId ){
1598
+ db_prepare(&q,
1599
+ "WITH RECURSIVE dx(id,mtime) AS ("
1600
+ " SELECT %d, event.mtime FROM event WHERE objid=%d"
1601
+ " UNION ALL"
1602
+ " SELECT plink.cid, plink.mtime"
1603
+ " FROM dx, plink"
1604
+ " WHERE plink.pid=dx.id"
1605
+ " ORDER BY plink.mtime)"
1606
+ "SELECT id FROM dx, tagxref"
1607
+ " WHERE tagid=%d AND tagtype>0 AND rid=id LIMIT 1",
1608
+ iFrom, iFrom, tagId
1609
+ );
1610
+ }else{
1611
+ db_prepare(&q,
1612
+ "WITH RECURSIVE dx(id,mtime) AS ("
1613
+ " SELECT %d, event.mtime FROM event WHERE objid=%d"
1614
+ " UNION ALL"
1615
+ " SELECT plink.cid, plink.mtime"
1616
+ " FROM dx, plink"
1617
+ " WHERE plink.pid=dx.id"
1618
+ " AND plink.mtime<=(SELECT mtime FROM event WHERE objid=%d)"
1619
+ " ORDER BY plink.mtime)"
1620
+ "SELECT id FROM dx WHERE id=%d",
1621
+ iFrom, iFrom, endId, endId
1622
+ );
1623
+ }
1624
+ }else{
1625
+ if( tagId ){
1626
+ db_prepare(&q,
1627
+ "WITH RECURSIVE dx(id,mtime) AS ("
1628
+ " SELECT %d, event.mtime FROM event WHERE objid=%d"
1629
+ " UNION ALL"
1630
+ " SELECT plink.pid, event.mtime"
1631
+ " FROM dx, plink, event"
1632
+ " WHERE plink.cid=dx.id AND event.objid=plink.pid"
1633
+ " ORDER BY event.mtime DESC)"
1634
+ "SELECT id FROM dx, tagxref"
1635
+ " WHERE tagid=%d AND tagtype>0 AND rid=id LIMIT 1",
1636
+ iFrom, iFrom, tagId
1637
+ );
1638
+ }else{
1639
+ db_prepare(&q,
1640
+ "WITH RECURSIVE dx(id,mtime) AS ("
1641
+ " SELECT %d, event.mtime FROM event WHERE objid=%d"
1642
+ " UNION ALL"
1643
+ " SELECT plink.pid, event.mtime"
1644
+ " FROM dx, plink, event"
1645
+ " WHERE plink.cid=dx.id AND event.objid=plink.pid"
1646
+ " AND event.mtime>=(SELECT mtime FROM event WHERE objid=%d)"
1647
+ " ORDER BY event.mtime DESC)"
1648
+ "SELECT id FROM dx WHERE id=%d",
1649
+ iFrom, iFrom, endId, endId
1650
+ );
1651
+ }
1652
+ }
1653
+ if( db_step(&q)==SQLITE_ROW ){
1654
+ ans = db_column_int(&q, 0);
1655
+ }
1656
+ db_finalize(&q);
1657
+ return ans;
1658
+}
1659
+
15731660
15741661
/*
15751662
** WEBPAGE: timeline
15761663
**
15771664
** Query parameters:
@@ -1598,14 +1685,16 @@
15981685
** bt=PRIOR ... going back to PRIOR
15991686
** d=CHECKIN Children and descendants of CHECKIN
16001687
** ft=DESCENDANT ... going forward to DESCENDANT
16011688
** dp=CHECKIN Same as 'd=CHECKIN&p=CHECKIN'
16021689
** df=CHECKIN Same as 'd=CHECKIN&n1=all&nd'. Mnemonic: "Derived From"
1603
-** bt=CHECKIN In conjunction with p=CX, this means show all
1604
-** ancestors of CX going back to the time of CHECKIN.
1605
-** All qualifying check-ins are shown unless there
1606
-** is also an n= or n1= query parameter.
1690
+** bt=CHECKIN "Back To". Show ancenstors going back to CHECKIN
1691
+** p=CX ... from CX back to time of CHECKIN
1692
+** from=CX ... shortest path from CX back to CHECKIN
1693
+** ft=CHECKIN "Forward To": Show decendents forward to CHECKIN
1694
+** d=CX ... from CX up to the time of CHECKIN
1695
+** from=CX ... shortest path from CX up to CHECKIN
16071696
** t=TAG Show only check-ins with the given TAG
16081697
** r=TAG Show check-ins related to TAG, equivalent to t=TAG&rel
16091698
** tl=TAGLIST Shorthand for t=TAGLIST&ms=brlist
16101699
** rl=TAGLIST Shorthand for r=TAGLIST&ms=brlist
16111700
** rel Show related check-ins as well as those matching t=TAG
@@ -1627,10 +1716,12 @@
16271716
** f=CHECKIN Show family (immediate parents and children) of CHECKIN
16281717
** from=CHECKIN Path from...
16291718
** to=CHECKIN ... to this
16301719
** shortest ... show only the shortest path
16311720
** rel ... also show related checkins
1721
+** bt=PRIOR ... path from CHECKIN back to PRIOR
1722
+** ft=LATER ... path from CHECKIN forward to LATER
16321723
** uf=FILE_HASH Show only check-ins that contain the given file version
16331724
** All qualifying check-ins are shown unless there is
16341725
** also an n= or n1= query parameter.
16351726
** chng=GLOBLIST Show only check-ins that involve changes to a file whose
16361727
** name matches one of the comma-separate GLOBLIST
@@ -1727,10 +1818,11 @@
17271818
int disableY = 0; /* Disable type selector on submenu */
17281819
int advancedMenu = 0; /* Use the advanced menu design */
17291820
char *zPlural; /* Ending for plural forms */
17301821
int showCherrypicks = 1; /* True to show cherrypick merges */
17311822
int haveParameterN; /* True if n= query parameter present */
1823
+ int from_to_mode = 0; /* 0: from,to. 1: from,ft 2: from,bt */
17321824
17331825
url_initialize(&url, "timeline");
17341826
cgi_query_parameters_to_url(&url);
17351827
17361828
(void)P_NoBot("ss")
@@ -2043,10 +2135,29 @@
20432135
blob_append_sql(&sql,
20442136
" AND NOT EXISTS(SELECT 1 FROM tagxref"
20452137
" WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)\n",
20462138
TAG_HIDDEN
20472139
);
2140
+ }
2141
+ if( from_rid && !to_rid && (P("ft")!=0 || P("bt")!=0) ){
2142
+ const char *zTo = P("ft");
2143
+ if( zTo ){
2144
+ from_to_mode = 1;
2145
+ to_rid = timeline_endpoint(from_rid, zTo, 1);
2146
+ }else{
2147
+ from_to_mode = 2;
2148
+ zTo = P("bt");
2149
+ to_rid = timeline_endpoint(from_rid, zTo, 0);
2150
+ }
2151
+ if( to_rid ){
2152
+ cgi_replace_parameter("to", zTo);
2153
+ if( selectedRid==0 ) selectedRid = from_rid;
2154
+ if( secondaryRid==0 ) secondaryRid = to_rid;
2155
+ }else{
2156
+ blob_appendf(&desc, "There is no path from %h %s to %h.<br>Instead: ",
2157
+ P("from"), from_to_mode==1 ? "forward" : "back", zTo);
2158
+ }
20482159
}
20492160
if( ((from_rid && to_rid) || (me_rid && you_rid)) && g.perm.Read ){
20502161
/* If from= and to= are present, display all nodes on a path connecting
20512162
** the two */
20522163
PathNode *p = 0;
@@ -2054,11 +2165,17 @@
20542165
const char *zTo = 0;
20552166
Blob ins;
20562167
int nNodeOnPath = 0;
20572168
20582169
if( from_rid && to_rid ){
2059
- p = path_shortest(from_rid, to_rid, noMerge, 0, 0);
2170
+ if( from_to_mode==0 ){
2171
+ p = path_shortest(from_rid, to_rid, noMerge, 0, 0);
2172
+ }else if( from_to_mode==1 ){
2173
+ p = path_shortest(from_rid, to_rid, 0, 1, 0);
2174
+ }else{
2175
+ p = path_shortest(to_rid, from_rid, 0, 1, 0);
2176
+ }
20602177
zFrom = P("from");
20612178
zTo = P("to");
20622179
}else{
20632180
if( path_common_ancestor(me_rid, you_rid) ){
20642181
p = path_first();
@@ -2122,14 +2239,26 @@
21222239
db_multi_exec("%s", blob_sql_text(&sql));
21232240
if( advancedMenu ){
21242241
style_submenu_checkbox("v", "Files", (zType[0]!='a' && zType[0]!='c'),0);
21252242
}
21262243
nNodeOnPath = db_int(0, "SELECT count(*) FROM temp.pathnode");
2127
- blob_appendf(&desc, "%d check-ins going from ", nNodeOnPath);
2244
+ if( from_to_mode>0 ){
2245
+ blob_appendf(&desc, "%d check-ins on the shorted path from ",nNodeOnPath);
2246
+ }else{
2247
+ blob_appendf(&desc, "%d check-ins going from ", nNodeOnPath);
2248
+ }
2249
+ if( from_rid==selectedRid ){
2250
+ blob_appendf(&desc, "<span class='timelineSelected'>");
2251
+ }
21282252
blob_appendf(&desc, "%z%h</a>", href("%R/info/%h", zFrom), zFrom);
2253
+ if( from_rid==selectedRid ) blob_appendf(&desc, "</span>");
21292254
blob_append(&desc, " to ", -1);
2255
+ if( to_rid==secondaryRid ){
2256
+ blob_appendf(&desc, "<span class='timelineSelected timelineSecondary'>");
2257
+ }
21302258
blob_appendf(&desc, "%z%h</a>", href("%R/info/%h",zTo), zTo);
2259
+ if( to_rid==secondaryRid ) blob_appendf(&desc, "</span>");
21312260
if( related ){
21322261
int nRelated = db_int(0, "SELECT count(*) FROM timeline") - nNodeOnPath;
21332262
if( nRelated>0 ){
21342263
blob_appendf(&desc, " and %d related check-in%s", nRelated,
21352264
nRelated>1 ? "s" : "");
21362265
--- src/timeline.c
+++ src/timeline.c
@@ -1568,10 +1568,97 @@
1568
1569 /* It looks like this may be a date. Return it with punctuation added. */
1570 return zEDate;
1571 }
1572
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1573
1574 /*
1575 ** WEBPAGE: timeline
1576 **
1577 ** Query parameters:
@@ -1598,14 +1685,16 @@
1598 ** bt=PRIOR ... going back to PRIOR
1599 ** d=CHECKIN Children and descendants of CHECKIN
1600 ** ft=DESCENDANT ... going forward to DESCENDANT
1601 ** dp=CHECKIN Same as 'd=CHECKIN&p=CHECKIN'
1602 ** df=CHECKIN Same as 'd=CHECKIN&n1=all&nd'. Mnemonic: "Derived From"
1603 ** bt=CHECKIN In conjunction with p=CX, this means show all
1604 ** ancestors of CX going back to the time of CHECKIN.
1605 ** All qualifying check-ins are shown unless there
1606 ** is also an n= or n1= query parameter.
 
 
1607 ** t=TAG Show only check-ins with the given TAG
1608 ** r=TAG Show check-ins related to TAG, equivalent to t=TAG&rel
1609 ** tl=TAGLIST Shorthand for t=TAGLIST&ms=brlist
1610 ** rl=TAGLIST Shorthand for r=TAGLIST&ms=brlist
1611 ** rel Show related check-ins as well as those matching t=TAG
@@ -1627,10 +1716,12 @@
1627 ** f=CHECKIN Show family (immediate parents and children) of CHECKIN
1628 ** from=CHECKIN Path from...
1629 ** to=CHECKIN ... to this
1630 ** shortest ... show only the shortest path
1631 ** rel ... also show related checkins
 
 
1632 ** uf=FILE_HASH Show only check-ins that contain the given file version
1633 ** All qualifying check-ins are shown unless there is
1634 ** also an n= or n1= query parameter.
1635 ** chng=GLOBLIST Show only check-ins that involve changes to a file whose
1636 ** name matches one of the comma-separate GLOBLIST
@@ -1727,10 +1818,11 @@
1727 int disableY = 0; /* Disable type selector on submenu */
1728 int advancedMenu = 0; /* Use the advanced menu design */
1729 char *zPlural; /* Ending for plural forms */
1730 int showCherrypicks = 1; /* True to show cherrypick merges */
1731 int haveParameterN; /* True if n= query parameter present */
 
1732
1733 url_initialize(&url, "timeline");
1734 cgi_query_parameters_to_url(&url);
1735
1736 (void)P_NoBot("ss")
@@ -2043,10 +2135,29 @@
2043 blob_append_sql(&sql,
2044 " AND NOT EXISTS(SELECT 1 FROM tagxref"
2045 " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)\n",
2046 TAG_HIDDEN
2047 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2048 }
2049 if( ((from_rid && to_rid) || (me_rid && you_rid)) && g.perm.Read ){
2050 /* If from= and to= are present, display all nodes on a path connecting
2051 ** the two */
2052 PathNode *p = 0;
@@ -2054,11 +2165,17 @@
2054 const char *zTo = 0;
2055 Blob ins;
2056 int nNodeOnPath = 0;
2057
2058 if( from_rid && to_rid ){
2059 p = path_shortest(from_rid, to_rid, noMerge, 0, 0);
 
 
 
 
 
 
2060 zFrom = P("from");
2061 zTo = P("to");
2062 }else{
2063 if( path_common_ancestor(me_rid, you_rid) ){
2064 p = path_first();
@@ -2122,14 +2239,26 @@
2122 db_multi_exec("%s", blob_sql_text(&sql));
2123 if( advancedMenu ){
2124 style_submenu_checkbox("v", "Files", (zType[0]!='a' && zType[0]!='c'),0);
2125 }
2126 nNodeOnPath = db_int(0, "SELECT count(*) FROM temp.pathnode");
2127 blob_appendf(&desc, "%d check-ins going from ", nNodeOnPath);
 
 
 
 
 
 
 
2128 blob_appendf(&desc, "%z%h</a>", href("%R/info/%h", zFrom), zFrom);
 
2129 blob_append(&desc, " to ", -1);
 
 
 
2130 blob_appendf(&desc, "%z%h</a>", href("%R/info/%h",zTo), zTo);
 
2131 if( related ){
2132 int nRelated = db_int(0, "SELECT count(*) FROM timeline") - nNodeOnPath;
2133 if( nRelated>0 ){
2134 blob_appendf(&desc, " and %d related check-in%s", nRelated,
2135 nRelated>1 ? "s" : "");
2136
--- src/timeline.c
+++ src/timeline.c
@@ -1568,10 +1568,97 @@
1568
1569 /* It looks like this may be a date. Return it with punctuation added. */
1570 return zEDate;
1571 }
1572
1573 /*
1574 ** Find the first check-in encountered with a particular tag
1575 ** when moving either forwards are backwards in time from a
1576 ** particular starting point (iFrom). Return the rid of that
1577 ** first check-in. If there are no check-ins in the decendent
1578 ** or ancestor set of check-in iFrom that match the tag, then
1579 ** return 0.
1580 */
1581 static int timeline_endpoint(
1582 int iFrom, /* Starting point */
1583 const char *zEnd, /* Tag we are searching for */
1584 int bForward /* 1: forwards in time (descendents) 0: backwards */
1585 ){
1586 int tagId;
1587 int endId = 0;
1588 Stmt q;
1589 int ans = 0;
1590
1591 tagId = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'", zEnd);
1592 if( tagId==0 ){
1593 endId = symbolic_name_to_rid(zEnd, "ci");
1594 if( endId==0 ) return 0;
1595 }
1596 if( bForward ){
1597 if( tagId ){
1598 db_prepare(&q,
1599 "WITH RECURSIVE dx(id,mtime) AS ("
1600 " SELECT %d, event.mtime FROM event WHERE objid=%d"
1601 " UNION ALL"
1602 " SELECT plink.cid, plink.mtime"
1603 " FROM dx, plink"
1604 " WHERE plink.pid=dx.id"
1605 " ORDER BY plink.mtime)"
1606 "SELECT id FROM dx, tagxref"
1607 " WHERE tagid=%d AND tagtype>0 AND rid=id LIMIT 1",
1608 iFrom, iFrom, tagId
1609 );
1610 }else{
1611 db_prepare(&q,
1612 "WITH RECURSIVE dx(id,mtime) AS ("
1613 " SELECT %d, event.mtime FROM event WHERE objid=%d"
1614 " UNION ALL"
1615 " SELECT plink.cid, plink.mtime"
1616 " FROM dx, plink"
1617 " WHERE plink.pid=dx.id"
1618 " AND plink.mtime<=(SELECT mtime FROM event WHERE objid=%d)"
1619 " ORDER BY plink.mtime)"
1620 "SELECT id FROM dx WHERE id=%d",
1621 iFrom, iFrom, endId, endId
1622 );
1623 }
1624 }else{
1625 if( tagId ){
1626 db_prepare(&q,
1627 "WITH RECURSIVE dx(id,mtime) AS ("
1628 " SELECT %d, event.mtime FROM event WHERE objid=%d"
1629 " UNION ALL"
1630 " SELECT plink.pid, event.mtime"
1631 " FROM dx, plink, event"
1632 " WHERE plink.cid=dx.id AND event.objid=plink.pid"
1633 " ORDER BY event.mtime DESC)"
1634 "SELECT id FROM dx, tagxref"
1635 " WHERE tagid=%d AND tagtype>0 AND rid=id LIMIT 1",
1636 iFrom, iFrom, tagId
1637 );
1638 }else{
1639 db_prepare(&q,
1640 "WITH RECURSIVE dx(id,mtime) AS ("
1641 " SELECT %d, event.mtime FROM event WHERE objid=%d"
1642 " UNION ALL"
1643 " SELECT plink.pid, event.mtime"
1644 " FROM dx, plink, event"
1645 " WHERE plink.cid=dx.id AND event.objid=plink.pid"
1646 " AND event.mtime>=(SELECT mtime FROM event WHERE objid=%d)"
1647 " ORDER BY event.mtime DESC)"
1648 "SELECT id FROM dx WHERE id=%d",
1649 iFrom, iFrom, endId, endId
1650 );
1651 }
1652 }
1653 if( db_step(&q)==SQLITE_ROW ){
1654 ans = db_column_int(&q, 0);
1655 }
1656 db_finalize(&q);
1657 return ans;
1658 }
1659
1660
1661 /*
1662 ** WEBPAGE: timeline
1663 **
1664 ** Query parameters:
@@ -1598,14 +1685,16 @@
1685 ** bt=PRIOR ... going back to PRIOR
1686 ** d=CHECKIN Children and descendants of CHECKIN
1687 ** ft=DESCENDANT ... going forward to DESCENDANT
1688 ** dp=CHECKIN Same as 'd=CHECKIN&p=CHECKIN'
1689 ** df=CHECKIN Same as 'd=CHECKIN&n1=all&nd'. Mnemonic: "Derived From"
1690 ** bt=CHECKIN "Back To". Show ancenstors going back to CHECKIN
1691 ** p=CX ... from CX back to time of CHECKIN
1692 ** from=CX ... shortest path from CX back to CHECKIN
1693 ** ft=CHECKIN "Forward To": Show decendents forward to CHECKIN
1694 ** d=CX ... from CX up to the time of CHECKIN
1695 ** from=CX ... shortest path from CX up to CHECKIN
1696 ** t=TAG Show only check-ins with the given TAG
1697 ** r=TAG Show check-ins related to TAG, equivalent to t=TAG&rel
1698 ** tl=TAGLIST Shorthand for t=TAGLIST&ms=brlist
1699 ** rl=TAGLIST Shorthand for r=TAGLIST&ms=brlist
1700 ** rel Show related check-ins as well as those matching t=TAG
@@ -1627,10 +1716,12 @@
1716 ** f=CHECKIN Show family (immediate parents and children) of CHECKIN
1717 ** from=CHECKIN Path from...
1718 ** to=CHECKIN ... to this
1719 ** shortest ... show only the shortest path
1720 ** rel ... also show related checkins
1721 ** bt=PRIOR ... path from CHECKIN back to PRIOR
1722 ** ft=LATER ... path from CHECKIN forward to LATER
1723 ** uf=FILE_HASH Show only check-ins that contain the given file version
1724 ** All qualifying check-ins are shown unless there is
1725 ** also an n= or n1= query parameter.
1726 ** chng=GLOBLIST Show only check-ins that involve changes to a file whose
1727 ** name matches one of the comma-separate GLOBLIST
@@ -1727,10 +1818,11 @@
1818 int disableY = 0; /* Disable type selector on submenu */
1819 int advancedMenu = 0; /* Use the advanced menu design */
1820 char *zPlural; /* Ending for plural forms */
1821 int showCherrypicks = 1; /* True to show cherrypick merges */
1822 int haveParameterN; /* True if n= query parameter present */
1823 int from_to_mode = 0; /* 0: from,to. 1: from,ft 2: from,bt */
1824
1825 url_initialize(&url, "timeline");
1826 cgi_query_parameters_to_url(&url);
1827
1828 (void)P_NoBot("ss")
@@ -2043,10 +2135,29 @@
2135 blob_append_sql(&sql,
2136 " AND NOT EXISTS(SELECT 1 FROM tagxref"
2137 " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)\n",
2138 TAG_HIDDEN
2139 );
2140 }
2141 if( from_rid && !to_rid && (P("ft")!=0 || P("bt")!=0) ){
2142 const char *zTo = P("ft");
2143 if( zTo ){
2144 from_to_mode = 1;
2145 to_rid = timeline_endpoint(from_rid, zTo, 1);
2146 }else{
2147 from_to_mode = 2;
2148 zTo = P("bt");
2149 to_rid = timeline_endpoint(from_rid, zTo, 0);
2150 }
2151 if( to_rid ){
2152 cgi_replace_parameter("to", zTo);
2153 if( selectedRid==0 ) selectedRid = from_rid;
2154 if( secondaryRid==0 ) secondaryRid = to_rid;
2155 }else{
2156 blob_appendf(&desc, "There is no path from %h %s to %h.<br>Instead: ",
2157 P("from"), from_to_mode==1 ? "forward" : "back", zTo);
2158 }
2159 }
2160 if( ((from_rid && to_rid) || (me_rid && you_rid)) && g.perm.Read ){
2161 /* If from= and to= are present, display all nodes on a path connecting
2162 ** the two */
2163 PathNode *p = 0;
@@ -2054,11 +2165,17 @@
2165 const char *zTo = 0;
2166 Blob ins;
2167 int nNodeOnPath = 0;
2168
2169 if( from_rid && to_rid ){
2170 if( from_to_mode==0 ){
2171 p = path_shortest(from_rid, to_rid, noMerge, 0, 0);
2172 }else if( from_to_mode==1 ){
2173 p = path_shortest(from_rid, to_rid, 0, 1, 0);
2174 }else{
2175 p = path_shortest(to_rid, from_rid, 0, 1, 0);
2176 }
2177 zFrom = P("from");
2178 zTo = P("to");
2179 }else{
2180 if( path_common_ancestor(me_rid, you_rid) ){
2181 p = path_first();
@@ -2122,14 +2239,26 @@
2239 db_multi_exec("%s", blob_sql_text(&sql));
2240 if( advancedMenu ){
2241 style_submenu_checkbox("v", "Files", (zType[0]!='a' && zType[0]!='c'),0);
2242 }
2243 nNodeOnPath = db_int(0, "SELECT count(*) FROM temp.pathnode");
2244 if( from_to_mode>0 ){
2245 blob_appendf(&desc, "%d check-ins on the shorted path from ",nNodeOnPath);
2246 }else{
2247 blob_appendf(&desc, "%d check-ins going from ", nNodeOnPath);
2248 }
2249 if( from_rid==selectedRid ){
2250 blob_appendf(&desc, "<span class='timelineSelected'>");
2251 }
2252 blob_appendf(&desc, "%z%h</a>", href("%R/info/%h", zFrom), zFrom);
2253 if( from_rid==selectedRid ) blob_appendf(&desc, "</span>");
2254 blob_append(&desc, " to ", -1);
2255 if( to_rid==secondaryRid ){
2256 blob_appendf(&desc, "<span class='timelineSelected timelineSecondary'>");
2257 }
2258 blob_appendf(&desc, "%z%h</a>", href("%R/info/%h",zTo), zTo);
2259 if( to_rid==secondaryRid ) blob_appendf(&desc, "</span>");
2260 if( related ){
2261 int nRelated = db_int(0, "SELECT count(*) FROM timeline") - nNodeOnPath;
2262 if( nRelated>0 ){
2263 blob_appendf(&desc, " and %d related check-in%s", nRelated,
2264 nRelated>1 ? "s" : "");
2265

Keyboard Shortcuts

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