Fossil SCM

Add the -r option to the 'timeline' command to display items in chronological order.

danield 2025-10-08 13:14 trunk
Commit 7ac9d8bf35238a16578417d84df61ad8929f6742c352a9b032b3f3c9a8cf3918
1 file changed +18 -13
+18 -13
--- src/timeline.c
+++ src/timeline.c
@@ -598,11 +598,11 @@
598598
drawDetailEllipsis = 0;
599599
}else{
600600
cgi_printf("%W",blob_str(&comment));
601601
}
602602
}
603
-
603
+
604604
if( zType[0]=='c' && strcmp(zUuid, MANIFEST_UUID)==0 ){
605605
/* This will only ever happen when Fossil is drawing a timeline for
606606
** its own self-host repository. If the timeline shows the specific
607607
** check-in corresponding to the current executable, then tag that
608608
** check-in with "This is me!". */
@@ -1363,11 +1363,11 @@
13631363
** the input is a valid date space and false if not.
13641364
*/
13651365
static int timeline_is_datespan(const char *zDay){
13661366
size_t n = strlen(zDay);
13671367
int i, d, m;
1368
-
1368
+
13691369
if( n<17 || n>18 ) return 0;
13701370
if( n==18 ){
13711371
if( zDay[17]!='Z' && zDay[17]!='z' ) return 0;
13721372
n--;
13731373
}
@@ -1395,11 +1395,11 @@
13951395
** or ancestor set of check-in iFrom that match the tag, then
13961396
** return 0.
13971397
*/
13981398
static int timeline_endpoint(
13991399
int iFrom, /* Starting point */
1400
- const char *zEnd, /* Tag we are searching for */
1400
+ const char *zEnd, /* Tag we are searching for */
14011401
int bForward /* 1: forwards in time (descendants) 0: backwards */
14021402
){
14031403
int tagId;
14041404
int endId = 0;
14051405
Stmt q;
@@ -2285,11 +2285,11 @@
22852285
if( zError==0 ){
22862286
zError = "Cannot use the ft= query parameter when both p= and d= "
22872287
"are used and have distinct values.";
22882288
}
22892289
zFwdTo = 0;
2290
- }
2290
+ }
22912291
if( zFwdTo ){
22922292
double rStartDate = mtime_of_rid(d_rid, 0.0);
22932293
ridFwdTo = first_checkin_with_tag_after_date(zFwdTo, rStartDate);
22942294
if( ridFwdTo==0 ){
22952295
ridFwdTo = name_to_typed_rid(zBackTo,"ci");
@@ -2344,11 +2344,11 @@
23442344
if( zError==0 ){
23452345
zError = "Cannot use the bt= query parameter when both p= and d= "
23462346
"are used and have distinct values.";
23472347
}
23482348
zBackTo = 0;
2349
- }
2349
+ }
23502350
if( zBackTo ){
23512351
double rDateLimit = mtime_of_rid(p_rid, 0.0);
23522352
ridBackTo = last_checkin_with_tag_before_date(zBackTo, rDateLimit);
23532353
if( ridBackTo==0 ){
23542354
ridBackTo = name_to_typed_rid(zBackTo,"ci");
@@ -2370,11 +2370,11 @@
23702370
}else{
23712371
removeFileGlobFromOk(zChng);
23722372
np = db_int(0, "SELECT count(*)-1 FROM ok");
23732373
if( np>0 || nd==0 ){
23742374
if( nd>0 ) blob_appendf(&desc, " and ");
2375
- blob_appendf(&desc, "%d ancestor%s",
2375
+ blob_appendf(&desc, "%d ancestor%s",
23762376
np>=0 ? np : 0, (1==np)?"":"s");
23772377
db_multi_exec("%s", blob_sql_text(&sql));
23782378
}
23792379
if( useDividers && !selectedRid ) selectedRid = p_rid;
23802380
}
@@ -2653,11 +2653,11 @@
26532653
blob_append_sql(&cond,
26542654
" AND event.mtime>=julianday(%Q,%Q)"
26552655
" AND event.mtime<julianday(%Q,%Q,'+1 day')\n",
26562656
zStart, zTZMod, zEnd, zTZMod);
26572657
nEntry = -1;
2658
-
2658
+
26592659
if( fossil_ui_localtime() && bZulu ){
26602660
zDay = mprintf("%d days between %zZ and %zZ", nDay, zStart, zEnd);
26612661
}else{
26622662
zDay = mprintf("%d days between %z and %z", nDay, zStart, zEnd);
26632663
}
@@ -3622,10 +3622,11 @@
36223622
** N is negative, output the first -N lines. If N is
36233623
** zero, no limit. Default is -20 meaning 20 lines.
36243624
** --offset P Skip P changes
36253625
** -p|--path PATH Output items affecting PATH only.
36263626
** PATH can be a file or a sub directory.
3627
+** -r|--reverse Show items in chronological order.
36273628
** -R REPO_FILE Specifies the repository db to use. Default is
36283629
** the current check-out's repository.
36293630
** --sql Show the SQL used to generate the timeline
36303631
** -t|--type TYPE Output items from the given types only, such as:
36313632
** ci = file commits only
@@ -3652,11 +3653,12 @@
36523653
char *zDate;
36533654
Blob sql;
36543655
int objid = 0;
36553656
Blob uuid;
36563657
int mode = TIMELINE_MODE_NONE;
3657
- int verboseFlag = 0 ;
3658
+ int verboseFlag = 0;
3659
+ int reverseFlag = 0;
36583660
int iOffset;
36593661
const char *zFilePattern = 0;
36603662
const char *zFormat = 0;
36613663
const char *zBr = 0;
36623664
Blob treeName;
@@ -3709,10 +3711,11 @@
37093711
}else{
37103712
width = -1;
37113713
}
37123714
zOffset = find_option("offset",0,1);
37133715
iOffset = zOffset ? atoi(zOffset) : 0;
3716
+ reverseFlag = find_option("reverse","r",0)!=0;
37143717
37153718
/* We should be done with options.. */
37163719
verify_all_options();
37173720
37183721
if( g.argc>=4 ){
@@ -3729,11 +3732,11 @@
37293732
mode = TIMELINE_MODE_PARENTS;
37303733
}else if( strncmp(g.argv[2],"parents",k)==0 ){
37313734
mode = TIMELINE_MODE_PARENTS;
37323735
}else if(!zType && !zLimit){
37333736
usage("?WHEN? ?CHECKIN|DATETIME? ?-n|--limit #? ?-t|--type TYPE? "
3734
- "?-W|--width WIDTH? ?-p|--path PATH?");
3737
+ "?-W|--width WIDTH? ?-p|--path PATH? ?-r|--reverse?");
37353738
}
37363739
if( '-' != *g.argv[3] ){
37373740
zOrigin = g.argv[3];
37383741
}else{
37393742
zOrigin = "now";
@@ -3852,23 +3855,25 @@
38523855
" WHERE tx.value='%q'\n"
38533856
")\n" /* No merge closures */
38543857
" AND (tagxref.value IS NULL OR tagxref.value='%q')",
38553858
zBr, zBr, zBr, TAG_BRANCH, zBr, zBr);
38563859
}
3857
-
3860
+
38583861
if( mode==TIMELINE_MODE_AFTER ){
38593862
int lim = n;
38603863
if( n == 0 ){
38613864
lim = -1; /* 0 means no limit */
38623865
}else if( n < 0 ){
38633866
lim = -n;
38643867
}
38653868
/* Complete the above outer select. */
3866
- blob_append_sql(&sql,
3867
- "\nORDER BY event.mtime LIMIT %d) t ORDER BY t.mDateTime DESC", lim);
3869
+ blob_append_sql(&sql,
3870
+ "\nORDER BY event.mtime LIMIT %d) t ORDER BY t.mDateTime %s",
3871
+ lim, reverseFlag ? "" : "DESC");
38683872
}else{
3869
- blob_append_sql(&sql, "\nORDER BY event.mtime DESC");
3873
+ blob_append_sql(&sql,
3874
+ "\nORDER BY event.mtime %s", reverseFlag ? "" : "DESC");
38703875
}
38713876
if( iOffset>0 ){
38723877
/* Don't handle LIMIT here, otherwise print_timeline()
38733878
* will not determine the end-marker correctly! */
38743879
blob_append_sql(&sql, "\n LIMIT -1 OFFSET %d", iOffset);
38753880
--- src/timeline.c
+++ src/timeline.c
@@ -598,11 +598,11 @@
598 drawDetailEllipsis = 0;
599 }else{
600 cgi_printf("%W",blob_str(&comment));
601 }
602 }
603
604 if( zType[0]=='c' && strcmp(zUuid, MANIFEST_UUID)==0 ){
605 /* This will only ever happen when Fossil is drawing a timeline for
606 ** its own self-host repository. If the timeline shows the specific
607 ** check-in corresponding to the current executable, then tag that
608 ** check-in with "This is me!". */
@@ -1363,11 +1363,11 @@
1363 ** the input is a valid date space and false if not.
1364 */
1365 static int timeline_is_datespan(const char *zDay){
1366 size_t n = strlen(zDay);
1367 int i, d, m;
1368
1369 if( n<17 || n>18 ) return 0;
1370 if( n==18 ){
1371 if( zDay[17]!='Z' && zDay[17]!='z' ) return 0;
1372 n--;
1373 }
@@ -1395,11 +1395,11 @@
1395 ** or ancestor set of check-in iFrom that match the tag, then
1396 ** return 0.
1397 */
1398 static int timeline_endpoint(
1399 int iFrom, /* Starting point */
1400 const char *zEnd, /* Tag we are searching for */
1401 int bForward /* 1: forwards in time (descendants) 0: backwards */
1402 ){
1403 int tagId;
1404 int endId = 0;
1405 Stmt q;
@@ -2285,11 +2285,11 @@
2285 if( zError==0 ){
2286 zError = "Cannot use the ft= query parameter when both p= and d= "
2287 "are used and have distinct values.";
2288 }
2289 zFwdTo = 0;
2290 }
2291 if( zFwdTo ){
2292 double rStartDate = mtime_of_rid(d_rid, 0.0);
2293 ridFwdTo = first_checkin_with_tag_after_date(zFwdTo, rStartDate);
2294 if( ridFwdTo==0 ){
2295 ridFwdTo = name_to_typed_rid(zBackTo,"ci");
@@ -2344,11 +2344,11 @@
2344 if( zError==0 ){
2345 zError = "Cannot use the bt= query parameter when both p= and d= "
2346 "are used and have distinct values.";
2347 }
2348 zBackTo = 0;
2349 }
2350 if( zBackTo ){
2351 double rDateLimit = mtime_of_rid(p_rid, 0.0);
2352 ridBackTo = last_checkin_with_tag_before_date(zBackTo, rDateLimit);
2353 if( ridBackTo==0 ){
2354 ridBackTo = name_to_typed_rid(zBackTo,"ci");
@@ -2370,11 +2370,11 @@
2370 }else{
2371 removeFileGlobFromOk(zChng);
2372 np = db_int(0, "SELECT count(*)-1 FROM ok");
2373 if( np>0 || nd==0 ){
2374 if( nd>0 ) blob_appendf(&desc, " and ");
2375 blob_appendf(&desc, "%d ancestor%s",
2376 np>=0 ? np : 0, (1==np)?"":"s");
2377 db_multi_exec("%s", blob_sql_text(&sql));
2378 }
2379 if( useDividers && !selectedRid ) selectedRid = p_rid;
2380 }
@@ -2653,11 +2653,11 @@
2653 blob_append_sql(&cond,
2654 " AND event.mtime>=julianday(%Q,%Q)"
2655 " AND event.mtime<julianday(%Q,%Q,'+1 day')\n",
2656 zStart, zTZMod, zEnd, zTZMod);
2657 nEntry = -1;
2658
2659 if( fossil_ui_localtime() && bZulu ){
2660 zDay = mprintf("%d days between %zZ and %zZ", nDay, zStart, zEnd);
2661 }else{
2662 zDay = mprintf("%d days between %z and %z", nDay, zStart, zEnd);
2663 }
@@ -3622,10 +3622,11 @@
3622 ** N is negative, output the first -N lines. If N is
3623 ** zero, no limit. Default is -20 meaning 20 lines.
3624 ** --offset P Skip P changes
3625 ** -p|--path PATH Output items affecting PATH only.
3626 ** PATH can be a file or a sub directory.
 
3627 ** -R REPO_FILE Specifies the repository db to use. Default is
3628 ** the current check-out's repository.
3629 ** --sql Show the SQL used to generate the timeline
3630 ** -t|--type TYPE Output items from the given types only, such as:
3631 ** ci = file commits only
@@ -3652,11 +3653,12 @@
3652 char *zDate;
3653 Blob sql;
3654 int objid = 0;
3655 Blob uuid;
3656 int mode = TIMELINE_MODE_NONE;
3657 int verboseFlag = 0 ;
 
3658 int iOffset;
3659 const char *zFilePattern = 0;
3660 const char *zFormat = 0;
3661 const char *zBr = 0;
3662 Blob treeName;
@@ -3709,10 +3711,11 @@
3709 }else{
3710 width = -1;
3711 }
3712 zOffset = find_option("offset",0,1);
3713 iOffset = zOffset ? atoi(zOffset) : 0;
 
3714
3715 /* We should be done with options.. */
3716 verify_all_options();
3717
3718 if( g.argc>=4 ){
@@ -3729,11 +3732,11 @@
3729 mode = TIMELINE_MODE_PARENTS;
3730 }else if( strncmp(g.argv[2],"parents",k)==0 ){
3731 mode = TIMELINE_MODE_PARENTS;
3732 }else if(!zType && !zLimit){
3733 usage("?WHEN? ?CHECKIN|DATETIME? ?-n|--limit #? ?-t|--type TYPE? "
3734 "?-W|--width WIDTH? ?-p|--path PATH?");
3735 }
3736 if( '-' != *g.argv[3] ){
3737 zOrigin = g.argv[3];
3738 }else{
3739 zOrigin = "now";
@@ -3852,23 +3855,25 @@
3852 " WHERE tx.value='%q'\n"
3853 ")\n" /* No merge closures */
3854 " AND (tagxref.value IS NULL OR tagxref.value='%q')",
3855 zBr, zBr, zBr, TAG_BRANCH, zBr, zBr);
3856 }
3857
3858 if( mode==TIMELINE_MODE_AFTER ){
3859 int lim = n;
3860 if( n == 0 ){
3861 lim = -1; /* 0 means no limit */
3862 }else if( n < 0 ){
3863 lim = -n;
3864 }
3865 /* Complete the above outer select. */
3866 blob_append_sql(&sql,
3867 "\nORDER BY event.mtime LIMIT %d) t ORDER BY t.mDateTime DESC", lim);
 
3868 }else{
3869 blob_append_sql(&sql, "\nORDER BY event.mtime DESC");
 
3870 }
3871 if( iOffset>0 ){
3872 /* Don't handle LIMIT here, otherwise print_timeline()
3873 * will not determine the end-marker correctly! */
3874 blob_append_sql(&sql, "\n LIMIT -1 OFFSET %d", iOffset);
3875
--- src/timeline.c
+++ src/timeline.c
@@ -598,11 +598,11 @@
598 drawDetailEllipsis = 0;
599 }else{
600 cgi_printf("%W",blob_str(&comment));
601 }
602 }
603
604 if( zType[0]=='c' && strcmp(zUuid, MANIFEST_UUID)==0 ){
605 /* This will only ever happen when Fossil is drawing a timeline for
606 ** its own self-host repository. If the timeline shows the specific
607 ** check-in corresponding to the current executable, then tag that
608 ** check-in with "This is me!". */
@@ -1363,11 +1363,11 @@
1363 ** the input is a valid date space and false if not.
1364 */
1365 static int timeline_is_datespan(const char *zDay){
1366 size_t n = strlen(zDay);
1367 int i, d, m;
1368
1369 if( n<17 || n>18 ) return 0;
1370 if( n==18 ){
1371 if( zDay[17]!='Z' && zDay[17]!='z' ) return 0;
1372 n--;
1373 }
@@ -1395,11 +1395,11 @@
1395 ** or ancestor set of check-in iFrom that match the tag, then
1396 ** return 0.
1397 */
1398 static int timeline_endpoint(
1399 int iFrom, /* Starting point */
1400 const char *zEnd, /* Tag we are searching for */
1401 int bForward /* 1: forwards in time (descendants) 0: backwards */
1402 ){
1403 int tagId;
1404 int endId = 0;
1405 Stmt q;
@@ -2285,11 +2285,11 @@
2285 if( zError==0 ){
2286 zError = "Cannot use the ft= query parameter when both p= and d= "
2287 "are used and have distinct values.";
2288 }
2289 zFwdTo = 0;
2290 }
2291 if( zFwdTo ){
2292 double rStartDate = mtime_of_rid(d_rid, 0.0);
2293 ridFwdTo = first_checkin_with_tag_after_date(zFwdTo, rStartDate);
2294 if( ridFwdTo==0 ){
2295 ridFwdTo = name_to_typed_rid(zBackTo,"ci");
@@ -2344,11 +2344,11 @@
2344 if( zError==0 ){
2345 zError = "Cannot use the bt= query parameter when both p= and d= "
2346 "are used and have distinct values.";
2347 }
2348 zBackTo = 0;
2349 }
2350 if( zBackTo ){
2351 double rDateLimit = mtime_of_rid(p_rid, 0.0);
2352 ridBackTo = last_checkin_with_tag_before_date(zBackTo, rDateLimit);
2353 if( ridBackTo==0 ){
2354 ridBackTo = name_to_typed_rid(zBackTo,"ci");
@@ -2370,11 +2370,11 @@
2370 }else{
2371 removeFileGlobFromOk(zChng);
2372 np = db_int(0, "SELECT count(*)-1 FROM ok");
2373 if( np>0 || nd==0 ){
2374 if( nd>0 ) blob_appendf(&desc, " and ");
2375 blob_appendf(&desc, "%d ancestor%s",
2376 np>=0 ? np : 0, (1==np)?"":"s");
2377 db_multi_exec("%s", blob_sql_text(&sql));
2378 }
2379 if( useDividers && !selectedRid ) selectedRid = p_rid;
2380 }
@@ -2653,11 +2653,11 @@
2653 blob_append_sql(&cond,
2654 " AND event.mtime>=julianday(%Q,%Q)"
2655 " AND event.mtime<julianday(%Q,%Q,'+1 day')\n",
2656 zStart, zTZMod, zEnd, zTZMod);
2657 nEntry = -1;
2658
2659 if( fossil_ui_localtime() && bZulu ){
2660 zDay = mprintf("%d days between %zZ and %zZ", nDay, zStart, zEnd);
2661 }else{
2662 zDay = mprintf("%d days between %z and %z", nDay, zStart, zEnd);
2663 }
@@ -3622,10 +3622,11 @@
3622 ** N is negative, output the first -N lines. If N is
3623 ** zero, no limit. Default is -20 meaning 20 lines.
3624 ** --offset P Skip P changes
3625 ** -p|--path PATH Output items affecting PATH only.
3626 ** PATH can be a file or a sub directory.
3627 ** -r|--reverse Show items in chronological order.
3628 ** -R REPO_FILE Specifies the repository db to use. Default is
3629 ** the current check-out's repository.
3630 ** --sql Show the SQL used to generate the timeline
3631 ** -t|--type TYPE Output items from the given types only, such as:
3632 ** ci = file commits only
@@ -3652,11 +3653,12 @@
3653 char *zDate;
3654 Blob sql;
3655 int objid = 0;
3656 Blob uuid;
3657 int mode = TIMELINE_MODE_NONE;
3658 int verboseFlag = 0;
3659 int reverseFlag = 0;
3660 int iOffset;
3661 const char *zFilePattern = 0;
3662 const char *zFormat = 0;
3663 const char *zBr = 0;
3664 Blob treeName;
@@ -3709,10 +3711,11 @@
3711 }else{
3712 width = -1;
3713 }
3714 zOffset = find_option("offset",0,1);
3715 iOffset = zOffset ? atoi(zOffset) : 0;
3716 reverseFlag = find_option("reverse","r",0)!=0;
3717
3718 /* We should be done with options.. */
3719 verify_all_options();
3720
3721 if( g.argc>=4 ){
@@ -3729,11 +3732,11 @@
3732 mode = TIMELINE_MODE_PARENTS;
3733 }else if( strncmp(g.argv[2],"parents",k)==0 ){
3734 mode = TIMELINE_MODE_PARENTS;
3735 }else if(!zType && !zLimit){
3736 usage("?WHEN? ?CHECKIN|DATETIME? ?-n|--limit #? ?-t|--type TYPE? "
3737 "?-W|--width WIDTH? ?-p|--path PATH? ?-r|--reverse?");
3738 }
3739 if( '-' != *g.argv[3] ){
3740 zOrigin = g.argv[3];
3741 }else{
3742 zOrigin = "now";
@@ -3852,23 +3855,25 @@
3855 " WHERE tx.value='%q'\n"
3856 ")\n" /* No merge closures */
3857 " AND (tagxref.value IS NULL OR tagxref.value='%q')",
3858 zBr, zBr, zBr, TAG_BRANCH, zBr, zBr);
3859 }
3860
3861 if( mode==TIMELINE_MODE_AFTER ){
3862 int lim = n;
3863 if( n == 0 ){
3864 lim = -1; /* 0 means no limit */
3865 }else if( n < 0 ){
3866 lim = -n;
3867 }
3868 /* Complete the above outer select. */
3869 blob_append_sql(&sql,
3870 "\nORDER BY event.mtime LIMIT %d) t ORDER BY t.mDateTime %s",
3871 lim, reverseFlag ? "" : "DESC");
3872 }else{
3873 blob_append_sql(&sql,
3874 "\nORDER BY event.mtime %s", reverseFlag ? "" : "DESC");
3875 }
3876 if( iOffset>0 ){
3877 /* Don't handle LIMIT here, otherwise print_timeline()
3878 * will not determine the end-marker correctly! */
3879 blob_append_sql(&sql, "\n LIMIT -1 OFFSET %d", iOffset);
3880

Keyboard Shortcuts

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