Fossil SCM
Always put [..] marks around SHA1 hyperlinks. For unknown SHA1 numbers, enclose in <span class="brokenlink">.
Commit
a99e9c91648c0a8fa00bbf6a4b8d2c5634da8d4d
Parent
dbc2098a6a089d0…
2 files changed
+4
+31
-9
+4
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -734,10 +734,14 @@ | ||
| 734 | 734 | @ color: blue; |
| 735 | 735 | }, |
| 736 | 736 | { "p.shunned", |
| 737 | 737 | "format for artifact lines beeing shunned", |
| 738 | 738 | @ color: blue; |
| 739 | + }, | |
| 740 | + { "span.brokenlink", | |
| 741 | + "a broken hyperlink", | |
| 742 | + @ color: red; | |
| 739 | 743 | }, |
| 740 | 744 | { 0, |
| 741 | 745 | 0, |
| 742 | 746 | 0 |
| 743 | 747 | } |
| 744 | 748 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -734,10 +734,14 @@ | |
| 734 | @ color: blue; |
| 735 | }, |
| 736 | { "p.shunned", |
| 737 | "format for artifact lines beeing shunned", |
| 738 | @ color: blue; |
| 739 | }, |
| 740 | { 0, |
| 741 | 0, |
| 742 | 0 |
| 743 | } |
| 744 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -734,10 +734,14 @@ | |
| 734 | @ color: blue; |
| 735 | }, |
| 736 | { "p.shunned", |
| 737 | "format for artifact lines beeing shunned", |
| 738 | @ color: blue; |
| 739 | }, |
| 740 | { "span.brokenlink", |
| 741 | "a broken hyperlink", |
| 742 | @ color: red; |
| 743 | }, |
| 744 | { 0, |
| 745 | 0, |
| 746 | 0 |
| 747 | } |
| 748 |
+31
-9
| --- src/wikiformat.c | ||
| +++ src/wikiformat.c | ||
| @@ -939,10 +939,26 @@ | ||
| 939 | 939 | int n = strlen(z); |
| 940 | 940 | if( n<4 || n>UUID_SIZE ) return 0; |
| 941 | 941 | if( !validate16(z, n) ) return 0; |
| 942 | 942 | return 1; |
| 943 | 943 | } |
| 944 | + | |
| 945 | +/* | |
| 946 | +** Return TRUE if a UUID corresponds to an artifact in this | |
| 947 | +** repository. | |
| 948 | +*/ | |
| 949 | +static int in_this_repo(const char *zUuid){ | |
| 950 | + static Stmt q; | |
| 951 | + int rc; | |
| 952 | + db_static_prepare(&q, | |
| 953 | + "SELECT 1 FROM blob WHERE uuid>=:u AND +uuid GLOB (:u || '*')" | |
| 954 | + ); | |
| 955 | + db_bind_text(&q, ":u", zUuid); | |
| 956 | + rc = db_step(&q); | |
| 957 | + db_reset(&q); | |
| 958 | + return rc==SQLITE_ROW; | |
| 959 | +} | |
| 944 | 960 | |
| 945 | 961 | /* |
| 946 | 962 | ** zTarget is guaranteed to be a UUID. It might be the UUID of a ticket. |
| 947 | 963 | ** If it is, store in *pClosed a true or false depending on whether or not |
| 948 | 964 | ** the ticket is closed and return true. If zTarget |
| @@ -1040,36 +1056,42 @@ | ||
| 1040 | 1056 | }else{ |
| 1041 | 1057 | zTerm = ""; |
| 1042 | 1058 | } |
| 1043 | 1059 | }else if( is_valid_uuid(zTarget) ){ |
| 1044 | 1060 | int isClosed = 0; |
| 1045 | - if( is_ticket(zTarget, &isClosed) ){ | |
| 1061 | + if( !in_this_repo(zTarget) ){ | |
| 1062 | + blob_appendf(p->pOut, "<span class=\"brokenlink\">[", zTarget); | |
| 1063 | + zTerm = "]</span>"; | |
| 1064 | + }else if( is_ticket(zTarget, &isClosed) ){ | |
| 1046 | 1065 | /* Special display processing for tickets. Display the hyperlink |
| 1047 | 1066 | ** as crossed out if the ticket is closed. |
| 1048 | 1067 | */ |
| 1049 | 1068 | if( isClosed ){ |
| 1050 | 1069 | if( g.okHistory ){ |
| 1051 | 1070 | blob_appendf(p->pOut, |
| 1052 | - "<a href=\"%s/info/%s\"><span class=\"wikiTagCancelled\">", | |
| 1071 | + "<a href=\"%s/info/%s\"><span class=\"wikiTagCancelled\">[", | |
| 1053 | 1072 | g.zTop, zTarget |
| 1054 | 1073 | ); |
| 1055 | - zTerm = "</span></a>"; | |
| 1074 | + zTerm = "]</span></a>"; | |
| 1056 | 1075 | }else{ |
| 1057 | - blob_appendf(p->pOut,"<span class=\"wikiTagCancelled\">"); | |
| 1058 | - zTerm = "</span>"; | |
| 1076 | + blob_appendf(p->pOut,"<span class=\"wikiTagCancelled\">["); | |
| 1077 | + zTerm = "]</span>"; | |
| 1059 | 1078 | } |
| 1060 | 1079 | }else{ |
| 1061 | 1080 | if( g.okHistory ){ |
| 1062 | - blob_appendf(p->pOut,"<a href=\"%s/info/%s\">", | |
| 1081 | + blob_appendf(p->pOut,"<a href=\"%s/info/%s\">[", | |
| 1063 | 1082 | g.zTop, zTarget |
| 1064 | 1083 | ); |
| 1084 | + zTerm = "]</a>"; | |
| 1065 | 1085 | }else{ |
| 1066 | - zTerm = ""; | |
| 1086 | + blob_appendf(p->pOut, "["); | |
| 1087 | + zTerm = "]"; | |
| 1067 | 1088 | } |
| 1068 | 1089 | } |
| 1069 | 1090 | }else if( g.okHistory ){ |
| 1070 | - blob_appendf(p->pOut, "<a href=\"%s/info/%s\">", g.zTop, zTarget); | |
| 1091 | + blob_appendf(p->pOut, "<a href=\"%s/info/%s\">[", g.zTop, zTarget); | |
| 1092 | + zTerm = "]</a>"; | |
| 1071 | 1093 | } |
| 1072 | 1094 | }else if( strlen(zTarget)>=10 && fossil_isdigit(zTarget[0]) && zTarget[4]=='-' |
| 1073 | 1095 | && db_int(0, "SELECT datetime(%Q) NOT NULL", zTarget) ){ |
| 1074 | 1096 | blob_appendf(p->pOut, "<a href=\"%s/timeline?c=%T\">", g.zTop, zTarget); |
| 1075 | 1097 | }else if( strncmp(zTarget, "wiki:", 5)==0 |
| @@ -1077,11 +1099,11 @@ | ||
| 1077 | 1099 | zTarget += 5; |
| 1078 | 1100 | blob_appendf(p->pOut, "<a href=\"%s/wiki?name=%T\">", g.zTop, zTarget); |
| 1079 | 1101 | }else if( wiki_name_is_wellformed((const unsigned char *)zTarget) ){ |
| 1080 | 1102 | blob_appendf(p->pOut, "<a href=\"%s/wiki?name=%T\">", g.zTop, zTarget); |
| 1081 | 1103 | }else{ |
| 1082 | - blob_appendf(p->pOut, "[bad-link: %h]", zTarget); | |
| 1104 | + blob_appendf(p->pOut, "<span class=\"brokenlink\">[%h]</span>", zTarget); | |
| 1083 | 1105 | zTerm = ""; |
| 1084 | 1106 | } |
| 1085 | 1107 | assert( strlen(zTerm)<nClose ); |
| 1086 | 1108 | sqlite3_snprintf(nClose, zClose, "%s", zTerm); |
| 1087 | 1109 | } |
| 1088 | 1110 |
| --- src/wikiformat.c | |
| +++ src/wikiformat.c | |
| @@ -939,10 +939,26 @@ | |
| 939 | int n = strlen(z); |
| 940 | if( n<4 || n>UUID_SIZE ) return 0; |
| 941 | if( !validate16(z, n) ) return 0; |
| 942 | return 1; |
| 943 | } |
| 944 | |
| 945 | /* |
| 946 | ** zTarget is guaranteed to be a UUID. It might be the UUID of a ticket. |
| 947 | ** If it is, store in *pClosed a true or false depending on whether or not |
| 948 | ** the ticket is closed and return true. If zTarget |
| @@ -1040,36 +1056,42 @@ | |
| 1040 | }else{ |
| 1041 | zTerm = ""; |
| 1042 | } |
| 1043 | }else if( is_valid_uuid(zTarget) ){ |
| 1044 | int isClosed = 0; |
| 1045 | if( is_ticket(zTarget, &isClosed) ){ |
| 1046 | /* Special display processing for tickets. Display the hyperlink |
| 1047 | ** as crossed out if the ticket is closed. |
| 1048 | */ |
| 1049 | if( isClosed ){ |
| 1050 | if( g.okHistory ){ |
| 1051 | blob_appendf(p->pOut, |
| 1052 | "<a href=\"%s/info/%s\"><span class=\"wikiTagCancelled\">", |
| 1053 | g.zTop, zTarget |
| 1054 | ); |
| 1055 | zTerm = "</span></a>"; |
| 1056 | }else{ |
| 1057 | blob_appendf(p->pOut,"<span class=\"wikiTagCancelled\">"); |
| 1058 | zTerm = "</span>"; |
| 1059 | } |
| 1060 | }else{ |
| 1061 | if( g.okHistory ){ |
| 1062 | blob_appendf(p->pOut,"<a href=\"%s/info/%s\">", |
| 1063 | g.zTop, zTarget |
| 1064 | ); |
| 1065 | }else{ |
| 1066 | zTerm = ""; |
| 1067 | } |
| 1068 | } |
| 1069 | }else if( g.okHistory ){ |
| 1070 | blob_appendf(p->pOut, "<a href=\"%s/info/%s\">", g.zTop, zTarget); |
| 1071 | } |
| 1072 | }else if( strlen(zTarget)>=10 && fossil_isdigit(zTarget[0]) && zTarget[4]=='-' |
| 1073 | && db_int(0, "SELECT datetime(%Q) NOT NULL", zTarget) ){ |
| 1074 | blob_appendf(p->pOut, "<a href=\"%s/timeline?c=%T\">", g.zTop, zTarget); |
| 1075 | }else if( strncmp(zTarget, "wiki:", 5)==0 |
| @@ -1077,11 +1099,11 @@ | |
| 1077 | zTarget += 5; |
| 1078 | blob_appendf(p->pOut, "<a href=\"%s/wiki?name=%T\">", g.zTop, zTarget); |
| 1079 | }else if( wiki_name_is_wellformed((const unsigned char *)zTarget) ){ |
| 1080 | blob_appendf(p->pOut, "<a href=\"%s/wiki?name=%T\">", g.zTop, zTarget); |
| 1081 | }else{ |
| 1082 | blob_appendf(p->pOut, "[bad-link: %h]", zTarget); |
| 1083 | zTerm = ""; |
| 1084 | } |
| 1085 | assert( strlen(zTerm)<nClose ); |
| 1086 | sqlite3_snprintf(nClose, zClose, "%s", zTerm); |
| 1087 | } |
| 1088 |
| --- src/wikiformat.c | |
| +++ src/wikiformat.c | |
| @@ -939,10 +939,26 @@ | |
| 939 | int n = strlen(z); |
| 940 | if( n<4 || n>UUID_SIZE ) return 0; |
| 941 | if( !validate16(z, n) ) return 0; |
| 942 | return 1; |
| 943 | } |
| 944 | |
| 945 | /* |
| 946 | ** Return TRUE if a UUID corresponds to an artifact in this |
| 947 | ** repository. |
| 948 | */ |
| 949 | static int in_this_repo(const char *zUuid){ |
| 950 | static Stmt q; |
| 951 | int rc; |
| 952 | db_static_prepare(&q, |
| 953 | "SELECT 1 FROM blob WHERE uuid>=:u AND +uuid GLOB (:u || '*')" |
| 954 | ); |
| 955 | db_bind_text(&q, ":u", zUuid); |
| 956 | rc = db_step(&q); |
| 957 | db_reset(&q); |
| 958 | return rc==SQLITE_ROW; |
| 959 | } |
| 960 | |
| 961 | /* |
| 962 | ** zTarget is guaranteed to be a UUID. It might be the UUID of a ticket. |
| 963 | ** If it is, store in *pClosed a true or false depending on whether or not |
| 964 | ** the ticket is closed and return true. If zTarget |
| @@ -1040,36 +1056,42 @@ | |
| 1056 | }else{ |
| 1057 | zTerm = ""; |
| 1058 | } |
| 1059 | }else if( is_valid_uuid(zTarget) ){ |
| 1060 | int isClosed = 0; |
| 1061 | if( !in_this_repo(zTarget) ){ |
| 1062 | blob_appendf(p->pOut, "<span class=\"brokenlink\">[", zTarget); |
| 1063 | zTerm = "]</span>"; |
| 1064 | }else if( is_ticket(zTarget, &isClosed) ){ |
| 1065 | /* Special display processing for tickets. Display the hyperlink |
| 1066 | ** as crossed out if the ticket is closed. |
| 1067 | */ |
| 1068 | if( isClosed ){ |
| 1069 | if( g.okHistory ){ |
| 1070 | blob_appendf(p->pOut, |
| 1071 | "<a href=\"%s/info/%s\"><span class=\"wikiTagCancelled\">[", |
| 1072 | g.zTop, zTarget |
| 1073 | ); |
| 1074 | zTerm = "]</span></a>"; |
| 1075 | }else{ |
| 1076 | blob_appendf(p->pOut,"<span class=\"wikiTagCancelled\">["); |
| 1077 | zTerm = "]</span>"; |
| 1078 | } |
| 1079 | }else{ |
| 1080 | if( g.okHistory ){ |
| 1081 | blob_appendf(p->pOut,"<a href=\"%s/info/%s\">[", |
| 1082 | g.zTop, zTarget |
| 1083 | ); |
| 1084 | zTerm = "]</a>"; |
| 1085 | }else{ |
| 1086 | blob_appendf(p->pOut, "["); |
| 1087 | zTerm = "]"; |
| 1088 | } |
| 1089 | } |
| 1090 | }else if( g.okHistory ){ |
| 1091 | blob_appendf(p->pOut, "<a href=\"%s/info/%s\">[", g.zTop, zTarget); |
| 1092 | zTerm = "]</a>"; |
| 1093 | } |
| 1094 | }else if( strlen(zTarget)>=10 && fossil_isdigit(zTarget[0]) && zTarget[4]=='-' |
| 1095 | && db_int(0, "SELECT datetime(%Q) NOT NULL", zTarget) ){ |
| 1096 | blob_appendf(p->pOut, "<a href=\"%s/timeline?c=%T\">", g.zTop, zTarget); |
| 1097 | }else if( strncmp(zTarget, "wiki:", 5)==0 |
| @@ -1077,11 +1099,11 @@ | |
| 1099 | zTarget += 5; |
| 1100 | blob_appendf(p->pOut, "<a href=\"%s/wiki?name=%T\">", g.zTop, zTarget); |
| 1101 | }else if( wiki_name_is_wellformed((const unsigned char *)zTarget) ){ |
| 1102 | blob_appendf(p->pOut, "<a href=\"%s/wiki?name=%T\">", g.zTop, zTarget); |
| 1103 | }else{ |
| 1104 | blob_appendf(p->pOut, "<span class=\"brokenlink\">[%h]</span>", zTarget); |
| 1105 | zTerm = ""; |
| 1106 | } |
| 1107 | assert( strlen(zTerm)<nClose ); |
| 1108 | sqlite3_snprintf(nClose, zClose, "%s", zTerm); |
| 1109 | } |
| 1110 |