Fossil SCM
Add the /uv webpage.
Commit
440defe233ae6bc14a62ff8d05fc1e87aa22458f
Parent
a9463a7157129ee…
1 file changed
+40
-16
+40
-16
| --- src/doc.c | ||
| +++ src/doc.c | ||
| @@ -522,12 +522,13 @@ | ||
| 522 | 522 | } |
| 523 | 523 | blob_append(cgi_output_blob(), &z[base], i-base); |
| 524 | 524 | } |
| 525 | 525 | |
| 526 | 526 | /* |
| 527 | +** WEBPAGE: uv | |
| 527 | 528 | ** WEBPAGE: doc |
| 528 | -** URL: /doc?name=CHECKIN/FILE | |
| 529 | +** URL: /uv/FILE | |
| 529 | 530 | ** URL: /doc/CHECKIN/FILE |
| 530 | 531 | ** |
| 531 | 532 | ** CHECKIN can be either tag or SHA1 hash or timestamp identifying a |
| 532 | 533 | ** particular check, or the name of a branch (meaning the most recent |
| 533 | 534 | ** check-in on that branch) or one of various magic words: |
| @@ -578,10 +579,12 @@ | ||
| 578 | 579 | int rid = 0; /* Artifact of file */ |
| 579 | 580 | int i; /* Loop counter */ |
| 580 | 581 | Blob filebody; /* Content of the documentation file */ |
| 581 | 582 | Blob title; /* Document title */ |
| 582 | 583 | int nMiss = (-1); /* Failed attempts to find the document */ |
| 584 | + int isUV = g.zPath[0]=='u'; /* True for /uv. False for /doc */ | |
| 585 | + const char *zDfltTitle; | |
| 583 | 586 | static const char *const azSuffix[] = { |
| 584 | 587 | "index.html", "index.wiki", "index.md" |
| 585 | 588 | #ifdef FOSSIL_ENABLE_TH1_DOCS |
| 586 | 589 | , "index.th1" |
| 587 | 590 | #endif |
| @@ -588,29 +591,38 @@ | ||
| 588 | 591 | }; |
| 589 | 592 | |
| 590 | 593 | login_check_credentials(); |
| 591 | 594 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 592 | 595 | blob_init(&title, 0, 0); |
| 596 | + zDfltTitle = isUV ? "" : "Documentation"; | |
| 593 | 597 | db_begin_transaction(); |
| 594 | 598 | while( rid==0 && (++nMiss)<=ArraySize(azSuffix) ){ |
| 595 | 599 | zName = P("name"); |
| 596 | - if( zName==0 || zName[0]==0 ) zName = "tip/index.wiki"; | |
| 597 | - for(i=0; zName[i] && zName[i]!='/'; i++){} | |
| 598 | - zCheckin = mprintf("%.*s", i, zName); | |
| 599 | - if( fossil_strcmp(zCheckin,"ckout")==0 && g.localOpen==0 ){ | |
| 600 | - zCheckin = "tip"; | |
| 600 | + if( isUV ){ | |
| 601 | + i = 0; | |
| 602 | + }else{ | |
| 603 | + if( zName==0 || zName[0]==0 ) zName = "tip/index.wiki"; | |
| 604 | + for(i=0; zName[i] && zName[i]!='/'; i++){} | |
| 605 | + zCheckin = mprintf("%.*s", i, zName); | |
| 606 | + if( fossil_strcmp(zCheckin,"ckout")==0 && g.localOpen==0 ){ | |
| 607 | + zCheckin = "tip"; | |
| 608 | + } | |
| 601 | 609 | } |
| 602 | 610 | if( nMiss==ArraySize(azSuffix) ){ |
| 603 | 611 | zName = "404.md"; |
| 604 | 612 | }else if( zName[i]==0 ){ |
| 605 | 613 | assert( nMiss>=0 && nMiss<ArraySize(azSuffix) ); |
| 606 | 614 | zName = azSuffix[nMiss]; |
| 607 | - }else{ | |
| 615 | + }else if( !isUV ){ | |
| 608 | 616 | zName += i; |
| 609 | 617 | } |
| 610 | 618 | while( zName[0]=='/' ){ zName++; } |
| 611 | - g.zPath = mprintf("%s/%s/%s", g.zPath, zCheckin, zName); | |
| 619 | + if( isUV ){ | |
| 620 | + g.zPath = mprintf("%s/%s", g.zPath, zName); | |
| 621 | + }else{ | |
| 622 | + g.zPath = mprintf("%s/%s/%s", g.zPath, zCheckin, zName); | |
| 623 | + } | |
| 612 | 624 | if( nMiss==0 ) zOrigName = zName; |
| 613 | 625 | if( !file_is_simple_pathname(zName, 1) ){ |
| 614 | 626 | if( sqlite3_strglob("*/", zName)==0 ){ |
| 615 | 627 | assert( nMiss>=0 && nMiss<ArraySize(azSuffix) ); |
| 616 | 628 | zName = mprintf("%s%s", zName, azSuffix[nMiss]); |
| @@ -619,11 +631,21 @@ | ||
| 619 | 631 | } |
| 620 | 632 | }else{ |
| 621 | 633 | goto doc_not_found; |
| 622 | 634 | } |
| 623 | 635 | } |
| 624 | - if( fossil_strcmp(zCheckin,"ckout")==0 ){ | |
| 636 | + if( isUV ){ | |
| 637 | + if( db_exists("SELECT 1 FROM unversioned" | |
| 638 | + " WHERE name=%Q AND content IS NOT NULL", zName) ){ | |
| 639 | + blob_init(&filebody, 0, 0); | |
| 640 | + db_blob(&filebody, "SELECT content FROM unversioned WHERE name=%Q", | |
| 641 | + zName); | |
| 642 | + blob_uncompress(&filebody, &filebody); | |
| 643 | + rid = 1; | |
| 644 | + zDfltTitle = zName; | |
| 645 | + } | |
| 646 | + }else if( fossil_strcmp(zCheckin,"ckout")==0 ){ | |
| 625 | 647 | /* Read from the local checkout */ |
| 626 | 648 | char *zFullpath; |
| 627 | 649 | db_must_be_within_tree(); |
| 628 | 650 | zFullpath = mprintf("%s/%s", g.zLocalRoot, zName); |
| 629 | 651 | if( file_isfile(zFullpath) |
| @@ -645,22 +667,24 @@ | ||
| 645 | 667 | zMime = nMiss==0 ? P("mimetype") : 0; |
| 646 | 668 | if( zMime==0 ){ |
| 647 | 669 | zMime = mimetype_from_name(zName); |
| 648 | 670 | } |
| 649 | 671 | Th_Store("doc_name", zName); |
| 650 | - Th_Store("doc_version", db_text(0, "SELECT '[' || substr(uuid,1,10) || ']'" | |
| 651 | - " FROM blob WHERE rid=%d", vid)); | |
| 652 | - Th_Store("doc_date", db_text(0, "SELECT datetime(mtime) FROM event" | |
| 653 | - " WHERE objid=%d AND type='ci'", vid)); | |
| 672 | + if( vid ){ | |
| 673 | + Th_Store("doc_version", db_text(0, "SELECT '[' || substr(uuid,1,10) || ']'" | |
| 674 | + " FROM blob WHERE rid=%d", vid)); | |
| 675 | + Th_Store("doc_date", db_text(0, "SELECT datetime(mtime) FROM event" | |
| 676 | + " WHERE objid=%d AND type='ci'", vid)); | |
| 677 | + } | |
| 654 | 678 | if( fossil_strcmp(zMime, "text/x-fossil-wiki")==0 ){ |
| 655 | 679 | Blob tail; |
| 656 | 680 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 657 | 681 | if( wiki_find_title(&filebody, &title, &tail) ){ |
| 658 | 682 | style_header("%s", blob_str(&title)); |
| 659 | 683 | wiki_convert(&tail, 0, WIKI_BUTTONS); |
| 660 | 684 | }else{ |
| 661 | - style_header("Documentation"); | |
| 685 | + style_header("%s", zDfltTitle); | |
| 662 | 686 | wiki_convert(&filebody, 0, WIKI_BUTTONS); |
| 663 | 687 | } |
| 664 | 688 | style_footer(); |
| 665 | 689 | }else if( fossil_strcmp(zMime, "text/x-markdown")==0 ){ |
| 666 | 690 | Blob tail = BLOB_INITIALIZER; |
| @@ -667,16 +691,16 @@ | ||
| 667 | 691 | markdown_to_html(&filebody, &title, &tail); |
| 668 | 692 | if( blob_size(&title)>0 ){ |
| 669 | 693 | style_header("%s", blob_str(&title)); |
| 670 | 694 | }else{ |
| 671 | 695 | style_header("%s", nMiss>=ArraySize(azSuffix)? |
| 672 | - "Not Found" : "Documentation"); | |
| 696 | + "Not Found" : zDfltTitle); | |
| 673 | 697 | } |
| 674 | 698 | convert_href_and_output(&tail); |
| 675 | 699 | style_footer(); |
| 676 | 700 | }else if( fossil_strcmp(zMime, "text/plain")==0 ){ |
| 677 | - style_header("Documentation"); | |
| 701 | + style_header("%s", zDfltTitle); | |
| 678 | 702 | @ <blockquote><pre> |
| 679 | 703 | @ %h(blob_str(&filebody)) |
| 680 | 704 | @ </pre></blockquote> |
| 681 | 705 | style_footer(); |
| 682 | 706 | }else if( fossil_strcmp(zMime, "text/html")==0 |
| 683 | 707 |
| --- src/doc.c | |
| +++ src/doc.c | |
| @@ -522,12 +522,13 @@ | |
| 522 | } |
| 523 | blob_append(cgi_output_blob(), &z[base], i-base); |
| 524 | } |
| 525 | |
| 526 | /* |
| 527 | ** WEBPAGE: doc |
| 528 | ** URL: /doc?name=CHECKIN/FILE |
| 529 | ** URL: /doc/CHECKIN/FILE |
| 530 | ** |
| 531 | ** CHECKIN can be either tag or SHA1 hash or timestamp identifying a |
| 532 | ** particular check, or the name of a branch (meaning the most recent |
| 533 | ** check-in on that branch) or one of various magic words: |
| @@ -578,10 +579,12 @@ | |
| 578 | int rid = 0; /* Artifact of file */ |
| 579 | int i; /* Loop counter */ |
| 580 | Blob filebody; /* Content of the documentation file */ |
| 581 | Blob title; /* Document title */ |
| 582 | int nMiss = (-1); /* Failed attempts to find the document */ |
| 583 | static const char *const azSuffix[] = { |
| 584 | "index.html", "index.wiki", "index.md" |
| 585 | #ifdef FOSSIL_ENABLE_TH1_DOCS |
| 586 | , "index.th1" |
| 587 | #endif |
| @@ -588,29 +591,38 @@ | |
| 588 | }; |
| 589 | |
| 590 | login_check_credentials(); |
| 591 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 592 | blob_init(&title, 0, 0); |
| 593 | db_begin_transaction(); |
| 594 | while( rid==0 && (++nMiss)<=ArraySize(azSuffix) ){ |
| 595 | zName = P("name"); |
| 596 | if( zName==0 || zName[0]==0 ) zName = "tip/index.wiki"; |
| 597 | for(i=0; zName[i] && zName[i]!='/'; i++){} |
| 598 | zCheckin = mprintf("%.*s", i, zName); |
| 599 | if( fossil_strcmp(zCheckin,"ckout")==0 && g.localOpen==0 ){ |
| 600 | zCheckin = "tip"; |
| 601 | } |
| 602 | if( nMiss==ArraySize(azSuffix) ){ |
| 603 | zName = "404.md"; |
| 604 | }else if( zName[i]==0 ){ |
| 605 | assert( nMiss>=0 && nMiss<ArraySize(azSuffix) ); |
| 606 | zName = azSuffix[nMiss]; |
| 607 | }else{ |
| 608 | zName += i; |
| 609 | } |
| 610 | while( zName[0]=='/' ){ zName++; } |
| 611 | g.zPath = mprintf("%s/%s/%s", g.zPath, zCheckin, zName); |
| 612 | if( nMiss==0 ) zOrigName = zName; |
| 613 | if( !file_is_simple_pathname(zName, 1) ){ |
| 614 | if( sqlite3_strglob("*/", zName)==0 ){ |
| 615 | assert( nMiss>=0 && nMiss<ArraySize(azSuffix) ); |
| 616 | zName = mprintf("%s%s", zName, azSuffix[nMiss]); |
| @@ -619,11 +631,21 @@ | |
| 619 | } |
| 620 | }else{ |
| 621 | goto doc_not_found; |
| 622 | } |
| 623 | } |
| 624 | if( fossil_strcmp(zCheckin,"ckout")==0 ){ |
| 625 | /* Read from the local checkout */ |
| 626 | char *zFullpath; |
| 627 | db_must_be_within_tree(); |
| 628 | zFullpath = mprintf("%s/%s", g.zLocalRoot, zName); |
| 629 | if( file_isfile(zFullpath) |
| @@ -645,22 +667,24 @@ | |
| 645 | zMime = nMiss==0 ? P("mimetype") : 0; |
| 646 | if( zMime==0 ){ |
| 647 | zMime = mimetype_from_name(zName); |
| 648 | } |
| 649 | Th_Store("doc_name", zName); |
| 650 | Th_Store("doc_version", db_text(0, "SELECT '[' || substr(uuid,1,10) || ']'" |
| 651 | " FROM blob WHERE rid=%d", vid)); |
| 652 | Th_Store("doc_date", db_text(0, "SELECT datetime(mtime) FROM event" |
| 653 | " WHERE objid=%d AND type='ci'", vid)); |
| 654 | if( fossil_strcmp(zMime, "text/x-fossil-wiki")==0 ){ |
| 655 | Blob tail; |
| 656 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 657 | if( wiki_find_title(&filebody, &title, &tail) ){ |
| 658 | style_header("%s", blob_str(&title)); |
| 659 | wiki_convert(&tail, 0, WIKI_BUTTONS); |
| 660 | }else{ |
| 661 | style_header("Documentation"); |
| 662 | wiki_convert(&filebody, 0, WIKI_BUTTONS); |
| 663 | } |
| 664 | style_footer(); |
| 665 | }else if( fossil_strcmp(zMime, "text/x-markdown")==0 ){ |
| 666 | Blob tail = BLOB_INITIALIZER; |
| @@ -667,16 +691,16 @@ | |
| 667 | markdown_to_html(&filebody, &title, &tail); |
| 668 | if( blob_size(&title)>0 ){ |
| 669 | style_header("%s", blob_str(&title)); |
| 670 | }else{ |
| 671 | style_header("%s", nMiss>=ArraySize(azSuffix)? |
| 672 | "Not Found" : "Documentation"); |
| 673 | } |
| 674 | convert_href_and_output(&tail); |
| 675 | style_footer(); |
| 676 | }else if( fossil_strcmp(zMime, "text/plain")==0 ){ |
| 677 | style_header("Documentation"); |
| 678 | @ <blockquote><pre> |
| 679 | @ %h(blob_str(&filebody)) |
| 680 | @ </pre></blockquote> |
| 681 | style_footer(); |
| 682 | }else if( fossil_strcmp(zMime, "text/html")==0 |
| 683 |
| --- src/doc.c | |
| +++ src/doc.c | |
| @@ -522,12 +522,13 @@ | |
| 522 | } |
| 523 | blob_append(cgi_output_blob(), &z[base], i-base); |
| 524 | } |
| 525 | |
| 526 | /* |
| 527 | ** WEBPAGE: uv |
| 528 | ** WEBPAGE: doc |
| 529 | ** URL: /uv/FILE |
| 530 | ** URL: /doc/CHECKIN/FILE |
| 531 | ** |
| 532 | ** CHECKIN can be either tag or SHA1 hash or timestamp identifying a |
| 533 | ** particular check, or the name of a branch (meaning the most recent |
| 534 | ** check-in on that branch) or one of various magic words: |
| @@ -578,10 +579,12 @@ | |
| 579 | int rid = 0; /* Artifact of file */ |
| 580 | int i; /* Loop counter */ |
| 581 | Blob filebody; /* Content of the documentation file */ |
| 582 | Blob title; /* Document title */ |
| 583 | int nMiss = (-1); /* Failed attempts to find the document */ |
| 584 | int isUV = g.zPath[0]=='u'; /* True for /uv. False for /doc */ |
| 585 | const char *zDfltTitle; |
| 586 | static const char *const azSuffix[] = { |
| 587 | "index.html", "index.wiki", "index.md" |
| 588 | #ifdef FOSSIL_ENABLE_TH1_DOCS |
| 589 | , "index.th1" |
| 590 | #endif |
| @@ -588,29 +591,38 @@ | |
| 591 | }; |
| 592 | |
| 593 | login_check_credentials(); |
| 594 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 595 | blob_init(&title, 0, 0); |
| 596 | zDfltTitle = isUV ? "" : "Documentation"; |
| 597 | db_begin_transaction(); |
| 598 | while( rid==0 && (++nMiss)<=ArraySize(azSuffix) ){ |
| 599 | zName = P("name"); |
| 600 | if( isUV ){ |
| 601 | i = 0; |
| 602 | }else{ |
| 603 | if( zName==0 || zName[0]==0 ) zName = "tip/index.wiki"; |
| 604 | for(i=0; zName[i] && zName[i]!='/'; i++){} |
| 605 | zCheckin = mprintf("%.*s", i, zName); |
| 606 | if( fossil_strcmp(zCheckin,"ckout")==0 && g.localOpen==0 ){ |
| 607 | zCheckin = "tip"; |
| 608 | } |
| 609 | } |
| 610 | if( nMiss==ArraySize(azSuffix) ){ |
| 611 | zName = "404.md"; |
| 612 | }else if( zName[i]==0 ){ |
| 613 | assert( nMiss>=0 && nMiss<ArraySize(azSuffix) ); |
| 614 | zName = azSuffix[nMiss]; |
| 615 | }else if( !isUV ){ |
| 616 | zName += i; |
| 617 | } |
| 618 | while( zName[0]=='/' ){ zName++; } |
| 619 | if( isUV ){ |
| 620 | g.zPath = mprintf("%s/%s", g.zPath, zName); |
| 621 | }else{ |
| 622 | g.zPath = mprintf("%s/%s/%s", g.zPath, zCheckin, zName); |
| 623 | } |
| 624 | if( nMiss==0 ) zOrigName = zName; |
| 625 | if( !file_is_simple_pathname(zName, 1) ){ |
| 626 | if( sqlite3_strglob("*/", zName)==0 ){ |
| 627 | assert( nMiss>=0 && nMiss<ArraySize(azSuffix) ); |
| 628 | zName = mprintf("%s%s", zName, azSuffix[nMiss]); |
| @@ -619,11 +631,21 @@ | |
| 631 | } |
| 632 | }else{ |
| 633 | goto doc_not_found; |
| 634 | } |
| 635 | } |
| 636 | if( isUV ){ |
| 637 | if( db_exists("SELECT 1 FROM unversioned" |
| 638 | " WHERE name=%Q AND content IS NOT NULL", zName) ){ |
| 639 | blob_init(&filebody, 0, 0); |
| 640 | db_blob(&filebody, "SELECT content FROM unversioned WHERE name=%Q", |
| 641 | zName); |
| 642 | blob_uncompress(&filebody, &filebody); |
| 643 | rid = 1; |
| 644 | zDfltTitle = zName; |
| 645 | } |
| 646 | }else if( fossil_strcmp(zCheckin,"ckout")==0 ){ |
| 647 | /* Read from the local checkout */ |
| 648 | char *zFullpath; |
| 649 | db_must_be_within_tree(); |
| 650 | zFullpath = mprintf("%s/%s", g.zLocalRoot, zName); |
| 651 | if( file_isfile(zFullpath) |
| @@ -645,22 +667,24 @@ | |
| 667 | zMime = nMiss==0 ? P("mimetype") : 0; |
| 668 | if( zMime==0 ){ |
| 669 | zMime = mimetype_from_name(zName); |
| 670 | } |
| 671 | Th_Store("doc_name", zName); |
| 672 | if( vid ){ |
| 673 | Th_Store("doc_version", db_text(0, "SELECT '[' || substr(uuid,1,10) || ']'" |
| 674 | " FROM blob WHERE rid=%d", vid)); |
| 675 | Th_Store("doc_date", db_text(0, "SELECT datetime(mtime) FROM event" |
| 676 | " WHERE objid=%d AND type='ci'", vid)); |
| 677 | } |
| 678 | if( fossil_strcmp(zMime, "text/x-fossil-wiki")==0 ){ |
| 679 | Blob tail; |
| 680 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 681 | if( wiki_find_title(&filebody, &title, &tail) ){ |
| 682 | style_header("%s", blob_str(&title)); |
| 683 | wiki_convert(&tail, 0, WIKI_BUTTONS); |
| 684 | }else{ |
| 685 | style_header("%s", zDfltTitle); |
| 686 | wiki_convert(&filebody, 0, WIKI_BUTTONS); |
| 687 | } |
| 688 | style_footer(); |
| 689 | }else if( fossil_strcmp(zMime, "text/x-markdown")==0 ){ |
| 690 | Blob tail = BLOB_INITIALIZER; |
| @@ -667,16 +691,16 @@ | |
| 691 | markdown_to_html(&filebody, &title, &tail); |
| 692 | if( blob_size(&title)>0 ){ |
| 693 | style_header("%s", blob_str(&title)); |
| 694 | }else{ |
| 695 | style_header("%s", nMiss>=ArraySize(azSuffix)? |
| 696 | "Not Found" : zDfltTitle); |
| 697 | } |
| 698 | convert_href_and_output(&tail); |
| 699 | style_footer(); |
| 700 | }else if( fossil_strcmp(zMime, "text/plain")==0 ){ |
| 701 | style_header("%s", zDfltTitle); |
| 702 | @ <blockquote><pre> |
| 703 | @ %h(blob_str(&filebody)) |
| 704 | @ </pre></blockquote> |
| 705 | style_footer(); |
| 706 | }else if( fossil_strcmp(zMime, "text/html")==0 |
| 707 |