Fossil SCM

Make some auxiliary Th1 variables available within skins' header/footer. For /doc, /uv and /wiki pages put into "artifact_hashsum" variable (and also into its page-specific variant) a full identifier of the requested file or wiki. For /wiki pages also provide "wiki_editor" and "wiki_timestamp" variables. There is an old forum [forum:/forumtread/436c618d309917|thread on the topic] and another thread on [forum:/forumthread/48e2ae955f09|a little bit related] issue.

george 2021-04-07 03:10 trunk
Commit 80e062e1a7fea350fae19c47762d3e7263038327ffbc1aee7073f1da5f5f817c
2 files changed +28 -6 +12
+28 -6
--- src/doc.c
+++ src/doc.c
@@ -910,19 +910,20 @@
910910
*/
911911
void doc_page(void){
912912
const char *zName = 0; /* Argument to the /doc page */
913913
const char *zOrigName = "?"; /* Original document name */
914914
const char *zMime; /* Document MIME type */
915
- char *zCheckin = "tip"; /* The check-in holding the document */
916
- char *zPathSuffix = ""; /* Text to append to g.zPath */
915
+ const char *zCheckin = "tip"; /* The check-in holding the document */
916
+ const char *zPathSuffix = ""; /* Text to append to g.zPath */
917917
int vid = 0; /* Artifact of check-in */
918918
int rid = 0; /* Artifact of file */
919919
int i; /* Loop counter */
920920
Blob filebody; /* Content of the documentation file */
921921
Blob title; /* Document title */
922
+ Blob filehash = empty_blob; /* Hashsum of the document's source */
922923
int nMiss = (-1); /* Failed attempts to find the document */
923
- int isUV = g.zPath[0]=='u'; /* True for /uv. False for /doc */
924
+ const int isUV = g.zPath[0]=='u'; /* True for /uv. False for /doc */
924925
const char *zDfltTitle;
925926
static const char *const azSuffix[] = {
926927
"index.html", "index.wiki", "index.md"
927928
#ifdef FOSSIL_ENABLE_TH1_DOCS
928929
, "index.th1"
@@ -986,20 +987,23 @@
986987
}
987988
}
988989
if( isUV ){
989990
if( db_table_exists("repository","unversioned") ){
990991
rid = unversioned_content(zName, &filebody);
991
- if( rid==1 ){
992
+ if( rid==1 ){ /* found by name */
992993
Stmt q;
993994
db_prepare(&q, "SELECT hash, mtime FROM unversioned"
994995
" WHERE name=%Q", zName);
995996
if( db_step(&q)==SQLITE_ROW ){
996
- etag_check(ETAG_HASH, db_column_text(&q,0));
997
+ const char* hash = db_column_text(&q,0);
998
+ blob_set_dynamic( &filehash, fossil_strdup( hash ));
999
+ etag_check(ETAG_HASH,hash);
9971000
etag_last_modified(db_column_int64(&q,1));
9981001
}
9991002
db_finalize(&q);
1000
- }else if( rid==2 ){
1003
+ }else if( rid==2 ){ /* found by hash */
1004
+ blob_set_dynamic( &filehash, fossil_strdup( zName ));
10011005
zName = db_text(zName,
10021006
"SELECT name FROM unversioned WHERE hash=%Q", zName);
10031007
g.isConst = 1;
10041008
}
10051009
zDfltTitle = zName;
@@ -1012,15 +1016,21 @@
10121016
db_must_be_within_tree();
10131017
zFullpath = mprintf("%s/%s", g.zLocalRoot, zName);
10141018
if( file_isfile(zFullpath, RepoFILE)
10151019
&& blob_read_from_file(&filebody, zFullpath, RepoFILE)>0 ){
10161020
rid = 1; /* Fake RID just to get the loop to end */
1021
+ if(filebody.nUsed <= 256*1024){/* don't hash big files */
1022
+ hname_hash( &filebody, 0, &filehash );
1023
+ }
10171024
}
10181025
fossil_free(zFullpath);
10191026
}else{
10201027
vid = symbolic_name_to_rid(zCheckin, "ci");
10211028
rid = vid>0 ? doc_load_content(vid, zName, &filebody) : 0;
1029
+ if( rid ){
1030
+ blob_set_dynamic( &filehash, rid_to_uuid(rid) );
1031
+ }
10221032
}
10231033
}
10241034
g.zPath = mprintf("%s/%s", g.zPath, zPathSuffix);
10251035
if( rid==0 ) goto doc_not_found;
10261036
blob_to_utf8_no_bom(&filebody, 0);
@@ -1031,11 +1041,23 @@
10311041
zMime = nMiss==0 ? P("mimetype") : 0;
10321042
if( zMime==0 ){
10331043
zMime = mimetype_from_name(zName);
10341044
}
10351045
Th_Store("doc_name", zName);
1046
+ if( !blob_is_reset(&filehash) ){
1047
+ Th_Store( "artifact_hashsum", blob_str(&filehash));
1048
+ Th_Store( isUV ? "uv_hashsum" : "doc_hashsum", blob_str(&filehash));
1049
+ blob_reset( &filehash );
1050
+ }
10361051
if( vid ){
1052
+ /* FIXME: the following two Th1 variables seem misleading because
1053
+ ** 1) variables' names imply a document while their
1054
+ ** values correspond to a check-in that is being served,
1055
+ ** 2) truncation and mangling of `uuid` seems very unhelpful,
1056
+ ** 3) the date's meaning seems ambiguous
1057
+ ** (expecially if check-in has been amended)
1058
+ */
10371059
Th_Store("doc_version", db_text(0, "SELECT '[' || substr(uuid,1,10) || ']'"
10381060
" FROM blob WHERE rid=%d", vid));
10391061
Th_Store("doc_date", db_text(0, "SELECT datetime(mtime) FROM event"
10401062
" WHERE objid=%d AND type='ci'", vid));
10411063
}
10421064
--- src/doc.c
+++ src/doc.c
@@ -910,19 +910,20 @@
910 */
911 void doc_page(void){
912 const char *zName = 0; /* Argument to the /doc page */
913 const char *zOrigName = "?"; /* Original document name */
914 const char *zMime; /* Document MIME type */
915 char *zCheckin = "tip"; /* The check-in holding the document */
916 char *zPathSuffix = ""; /* Text to append to g.zPath */
917 int vid = 0; /* Artifact of check-in */
918 int rid = 0; /* Artifact of file */
919 int i; /* Loop counter */
920 Blob filebody; /* Content of the documentation file */
921 Blob title; /* Document title */
 
922 int nMiss = (-1); /* Failed attempts to find the document */
923 int isUV = g.zPath[0]=='u'; /* True for /uv. False for /doc */
924 const char *zDfltTitle;
925 static const char *const azSuffix[] = {
926 "index.html", "index.wiki", "index.md"
927 #ifdef FOSSIL_ENABLE_TH1_DOCS
928 , "index.th1"
@@ -986,20 +987,23 @@
986 }
987 }
988 if( isUV ){
989 if( db_table_exists("repository","unversioned") ){
990 rid = unversioned_content(zName, &filebody);
991 if( rid==1 ){
992 Stmt q;
993 db_prepare(&q, "SELECT hash, mtime FROM unversioned"
994 " WHERE name=%Q", zName);
995 if( db_step(&q)==SQLITE_ROW ){
996 etag_check(ETAG_HASH, db_column_text(&q,0));
 
 
997 etag_last_modified(db_column_int64(&q,1));
998 }
999 db_finalize(&q);
1000 }else if( rid==2 ){
 
1001 zName = db_text(zName,
1002 "SELECT name FROM unversioned WHERE hash=%Q", zName);
1003 g.isConst = 1;
1004 }
1005 zDfltTitle = zName;
@@ -1012,15 +1016,21 @@
1012 db_must_be_within_tree();
1013 zFullpath = mprintf("%s/%s", g.zLocalRoot, zName);
1014 if( file_isfile(zFullpath, RepoFILE)
1015 && blob_read_from_file(&filebody, zFullpath, RepoFILE)>0 ){
1016 rid = 1; /* Fake RID just to get the loop to end */
 
 
 
1017 }
1018 fossil_free(zFullpath);
1019 }else{
1020 vid = symbolic_name_to_rid(zCheckin, "ci");
1021 rid = vid>0 ? doc_load_content(vid, zName, &filebody) : 0;
 
 
 
1022 }
1023 }
1024 g.zPath = mprintf("%s/%s", g.zPath, zPathSuffix);
1025 if( rid==0 ) goto doc_not_found;
1026 blob_to_utf8_no_bom(&filebody, 0);
@@ -1031,11 +1041,23 @@
1031 zMime = nMiss==0 ? P("mimetype") : 0;
1032 if( zMime==0 ){
1033 zMime = mimetype_from_name(zName);
1034 }
1035 Th_Store("doc_name", zName);
 
 
 
 
 
1036 if( vid ){
 
 
 
 
 
 
 
1037 Th_Store("doc_version", db_text(0, "SELECT '[' || substr(uuid,1,10) || ']'"
1038 " FROM blob WHERE rid=%d", vid));
1039 Th_Store("doc_date", db_text(0, "SELECT datetime(mtime) FROM event"
1040 " WHERE objid=%d AND type='ci'", vid));
1041 }
1042
--- src/doc.c
+++ src/doc.c
@@ -910,19 +910,20 @@
910 */
911 void doc_page(void){
912 const char *zName = 0; /* Argument to the /doc page */
913 const char *zOrigName = "?"; /* Original document name */
914 const char *zMime; /* Document MIME type */
915 const char *zCheckin = "tip"; /* The check-in holding the document */
916 const char *zPathSuffix = ""; /* Text to append to g.zPath */
917 int vid = 0; /* Artifact of check-in */
918 int rid = 0; /* Artifact of file */
919 int i; /* Loop counter */
920 Blob filebody; /* Content of the documentation file */
921 Blob title; /* Document title */
922 Blob filehash = empty_blob; /* Hashsum of the document's source */
923 int nMiss = (-1); /* Failed attempts to find the document */
924 const int isUV = g.zPath[0]=='u'; /* True for /uv. False for /doc */
925 const char *zDfltTitle;
926 static const char *const azSuffix[] = {
927 "index.html", "index.wiki", "index.md"
928 #ifdef FOSSIL_ENABLE_TH1_DOCS
929 , "index.th1"
@@ -986,20 +987,23 @@
987 }
988 }
989 if( isUV ){
990 if( db_table_exists("repository","unversioned") ){
991 rid = unversioned_content(zName, &filebody);
992 if( rid==1 ){ /* found by name */
993 Stmt q;
994 db_prepare(&q, "SELECT hash, mtime FROM unversioned"
995 " WHERE name=%Q", zName);
996 if( db_step(&q)==SQLITE_ROW ){
997 const char* hash = db_column_text(&q,0);
998 blob_set_dynamic( &filehash, fossil_strdup( hash ));
999 etag_check(ETAG_HASH,hash);
1000 etag_last_modified(db_column_int64(&q,1));
1001 }
1002 db_finalize(&q);
1003 }else if( rid==2 ){ /* found by hash */
1004 blob_set_dynamic( &filehash, fossil_strdup( zName ));
1005 zName = db_text(zName,
1006 "SELECT name FROM unversioned WHERE hash=%Q", zName);
1007 g.isConst = 1;
1008 }
1009 zDfltTitle = zName;
@@ -1012,15 +1016,21 @@
1016 db_must_be_within_tree();
1017 zFullpath = mprintf("%s/%s", g.zLocalRoot, zName);
1018 if( file_isfile(zFullpath, RepoFILE)
1019 && blob_read_from_file(&filebody, zFullpath, RepoFILE)>0 ){
1020 rid = 1; /* Fake RID just to get the loop to end */
1021 if(filebody.nUsed <= 256*1024){/* don't hash big files */
1022 hname_hash( &filebody, 0, &filehash );
1023 }
1024 }
1025 fossil_free(zFullpath);
1026 }else{
1027 vid = symbolic_name_to_rid(zCheckin, "ci");
1028 rid = vid>0 ? doc_load_content(vid, zName, &filebody) : 0;
1029 if( rid ){
1030 blob_set_dynamic( &filehash, rid_to_uuid(rid) );
1031 }
1032 }
1033 }
1034 g.zPath = mprintf("%s/%s", g.zPath, zPathSuffix);
1035 if( rid==0 ) goto doc_not_found;
1036 blob_to_utf8_no_bom(&filebody, 0);
@@ -1031,11 +1041,23 @@
1041 zMime = nMiss==0 ? P("mimetype") : 0;
1042 if( zMime==0 ){
1043 zMime = mimetype_from_name(zName);
1044 }
1045 Th_Store("doc_name", zName);
1046 if( !blob_is_reset(&filehash) ){
1047 Th_Store( "artifact_hashsum", blob_str(&filehash));
1048 Th_Store( isUV ? "uv_hashsum" : "doc_hashsum", blob_str(&filehash));
1049 blob_reset( &filehash );
1050 }
1051 if( vid ){
1052 /* FIXME: the following two Th1 variables seem misleading because
1053 ** 1) variables' names imply a document while their
1054 ** values correspond to a check-in that is being served,
1055 ** 2) truncation and mangling of `uuid` seems very unhelpful,
1056 ** 3) the date's meaning seems ambiguous
1057 ** (expecially if check-in has been amended)
1058 */
1059 Th_Store("doc_version", db_text(0, "SELECT '[' || substr(uuid,1,10) || ']'"
1060 " FROM blob WHERE rid=%d", vid));
1061 Th_Store("doc_date", db_text(0, "SELECT datetime(mtime) FROM event"
1062 " WHERE objid=%d AND type='ci'", vid));
1063 }
1064
+12
--- src/wiki.c
+++ src/wiki.c
@@ -543,10 +543,11 @@
543543
unsigned submenuFlags = W_HELP;
544544
Blob wiki;
545545
Manifest *pWiki = 0;
546546
const char *zPageName;
547547
const char *zMimetype = 0;
548
+ const char *zHashsum = 0; /* of the wiki's corresponding artifact */
548549
int isPopup = P("popup")!=0;
549550
char *zBody = mprintf("%s","<i>Empty Page</i>");
550551
int noSubmenu = P("nsm")!=0;
551552
552553
login_check_credentials();
@@ -580,10 +581,11 @@
580581
}
581582
pWiki = manifest_get(rid, CFTYPE_WIKI, 0);
582583
if( pWiki ){
583584
zBody = pWiki->zWiki;
584585
zMimetype = pWiki->zMimetype;
586
+ zHashsum = rid_to_uuid(rid);
585587
}
586588
}
587589
zMimetype = wiki_filter_mimetypes(zMimetype);
588590
if( !g.isHome && !noSubmenu ){
589591
if( ((rid && g.perm.WrWiki) || (!rid && g.perm.NewWiki))
@@ -597,10 +599,20 @@
597599
style_submenu_element("History", "%R/whistory?name=%T", zPageName);
598600
style_submenu_parametric("wiki",7);
599601
}
600602
}
601603
if( !isPopup ){
604
+ char *zDate = db_text(0,"SELECT strftime('%%Y-%%m-%%d %%H:%%M',"
605
+ "'%.17g',toLocal())",pWiki->rDate);
606
+ Th_Store("wiki_timestamp",zDate);
607
+ fossil_free( zDate );
608
+ Th_Store("wiki_editor",pWiki->zUser);
609
+ if( zHashsum ){
610
+ Th_Store("artifact_hashsum",zHashsum);
611
+ Th_Store("wiki_hashsum",zHashsum);
612
+ fossil_free( (char*)zHashsum );
613
+ }
602614
style_set_current_page("%T?name=%T", g.zPath, zPageName);
603615
wiki_page_header(WIKITYPE_UNKNOWN, zPageName, "");
604616
if( !noSubmenu ){
605617
wiki_standard_submenu(submenuFlags);
606618
}
607619
--- src/wiki.c
+++ src/wiki.c
@@ -543,10 +543,11 @@
543 unsigned submenuFlags = W_HELP;
544 Blob wiki;
545 Manifest *pWiki = 0;
546 const char *zPageName;
547 const char *zMimetype = 0;
 
548 int isPopup = P("popup")!=0;
549 char *zBody = mprintf("%s","<i>Empty Page</i>");
550 int noSubmenu = P("nsm")!=0;
551
552 login_check_credentials();
@@ -580,10 +581,11 @@
580 }
581 pWiki = manifest_get(rid, CFTYPE_WIKI, 0);
582 if( pWiki ){
583 zBody = pWiki->zWiki;
584 zMimetype = pWiki->zMimetype;
 
585 }
586 }
587 zMimetype = wiki_filter_mimetypes(zMimetype);
588 if( !g.isHome && !noSubmenu ){
589 if( ((rid && g.perm.WrWiki) || (!rid && g.perm.NewWiki))
@@ -597,10 +599,20 @@
597 style_submenu_element("History", "%R/whistory?name=%T", zPageName);
598 style_submenu_parametric("wiki",7);
599 }
600 }
601 if( !isPopup ){
 
 
 
 
 
 
 
 
 
 
602 style_set_current_page("%T?name=%T", g.zPath, zPageName);
603 wiki_page_header(WIKITYPE_UNKNOWN, zPageName, "");
604 if( !noSubmenu ){
605 wiki_standard_submenu(submenuFlags);
606 }
607
--- src/wiki.c
+++ src/wiki.c
@@ -543,10 +543,11 @@
543 unsigned submenuFlags = W_HELP;
544 Blob wiki;
545 Manifest *pWiki = 0;
546 const char *zPageName;
547 const char *zMimetype = 0;
548 const char *zHashsum = 0; /* of the wiki's corresponding artifact */
549 int isPopup = P("popup")!=0;
550 char *zBody = mprintf("%s","<i>Empty Page</i>");
551 int noSubmenu = P("nsm")!=0;
552
553 login_check_credentials();
@@ -580,10 +581,11 @@
581 }
582 pWiki = manifest_get(rid, CFTYPE_WIKI, 0);
583 if( pWiki ){
584 zBody = pWiki->zWiki;
585 zMimetype = pWiki->zMimetype;
586 zHashsum = rid_to_uuid(rid);
587 }
588 }
589 zMimetype = wiki_filter_mimetypes(zMimetype);
590 if( !g.isHome && !noSubmenu ){
591 if( ((rid && g.perm.WrWiki) || (!rid && g.perm.NewWiki))
@@ -597,10 +599,20 @@
599 style_submenu_element("History", "%R/whistory?name=%T", zPageName);
600 style_submenu_parametric("wiki",7);
601 }
602 }
603 if( !isPopup ){
604 char *zDate = db_text(0,"SELECT strftime('%%Y-%%m-%%d %%H:%%M',"
605 "'%.17g',toLocal())",pWiki->rDate);
606 Th_Store("wiki_timestamp",zDate);
607 fossil_free( zDate );
608 Th_Store("wiki_editor",pWiki->zUser);
609 if( zHashsum ){
610 Th_Store("artifact_hashsum",zHashsum);
611 Th_Store("wiki_hashsum",zHashsum);
612 fossil_free( (char*)zHashsum );
613 }
614 style_set_current_page("%T?name=%T", g.zPath, zPageName);
615 wiki_page_header(WIKITYPE_UNKNOWN, zPageName, "");
616 if( !noSubmenu ){
617 wiki_standard_submenu(submenuFlags);
618 }
619

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button