Fossil SCM
Fix two issues with Older/Newer buttons at timeline edges.
Commit
f7c19ec0cc098d2d1901a647b957099a367a4cc8
Parent
f4f3af4adb62e80…
1 file changed
+55
-50
+55
-50
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -1517,39 +1517,41 @@ | ||
| 1517 | 1517 | if( (tmFlags & TIMELINE_UNHIDE)==0 ){ |
| 1518 | 1518 | timeline_submenu(&url, "Unhide", "unhide", "", 0); |
| 1519 | 1519 | } |
| 1520 | 1520 | }else{ |
| 1521 | 1521 | /* Otherwise, a timeline based on a span of time */ |
| 1522 | - int n, nBefore, nAfter; | |
| 1522 | + int n; | |
| 1523 | 1523 | const char *zEType = "timeline item"; |
| 1524 | 1524 | char *zDate; |
| 1525 | + Blob cond; | |
| 1526 | + blob_zero(&cond); | |
| 1525 | 1527 | if( zUses ){ |
| 1526 | - blob_append_sql(&sql, " AND event.objid IN usesfile "); | |
| 1528 | + blob_append_sql(&cond, " AND event.objid IN usesfile "); | |
| 1527 | 1529 | } |
| 1528 | 1530 | if( renameOnly ){ |
| 1529 | - blob_append_sql(&sql, " AND event.objid IN rnfile "); | |
| 1531 | + blob_append_sql(&cond, " AND event.objid IN rnfile "); | |
| 1530 | 1532 | } |
| 1531 | 1533 | if( forkOnly ){ |
| 1532 | - blob_append_sql(&sql, " AND event.objid IN rnfork "); | |
| 1534 | + blob_append_sql(&cond, " AND event.objid IN rnfork "); | |
| 1533 | 1535 | } |
| 1534 | 1536 | if( bisectOnly ){ |
| 1535 | - blob_append_sql(&sql, " AND event.objid IN (SELECT rid FROM bilog) "); | |
| 1537 | + blob_append_sql(&cond, " AND event.objid IN (SELECT rid FROM bilog) "); | |
| 1536 | 1538 | } |
| 1537 | 1539 | if( zYearMonth ){ |
| 1538 | - blob_append_sql(&sql, " AND %Q=strftime('%%Y-%%m',event.mtime) ", | |
| 1540 | + blob_append_sql(&cond, " AND %Q=strftime('%%Y-%%m',event.mtime) ", | |
| 1539 | 1541 | zYearMonth); |
| 1540 | 1542 | } |
| 1541 | 1543 | else if( zYearWeek ){ |
| 1542 | - blob_append_sql(&sql, " AND %Q=strftime('%%Y-%%W',event.mtime) ", | |
| 1544 | + blob_append_sql(&cond, " AND %Q=strftime('%%Y-%%W',event.mtime) ", | |
| 1543 | 1545 | zYearWeek); |
| 1544 | 1546 | } |
| 1545 | 1547 | else if( zDay ){ |
| 1546 | - blob_append_sql(&sql, " AND %Q=strftime('%%Y-%%m-%%d',event.mtime) ", | |
| 1548 | + blob_append_sql(&cond, " AND %Q=strftime('%%Y-%%m-%%d',event.mtime) ", | |
| 1547 | 1549 | zDay); |
| 1548 | 1550 | } |
| 1549 | 1551 | if( tagid ){ |
| 1550 | - blob_append_sql(&sql, | |
| 1552 | + blob_append_sql(&cond, | |
| 1551 | 1553 | " AND (EXISTS(SELECT 1 FROM tagxref" |
| 1552 | 1554 | " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)\n", tagid); |
| 1553 | 1555 | |
| 1554 | 1556 | if( zBrName ){ |
| 1555 | 1557 | /* The next two blob_appendf() calls add SQL that causes check-ins that |
| @@ -1556,38 +1558,38 @@ | ||
| 1556 | 1558 | ** are not part of the branch which are parents or children of the |
| 1557 | 1559 | ** branch to be included in the report. This related check-ins are |
| 1558 | 1560 | ** useful in helping to visualize what has happened on a quiescent |
| 1559 | 1561 | ** branch that is infrequently merged with a much more activate branch. |
| 1560 | 1562 | */ |
| 1561 | - blob_append_sql(&sql, | |
| 1563 | + blob_append_sql(&cond, | |
| 1562 | 1564 | " OR EXISTS(SELECT 1 FROM plink CROSS JOIN tagxref ON rid=cid" |
| 1563 | 1565 | " WHERE tagid=%d AND tagtype>0 AND pid=blob.rid)\n", |
| 1564 | 1566 | tagid |
| 1565 | 1567 | ); |
| 1566 | 1568 | if( (tmFlags & TIMELINE_UNHIDE)==0 ){ |
| 1567 | - blob_append_sql(&sql, | |
| 1569 | + blob_append_sql(&cond, | |
| 1568 | 1570 | " AND NOT EXISTS(SELECT 1 FROM plink JOIN tagxref ON rid=cid" |
| 1569 | 1571 | " WHERE tagid=%d AND tagtype>0 AND pid=blob.rid)\n", |
| 1570 | 1572 | TAG_HIDDEN |
| 1571 | 1573 | ); |
| 1572 | 1574 | } |
| 1573 | 1575 | if( P("mionly")==0 ){ |
| 1574 | - blob_append_sql(&sql, | |
| 1576 | + blob_append_sql(&cond, | |
| 1575 | 1577 | " OR EXISTS(SELECT 1 FROM plink CROSS JOIN tagxref ON rid=pid" |
| 1576 | 1578 | " WHERE tagid=%d AND tagtype>0 AND cid=blob.rid)\n", |
| 1577 | 1579 | tagid |
| 1578 | 1580 | ); |
| 1579 | 1581 | if( (tmFlags & TIMELINE_UNHIDE)==0 ){ |
| 1580 | - blob_append_sql(&sql, | |
| 1582 | + blob_append_sql(&cond, | |
| 1581 | 1583 | " AND NOT EXISTS(SELECT 1 FROM plink JOIN tagxref ON rid=pid" |
| 1582 | 1584 | " WHERE tagid=%d AND tagtype>0 AND cid=blob.rid)\n", |
| 1583 | 1585 | TAG_HIDDEN |
| 1584 | 1586 | ); |
| 1585 | 1587 | } |
| 1586 | 1588 | } |
| 1587 | 1589 | } |
| 1588 | - blob_append_sql(&sql, ")"); | |
| 1590 | + blob_append_sql(&cond, ")"); | |
| 1589 | 1591 | } |
| 1590 | 1592 | if( (zType[0]=='w' && !g.perm.RdWiki) |
| 1591 | 1593 | || (zType[0]=='t' && !g.perm.RdTkt) |
| 1592 | 1594 | || (zType[0]=='e' && !g.perm.RdWiki) |
| 1593 | 1595 | || (zType[0]=='c' && !g.perm.Read) |
| @@ -1596,27 +1598,27 @@ | ||
| 1596 | 1598 | zType = "all"; |
| 1597 | 1599 | } |
| 1598 | 1600 | if( zType[0]=='a' ){ |
| 1599 | 1601 | if( !g.perm.Read || !g.perm.RdWiki || !g.perm.RdTkt ){ |
| 1600 | 1602 | char cSep = '('; |
| 1601 | - blob_append_sql(&sql, " AND event.type IN "); | |
| 1603 | + blob_append_sql(&cond, " AND event.type IN "); | |
| 1602 | 1604 | if( g.perm.Read ){ |
| 1603 | - blob_append_sql(&sql, "%c'ci','g'", cSep); | |
| 1605 | + blob_append_sql(&cond, "%c'ci','g'", cSep); | |
| 1604 | 1606 | cSep = ','; |
| 1605 | 1607 | } |
| 1606 | 1608 | if( g.perm.RdWiki ){ |
| 1607 | - blob_append_sql(&sql, "%c'w','e'", cSep); | |
| 1609 | + blob_append_sql(&cond, "%c'w','e'", cSep); | |
| 1608 | 1610 | cSep = ','; |
| 1609 | 1611 | } |
| 1610 | 1612 | if( g.perm.RdTkt ){ |
| 1611 | - blob_append_sql(&sql, "%c't'", cSep); | |
| 1613 | + blob_append_sql(&cond, "%c't'", cSep); | |
| 1612 | 1614 | cSep = ','; |
| 1613 | 1615 | } |
| 1614 | - blob_append_sql(&sql, ")"); | |
| 1616 | + blob_append_sql(&cond, ")"); | |
| 1615 | 1617 | } |
| 1616 | 1618 | }else{ /* zType!="all" */ |
| 1617 | - blob_append_sql(&sql, " AND event.type=%Q", zType); | |
| 1619 | + blob_append_sql(&cond, " AND event.type=%Q", zType); | |
| 1618 | 1620 | if( zType[0]=='c' ){ |
| 1619 | 1621 | zEType = "check-in"; |
| 1620 | 1622 | }else if( zType[0]=='w' ){ |
| 1621 | 1623 | zEType = "wiki edit"; |
| 1622 | 1624 | }else if( zType[0]=='t' ){ |
| @@ -1632,22 +1634,23 @@ | ||
| 1632 | 1634 | " WHERE user=%Q OR euser=%Q", zUser, zUser); |
| 1633 | 1635 | if( n<=nEntry ){ |
| 1634 | 1636 | zCirca = zBefore = zAfter = 0; |
| 1635 | 1637 | nEntry = -1; |
| 1636 | 1638 | } |
| 1637 | - blob_append_sql(&sql, " AND (event.user=%Q OR event.euser=%Q)", | |
| 1639 | + blob_append_sql(&cond, " AND (event.user=%Q OR event.euser=%Q)", | |
| 1638 | 1640 | zUser, zUser); |
| 1639 | 1641 | zThisUser = zUser; |
| 1640 | 1642 | } |
| 1641 | 1643 | if( zSearch ){ |
| 1642 | - blob_append_sql(&sql, | |
| 1644 | + blob_append_sql(&cond, | |
| 1643 | 1645 | " AND (event.comment LIKE '%%%q%%' OR event.brief LIKE '%%%q%%')", |
| 1644 | 1646 | zSearch, zSearch); |
| 1645 | 1647 | } |
| 1646 | 1648 | rBefore = symbolic_name_to_mtime(zBefore); |
| 1647 | 1649 | rAfter = symbolic_name_to_mtime(zAfter); |
| 1648 | 1650 | rCirca = symbolic_name_to_mtime(zCirca); |
| 1651 | + blob_append_sql(&sql, "%s", blob_sql_text(&cond)); | |
| 1649 | 1652 | if( rAfter>0.0 ){ |
| 1650 | 1653 | if( rBefore>0.0 ){ |
| 1651 | 1654 | blob_append_sql(&sql, |
| 1652 | 1655 | " AND event.mtime>=%.17g AND event.mtime<=%.17g" |
| 1653 | 1656 | " ORDER BY event.mtime ASC", rAfter-ONE_SECOND, rBefore+ONE_SECOND); |
| @@ -1745,38 +1748,39 @@ | ||
| 1745 | 1748 | } |
| 1746 | 1749 | if( zSearch ){ |
| 1747 | 1750 | blob_appendf(&desc, " matching \"%h\"", zSearch); |
| 1748 | 1751 | } |
| 1749 | 1752 | if( g.perm.Hyperlink ){ |
| 1750 | - if( zCirca && rCirca ){ | |
| 1751 | - nBefore = db_int(0, | |
| 1752 | - "SELECT count(*) FROM timeline WHERE etype!='div'" | |
| 1753 | - " AND sortby<=%f /*scan*/", rCirca); | |
| 1754 | - nAfter = db_int(0, | |
| 1755 | - "SELECT count(*) FROM timeline WHERE etype!='div'" | |
| 1756 | - " AND sortby>=%f /*scan*/", rCirca); | |
| 1757 | - zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/"); | |
| 1758 | - if( nBefore>=nEntry ){ | |
| 1759 | - timeline_submenu(&url, "Older", "b", zDate, "c"); | |
| 1760 | - zOlderButton = fossil_strdup(url_render(&url, "b", zDate, "c", 0)); | |
| 1761 | - } | |
| 1762 | - if( nAfter>=nEntry ){ | |
| 1763 | - timeline_submenu(&url, "Newer", "a", zDate, "c"); | |
| 1764 | - } | |
| 1765 | - free(zDate); | |
| 1766 | - }else{ | |
| 1767 | - if( zAfter || n==nEntry ){ | |
| 1768 | - zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/"); | |
| 1769 | - timeline_submenu(&url, "Older", "b", zDate, "a"); | |
| 1770 | - zOlderButton = fossil_strdup(url_render(&url, "b", zDate, "a", 0)); | |
| 1771 | - free(zDate); | |
| 1772 | - } | |
| 1773 | - if( zBefore || (zAfter && n==nEntry) ){ | |
| 1774 | - zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/"); | |
| 1775 | - timeline_submenu(&url, "Newer", "a", zDate, "b"); | |
| 1776 | - free(zDate); | |
| 1777 | - } | |
| 1753 | + double rDate; | |
| 1754 | + zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/"); | |
| 1755 | + if( (!zDate || !zDate[0]) && ( zAfter || zBefore ) ){ | |
| 1756 | + zDate = mprintf("%s", (zAfter ? zAfter : zBefore)); | |
| 1757 | + } | |
| 1758 | + if( zDate ){ | |
| 1759 | + rDate = symbolic_name_to_mtime(zDate); | |
| 1760 | + if( db_int(0, | |
| 1761 | + "SELECT EXISTS (SELECT 1 FROM event WHERE mtime<=%.17g%s)", | |
| 1762 | + rDate-ONE_SECOND, blob_sql_text(&cond)) | |
| 1763 | + ){ | |
| 1764 | + timeline_submenu(&url, "Older", "b", zDate, "a"); | |
| 1765 | + zOlderButton = fossil_strdup(url_render(&url, "b", zDate, "a", 0)); | |
| 1766 | + } | |
| 1767 | + free(zDate); | |
| 1768 | + } | |
| 1769 | + zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/"); | |
| 1770 | + if( (!zDate || !zDate[0]) && ( zAfter || zBefore ) ){ | |
| 1771 | + zDate = mprintf("%s", (zBefore ? zBefore : zAfter)); | |
| 1772 | + } | |
| 1773 | + if( zDate ){ | |
| 1774 | + rDate = symbolic_name_to_mtime(zDate); | |
| 1775 | + if( db_int(0, | |
| 1776 | + "SELECT EXISTS (SELECT 1 FROM event WHERE mtime>=%.17g%s)", | |
| 1777 | + rDate+ONE_SECOND, blob_sql_text(&cond)) | |
| 1778 | + ){ | |
| 1779 | + timeline_submenu(&url, "Newer", "a", zDate, "b"); | |
| 1780 | + } | |
| 1781 | + free(zDate); | |
| 1778 | 1782 | } |
| 1779 | 1783 | if( zType[0]=='a' || zType[0]=='c' ){ |
| 1780 | 1784 | if( (tmFlags & TIMELINE_UNHIDE)==0 ){ |
| 1781 | 1785 | timeline_submenu(&url, "Unhide", "unhide", "", 0); |
| 1782 | 1786 | } |
| @@ -1784,10 +1788,11 @@ | ||
| 1784 | 1788 | style_submenu_entry("n","Max:",4,0); |
| 1785 | 1789 | timeline_y_submenu(disableY); |
| 1786 | 1790 | style_submenu_binary("v","With Files","Without Files", |
| 1787 | 1791 | zType[0]!='a' && zType[0]!='c'); |
| 1788 | 1792 | } |
| 1793 | + blob_zero(&cond); | |
| 1789 | 1794 | } |
| 1790 | 1795 | if( PB("showsql") ){ |
| 1791 | 1796 | @ <pre>%h(blob_sql_text(&sql))</pre> |
| 1792 | 1797 | } |
| 1793 | 1798 | if( search_restrict(SRCH_CKIN)!=0 ){ |
| 1794 | 1799 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -1517,39 +1517,41 @@ | |
| 1517 | if( (tmFlags & TIMELINE_UNHIDE)==0 ){ |
| 1518 | timeline_submenu(&url, "Unhide", "unhide", "", 0); |
| 1519 | } |
| 1520 | }else{ |
| 1521 | /* Otherwise, a timeline based on a span of time */ |
| 1522 | int n, nBefore, nAfter; |
| 1523 | const char *zEType = "timeline item"; |
| 1524 | char *zDate; |
| 1525 | if( zUses ){ |
| 1526 | blob_append_sql(&sql, " AND event.objid IN usesfile "); |
| 1527 | } |
| 1528 | if( renameOnly ){ |
| 1529 | blob_append_sql(&sql, " AND event.objid IN rnfile "); |
| 1530 | } |
| 1531 | if( forkOnly ){ |
| 1532 | blob_append_sql(&sql, " AND event.objid IN rnfork "); |
| 1533 | } |
| 1534 | if( bisectOnly ){ |
| 1535 | blob_append_sql(&sql, " AND event.objid IN (SELECT rid FROM bilog) "); |
| 1536 | } |
| 1537 | if( zYearMonth ){ |
| 1538 | blob_append_sql(&sql, " AND %Q=strftime('%%Y-%%m',event.mtime) ", |
| 1539 | zYearMonth); |
| 1540 | } |
| 1541 | else if( zYearWeek ){ |
| 1542 | blob_append_sql(&sql, " AND %Q=strftime('%%Y-%%W',event.mtime) ", |
| 1543 | zYearWeek); |
| 1544 | } |
| 1545 | else if( zDay ){ |
| 1546 | blob_append_sql(&sql, " AND %Q=strftime('%%Y-%%m-%%d',event.mtime) ", |
| 1547 | zDay); |
| 1548 | } |
| 1549 | if( tagid ){ |
| 1550 | blob_append_sql(&sql, |
| 1551 | " AND (EXISTS(SELECT 1 FROM tagxref" |
| 1552 | " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)\n", tagid); |
| 1553 | |
| 1554 | if( zBrName ){ |
| 1555 | /* The next two blob_appendf() calls add SQL that causes check-ins that |
| @@ -1556,38 +1558,38 @@ | |
| 1556 | ** are not part of the branch which are parents or children of the |
| 1557 | ** branch to be included in the report. This related check-ins are |
| 1558 | ** useful in helping to visualize what has happened on a quiescent |
| 1559 | ** branch that is infrequently merged with a much more activate branch. |
| 1560 | */ |
| 1561 | blob_append_sql(&sql, |
| 1562 | " OR EXISTS(SELECT 1 FROM plink CROSS JOIN tagxref ON rid=cid" |
| 1563 | " WHERE tagid=%d AND tagtype>0 AND pid=blob.rid)\n", |
| 1564 | tagid |
| 1565 | ); |
| 1566 | if( (tmFlags & TIMELINE_UNHIDE)==0 ){ |
| 1567 | blob_append_sql(&sql, |
| 1568 | " AND NOT EXISTS(SELECT 1 FROM plink JOIN tagxref ON rid=cid" |
| 1569 | " WHERE tagid=%d AND tagtype>0 AND pid=blob.rid)\n", |
| 1570 | TAG_HIDDEN |
| 1571 | ); |
| 1572 | } |
| 1573 | if( P("mionly")==0 ){ |
| 1574 | blob_append_sql(&sql, |
| 1575 | " OR EXISTS(SELECT 1 FROM plink CROSS JOIN tagxref ON rid=pid" |
| 1576 | " WHERE tagid=%d AND tagtype>0 AND cid=blob.rid)\n", |
| 1577 | tagid |
| 1578 | ); |
| 1579 | if( (tmFlags & TIMELINE_UNHIDE)==0 ){ |
| 1580 | blob_append_sql(&sql, |
| 1581 | " AND NOT EXISTS(SELECT 1 FROM plink JOIN tagxref ON rid=pid" |
| 1582 | " WHERE tagid=%d AND tagtype>0 AND cid=blob.rid)\n", |
| 1583 | TAG_HIDDEN |
| 1584 | ); |
| 1585 | } |
| 1586 | } |
| 1587 | } |
| 1588 | blob_append_sql(&sql, ")"); |
| 1589 | } |
| 1590 | if( (zType[0]=='w' && !g.perm.RdWiki) |
| 1591 | || (zType[0]=='t' && !g.perm.RdTkt) |
| 1592 | || (zType[0]=='e' && !g.perm.RdWiki) |
| 1593 | || (zType[0]=='c' && !g.perm.Read) |
| @@ -1596,27 +1598,27 @@ | |
| 1596 | zType = "all"; |
| 1597 | } |
| 1598 | if( zType[0]=='a' ){ |
| 1599 | if( !g.perm.Read || !g.perm.RdWiki || !g.perm.RdTkt ){ |
| 1600 | char cSep = '('; |
| 1601 | blob_append_sql(&sql, " AND event.type IN "); |
| 1602 | if( g.perm.Read ){ |
| 1603 | blob_append_sql(&sql, "%c'ci','g'", cSep); |
| 1604 | cSep = ','; |
| 1605 | } |
| 1606 | if( g.perm.RdWiki ){ |
| 1607 | blob_append_sql(&sql, "%c'w','e'", cSep); |
| 1608 | cSep = ','; |
| 1609 | } |
| 1610 | if( g.perm.RdTkt ){ |
| 1611 | blob_append_sql(&sql, "%c't'", cSep); |
| 1612 | cSep = ','; |
| 1613 | } |
| 1614 | blob_append_sql(&sql, ")"); |
| 1615 | } |
| 1616 | }else{ /* zType!="all" */ |
| 1617 | blob_append_sql(&sql, " AND event.type=%Q", zType); |
| 1618 | if( zType[0]=='c' ){ |
| 1619 | zEType = "check-in"; |
| 1620 | }else if( zType[0]=='w' ){ |
| 1621 | zEType = "wiki edit"; |
| 1622 | }else if( zType[0]=='t' ){ |
| @@ -1632,22 +1634,23 @@ | |
| 1632 | " WHERE user=%Q OR euser=%Q", zUser, zUser); |
| 1633 | if( n<=nEntry ){ |
| 1634 | zCirca = zBefore = zAfter = 0; |
| 1635 | nEntry = -1; |
| 1636 | } |
| 1637 | blob_append_sql(&sql, " AND (event.user=%Q OR event.euser=%Q)", |
| 1638 | zUser, zUser); |
| 1639 | zThisUser = zUser; |
| 1640 | } |
| 1641 | if( zSearch ){ |
| 1642 | blob_append_sql(&sql, |
| 1643 | " AND (event.comment LIKE '%%%q%%' OR event.brief LIKE '%%%q%%')", |
| 1644 | zSearch, zSearch); |
| 1645 | } |
| 1646 | rBefore = symbolic_name_to_mtime(zBefore); |
| 1647 | rAfter = symbolic_name_to_mtime(zAfter); |
| 1648 | rCirca = symbolic_name_to_mtime(zCirca); |
| 1649 | if( rAfter>0.0 ){ |
| 1650 | if( rBefore>0.0 ){ |
| 1651 | blob_append_sql(&sql, |
| 1652 | " AND event.mtime>=%.17g AND event.mtime<=%.17g" |
| 1653 | " ORDER BY event.mtime ASC", rAfter-ONE_SECOND, rBefore+ONE_SECOND); |
| @@ -1745,38 +1748,39 @@ | |
| 1745 | } |
| 1746 | if( zSearch ){ |
| 1747 | blob_appendf(&desc, " matching \"%h\"", zSearch); |
| 1748 | } |
| 1749 | if( g.perm.Hyperlink ){ |
| 1750 | if( zCirca && rCirca ){ |
| 1751 | nBefore = db_int(0, |
| 1752 | "SELECT count(*) FROM timeline WHERE etype!='div'" |
| 1753 | " AND sortby<=%f /*scan*/", rCirca); |
| 1754 | nAfter = db_int(0, |
| 1755 | "SELECT count(*) FROM timeline WHERE etype!='div'" |
| 1756 | " AND sortby>=%f /*scan*/", rCirca); |
| 1757 | zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/"); |
| 1758 | if( nBefore>=nEntry ){ |
| 1759 | timeline_submenu(&url, "Older", "b", zDate, "c"); |
| 1760 | zOlderButton = fossil_strdup(url_render(&url, "b", zDate, "c", 0)); |
| 1761 | } |
| 1762 | if( nAfter>=nEntry ){ |
| 1763 | timeline_submenu(&url, "Newer", "a", zDate, "c"); |
| 1764 | } |
| 1765 | free(zDate); |
| 1766 | }else{ |
| 1767 | if( zAfter || n==nEntry ){ |
| 1768 | zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/"); |
| 1769 | timeline_submenu(&url, "Older", "b", zDate, "a"); |
| 1770 | zOlderButton = fossil_strdup(url_render(&url, "b", zDate, "a", 0)); |
| 1771 | free(zDate); |
| 1772 | } |
| 1773 | if( zBefore || (zAfter && n==nEntry) ){ |
| 1774 | zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/"); |
| 1775 | timeline_submenu(&url, "Newer", "a", zDate, "b"); |
| 1776 | free(zDate); |
| 1777 | } |
| 1778 | } |
| 1779 | if( zType[0]=='a' || zType[0]=='c' ){ |
| 1780 | if( (tmFlags & TIMELINE_UNHIDE)==0 ){ |
| 1781 | timeline_submenu(&url, "Unhide", "unhide", "", 0); |
| 1782 | } |
| @@ -1784,10 +1788,11 @@ | |
| 1784 | style_submenu_entry("n","Max:",4,0); |
| 1785 | timeline_y_submenu(disableY); |
| 1786 | style_submenu_binary("v","With Files","Without Files", |
| 1787 | zType[0]!='a' && zType[0]!='c'); |
| 1788 | } |
| 1789 | } |
| 1790 | if( PB("showsql") ){ |
| 1791 | @ <pre>%h(blob_sql_text(&sql))</pre> |
| 1792 | } |
| 1793 | if( search_restrict(SRCH_CKIN)!=0 ){ |
| 1794 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -1517,39 +1517,41 @@ | |
| 1517 | if( (tmFlags & TIMELINE_UNHIDE)==0 ){ |
| 1518 | timeline_submenu(&url, "Unhide", "unhide", "", 0); |
| 1519 | } |
| 1520 | }else{ |
| 1521 | /* Otherwise, a timeline based on a span of time */ |
| 1522 | int n; |
| 1523 | const char *zEType = "timeline item"; |
| 1524 | char *zDate; |
| 1525 | Blob cond; |
| 1526 | blob_zero(&cond); |
| 1527 | if( zUses ){ |
| 1528 | blob_append_sql(&cond, " AND event.objid IN usesfile "); |
| 1529 | } |
| 1530 | if( renameOnly ){ |
| 1531 | blob_append_sql(&cond, " AND event.objid IN rnfile "); |
| 1532 | } |
| 1533 | if( forkOnly ){ |
| 1534 | blob_append_sql(&cond, " AND event.objid IN rnfork "); |
| 1535 | } |
| 1536 | if( bisectOnly ){ |
| 1537 | blob_append_sql(&cond, " AND event.objid IN (SELECT rid FROM bilog) "); |
| 1538 | } |
| 1539 | if( zYearMonth ){ |
| 1540 | blob_append_sql(&cond, " AND %Q=strftime('%%Y-%%m',event.mtime) ", |
| 1541 | zYearMonth); |
| 1542 | } |
| 1543 | else if( zYearWeek ){ |
| 1544 | blob_append_sql(&cond, " AND %Q=strftime('%%Y-%%W',event.mtime) ", |
| 1545 | zYearWeek); |
| 1546 | } |
| 1547 | else if( zDay ){ |
| 1548 | blob_append_sql(&cond, " AND %Q=strftime('%%Y-%%m-%%d',event.mtime) ", |
| 1549 | zDay); |
| 1550 | } |
| 1551 | if( tagid ){ |
| 1552 | blob_append_sql(&cond, |
| 1553 | " AND (EXISTS(SELECT 1 FROM tagxref" |
| 1554 | " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)\n", tagid); |
| 1555 | |
| 1556 | if( zBrName ){ |
| 1557 | /* The next two blob_appendf() calls add SQL that causes check-ins that |
| @@ -1556,38 +1558,38 @@ | |
| 1558 | ** are not part of the branch which are parents or children of the |
| 1559 | ** branch to be included in the report. This related check-ins are |
| 1560 | ** useful in helping to visualize what has happened on a quiescent |
| 1561 | ** branch that is infrequently merged with a much more activate branch. |
| 1562 | */ |
| 1563 | blob_append_sql(&cond, |
| 1564 | " OR EXISTS(SELECT 1 FROM plink CROSS JOIN tagxref ON rid=cid" |
| 1565 | " WHERE tagid=%d AND tagtype>0 AND pid=blob.rid)\n", |
| 1566 | tagid |
| 1567 | ); |
| 1568 | if( (tmFlags & TIMELINE_UNHIDE)==0 ){ |
| 1569 | blob_append_sql(&cond, |
| 1570 | " AND NOT EXISTS(SELECT 1 FROM plink JOIN tagxref ON rid=cid" |
| 1571 | " WHERE tagid=%d AND tagtype>0 AND pid=blob.rid)\n", |
| 1572 | TAG_HIDDEN |
| 1573 | ); |
| 1574 | } |
| 1575 | if( P("mionly")==0 ){ |
| 1576 | blob_append_sql(&cond, |
| 1577 | " OR EXISTS(SELECT 1 FROM plink CROSS JOIN tagxref ON rid=pid" |
| 1578 | " WHERE tagid=%d AND tagtype>0 AND cid=blob.rid)\n", |
| 1579 | tagid |
| 1580 | ); |
| 1581 | if( (tmFlags & TIMELINE_UNHIDE)==0 ){ |
| 1582 | blob_append_sql(&cond, |
| 1583 | " AND NOT EXISTS(SELECT 1 FROM plink JOIN tagxref ON rid=pid" |
| 1584 | " WHERE tagid=%d AND tagtype>0 AND cid=blob.rid)\n", |
| 1585 | TAG_HIDDEN |
| 1586 | ); |
| 1587 | } |
| 1588 | } |
| 1589 | } |
| 1590 | blob_append_sql(&cond, ")"); |
| 1591 | } |
| 1592 | if( (zType[0]=='w' && !g.perm.RdWiki) |
| 1593 | || (zType[0]=='t' && !g.perm.RdTkt) |
| 1594 | || (zType[0]=='e' && !g.perm.RdWiki) |
| 1595 | || (zType[0]=='c' && !g.perm.Read) |
| @@ -1596,27 +1598,27 @@ | |
| 1598 | zType = "all"; |
| 1599 | } |
| 1600 | if( zType[0]=='a' ){ |
| 1601 | if( !g.perm.Read || !g.perm.RdWiki || !g.perm.RdTkt ){ |
| 1602 | char cSep = '('; |
| 1603 | blob_append_sql(&cond, " AND event.type IN "); |
| 1604 | if( g.perm.Read ){ |
| 1605 | blob_append_sql(&cond, "%c'ci','g'", cSep); |
| 1606 | cSep = ','; |
| 1607 | } |
| 1608 | if( g.perm.RdWiki ){ |
| 1609 | blob_append_sql(&cond, "%c'w','e'", cSep); |
| 1610 | cSep = ','; |
| 1611 | } |
| 1612 | if( g.perm.RdTkt ){ |
| 1613 | blob_append_sql(&cond, "%c't'", cSep); |
| 1614 | cSep = ','; |
| 1615 | } |
| 1616 | blob_append_sql(&cond, ")"); |
| 1617 | } |
| 1618 | }else{ /* zType!="all" */ |
| 1619 | blob_append_sql(&cond, " AND event.type=%Q", zType); |
| 1620 | if( zType[0]=='c' ){ |
| 1621 | zEType = "check-in"; |
| 1622 | }else if( zType[0]=='w' ){ |
| 1623 | zEType = "wiki edit"; |
| 1624 | }else if( zType[0]=='t' ){ |
| @@ -1632,22 +1634,23 @@ | |
| 1634 | " WHERE user=%Q OR euser=%Q", zUser, zUser); |
| 1635 | if( n<=nEntry ){ |
| 1636 | zCirca = zBefore = zAfter = 0; |
| 1637 | nEntry = -1; |
| 1638 | } |
| 1639 | blob_append_sql(&cond, " AND (event.user=%Q OR event.euser=%Q)", |
| 1640 | zUser, zUser); |
| 1641 | zThisUser = zUser; |
| 1642 | } |
| 1643 | if( zSearch ){ |
| 1644 | blob_append_sql(&cond, |
| 1645 | " AND (event.comment LIKE '%%%q%%' OR event.brief LIKE '%%%q%%')", |
| 1646 | zSearch, zSearch); |
| 1647 | } |
| 1648 | rBefore = symbolic_name_to_mtime(zBefore); |
| 1649 | rAfter = symbolic_name_to_mtime(zAfter); |
| 1650 | rCirca = symbolic_name_to_mtime(zCirca); |
| 1651 | blob_append_sql(&sql, "%s", blob_sql_text(&cond)); |
| 1652 | if( rAfter>0.0 ){ |
| 1653 | if( rBefore>0.0 ){ |
| 1654 | blob_append_sql(&sql, |
| 1655 | " AND event.mtime>=%.17g AND event.mtime<=%.17g" |
| 1656 | " ORDER BY event.mtime ASC", rAfter-ONE_SECOND, rBefore+ONE_SECOND); |
| @@ -1745,38 +1748,39 @@ | |
| 1748 | } |
| 1749 | if( zSearch ){ |
| 1750 | blob_appendf(&desc, " matching \"%h\"", zSearch); |
| 1751 | } |
| 1752 | if( g.perm.Hyperlink ){ |
| 1753 | double rDate; |
| 1754 | zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/"); |
| 1755 | if( (!zDate || !zDate[0]) && ( zAfter || zBefore ) ){ |
| 1756 | zDate = mprintf("%s", (zAfter ? zAfter : zBefore)); |
| 1757 | } |
| 1758 | if( zDate ){ |
| 1759 | rDate = symbolic_name_to_mtime(zDate); |
| 1760 | if( db_int(0, |
| 1761 | "SELECT EXISTS (SELECT 1 FROM event WHERE mtime<=%.17g%s)", |
| 1762 | rDate-ONE_SECOND, blob_sql_text(&cond)) |
| 1763 | ){ |
| 1764 | timeline_submenu(&url, "Older", "b", zDate, "a"); |
| 1765 | zOlderButton = fossil_strdup(url_render(&url, "b", zDate, "a", 0)); |
| 1766 | } |
| 1767 | free(zDate); |
| 1768 | } |
| 1769 | zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/"); |
| 1770 | if( (!zDate || !zDate[0]) && ( zAfter || zBefore ) ){ |
| 1771 | zDate = mprintf("%s", (zBefore ? zBefore : zAfter)); |
| 1772 | } |
| 1773 | if( zDate ){ |
| 1774 | rDate = symbolic_name_to_mtime(zDate); |
| 1775 | if( db_int(0, |
| 1776 | "SELECT EXISTS (SELECT 1 FROM event WHERE mtime>=%.17g%s)", |
| 1777 | rDate+ONE_SECOND, blob_sql_text(&cond)) |
| 1778 | ){ |
| 1779 | timeline_submenu(&url, "Newer", "a", zDate, "b"); |
| 1780 | } |
| 1781 | free(zDate); |
| 1782 | } |
| 1783 | if( zType[0]=='a' || zType[0]=='c' ){ |
| 1784 | if( (tmFlags & TIMELINE_UNHIDE)==0 ){ |
| 1785 | timeline_submenu(&url, "Unhide", "unhide", "", 0); |
| 1786 | } |
| @@ -1784,10 +1788,11 @@ | |
| 1788 | style_submenu_entry("n","Max:",4,0); |
| 1789 | timeline_y_submenu(disableY); |
| 1790 | style_submenu_binary("v","With Files","Without Files", |
| 1791 | zType[0]!='a' && zType[0]!='c'); |
| 1792 | } |
| 1793 | blob_zero(&cond); |
| 1794 | } |
| 1795 | if( PB("showsql") ){ |
| 1796 | @ <pre>%h(blob_sql_text(&sql))</pre> |
| 1797 | } |
| 1798 | if( search_restrict(SRCH_CKIN)!=0 ){ |
| 1799 |