Fossil SCM

Add the --format option to the "fossil timeline" command.

drh 2021-01-07 16:26 trunk merge
Commit e86aeb72ac213db2224073e0b3fd9d1ca113e8f7bc572b97973c263e03dd5963
--- src/descendants.c
+++ src/descendants.c
@@ -382,11 +382,11 @@
382382
"%s"
383383
" AND event.objid IN (SELECT rid FROM leaves)"
384384
" ORDER BY event.mtime DESC",
385385
timeline_query_for_tty()
386386
);
387
- print_timeline(&q, 0, width, 0);
387
+ print_timeline(&q, 0, width, 0, 0);
388388
db_finalize(&q);
389389
}
390390
391391
/*
392392
** COMMAND: leaves*
393393
--- src/descendants.c
+++ src/descendants.c
@@ -382,11 +382,11 @@
382 "%s"
383 " AND event.objid IN (SELECT rid FROM leaves)"
384 " ORDER BY event.mtime DESC",
385 timeline_query_for_tty()
386 );
387 print_timeline(&q, 0, width, 0);
388 db_finalize(&q);
389 }
390
391 /*
392 ** COMMAND: leaves*
393
--- src/descendants.c
+++ src/descendants.c
@@ -382,11 +382,11 @@
382 "%s"
383 " AND event.objid IN (SELECT rid FROM leaves)"
384 " ORDER BY event.mtime DESC",
385 timeline_query_for_tty()
386 );
387 print_timeline(&q, 0, width, 0, 0);
388 db_finalize(&q);
389 }
390
391 /*
392 ** COMMAND: leaves*
393
--- src/descendants.c
+++ src/descendants.c
@@ -382,11 +382,11 @@
382382
"%s"
383383
" AND event.objid IN (SELECT rid FROM leaves)"
384384
" ORDER BY event.mtime DESC",
385385
timeline_query_for_tty()
386386
);
387
- print_timeline(&q, 0, width, 0);
387
+ print_timeline(&q, 0, width, 0, 0);
388388
db_finalize(&q);
389389
}
390390
391391
/*
392392
** COMMAND: leaves*
393393
--- src/descendants.c
+++ src/descendants.c
@@ -382,11 +382,11 @@
382 "%s"
383 " AND event.objid IN (SELECT rid FROM leaves)"
384 " ORDER BY event.mtime DESC",
385 timeline_query_for_tty()
386 );
387 print_timeline(&q, 0, width, 0);
388 db_finalize(&q);
389 }
390
391 /*
392 ** COMMAND: leaves*
393
--- src/descendants.c
+++ src/descendants.c
@@ -382,11 +382,11 @@
382 "%s"
383 " AND event.objid IN (SELECT rid FROM leaves)"
384 " ORDER BY event.mtime DESC",
385 timeline_query_for_tty()
386 );
387 print_timeline(&q, 0, width, 0, 0);
388 db_finalize(&q);
389 }
390
391 /*
392 ** COMMAND: leaves*
393
+1 -1
--- src/search.c
+++ src/search.c
@@ -643,11 +643,11 @@
643643
blob_append_sql(&sql,"AND x>%d ", iBest/3);
644644
}
645645
blob_append(&sql, "ORDER BY x DESC, date DESC ", -1);
646646
db_prepare(&q, "%s", blob_sql_text(&sql));
647647
blob_reset(&sql);
648
- print_timeline(&q, nLimit, width, 0);
648
+ print_timeline(&q, nLimit, width, 0, 0);
649649
db_finalize(&q);
650650
}
651651
652652
#if INTERFACE
653653
/* What to search for */
654654
--- src/search.c
+++ src/search.c
@@ -643,11 +643,11 @@
643 blob_append_sql(&sql,"AND x>%d ", iBest/3);
644 }
645 blob_append(&sql, "ORDER BY x DESC, date DESC ", -1);
646 db_prepare(&q, "%s", blob_sql_text(&sql));
647 blob_reset(&sql);
648 print_timeline(&q, nLimit, width, 0);
649 db_finalize(&q);
650 }
651
652 #if INTERFACE
653 /* What to search for */
654
--- src/search.c
+++ src/search.c
@@ -643,11 +643,11 @@
643 blob_append_sql(&sql,"AND x>%d ", iBest/3);
644 }
645 blob_append(&sql, "ORDER BY x DESC, date DESC ", -1);
646 db_prepare(&q, "%s", blob_sql_text(&sql));
647 blob_reset(&sql);
648 print_timeline(&q, nLimit, width, 0, 0);
649 db_finalize(&q);
650 }
651
652 #if INTERFACE
653 /* What to search for */
654
+1 -1
--- src/search.c
+++ src/search.c
@@ -643,11 +643,11 @@
643643
blob_append_sql(&sql,"AND x>%d ", iBest/3);
644644
}
645645
blob_append(&sql, "ORDER BY x DESC, date DESC ", -1);
646646
db_prepare(&q, "%s", blob_sql_text(&sql));
647647
blob_reset(&sql);
648
- print_timeline(&q, nLimit, width, 0);
648
+ print_timeline(&q, nLimit, width, 0, 0);
649649
db_finalize(&q);
650650
}
651651
652652
#if INTERFACE
653653
/* What to search for */
654654
--- src/search.c
+++ src/search.c
@@ -643,11 +643,11 @@
643 blob_append_sql(&sql,"AND x>%d ", iBest/3);
644 }
645 blob_append(&sql, "ORDER BY x DESC, date DESC ", -1);
646 db_prepare(&q, "%s", blob_sql_text(&sql));
647 blob_reset(&sql);
648 print_timeline(&q, nLimit, width, 0);
649 db_finalize(&q);
650 }
651
652 #if INTERFACE
653 /* What to search for */
654
--- src/search.c
+++ src/search.c
@@ -643,11 +643,11 @@
643 blob_append_sql(&sql,"AND x>%d ", iBest/3);
644 }
645 blob_append(&sql, "ORDER BY x DESC, date DESC ", -1);
646 db_prepare(&q, "%s", blob_sql_text(&sql));
647 blob_reset(&sql);
648 print_timeline(&q, nLimit, width, 0, 0);
649 db_finalize(&q);
650 }
651
652 #if INTERFACE
653 /* What to search for */
654
+1 -1
--- src/tag.c
+++ src/tag.c
@@ -541,11 +541,11 @@
541541
" ORDER BY event.mtime DESC /*sort*/",
542542
timeline_query_for_tty(), zType, tagid
543543
);
544544
db_prepare(&q, "%s", blob_sql_text(&sql));
545545
blob_reset(&sql);
546
- print_timeline(&q, nFindLimit, 79, 0);
546
+ print_timeline(&q, nFindLimit, 79, 0, 0);
547547
db_finalize(&q);
548548
}
549549
}
550550
}else
551551
552552
--- src/tag.c
+++ src/tag.c
@@ -541,11 +541,11 @@
541 " ORDER BY event.mtime DESC /*sort*/",
542 timeline_query_for_tty(), zType, tagid
543 );
544 db_prepare(&q, "%s", blob_sql_text(&sql));
545 blob_reset(&sql);
546 print_timeline(&q, nFindLimit, 79, 0);
547 db_finalize(&q);
548 }
549 }
550 }else
551
552
--- src/tag.c
+++ src/tag.c
@@ -541,11 +541,11 @@
541 " ORDER BY event.mtime DESC /*sort*/",
542 timeline_query_for_tty(), zType, tagid
543 );
544 db_prepare(&q, "%s", blob_sql_text(&sql));
545 blob_reset(&sql);
546 print_timeline(&q, nFindLimit, 79, 0, 0);
547 db_finalize(&q);
548 }
549 }
550 }else
551
552
+1 -1
--- src/tag.c
+++ src/tag.c
@@ -541,11 +541,11 @@
541541
" ORDER BY event.mtime DESC /*sort*/",
542542
timeline_query_for_tty(), zType, tagid
543543
);
544544
db_prepare(&q, "%s", blob_sql_text(&sql));
545545
blob_reset(&sql);
546
- print_timeline(&q, nFindLimit, 79, 0);
546
+ print_timeline(&q, nFindLimit, 79, 0, 0);
547547
db_finalize(&q);
548548
}
549549
}
550550
}else
551551
552552
--- src/tag.c
+++ src/tag.c
@@ -541,11 +541,11 @@
541 " ORDER BY event.mtime DESC /*sort*/",
542 timeline_query_for_tty(), zType, tagid
543 );
544 db_prepare(&q, "%s", blob_sql_text(&sql));
545 blob_reset(&sql);
546 print_timeline(&q, nFindLimit, 79, 0);
547 db_finalize(&q);
548 }
549 }
550 }else
551
552
--- src/tag.c
+++ src/tag.c
@@ -541,11 +541,11 @@
541 " ORDER BY event.mtime DESC /*sort*/",
542 timeline_query_for_tty(), zType, tagid
543 );
544 db_prepare(&q, "%s", blob_sql_text(&sql));
545 blob_reset(&sql);
546 print_timeline(&q, nFindLimit, 79, 0, 0);
547 db_finalize(&q);
548 }
549 }
550 }else
551
552
+161 -7
--- src/timeline.c
+++ src/timeline.c
@@ -2773,10 +2773,105 @@
27732773
@ &nbsp;&darr;</a>
27742774
}
27752775
document_emit_js(/*handles pikchrs rendered above*/);
27762776
style_finish_page();
27772777
}
2778
+
2779
+/*
2780
+** Translate a timeline entry into the printable format by
2781
+** converting every %-substitutions as follows:
2782
+**
2783
+** %n newline
2784
+** %% a raw %
2785
+** %H commit hash
2786
+** %h abbreviated commit hash
2787
+** %a author name
2788
+** %d date
2789
+** %c comment (\n, \t replaced by space, \r deleted)
2790
+** %b branch
2791
+** %t tags
2792
+** %p phase (zero or more of: *CURRENT*, *MERGE*, *FORK*,
2793
+** *UNPUBLISHED*, *LEAF*, *BRANCH*)
2794
+**
2795
+** The returned string is obtained from fossil_malloc() and should
2796
+** be freed by the caller.
2797
+*/
2798
+static char *timeline_entry_subst(
2799
+ const char *zFormat,
2800
+ int *nLine,
2801
+ const char *zId,
2802
+ const char *zDate,
2803
+ const char *zUser,
2804
+ const char *zCom,
2805
+ const char *zBranch,
2806
+ const char *zTags,
2807
+ const char *zPhase
2808
+){
2809
+ Blob r, co;
2810
+ int i, j;
2811
+ blob_init(&r, 0, 0);
2812
+ blob_init(&co, 0, 0);
2813
+
2814
+ /* Replace LF and tab with space, delete CR */
2815
+ while( zCom[0] ){
2816
+ for(j=0; zCom[j] && zCom[j]!='\r' && zCom[j]!='\n' && zCom[j]!='\t'; j++){}
2817
+ blob_append(&co, zCom, j);
2818
+ if( zCom[j]==0 ) break;
2819
+ if( zCom[j]!='\r')
2820
+ blob_append(&co, " ", 1);
2821
+ zCom += j+1;
2822
+ }
2823
+ blob_str(&co);
2824
+
2825
+ *nLine = 1;
2826
+ while( zFormat[0] ){
2827
+ for(i=0; zFormat[i] && zFormat[i]!='%'; i++){}
2828
+ blob_append(&r, zFormat, i);
2829
+ if( zFormat[i]==0 ) break;
2830
+ if( zFormat[i+1]=='%' ){
2831
+ blob_append(&r, "%", 1);
2832
+ zFormat += i+2;
2833
+ }else if( zFormat[i+1]=='n' ){
2834
+ blob_append(&r, "\n", 1);
2835
+ *nLine += 1;
2836
+ zFormat += i+2;
2837
+ }else if( zFormat[i+1]=='H' ){
2838
+ blob_append(&r, zId, -1);
2839
+ zFormat += i+2;
2840
+ }else if( zFormat[i+1]=='h' ){
2841
+ char *zFree = 0;
2842
+ zFree = mprintf("%S", zId);
2843
+ blob_append(&r, zFree, -1);
2844
+ fossil_free(zFree);
2845
+ zFormat += i+2;
2846
+ }else if( zFormat[i+1]=='d' ){
2847
+ blob_append(&r, zDate, -1);
2848
+ zFormat += i+2;
2849
+ }else if( zFormat[i+1]=='a' ){
2850
+ blob_append(&r, zUser, -1);
2851
+ zFormat += i+2;
2852
+ }else if( zFormat[i+1]=='c' ){
2853
+ blob_append(&r, co.aData, -1);
2854
+ zFormat += i+2;
2855
+ }else if( zFormat[i+1]=='b' ){
2856
+ if( zBranch ) blob_append(&r, zBranch, -1);
2857
+ zFormat += i+2;
2858
+ }else if( zFormat[i+1]=='t' ){
2859
+ blob_append(&r, zTags, -1);
2860
+ zFormat += i+2;
2861
+ }else if( zFormat[i+1]=='p' ){
2862
+ blob_append(&r, zPhase, -1);
2863
+ zFormat += i+2;
2864
+ }else{
2865
+ blob_append(&r, zFormat+i, 1);
2866
+ zFormat += i+1;
2867
+ }
2868
+ }
2869
+ fossil_free(co.aData);
2870
+ blob_str(&r);
2871
+ return r.aData;
2872
+}
27782873
27792874
/*
27802875
** The input query q selects various records. Print a human-readable
27812876
** summary of those records.
27822877
**
@@ -2791,18 +2886,21 @@
27912886
** The query should return these columns:
27922887
**
27932888
** 0. rid
27942889
** 1. uuid
27952890
** 2. Date/Time
2796
-** 3. Comment string and user
2891
+** 3. Comment string, user, and tags
27972892
** 4. Number of non-merge children
27982893
** 5. Number of parents
27992894
** 6. mtime
28002895
** 7. branch
28012896
** 8. event-type: 'ci', 'w', 't', 'f', and so forth.
2897
+** 9. comment
2898
+** 10. user
2899
+** 11. tags
28022900
*/
2803
-void print_timeline(Stmt *q, int nLimit, int width, int verboseFlag){
2901
+void print_timeline(Stmt *q, int nLimit, int width, const char *zFormat, int verboseFlag){
28042902
int nAbsLimit = (nLimit >= 0) ? nLimit : -nLimit;
28052903
int nLine = 0;
28062904
int nEntry = 0;
28072905
char zPrevDate[20];
28082906
const char *zCurrentUuid = 0;
@@ -2821,11 +2919,15 @@
28212919
const char *zId = db_column_text(q, 1);
28222920
const char *zDate = db_column_text(q, 2);
28232921
const char *zCom = db_column_text(q, 3);
28242922
int nChild = db_column_int(q, 4);
28252923
int nParent = db_column_int(q, 5);
2924
+ const char *zBranch = db_column_text(q, 7);
28262925
const char *zType = db_column_text(q, 8);
2926
+ const char *zComShort = db_column_text(q, 9);
2927
+ const char *zUserShort = db_column_text(q, 10);
2928
+ const char *zTags = db_column_text(q, 11);
28272929
char *zFree = 0;
28282930
int n = 0;
28292931
char zPrefix[80];
28302932
28312933
if( nAbsLimit!=0 ){
@@ -2835,17 +2937,18 @@
28352937
}else if( nEntry>=nAbsLimit ){
28362938
fossil_print("--- entry limit (%d) reached ---\n", nAbsLimit);
28372939
break; /* entry count limit hit, stop. */
28382940
}
28392941
}
2840
- if( fossil_strnicmp(zDate, zPrevDate, 10) ){
2942
+ if( zFormat == 0 && fossil_strnicmp(zDate, zPrevDate, 10) ){
28412943
fossil_print("=== %.10s ===\n", zDate);
28422944
memcpy(zPrevDate, zDate, 10);
28432945
nLine++; /* record another line */
28442946
}
28452947
if( zCom==0 ) zCom = "";
2846
- fossil_print("%.8s ", &zDate[11]);
2948
+ if( zFormat == 0 )
2949
+ fossil_print("%.8s ", &zDate[11]);
28472950
zPrefix[0] = 0;
28482951
if( nParent>1 ){
28492952
sqlite3_snprintf(sizeof(zPrefix), zPrefix, "*MERGE* ");
28502953
n = strlen(zPrefix);
28512954
}
@@ -2877,12 +2980,27 @@
28772980
zFree = mprintf("[%S] Edit to wiki page \"%s\"", zId, zCom+1);
28782981
}
28792982
}else{
28802983
zFree = mprintf("[%S] %s%s", zId, zPrefix, zCom);
28812984
}
2882
- /* record another X lines */
2883
- nLine += comment_print(zFree, zCom, 9, width, get_comment_format());
2985
+
2986
+ if( zFormat ){
2987
+ if( nChild==0 ){
2988
+ sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], "*LEAF* ");
2989
+ }
2990
+ char *zEntry;
2991
+ int nEntryLine = 0;
2992
+ zEntry = timeline_entry_subst(zFormat, &nEntryLine, zId, zDate, zUserShort,
2993
+ zComShort, zBranch, zTags, zPrefix);
2994
+ nLine += nEntryLine;
2995
+ fossil_print("%s\n", zEntry);
2996
+ fossil_free(zEntry);
2997
+ }
2998
+ else{
2999
+ /* record another X lines */
3000
+ nLine += comment_print(zFree, zCom, 9, width, get_comment_format());
3001
+ }
28843002
fossil_free(zFree);
28853003
28863004
if(verboseFlag){
28873005
if( !fchngQueryInit ){
28883006
db_prepare(&fchngQuery,
@@ -2911,10 +3029,13 @@
29113029
}
29123030
nLine++; /* record another line */
29133031
}
29143032
db_reset(&fchngQuery);
29153033
}
3034
+ /* Except for "oneline", separate formatted entries by one empty line */
3035
+ if( zFormat && fossil_strcmp(zFormat, "%h %c")!=0 )
3036
+ fossil_print("\n");
29163037
nEntry++; /* record another complete entry */
29173038
}
29183039
if( rc==SQLITE_DONE ){
29193040
/* Did the underlying query actually have all entries? */
29203041
if( nAbsLimit==0 ){
@@ -2948,10 +3069,17 @@
29483069
@ AS primPlinkCount,
29493070
@ (SELECT count(*) FROM plink WHERE cid=blob.rid) AS plinkCount,
29503071
@ event.mtime AS mtime,
29513072
@ tagxref.value AS branch,
29523073
@ event.type
3074
+ @ , coalesce(ecomment,comment) AS comment0
3075
+ @ , coalesce(euser,user,'?') AS user0
3076
+ @ , (SELECT case when length(x)>0 then x else '' end
3077
+ @ FROM (SELECT group_concat(substr(tagname,5), ', ') AS x
3078
+ @ FROM tag, tagxref
3079
+ @ WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid
3080
+ @ AND tagxref.rid=blob.rid AND tagxref.tagtype>0)) AS tags
29533081
@ FROM tag CROSS JOIN event CROSS JOIN blob
29543082
@ LEFT JOIN tagxref ON tagxref.tagid=tag.tagid
29553083
@ AND tagxref.tagtype>0
29563084
@ AND tagxref.rid=blob.rid
29573085
@ WHERE blob.rid=event.objid
@@ -2977,10 +3105,11 @@
29773105
*/
29783106
static int fossil_is_julianday(const char *zDate){
29793107
return db_int(0, "SELECT EXISTS (SELECT julianday(%Q) AS jd"
29803108
" WHERE jd IS NOT NULL)", zDate);
29813109
}
3110
+
29823111
29833112
/*
29843113
** COMMAND: timeline
29853114
**
29863115
** Usage: %fossil timeline ?WHEN? ?CHECKIN|DATETIME? ?OPTIONS?
@@ -3023,10 +3152,27 @@
30233152
** etc.) after the check-in comment.
30243153
** -W|--width N Width of lines (default is to auto-detect). N must be
30253154
** either greater than 20 or it ust be zero 0 to
30263155
** indicate no limit, resulting in a single line per
30273156
** entry.
3157
+** -F|--format Entry format. Values "oneline", "medium", and "full"
3158
+** get mapped to the full options below. Otherwise a
3159
+** string which can contain these placeholders:
3160
+** %n newline
3161
+** %% a raw %
3162
+** %H commit hash
3163
+** %h abbreviated commit hash
3164
+** %a author name
3165
+** %d date
3166
+** %c comment (NL, TAB replaced by space, LF deleted)
3167
+** %b branch
3168
+** %t tags
3169
+** %p phase: zero or more of *CURRENT*, *MERGE*,
3170
+** *FORK*, *UNPUBLISHED*, *LEAF*, *BRANCH*
3171
+** --oneline Show only short hash and comment for each entry
3172
+** --medium Medium-verbose entry formatting
3173
+** --full Extra verbose entry formatting
30283174
** -R REPO_FILE Specifies the repository db to use. Default is
30293175
** the current checkout's repository.
30303176
*/
30313177
void timeline_cmd(void){
30323178
Stmt q;
@@ -3042,10 +3188,11 @@
30423188
Blob uuid;
30433189
int mode = TIMELINE_MODE_NONE;
30443190
int verboseFlag = 0 ;
30453191
int iOffset;
30463192
const char *zFilePattern = 0;
3193
+ const char *zFormat = 0;
30473194
Blob treeName;
30483195
int showSql = 0;
30493196
30503197
verboseFlag = find_option("verbose","v", 0)!=0;
30513198
if( !verboseFlag){
@@ -3054,10 +3201,17 @@
30543201
db_find_and_open_repository(0, 0);
30553202
zLimit = find_option("limit","n",1);
30563203
zWidth = find_option("width","W",1);
30573204
zType = find_option("type","t",1);
30583205
zFilePattern = find_option("path","p",1);
3206
+ zFormat = find_option("format","F",1);
3207
+ if( find_option("oneline",0,0)!= 0 || fossil_strcmp(zFormat,"oneline")==0 )
3208
+ zFormat = "%h %c";
3209
+ if( find_option("medium",0,0)!= 0 || fossil_strcmp(zFormat,"medium")==0 )
3210
+ zFormat = "Commit: %h%nDate: %d%nAuthor: %a%nComment: %c";
3211
+ if( find_option("full",0,0)!= 0 || fossil_strcmp(zFormat,"full")==0 )
3212
+ zFormat = "Commit: %H%nDate: %d%nAuthor: %a%nComment: %c%nBranch: %b%nTags: %t%nPrefix: %p";
30593213
showSql = find_option("sql",0,0)!=0;
30603214
30613215
if( !zLimit ){
30623216
zLimit = find_option("count",0,1);
30633217
}
@@ -3203,11 +3357,11 @@
32033357
if( showSql ){
32043358
fossil_print("%s\n", blob_str(&sql));
32053359
}
32063360
db_prepare_blob(&q, &sql);
32073361
blob_reset(&sql);
3208
- print_timeline(&q, n, width, verboseFlag);
3362
+ print_timeline(&q, n, width, zFormat, verboseFlag);
32093363
db_finalize(&q);
32103364
}
32113365
32123366
/*
32133367
** WEBPAGE: thisdayinhistory
32143368
--- src/timeline.c
+++ src/timeline.c
@@ -2773,10 +2773,105 @@
2773 @ &nbsp;&darr;</a>
2774 }
2775 document_emit_js(/*handles pikchrs rendered above*/);
2776 style_finish_page();
2777 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2778
2779 /*
2780 ** The input query q selects various records. Print a human-readable
2781 ** summary of those records.
2782 **
@@ -2791,18 +2886,21 @@
2791 ** The query should return these columns:
2792 **
2793 ** 0. rid
2794 ** 1. uuid
2795 ** 2. Date/Time
2796 ** 3. Comment string and user
2797 ** 4. Number of non-merge children
2798 ** 5. Number of parents
2799 ** 6. mtime
2800 ** 7. branch
2801 ** 8. event-type: 'ci', 'w', 't', 'f', and so forth.
 
 
 
2802 */
2803 void print_timeline(Stmt *q, int nLimit, int width, int verboseFlag){
2804 int nAbsLimit = (nLimit >= 0) ? nLimit : -nLimit;
2805 int nLine = 0;
2806 int nEntry = 0;
2807 char zPrevDate[20];
2808 const char *zCurrentUuid = 0;
@@ -2821,11 +2919,15 @@
2821 const char *zId = db_column_text(q, 1);
2822 const char *zDate = db_column_text(q, 2);
2823 const char *zCom = db_column_text(q, 3);
2824 int nChild = db_column_int(q, 4);
2825 int nParent = db_column_int(q, 5);
 
2826 const char *zType = db_column_text(q, 8);
 
 
 
2827 char *zFree = 0;
2828 int n = 0;
2829 char zPrefix[80];
2830
2831 if( nAbsLimit!=0 ){
@@ -2835,17 +2937,18 @@
2835 }else if( nEntry>=nAbsLimit ){
2836 fossil_print("--- entry limit (%d) reached ---\n", nAbsLimit);
2837 break; /* entry count limit hit, stop. */
2838 }
2839 }
2840 if( fossil_strnicmp(zDate, zPrevDate, 10) ){
2841 fossil_print("=== %.10s ===\n", zDate);
2842 memcpy(zPrevDate, zDate, 10);
2843 nLine++; /* record another line */
2844 }
2845 if( zCom==0 ) zCom = "";
2846 fossil_print("%.8s ", &zDate[11]);
 
2847 zPrefix[0] = 0;
2848 if( nParent>1 ){
2849 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "*MERGE* ");
2850 n = strlen(zPrefix);
2851 }
@@ -2877,12 +2980,27 @@
2877 zFree = mprintf("[%S] Edit to wiki page \"%s\"", zId, zCom+1);
2878 }
2879 }else{
2880 zFree = mprintf("[%S] %s%s", zId, zPrefix, zCom);
2881 }
2882 /* record another X lines */
2883 nLine += comment_print(zFree, zCom, 9, width, get_comment_format());
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2884 fossil_free(zFree);
2885
2886 if(verboseFlag){
2887 if( !fchngQueryInit ){
2888 db_prepare(&fchngQuery,
@@ -2911,10 +3029,13 @@
2911 }
2912 nLine++; /* record another line */
2913 }
2914 db_reset(&fchngQuery);
2915 }
 
 
 
2916 nEntry++; /* record another complete entry */
2917 }
2918 if( rc==SQLITE_DONE ){
2919 /* Did the underlying query actually have all entries? */
2920 if( nAbsLimit==0 ){
@@ -2948,10 +3069,17 @@
2948 @ AS primPlinkCount,
2949 @ (SELECT count(*) FROM plink WHERE cid=blob.rid) AS plinkCount,
2950 @ event.mtime AS mtime,
2951 @ tagxref.value AS branch,
2952 @ event.type
 
 
 
 
 
 
 
2953 @ FROM tag CROSS JOIN event CROSS JOIN blob
2954 @ LEFT JOIN tagxref ON tagxref.tagid=tag.tagid
2955 @ AND tagxref.tagtype>0
2956 @ AND tagxref.rid=blob.rid
2957 @ WHERE blob.rid=event.objid
@@ -2977,10 +3105,11 @@
2977 */
2978 static int fossil_is_julianday(const char *zDate){
2979 return db_int(0, "SELECT EXISTS (SELECT julianday(%Q) AS jd"
2980 " WHERE jd IS NOT NULL)", zDate);
2981 }
 
2982
2983 /*
2984 ** COMMAND: timeline
2985 **
2986 ** Usage: %fossil timeline ?WHEN? ?CHECKIN|DATETIME? ?OPTIONS?
@@ -3023,10 +3152,27 @@
3023 ** etc.) after the check-in comment.
3024 ** -W|--width N Width of lines (default is to auto-detect). N must be
3025 ** either greater than 20 or it ust be zero 0 to
3026 ** indicate no limit, resulting in a single line per
3027 ** entry.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3028 ** -R REPO_FILE Specifies the repository db to use. Default is
3029 ** the current checkout's repository.
3030 */
3031 void timeline_cmd(void){
3032 Stmt q;
@@ -3042,10 +3188,11 @@
3042 Blob uuid;
3043 int mode = TIMELINE_MODE_NONE;
3044 int verboseFlag = 0 ;
3045 int iOffset;
3046 const char *zFilePattern = 0;
 
3047 Blob treeName;
3048 int showSql = 0;
3049
3050 verboseFlag = find_option("verbose","v", 0)!=0;
3051 if( !verboseFlag){
@@ -3054,10 +3201,17 @@
3054 db_find_and_open_repository(0, 0);
3055 zLimit = find_option("limit","n",1);
3056 zWidth = find_option("width","W",1);
3057 zType = find_option("type","t",1);
3058 zFilePattern = find_option("path","p",1);
 
 
 
 
 
 
 
3059 showSql = find_option("sql",0,0)!=0;
3060
3061 if( !zLimit ){
3062 zLimit = find_option("count",0,1);
3063 }
@@ -3203,11 +3357,11 @@
3203 if( showSql ){
3204 fossil_print("%s\n", blob_str(&sql));
3205 }
3206 db_prepare_blob(&q, &sql);
3207 blob_reset(&sql);
3208 print_timeline(&q, n, width, verboseFlag);
3209 db_finalize(&q);
3210 }
3211
3212 /*
3213 ** WEBPAGE: thisdayinhistory
3214
--- src/timeline.c
+++ src/timeline.c
@@ -2773,10 +2773,105 @@
2773 @ &nbsp;&darr;</a>
2774 }
2775 document_emit_js(/*handles pikchrs rendered above*/);
2776 style_finish_page();
2777 }
2778
2779 /*
2780 ** Translate a timeline entry into the printable format by
2781 ** converting every %-substitutions as follows:
2782 **
2783 ** %n newline
2784 ** %% a raw %
2785 ** %H commit hash
2786 ** %h abbreviated commit hash
2787 ** %a author name
2788 ** %d date
2789 ** %c comment (\n, \t replaced by space, \r deleted)
2790 ** %b branch
2791 ** %t tags
2792 ** %p phase (zero or more of: *CURRENT*, *MERGE*, *FORK*,
2793 ** *UNPUBLISHED*, *LEAF*, *BRANCH*)
2794 **
2795 ** The returned string is obtained from fossil_malloc() and should
2796 ** be freed by the caller.
2797 */
2798 static char *timeline_entry_subst(
2799 const char *zFormat,
2800 int *nLine,
2801 const char *zId,
2802 const char *zDate,
2803 const char *zUser,
2804 const char *zCom,
2805 const char *zBranch,
2806 const char *zTags,
2807 const char *zPhase
2808 ){
2809 Blob r, co;
2810 int i, j;
2811 blob_init(&r, 0, 0);
2812 blob_init(&co, 0, 0);
2813
2814 /* Replace LF and tab with space, delete CR */
2815 while( zCom[0] ){
2816 for(j=0; zCom[j] && zCom[j]!='\r' && zCom[j]!='\n' && zCom[j]!='\t'; j++){}
2817 blob_append(&co, zCom, j);
2818 if( zCom[j]==0 ) break;
2819 if( zCom[j]!='\r')
2820 blob_append(&co, " ", 1);
2821 zCom += j+1;
2822 }
2823 blob_str(&co);
2824
2825 *nLine = 1;
2826 while( zFormat[0] ){
2827 for(i=0; zFormat[i] && zFormat[i]!='%'; i++){}
2828 blob_append(&r, zFormat, i);
2829 if( zFormat[i]==0 ) break;
2830 if( zFormat[i+1]=='%' ){
2831 blob_append(&r, "%", 1);
2832 zFormat += i+2;
2833 }else if( zFormat[i+1]=='n' ){
2834 blob_append(&r, "\n", 1);
2835 *nLine += 1;
2836 zFormat += i+2;
2837 }else if( zFormat[i+1]=='H' ){
2838 blob_append(&r, zId, -1);
2839 zFormat += i+2;
2840 }else if( zFormat[i+1]=='h' ){
2841 char *zFree = 0;
2842 zFree = mprintf("%S", zId);
2843 blob_append(&r, zFree, -1);
2844 fossil_free(zFree);
2845 zFormat += i+2;
2846 }else if( zFormat[i+1]=='d' ){
2847 blob_append(&r, zDate, -1);
2848 zFormat += i+2;
2849 }else if( zFormat[i+1]=='a' ){
2850 blob_append(&r, zUser, -1);
2851 zFormat += i+2;
2852 }else if( zFormat[i+1]=='c' ){
2853 blob_append(&r, co.aData, -1);
2854 zFormat += i+2;
2855 }else if( zFormat[i+1]=='b' ){
2856 if( zBranch ) blob_append(&r, zBranch, -1);
2857 zFormat += i+2;
2858 }else if( zFormat[i+1]=='t' ){
2859 blob_append(&r, zTags, -1);
2860 zFormat += i+2;
2861 }else if( zFormat[i+1]=='p' ){
2862 blob_append(&r, zPhase, -1);
2863 zFormat += i+2;
2864 }else{
2865 blob_append(&r, zFormat+i, 1);
2866 zFormat += i+1;
2867 }
2868 }
2869 fossil_free(co.aData);
2870 blob_str(&r);
2871 return r.aData;
2872 }
2873
2874 /*
2875 ** The input query q selects various records. Print a human-readable
2876 ** summary of those records.
2877 **
@@ -2791,18 +2886,21 @@
2886 ** The query should return these columns:
2887 **
2888 ** 0. rid
2889 ** 1. uuid
2890 ** 2. Date/Time
2891 ** 3. Comment string, user, and tags
2892 ** 4. Number of non-merge children
2893 ** 5. Number of parents
2894 ** 6. mtime
2895 ** 7. branch
2896 ** 8. event-type: 'ci', 'w', 't', 'f', and so forth.
2897 ** 9. comment
2898 ** 10. user
2899 ** 11. tags
2900 */
2901 void print_timeline(Stmt *q, int nLimit, int width, const char *zFormat, int verboseFlag){
2902 int nAbsLimit = (nLimit >= 0) ? nLimit : -nLimit;
2903 int nLine = 0;
2904 int nEntry = 0;
2905 char zPrevDate[20];
2906 const char *zCurrentUuid = 0;
@@ -2821,11 +2919,15 @@
2919 const char *zId = db_column_text(q, 1);
2920 const char *zDate = db_column_text(q, 2);
2921 const char *zCom = db_column_text(q, 3);
2922 int nChild = db_column_int(q, 4);
2923 int nParent = db_column_int(q, 5);
2924 const char *zBranch = db_column_text(q, 7);
2925 const char *zType = db_column_text(q, 8);
2926 const char *zComShort = db_column_text(q, 9);
2927 const char *zUserShort = db_column_text(q, 10);
2928 const char *zTags = db_column_text(q, 11);
2929 char *zFree = 0;
2930 int n = 0;
2931 char zPrefix[80];
2932
2933 if( nAbsLimit!=0 ){
@@ -2835,17 +2937,18 @@
2937 }else if( nEntry>=nAbsLimit ){
2938 fossil_print("--- entry limit (%d) reached ---\n", nAbsLimit);
2939 break; /* entry count limit hit, stop. */
2940 }
2941 }
2942 if( zFormat == 0 && fossil_strnicmp(zDate, zPrevDate, 10) ){
2943 fossil_print("=== %.10s ===\n", zDate);
2944 memcpy(zPrevDate, zDate, 10);
2945 nLine++; /* record another line */
2946 }
2947 if( zCom==0 ) zCom = "";
2948 if( zFormat == 0 )
2949 fossil_print("%.8s ", &zDate[11]);
2950 zPrefix[0] = 0;
2951 if( nParent>1 ){
2952 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "*MERGE* ");
2953 n = strlen(zPrefix);
2954 }
@@ -2877,12 +2980,27 @@
2980 zFree = mprintf("[%S] Edit to wiki page \"%s\"", zId, zCom+1);
2981 }
2982 }else{
2983 zFree = mprintf("[%S] %s%s", zId, zPrefix, zCom);
2984 }
2985
2986 if( zFormat ){
2987 if( nChild==0 ){
2988 sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], "*LEAF* ");
2989 }
2990 char *zEntry;
2991 int nEntryLine = 0;
2992 zEntry = timeline_entry_subst(zFormat, &nEntryLine, zId, zDate, zUserShort,
2993 zComShort, zBranch, zTags, zPrefix);
2994 nLine += nEntryLine;
2995 fossil_print("%s\n", zEntry);
2996 fossil_free(zEntry);
2997 }
2998 else{
2999 /* record another X lines */
3000 nLine += comment_print(zFree, zCom, 9, width, get_comment_format());
3001 }
3002 fossil_free(zFree);
3003
3004 if(verboseFlag){
3005 if( !fchngQueryInit ){
3006 db_prepare(&fchngQuery,
@@ -2911,10 +3029,13 @@
3029 }
3030 nLine++; /* record another line */
3031 }
3032 db_reset(&fchngQuery);
3033 }
3034 /* Except for "oneline", separate formatted entries by one empty line */
3035 if( zFormat && fossil_strcmp(zFormat, "%h %c")!=0 )
3036 fossil_print("\n");
3037 nEntry++; /* record another complete entry */
3038 }
3039 if( rc==SQLITE_DONE ){
3040 /* Did the underlying query actually have all entries? */
3041 if( nAbsLimit==0 ){
@@ -2948,10 +3069,17 @@
3069 @ AS primPlinkCount,
3070 @ (SELECT count(*) FROM plink WHERE cid=blob.rid) AS plinkCount,
3071 @ event.mtime AS mtime,
3072 @ tagxref.value AS branch,
3073 @ event.type
3074 @ , coalesce(ecomment,comment) AS comment0
3075 @ , coalesce(euser,user,'?') AS user0
3076 @ , (SELECT case when length(x)>0 then x else '' end
3077 @ FROM (SELECT group_concat(substr(tagname,5), ', ') AS x
3078 @ FROM tag, tagxref
3079 @ WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid
3080 @ AND tagxref.rid=blob.rid AND tagxref.tagtype>0)) AS tags
3081 @ FROM tag CROSS JOIN event CROSS JOIN blob
3082 @ LEFT JOIN tagxref ON tagxref.tagid=tag.tagid
3083 @ AND tagxref.tagtype>0
3084 @ AND tagxref.rid=blob.rid
3085 @ WHERE blob.rid=event.objid
@@ -2977,10 +3105,11 @@
3105 */
3106 static int fossil_is_julianday(const char *zDate){
3107 return db_int(0, "SELECT EXISTS (SELECT julianday(%Q) AS jd"
3108 " WHERE jd IS NOT NULL)", zDate);
3109 }
3110
3111
3112 /*
3113 ** COMMAND: timeline
3114 **
3115 ** Usage: %fossil timeline ?WHEN? ?CHECKIN|DATETIME? ?OPTIONS?
@@ -3023,10 +3152,27 @@
3152 ** etc.) after the check-in comment.
3153 ** -W|--width N Width of lines (default is to auto-detect). N must be
3154 ** either greater than 20 or it ust be zero 0 to
3155 ** indicate no limit, resulting in a single line per
3156 ** entry.
3157 ** -F|--format Entry format. Values "oneline", "medium", and "full"
3158 ** get mapped to the full options below. Otherwise a
3159 ** string which can contain these placeholders:
3160 ** %n newline
3161 ** %% a raw %
3162 ** %H commit hash
3163 ** %h abbreviated commit hash
3164 ** %a author name
3165 ** %d date
3166 ** %c comment (NL, TAB replaced by space, LF deleted)
3167 ** %b branch
3168 ** %t tags
3169 ** %p phase: zero or more of *CURRENT*, *MERGE*,
3170 ** *FORK*, *UNPUBLISHED*, *LEAF*, *BRANCH*
3171 ** --oneline Show only short hash and comment for each entry
3172 ** --medium Medium-verbose entry formatting
3173 ** --full Extra verbose entry formatting
3174 ** -R REPO_FILE Specifies the repository db to use. Default is
3175 ** the current checkout's repository.
3176 */
3177 void timeline_cmd(void){
3178 Stmt q;
@@ -3042,10 +3188,11 @@
3188 Blob uuid;
3189 int mode = TIMELINE_MODE_NONE;
3190 int verboseFlag = 0 ;
3191 int iOffset;
3192 const char *zFilePattern = 0;
3193 const char *zFormat = 0;
3194 Blob treeName;
3195 int showSql = 0;
3196
3197 verboseFlag = find_option("verbose","v", 0)!=0;
3198 if( !verboseFlag){
@@ -3054,10 +3201,17 @@
3201 db_find_and_open_repository(0, 0);
3202 zLimit = find_option("limit","n",1);
3203 zWidth = find_option("width","W",1);
3204 zType = find_option("type","t",1);
3205 zFilePattern = find_option("path","p",1);
3206 zFormat = find_option("format","F",1);
3207 if( find_option("oneline",0,0)!= 0 || fossil_strcmp(zFormat,"oneline")==0 )
3208 zFormat = "%h %c";
3209 if( find_option("medium",0,0)!= 0 || fossil_strcmp(zFormat,"medium")==0 )
3210 zFormat = "Commit: %h%nDate: %d%nAuthor: %a%nComment: %c";
3211 if( find_option("full",0,0)!= 0 || fossil_strcmp(zFormat,"full")==0 )
3212 zFormat = "Commit: %H%nDate: %d%nAuthor: %a%nComment: %c%nBranch: %b%nTags: %t%nPrefix: %p";
3213 showSql = find_option("sql",0,0)!=0;
3214
3215 if( !zLimit ){
3216 zLimit = find_option("count",0,1);
3217 }
@@ -3203,11 +3357,11 @@
3357 if( showSql ){
3358 fossil_print("%s\n", blob_str(&sql));
3359 }
3360 db_prepare_blob(&q, &sql);
3361 blob_reset(&sql);
3362 print_timeline(&q, n, width, zFormat, verboseFlag);
3363 db_finalize(&q);
3364 }
3365
3366 /*
3367 ** WEBPAGE: thisdayinhistory
3368
+161 -7
--- src/timeline.c
+++ src/timeline.c
@@ -2773,10 +2773,105 @@
27732773
@ &nbsp;&darr;</a>
27742774
}
27752775
document_emit_js(/*handles pikchrs rendered above*/);
27762776
style_finish_page();
27772777
}
2778
+
2779
+/*
2780
+** Translate a timeline entry into the printable format by
2781
+** converting every %-substitutions as follows:
2782
+**
2783
+** %n newline
2784
+** %% a raw %
2785
+** %H commit hash
2786
+** %h abbreviated commit hash
2787
+** %a author name
2788
+** %d date
2789
+** %c comment (\n, \t replaced by space, \r deleted)
2790
+** %b branch
2791
+** %t tags
2792
+** %p phase (zero or more of: *CURRENT*, *MERGE*, *FORK*,
2793
+** *UNPUBLISHED*, *LEAF*, *BRANCH*)
2794
+**
2795
+** The returned string is obtained from fossil_malloc() and should
2796
+** be freed by the caller.
2797
+*/
2798
+static char *timeline_entry_subst(
2799
+ const char *zFormat,
2800
+ int *nLine,
2801
+ const char *zId,
2802
+ const char *zDate,
2803
+ const char *zUser,
2804
+ const char *zCom,
2805
+ const char *zBranch,
2806
+ const char *zTags,
2807
+ const char *zPhase
2808
+){
2809
+ Blob r, co;
2810
+ int i, j;
2811
+ blob_init(&r, 0, 0);
2812
+ blob_init(&co, 0, 0);
2813
+
2814
+ /* Replace LF and tab with space, delete CR */
2815
+ while( zCom[0] ){
2816
+ for(j=0; zCom[j] && zCom[j]!='\r' && zCom[j]!='\n' && zCom[j]!='\t'; j++){}
2817
+ blob_append(&co, zCom, j);
2818
+ if( zCom[j]==0 ) break;
2819
+ if( zCom[j]!='\r')
2820
+ blob_append(&co, " ", 1);
2821
+ zCom += j+1;
2822
+ }
2823
+ blob_str(&co);
2824
+
2825
+ *nLine = 1;
2826
+ while( zFormat[0] ){
2827
+ for(i=0; zFormat[i] && zFormat[i]!='%'; i++){}
2828
+ blob_append(&r, zFormat, i);
2829
+ if( zFormat[i]==0 ) break;
2830
+ if( zFormat[i+1]=='%' ){
2831
+ blob_append(&r, "%", 1);
2832
+ zFormat += i+2;
2833
+ }else if( zFormat[i+1]=='n' ){
2834
+ blob_append(&r, "\n", 1);
2835
+ *nLine += 1;
2836
+ zFormat += i+2;
2837
+ }else if( zFormat[i+1]=='H' ){
2838
+ blob_append(&r, zId, -1);
2839
+ zFormat += i+2;
2840
+ }else if( zFormat[i+1]=='h' ){
2841
+ char *zFree = 0;
2842
+ zFree = mprintf("%S", zId);
2843
+ blob_append(&r, zFree, -1);
2844
+ fossil_free(zFree);
2845
+ zFormat += i+2;
2846
+ }else if( zFormat[i+1]=='d' ){
2847
+ blob_append(&r, zDate, -1);
2848
+ zFormat += i+2;
2849
+ }else if( zFormat[i+1]=='a' ){
2850
+ blob_append(&r, zUser, -1);
2851
+ zFormat += i+2;
2852
+ }else if( zFormat[i+1]=='c' ){
2853
+ blob_append(&r, co.aData, -1);
2854
+ zFormat += i+2;
2855
+ }else if( zFormat[i+1]=='b' ){
2856
+ if( zBranch ) blob_append(&r, zBranch, -1);
2857
+ zFormat += i+2;
2858
+ }else if( zFormat[i+1]=='t' ){
2859
+ blob_append(&r, zTags, -1);
2860
+ zFormat += i+2;
2861
+ }else if( zFormat[i+1]=='p' ){
2862
+ blob_append(&r, zPhase, -1);
2863
+ zFormat += i+2;
2864
+ }else{
2865
+ blob_append(&r, zFormat+i, 1);
2866
+ zFormat += i+1;
2867
+ }
2868
+ }
2869
+ fossil_free(co.aData);
2870
+ blob_str(&r);
2871
+ return r.aData;
2872
+}
27782873
27792874
/*
27802875
** The input query q selects various records. Print a human-readable
27812876
** summary of those records.
27822877
**
@@ -2791,18 +2886,21 @@
27912886
** The query should return these columns:
27922887
**
27932888
** 0. rid
27942889
** 1. uuid
27952890
** 2. Date/Time
2796
-** 3. Comment string and user
2891
+** 3. Comment string, user, and tags
27972892
** 4. Number of non-merge children
27982893
** 5. Number of parents
27992894
** 6. mtime
28002895
** 7. branch
28012896
** 8. event-type: 'ci', 'w', 't', 'f', and so forth.
2897
+** 9. comment
2898
+** 10. user
2899
+** 11. tags
28022900
*/
2803
-void print_timeline(Stmt *q, int nLimit, int width, int verboseFlag){
2901
+void print_timeline(Stmt *q, int nLimit, int width, const char *zFormat, int verboseFlag){
28042902
int nAbsLimit = (nLimit >= 0) ? nLimit : -nLimit;
28052903
int nLine = 0;
28062904
int nEntry = 0;
28072905
char zPrevDate[20];
28082906
const char *zCurrentUuid = 0;
@@ -2821,11 +2919,15 @@
28212919
const char *zId = db_column_text(q, 1);
28222920
const char *zDate = db_column_text(q, 2);
28232921
const char *zCom = db_column_text(q, 3);
28242922
int nChild = db_column_int(q, 4);
28252923
int nParent = db_column_int(q, 5);
2924
+ const char *zBranch = db_column_text(q, 7);
28262925
const char *zType = db_column_text(q, 8);
2926
+ const char *zComShort = db_column_text(q, 9);
2927
+ const char *zUserShort = db_column_text(q, 10);
2928
+ const char *zTags = db_column_text(q, 11);
28272929
char *zFree = 0;
28282930
int n = 0;
28292931
char zPrefix[80];
28302932
28312933
if( nAbsLimit!=0 ){
@@ -2835,17 +2937,18 @@
28352937
}else if( nEntry>=nAbsLimit ){
28362938
fossil_print("--- entry limit (%d) reached ---\n", nAbsLimit);
28372939
break; /* entry count limit hit, stop. */
28382940
}
28392941
}
2840
- if( fossil_strnicmp(zDate, zPrevDate, 10) ){
2942
+ if( zFormat == 0 && fossil_strnicmp(zDate, zPrevDate, 10) ){
28412943
fossil_print("=== %.10s ===\n", zDate);
28422944
memcpy(zPrevDate, zDate, 10);
28432945
nLine++; /* record another line */
28442946
}
28452947
if( zCom==0 ) zCom = "";
2846
- fossil_print("%.8s ", &zDate[11]);
2948
+ if( zFormat == 0 )
2949
+ fossil_print("%.8s ", &zDate[11]);
28472950
zPrefix[0] = 0;
28482951
if( nParent>1 ){
28492952
sqlite3_snprintf(sizeof(zPrefix), zPrefix, "*MERGE* ");
28502953
n = strlen(zPrefix);
28512954
}
@@ -2877,12 +2980,27 @@
28772980
zFree = mprintf("[%S] Edit to wiki page \"%s\"", zId, zCom+1);
28782981
}
28792982
}else{
28802983
zFree = mprintf("[%S] %s%s", zId, zPrefix, zCom);
28812984
}
2882
- /* record another X lines */
2883
- nLine += comment_print(zFree, zCom, 9, width, get_comment_format());
2985
+
2986
+ if( zFormat ){
2987
+ if( nChild==0 ){
2988
+ sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], "*LEAF* ");
2989
+ }
2990
+ char *zEntry;
2991
+ int nEntryLine = 0;
2992
+ zEntry = timeline_entry_subst(zFormat, &nEntryLine, zId, zDate, zUserShort,
2993
+ zComShort, zBranch, zTags, zPrefix);
2994
+ nLine += nEntryLine;
2995
+ fossil_print("%s\n", zEntry);
2996
+ fossil_free(zEntry);
2997
+ }
2998
+ else{
2999
+ /* record another X lines */
3000
+ nLine += comment_print(zFree, zCom, 9, width, get_comment_format());
3001
+ }
28843002
fossil_free(zFree);
28853003
28863004
if(verboseFlag){
28873005
if( !fchngQueryInit ){
28883006
db_prepare(&fchngQuery,
@@ -2911,10 +3029,13 @@
29113029
}
29123030
nLine++; /* record another line */
29133031
}
29143032
db_reset(&fchngQuery);
29153033
}
3034
+ /* Except for "oneline", separate formatted entries by one empty line */
3035
+ if( zFormat && fossil_strcmp(zFormat, "%h %c")!=0 )
3036
+ fossil_print("\n");
29163037
nEntry++; /* record another complete entry */
29173038
}
29183039
if( rc==SQLITE_DONE ){
29193040
/* Did the underlying query actually have all entries? */
29203041
if( nAbsLimit==0 ){
@@ -2948,10 +3069,17 @@
29483069
@ AS primPlinkCount,
29493070
@ (SELECT count(*) FROM plink WHERE cid=blob.rid) AS plinkCount,
29503071
@ event.mtime AS mtime,
29513072
@ tagxref.value AS branch,
29523073
@ event.type
3074
+ @ , coalesce(ecomment,comment) AS comment0
3075
+ @ , coalesce(euser,user,'?') AS user0
3076
+ @ , (SELECT case when length(x)>0 then x else '' end
3077
+ @ FROM (SELECT group_concat(substr(tagname,5), ', ') AS x
3078
+ @ FROM tag, tagxref
3079
+ @ WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid
3080
+ @ AND tagxref.rid=blob.rid AND tagxref.tagtype>0)) AS tags
29533081
@ FROM tag CROSS JOIN event CROSS JOIN blob
29543082
@ LEFT JOIN tagxref ON tagxref.tagid=tag.tagid
29553083
@ AND tagxref.tagtype>0
29563084
@ AND tagxref.rid=blob.rid
29573085
@ WHERE blob.rid=event.objid
@@ -2977,10 +3105,11 @@
29773105
*/
29783106
static int fossil_is_julianday(const char *zDate){
29793107
return db_int(0, "SELECT EXISTS (SELECT julianday(%Q) AS jd"
29803108
" WHERE jd IS NOT NULL)", zDate);
29813109
}
3110
+
29823111
29833112
/*
29843113
** COMMAND: timeline
29853114
**
29863115
** Usage: %fossil timeline ?WHEN? ?CHECKIN|DATETIME? ?OPTIONS?
@@ -3023,10 +3152,27 @@
30233152
** etc.) after the check-in comment.
30243153
** -W|--width N Width of lines (default is to auto-detect). N must be
30253154
** either greater than 20 or it ust be zero 0 to
30263155
** indicate no limit, resulting in a single line per
30273156
** entry.
3157
+** -F|--format Entry format. Values "oneline", "medium", and "full"
3158
+** get mapped to the full options below. Otherwise a
3159
+** string which can contain these placeholders:
3160
+** %n newline
3161
+** %% a raw %
3162
+** %H commit hash
3163
+** %h abbreviated commit hash
3164
+** %a author name
3165
+** %d date
3166
+** %c comment (NL, TAB replaced by space, LF deleted)
3167
+** %b branch
3168
+** %t tags
3169
+** %p phase: zero or more of *CURRENT*, *MERGE*,
3170
+** *FORK*, *UNPUBLISHED*, *LEAF*, *BRANCH*
3171
+** --oneline Show only short hash and comment for each entry
3172
+** --medium Medium-verbose entry formatting
3173
+** --full Extra verbose entry formatting
30283174
** -R REPO_FILE Specifies the repository db to use. Default is
30293175
** the current checkout's repository.
30303176
*/
30313177
void timeline_cmd(void){
30323178
Stmt q;
@@ -3042,10 +3188,11 @@
30423188
Blob uuid;
30433189
int mode = TIMELINE_MODE_NONE;
30443190
int verboseFlag = 0 ;
30453191
int iOffset;
30463192
const char *zFilePattern = 0;
3193
+ const char *zFormat = 0;
30473194
Blob treeName;
30483195
int showSql = 0;
30493196
30503197
verboseFlag = find_option("verbose","v", 0)!=0;
30513198
if( !verboseFlag){
@@ -3054,10 +3201,17 @@
30543201
db_find_and_open_repository(0, 0);
30553202
zLimit = find_option("limit","n",1);
30563203
zWidth = find_option("width","W",1);
30573204
zType = find_option("type","t",1);
30583205
zFilePattern = find_option("path","p",1);
3206
+ zFormat = find_option("format","F",1);
3207
+ if( find_option("oneline",0,0)!= 0 || fossil_strcmp(zFormat,"oneline")==0 )
3208
+ zFormat = "%h %c";
3209
+ if( find_option("medium",0,0)!= 0 || fossil_strcmp(zFormat,"medium")==0 )
3210
+ zFormat = "Commit: %h%nDate: %d%nAuthor: %a%nComment: %c";
3211
+ if( find_option("full",0,0)!= 0 || fossil_strcmp(zFormat,"full")==0 )
3212
+ zFormat = "Commit: %H%nDate: %d%nAuthor: %a%nComment: %c%nBranch: %b%nTags: %t%nPrefix: %p";
30593213
showSql = find_option("sql",0,0)!=0;
30603214
30613215
if( !zLimit ){
30623216
zLimit = find_option("count",0,1);
30633217
}
@@ -3203,11 +3357,11 @@
32033357
if( showSql ){
32043358
fossil_print("%s\n", blob_str(&sql));
32053359
}
32063360
db_prepare_blob(&q, &sql);
32073361
blob_reset(&sql);
3208
- print_timeline(&q, n, width, verboseFlag);
3362
+ print_timeline(&q, n, width, zFormat, verboseFlag);
32093363
db_finalize(&q);
32103364
}
32113365
32123366
/*
32133367
** WEBPAGE: thisdayinhistory
32143368
--- src/timeline.c
+++ src/timeline.c
@@ -2773,10 +2773,105 @@
2773 @ &nbsp;&darr;</a>
2774 }
2775 document_emit_js(/*handles pikchrs rendered above*/);
2776 style_finish_page();
2777 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2778
2779 /*
2780 ** The input query q selects various records. Print a human-readable
2781 ** summary of those records.
2782 **
@@ -2791,18 +2886,21 @@
2791 ** The query should return these columns:
2792 **
2793 ** 0. rid
2794 ** 1. uuid
2795 ** 2. Date/Time
2796 ** 3. Comment string and user
2797 ** 4. Number of non-merge children
2798 ** 5. Number of parents
2799 ** 6. mtime
2800 ** 7. branch
2801 ** 8. event-type: 'ci', 'w', 't', 'f', and so forth.
 
 
 
2802 */
2803 void print_timeline(Stmt *q, int nLimit, int width, int verboseFlag){
2804 int nAbsLimit = (nLimit >= 0) ? nLimit : -nLimit;
2805 int nLine = 0;
2806 int nEntry = 0;
2807 char zPrevDate[20];
2808 const char *zCurrentUuid = 0;
@@ -2821,11 +2919,15 @@
2821 const char *zId = db_column_text(q, 1);
2822 const char *zDate = db_column_text(q, 2);
2823 const char *zCom = db_column_text(q, 3);
2824 int nChild = db_column_int(q, 4);
2825 int nParent = db_column_int(q, 5);
 
2826 const char *zType = db_column_text(q, 8);
 
 
 
2827 char *zFree = 0;
2828 int n = 0;
2829 char zPrefix[80];
2830
2831 if( nAbsLimit!=0 ){
@@ -2835,17 +2937,18 @@
2835 }else if( nEntry>=nAbsLimit ){
2836 fossil_print("--- entry limit (%d) reached ---\n", nAbsLimit);
2837 break; /* entry count limit hit, stop. */
2838 }
2839 }
2840 if( fossil_strnicmp(zDate, zPrevDate, 10) ){
2841 fossil_print("=== %.10s ===\n", zDate);
2842 memcpy(zPrevDate, zDate, 10);
2843 nLine++; /* record another line */
2844 }
2845 if( zCom==0 ) zCom = "";
2846 fossil_print("%.8s ", &zDate[11]);
 
2847 zPrefix[0] = 0;
2848 if( nParent>1 ){
2849 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "*MERGE* ");
2850 n = strlen(zPrefix);
2851 }
@@ -2877,12 +2980,27 @@
2877 zFree = mprintf("[%S] Edit to wiki page \"%s\"", zId, zCom+1);
2878 }
2879 }else{
2880 zFree = mprintf("[%S] %s%s", zId, zPrefix, zCom);
2881 }
2882 /* record another X lines */
2883 nLine += comment_print(zFree, zCom, 9, width, get_comment_format());
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2884 fossil_free(zFree);
2885
2886 if(verboseFlag){
2887 if( !fchngQueryInit ){
2888 db_prepare(&fchngQuery,
@@ -2911,10 +3029,13 @@
2911 }
2912 nLine++; /* record another line */
2913 }
2914 db_reset(&fchngQuery);
2915 }
 
 
 
2916 nEntry++; /* record another complete entry */
2917 }
2918 if( rc==SQLITE_DONE ){
2919 /* Did the underlying query actually have all entries? */
2920 if( nAbsLimit==0 ){
@@ -2948,10 +3069,17 @@
2948 @ AS primPlinkCount,
2949 @ (SELECT count(*) FROM plink WHERE cid=blob.rid) AS plinkCount,
2950 @ event.mtime AS mtime,
2951 @ tagxref.value AS branch,
2952 @ event.type
 
 
 
 
 
 
 
2953 @ FROM tag CROSS JOIN event CROSS JOIN blob
2954 @ LEFT JOIN tagxref ON tagxref.tagid=tag.tagid
2955 @ AND tagxref.tagtype>0
2956 @ AND tagxref.rid=blob.rid
2957 @ WHERE blob.rid=event.objid
@@ -2977,10 +3105,11 @@
2977 */
2978 static int fossil_is_julianday(const char *zDate){
2979 return db_int(0, "SELECT EXISTS (SELECT julianday(%Q) AS jd"
2980 " WHERE jd IS NOT NULL)", zDate);
2981 }
 
2982
2983 /*
2984 ** COMMAND: timeline
2985 **
2986 ** Usage: %fossil timeline ?WHEN? ?CHECKIN|DATETIME? ?OPTIONS?
@@ -3023,10 +3152,27 @@
3023 ** etc.) after the check-in comment.
3024 ** -W|--width N Width of lines (default is to auto-detect). N must be
3025 ** either greater than 20 or it ust be zero 0 to
3026 ** indicate no limit, resulting in a single line per
3027 ** entry.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3028 ** -R REPO_FILE Specifies the repository db to use. Default is
3029 ** the current checkout's repository.
3030 */
3031 void timeline_cmd(void){
3032 Stmt q;
@@ -3042,10 +3188,11 @@
3042 Blob uuid;
3043 int mode = TIMELINE_MODE_NONE;
3044 int verboseFlag = 0 ;
3045 int iOffset;
3046 const char *zFilePattern = 0;
 
3047 Blob treeName;
3048 int showSql = 0;
3049
3050 verboseFlag = find_option("verbose","v", 0)!=0;
3051 if( !verboseFlag){
@@ -3054,10 +3201,17 @@
3054 db_find_and_open_repository(0, 0);
3055 zLimit = find_option("limit","n",1);
3056 zWidth = find_option("width","W",1);
3057 zType = find_option("type","t",1);
3058 zFilePattern = find_option("path","p",1);
 
 
 
 
 
 
 
3059 showSql = find_option("sql",0,0)!=0;
3060
3061 if( !zLimit ){
3062 zLimit = find_option("count",0,1);
3063 }
@@ -3203,11 +3357,11 @@
3203 if( showSql ){
3204 fossil_print("%s\n", blob_str(&sql));
3205 }
3206 db_prepare_blob(&q, &sql);
3207 blob_reset(&sql);
3208 print_timeline(&q, n, width, verboseFlag);
3209 db_finalize(&q);
3210 }
3211
3212 /*
3213 ** WEBPAGE: thisdayinhistory
3214
--- src/timeline.c
+++ src/timeline.c
@@ -2773,10 +2773,105 @@
2773 @ &nbsp;&darr;</a>
2774 }
2775 document_emit_js(/*handles pikchrs rendered above*/);
2776 style_finish_page();
2777 }
2778
2779 /*
2780 ** Translate a timeline entry into the printable format by
2781 ** converting every %-substitutions as follows:
2782 **
2783 ** %n newline
2784 ** %% a raw %
2785 ** %H commit hash
2786 ** %h abbreviated commit hash
2787 ** %a author name
2788 ** %d date
2789 ** %c comment (\n, \t replaced by space, \r deleted)
2790 ** %b branch
2791 ** %t tags
2792 ** %p phase (zero or more of: *CURRENT*, *MERGE*, *FORK*,
2793 ** *UNPUBLISHED*, *LEAF*, *BRANCH*)
2794 **
2795 ** The returned string is obtained from fossil_malloc() and should
2796 ** be freed by the caller.
2797 */
2798 static char *timeline_entry_subst(
2799 const char *zFormat,
2800 int *nLine,
2801 const char *zId,
2802 const char *zDate,
2803 const char *zUser,
2804 const char *zCom,
2805 const char *zBranch,
2806 const char *zTags,
2807 const char *zPhase
2808 ){
2809 Blob r, co;
2810 int i, j;
2811 blob_init(&r, 0, 0);
2812 blob_init(&co, 0, 0);
2813
2814 /* Replace LF and tab with space, delete CR */
2815 while( zCom[0] ){
2816 for(j=0; zCom[j] && zCom[j]!='\r' && zCom[j]!='\n' && zCom[j]!='\t'; j++){}
2817 blob_append(&co, zCom, j);
2818 if( zCom[j]==0 ) break;
2819 if( zCom[j]!='\r')
2820 blob_append(&co, " ", 1);
2821 zCom += j+1;
2822 }
2823 blob_str(&co);
2824
2825 *nLine = 1;
2826 while( zFormat[0] ){
2827 for(i=0; zFormat[i] && zFormat[i]!='%'; i++){}
2828 blob_append(&r, zFormat, i);
2829 if( zFormat[i]==0 ) break;
2830 if( zFormat[i+1]=='%' ){
2831 blob_append(&r, "%", 1);
2832 zFormat += i+2;
2833 }else if( zFormat[i+1]=='n' ){
2834 blob_append(&r, "\n", 1);
2835 *nLine += 1;
2836 zFormat += i+2;
2837 }else if( zFormat[i+1]=='H' ){
2838 blob_append(&r, zId, -1);
2839 zFormat += i+2;
2840 }else if( zFormat[i+1]=='h' ){
2841 char *zFree = 0;
2842 zFree = mprintf("%S", zId);
2843 blob_append(&r, zFree, -1);
2844 fossil_free(zFree);
2845 zFormat += i+2;
2846 }else if( zFormat[i+1]=='d' ){
2847 blob_append(&r, zDate, -1);
2848 zFormat += i+2;
2849 }else if( zFormat[i+1]=='a' ){
2850 blob_append(&r, zUser, -1);
2851 zFormat += i+2;
2852 }else if( zFormat[i+1]=='c' ){
2853 blob_append(&r, co.aData, -1);
2854 zFormat += i+2;
2855 }else if( zFormat[i+1]=='b' ){
2856 if( zBranch ) blob_append(&r, zBranch, -1);
2857 zFormat += i+2;
2858 }else if( zFormat[i+1]=='t' ){
2859 blob_append(&r, zTags, -1);
2860 zFormat += i+2;
2861 }else if( zFormat[i+1]=='p' ){
2862 blob_append(&r, zPhase, -1);
2863 zFormat += i+2;
2864 }else{
2865 blob_append(&r, zFormat+i, 1);
2866 zFormat += i+1;
2867 }
2868 }
2869 fossil_free(co.aData);
2870 blob_str(&r);
2871 return r.aData;
2872 }
2873
2874 /*
2875 ** The input query q selects various records. Print a human-readable
2876 ** summary of those records.
2877 **
@@ -2791,18 +2886,21 @@
2886 ** The query should return these columns:
2887 **
2888 ** 0. rid
2889 ** 1. uuid
2890 ** 2. Date/Time
2891 ** 3. Comment string, user, and tags
2892 ** 4. Number of non-merge children
2893 ** 5. Number of parents
2894 ** 6. mtime
2895 ** 7. branch
2896 ** 8. event-type: 'ci', 'w', 't', 'f', and so forth.
2897 ** 9. comment
2898 ** 10. user
2899 ** 11. tags
2900 */
2901 void print_timeline(Stmt *q, int nLimit, int width, const char *zFormat, int verboseFlag){
2902 int nAbsLimit = (nLimit >= 0) ? nLimit : -nLimit;
2903 int nLine = 0;
2904 int nEntry = 0;
2905 char zPrevDate[20];
2906 const char *zCurrentUuid = 0;
@@ -2821,11 +2919,15 @@
2919 const char *zId = db_column_text(q, 1);
2920 const char *zDate = db_column_text(q, 2);
2921 const char *zCom = db_column_text(q, 3);
2922 int nChild = db_column_int(q, 4);
2923 int nParent = db_column_int(q, 5);
2924 const char *zBranch = db_column_text(q, 7);
2925 const char *zType = db_column_text(q, 8);
2926 const char *zComShort = db_column_text(q, 9);
2927 const char *zUserShort = db_column_text(q, 10);
2928 const char *zTags = db_column_text(q, 11);
2929 char *zFree = 0;
2930 int n = 0;
2931 char zPrefix[80];
2932
2933 if( nAbsLimit!=0 ){
@@ -2835,17 +2937,18 @@
2937 }else if( nEntry>=nAbsLimit ){
2938 fossil_print("--- entry limit (%d) reached ---\n", nAbsLimit);
2939 break; /* entry count limit hit, stop. */
2940 }
2941 }
2942 if( zFormat == 0 && fossil_strnicmp(zDate, zPrevDate, 10) ){
2943 fossil_print("=== %.10s ===\n", zDate);
2944 memcpy(zPrevDate, zDate, 10);
2945 nLine++; /* record another line */
2946 }
2947 if( zCom==0 ) zCom = "";
2948 if( zFormat == 0 )
2949 fossil_print("%.8s ", &zDate[11]);
2950 zPrefix[0] = 0;
2951 if( nParent>1 ){
2952 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "*MERGE* ");
2953 n = strlen(zPrefix);
2954 }
@@ -2877,12 +2980,27 @@
2980 zFree = mprintf("[%S] Edit to wiki page \"%s\"", zId, zCom+1);
2981 }
2982 }else{
2983 zFree = mprintf("[%S] %s%s", zId, zPrefix, zCom);
2984 }
2985
2986 if( zFormat ){
2987 if( nChild==0 ){
2988 sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], "*LEAF* ");
2989 }
2990 char *zEntry;
2991 int nEntryLine = 0;
2992 zEntry = timeline_entry_subst(zFormat, &nEntryLine, zId, zDate, zUserShort,
2993 zComShort, zBranch, zTags, zPrefix);
2994 nLine += nEntryLine;
2995 fossil_print("%s\n", zEntry);
2996 fossil_free(zEntry);
2997 }
2998 else{
2999 /* record another X lines */
3000 nLine += comment_print(zFree, zCom, 9, width, get_comment_format());
3001 }
3002 fossil_free(zFree);
3003
3004 if(verboseFlag){
3005 if( !fchngQueryInit ){
3006 db_prepare(&fchngQuery,
@@ -2911,10 +3029,13 @@
3029 }
3030 nLine++; /* record another line */
3031 }
3032 db_reset(&fchngQuery);
3033 }
3034 /* Except for "oneline", separate formatted entries by one empty line */
3035 if( zFormat && fossil_strcmp(zFormat, "%h %c")!=0 )
3036 fossil_print("\n");
3037 nEntry++; /* record another complete entry */
3038 }
3039 if( rc==SQLITE_DONE ){
3040 /* Did the underlying query actually have all entries? */
3041 if( nAbsLimit==0 ){
@@ -2948,10 +3069,17 @@
3069 @ AS primPlinkCount,
3070 @ (SELECT count(*) FROM plink WHERE cid=blob.rid) AS plinkCount,
3071 @ event.mtime AS mtime,
3072 @ tagxref.value AS branch,
3073 @ event.type
3074 @ , coalesce(ecomment,comment) AS comment0
3075 @ , coalesce(euser,user,'?') AS user0
3076 @ , (SELECT case when length(x)>0 then x else '' end
3077 @ FROM (SELECT group_concat(substr(tagname,5), ', ') AS x
3078 @ FROM tag, tagxref
3079 @ WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid
3080 @ AND tagxref.rid=blob.rid AND tagxref.tagtype>0)) AS tags
3081 @ FROM tag CROSS JOIN event CROSS JOIN blob
3082 @ LEFT JOIN tagxref ON tagxref.tagid=tag.tagid
3083 @ AND tagxref.tagtype>0
3084 @ AND tagxref.rid=blob.rid
3085 @ WHERE blob.rid=event.objid
@@ -2977,10 +3105,11 @@
3105 */
3106 static int fossil_is_julianday(const char *zDate){
3107 return db_int(0, "SELECT EXISTS (SELECT julianday(%Q) AS jd"
3108 " WHERE jd IS NOT NULL)", zDate);
3109 }
3110
3111
3112 /*
3113 ** COMMAND: timeline
3114 **
3115 ** Usage: %fossil timeline ?WHEN? ?CHECKIN|DATETIME? ?OPTIONS?
@@ -3023,10 +3152,27 @@
3152 ** etc.) after the check-in comment.
3153 ** -W|--width N Width of lines (default is to auto-detect). N must be
3154 ** either greater than 20 or it ust be zero 0 to
3155 ** indicate no limit, resulting in a single line per
3156 ** entry.
3157 ** -F|--format Entry format. Values "oneline", "medium", and "full"
3158 ** get mapped to the full options below. Otherwise a
3159 ** string which can contain these placeholders:
3160 ** %n newline
3161 ** %% a raw %
3162 ** %H commit hash
3163 ** %h abbreviated commit hash
3164 ** %a author name
3165 ** %d date
3166 ** %c comment (NL, TAB replaced by space, LF deleted)
3167 ** %b branch
3168 ** %t tags
3169 ** %p phase: zero or more of *CURRENT*, *MERGE*,
3170 ** *FORK*, *UNPUBLISHED*, *LEAF*, *BRANCH*
3171 ** --oneline Show only short hash and comment for each entry
3172 ** --medium Medium-verbose entry formatting
3173 ** --full Extra verbose entry formatting
3174 ** -R REPO_FILE Specifies the repository db to use. Default is
3175 ** the current checkout's repository.
3176 */
3177 void timeline_cmd(void){
3178 Stmt q;
@@ -3042,10 +3188,11 @@
3188 Blob uuid;
3189 int mode = TIMELINE_MODE_NONE;
3190 int verboseFlag = 0 ;
3191 int iOffset;
3192 const char *zFilePattern = 0;
3193 const char *zFormat = 0;
3194 Blob treeName;
3195 int showSql = 0;
3196
3197 verboseFlag = find_option("verbose","v", 0)!=0;
3198 if( !verboseFlag){
@@ -3054,10 +3201,17 @@
3201 db_find_and_open_repository(0, 0);
3202 zLimit = find_option("limit","n",1);
3203 zWidth = find_option("width","W",1);
3204 zType = find_option("type","t",1);
3205 zFilePattern = find_option("path","p",1);
3206 zFormat = find_option("format","F",1);
3207 if( find_option("oneline",0,0)!= 0 || fossil_strcmp(zFormat,"oneline")==0 )
3208 zFormat = "%h %c";
3209 if( find_option("medium",0,0)!= 0 || fossil_strcmp(zFormat,"medium")==0 )
3210 zFormat = "Commit: %h%nDate: %d%nAuthor: %a%nComment: %c";
3211 if( find_option("full",0,0)!= 0 || fossil_strcmp(zFormat,"full")==0 )
3212 zFormat = "Commit: %H%nDate: %d%nAuthor: %a%nComment: %c%nBranch: %b%nTags: %t%nPrefix: %p";
3213 showSql = find_option("sql",0,0)!=0;
3214
3215 if( !zLimit ){
3216 zLimit = find_option("count",0,1);
3217 }
@@ -3203,11 +3357,11 @@
3357 if( showSql ){
3358 fossil_print("%s\n", blob_str(&sql));
3359 }
3360 db_prepare_blob(&q, &sql);
3361 blob_reset(&sql);
3362 print_timeline(&q, n, width, zFormat, verboseFlag);
3363 db_finalize(&q);
3364 }
3365
3366 /*
3367 ** WEBPAGE: thisdayinhistory
3368
+1 -1
--- src/update.c
+++ src/update.c
@@ -221,11 +221,11 @@
221221
"%s "
222222
" AND event.objid IN leaves"
223223
" ORDER BY event.mtime DESC",
224224
timeline_query_for_tty()
225225
);
226
- print_timeline(&q, -100, width, 0);
226
+ print_timeline(&q, -100, width, 0, 0);
227227
db_finalize(&q);
228228
fossil_fatal("Multiple descendants");
229229
}
230230
}
231231
tid = db_int(0, "SELECT rid FROM leaves, event"
232232
--- src/update.c
+++ src/update.c
@@ -221,11 +221,11 @@
221 "%s "
222 " AND event.objid IN leaves"
223 " ORDER BY event.mtime DESC",
224 timeline_query_for_tty()
225 );
226 print_timeline(&q, -100, width, 0);
227 db_finalize(&q);
228 fossil_fatal("Multiple descendants");
229 }
230 }
231 tid = db_int(0, "SELECT rid FROM leaves, event"
232
--- src/update.c
+++ src/update.c
@@ -221,11 +221,11 @@
221 "%s "
222 " AND event.objid IN leaves"
223 " ORDER BY event.mtime DESC",
224 timeline_query_for_tty()
225 );
226 print_timeline(&q, -100, width, 0, 0);
227 db_finalize(&q);
228 fossil_fatal("Multiple descendants");
229 }
230 }
231 tid = db_int(0, "SELECT rid FROM leaves, event"
232

Keyboard Shortcuts

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