Fossil SCM
Improvements to the /fdiff webpage: Add the option of using from= and to= query parameters to get a diff between two files in the same check-in.
Commit
19497648d70fb1bba6ae35a193c77d3f65c5e5c4882f2546e01fdc30bcc17d91
Parent
0d8c3c2bef82eb0…
1 file changed
+43
-15
+43
-15
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -1528,21 +1528,30 @@ | ||
| 1528 | 1528 | } |
| 1529 | 1529 | |
| 1530 | 1530 | |
| 1531 | 1531 | /* |
| 1532 | 1532 | ** WEBPAGE: fdiff |
| 1533 | -** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN®ex=REGEX | |
| 1533 | +** URL: fdiff?v1=UUID&v2=UUID | |
| 1534 | +** | |
| 1535 | +** Two arguments, v1 and v2, identify the artifacts to be diffed. | |
| 1536 | +** Show diff side by side unless sbs is 0. Generate plain text if | |
| 1537 | +** "patch" is present, otherwise generate "pretty" HTML. | |
| 1538 | +** | |
| 1539 | +** Alternative URL: fdiff?from=filename1&to=filename2&ci=checkin | |
| 1534 | 1540 | ** |
| 1535 | -** Two arguments, v1 and v2, identify the files to be diffed. Show the | |
| 1536 | -** difference between the two artifacts. Show diff side by side unless sbs | |
| 1537 | -** is 0. Generate plain text if "patch" is present, otherwise generate | |
| 1538 | -** "pretty" HTML. | |
| 1541 | +** If the "from" and "to" query parameters are both present, then they are | |
| 1542 | +** the names of two files within the check-in "ci" that are diffed. If the | |
| 1543 | +** "ci" parameter is omitted, then the most recent check-in ("tip") is | |
| 1544 | +** used. | |
| 1539 | 1545 | ** |
| 1540 | 1546 | ** Additional parameters: |
| 1541 | 1547 | ** |
| 1542 | -** verbose Show more detail when describing artifacts | |
| 1543 | 1548 | ** dc=N Show N lines of context around each diff |
| 1549 | +** patch Use the patch diff format | |
| 1550 | +** regex=REGEX Only show differences that match REGEX | |
| 1551 | +** sbs=BOOLEAN Turn side-by-side diffs on and off (default: on) | |
| 1552 | +** verbose Show more detail when describing artifacts | |
| 1544 | 1553 | ** w Ignore whitespace |
| 1545 | 1554 | */ |
| 1546 | 1555 | void diff_page(void){ |
| 1547 | 1556 | int v1, v2; |
| 1548 | 1557 | int isPatch; |
| @@ -1555,12 +1564,17 @@ | ||
| 1555 | 1564 | u64 diffFlags; |
| 1556 | 1565 | u32 objdescFlags = 0; |
| 1557 | 1566 | |
| 1558 | 1567 | login_check_credentials(); |
| 1559 | 1568 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1560 | - v1 = name_to_rid_www("v1"); | |
| 1561 | - v2 = name_to_rid_www("v2"); | |
| 1569 | + if( P("from") && P("to") ){ | |
| 1570 | + v1 = artifact_from_ci_and_filename(0, "from"); | |
| 1571 | + v2 = artifact_from_ci_and_filename(0, "to"); | |
| 1572 | + }else{ | |
| 1573 | + v1 = name_to_rid_www("v1"); | |
| 1574 | + v2 = name_to_rid_www("v2"); | |
| 1575 | + } | |
| 1562 | 1576 | if( v1==0 || v2==0 ) fossil_redirect_home(); |
| 1563 | 1577 | zRe = P("regex"); |
| 1564 | 1578 | if( zRe ) re_compile(&pRe, zRe, 0); |
| 1565 | 1579 | if( P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL; |
| 1566 | 1580 | isPatch = P("patch")!=0; |
| @@ -1639,11 +1653,11 @@ | ||
| 1639 | 1653 | char *zUuid; |
| 1640 | 1654 | const char *zMime; |
| 1641 | 1655 | Blob content; |
| 1642 | 1656 | |
| 1643 | 1657 | if( P("ci") && P("filename") ){ |
| 1644 | - rid = artifact_from_ci_and_filename(0); | |
| 1658 | + rid = artifact_from_ci_and_filename(0, 0); | |
| 1645 | 1659 | } |
| 1646 | 1660 | if( rid==0 ){ |
| 1647 | 1661 | rid = name_to_rid_www("name"); |
| 1648 | 1662 | } |
| 1649 | 1663 | login_check_credentials(); |
| @@ -1780,23 +1794,36 @@ | ||
| 1780 | 1794 | ** use them to extract the record ID of an artifact for the file. |
| 1781 | 1795 | ** |
| 1782 | 1796 | ** Also look for "fn" as an alias for "filename". If either "filename" |
| 1783 | 1797 | ** or "fn" is present but "ci" is missing, use "tip" as a default value |
| 1784 | 1798 | ** for "ci". |
| 1799 | +** | |
| 1800 | +** If zNameParam is not NULL, this use that parameter as the filename | |
| 1801 | +** rather than "fn" or "filename". | |
| 1802 | +** | |
| 1803 | +** If pUrl is not NULL, then record the "ci" and "filename" values in | |
| 1804 | +** pUrl. | |
| 1805 | +** | |
| 1806 | +** At least one of pUrl or zNameParam must be NULL. | |
| 1785 | 1807 | */ |
| 1786 | -int artifact_from_ci_and_filename(HQuery *pUrl){ | |
| 1808 | +int artifact_from_ci_and_filename(HQuery *pUrl, const char *zNameParam){ | |
| 1787 | 1809 | const char *zFilename; |
| 1788 | 1810 | const char *zCI; |
| 1789 | 1811 | int cirid; |
| 1790 | 1812 | Manifest *pManifest; |
| 1791 | 1813 | ManifestFile *pFile; |
| 1792 | 1814 | |
| 1793 | - zFilename = P("filename"); | |
| 1794 | - if( zFilename==0 ){ | |
| 1795 | - zFilename = P("fn"); | |
| 1796 | - if( zFilename==0 ) return 0; | |
| 1815 | + if( zNameParam ){ | |
| 1816 | + zFilename = P(zNameParam); | |
| 1817 | + }else{ | |
| 1818 | + zFilename = P("filename"); | |
| 1819 | + if( zFilename==0 ){ | |
| 1820 | + zFilename = P("fn"); | |
| 1821 | + } | |
| 1797 | 1822 | } |
| 1823 | + if( zFilename==0 ) return 0; | |
| 1824 | + | |
| 1798 | 1825 | zCI = P("ci"); |
| 1799 | 1826 | cirid = name_to_typed_rid(zCI ? zCI : "tip", "ci"); |
| 1800 | 1827 | if( cirid<=0 ) return 0; |
| 1801 | 1828 | pManifest = manifest_get(cirid, CFTYPE_MANIFEST, 0); |
| 1802 | 1829 | if( pManifest==0 ) return 0; |
| @@ -1804,10 +1831,11 @@ | ||
| 1804 | 1831 | while( (pFile = manifest_file_next(pManifest,0))!=0 ){ |
| 1805 | 1832 | if( fossil_strcmp(zFilename, pFile->zName)==0 ){ |
| 1806 | 1833 | int rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", pFile->zUuid); |
| 1807 | 1834 | manifest_destroy(pManifest); |
| 1808 | 1835 | if( pUrl ){ |
| 1836 | + assert( zNameParam==0 ); | |
| 1809 | 1837 | url_add_parameter(pUrl, "fn", zFilename); |
| 1810 | 1838 | if( zCI ) url_add_parameter(pUrl, "ci", zCI); |
| 1811 | 1839 | } |
| 1812 | 1840 | return rid; |
| 1813 | 1841 | } |
| @@ -1947,11 +1975,11 @@ | ||
| 1947 | 1975 | const char *zLn = P("ln"); |
| 1948 | 1976 | const char *zName = P("name"); |
| 1949 | 1977 | HQuery url; |
| 1950 | 1978 | |
| 1951 | 1979 | url_initialize(&url, g.zPath); |
| 1952 | - rid = artifact_from_ci_and_filename(&url); | |
| 1980 | + rid = artifact_from_ci_and_filename(&url, 0); | |
| 1953 | 1981 | if( rid==0 ){ |
| 1954 | 1982 | url_add_parameter(&url, "name", zName); |
| 1955 | 1983 | if( isFile ){ |
| 1956 | 1984 | /* Do a top-level directory listing in /file mode if no argument |
| 1957 | 1985 | ** specified */ |
| 1958 | 1986 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -1528,21 +1528,30 @@ | |
| 1528 | } |
| 1529 | |
| 1530 | |
| 1531 | /* |
| 1532 | ** WEBPAGE: fdiff |
| 1533 | ** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN®ex=REGEX |
| 1534 | ** |
| 1535 | ** Two arguments, v1 and v2, identify the files to be diffed. Show the |
| 1536 | ** difference between the two artifacts. Show diff side by side unless sbs |
| 1537 | ** is 0. Generate plain text if "patch" is present, otherwise generate |
| 1538 | ** "pretty" HTML. |
| 1539 | ** |
| 1540 | ** Additional parameters: |
| 1541 | ** |
| 1542 | ** verbose Show more detail when describing artifacts |
| 1543 | ** dc=N Show N lines of context around each diff |
| 1544 | ** w Ignore whitespace |
| 1545 | */ |
| 1546 | void diff_page(void){ |
| 1547 | int v1, v2; |
| 1548 | int isPatch; |
| @@ -1555,12 +1564,17 @@ | |
| 1555 | u64 diffFlags; |
| 1556 | u32 objdescFlags = 0; |
| 1557 | |
| 1558 | login_check_credentials(); |
| 1559 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1560 | v1 = name_to_rid_www("v1"); |
| 1561 | v2 = name_to_rid_www("v2"); |
| 1562 | if( v1==0 || v2==0 ) fossil_redirect_home(); |
| 1563 | zRe = P("regex"); |
| 1564 | if( zRe ) re_compile(&pRe, zRe, 0); |
| 1565 | if( P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL; |
| 1566 | isPatch = P("patch")!=0; |
| @@ -1639,11 +1653,11 @@ | |
| 1639 | char *zUuid; |
| 1640 | const char *zMime; |
| 1641 | Blob content; |
| 1642 | |
| 1643 | if( P("ci") && P("filename") ){ |
| 1644 | rid = artifact_from_ci_and_filename(0); |
| 1645 | } |
| 1646 | if( rid==0 ){ |
| 1647 | rid = name_to_rid_www("name"); |
| 1648 | } |
| 1649 | login_check_credentials(); |
| @@ -1780,23 +1794,36 @@ | |
| 1780 | ** use them to extract the record ID of an artifact for the file. |
| 1781 | ** |
| 1782 | ** Also look for "fn" as an alias for "filename". If either "filename" |
| 1783 | ** or "fn" is present but "ci" is missing, use "tip" as a default value |
| 1784 | ** for "ci". |
| 1785 | */ |
| 1786 | int artifact_from_ci_and_filename(HQuery *pUrl){ |
| 1787 | const char *zFilename; |
| 1788 | const char *zCI; |
| 1789 | int cirid; |
| 1790 | Manifest *pManifest; |
| 1791 | ManifestFile *pFile; |
| 1792 | |
| 1793 | zFilename = P("filename"); |
| 1794 | if( zFilename==0 ){ |
| 1795 | zFilename = P("fn"); |
| 1796 | if( zFilename==0 ) return 0; |
| 1797 | } |
| 1798 | zCI = P("ci"); |
| 1799 | cirid = name_to_typed_rid(zCI ? zCI : "tip", "ci"); |
| 1800 | if( cirid<=0 ) return 0; |
| 1801 | pManifest = manifest_get(cirid, CFTYPE_MANIFEST, 0); |
| 1802 | if( pManifest==0 ) return 0; |
| @@ -1804,10 +1831,11 @@ | |
| 1804 | while( (pFile = manifest_file_next(pManifest,0))!=0 ){ |
| 1805 | if( fossil_strcmp(zFilename, pFile->zName)==0 ){ |
| 1806 | int rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", pFile->zUuid); |
| 1807 | manifest_destroy(pManifest); |
| 1808 | if( pUrl ){ |
| 1809 | url_add_parameter(pUrl, "fn", zFilename); |
| 1810 | if( zCI ) url_add_parameter(pUrl, "ci", zCI); |
| 1811 | } |
| 1812 | return rid; |
| 1813 | } |
| @@ -1947,11 +1975,11 @@ | |
| 1947 | const char *zLn = P("ln"); |
| 1948 | const char *zName = P("name"); |
| 1949 | HQuery url; |
| 1950 | |
| 1951 | url_initialize(&url, g.zPath); |
| 1952 | rid = artifact_from_ci_and_filename(&url); |
| 1953 | if( rid==0 ){ |
| 1954 | url_add_parameter(&url, "name", zName); |
| 1955 | if( isFile ){ |
| 1956 | /* Do a top-level directory listing in /file mode if no argument |
| 1957 | ** specified */ |
| 1958 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -1528,21 +1528,30 @@ | |
| 1528 | } |
| 1529 | |
| 1530 | |
| 1531 | /* |
| 1532 | ** WEBPAGE: fdiff |
| 1533 | ** URL: fdiff?v1=UUID&v2=UUID |
| 1534 | ** |
| 1535 | ** Two arguments, v1 and v2, identify the artifacts to be diffed. |
| 1536 | ** Show diff side by side unless sbs is 0. Generate plain text if |
| 1537 | ** "patch" is present, otherwise generate "pretty" HTML. |
| 1538 | ** |
| 1539 | ** Alternative URL: fdiff?from=filename1&to=filename2&ci=checkin |
| 1540 | ** |
| 1541 | ** If the "from" and "to" query parameters are both present, then they are |
| 1542 | ** the names of two files within the check-in "ci" that are diffed. If the |
| 1543 | ** "ci" parameter is omitted, then the most recent check-in ("tip") is |
| 1544 | ** used. |
| 1545 | ** |
| 1546 | ** Additional parameters: |
| 1547 | ** |
| 1548 | ** dc=N Show N lines of context around each diff |
| 1549 | ** patch Use the patch diff format |
| 1550 | ** regex=REGEX Only show differences that match REGEX |
| 1551 | ** sbs=BOOLEAN Turn side-by-side diffs on and off (default: on) |
| 1552 | ** verbose Show more detail when describing artifacts |
| 1553 | ** w Ignore whitespace |
| 1554 | */ |
| 1555 | void diff_page(void){ |
| 1556 | int v1, v2; |
| 1557 | int isPatch; |
| @@ -1555,12 +1564,17 @@ | |
| 1564 | u64 diffFlags; |
| 1565 | u32 objdescFlags = 0; |
| 1566 | |
| 1567 | login_check_credentials(); |
| 1568 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1569 | if( P("from") && P("to") ){ |
| 1570 | v1 = artifact_from_ci_and_filename(0, "from"); |
| 1571 | v2 = artifact_from_ci_and_filename(0, "to"); |
| 1572 | }else{ |
| 1573 | v1 = name_to_rid_www("v1"); |
| 1574 | v2 = name_to_rid_www("v2"); |
| 1575 | } |
| 1576 | if( v1==0 || v2==0 ) fossil_redirect_home(); |
| 1577 | zRe = P("regex"); |
| 1578 | if( zRe ) re_compile(&pRe, zRe, 0); |
| 1579 | if( P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL; |
| 1580 | isPatch = P("patch")!=0; |
| @@ -1639,11 +1653,11 @@ | |
| 1653 | char *zUuid; |
| 1654 | const char *zMime; |
| 1655 | Blob content; |
| 1656 | |
| 1657 | if( P("ci") && P("filename") ){ |
| 1658 | rid = artifact_from_ci_and_filename(0, 0); |
| 1659 | } |
| 1660 | if( rid==0 ){ |
| 1661 | rid = name_to_rid_www("name"); |
| 1662 | } |
| 1663 | login_check_credentials(); |
| @@ -1780,23 +1794,36 @@ | |
| 1794 | ** use them to extract the record ID of an artifact for the file. |
| 1795 | ** |
| 1796 | ** Also look for "fn" as an alias for "filename". If either "filename" |
| 1797 | ** or "fn" is present but "ci" is missing, use "tip" as a default value |
| 1798 | ** for "ci". |
| 1799 | ** |
| 1800 | ** If zNameParam is not NULL, this use that parameter as the filename |
| 1801 | ** rather than "fn" or "filename". |
| 1802 | ** |
| 1803 | ** If pUrl is not NULL, then record the "ci" and "filename" values in |
| 1804 | ** pUrl. |
| 1805 | ** |
| 1806 | ** At least one of pUrl or zNameParam must be NULL. |
| 1807 | */ |
| 1808 | int artifact_from_ci_and_filename(HQuery *pUrl, const char *zNameParam){ |
| 1809 | const char *zFilename; |
| 1810 | const char *zCI; |
| 1811 | int cirid; |
| 1812 | Manifest *pManifest; |
| 1813 | ManifestFile *pFile; |
| 1814 | |
| 1815 | if( zNameParam ){ |
| 1816 | zFilename = P(zNameParam); |
| 1817 | }else{ |
| 1818 | zFilename = P("filename"); |
| 1819 | if( zFilename==0 ){ |
| 1820 | zFilename = P("fn"); |
| 1821 | } |
| 1822 | } |
| 1823 | if( zFilename==0 ) return 0; |
| 1824 | |
| 1825 | zCI = P("ci"); |
| 1826 | cirid = name_to_typed_rid(zCI ? zCI : "tip", "ci"); |
| 1827 | if( cirid<=0 ) return 0; |
| 1828 | pManifest = manifest_get(cirid, CFTYPE_MANIFEST, 0); |
| 1829 | if( pManifest==0 ) return 0; |
| @@ -1804,10 +1831,11 @@ | |
| 1831 | while( (pFile = manifest_file_next(pManifest,0))!=0 ){ |
| 1832 | if( fossil_strcmp(zFilename, pFile->zName)==0 ){ |
| 1833 | int rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", pFile->zUuid); |
| 1834 | manifest_destroy(pManifest); |
| 1835 | if( pUrl ){ |
| 1836 | assert( zNameParam==0 ); |
| 1837 | url_add_parameter(pUrl, "fn", zFilename); |
| 1838 | if( zCI ) url_add_parameter(pUrl, "ci", zCI); |
| 1839 | } |
| 1840 | return rid; |
| 1841 | } |
| @@ -1947,11 +1975,11 @@ | |
| 1975 | const char *zLn = P("ln"); |
| 1976 | const char *zName = P("name"); |
| 1977 | HQuery url; |
| 1978 | |
| 1979 | url_initialize(&url, g.zPath); |
| 1980 | rid = artifact_from_ci_and_filename(&url, 0); |
| 1981 | if( rid==0 ){ |
| 1982 | url_add_parameter(&url, "name", zName); |
| 1983 | if( isFile ){ |
| 1984 | /* Do a top-level directory listing in /file mode if no argument |
| 1985 | ** specified */ |
| 1986 |