Fossil SCM
Cleanup and simplify the code for the recently added "wiki" command.
Commit
decac09b7d246ca64cd916121ba74fe8d3b5327e
Parent
feee32d3af2760a…
1 file changed
+33
-101
+33
-101
| --- src/wiki.c | ||
| +++ src/wiki.c | ||
| @@ -598,15 +598,10 @@ | ||
| 598 | 598 | @ </nowiki> element. |
| 599 | 599 | @ </ol> |
| 600 | 600 | style_footer(); |
| 601 | 601 | } |
| 602 | 602 | |
| 603 | -void dump_blob_to_FILE( Blob * b, FILE * f ) | |
| 604 | -{ | |
| 605 | - fwrite(blob_buffer(b), 1, blob_size(b), stdout); | |
| 606 | -} | |
| 607 | - | |
| 608 | 603 | /* |
| 609 | 604 | ** COMMAND: wiki |
| 610 | 605 | ** |
| 611 | 606 | ** Usage: %fossil wiki (export|commit|list) WikiName |
| 612 | 607 | ** |
| @@ -637,132 +632,69 @@ | ||
| 637 | 632 | if( n==0 ){ |
| 638 | 633 | goto wiki_cmd_usage; |
| 639 | 634 | } |
| 640 | 635 | |
| 641 | 636 | if( strncmp(g.argv[2],"export",n)==0 ){ |
| 642 | - Stmt q; | |
| 643 | - char *wname; | |
| 644 | - Blob buf; | |
| 645 | - int rid; | |
| 646 | - char * sql; | |
| 637 | + char *wname; /* Name of the wiki page to export */ | |
| 638 | + int rid; /* Artifact ID of the wiki page */ | |
| 639 | + int i; /* Loop counter */ | |
| 640 | + char *zBody = 0; /* Wiki page content */ | |
| 641 | + Manifest m; /* Parsed wiki page content */ | |
| 642 | + | |
| 647 | 643 | if( g.argc!=4 ){ |
| 648 | - usage("export EntryName"); | |
| 644 | + usage("export PAGENAME"); | |
| 649 | 645 | } |
| 650 | 646 | wname = g.argv[3]; |
| 651 | - rid = -1; | |
| 652 | - sql = mprintf("SELECT x.rid FROM tag t, tagxref x" | |
| 647 | + rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x" | |
| 653 | 648 | " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'" |
| 654 | 649 | " ORDER BY x.mtime DESC LIMIT 1", |
| 655 | - wname ); | |
| 656 | - db_prepare(&q, "%z", sql ); | |
| 657 | - if( db_step(&q) == SQLITE_ROW ){ | |
| 658 | - rid = db_column_int(&q,0); | |
| 659 | - } | |
| 660 | - db_finalize(&q); | |
| 661 | - if( -1 == rid ){ | |
| 662 | - fprintf(stderr,"export error: wiki entry [%s] not found.\n",wname); | |
| 663 | - exit(1); | |
| 664 | - } | |
| 665 | - if( ! content_get(rid,&buf) ){ | |
| 666 | - fprintf(stderr,"export error: content_get(%d) returned 0\n", rid ); | |
| 667 | - exit(1); | |
| 668 | - }else | |
| 669 | - { | |
| 670 | - /* Unfortunately, the content_get() routine does ALMOST what i want, | |
| 671 | - but not quite. It is quite complex, so i don't want to fork a | |
| 672 | - modified copy here. That's what all the skipping-over bits are for... | |
| 673 | - | |
| 674 | - We look for the first line starting with 'W', then expect ' | |
| 675 | - NUMBER\n' immediately after that, followed by NUMBER bytes | |
| 676 | - of plain blob content. | |
| 677 | - */ | |
| 678 | - int len; | |
| 679 | - char * it; | |
| 680 | - Blob numbuf; | |
| 681 | - blob_zero(&numbuf); | |
| 682 | - it = blob_buffer(&buf); | |
| 683 | - while(*it){ | |
| 684 | - if( *it != 'W' ){ | |
| 685 | - ++it; | |
| 686 | - while( *it ){ | |
| 687 | - if( *it == '\n') { ++it; break; } | |
| 688 | - ++it; | |
| 689 | - } | |
| 690 | - continue; | |
| 691 | - } | |
| 692 | - if( ! *it ) | |
| 693 | - { | |
| 694 | - fprintf(stderr, | |
| 695 | - "export reached end of input before finding a 'W' card.\n"); | |
| 696 | - exit(1); | |
| 697 | - } | |
| 698 | - ++it; | |
| 699 | - while( (*it) && (*it != '\n') ){ | |
| 700 | - if( isspace(*it) ) { ++it; continue; } | |
| 701 | - blob_append(&numbuf,it,1); | |
| 702 | - ++it; | |
| 703 | - } | |
| 704 | - if( '\n' == *it ) ++it; | |
| 705 | - if( 0 == blob_size(&numbuf) ){ | |
| 706 | - fprintf(stderr, | |
| 707 | - "export error: didn't find \"W NUMBER\" line in input!\n"); | |
| 708 | - blob_reset(&buf); | |
| 709 | - blob_reset(&numbuf); | |
| 710 | - exit(1); | |
| 711 | - } | |
| 712 | - len = atoi(blob_buffer(&numbuf)); | |
| 713 | - //fprintf(stderr,"Writing %s (%d) bytes...\n",blob_buffer(&numbuf),len); | |
| 714 | - blob_reset(&numbuf); | |
| 715 | - if( ( (it - blob_buffer(&buf)) + len) > blob_size(&buf) ){ | |
| 716 | - fprintf(stderr, | |
| 717 | - "export error: manifest data doesn't match actual data size!" | |
| 718 | - " Manifest says [%s (%d)] bytes.\n", | |
| 719 | - blob_buffer(&numbuf), len ); | |
| 720 | - blob_reset(&buf); | |
| 721 | - blob_reset(&numbuf); | |
| 722 | - exit(1); | |
| 723 | - } | |
| 724 | - fwrite(it,sizeof(char),len,stdout); | |
| 725 | - blob_reset(&buf); | |
| 726 | - return; | |
| 727 | - } | |
| 728 | - } | |
| 729 | - blob_reset(&buf); | |
| 650 | + wname | |
| 651 | + ); | |
| 652 | + if( rid ){ | |
| 653 | + Blob content; | |
| 654 | + content_get(rid, &content); | |
| 655 | + manifest_parse(&m, &content); | |
| 656 | + if( m.type==CFTYPE_WIKI ){ | |
| 657 | + zBody = m.zWiki; | |
| 658 | + } | |
| 659 | + } | |
| 660 | + if( zBody==0 ){ | |
| 661 | + fossil_fatal("wiki page [%s] not found",wname); | |
| 662 | + } | |
| 663 | + for(i=strlen(zBody); i>0 && isspace(zBody[i-1]); i--){} | |
| 664 | + printf("%.*s\n", i, zBody); | |
| 730 | 665 | return; |
| 731 | 666 | }else |
| 732 | 667 | if( strncmp(g.argv[2],"commit",n)==0 ){ |
| 733 | 668 | char *wname; |
| 734 | 669 | if( g.argc!=4 ){ |
| 735 | - usage("commit EntryName"); | |
| 670 | + usage("commit PAGENAME"); | |
| 736 | 671 | } |
| 737 | 672 | wname = g.argv[3]; |
| 738 | - fprintf(stderr,"commit not yet implemented.\n"); | |
| 739 | - exit(1); | |
| 673 | + fossil_fatal("wiki commit not yet implemented."); | |
| 740 | 674 | }else |
| 741 | 675 | if( strncmp(g.argv[2],"delete",n)==0 ){ |
| 742 | 676 | if( g.argc!=5 ){ |
| 743 | - usage("delete WikiName"); | |
| 677 | + usage("delete PAGENAME"); | |
| 744 | 678 | } |
| 745 | - fprintf(stderr,"delete not yet implemented.\n"); | |
| 746 | - exit(1); | |
| 679 | + fossil_fatal("delete not yet implemented."); | |
| 747 | 680 | }else |
| 748 | 681 | if( strncmp(g.argv[2],"list",n)==0 ){ |
| 749 | 682 | Stmt q; |
| 750 | 683 | db_prepare(&q, |
| 751 | - "SELECT substr(tagname, 6, 1000) FROM tag WHERE tagname GLOB 'wiki-*'" | |
| 752 | - " ORDER BY lower(tagname)" | |
| 753 | - ); | |
| 684 | + "SELECT substr(tagname, 6) FROM tag WHERE tagname GLOB 'wiki-*'" | |
| 685 | + " ORDER BY lower(tagname)" | |
| 686 | + ); | |
| 754 | 687 | while( db_step(&q)==SQLITE_ROW ){ |
| 755 | - const char *zName = db_column_text(&q, 0); | |
| 756 | - printf( "%s\n",zName); | |
| 688 | + const char *zName = db_column_text(&q, 0); | |
| 689 | + printf( "%s\n",zName); | |
| 757 | 690 | } |
| 758 | 691 | db_finalize(&q); |
| 759 | 692 | }else |
| 760 | 693 | { |
| 761 | 694 | goto wiki_cmd_usage; |
| 762 | 695 | } |
| 763 | 696 | return; |
| 764 | 697 | |
| 765 | 698 | wiki_cmd_usage: |
| 766 | - usage("delete|export|commit|list [EntryName]"); | |
| 699 | + usage("delete|export|commit|list ..."); | |
| 767 | 700 | } |
| 768 | - | |
| 769 | 701 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -598,15 +598,10 @@ | |
| 598 | @ </nowiki> element. |
| 599 | @ </ol> |
| 600 | style_footer(); |
| 601 | } |
| 602 | |
| 603 | void dump_blob_to_FILE( Blob * b, FILE * f ) |
| 604 | { |
| 605 | fwrite(blob_buffer(b), 1, blob_size(b), stdout); |
| 606 | } |
| 607 | |
| 608 | /* |
| 609 | ** COMMAND: wiki |
| 610 | ** |
| 611 | ** Usage: %fossil wiki (export|commit|list) WikiName |
| 612 | ** |
| @@ -637,132 +632,69 @@ | |
| 637 | if( n==0 ){ |
| 638 | goto wiki_cmd_usage; |
| 639 | } |
| 640 | |
| 641 | if( strncmp(g.argv[2],"export",n)==0 ){ |
| 642 | Stmt q; |
| 643 | char *wname; |
| 644 | Blob buf; |
| 645 | int rid; |
| 646 | char * sql; |
| 647 | if( g.argc!=4 ){ |
| 648 | usage("export EntryName"); |
| 649 | } |
| 650 | wname = g.argv[3]; |
| 651 | rid = -1; |
| 652 | sql = mprintf("SELECT x.rid FROM tag t, tagxref x" |
| 653 | " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'" |
| 654 | " ORDER BY x.mtime DESC LIMIT 1", |
| 655 | wname ); |
| 656 | db_prepare(&q, "%z", sql ); |
| 657 | if( db_step(&q) == SQLITE_ROW ){ |
| 658 | rid = db_column_int(&q,0); |
| 659 | } |
| 660 | db_finalize(&q); |
| 661 | if( -1 == rid ){ |
| 662 | fprintf(stderr,"export error: wiki entry [%s] not found.\n",wname); |
| 663 | exit(1); |
| 664 | } |
| 665 | if( ! content_get(rid,&buf) ){ |
| 666 | fprintf(stderr,"export error: content_get(%d) returned 0\n", rid ); |
| 667 | exit(1); |
| 668 | }else |
| 669 | { |
| 670 | /* Unfortunately, the content_get() routine does ALMOST what i want, |
| 671 | but not quite. It is quite complex, so i don't want to fork a |
| 672 | modified copy here. That's what all the skipping-over bits are for... |
| 673 | |
| 674 | We look for the first line starting with 'W', then expect ' |
| 675 | NUMBER\n' immediately after that, followed by NUMBER bytes |
| 676 | of plain blob content. |
| 677 | */ |
| 678 | int len; |
| 679 | char * it; |
| 680 | Blob numbuf; |
| 681 | blob_zero(&numbuf); |
| 682 | it = blob_buffer(&buf); |
| 683 | while(*it){ |
| 684 | if( *it != 'W' ){ |
| 685 | ++it; |
| 686 | while( *it ){ |
| 687 | if( *it == '\n') { ++it; break; } |
| 688 | ++it; |
| 689 | } |
| 690 | continue; |
| 691 | } |
| 692 | if( ! *it ) |
| 693 | { |
| 694 | fprintf(stderr, |
| 695 | "export reached end of input before finding a 'W' card.\n"); |
| 696 | exit(1); |
| 697 | } |
| 698 | ++it; |
| 699 | while( (*it) && (*it != '\n') ){ |
| 700 | if( isspace(*it) ) { ++it; continue; } |
| 701 | blob_append(&numbuf,it,1); |
| 702 | ++it; |
| 703 | } |
| 704 | if( '\n' == *it ) ++it; |
| 705 | if( 0 == blob_size(&numbuf) ){ |
| 706 | fprintf(stderr, |
| 707 | "export error: didn't find \"W NUMBER\" line in input!\n"); |
| 708 | blob_reset(&buf); |
| 709 | blob_reset(&numbuf); |
| 710 | exit(1); |
| 711 | } |
| 712 | len = atoi(blob_buffer(&numbuf)); |
| 713 | //fprintf(stderr,"Writing %s (%d) bytes...\n",blob_buffer(&numbuf),len); |
| 714 | blob_reset(&numbuf); |
| 715 | if( ( (it - blob_buffer(&buf)) + len) > blob_size(&buf) ){ |
| 716 | fprintf(stderr, |
| 717 | "export error: manifest data doesn't match actual data size!" |
| 718 | " Manifest says [%s (%d)] bytes.\n", |
| 719 | blob_buffer(&numbuf), len ); |
| 720 | blob_reset(&buf); |
| 721 | blob_reset(&numbuf); |
| 722 | exit(1); |
| 723 | } |
| 724 | fwrite(it,sizeof(char),len,stdout); |
| 725 | blob_reset(&buf); |
| 726 | return; |
| 727 | } |
| 728 | } |
| 729 | blob_reset(&buf); |
| 730 | return; |
| 731 | }else |
| 732 | if( strncmp(g.argv[2],"commit",n)==0 ){ |
| 733 | char *wname; |
| 734 | if( g.argc!=4 ){ |
| 735 | usage("commit EntryName"); |
| 736 | } |
| 737 | wname = g.argv[3]; |
| 738 | fprintf(stderr,"commit not yet implemented.\n"); |
| 739 | exit(1); |
| 740 | }else |
| 741 | if( strncmp(g.argv[2],"delete",n)==0 ){ |
| 742 | if( g.argc!=5 ){ |
| 743 | usage("delete WikiName"); |
| 744 | } |
| 745 | fprintf(stderr,"delete not yet implemented.\n"); |
| 746 | exit(1); |
| 747 | }else |
| 748 | if( strncmp(g.argv[2],"list",n)==0 ){ |
| 749 | Stmt q; |
| 750 | db_prepare(&q, |
| 751 | "SELECT substr(tagname, 6, 1000) FROM tag WHERE tagname GLOB 'wiki-*'" |
| 752 | " ORDER BY lower(tagname)" |
| 753 | ); |
| 754 | while( db_step(&q)==SQLITE_ROW ){ |
| 755 | const char *zName = db_column_text(&q, 0); |
| 756 | printf( "%s\n",zName); |
| 757 | } |
| 758 | db_finalize(&q); |
| 759 | }else |
| 760 | { |
| 761 | goto wiki_cmd_usage; |
| 762 | } |
| 763 | return; |
| 764 | |
| 765 | wiki_cmd_usage: |
| 766 | usage("delete|export|commit|list [EntryName]"); |
| 767 | } |
| 768 | |
| 769 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -598,15 +598,10 @@ | |
| 598 | @ </nowiki> element. |
| 599 | @ </ol> |
| 600 | style_footer(); |
| 601 | } |
| 602 | |
| 603 | /* |
| 604 | ** COMMAND: wiki |
| 605 | ** |
| 606 | ** Usage: %fossil wiki (export|commit|list) WikiName |
| 607 | ** |
| @@ -637,132 +632,69 @@ | |
| 632 | if( n==0 ){ |
| 633 | goto wiki_cmd_usage; |
| 634 | } |
| 635 | |
| 636 | if( strncmp(g.argv[2],"export",n)==0 ){ |
| 637 | char *wname; /* Name of the wiki page to export */ |
| 638 | int rid; /* Artifact ID of the wiki page */ |
| 639 | int i; /* Loop counter */ |
| 640 | char *zBody = 0; /* Wiki page content */ |
| 641 | Manifest m; /* Parsed wiki page content */ |
| 642 | |
| 643 | if( g.argc!=4 ){ |
| 644 | usage("export PAGENAME"); |
| 645 | } |
| 646 | wname = g.argv[3]; |
| 647 | rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x" |
| 648 | " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'" |
| 649 | " ORDER BY x.mtime DESC LIMIT 1", |
| 650 | wname |
| 651 | ); |
| 652 | if( rid ){ |
| 653 | Blob content; |
| 654 | content_get(rid, &content); |
| 655 | manifest_parse(&m, &content); |
| 656 | if( m.type==CFTYPE_WIKI ){ |
| 657 | zBody = m.zWiki; |
| 658 | } |
| 659 | } |
| 660 | if( zBody==0 ){ |
| 661 | fossil_fatal("wiki page [%s] not found",wname); |
| 662 | } |
| 663 | for(i=strlen(zBody); i>0 && isspace(zBody[i-1]); i--){} |
| 664 | printf("%.*s\n", i, zBody); |
| 665 | return; |
| 666 | }else |
| 667 | if( strncmp(g.argv[2],"commit",n)==0 ){ |
| 668 | char *wname; |
| 669 | if( g.argc!=4 ){ |
| 670 | usage("commit PAGENAME"); |
| 671 | } |
| 672 | wname = g.argv[3]; |
| 673 | fossil_fatal("wiki commit not yet implemented."); |
| 674 | }else |
| 675 | if( strncmp(g.argv[2],"delete",n)==0 ){ |
| 676 | if( g.argc!=5 ){ |
| 677 | usage("delete PAGENAME"); |
| 678 | } |
| 679 | fossil_fatal("delete not yet implemented."); |
| 680 | }else |
| 681 | if( strncmp(g.argv[2],"list",n)==0 ){ |
| 682 | Stmt q; |
| 683 | db_prepare(&q, |
| 684 | "SELECT substr(tagname, 6) FROM tag WHERE tagname GLOB 'wiki-*'" |
| 685 | " ORDER BY lower(tagname)" |
| 686 | ); |
| 687 | while( db_step(&q)==SQLITE_ROW ){ |
| 688 | const char *zName = db_column_text(&q, 0); |
| 689 | printf( "%s\n",zName); |
| 690 | } |
| 691 | db_finalize(&q); |
| 692 | }else |
| 693 | { |
| 694 | goto wiki_cmd_usage; |
| 695 | } |
| 696 | return; |
| 697 | |
| 698 | wiki_cmd_usage: |
| 699 | usage("delete|export|commit|list ..."); |
| 700 | } |
| 701 |