Fossil SCM

Show tag changes on the timeline. A "fossil rebuild" is required to take advantage of this new feature. Also put a • character in front of non-checkin timeline entries to make them stand out more.

drh 2011-10-16 23:00 trunk
Commit 87540ed6e60b7bcadd459e32643656c8d8bdecc9
--- src/manifest.c
+++ src/manifest.c
@@ -1819,10 +1819,49 @@
18191819
"VALUES('t',%.17g,%d,%Q,%Q)",
18201820
p->rDate, rid, p->zUser, zComment
18211821
);
18221822
free(zComment);
18231823
}
1824
+ }
1825
+ if( p->type==CFTYPE_CONTROL ){
1826
+ Blob comment;
1827
+ int i;
1828
+ const char *zName;
1829
+ const char *zValue;
1830
+ const char *zUuid;
1831
+ blob_zero(&comment);
1832
+ for(i=0; i<p->nTag; i++){
1833
+ zUuid = p->aTag[i].zUuid;
1834
+ if( i==0 || fossil_strcmp(zUuid, p->aTag[i-1].zUuid)!=0 ){
1835
+ if( i>0 ) blob_append(&comment, " ", 1);
1836
+ blob_appendf(&comment, "Tag chagnes on "
1837
+ "<a href=\"%s/timeline?dp=%S&n=4\">&#91;%S&#93;</a>:",
1838
+ g.zTop, zUuid, zUuid);
1839
+ }
1840
+ zName = p->aTag[i].zName;
1841
+ zValue = p->aTag[i].zValue;
1842
+ if( zName[0]=='-' ){
1843
+ blob_appendf(&comment, " Cancel");
1844
+ }else if( zName[0]=='+' ){
1845
+ blob_appendf(&comment, " Add");
1846
+ }else{
1847
+ blob_appendf(&comment, " Add propagating");
1848
+ }
1849
+ if( memcmp(&zName[1], "sym-",4)==0 ){
1850
+ blob_appendf(&comment, " symbolic tag \"%h\".", &zName[5]);
1851
+ }else if( fossil_strcmp(&zName[1], "comment")!=0 && zValue && zValue[0] ){
1852
+ blob_appendf(&comment, " %h=%h.", &zName[1], zValue);
1853
+ }else{
1854
+ blob_appendf(&comment, " %h.", &zName[1]);
1855
+ }
1856
+ }
1857
+ db_multi_exec(
1858
+ "REPLACE INTO event(type,mtime,objid,user,comment)"
1859
+ "VALUES('g',%.17g,%d,%Q,%Q)",
1860
+ p->rDate, rid, p->zUser, blob_str(&comment)
1861
+ );
1862
+ blob_reset(&comment);
18241863
}
18251864
db_end_transaction(0);
18261865
if( p->type==CFTYPE_MANIFEST ){
18271866
manifest_cache_insert(p);
18281867
}else{
18291868
--- src/manifest.c
+++ src/manifest.c
@@ -1819,10 +1819,49 @@
1819 "VALUES('t',%.17g,%d,%Q,%Q)",
1820 p->rDate, rid, p->zUser, zComment
1821 );
1822 free(zComment);
1823 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1824 }
1825 db_end_transaction(0);
1826 if( p->type==CFTYPE_MANIFEST ){
1827 manifest_cache_insert(p);
1828 }else{
1829
--- src/manifest.c
+++ src/manifest.c
@@ -1819,10 +1819,49 @@
1819 "VALUES('t',%.17g,%d,%Q,%Q)",
1820 p->rDate, rid, p->zUser, zComment
1821 );
1822 free(zComment);
1823 }
1824 }
1825 if( p->type==CFTYPE_CONTROL ){
1826 Blob comment;
1827 int i;
1828 const char *zName;
1829 const char *zValue;
1830 const char *zUuid;
1831 blob_zero(&comment);
1832 for(i=0; i<p->nTag; i++){
1833 zUuid = p->aTag[i].zUuid;
1834 if( i==0 || fossil_strcmp(zUuid, p->aTag[i-1].zUuid)!=0 ){
1835 if( i>0 ) blob_append(&comment, " ", 1);
1836 blob_appendf(&comment, "Tag chagnes on "
1837 "<a href=\"%s/timeline?dp=%S&n=4\">&#91;%S&#93;</a>:",
1838 g.zTop, zUuid, zUuid);
1839 }
1840 zName = p->aTag[i].zName;
1841 zValue = p->aTag[i].zValue;
1842 if( zName[0]=='-' ){
1843 blob_appendf(&comment, " Cancel");
1844 }else if( zName[0]=='+' ){
1845 blob_appendf(&comment, " Add");
1846 }else{
1847 blob_appendf(&comment, " Add propagating");
1848 }
1849 if( memcmp(&zName[1], "sym-",4)==0 ){
1850 blob_appendf(&comment, " symbolic tag \"%h\".", &zName[5]);
1851 }else if( fossil_strcmp(&zName[1], "comment")!=0 && zValue && zValue[0] ){
1852 blob_appendf(&comment, " %h=%h.", &zName[1], zValue);
1853 }else{
1854 blob_appendf(&comment, " %h.", &zName[1]);
1855 }
1856 }
1857 db_multi_exec(
1858 "REPLACE INTO event(type,mtime,objid,user,comment)"
1859 "VALUES('g',%.17g,%d,%Q,%Q)",
1860 p->rDate, rid, p->zUser, blob_str(&comment)
1861 );
1862 blob_reset(&comment);
1863 }
1864 db_end_transaction(0);
1865 if( p->type==CFTYPE_MANIFEST ){
1866 manifest_cache_insert(p);
1867 }else{
1868
+1 -1
--- src/schema.c
+++ src/schema.c
@@ -251,11 +251,11 @@
251251
@ CREATE TABLE leaf(rid INTEGER PRIMARY KEY);
252252
@
253253
@ -- Events used to generate a timeline
254254
@ --
255255
@ CREATE TABLE event(
256
-@ type TEXT, -- Type of event: 'ci', 'w', 'e', 't'
256
+@ type TEXT, -- Type of event: 'ci', 'w', 'e', 't', 'g'
257257
@ mtime DATETIME, -- Time of occurrence. Julian day.
258258
@ objid INTEGER PRIMARY KEY, -- Associated record ID
259259
@ tagid INTEGER, -- Associated ticket or wiki name tag
260260
@ uid INTEGER REFERENCES user, -- User who caused the event
261261
@ bgcolor TEXT, -- Color set by 'bgcolor' property
262262
--- src/schema.c
+++ src/schema.c
@@ -251,11 +251,11 @@
251 @ CREATE TABLE leaf(rid INTEGER PRIMARY KEY);
252 @
253 @ -- Events used to generate a timeline
254 @ --
255 @ CREATE TABLE event(
256 @ type TEXT, -- Type of event: 'ci', 'w', 'e', 't'
257 @ mtime DATETIME, -- Time of occurrence. Julian day.
258 @ objid INTEGER PRIMARY KEY, -- Associated record ID
259 @ tagid INTEGER, -- Associated ticket or wiki name tag
260 @ uid INTEGER REFERENCES user, -- User who caused the event
261 @ bgcolor TEXT, -- Color set by 'bgcolor' property
262
--- src/schema.c
+++ src/schema.c
@@ -251,11 +251,11 @@
251 @ CREATE TABLE leaf(rid INTEGER PRIMARY KEY);
252 @
253 @ -- Events used to generate a timeline
254 @ --
255 @ CREATE TABLE event(
256 @ type TEXT, -- Type of event: 'ci', 'w', 'e', 't', 'g'
257 @ mtime DATETIME, -- Time of occurrence. Julian day.
258 @ objid INTEGER PRIMARY KEY, -- Associated record ID
259 @ tagid INTEGER, -- Associated ticket or wiki name tag
260 @ uid INTEGER REFERENCES user, -- User who caused the event
261 @ bgcolor TEXT, -- Color set by 'bgcolor' property
262
+20 -3
--- src/timeline.c
+++ src/timeline.c
@@ -179,11 +179,11 @@
179179
** 2. Date/Time
180180
** 3. Comment string
181181
** 4. User
182182
** 5. True if is a leaf
183183
** 6. background color
184
-** 7. type ("ci", "w", "t", "e", "div")
184
+** 7. type ("ci", "w", "t", "e", "g", "div")
185185
** 8. list of symbolic tags.
186186
** 9. tagid for ticket or wiki or event
187187
** 10. Short comment to user for repeated tickets and wiki
188188
*/
189189
void www_print_timeline(
@@ -316,10 +316,13 @@
316316
@</td>
317317
if( zBgClr && zBgClr[0] ){
318318
@ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
319319
}else{
320320
@ <td class="timelineTableCell">
321
+ }
322
+ if( pGraph && zType[0]!='c' ){
323
+ @ &bull;
321324
}
322325
if( zType[0]=='c' ){
323326
hyperlink_to_uuid(zUuid);
324327
if( isLeaf ){
325328
if( db_exists("SELECT 1 FROM tagxref"
@@ -892,15 +895,23 @@
892895
int from_rid = name_to_typed_rid(P("from"),"ci"); /* from= for paths */
893896
int to_rid = name_to_typed_rid(P("to"),"ci"); /* to= for path timelines */
894897
int noMerge = P("nomerge")!=0; /* Do not follow merge links */
895898
int me_rid = name_to_typed_rid(P("me"),"ci"); /* me= for common ancestory */
896899
int you_rid = name_to_typed_rid(P("you"),"ci");/* you= for common ancst */
900
+ int pd_rid;
897901
898902
/* To view the timeline, must have permission to read project data.
899903
*/
904
+ pd_rid = name_to_typed_rid(P("dp"),"ci");
905
+ if( pd_rid ){
906
+ p_rid = d_rid = pd_rid;
907
+ }
900908
login_check_credentials();
901
- if( !g.perm.Read && !g.perm.RdTkt && !g.perm.RdWiki ){ login_needed(); return; }
909
+ if( !g.perm.Read && !g.perm.RdTkt && !g.perm.RdWiki ){
910
+ login_needed();
911
+ return;
912
+ }
902913
if( zTagName && g.perm.Read ){
903914
tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'", zTagName);
904915
zThisTag = zTagName;
905916
}else if( zBrName && g.perm.Read ){
906917
tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'",zBrName);
@@ -1075,19 +1086,20 @@
10751086
}
10761087
if( (zType[0]=='w' && !g.perm.RdWiki)
10771088
|| (zType[0]=='t' && !g.perm.RdTkt)
10781089
|| (zType[0]=='e' && !g.perm.RdWiki)
10791090
|| (zType[0]=='c' && !g.perm.Read)
1091
+ || (zType[0]=='g' && !g.perm.Read)
10801092
){
10811093
zType = "all";
10821094
}
10831095
if( zType[0]=='a' ){
10841096
if( !g.perm.Read || !g.perm.RdWiki || !g.perm.RdTkt ){
10851097
char cSep = '(';
10861098
blob_appendf(&sql, " AND event.type IN ");
10871099
if( g.perm.Read ){
1088
- blob_appendf(&sql, "%c'ci'", cSep);
1100
+ blob_appendf(&sql, "%c'ci','g'", cSep);
10891101
cSep = ',';
10901102
}
10911103
if( g.perm.RdWiki ){
10921104
blob_appendf(&sql, "%c'w','e'", cSep);
10931105
cSep = ',';
@@ -1107,10 +1119,12 @@
11071119
zEType = "wiki edit";
11081120
}else if( zType[0]=='t' ){
11091121
zEType = "ticket change";
11101122
}else if( zType[0]=='e' ){
11111123
zEType = "event";
1124
+ }else if( zType[0]=='g' ){
1125
+ zEType = "tag";
11121126
}
11131127
}
11141128
if( zUser ){
11151129
blob_appendf(&sql, " AND (event.user=%Q OR event.euser=%Q)",
11161130
zUser, zUser);
@@ -1226,10 +1240,13 @@
12261240
timeline_submenu(&url, "Tickets Only", "y", "t", 0);
12271241
}
12281242
if( zType[0]!='e' && g.perm.RdWiki ){
12291243
timeline_submenu(&url, "Events Only", "y", "e", 0);
12301244
}
1245
+ if( zType[0]!='g' && g.perm.Read ){
1246
+ timeline_submenu(&url, "Tags Only", "y", "g", 0);
1247
+ }
12311248
}
12321249
if( nEntry>20 ){
12331250
timeline_submenu(&url, "20 Entries", "n", "20", 0);
12341251
}
12351252
if( nEntry<200 ){
12361253
--- src/timeline.c
+++ src/timeline.c
@@ -179,11 +179,11 @@
179 ** 2. Date/Time
180 ** 3. Comment string
181 ** 4. User
182 ** 5. True if is a leaf
183 ** 6. background color
184 ** 7. type ("ci", "w", "t", "e", "div")
185 ** 8. list of symbolic tags.
186 ** 9. tagid for ticket or wiki or event
187 ** 10. Short comment to user for repeated tickets and wiki
188 */
189 void www_print_timeline(
@@ -316,10 +316,13 @@
316 @</td>
317 if( zBgClr && zBgClr[0] ){
318 @ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
319 }else{
320 @ <td class="timelineTableCell">
 
 
 
321 }
322 if( zType[0]=='c' ){
323 hyperlink_to_uuid(zUuid);
324 if( isLeaf ){
325 if( db_exists("SELECT 1 FROM tagxref"
@@ -892,15 +895,23 @@
892 int from_rid = name_to_typed_rid(P("from"),"ci"); /* from= for paths */
893 int to_rid = name_to_typed_rid(P("to"),"ci"); /* to= for path timelines */
894 int noMerge = P("nomerge")!=0; /* Do not follow merge links */
895 int me_rid = name_to_typed_rid(P("me"),"ci"); /* me= for common ancestory */
896 int you_rid = name_to_typed_rid(P("you"),"ci");/* you= for common ancst */
 
897
898 /* To view the timeline, must have permission to read project data.
899 */
 
 
 
 
900 login_check_credentials();
901 if( !g.perm.Read && !g.perm.RdTkt && !g.perm.RdWiki ){ login_needed(); return; }
 
 
 
902 if( zTagName && g.perm.Read ){
903 tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'", zTagName);
904 zThisTag = zTagName;
905 }else if( zBrName && g.perm.Read ){
906 tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'",zBrName);
@@ -1075,19 +1086,20 @@
1075 }
1076 if( (zType[0]=='w' && !g.perm.RdWiki)
1077 || (zType[0]=='t' && !g.perm.RdTkt)
1078 || (zType[0]=='e' && !g.perm.RdWiki)
1079 || (zType[0]=='c' && !g.perm.Read)
 
1080 ){
1081 zType = "all";
1082 }
1083 if( zType[0]=='a' ){
1084 if( !g.perm.Read || !g.perm.RdWiki || !g.perm.RdTkt ){
1085 char cSep = '(';
1086 blob_appendf(&sql, " AND event.type IN ");
1087 if( g.perm.Read ){
1088 blob_appendf(&sql, "%c'ci'", cSep);
1089 cSep = ',';
1090 }
1091 if( g.perm.RdWiki ){
1092 blob_appendf(&sql, "%c'w','e'", cSep);
1093 cSep = ',';
@@ -1107,10 +1119,12 @@
1107 zEType = "wiki edit";
1108 }else if( zType[0]=='t' ){
1109 zEType = "ticket change";
1110 }else if( zType[0]=='e' ){
1111 zEType = "event";
 
 
1112 }
1113 }
1114 if( zUser ){
1115 blob_appendf(&sql, " AND (event.user=%Q OR event.euser=%Q)",
1116 zUser, zUser);
@@ -1226,10 +1240,13 @@
1226 timeline_submenu(&url, "Tickets Only", "y", "t", 0);
1227 }
1228 if( zType[0]!='e' && g.perm.RdWiki ){
1229 timeline_submenu(&url, "Events Only", "y", "e", 0);
1230 }
 
 
 
1231 }
1232 if( nEntry>20 ){
1233 timeline_submenu(&url, "20 Entries", "n", "20", 0);
1234 }
1235 if( nEntry<200 ){
1236
--- src/timeline.c
+++ src/timeline.c
@@ -179,11 +179,11 @@
179 ** 2. Date/Time
180 ** 3. Comment string
181 ** 4. User
182 ** 5. True if is a leaf
183 ** 6. background color
184 ** 7. type ("ci", "w", "t", "e", "g", "div")
185 ** 8. list of symbolic tags.
186 ** 9. tagid for ticket or wiki or event
187 ** 10. Short comment to user for repeated tickets and wiki
188 */
189 void www_print_timeline(
@@ -316,10 +316,13 @@
316 @</td>
317 if( zBgClr && zBgClr[0] ){
318 @ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
319 }else{
320 @ <td class="timelineTableCell">
321 }
322 if( pGraph && zType[0]!='c' ){
323 @ &bull;
324 }
325 if( zType[0]=='c' ){
326 hyperlink_to_uuid(zUuid);
327 if( isLeaf ){
328 if( db_exists("SELECT 1 FROM tagxref"
@@ -892,15 +895,23 @@
895 int from_rid = name_to_typed_rid(P("from"),"ci"); /* from= for paths */
896 int to_rid = name_to_typed_rid(P("to"),"ci"); /* to= for path timelines */
897 int noMerge = P("nomerge")!=0; /* Do not follow merge links */
898 int me_rid = name_to_typed_rid(P("me"),"ci"); /* me= for common ancestory */
899 int you_rid = name_to_typed_rid(P("you"),"ci");/* you= for common ancst */
900 int pd_rid;
901
902 /* To view the timeline, must have permission to read project data.
903 */
904 pd_rid = name_to_typed_rid(P("dp"),"ci");
905 if( pd_rid ){
906 p_rid = d_rid = pd_rid;
907 }
908 login_check_credentials();
909 if( !g.perm.Read && !g.perm.RdTkt && !g.perm.RdWiki ){
910 login_needed();
911 return;
912 }
913 if( zTagName && g.perm.Read ){
914 tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'", zTagName);
915 zThisTag = zTagName;
916 }else if( zBrName && g.perm.Read ){
917 tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'",zBrName);
@@ -1075,19 +1086,20 @@
1086 }
1087 if( (zType[0]=='w' && !g.perm.RdWiki)
1088 || (zType[0]=='t' && !g.perm.RdTkt)
1089 || (zType[0]=='e' && !g.perm.RdWiki)
1090 || (zType[0]=='c' && !g.perm.Read)
1091 || (zType[0]=='g' && !g.perm.Read)
1092 ){
1093 zType = "all";
1094 }
1095 if( zType[0]=='a' ){
1096 if( !g.perm.Read || !g.perm.RdWiki || !g.perm.RdTkt ){
1097 char cSep = '(';
1098 blob_appendf(&sql, " AND event.type IN ");
1099 if( g.perm.Read ){
1100 blob_appendf(&sql, "%c'ci','g'", cSep);
1101 cSep = ',';
1102 }
1103 if( g.perm.RdWiki ){
1104 blob_appendf(&sql, "%c'w','e'", cSep);
1105 cSep = ',';
@@ -1107,10 +1119,12 @@
1119 zEType = "wiki edit";
1120 }else if( zType[0]=='t' ){
1121 zEType = "ticket change";
1122 }else if( zType[0]=='e' ){
1123 zEType = "event";
1124 }else if( zType[0]=='g' ){
1125 zEType = "tag";
1126 }
1127 }
1128 if( zUser ){
1129 blob_appendf(&sql, " AND (event.user=%Q OR event.euser=%Q)",
1130 zUser, zUser);
@@ -1226,10 +1240,13 @@
1240 timeline_submenu(&url, "Tickets Only", "y", "t", 0);
1241 }
1242 if( zType[0]!='e' && g.perm.RdWiki ){
1243 timeline_submenu(&url, "Events Only", "y", "e", 0);
1244 }
1245 if( zType[0]!='g' && g.perm.Read ){
1246 timeline_submenu(&url, "Tags Only", "y", "g", 0);
1247 }
1248 }
1249 if( nEntry>20 ){
1250 timeline_submenu(&url, "20 Entries", "n", "20", 0);
1251 }
1252 if( nEntry<200 ){
1253

Keyboard Shortcuts

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