Fossil SCM
Added -H|-html and -p|-pre flags to [/help?cmd=wiki|wiki command]. Added fossil_fopen_for_output() and fossil_fclose() to support that.
Commit
fe86954ffbf239806fc7c40c19e2bbe7c4b5d8b76b0de0cf35d40b2b33e7aa5a
Parent
b23eb8331488435…
2 files changed
+49
+34
-6
+49
| --- src/file.c | ||
| +++ src/file.c | ||
| @@ -1808,10 +1808,59 @@ | ||
| 1808 | 1808 | #else |
| 1809 | 1809 | FILE *f = fopen(zName, zMode); |
| 1810 | 1810 | #endif |
| 1811 | 1811 | return f; |
| 1812 | 1812 | } |
| 1813 | + | |
| 1814 | +/* | |
| 1815 | +** Works like fclose() except that is a no-op if f is 0 and it | |
| 1816 | +** flushes, but does not close, f if it is one of (stdout, stderr). | |
| 1817 | +*/ | |
| 1818 | +void fossil_fclose(FILE *f){ | |
| 1819 | + | |
| 1820 | + if(f!=0){ | |
| 1821 | + if(stdout==f || stderr==f){ | |
| 1822 | + fflush(f); | |
| 1823 | + }else{ | |
| 1824 | + fclose(f); | |
| 1825 | + } | |
| 1826 | + } | |
| 1827 | +} | |
| 1828 | + | |
| 1829 | +/* | |
| 1830 | +** Works like fopen(zName,"wb") except that: | |
| 1831 | +** | |
| 1832 | +** 1) If zName is "-", the stdout handle is returned. | |
| 1833 | +** | |
| 1834 | +** 2) Else file_mkfolder() is used to create all directories | |
| 1835 | +** which lead up to the file before opening it. | |
| 1836 | +** | |
| 1837 | +** 3) It fails fatally if the file cannot be opened. | |
| 1838 | +*/ | |
| 1839 | +FILE *fossil_fopen_for_output(const char *zFilename){ | |
| 1840 | + if(zFilename[0]=='-' && zFilename[1]==0){ | |
| 1841 | + return stdout; | |
| 1842 | + }else{ | |
| 1843 | + FILE * p; | |
| 1844 | + file_mkfolder(zFilename, ExtFILE, 1, 0); | |
| 1845 | + p = fossil_fopen(zFilename, "wb"); | |
| 1846 | + if( p==0 ){ | |
| 1847 | +#if _WIN32 | |
| 1848 | + const char *zReserved = file_is_win_reserved(zFilename); | |
| 1849 | + if( zReserved ){ | |
| 1850 | + fossil_fatal("cannot open \"%s\" because \"%s\" is " | |
| 1851 | + "a reserved name on Windows", zFilename, | |
| 1852 | + zReserved); | |
| 1853 | + } | |
| 1854 | +#endif | |
| 1855 | + fossil_fatal("unable to open file \"%s\" for writing", | |
| 1856 | + zFilename); | |
| 1857 | + } | |
| 1858 | + return p; | |
| 1859 | + } | |
| 1860 | +} | |
| 1861 | + | |
| 1813 | 1862 | |
| 1814 | 1863 | /* |
| 1815 | 1864 | ** Return non-NULL if zFilename contains pathname elements that |
| 1816 | 1865 | ** are reserved on Windows. The returned string is the disallowed |
| 1817 | 1866 | ** path element. |
| 1818 | 1867 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -1808,10 +1808,59 @@ | |
| 1808 | #else |
| 1809 | FILE *f = fopen(zName, zMode); |
| 1810 | #endif |
| 1811 | return f; |
| 1812 | } |
| 1813 | |
| 1814 | /* |
| 1815 | ** Return non-NULL if zFilename contains pathname elements that |
| 1816 | ** are reserved on Windows. The returned string is the disallowed |
| 1817 | ** path element. |
| 1818 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -1808,10 +1808,59 @@ | |
| 1808 | #else |
| 1809 | FILE *f = fopen(zName, zMode); |
| 1810 | #endif |
| 1811 | return f; |
| 1812 | } |
| 1813 | |
| 1814 | /* |
| 1815 | ** Works like fclose() except that is a no-op if f is 0 and it |
| 1816 | ** flushes, but does not close, f if it is one of (stdout, stderr). |
| 1817 | */ |
| 1818 | void fossil_fclose(FILE *f){ |
| 1819 | |
| 1820 | if(f!=0){ |
| 1821 | if(stdout==f || stderr==f){ |
| 1822 | fflush(f); |
| 1823 | }else{ |
| 1824 | fclose(f); |
| 1825 | } |
| 1826 | } |
| 1827 | } |
| 1828 | |
| 1829 | /* |
| 1830 | ** Works like fopen(zName,"wb") except that: |
| 1831 | ** |
| 1832 | ** 1) If zName is "-", the stdout handle is returned. |
| 1833 | ** |
| 1834 | ** 2) Else file_mkfolder() is used to create all directories |
| 1835 | ** which lead up to the file before opening it. |
| 1836 | ** |
| 1837 | ** 3) It fails fatally if the file cannot be opened. |
| 1838 | */ |
| 1839 | FILE *fossil_fopen_for_output(const char *zFilename){ |
| 1840 | if(zFilename[0]=='-' && zFilename[1]==0){ |
| 1841 | return stdout; |
| 1842 | }else{ |
| 1843 | FILE * p; |
| 1844 | file_mkfolder(zFilename, ExtFILE, 1, 0); |
| 1845 | p = fossil_fopen(zFilename, "wb"); |
| 1846 | if( p==0 ){ |
| 1847 | #if _WIN32 |
| 1848 | const char *zReserved = file_is_win_reserved(zFilename); |
| 1849 | if( zReserved ){ |
| 1850 | fossil_fatal("cannot open \"%s\" because \"%s\" is " |
| 1851 | "a reserved name on Windows", zFilename, |
| 1852 | zReserved); |
| 1853 | } |
| 1854 | #endif |
| 1855 | fossil_fatal("unable to open file \"%s\" for writing", |
| 1856 | zFilename); |
| 1857 | } |
| 1858 | return p; |
| 1859 | } |
| 1860 | } |
| 1861 | |
| 1862 | |
| 1863 | /* |
| 1864 | ** Return non-NULL if zFilename contains pathname elements that |
| 1865 | ** are reserved on Windows. The returned string is the disallowed |
| 1866 | ** path element. |
| 1867 |
+34
-6
| --- src/wiki.c | ||
| +++ src/wiki.c | ||
| @@ -1364,15 +1364,17 @@ | ||
| 1364 | 1364 | ** |
| 1365 | 1365 | ** Usage: %fossil wiki (export|create|commit|list) WikiName |
| 1366 | 1366 | ** |
| 1367 | 1367 | ** Run various subcommands to work with wiki entries or tech notes. |
| 1368 | 1368 | ** |
| 1369 | -** %fossil wiki export ?OPTIONS? ?PAGENAME? ?FILE? | |
| 1369 | +** %fossil wiki export ?OPTIONS? PAGENAME ?FILE? | |
| 1370 | 1370 | ** %fossil wiki export ?OPTIONS? -t|--technote DATETIME|TECHNOTE-ID ?FILE? |
| 1371 | 1371 | ** |
| 1372 | -** Sends the latest version of either a wiki page or of a tech note | |
| 1373 | -** to the given file or standard output. | |
| 1372 | +** Sends the latest version of either a wiki page or of a tech | |
| 1373 | +** note to the given file or standard output. A filename of "-" | |
| 1374 | +** writes the output to standard output. The directory parts of | |
| 1375 | +** the output filename are created if needed. | |
| 1374 | 1376 | ** |
| 1375 | 1377 | ** Options: |
| 1376 | 1378 | ** If PAGENAME is provided, the named wiki page will be output. |
| 1377 | 1379 | ** --technote|-t DATETIME|TECHNOTE-ID |
| 1378 | 1380 | ** Specifies that a technote, rather than a wiki page, |
| @@ -1379,10 +1381,15 @@ | ||
| 1379 | 1381 | ** will be exported. If DATETIME is used, the most |
| 1380 | 1382 | ** recently modified tech note with that DATETIME will |
| 1381 | 1383 | ** output. |
| 1382 | 1384 | ** -h|--html The body (only) is rendered in HTML form, without |
| 1383 | 1385 | ** any page header/foot or HTML/BODY tag wrappers. |
| 1386 | +** -H|--HTML Works like -h|-html but wraps the output in | |
| 1387 | +** <html><body>...</body></html>. | |
| 1388 | +** -p|--pre If -h|-H is used and the page or technote has | |
| 1389 | +** the text/plain mimetype, its HTML-escaped output | |
| 1390 | +** will be wrapped in <pre>...</pre>. | |
| 1384 | 1391 | ** |
| 1385 | 1392 | ** %fossil wiki (create|commit) PAGENAME ?FILE? ?OPTIONS? |
| 1386 | 1393 | ** |
| 1387 | 1394 | ** Create a new or commit changes to an existing wiki page or |
| 1388 | 1395 | ** technote from FILE or from standard input. PAGENAME is the |
| @@ -1453,12 +1460,19 @@ | ||
| 1453 | 1460 | int i; /* Loop counter */ |
| 1454 | 1461 | char *zBody = 0; /* Wiki page content */ |
| 1455 | 1462 | Blob body = empty_blob; /* Wiki page content */ |
| 1456 | 1463 | Manifest *pWiki = 0; /* Parsed wiki page content */ |
| 1457 | 1464 | int fHtml = 0; /* Export in HTML form */ |
| 1458 | - | |
| 1459 | - fHtml = find_option("html","h",0)!=0; | |
| 1465 | + FILE * pFile = 0; /* Output file */ | |
| 1466 | + int fPre = 0; /* Indicates that -h|-H should be | |
| 1467 | + ** wrapped in <pre>...</pre> if pWiki | |
| 1468 | + ** has the text/plain mimetype. */ | |
| 1469 | + fHtml = find_option("HTML","H",0)!=0 | |
| 1470 | + ? 2 | |
| 1471 | + : (find_option("html","h",0)!=0 ? 1 : 0) | |
| 1472 | + /* 1 == -html, 2 == -HTML */; | |
| 1473 | + fPre = fHtml==0 ? 0 : find_option("pre","p",0)!=0; | |
| 1460 | 1474 | zETime = find_option("technote","t",1); |
| 1461 | 1475 | verify_all_options(); |
| 1462 | 1476 | if( !zETime ){ |
| 1463 | 1477 | if( (g.argc!=4) && (g.argc!=5) ){ |
| 1464 | 1478 | usage("export ?-html? PAGENAME ?FILE?"); |
| @@ -1520,11 +1534,25 @@ | ||
| 1520 | 1534 | zMimetype, pWiki->zWikiTitle ); |
| 1521 | 1535 | } |
| 1522 | 1536 | blob_reset(&body); |
| 1523 | 1537 | body = html /* transfer memory */; |
| 1524 | 1538 | } |
| 1525 | - blob_write_to_file(&body, zFile); | |
| 1539 | + pFile = fossil_fopen_for_output(zFile); | |
| 1540 | + if(fHtml==2){ | |
| 1541 | + fwrite("<html><body>", 1, 12, pFile); | |
| 1542 | + } | |
| 1543 | + if(fPre!=0){ | |
| 1544 | + fwrite("<pre>", 1, 5, pFile); | |
| 1545 | + } | |
| 1546 | + fwrite(blob_buffer(&body), 1, blob_size(&body), pFile); | |
| 1547 | + if(fPre!=0){ | |
| 1548 | + fwrite("</pre>", 1, 6, pFile); | |
| 1549 | + } | |
| 1550 | + if(fHtml==2){ | |
| 1551 | + fwrite("</body></html>\n", 1, 15, pFile); | |
| 1552 | + } | |
| 1553 | + fossil_fclose(pFile); | |
| 1526 | 1554 | blob_reset(&body); |
| 1527 | 1555 | manifest_destroy(pWiki); |
| 1528 | 1556 | return; |
| 1529 | 1557 | }else if( strncmp(g.argv[2],"commit",n)==0 |
| 1530 | 1558 | || strncmp(g.argv[2],"create",n)==0 ){ |
| 1531 | 1559 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -1364,15 +1364,17 @@ | |
| 1364 | ** |
| 1365 | ** Usage: %fossil wiki (export|create|commit|list) WikiName |
| 1366 | ** |
| 1367 | ** Run various subcommands to work with wiki entries or tech notes. |
| 1368 | ** |
| 1369 | ** %fossil wiki export ?OPTIONS? ?PAGENAME? ?FILE? |
| 1370 | ** %fossil wiki export ?OPTIONS? -t|--technote DATETIME|TECHNOTE-ID ?FILE? |
| 1371 | ** |
| 1372 | ** Sends the latest version of either a wiki page or of a tech note |
| 1373 | ** to the given file or standard output. |
| 1374 | ** |
| 1375 | ** Options: |
| 1376 | ** If PAGENAME is provided, the named wiki page will be output. |
| 1377 | ** --technote|-t DATETIME|TECHNOTE-ID |
| 1378 | ** Specifies that a technote, rather than a wiki page, |
| @@ -1379,10 +1381,15 @@ | |
| 1379 | ** will be exported. If DATETIME is used, the most |
| 1380 | ** recently modified tech note with that DATETIME will |
| 1381 | ** output. |
| 1382 | ** -h|--html The body (only) is rendered in HTML form, without |
| 1383 | ** any page header/foot or HTML/BODY tag wrappers. |
| 1384 | ** |
| 1385 | ** %fossil wiki (create|commit) PAGENAME ?FILE? ?OPTIONS? |
| 1386 | ** |
| 1387 | ** Create a new or commit changes to an existing wiki page or |
| 1388 | ** technote from FILE or from standard input. PAGENAME is the |
| @@ -1453,12 +1460,19 @@ | |
| 1453 | int i; /* Loop counter */ |
| 1454 | char *zBody = 0; /* Wiki page content */ |
| 1455 | Blob body = empty_blob; /* Wiki page content */ |
| 1456 | Manifest *pWiki = 0; /* Parsed wiki page content */ |
| 1457 | int fHtml = 0; /* Export in HTML form */ |
| 1458 | |
| 1459 | fHtml = find_option("html","h",0)!=0; |
| 1460 | zETime = find_option("technote","t",1); |
| 1461 | verify_all_options(); |
| 1462 | if( !zETime ){ |
| 1463 | if( (g.argc!=4) && (g.argc!=5) ){ |
| 1464 | usage("export ?-html? PAGENAME ?FILE?"); |
| @@ -1520,11 +1534,25 @@ | |
| 1520 | zMimetype, pWiki->zWikiTitle ); |
| 1521 | } |
| 1522 | blob_reset(&body); |
| 1523 | body = html /* transfer memory */; |
| 1524 | } |
| 1525 | blob_write_to_file(&body, zFile); |
| 1526 | blob_reset(&body); |
| 1527 | manifest_destroy(pWiki); |
| 1528 | return; |
| 1529 | }else if( strncmp(g.argv[2],"commit",n)==0 |
| 1530 | || strncmp(g.argv[2],"create",n)==0 ){ |
| 1531 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -1364,15 +1364,17 @@ | |
| 1364 | ** |
| 1365 | ** Usage: %fossil wiki (export|create|commit|list) WikiName |
| 1366 | ** |
| 1367 | ** Run various subcommands to work with wiki entries or tech notes. |
| 1368 | ** |
| 1369 | ** %fossil wiki export ?OPTIONS? PAGENAME ?FILE? |
| 1370 | ** %fossil wiki export ?OPTIONS? -t|--technote DATETIME|TECHNOTE-ID ?FILE? |
| 1371 | ** |
| 1372 | ** Sends the latest version of either a wiki page or of a tech |
| 1373 | ** note to the given file or standard output. A filename of "-" |
| 1374 | ** writes the output to standard output. The directory parts of |
| 1375 | ** the output filename are created if needed. |
| 1376 | ** |
| 1377 | ** Options: |
| 1378 | ** If PAGENAME is provided, the named wiki page will be output. |
| 1379 | ** --technote|-t DATETIME|TECHNOTE-ID |
| 1380 | ** Specifies that a technote, rather than a wiki page, |
| @@ -1379,10 +1381,15 @@ | |
| 1381 | ** will be exported. If DATETIME is used, the most |
| 1382 | ** recently modified tech note with that DATETIME will |
| 1383 | ** output. |
| 1384 | ** -h|--html The body (only) is rendered in HTML form, without |
| 1385 | ** any page header/foot or HTML/BODY tag wrappers. |
| 1386 | ** -H|--HTML Works like -h|-html but wraps the output in |
| 1387 | ** <html><body>...</body></html>. |
| 1388 | ** -p|--pre If -h|-H is used and the page or technote has |
| 1389 | ** the text/plain mimetype, its HTML-escaped output |
| 1390 | ** will be wrapped in <pre>...</pre>. |
| 1391 | ** |
| 1392 | ** %fossil wiki (create|commit) PAGENAME ?FILE? ?OPTIONS? |
| 1393 | ** |
| 1394 | ** Create a new or commit changes to an existing wiki page or |
| 1395 | ** technote from FILE or from standard input. PAGENAME is the |
| @@ -1453,12 +1460,19 @@ | |
| 1460 | int i; /* Loop counter */ |
| 1461 | char *zBody = 0; /* Wiki page content */ |
| 1462 | Blob body = empty_blob; /* Wiki page content */ |
| 1463 | Manifest *pWiki = 0; /* Parsed wiki page content */ |
| 1464 | int fHtml = 0; /* Export in HTML form */ |
| 1465 | FILE * pFile = 0; /* Output file */ |
| 1466 | int fPre = 0; /* Indicates that -h|-H should be |
| 1467 | ** wrapped in <pre>...</pre> if pWiki |
| 1468 | ** has the text/plain mimetype. */ |
| 1469 | fHtml = find_option("HTML","H",0)!=0 |
| 1470 | ? 2 |
| 1471 | : (find_option("html","h",0)!=0 ? 1 : 0) |
| 1472 | /* 1 == -html, 2 == -HTML */; |
| 1473 | fPre = fHtml==0 ? 0 : find_option("pre","p",0)!=0; |
| 1474 | zETime = find_option("technote","t",1); |
| 1475 | verify_all_options(); |
| 1476 | if( !zETime ){ |
| 1477 | if( (g.argc!=4) && (g.argc!=5) ){ |
| 1478 | usage("export ?-html? PAGENAME ?FILE?"); |
| @@ -1520,11 +1534,25 @@ | |
| 1534 | zMimetype, pWiki->zWikiTitle ); |
| 1535 | } |
| 1536 | blob_reset(&body); |
| 1537 | body = html /* transfer memory */; |
| 1538 | } |
| 1539 | pFile = fossil_fopen_for_output(zFile); |
| 1540 | if(fHtml==2){ |
| 1541 | fwrite("<html><body>", 1, 12, pFile); |
| 1542 | } |
| 1543 | if(fPre!=0){ |
| 1544 | fwrite("<pre>", 1, 5, pFile); |
| 1545 | } |
| 1546 | fwrite(blob_buffer(&body), 1, blob_size(&body), pFile); |
| 1547 | if(fPre!=0){ |
| 1548 | fwrite("</pre>", 1, 6, pFile); |
| 1549 | } |
| 1550 | if(fHtml==2){ |
| 1551 | fwrite("</body></html>\n", 1, 15, pFile); |
| 1552 | } |
| 1553 | fossil_fclose(pFile); |
| 1554 | blob_reset(&body); |
| 1555 | manifest_destroy(pWiki); |
| 1556 | return; |
| 1557 | }else if( strncmp(g.argv[2],"commit",n)==0 |
| 1558 | || strncmp(g.argv[2],"create",n)==0 ){ |
| 1559 |