Fossil SCM
Add the "brief" query parameter to the "artifact" page, to shorten sometimes lengthy descriptions of the artifact.
Commit
0ac4cead8d55805b73751e67fb9eb5f4e6ecfa9b
Parent
119cc97040a4e3d…
1 file changed
+46
-16
+46
-16
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -1111,10 +1111,16 @@ | ||
| 1111 | 1111 | #define OBJTYPE_ATTACHMENT 0x0010 |
| 1112 | 1112 | #define OBJTYPE_EVENT 0x0020 |
| 1113 | 1113 | #define OBJTYPE_TAG 0x0040 |
| 1114 | 1114 | #define OBJTYPE_SYMLINK 0x0080 |
| 1115 | 1115 | #define OBJTYPE_EXE 0x0100 |
| 1116 | + | |
| 1117 | +/* | |
| 1118 | +** Possible flags for the second parameter to | |
| 1119 | +** object_description() | |
| 1120 | +*/ | |
| 1121 | +#define OBJDESC_BRIEF 0x0001 /* Less detail */ | |
| 1116 | 1122 | #endif |
| 1117 | 1123 | |
| 1118 | 1124 | /* |
| 1119 | 1125 | ** Write a description of an object to the www reply. |
| 1120 | 1126 | ** |
| @@ -1130,19 +1136,19 @@ | ||
| 1130 | 1136 | ** * date of check-in |
| 1131 | 1137 | ** * Comment & user |
| 1132 | 1138 | */ |
| 1133 | 1139 | int object_description( |
| 1134 | 1140 | int rid, /* The artifact ID */ |
| 1135 | - int linkToView, /* Add viewer link if true */ | |
| 1141 | + u32 objdescFlags, /* Flags to control display */ | |
| 1136 | 1142 | Blob *pDownloadName /* Fill with an appropriate download name */ |
| 1137 | 1143 | ){ |
| 1138 | 1144 | Stmt q; |
| 1139 | 1145 | int cnt = 0; |
| 1140 | 1146 | int nWiki = 0; |
| 1141 | 1147 | int objType = 0; |
| 1142 | 1148 | char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1143 | - | |
| 1149 | + int isBrief = (objdescFlags & OBJDESC_BRIEF)!=0; | |
| 1144 | 1150 | char *prevName = 0; |
| 1145 | 1151 | |
| 1146 | 1152 | db_prepare(&q, |
| 1147 | 1153 | "SELECT filename.name, datetime(event.mtime)," |
| 1148 | 1154 | " coalesce(event.ecomment,event.comment)," |
| @@ -1166,11 +1172,13 @@ | ||
| 1166 | 1172 | const char *zCom = db_column_text(&q, 2); |
| 1167 | 1173 | const char *zUser = db_column_text(&q, 3); |
| 1168 | 1174 | const char *zVers = db_column_text(&q, 4); |
| 1169 | 1175 | int mPerm = db_column_int(&q, 5); |
| 1170 | 1176 | const char *zBr = db_column_text(&q, 6); |
| 1171 | - if( !prevName || fossil_strcmp(zName, prevName) ) { | |
| 1177 | + int sameFilename = prevName!=0 && fossil_strcmp(zName,prevName)==0; | |
| 1178 | + if( sameFilename && isBrief ) continue; | |
| 1179 | + if( !sameFilename ){ | |
| 1172 | 1180 | if( prevName ) { |
| 1173 | 1181 | @ </ul> |
| 1174 | 1182 | } |
| 1175 | 1183 | if( mPerm==PERM_LNK ){ |
| 1176 | 1184 | @ <li>Symbolic link |
| @@ -1181,21 +1189,30 @@ | ||
| 1181 | 1189 | }else{ |
| 1182 | 1190 | @ <li>File |
| 1183 | 1191 | } |
| 1184 | 1192 | objType |= OBJTYPE_CONTENT; |
| 1185 | 1193 | @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 1186 | - @ <ul> | |
| 1194 | + if( !isBrief ){ | |
| 1195 | + @ <ul> | |
| 1196 | + } | |
| 1187 | 1197 | prevName = fossil_strdup(zName); |
| 1188 | 1198 | } |
| 1189 | - @ <li> | |
| 1190 | - hyperlink_to_date(zDate,""); | |
| 1191 | - @ - part of checkin | |
| 1192 | - hyperlink_to_uuid(zVers); | |
| 1199 | + if( isBrief ){ | |
| 1200 | + @ — from checkin | |
| 1201 | + hyperlink_to_uuid(zVers); | |
| 1202 | + @ at | |
| 1203 | + hyperlink_to_date(zDate,""); | |
| 1204 | + }else{ | |
| 1205 | + @ <li> | |
| 1206 | + hyperlink_to_date(zDate,""); | |
| 1207 | + @ — part of check-in | |
| 1208 | + hyperlink_to_uuid(zVers); | |
| 1209 | + } | |
| 1193 | 1210 | if( zBr && zBr[0] ){ |
| 1194 | 1211 | @ on branch %z(href("%R/timeline?r=%T",zBr))%h(zBr)</a> |
| 1195 | 1212 | } |
| 1196 | - @ - %!w(zCom) (user: | |
| 1213 | + @ — %!w(zCom) (user: | |
| 1197 | 1214 | hyperlink_to_user(zUser,zDate,")"); |
| 1198 | 1215 | if( g.perm.Hyperlink ){ |
| 1199 | 1216 | @ %z(href("%R/finfo?name=%T&ci=%s",zName,zVers))[ancestry]</a> |
| 1200 | 1217 | @ %z(href("%R/annotate?filename=%T&checkin=%s",zName,zVers)) |
| 1201 | 1218 | @ [annotate]</a> |
| @@ -1205,11 +1222,11 @@ | ||
| 1205 | 1222 | cnt++; |
| 1206 | 1223 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| 1207 | 1224 | blob_append(pDownloadName, zName, -1); |
| 1208 | 1225 | } |
| 1209 | 1226 | } |
| 1210 | - if( prevName ){ | |
| 1227 | + if( prevName && !isBrief ){ | |
| 1211 | 1228 | @ </ul> |
| 1212 | 1229 | } |
| 1213 | 1230 | @ </ul> |
| 1214 | 1231 | free(prevName); |
| 1215 | 1232 | db_finalize(&q); |
| @@ -1333,12 +1350,10 @@ | ||
| 1333 | 1350 | if( cnt==0 ){ |
| 1334 | 1351 | @ Control artifact. |
| 1335 | 1352 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| 1336 | 1353 | blob_appendf(pDownloadName, "%.10s.txt", zUuid); |
| 1337 | 1354 | } |
| 1338 | - }else if( linkToView && g.perm.Hyperlink ){ | |
| 1339 | - @ %z(href("%R/artifact/%s",zUuid))[view]</a> | |
| 1340 | 1355 | } |
| 1341 | 1356 | return objType; |
| 1342 | 1357 | } |
| 1343 | 1358 | |
| 1344 | 1359 | |
| @@ -1347,10 +1362,14 @@ | ||
| 1347 | 1362 | ** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN®ex=REGEX |
| 1348 | 1363 | ** |
| 1349 | 1364 | ** Two arguments, v1 and v2, identify the files to be diffed. Show the |
| 1350 | 1365 | ** difference between the two artifacts. Show diff side by side unless sbs |
| 1351 | 1366 | ** is 0. Generate plaintext if "patch" is present. |
| 1367 | +** | |
| 1368 | +** Additional parameters: | |
| 1369 | +** | |
| 1370 | +** brief Show less detail when describing artifacts | |
| 1352 | 1371 | */ |
| 1353 | 1372 | void diff_page(void){ |
| 1354 | 1373 | int v1, v2; |
| 1355 | 1374 | int isPatch; |
| 1356 | 1375 | int sideBySide; |
| @@ -1358,18 +1377,20 @@ | ||
| 1358 | 1377 | char *zV2; |
| 1359 | 1378 | const char *zRe; |
| 1360 | 1379 | const char *zW; /* URL param for ignoring whitespace */ |
| 1361 | 1380 | ReCompiled *pRe = 0; |
| 1362 | 1381 | u64 diffFlags; |
| 1382 | + u32 objdescFlags = 0; | |
| 1363 | 1383 | |
| 1364 | 1384 | login_check_credentials(); |
| 1365 | 1385 | if( !g.perm.Read ){ login_needed(); return; } |
| 1366 | 1386 | v1 = name_to_rid_www("v1"); |
| 1367 | 1387 | v2 = name_to_rid_www("v2"); |
| 1368 | 1388 | if( v1==0 || v2==0 ) fossil_redirect_home(); |
| 1369 | 1389 | zRe = P("regex"); |
| 1370 | 1390 | if( zRe ) re_compile(&pRe, zRe, 0); |
| 1391 | + if( P("brief")!=0 ) objdescFlags |= OBJDESC_BRIEF; | |
| 1371 | 1392 | isPatch = P("patch")!=0; |
| 1372 | 1393 | if( isPatch ){ |
| 1373 | 1394 | Blob c1, c2, *pOut; |
| 1374 | 1395 | pOut = cgi_output_blob(); |
| 1375 | 1396 | cgi_set_content_type("text/plain"); |
| @@ -1415,13 +1436,13 @@ | ||
| 1415 | 1436 | @ %z(href("%R/artifact/%s",zV1))[%S(zV1)]</a> To |
| 1416 | 1437 | @ %z(href("%R/artifact/%s",zV2))[%S(zV2)]</a>.</h2> |
| 1417 | 1438 | }else{ |
| 1418 | 1439 | @ <h2>Differences From |
| 1419 | 1440 | @ Artifact %z(href("%R/artifact/%s",zV1))[%S(zV1)]</a>:</h2> |
| 1420 | - object_description(v1, 0, 0); | |
| 1441 | + object_description(v1, objdescFlags, 0); | |
| 1421 | 1442 | @ <h2>To Artifact %z(href("%R/artifact/%s",zV2))[%S(zV2)]</a>:</h2> |
| 1422 | - object_description(v2, 0, 0); | |
| 1443 | + object_description(v2, objdescFlags, 0); | |
| 1423 | 1444 | } |
| 1424 | 1445 | if( pRe ){ |
| 1425 | 1446 | @ <b>Only differences that match regular expression "%h(zRe)" |
| 1426 | 1447 | @ are shown.</b> |
| 1427 | 1448 | } |
| @@ -1527,16 +1548,21 @@ | ||
| 1527 | 1548 | ** WEBPAGE: hexdump |
| 1528 | 1549 | ** URL: /hexdump?name=ARTIFACTID |
| 1529 | 1550 | ** |
| 1530 | 1551 | ** Show the complete content of a file identified by ARTIFACTID |
| 1531 | 1552 | ** as preformatted text. |
| 1553 | +** | |
| 1554 | +** Other parameters: | |
| 1555 | +** | |
| 1556 | +** brief Show less detail when describing the object | |
| 1532 | 1557 | */ |
| 1533 | 1558 | void hexdump_page(void){ |
| 1534 | 1559 | int rid; |
| 1535 | 1560 | Blob content; |
| 1536 | 1561 | Blob downloadName; |
| 1537 | 1562 | char *zUuid; |
| 1563 | + u32 objdescFlags = 0; | |
| 1538 | 1564 | |
| 1539 | 1565 | rid = name_to_rid_www("name"); |
| 1540 | 1566 | login_check_credentials(); |
| 1541 | 1567 | if( !g.perm.Read ){ login_needed(); return; } |
| 1542 | 1568 | if( rid==0 ) fossil_redirect_home(); |
| @@ -1556,11 +1582,12 @@ | ||
| 1556 | 1582 | @ <h2>Artifact %s(zUuid) (%d(rid)):</h2> |
| 1557 | 1583 | }else{ |
| 1558 | 1584 | @ <h2>Artifact %s(zUuid):</h2> |
| 1559 | 1585 | } |
| 1560 | 1586 | blob_zero(&downloadName); |
| 1561 | - object_description(rid, 0, &downloadName); | |
| 1587 | + if( P("brief")!=0 ) objdescFlags |= OBJDESC_BRIEF; | |
| 1588 | + object_description(rid, objdescFlags, &downloadName); | |
| 1562 | 1589 | style_submenu_element("Download", "Download", |
| 1563 | 1590 | "%s/raw/%T?name=%s", g.zTop, blob_str(&downloadName), zUuid); |
| 1564 | 1591 | @ <hr /> |
| 1565 | 1592 | content_get(rid, &content); |
| 1566 | 1593 | @ <blockquote><pre> |
| @@ -1690,10 +1717,11 @@ | ||
| 1690 | 1717 | ** Additional query parameters: |
| 1691 | 1718 | ** |
| 1692 | 1719 | ** ln - show line numbers |
| 1693 | 1720 | ** ln=N - highlight line number N |
| 1694 | 1721 | ** ln=M-N - highlight lines M through N inclusive |
| 1722 | +** brief - show less detail in the description | |
| 1695 | 1723 | ** |
| 1696 | 1724 | ** Show the complete content of a file identified by ARTIFACTID |
| 1697 | 1725 | ** as preformatted text. |
| 1698 | 1726 | */ |
| 1699 | 1727 | void artifact_page(void){ |
| @@ -1704,10 +1732,11 @@ | ||
| 1704 | 1732 | int renderAsWiki = 0; |
| 1705 | 1733 | int renderAsHtml = 0; |
| 1706 | 1734 | int objType; |
| 1707 | 1735 | int asText; |
| 1708 | 1736 | const char *zUuid; |
| 1737 | + u32 objdescFlags = 0; | |
| 1709 | 1738 | |
| 1710 | 1739 | if( P("ci") && P("filename") ){ |
| 1711 | 1740 | rid = artifact_from_ci_and_filename_www(); |
| 1712 | 1741 | } |
| 1713 | 1742 | if( rid==0 ){ |
| @@ -1725,19 +1754,20 @@ | ||
| 1725 | 1754 | }else{ |
| 1726 | 1755 | style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", |
| 1727 | 1756 | g.zTop, zUuid); |
| 1728 | 1757 | } |
| 1729 | 1758 | } |
| 1759 | + if( P("brief")!=0 ) objdescFlags |= OBJDESC_BRIEF; | |
| 1730 | 1760 | style_header("Artifact Content"); |
| 1731 | 1761 | zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1732 | 1762 | if( g.perm.Setup ){ |
| 1733 | 1763 | @ <h2>Artifact %s(zUuid) (%d(rid)):</h2> |
| 1734 | 1764 | }else{ |
| 1735 | 1765 | @ <h2>Artifact %s(zUuid):</h2> |
| 1736 | 1766 | } |
| 1737 | 1767 | blob_zero(&downloadName); |
| 1738 | - objType = object_description(rid, 0, &downloadName); | |
| 1768 | + objType = object_description(rid, objdescFlags, &downloadName); | |
| 1739 | 1769 | style_submenu_element("Download", "Download", |
| 1740 | 1770 | "%R/raw/%T?name=%s", blob_str(&downloadName), zUuid); |
| 1741 | 1771 | if( db_exists("SELECT 1 FROM mlink WHERE fid=%d", rid) ){ |
| 1742 | 1772 | style_submenu_element("Checkins Using", "Checkins Using", |
| 1743 | 1773 | "%R/timeline?n=200&uf=%s",zUuid); |
| 1744 | 1774 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -1111,10 +1111,16 @@ | |
| 1111 | #define OBJTYPE_ATTACHMENT 0x0010 |
| 1112 | #define OBJTYPE_EVENT 0x0020 |
| 1113 | #define OBJTYPE_TAG 0x0040 |
| 1114 | #define OBJTYPE_SYMLINK 0x0080 |
| 1115 | #define OBJTYPE_EXE 0x0100 |
| 1116 | #endif |
| 1117 | |
| 1118 | /* |
| 1119 | ** Write a description of an object to the www reply. |
| 1120 | ** |
| @@ -1130,19 +1136,19 @@ | |
| 1130 | ** * date of check-in |
| 1131 | ** * Comment & user |
| 1132 | */ |
| 1133 | int object_description( |
| 1134 | int rid, /* The artifact ID */ |
| 1135 | int linkToView, /* Add viewer link if true */ |
| 1136 | Blob *pDownloadName /* Fill with an appropriate download name */ |
| 1137 | ){ |
| 1138 | Stmt q; |
| 1139 | int cnt = 0; |
| 1140 | int nWiki = 0; |
| 1141 | int objType = 0; |
| 1142 | char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1143 | |
| 1144 | char *prevName = 0; |
| 1145 | |
| 1146 | db_prepare(&q, |
| 1147 | "SELECT filename.name, datetime(event.mtime)," |
| 1148 | " coalesce(event.ecomment,event.comment)," |
| @@ -1166,11 +1172,13 @@ | |
| 1166 | const char *zCom = db_column_text(&q, 2); |
| 1167 | const char *zUser = db_column_text(&q, 3); |
| 1168 | const char *zVers = db_column_text(&q, 4); |
| 1169 | int mPerm = db_column_int(&q, 5); |
| 1170 | const char *zBr = db_column_text(&q, 6); |
| 1171 | if( !prevName || fossil_strcmp(zName, prevName) ) { |
| 1172 | if( prevName ) { |
| 1173 | @ </ul> |
| 1174 | } |
| 1175 | if( mPerm==PERM_LNK ){ |
| 1176 | @ <li>Symbolic link |
| @@ -1181,21 +1189,30 @@ | |
| 1181 | }else{ |
| 1182 | @ <li>File |
| 1183 | } |
| 1184 | objType |= OBJTYPE_CONTENT; |
| 1185 | @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 1186 | @ <ul> |
| 1187 | prevName = fossil_strdup(zName); |
| 1188 | } |
| 1189 | @ <li> |
| 1190 | hyperlink_to_date(zDate,""); |
| 1191 | @ - part of checkin |
| 1192 | hyperlink_to_uuid(zVers); |
| 1193 | if( zBr && zBr[0] ){ |
| 1194 | @ on branch %z(href("%R/timeline?r=%T",zBr))%h(zBr)</a> |
| 1195 | } |
| 1196 | @ - %!w(zCom) (user: |
| 1197 | hyperlink_to_user(zUser,zDate,")"); |
| 1198 | if( g.perm.Hyperlink ){ |
| 1199 | @ %z(href("%R/finfo?name=%T&ci=%s",zName,zVers))[ancestry]</a> |
| 1200 | @ %z(href("%R/annotate?filename=%T&checkin=%s",zName,zVers)) |
| 1201 | @ [annotate]</a> |
| @@ -1205,11 +1222,11 @@ | |
| 1205 | cnt++; |
| 1206 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| 1207 | blob_append(pDownloadName, zName, -1); |
| 1208 | } |
| 1209 | } |
| 1210 | if( prevName ){ |
| 1211 | @ </ul> |
| 1212 | } |
| 1213 | @ </ul> |
| 1214 | free(prevName); |
| 1215 | db_finalize(&q); |
| @@ -1333,12 +1350,10 @@ | |
| 1333 | if( cnt==0 ){ |
| 1334 | @ Control artifact. |
| 1335 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| 1336 | blob_appendf(pDownloadName, "%.10s.txt", zUuid); |
| 1337 | } |
| 1338 | }else if( linkToView && g.perm.Hyperlink ){ |
| 1339 | @ %z(href("%R/artifact/%s",zUuid))[view]</a> |
| 1340 | } |
| 1341 | return objType; |
| 1342 | } |
| 1343 | |
| 1344 | |
| @@ -1347,10 +1362,14 @@ | |
| 1347 | ** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN®ex=REGEX |
| 1348 | ** |
| 1349 | ** Two arguments, v1 and v2, identify the files to be diffed. Show the |
| 1350 | ** difference between the two artifacts. Show diff side by side unless sbs |
| 1351 | ** is 0. Generate plaintext if "patch" is present. |
| 1352 | */ |
| 1353 | void diff_page(void){ |
| 1354 | int v1, v2; |
| 1355 | int isPatch; |
| 1356 | int sideBySide; |
| @@ -1358,18 +1377,20 @@ | |
| 1358 | char *zV2; |
| 1359 | const char *zRe; |
| 1360 | const char *zW; /* URL param for ignoring whitespace */ |
| 1361 | ReCompiled *pRe = 0; |
| 1362 | u64 diffFlags; |
| 1363 | |
| 1364 | login_check_credentials(); |
| 1365 | if( !g.perm.Read ){ login_needed(); return; } |
| 1366 | v1 = name_to_rid_www("v1"); |
| 1367 | v2 = name_to_rid_www("v2"); |
| 1368 | if( v1==0 || v2==0 ) fossil_redirect_home(); |
| 1369 | zRe = P("regex"); |
| 1370 | if( zRe ) re_compile(&pRe, zRe, 0); |
| 1371 | isPatch = P("patch")!=0; |
| 1372 | if( isPatch ){ |
| 1373 | Blob c1, c2, *pOut; |
| 1374 | pOut = cgi_output_blob(); |
| 1375 | cgi_set_content_type("text/plain"); |
| @@ -1415,13 +1436,13 @@ | |
| 1415 | @ %z(href("%R/artifact/%s",zV1))[%S(zV1)]</a> To |
| 1416 | @ %z(href("%R/artifact/%s",zV2))[%S(zV2)]</a>.</h2> |
| 1417 | }else{ |
| 1418 | @ <h2>Differences From |
| 1419 | @ Artifact %z(href("%R/artifact/%s",zV1))[%S(zV1)]</a>:</h2> |
| 1420 | object_description(v1, 0, 0); |
| 1421 | @ <h2>To Artifact %z(href("%R/artifact/%s",zV2))[%S(zV2)]</a>:</h2> |
| 1422 | object_description(v2, 0, 0); |
| 1423 | } |
| 1424 | if( pRe ){ |
| 1425 | @ <b>Only differences that match regular expression "%h(zRe)" |
| 1426 | @ are shown.</b> |
| 1427 | } |
| @@ -1527,16 +1548,21 @@ | |
| 1527 | ** WEBPAGE: hexdump |
| 1528 | ** URL: /hexdump?name=ARTIFACTID |
| 1529 | ** |
| 1530 | ** Show the complete content of a file identified by ARTIFACTID |
| 1531 | ** as preformatted text. |
| 1532 | */ |
| 1533 | void hexdump_page(void){ |
| 1534 | int rid; |
| 1535 | Blob content; |
| 1536 | Blob downloadName; |
| 1537 | char *zUuid; |
| 1538 | |
| 1539 | rid = name_to_rid_www("name"); |
| 1540 | login_check_credentials(); |
| 1541 | if( !g.perm.Read ){ login_needed(); return; } |
| 1542 | if( rid==0 ) fossil_redirect_home(); |
| @@ -1556,11 +1582,12 @@ | |
| 1556 | @ <h2>Artifact %s(zUuid) (%d(rid)):</h2> |
| 1557 | }else{ |
| 1558 | @ <h2>Artifact %s(zUuid):</h2> |
| 1559 | } |
| 1560 | blob_zero(&downloadName); |
| 1561 | object_description(rid, 0, &downloadName); |
| 1562 | style_submenu_element("Download", "Download", |
| 1563 | "%s/raw/%T?name=%s", g.zTop, blob_str(&downloadName), zUuid); |
| 1564 | @ <hr /> |
| 1565 | content_get(rid, &content); |
| 1566 | @ <blockquote><pre> |
| @@ -1690,10 +1717,11 @@ | |
| 1690 | ** Additional query parameters: |
| 1691 | ** |
| 1692 | ** ln - show line numbers |
| 1693 | ** ln=N - highlight line number N |
| 1694 | ** ln=M-N - highlight lines M through N inclusive |
| 1695 | ** |
| 1696 | ** Show the complete content of a file identified by ARTIFACTID |
| 1697 | ** as preformatted text. |
| 1698 | */ |
| 1699 | void artifact_page(void){ |
| @@ -1704,10 +1732,11 @@ | |
| 1704 | int renderAsWiki = 0; |
| 1705 | int renderAsHtml = 0; |
| 1706 | int objType; |
| 1707 | int asText; |
| 1708 | const char *zUuid; |
| 1709 | |
| 1710 | if( P("ci") && P("filename") ){ |
| 1711 | rid = artifact_from_ci_and_filename_www(); |
| 1712 | } |
| 1713 | if( rid==0 ){ |
| @@ -1725,19 +1754,20 @@ | |
| 1725 | }else{ |
| 1726 | style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", |
| 1727 | g.zTop, zUuid); |
| 1728 | } |
| 1729 | } |
| 1730 | style_header("Artifact Content"); |
| 1731 | zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1732 | if( g.perm.Setup ){ |
| 1733 | @ <h2>Artifact %s(zUuid) (%d(rid)):</h2> |
| 1734 | }else{ |
| 1735 | @ <h2>Artifact %s(zUuid):</h2> |
| 1736 | } |
| 1737 | blob_zero(&downloadName); |
| 1738 | objType = object_description(rid, 0, &downloadName); |
| 1739 | style_submenu_element("Download", "Download", |
| 1740 | "%R/raw/%T?name=%s", blob_str(&downloadName), zUuid); |
| 1741 | if( db_exists("SELECT 1 FROM mlink WHERE fid=%d", rid) ){ |
| 1742 | style_submenu_element("Checkins Using", "Checkins Using", |
| 1743 | "%R/timeline?n=200&uf=%s",zUuid); |
| 1744 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -1111,10 +1111,16 @@ | |
| 1111 | #define OBJTYPE_ATTACHMENT 0x0010 |
| 1112 | #define OBJTYPE_EVENT 0x0020 |
| 1113 | #define OBJTYPE_TAG 0x0040 |
| 1114 | #define OBJTYPE_SYMLINK 0x0080 |
| 1115 | #define OBJTYPE_EXE 0x0100 |
| 1116 | |
| 1117 | /* |
| 1118 | ** Possible flags for the second parameter to |
| 1119 | ** object_description() |
| 1120 | */ |
| 1121 | #define OBJDESC_BRIEF 0x0001 /* Less detail */ |
| 1122 | #endif |
| 1123 | |
| 1124 | /* |
| 1125 | ** Write a description of an object to the www reply. |
| 1126 | ** |
| @@ -1130,19 +1136,19 @@ | |
| 1136 | ** * date of check-in |
| 1137 | ** * Comment & user |
| 1138 | */ |
| 1139 | int object_description( |
| 1140 | int rid, /* The artifact ID */ |
| 1141 | u32 objdescFlags, /* Flags to control display */ |
| 1142 | Blob *pDownloadName /* Fill with an appropriate download name */ |
| 1143 | ){ |
| 1144 | Stmt q; |
| 1145 | int cnt = 0; |
| 1146 | int nWiki = 0; |
| 1147 | int objType = 0; |
| 1148 | char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1149 | int isBrief = (objdescFlags & OBJDESC_BRIEF)!=0; |
| 1150 | char *prevName = 0; |
| 1151 | |
| 1152 | db_prepare(&q, |
| 1153 | "SELECT filename.name, datetime(event.mtime)," |
| 1154 | " coalesce(event.ecomment,event.comment)," |
| @@ -1166,11 +1172,13 @@ | |
| 1172 | const char *zCom = db_column_text(&q, 2); |
| 1173 | const char *zUser = db_column_text(&q, 3); |
| 1174 | const char *zVers = db_column_text(&q, 4); |
| 1175 | int mPerm = db_column_int(&q, 5); |
| 1176 | const char *zBr = db_column_text(&q, 6); |
| 1177 | int sameFilename = prevName!=0 && fossil_strcmp(zName,prevName)==0; |
| 1178 | if( sameFilename && isBrief ) continue; |
| 1179 | if( !sameFilename ){ |
| 1180 | if( prevName ) { |
| 1181 | @ </ul> |
| 1182 | } |
| 1183 | if( mPerm==PERM_LNK ){ |
| 1184 | @ <li>Symbolic link |
| @@ -1181,21 +1189,30 @@ | |
| 1189 | }else{ |
| 1190 | @ <li>File |
| 1191 | } |
| 1192 | objType |= OBJTYPE_CONTENT; |
| 1193 | @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 1194 | if( !isBrief ){ |
| 1195 | @ <ul> |
| 1196 | } |
| 1197 | prevName = fossil_strdup(zName); |
| 1198 | } |
| 1199 | if( isBrief ){ |
| 1200 | @ — from checkin |
| 1201 | hyperlink_to_uuid(zVers); |
| 1202 | @ at |
| 1203 | hyperlink_to_date(zDate,""); |
| 1204 | }else{ |
| 1205 | @ <li> |
| 1206 | hyperlink_to_date(zDate,""); |
| 1207 | @ — part of check-in |
| 1208 | hyperlink_to_uuid(zVers); |
| 1209 | } |
| 1210 | if( zBr && zBr[0] ){ |
| 1211 | @ on branch %z(href("%R/timeline?r=%T",zBr))%h(zBr)</a> |
| 1212 | } |
| 1213 | @ — %!w(zCom) (user: |
| 1214 | hyperlink_to_user(zUser,zDate,")"); |
| 1215 | if( g.perm.Hyperlink ){ |
| 1216 | @ %z(href("%R/finfo?name=%T&ci=%s",zName,zVers))[ancestry]</a> |
| 1217 | @ %z(href("%R/annotate?filename=%T&checkin=%s",zName,zVers)) |
| 1218 | @ [annotate]</a> |
| @@ -1205,11 +1222,11 @@ | |
| 1222 | cnt++; |
| 1223 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| 1224 | blob_append(pDownloadName, zName, -1); |
| 1225 | } |
| 1226 | } |
| 1227 | if( prevName && !isBrief ){ |
| 1228 | @ </ul> |
| 1229 | } |
| 1230 | @ </ul> |
| 1231 | free(prevName); |
| 1232 | db_finalize(&q); |
| @@ -1333,12 +1350,10 @@ | |
| 1350 | if( cnt==0 ){ |
| 1351 | @ Control artifact. |
| 1352 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| 1353 | blob_appendf(pDownloadName, "%.10s.txt", zUuid); |
| 1354 | } |
| 1355 | } |
| 1356 | return objType; |
| 1357 | } |
| 1358 | |
| 1359 | |
| @@ -1347,10 +1362,14 @@ | |
| 1362 | ** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN®ex=REGEX |
| 1363 | ** |
| 1364 | ** Two arguments, v1 and v2, identify the files to be diffed. Show the |
| 1365 | ** difference between the two artifacts. Show diff side by side unless sbs |
| 1366 | ** is 0. Generate plaintext if "patch" is present. |
| 1367 | ** |
| 1368 | ** Additional parameters: |
| 1369 | ** |
| 1370 | ** brief Show less detail when describing artifacts |
| 1371 | */ |
| 1372 | void diff_page(void){ |
| 1373 | int v1, v2; |
| 1374 | int isPatch; |
| 1375 | int sideBySide; |
| @@ -1358,18 +1377,20 @@ | |
| 1377 | char *zV2; |
| 1378 | const char *zRe; |
| 1379 | const char *zW; /* URL param for ignoring whitespace */ |
| 1380 | ReCompiled *pRe = 0; |
| 1381 | u64 diffFlags; |
| 1382 | u32 objdescFlags = 0; |
| 1383 | |
| 1384 | login_check_credentials(); |
| 1385 | if( !g.perm.Read ){ login_needed(); return; } |
| 1386 | v1 = name_to_rid_www("v1"); |
| 1387 | v2 = name_to_rid_www("v2"); |
| 1388 | if( v1==0 || v2==0 ) fossil_redirect_home(); |
| 1389 | zRe = P("regex"); |
| 1390 | if( zRe ) re_compile(&pRe, zRe, 0); |
| 1391 | if( P("brief")!=0 ) objdescFlags |= OBJDESC_BRIEF; |
| 1392 | isPatch = P("patch")!=0; |
| 1393 | if( isPatch ){ |
| 1394 | Blob c1, c2, *pOut; |
| 1395 | pOut = cgi_output_blob(); |
| 1396 | cgi_set_content_type("text/plain"); |
| @@ -1415,13 +1436,13 @@ | |
| 1436 | @ %z(href("%R/artifact/%s",zV1))[%S(zV1)]</a> To |
| 1437 | @ %z(href("%R/artifact/%s",zV2))[%S(zV2)]</a>.</h2> |
| 1438 | }else{ |
| 1439 | @ <h2>Differences From |
| 1440 | @ Artifact %z(href("%R/artifact/%s",zV1))[%S(zV1)]</a>:</h2> |
| 1441 | object_description(v1, objdescFlags, 0); |
| 1442 | @ <h2>To Artifact %z(href("%R/artifact/%s",zV2))[%S(zV2)]</a>:</h2> |
| 1443 | object_description(v2, objdescFlags, 0); |
| 1444 | } |
| 1445 | if( pRe ){ |
| 1446 | @ <b>Only differences that match regular expression "%h(zRe)" |
| 1447 | @ are shown.</b> |
| 1448 | } |
| @@ -1527,16 +1548,21 @@ | |
| 1548 | ** WEBPAGE: hexdump |
| 1549 | ** URL: /hexdump?name=ARTIFACTID |
| 1550 | ** |
| 1551 | ** Show the complete content of a file identified by ARTIFACTID |
| 1552 | ** as preformatted text. |
| 1553 | ** |
| 1554 | ** Other parameters: |
| 1555 | ** |
| 1556 | ** brief Show less detail when describing the object |
| 1557 | */ |
| 1558 | void hexdump_page(void){ |
| 1559 | int rid; |
| 1560 | Blob content; |
| 1561 | Blob downloadName; |
| 1562 | char *zUuid; |
| 1563 | u32 objdescFlags = 0; |
| 1564 | |
| 1565 | rid = name_to_rid_www("name"); |
| 1566 | login_check_credentials(); |
| 1567 | if( !g.perm.Read ){ login_needed(); return; } |
| 1568 | if( rid==0 ) fossil_redirect_home(); |
| @@ -1556,11 +1582,12 @@ | |
| 1582 | @ <h2>Artifact %s(zUuid) (%d(rid)):</h2> |
| 1583 | }else{ |
| 1584 | @ <h2>Artifact %s(zUuid):</h2> |
| 1585 | } |
| 1586 | blob_zero(&downloadName); |
| 1587 | if( P("brief")!=0 ) objdescFlags |= OBJDESC_BRIEF; |
| 1588 | object_description(rid, objdescFlags, &downloadName); |
| 1589 | style_submenu_element("Download", "Download", |
| 1590 | "%s/raw/%T?name=%s", g.zTop, blob_str(&downloadName), zUuid); |
| 1591 | @ <hr /> |
| 1592 | content_get(rid, &content); |
| 1593 | @ <blockquote><pre> |
| @@ -1690,10 +1717,11 @@ | |
| 1717 | ** Additional query parameters: |
| 1718 | ** |
| 1719 | ** ln - show line numbers |
| 1720 | ** ln=N - highlight line number N |
| 1721 | ** ln=M-N - highlight lines M through N inclusive |
| 1722 | ** brief - show less detail in the description |
| 1723 | ** |
| 1724 | ** Show the complete content of a file identified by ARTIFACTID |
| 1725 | ** as preformatted text. |
| 1726 | */ |
| 1727 | void artifact_page(void){ |
| @@ -1704,10 +1732,11 @@ | |
| 1732 | int renderAsWiki = 0; |
| 1733 | int renderAsHtml = 0; |
| 1734 | int objType; |
| 1735 | int asText; |
| 1736 | const char *zUuid; |
| 1737 | u32 objdescFlags = 0; |
| 1738 | |
| 1739 | if( P("ci") && P("filename") ){ |
| 1740 | rid = artifact_from_ci_and_filename_www(); |
| 1741 | } |
| 1742 | if( rid==0 ){ |
| @@ -1725,19 +1754,20 @@ | |
| 1754 | }else{ |
| 1755 | style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", |
| 1756 | g.zTop, zUuid); |
| 1757 | } |
| 1758 | } |
| 1759 | if( P("brief")!=0 ) objdescFlags |= OBJDESC_BRIEF; |
| 1760 | style_header("Artifact Content"); |
| 1761 | zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1762 | if( g.perm.Setup ){ |
| 1763 | @ <h2>Artifact %s(zUuid) (%d(rid)):</h2> |
| 1764 | }else{ |
| 1765 | @ <h2>Artifact %s(zUuid):</h2> |
| 1766 | } |
| 1767 | blob_zero(&downloadName); |
| 1768 | objType = object_description(rid, objdescFlags, &downloadName); |
| 1769 | style_submenu_element("Download", "Download", |
| 1770 | "%R/raw/%T?name=%s", blob_str(&downloadName), zUuid); |
| 1771 | if( db_exists("SELECT 1 FROM mlink WHERE fid=%d", rid) ){ |
| 1772 | style_submenu_element("Checkins Using", "Checkins Using", |
| 1773 | "%R/timeline?n=200&uf=%s",zUuid); |
| 1774 |