Fossil SCM

On file listing pages, sort files that have numbers as part of their name in numeric order.

drh 2022-03-08 20:47 trunk
Commit 59dfca5ed575d6e321b895e392ca21405eedf13618254dc856f331ce866e3c66
2 files changed +5 -4 +53
+5 -4
--- src/browse.c
+++ src/browse.c
@@ -330,11 +330,12 @@
330330
** directory.
331331
*/
332332
mxLen = db_int(12, "SELECT max(length(x)) FROM localfiles /*scan*/");
333333
if( mxLen<12 ) mxLen = 12;
334334
mxLen += (mxLen+9)/10;
335
- db_prepare(&q, "SELECT x, u FROM localfiles ORDER BY x /*scan*/");
335
+ db_prepare(&q,
336
+ "SELECT x, u FROM localfiles ORDER BY x COLLATE uintnocase /*scan*/");
336337
@ <div class="columns files" style="columns: %d(mxLen)ex auto">
337338
@ <ul class="browser">
338339
while( db_step(&q)==SQLITE_ROW ){
339340
const char *zFN;
340341
zFN = db_column_text(&q, 0);
@@ -368,11 +369,11 @@
368369
*/
369370
db_prepare(&q,
370371
"SELECT x, u FROM localfiles"
371372
" WHERE x COLLATE nocase IN"
372373
" ('readme','readme.txt','readme.md','readme.wiki','readme.markdown',"
373
- " 'readme.html') ORDER BY x LIMIT 1;"
374
+ " 'readme.html') ORDER BY x COLLATE uintnocase LIMIT 1;"
374375
);
375376
if( db_step(&q)==SQLITE_ROW ){
376377
const char *zName = db_column_text(&q,0);
377378
const char *zUuid = db_column_text(&q,1);
378379
if( zUuid ){
@@ -790,11 +791,11 @@
790791
db_prepare(&q,
791792
"SELECT filename.name, blob.uuid, fileage.mtime\n"
792793
" FROM fileage, filename, blob\n"
793794
" WHERE filename.fnid=fileage.fnid\n"
794795
" AND blob.rid=fileage.fid\n"
795
- " ORDER BY filename.name COLLATE nocase;"
796
+ " ORDER BY filename.name COLLATE uintnocase;"
796797
);
797798
while( db_step(&q)==SQLITE_ROW ){
798799
const char *zFile = db_column_text(&q,0);
799800
const char *zUuid = db_column_text(&q,1);
800801
double mtime = db_column_double(&q,2);
@@ -813,11 +814,11 @@
813814
" (SELECT name FROM filename WHERE filename.fnid=mlink.fnid),\n"
814815
" (SELECT uuid FROM blob WHERE blob.rid=mlink.fid),\n"
815816
" max(event.mtime)\n"
816817
" FROM mlink JOIN event ON event.objid=mlink.mid\n"
817818
" GROUP BY mlink.fnid\n"
818
- " ORDER BY 1 COLLATE nocase;");
819
+ " ORDER BY 1 COLLATE uintnocase;");
819820
while( db_step(&q)==SQLITE_ROW ){
820821
const char *zName = db_column_text(&q, 0);
821822
const char *zUuid = db_column_text(&q,1);
822823
double mtime = db_column_double(&q,2);
823824
if( nD>0 && (fossil_strncmp(zName, zD, nD-1)!=0 || zName[nD-1]!='/') ){
824825
--- src/browse.c
+++ src/browse.c
@@ -330,11 +330,12 @@
330 ** directory.
331 */
332 mxLen = db_int(12, "SELECT max(length(x)) FROM localfiles /*scan*/");
333 if( mxLen<12 ) mxLen = 12;
334 mxLen += (mxLen+9)/10;
335 db_prepare(&q, "SELECT x, u FROM localfiles ORDER BY x /*scan*/");
 
336 @ <div class="columns files" style="columns: %d(mxLen)ex auto">
337 @ <ul class="browser">
338 while( db_step(&q)==SQLITE_ROW ){
339 const char *zFN;
340 zFN = db_column_text(&q, 0);
@@ -368,11 +369,11 @@
368 */
369 db_prepare(&q,
370 "SELECT x, u FROM localfiles"
371 " WHERE x COLLATE nocase IN"
372 " ('readme','readme.txt','readme.md','readme.wiki','readme.markdown',"
373 " 'readme.html') ORDER BY x LIMIT 1;"
374 );
375 if( db_step(&q)==SQLITE_ROW ){
376 const char *zName = db_column_text(&q,0);
377 const char *zUuid = db_column_text(&q,1);
378 if( zUuid ){
@@ -790,11 +791,11 @@
790 db_prepare(&q,
791 "SELECT filename.name, blob.uuid, fileage.mtime\n"
792 " FROM fileage, filename, blob\n"
793 " WHERE filename.fnid=fileage.fnid\n"
794 " AND blob.rid=fileage.fid\n"
795 " ORDER BY filename.name COLLATE nocase;"
796 );
797 while( db_step(&q)==SQLITE_ROW ){
798 const char *zFile = db_column_text(&q,0);
799 const char *zUuid = db_column_text(&q,1);
800 double mtime = db_column_double(&q,2);
@@ -813,11 +814,11 @@
813 " (SELECT name FROM filename WHERE filename.fnid=mlink.fnid),\n"
814 " (SELECT uuid FROM blob WHERE blob.rid=mlink.fid),\n"
815 " max(event.mtime)\n"
816 " FROM mlink JOIN event ON event.objid=mlink.mid\n"
817 " GROUP BY mlink.fnid\n"
818 " ORDER BY 1 COLLATE nocase;");
819 while( db_step(&q)==SQLITE_ROW ){
820 const char *zName = db_column_text(&q, 0);
821 const char *zUuid = db_column_text(&q,1);
822 double mtime = db_column_double(&q,2);
823 if( nD>0 && (fossil_strncmp(zName, zD, nD-1)!=0 || zName[nD-1]!='/') ){
824
--- src/browse.c
+++ src/browse.c
@@ -330,11 +330,12 @@
330 ** directory.
331 */
332 mxLen = db_int(12, "SELECT max(length(x)) FROM localfiles /*scan*/");
333 if( mxLen<12 ) mxLen = 12;
334 mxLen += (mxLen+9)/10;
335 db_prepare(&q,
336 "SELECT x, u FROM localfiles ORDER BY x COLLATE uintnocase /*scan*/");
337 @ <div class="columns files" style="columns: %d(mxLen)ex auto">
338 @ <ul class="browser">
339 while( db_step(&q)==SQLITE_ROW ){
340 const char *zFN;
341 zFN = db_column_text(&q, 0);
@@ -368,11 +369,11 @@
369 */
370 db_prepare(&q,
371 "SELECT x, u FROM localfiles"
372 " WHERE x COLLATE nocase IN"
373 " ('readme','readme.txt','readme.md','readme.wiki','readme.markdown',"
374 " 'readme.html') ORDER BY x COLLATE uintnocase LIMIT 1;"
375 );
376 if( db_step(&q)==SQLITE_ROW ){
377 const char *zName = db_column_text(&q,0);
378 const char *zUuid = db_column_text(&q,1);
379 if( zUuid ){
@@ -790,11 +791,11 @@
791 db_prepare(&q,
792 "SELECT filename.name, blob.uuid, fileage.mtime\n"
793 " FROM fileage, filename, blob\n"
794 " WHERE filename.fnid=fileage.fnid\n"
795 " AND blob.rid=fileage.fid\n"
796 " ORDER BY filename.name COLLATE uintnocase;"
797 );
798 while( db_step(&q)==SQLITE_ROW ){
799 const char *zFile = db_column_text(&q,0);
800 const char *zUuid = db_column_text(&q,1);
801 double mtime = db_column_double(&q,2);
@@ -813,11 +814,11 @@
814 " (SELECT name FROM filename WHERE filename.fnid=mlink.fnid),\n"
815 " (SELECT uuid FROM blob WHERE blob.rid=mlink.fid),\n"
816 " max(event.mtime)\n"
817 " FROM mlink JOIN event ON event.objid=mlink.mid\n"
818 " GROUP BY mlink.fnid\n"
819 " ORDER BY 1 COLLATE uintnocase;");
820 while( db_step(&q)==SQLITE_ROW ){
821 const char *zName = db_column_text(&q, 0);
822 const char *zUuid = db_column_text(&q,1);
823 double mtime = db_column_double(&q,2);
824 if( nD>0 && (fossil_strncmp(zName, zD, nD-1)!=0 || zName[nD-1]!='/') ){
825
+53
--- src/db.c
+++ src/db.c
@@ -1376,16 +1376,69 @@
13761376
return;
13771377
}
13781378
zSetting = (const char*)sqlite3_value_text(argv[0]);
13791379
sqlite3_result_int(context, db_setting_is_protected(zSetting));
13801380
}
1381
+
1382
+/*
1383
+** Copied from SQLite ext/misc/uint.c...
1384
+**
1385
+** Compare text in lexicographic order, except strings of digits
1386
+** compare in numeric order.
1387
+**
1388
+** This version modified to also ignore case.
1389
+*/
1390
+static int uintNocaseCollFunc(
1391
+ void *notUsed,
1392
+ int nKey1, const void *pKey1,
1393
+ int nKey2, const void *pKey2
1394
+){
1395
+ const unsigned char *zA = (const unsigned char*)pKey1;
1396
+ const unsigned char *zB = (const unsigned char*)pKey2;
1397
+ int i=0, j=0, x;
1398
+ (void)notUsed;
1399
+ while( i<nKey1 && j<nKey2 ){
1400
+ if( fossil_isdigit(zA[i]) ){
1401
+ int k;
1402
+ if( !fossil_isdigit(zB[j]) ) return x;
1403
+ while( i<nKey1 && zA[i]=='0' ){ i++; }
1404
+ while( j<nKey2 && zB[j]=='0' ){ j++; }
1405
+ k = 0;
1406
+ while( i+k<nKey1 && fossil_isdigit(zA[i+k])
1407
+ && j+k<nKey2 && fossil_isdigit(zB[j+k]) ){
1408
+ k++;
1409
+ }
1410
+ if( i+k<nKey1 && fossil_isdigit(zA[i+k]) ){
1411
+ return +1;
1412
+ }else if( j+k<nKey2 && fossil_isdigit(zB[j+k]) ){
1413
+ return -1;
1414
+ }else{
1415
+ x = memcmp(zA+i, zB+j, k);
1416
+ if( x ) return x;
1417
+ i += k;
1418
+ j += k;
1419
+ }
1420
+ }else
1421
+ if( zA[i]!=zB[j]
1422
+ && (x = fossil_tolower(zA[i]) - fossil_tolower(zB[j]))!=0
1423
+ ){
1424
+ return x;
1425
+ }else{
1426
+ i++;
1427
+ j++;
1428
+ }
1429
+ }
1430
+ return (nKey1 - i) - (nKey2 - j);
1431
+}
1432
+
13811433
13821434
/*
13831435
** Register the SQL functions that are useful both to the internal
13841436
** representation and to the "fossil sql" command.
13851437
*/
13861438
void db_add_aux_functions(sqlite3 *db){
1439
+ sqlite3_create_collation(db, "uintnocase", SQLITE_UTF8,0,uintNocaseCollFunc);
13871440
sqlite3_create_function(db, "checkin_mtime", 2, SQLITE_UTF8, 0,
13881441
db_checkin_mtime_function, 0, 0);
13891442
sqlite3_create_function(db, "symbolic_name_to_rid", 1, SQLITE_UTF8, 0,
13901443
db_sym2rid_function, 0, 0);
13911444
sqlite3_create_function(db, "symbolic_name_to_rid", 2, SQLITE_UTF8, 0,
13921445
--- src/db.c
+++ src/db.c
@@ -1376,16 +1376,69 @@
1376 return;
1377 }
1378 zSetting = (const char*)sqlite3_value_text(argv[0]);
1379 sqlite3_result_int(context, db_setting_is_protected(zSetting));
1380 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1381
1382 /*
1383 ** Register the SQL functions that are useful both to the internal
1384 ** representation and to the "fossil sql" command.
1385 */
1386 void db_add_aux_functions(sqlite3 *db){
 
1387 sqlite3_create_function(db, "checkin_mtime", 2, SQLITE_UTF8, 0,
1388 db_checkin_mtime_function, 0, 0);
1389 sqlite3_create_function(db, "symbolic_name_to_rid", 1, SQLITE_UTF8, 0,
1390 db_sym2rid_function, 0, 0);
1391 sqlite3_create_function(db, "symbolic_name_to_rid", 2, SQLITE_UTF8, 0,
1392
--- src/db.c
+++ src/db.c
@@ -1376,16 +1376,69 @@
1376 return;
1377 }
1378 zSetting = (const char*)sqlite3_value_text(argv[0]);
1379 sqlite3_result_int(context, db_setting_is_protected(zSetting));
1380 }
1381
1382 /*
1383 ** Copied from SQLite ext/misc/uint.c...
1384 **
1385 ** Compare text in lexicographic order, except strings of digits
1386 ** compare in numeric order.
1387 **
1388 ** This version modified to also ignore case.
1389 */
1390 static int uintNocaseCollFunc(
1391 void *notUsed,
1392 int nKey1, const void *pKey1,
1393 int nKey2, const void *pKey2
1394 ){
1395 const unsigned char *zA = (const unsigned char*)pKey1;
1396 const unsigned char *zB = (const unsigned char*)pKey2;
1397 int i=0, j=0, x;
1398 (void)notUsed;
1399 while( i<nKey1 && j<nKey2 ){
1400 if( fossil_isdigit(zA[i]) ){
1401 int k;
1402 if( !fossil_isdigit(zB[j]) ) return x;
1403 while( i<nKey1 && zA[i]=='0' ){ i++; }
1404 while( j<nKey2 && zB[j]=='0' ){ j++; }
1405 k = 0;
1406 while( i+k<nKey1 && fossil_isdigit(zA[i+k])
1407 && j+k<nKey2 && fossil_isdigit(zB[j+k]) ){
1408 k++;
1409 }
1410 if( i+k<nKey1 && fossil_isdigit(zA[i+k]) ){
1411 return +1;
1412 }else if( j+k<nKey2 && fossil_isdigit(zB[j+k]) ){
1413 return -1;
1414 }else{
1415 x = memcmp(zA+i, zB+j, k);
1416 if( x ) return x;
1417 i += k;
1418 j += k;
1419 }
1420 }else
1421 if( zA[i]!=zB[j]
1422 && (x = fossil_tolower(zA[i]) - fossil_tolower(zB[j]))!=0
1423 ){
1424 return x;
1425 }else{
1426 i++;
1427 j++;
1428 }
1429 }
1430 return (nKey1 - i) - (nKey2 - j);
1431 }
1432
1433
1434 /*
1435 ** Register the SQL functions that are useful both to the internal
1436 ** representation and to the "fossil sql" command.
1437 */
1438 void db_add_aux_functions(sqlite3 *db){
1439 sqlite3_create_collation(db, "uintnocase", SQLITE_UTF8,0,uintNocaseCollFunc);
1440 sqlite3_create_function(db, "checkin_mtime", 2, SQLITE_UTF8, 0,
1441 db_checkin_mtime_function, 0, 0);
1442 sqlite3_create_function(db, "symbolic_name_to_rid", 1, SQLITE_UTF8, 0,
1443 db_sym2rid_function, 0, 0);
1444 sqlite3_create_function(db, "symbolic_name_to_rid", 2, SQLITE_UTF8, 0,
1445

Keyboard Shortcuts

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