Fossil SCM
On the Fossil repository screen list that comes up with commands like "fossil all ui", show the last modification time of each repo, and allow sorting by mtime.
Commit
f2231ba6684157db99db5f1e5098c1e45f7a1196b34d29e8ab1ac404ea6feb58
Parent
209542742a6fef1…
1 file changed
+47
-7
+47
-7
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -1284,46 +1284,86 @@ | ||
| 1284 | 1284 | @ </head> |
| 1285 | 1285 | @ <body> |
| 1286 | 1286 | n = db_int(0, "SELECT count(*) FROM sfile"); |
| 1287 | 1287 | if( n>0 ){ |
| 1288 | 1288 | Stmt q; |
| 1289 | - @ <h1>Available Repositories:</h1> | |
| 1290 | - @ <ol> | |
| 1289 | + sqlite3_int64 iNow, iMTime; | |
| 1290 | + @ <h1 align="center">Fossil Repositories</h1> | |
| 1291 | + @ <table border="0" class="sortable" data-init-sort="1" \ | |
| 1292 | + @ data-column-types="tnk"><thead> | |
| 1293 | + @ <tr><th>Filename<th width="20"><th>Last Modified</tr> | |
| 1294 | + @ </thead><tbody> | |
| 1291 | 1295 | db_prepare(&q, "SELECT pathname" |
| 1292 | 1296 | " FROM sfile ORDER BY pathname COLLATE nocase;"); |
| 1297 | + iNow = db_int64(0, "SELECT strftime('%%s','now')"); | |
| 1293 | 1298 | while( db_step(&q)==SQLITE_ROW ){ |
| 1294 | 1299 | const char *zName = db_column_text(&q, 0); |
| 1295 | 1300 | int nName = (int)strlen(zName); |
| 1296 | 1301 | char *zUrl; |
| 1302 | + char *zAge; | |
| 1303 | + char *zFull; | |
| 1297 | 1304 | if( nName<7 ) continue; |
| 1298 | 1305 | zUrl = sqlite3_mprintf("%.*s", nName-7, zName); |
| 1306 | + if( allRepo ){ | |
| 1307 | + zFull = mprintf("/%s", zName); | |
| 1308 | + }else{ | |
| 1309 | + zFull = mprintf("%s/%s", g.zRepositoryName, zName); | |
| 1310 | + } | |
| 1311 | + iMTime = file_mtime(zFull, ExtFILE); | |
| 1312 | + fossil_free(zFull); | |
| 1313 | + if( iMTime<=0 ){ | |
| 1314 | + zAge = mprintf("..."); | |
| 1315 | + }else{ | |
| 1316 | + zAge = human_readable_age((iNow - iMTime)/86400.0); | |
| 1317 | + } | |
| 1299 | 1318 | if( sqlite3_strglob("*.fossil", zName)!=0 ){ |
| 1300 | 1319 | /* The "fossil server DIRECTORY" and "fossil ui DIRECTORY" commands |
| 1301 | 1320 | ** do not work for repositories whose names do not end in ".fossil". |
| 1302 | 1321 | ** So do not hyperlink those cases. */ |
| 1303 | - @ <li>%h(zName)</li> | |
| 1322 | + @ <tr><td>%h(zName) | |
| 1304 | 1323 | } else if( sqlite3_strglob("*/.*", zName)==0 ){ |
| 1305 | 1324 | /* Do not show hidden repos */ |
| 1306 | - @ <li>%h(zName) (hidden)</li> | |
| 1325 | + @ <tr><td>%h(zName) (hidden) | |
| 1307 | 1326 | } else if( allRepo && sqlite3_strglob("[a-zA-Z]:/?*", zName)!=0 ){ |
| 1308 | - @ <li><a href="%R/%T(zUrl)/home" target="_blank">/%h(zName)</a></li> | |
| 1327 | + @ <tr><td><a href="%R/%T(zUrl)/home" target="_blank">/%h(zName)</a> | |
| 1309 | 1328 | }else{ |
| 1310 | - @ <li><a href="%R/%T(zUrl)/home" target="_blank">%h(zName)</a></li> | |
| 1329 | + @ <tr><td><a href="%R/%T(zUrl)/home" target="_blank">%h(zName)</a> | |
| 1311 | 1330 | } |
| 1331 | + @ <td></td><td data-sortkey='%010llx(iNow - iMTime)'>%h(zAge)</tr> | |
| 1332 | + fossil_free(zAge); | |
| 1312 | 1333 | sqlite3_free(zUrl); |
| 1313 | 1334 | } |
| 1314 | - @ </ol> | |
| 1335 | + @ </tbody></table> | |
| 1315 | 1336 | }else{ |
| 1316 | 1337 | @ <h1>No Repositories Found</h1> |
| 1317 | 1338 | } |
| 1339 | + @ <script>%s(builtin_text("sorttable.js"))</script> | |
| 1318 | 1340 | @ </body> |
| 1319 | 1341 | @ </html> |
| 1320 | 1342 | cgi_reply(); |
| 1321 | 1343 | sqlite3_close(g.db); |
| 1322 | 1344 | g.db = 0; |
| 1323 | 1345 | return n; |
| 1324 | 1346 | } |
| 1347 | + | |
| 1348 | +/* | |
| 1349 | +** COMMAND: test-list-page | |
| 1350 | +** | |
| 1351 | +** Usage: %fossil test-list-page DIRECTORY | |
| 1352 | +** | |
| 1353 | +** Show all repositories underneath DIRECTORY. Or if DIRECTORY is "/" | |
| 1354 | +** show all repositories in the ~/.fossil file. | |
| 1355 | +*/ | |
| 1356 | +void test_list_page(void){ | |
| 1357 | + if( g.argc<3 ){ | |
| 1358 | + g.zRepositoryName = "/"; | |
| 1359 | + }else{ | |
| 1360 | + g.zRepositoryName = g.argv[2]; | |
| 1361 | + } | |
| 1362 | + g.httpOut = stdout; | |
| 1363 | + repo_list_page(); | |
| 1364 | +} | |
| 1325 | 1365 | |
| 1326 | 1366 | /* |
| 1327 | 1367 | ** Preconditions: |
| 1328 | 1368 | ** |
| 1329 | 1369 | ** * Environment variables are set up according to the CGI standard. |
| 1330 | 1370 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -1284,46 +1284,86 @@ | |
| 1284 | @ </head> |
| 1285 | @ <body> |
| 1286 | n = db_int(0, "SELECT count(*) FROM sfile"); |
| 1287 | if( n>0 ){ |
| 1288 | Stmt q; |
| 1289 | @ <h1>Available Repositories:</h1> |
| 1290 | @ <ol> |
| 1291 | db_prepare(&q, "SELECT pathname" |
| 1292 | " FROM sfile ORDER BY pathname COLLATE nocase;"); |
| 1293 | while( db_step(&q)==SQLITE_ROW ){ |
| 1294 | const char *zName = db_column_text(&q, 0); |
| 1295 | int nName = (int)strlen(zName); |
| 1296 | char *zUrl; |
| 1297 | if( nName<7 ) continue; |
| 1298 | zUrl = sqlite3_mprintf("%.*s", nName-7, zName); |
| 1299 | if( sqlite3_strglob("*.fossil", zName)!=0 ){ |
| 1300 | /* The "fossil server DIRECTORY" and "fossil ui DIRECTORY" commands |
| 1301 | ** do not work for repositories whose names do not end in ".fossil". |
| 1302 | ** So do not hyperlink those cases. */ |
| 1303 | @ <li>%h(zName)</li> |
| 1304 | } else if( sqlite3_strglob("*/.*", zName)==0 ){ |
| 1305 | /* Do not show hidden repos */ |
| 1306 | @ <li>%h(zName) (hidden)</li> |
| 1307 | } else if( allRepo && sqlite3_strglob("[a-zA-Z]:/?*", zName)!=0 ){ |
| 1308 | @ <li><a href="%R/%T(zUrl)/home" target="_blank">/%h(zName)</a></li> |
| 1309 | }else{ |
| 1310 | @ <li><a href="%R/%T(zUrl)/home" target="_blank">%h(zName)</a></li> |
| 1311 | } |
| 1312 | sqlite3_free(zUrl); |
| 1313 | } |
| 1314 | @ </ol> |
| 1315 | }else{ |
| 1316 | @ <h1>No Repositories Found</h1> |
| 1317 | } |
| 1318 | @ </body> |
| 1319 | @ </html> |
| 1320 | cgi_reply(); |
| 1321 | sqlite3_close(g.db); |
| 1322 | g.db = 0; |
| 1323 | return n; |
| 1324 | } |
| 1325 | |
| 1326 | /* |
| 1327 | ** Preconditions: |
| 1328 | ** |
| 1329 | ** * Environment variables are set up according to the CGI standard. |
| 1330 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -1284,46 +1284,86 @@ | |
| 1284 | @ </head> |
| 1285 | @ <body> |
| 1286 | n = db_int(0, "SELECT count(*) FROM sfile"); |
| 1287 | if( n>0 ){ |
| 1288 | Stmt q; |
| 1289 | sqlite3_int64 iNow, iMTime; |
| 1290 | @ <h1 align="center">Fossil Repositories</h1> |
| 1291 | @ <table border="0" class="sortable" data-init-sort="1" \ |
| 1292 | @ data-column-types="tnk"><thead> |
| 1293 | @ <tr><th>Filename<th width="20"><th>Last Modified</tr> |
| 1294 | @ </thead><tbody> |
| 1295 | db_prepare(&q, "SELECT pathname" |
| 1296 | " FROM sfile ORDER BY pathname COLLATE nocase;"); |
| 1297 | iNow = db_int64(0, "SELECT strftime('%%s','now')"); |
| 1298 | while( db_step(&q)==SQLITE_ROW ){ |
| 1299 | const char *zName = db_column_text(&q, 0); |
| 1300 | int nName = (int)strlen(zName); |
| 1301 | char *zUrl; |
| 1302 | char *zAge; |
| 1303 | char *zFull; |
| 1304 | if( nName<7 ) continue; |
| 1305 | zUrl = sqlite3_mprintf("%.*s", nName-7, zName); |
| 1306 | if( allRepo ){ |
| 1307 | zFull = mprintf("/%s", zName); |
| 1308 | }else{ |
| 1309 | zFull = mprintf("%s/%s", g.zRepositoryName, zName); |
| 1310 | } |
| 1311 | iMTime = file_mtime(zFull, ExtFILE); |
| 1312 | fossil_free(zFull); |
| 1313 | if( iMTime<=0 ){ |
| 1314 | zAge = mprintf("..."); |
| 1315 | }else{ |
| 1316 | zAge = human_readable_age((iNow - iMTime)/86400.0); |
| 1317 | } |
| 1318 | if( sqlite3_strglob("*.fossil", zName)!=0 ){ |
| 1319 | /* The "fossil server DIRECTORY" and "fossil ui DIRECTORY" commands |
| 1320 | ** do not work for repositories whose names do not end in ".fossil". |
| 1321 | ** So do not hyperlink those cases. */ |
| 1322 | @ <tr><td>%h(zName) |
| 1323 | } else if( sqlite3_strglob("*/.*", zName)==0 ){ |
| 1324 | /* Do not show hidden repos */ |
| 1325 | @ <tr><td>%h(zName) (hidden) |
| 1326 | } else if( allRepo && sqlite3_strglob("[a-zA-Z]:/?*", zName)!=0 ){ |
| 1327 | @ <tr><td><a href="%R/%T(zUrl)/home" target="_blank">/%h(zName)</a> |
| 1328 | }else{ |
| 1329 | @ <tr><td><a href="%R/%T(zUrl)/home" target="_blank">%h(zName)</a> |
| 1330 | } |
| 1331 | @ <td></td><td data-sortkey='%010llx(iNow - iMTime)'>%h(zAge)</tr> |
| 1332 | fossil_free(zAge); |
| 1333 | sqlite3_free(zUrl); |
| 1334 | } |
| 1335 | @ </tbody></table> |
| 1336 | }else{ |
| 1337 | @ <h1>No Repositories Found</h1> |
| 1338 | } |
| 1339 | @ <script>%s(builtin_text("sorttable.js"))</script> |
| 1340 | @ </body> |
| 1341 | @ </html> |
| 1342 | cgi_reply(); |
| 1343 | sqlite3_close(g.db); |
| 1344 | g.db = 0; |
| 1345 | return n; |
| 1346 | } |
| 1347 | |
| 1348 | /* |
| 1349 | ** COMMAND: test-list-page |
| 1350 | ** |
| 1351 | ** Usage: %fossil test-list-page DIRECTORY |
| 1352 | ** |
| 1353 | ** Show all repositories underneath DIRECTORY. Or if DIRECTORY is "/" |
| 1354 | ** show all repositories in the ~/.fossil file. |
| 1355 | */ |
| 1356 | void test_list_page(void){ |
| 1357 | if( g.argc<3 ){ |
| 1358 | g.zRepositoryName = "/"; |
| 1359 | }else{ |
| 1360 | g.zRepositoryName = g.argv[2]; |
| 1361 | } |
| 1362 | g.httpOut = stdout; |
| 1363 | repo_list_page(); |
| 1364 | } |
| 1365 | |
| 1366 | /* |
| 1367 | ** Preconditions: |
| 1368 | ** |
| 1369 | ** * Environment variables are set up according to the CGI standard. |
| 1370 |