Fossil SCM
Added 'wiki commit'. Minor stylistic cleanups.
Commit
cde6e7a303b0b19621b35b91628b573b6ed75085
Parent
a85cc7ce8de57cd…
1 file changed
+92
-9
+92
-9
| --- src/wiki.c | ||
| +++ src/wiki.c | ||
| @@ -597,22 +597,91 @@ | ||
| 597 | 597 | @ disables all wiki formatting rules through the matching |
| 598 | 598 | @ </nowiki> element. |
| 599 | 599 | @ </ol> |
| 600 | 600 | style_footer(); |
| 601 | 601 | } |
| 602 | + | |
| 603 | +/* | |
| 604 | +** wiki_cmd_commit() is the implementation of "wiki commit ...". | |
| 605 | +** | |
| 606 | +** As arguments it expects: | |
| 607 | +** | |
| 608 | +** zPageName = the wiki entry's name. | |
| 609 | +** | |
| 610 | +** rid = record ID for the zPageName entry. This func SHOULD deduce | |
| 611 | +** this from zPageName, but the code which calls this func already has | |
| 612 | +** the rid, so we pass it along here. If it does not match the entry | |
| 613 | +** for zPageName then Undefined Behaviour. | |
| 614 | +** | |
| 615 | +** in = input file. The file is read until EOF but is not closed | |
| 616 | +** by this function (it might be stdin!). | |
| 617 | +** | |
| 618 | +** Returns 0 on error, non-zero on success. | |
| 619 | +** | |
| 620 | +** TODOs: | |
| 621 | +** - take EITHER zPageName OR rid. We don't need both. | |
| 622 | +** - make use of the return value. Add more error checking. | |
| 623 | +** - give the uuid back to the caller so it can be shown | |
| 624 | +** in the status output. ("committed version XXXXX of page ...") | |
| 625 | +*/ | |
| 626 | +int wiki_cmd_commit( char const * zPageName, int rid, FILE * in ) | |
| 627 | +{ | |
| 628 | + Blob wiki; /* Wiki page content */ | |
| 629 | + Blob content; /* read-in content */ | |
| 630 | + Blob cksum; /* wiki checksum */ | |
| 631 | + int nrid; /* not really sure */ | |
| 632 | + char * zDate; /* timestamp */ | |
| 633 | + char * zUuid; /* uuid for rid */ | |
| 634 | + blob_read_from_channel( &content, in, -1 ); | |
| 635 | + // ^^^ Reminder: we should allow empty (zero-byte) entries, so don't exit | |
| 636 | + // if read returns 0. | |
| 637 | + blob_zero(&wiki); | |
| 638 | + zDate = db_text(0, "SELECT datetime('now')"); | |
| 639 | + zDate[10] = 'T'; | |
| 640 | + blob_appendf(&wiki, "D %s\n", zDate); | |
| 641 | + free(zDate); | |
| 642 | + blob_appendf(&wiki, "L %F\n", zPageName ); | |
| 643 | + zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); | |
| 644 | + blob_appendf(&wiki, "P %s\n", zUuid); | |
| 645 | + free(zUuid); | |
| 646 | + user_select(); | |
| 647 | + if( g.zLogin ){ | |
| 648 | + blob_appendf(&wiki, "U %F\n", g.zLogin); | |
| 649 | + } | |
| 650 | + blob_appendf( &wiki, "W %d\n%s\n", blob_size(&content), | |
| 651 | + blob_buffer(&content) ); | |
| 652 | + blob_reset(&content); | |
| 653 | + md5sum_blob(&wiki, &cksum); | |
| 654 | + blob_appendf(&wiki, "Z %b\n", &cksum); | |
| 655 | + blob_reset(&cksum); | |
| 656 | + db_begin_transaction(); | |
| 657 | + nrid = content_put( &wiki, 0, 0 ); | |
| 658 | + db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid); | |
| 659 | + manifest_crosslink(nrid,&wiki); | |
| 660 | + blob_reset(&wiki); | |
| 661 | + content_deltify(rid,nrid,0); | |
| 662 | + db_end_transaction(0); | |
| 663 | + return 1; | |
| 664 | +} | |
| 602 | 665 | |
| 603 | 666 | /* |
| 604 | 667 | ** COMMAND: wiki |
| 605 | 668 | ** |
| 606 | -** Usage: %fossil wiki (export|delete|commit|list) WikiName | |
| 669 | +** Usage: %fossil wiki (export|commit|list) WikiName | |
| 607 | 670 | ** |
| 608 | 671 | ** Run various subcommands to fetch wiki entries. |
| 609 | 672 | ** |
| 610 | 673 | ** %fossil wiki export WikiName |
| 611 | 674 | ** |
| 612 | 675 | ** Sends the latest version of the WikiName wiki |
| 613 | 676 | ** entry to stdout. |
| 677 | +** | |
| 678 | +** %fossil wiki commit WikiName | |
| 679 | +** | |
| 680 | +** Commit changes to a wiki page from standard input. | |
| 681 | +** It cannot currently create a new entry (this is on the | |
| 682 | +** to-fix list). | |
| 614 | 683 | ** |
| 615 | 684 | ** %fossil wiki list |
| 616 | 685 | ** |
| 617 | 686 | ** Lists all wiki entries, one per line, ordered |
| 618 | 687 | ** case-insentively by name. |
| @@ -636,10 +705,15 @@ | ||
| 636 | 705 | ** %fossil wiki commit ?-f infile[=stdin]? WikiName |
| 637 | 706 | ** |
| 638 | 707 | ** Commit changes to a wiki page from a file or standard input. |
| 639 | 708 | ** It creats a new entry if needed (or is that philosophically |
| 640 | 709 | ** wrong?). |
| 710 | +** | |
| 711 | +** %fossil wiki diff ?UUID? ?-f infile[=stdin]? EntryName | |
| 712 | +** | |
| 713 | +** Diffs the local copy of a page with a given version (defaulting | |
| 714 | +** to the head version). | |
| 641 | 715 | */ |
| 642 | 716 | void wiki_cmd(void){ |
| 643 | 717 | int n; |
| 644 | 718 | db_find_and_open_repository(1); |
| 645 | 719 | if( g.argc<3 ){ |
| @@ -649,24 +723,23 @@ | ||
| 649 | 723 | if( n==0 ){ |
| 650 | 724 | goto wiki_cmd_usage; |
| 651 | 725 | } |
| 652 | 726 | |
| 653 | 727 | if( strncmp(g.argv[2],"export",n)==0 ){ |
| 654 | - char *wname; /* Name of the wiki page to export */ | |
| 728 | + char const *zPageName; /* Name of the wiki page to export */ | |
| 655 | 729 | int rid; /* Artifact ID of the wiki page */ |
| 656 | 730 | int i; /* Loop counter */ |
| 657 | 731 | char *zBody = 0; /* Wiki page content */ |
| 658 | 732 | Manifest m; /* Parsed wiki page content */ |
| 659 | - | |
| 660 | 733 | if( g.argc!=4 ){ |
| 661 | 734 | usage("export PAGENAME"); |
| 662 | 735 | } |
| 663 | - wname = g.argv[3]; | |
| 736 | + zPageName = g.argv[3]; | |
| 664 | 737 | rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x" |
| 665 | 738 | " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'" |
| 666 | 739 | " ORDER BY x.mtime DESC LIMIT 1", |
| 667 | - wname | |
| 740 | + zPageName | |
| 668 | 741 | ); |
| 669 | 742 | if( rid ){ |
| 670 | 743 | Blob content; |
| 671 | 744 | content_get(rid, &content); |
| 672 | 745 | manifest_parse(&m, &content); |
| @@ -673,23 +746,33 @@ | ||
| 673 | 746 | if( m.type==CFTYPE_WIKI ){ |
| 674 | 747 | zBody = m.zWiki; |
| 675 | 748 | } |
| 676 | 749 | } |
| 677 | 750 | if( zBody==0 ){ |
| 678 | - fossil_fatal("wiki page [%s] not found",wname); | |
| 751 | + fossil_fatal("wiki page [%s] not found",zPageName); | |
| 679 | 752 | } |
| 680 | 753 | for(i=strlen(zBody); i>0 && isspace(zBody[i-1]); i--){} |
| 681 | 754 | printf("%.*s\n", i, zBody); |
| 682 | 755 | return; |
| 683 | 756 | }else |
| 684 | 757 | if( strncmp(g.argv[2],"commit",n)==0 ){ |
| 685 | - char *wname; | |
| 758 | + int rid; | |
| 759 | + char *zPageName; | |
| 686 | 760 | if( g.argc!=4 ){ |
| 687 | 761 | usage("commit PAGENAME"); |
| 688 | 762 | } |
| 689 | - wname = g.argv[3]; | |
| 690 | - fossil_fatal("wiki commit not yet implemented."); | |
| 763 | + zPageName = g.argv[3]; | |
| 764 | + rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x" | |
| 765 | + " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'" | |
| 766 | + " ORDER BY x.mtime DESC LIMIT 1", | |
| 767 | + zPageName | |
| 768 | + ); | |
| 769 | + if( ! rid ){ | |
| 770 | + fossil_fatal("wiki commit NewEntry not yet implemented."); | |
| 771 | + } | |
| 772 | + wiki_cmd_commit( zPageName, rid, stdin ); | |
| 773 | + printf("Committed wiki page %s.\n", zPageName); | |
| 691 | 774 | }else |
| 692 | 775 | if( strncmp(g.argv[2],"delete",n)==0 ){ |
| 693 | 776 | if( g.argc!=5 ){ |
| 694 | 777 | usage("delete PAGENAME"); |
| 695 | 778 | } |
| 696 | 779 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -597,22 +597,91 @@ | |
| 597 | @ disables all wiki formatting rules through the matching |
| 598 | @ </nowiki> element. |
| 599 | @ </ol> |
| 600 | style_footer(); |
| 601 | } |
| 602 | |
| 603 | /* |
| 604 | ** COMMAND: wiki |
| 605 | ** |
| 606 | ** Usage: %fossil wiki (export|delete|commit|list) WikiName |
| 607 | ** |
| 608 | ** Run various subcommands to fetch wiki entries. |
| 609 | ** |
| 610 | ** %fossil wiki export WikiName |
| 611 | ** |
| 612 | ** Sends the latest version of the WikiName wiki |
| 613 | ** entry to stdout. |
| 614 | ** |
| 615 | ** %fossil wiki list |
| 616 | ** |
| 617 | ** Lists all wiki entries, one per line, ordered |
| 618 | ** case-insentively by name. |
| @@ -636,10 +705,15 @@ | |
| 636 | ** %fossil wiki commit ?-f infile[=stdin]? WikiName |
| 637 | ** |
| 638 | ** Commit changes to a wiki page from a file or standard input. |
| 639 | ** It creats a new entry if needed (or is that philosophically |
| 640 | ** wrong?). |
| 641 | */ |
| 642 | void wiki_cmd(void){ |
| 643 | int n; |
| 644 | db_find_and_open_repository(1); |
| 645 | if( g.argc<3 ){ |
| @@ -649,24 +723,23 @@ | |
| 649 | if( n==0 ){ |
| 650 | goto wiki_cmd_usage; |
| 651 | } |
| 652 | |
| 653 | if( strncmp(g.argv[2],"export",n)==0 ){ |
| 654 | char *wname; /* Name of the wiki page to export */ |
| 655 | int rid; /* Artifact ID of the wiki page */ |
| 656 | int i; /* Loop counter */ |
| 657 | char *zBody = 0; /* Wiki page content */ |
| 658 | Manifest m; /* Parsed wiki page content */ |
| 659 | |
| 660 | if( g.argc!=4 ){ |
| 661 | usage("export PAGENAME"); |
| 662 | } |
| 663 | wname = g.argv[3]; |
| 664 | rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x" |
| 665 | " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'" |
| 666 | " ORDER BY x.mtime DESC LIMIT 1", |
| 667 | wname |
| 668 | ); |
| 669 | if( rid ){ |
| 670 | Blob content; |
| 671 | content_get(rid, &content); |
| 672 | manifest_parse(&m, &content); |
| @@ -673,23 +746,33 @@ | |
| 673 | if( m.type==CFTYPE_WIKI ){ |
| 674 | zBody = m.zWiki; |
| 675 | } |
| 676 | } |
| 677 | if( zBody==0 ){ |
| 678 | fossil_fatal("wiki page [%s] not found",wname); |
| 679 | } |
| 680 | for(i=strlen(zBody); i>0 && isspace(zBody[i-1]); i--){} |
| 681 | printf("%.*s\n", i, zBody); |
| 682 | return; |
| 683 | }else |
| 684 | if( strncmp(g.argv[2],"commit",n)==0 ){ |
| 685 | char *wname; |
| 686 | if( g.argc!=4 ){ |
| 687 | usage("commit PAGENAME"); |
| 688 | } |
| 689 | wname = g.argv[3]; |
| 690 | fossil_fatal("wiki commit not yet implemented."); |
| 691 | }else |
| 692 | if( strncmp(g.argv[2],"delete",n)==0 ){ |
| 693 | if( g.argc!=5 ){ |
| 694 | usage("delete PAGENAME"); |
| 695 | } |
| 696 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -597,22 +597,91 @@ | |
| 597 | @ disables all wiki formatting rules through the matching |
| 598 | @ </nowiki> element. |
| 599 | @ </ol> |
| 600 | style_footer(); |
| 601 | } |
| 602 | |
| 603 | /* |
| 604 | ** wiki_cmd_commit() is the implementation of "wiki commit ...". |
| 605 | ** |
| 606 | ** As arguments it expects: |
| 607 | ** |
| 608 | ** zPageName = the wiki entry's name. |
| 609 | ** |
| 610 | ** rid = record ID for the zPageName entry. This func SHOULD deduce |
| 611 | ** this from zPageName, but the code which calls this func already has |
| 612 | ** the rid, so we pass it along here. If it does not match the entry |
| 613 | ** for zPageName then Undefined Behaviour. |
| 614 | ** |
| 615 | ** in = input file. The file is read until EOF but is not closed |
| 616 | ** by this function (it might be stdin!). |
| 617 | ** |
| 618 | ** Returns 0 on error, non-zero on success. |
| 619 | ** |
| 620 | ** TODOs: |
| 621 | ** - take EITHER zPageName OR rid. We don't need both. |
| 622 | ** - make use of the return value. Add more error checking. |
| 623 | ** - give the uuid back to the caller so it can be shown |
| 624 | ** in the status output. ("committed version XXXXX of page ...") |
| 625 | */ |
| 626 | int wiki_cmd_commit( char const * zPageName, int rid, FILE * in ) |
| 627 | { |
| 628 | Blob wiki; /* Wiki page content */ |
| 629 | Blob content; /* read-in content */ |
| 630 | Blob cksum; /* wiki checksum */ |
| 631 | int nrid; /* not really sure */ |
| 632 | char * zDate; /* timestamp */ |
| 633 | char * zUuid; /* uuid for rid */ |
| 634 | blob_read_from_channel( &content, in, -1 ); |
| 635 | // ^^^ Reminder: we should allow empty (zero-byte) entries, so don't exit |
| 636 | // if read returns 0. |
| 637 | blob_zero(&wiki); |
| 638 | zDate = db_text(0, "SELECT datetime('now')"); |
| 639 | zDate[10] = 'T'; |
| 640 | blob_appendf(&wiki, "D %s\n", zDate); |
| 641 | free(zDate); |
| 642 | blob_appendf(&wiki, "L %F\n", zPageName ); |
| 643 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 644 | blob_appendf(&wiki, "P %s\n", zUuid); |
| 645 | free(zUuid); |
| 646 | user_select(); |
| 647 | if( g.zLogin ){ |
| 648 | blob_appendf(&wiki, "U %F\n", g.zLogin); |
| 649 | } |
| 650 | blob_appendf( &wiki, "W %d\n%s\n", blob_size(&content), |
| 651 | blob_buffer(&content) ); |
| 652 | blob_reset(&content); |
| 653 | md5sum_blob(&wiki, &cksum); |
| 654 | blob_appendf(&wiki, "Z %b\n", &cksum); |
| 655 | blob_reset(&cksum); |
| 656 | db_begin_transaction(); |
| 657 | nrid = content_put( &wiki, 0, 0 ); |
| 658 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid); |
| 659 | manifest_crosslink(nrid,&wiki); |
| 660 | blob_reset(&wiki); |
| 661 | content_deltify(rid,nrid,0); |
| 662 | db_end_transaction(0); |
| 663 | return 1; |
| 664 | } |
| 665 | |
| 666 | /* |
| 667 | ** COMMAND: wiki |
| 668 | ** |
| 669 | ** Usage: %fossil wiki (export|commit|list) WikiName |
| 670 | ** |
| 671 | ** Run various subcommands to fetch wiki entries. |
| 672 | ** |
| 673 | ** %fossil wiki export WikiName |
| 674 | ** |
| 675 | ** Sends the latest version of the WikiName wiki |
| 676 | ** entry to stdout. |
| 677 | ** |
| 678 | ** %fossil wiki commit WikiName |
| 679 | ** |
| 680 | ** Commit changes to a wiki page from standard input. |
| 681 | ** It cannot currently create a new entry (this is on the |
| 682 | ** to-fix list). |
| 683 | ** |
| 684 | ** %fossil wiki list |
| 685 | ** |
| 686 | ** Lists all wiki entries, one per line, ordered |
| 687 | ** case-insentively by name. |
| @@ -636,10 +705,15 @@ | |
| 705 | ** %fossil wiki commit ?-f infile[=stdin]? WikiName |
| 706 | ** |
| 707 | ** Commit changes to a wiki page from a file or standard input. |
| 708 | ** It creats a new entry if needed (or is that philosophically |
| 709 | ** wrong?). |
| 710 | ** |
| 711 | ** %fossil wiki diff ?UUID? ?-f infile[=stdin]? EntryName |
| 712 | ** |
| 713 | ** Diffs the local copy of a page with a given version (defaulting |
| 714 | ** to the head version). |
| 715 | */ |
| 716 | void wiki_cmd(void){ |
| 717 | int n; |
| 718 | db_find_and_open_repository(1); |
| 719 | if( g.argc<3 ){ |
| @@ -649,24 +723,23 @@ | |
| 723 | if( n==0 ){ |
| 724 | goto wiki_cmd_usage; |
| 725 | } |
| 726 | |
| 727 | if( strncmp(g.argv[2],"export",n)==0 ){ |
| 728 | char const *zPageName; /* Name of the wiki page to export */ |
| 729 | int rid; /* Artifact ID of the wiki page */ |
| 730 | int i; /* Loop counter */ |
| 731 | char *zBody = 0; /* Wiki page content */ |
| 732 | Manifest m; /* Parsed wiki page content */ |
| 733 | if( g.argc!=4 ){ |
| 734 | usage("export PAGENAME"); |
| 735 | } |
| 736 | zPageName = g.argv[3]; |
| 737 | rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x" |
| 738 | " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'" |
| 739 | " ORDER BY x.mtime DESC LIMIT 1", |
| 740 | zPageName |
| 741 | ); |
| 742 | if( rid ){ |
| 743 | Blob content; |
| 744 | content_get(rid, &content); |
| 745 | manifest_parse(&m, &content); |
| @@ -673,23 +746,33 @@ | |
| 746 | if( m.type==CFTYPE_WIKI ){ |
| 747 | zBody = m.zWiki; |
| 748 | } |
| 749 | } |
| 750 | if( zBody==0 ){ |
| 751 | fossil_fatal("wiki page [%s] not found",zPageName); |
| 752 | } |
| 753 | for(i=strlen(zBody); i>0 && isspace(zBody[i-1]); i--){} |
| 754 | printf("%.*s\n", i, zBody); |
| 755 | return; |
| 756 | }else |
| 757 | if( strncmp(g.argv[2],"commit",n)==0 ){ |
| 758 | int rid; |
| 759 | char *zPageName; |
| 760 | if( g.argc!=4 ){ |
| 761 | usage("commit PAGENAME"); |
| 762 | } |
| 763 | zPageName = g.argv[3]; |
| 764 | rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x" |
| 765 | " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'" |
| 766 | " ORDER BY x.mtime DESC LIMIT 1", |
| 767 | zPageName |
| 768 | ); |
| 769 | if( ! rid ){ |
| 770 | fossil_fatal("wiki commit NewEntry not yet implemented."); |
| 771 | } |
| 772 | wiki_cmd_commit( zPageName, rid, stdin ); |
| 773 | printf("Committed wiki page %s.\n", zPageName); |
| 774 | }else |
| 775 | if( strncmp(g.argv[2],"delete",n)==0 ){ |
| 776 | if( g.argc!=5 ){ |
| 777 | usage("delete PAGENAME"); |
| 778 | } |
| 779 |