Fossil SCM

Timeline now responses to comment and user properties.

drh 2007-09-22 12:38 trunk
Commit 9395aba4f41641191e172b786274f53b2b20a697
+12 -19
--- src/descendents.c
+++ src/descendents.c
@@ -147,16 +147,14 @@
147147
base = name_to_rid(g.argv[2]);
148148
}
149149
if( base==0 ) return;
150150
compute_leaves(base);
151151
db_prepare(&q,
152
- "SELECT blob.rid, uuid, datetime(event.mtime,'localtime'), comment, 0,"
153
- " (SELECT count(*) FROM plink WHERE cid=blob.rid)"
154
- " FROM leaves, blob, event"
155
- " WHERE blob.rid=leaves.rid"
156
- " AND event.objid=leaves.rid"
157
- " ORDER BY event.mtime DESC"
152
+ "%s"
153
+ " AND event.objid IN (SELECT rid FROM leaves)"
154
+ " ORDER BY event.mtime DESC",
155
+ timeline_query_for_tty()
158156
);
159157
print_timeline(&q, 20);
160158
db_finalize(&q);
161159
}
162160
@@ -169,18 +167,15 @@
169167
void branches_cmd(void){
170168
Stmt q;
171169
172170
db_must_be_within_tree();
173171
db_prepare(&q,
174
- "SELECT blob.rid, blob.uuid, datetime(event.mtime,'localtime'),"
175
- " event.comment, 0,"
176
- " (SELECT count(*) FROM plink WHERE cid=blob.rid)"
177
- " FROM blob, event"
178
- " WHERE blob.rid IN"
172
+ "%s"
173
+ " AND blob.rid IN"
179174
" (SELECT cid FROM plink EXCEPT SELECT pid FROM plink)"
180
- " AND event.objid=blob.rid"
181
- " ORDER BY event.mtime DESC"
175
+ " ORDER BY event.mtime DESC",
176
+ timeline_query_for_tty()
182177
);
183178
print_timeline(&q, 2000);
184179
db_finalize(&q);
185180
}
186181
@@ -195,17 +190,15 @@
195190
login_check_credentials();
196191
if( !g.okRead ){ login_needed(); return; }
197192
198193
style_header("Leaves");
199194
db_prepare(&q,
200
- "SELECT blob.rid, blob.uuid, datetime(event.mtime,'localtime'),"
201
- " event.comment, event.user, 1, 1, 0, NULL"
202
- " FROM blob, event"
203
- " WHERE blob.rid IN"
195
+ "%s"
196
+ " AND blob.rid IN"
204197
" (SELECT cid FROM plink EXCEPT SELECT pid FROM plink)"
205
- " AND event.objid=blob.rid"
206
- " ORDER BY event.mtime DESC"
198
+ " ORDER BY event.mtime DESC",
199
+ timeline_query_for_www()
207200
);
208201
www_print_timeline(&q, 0, 0, 0, 0);
209202
db_finalize(&q);
210203
@ <script>
211204
@ function xin(id){
212205
--- src/descendents.c
+++ src/descendents.c
@@ -147,16 +147,14 @@
147 base = name_to_rid(g.argv[2]);
148 }
149 if( base==0 ) return;
150 compute_leaves(base);
151 db_prepare(&q,
152 "SELECT blob.rid, uuid, datetime(event.mtime,'localtime'), comment, 0,"
153 " (SELECT count(*) FROM plink WHERE cid=blob.rid)"
154 " FROM leaves, blob, event"
155 " WHERE blob.rid=leaves.rid"
156 " AND event.objid=leaves.rid"
157 " ORDER BY event.mtime DESC"
158 );
159 print_timeline(&q, 20);
160 db_finalize(&q);
161 }
162
@@ -169,18 +167,15 @@
169 void branches_cmd(void){
170 Stmt q;
171
172 db_must_be_within_tree();
173 db_prepare(&q,
174 "SELECT blob.rid, blob.uuid, datetime(event.mtime,'localtime'),"
175 " event.comment, 0,"
176 " (SELECT count(*) FROM plink WHERE cid=blob.rid)"
177 " FROM blob, event"
178 " WHERE blob.rid IN"
179 " (SELECT cid FROM plink EXCEPT SELECT pid FROM plink)"
180 " AND event.objid=blob.rid"
181 " ORDER BY event.mtime DESC"
182 );
183 print_timeline(&q, 2000);
184 db_finalize(&q);
185 }
186
@@ -195,17 +190,15 @@
195 login_check_credentials();
196 if( !g.okRead ){ login_needed(); return; }
197
198 style_header("Leaves");
199 db_prepare(&q,
200 "SELECT blob.rid, blob.uuid, datetime(event.mtime,'localtime'),"
201 " event.comment, event.user, 1, 1, 0, NULL"
202 " FROM blob, event"
203 " WHERE blob.rid IN"
204 " (SELECT cid FROM plink EXCEPT SELECT pid FROM plink)"
205 " AND event.objid=blob.rid"
206 " ORDER BY event.mtime DESC"
207 );
208 www_print_timeline(&q, 0, 0, 0, 0);
209 db_finalize(&q);
210 @ <script>
211 @ function xin(id){
212
--- src/descendents.c
+++ src/descendents.c
@@ -147,16 +147,14 @@
147 base = name_to_rid(g.argv[2]);
148 }
149 if( base==0 ) return;
150 compute_leaves(base);
151 db_prepare(&q,
152 "%s"
153 " AND event.objid IN (SELECT rid FROM leaves)"
154 " ORDER BY event.mtime DESC",
155 timeline_query_for_tty()
 
 
156 );
157 print_timeline(&q, 20);
158 db_finalize(&q);
159 }
160
@@ -169,18 +167,15 @@
167 void branches_cmd(void){
168 Stmt q;
169
170 db_must_be_within_tree();
171 db_prepare(&q,
172 "%s"
173 " AND blob.rid IN"
 
 
 
174 " (SELECT cid FROM plink EXCEPT SELECT pid FROM plink)"
175 " ORDER BY event.mtime DESC",
176 timeline_query_for_tty()
177 );
178 print_timeline(&q, 2000);
179 db_finalize(&q);
180 }
181
@@ -195,17 +190,15 @@
190 login_check_credentials();
191 if( !g.okRead ){ login_needed(); return; }
192
193 style_header("Leaves");
194 db_prepare(&q,
195 "%s"
196 " AND blob.rid IN"
 
 
197 " (SELECT cid FROM plink EXCEPT SELECT pid FROM plink)"
198 " ORDER BY event.mtime DESC",
199 timeline_query_for_www()
200 );
201 www_print_timeline(&q, 0, 0, 0, 0);
202 db_finalize(&q);
203 @ <script>
204 @ function xin(id){
205
+56 -13
--- src/tag.c
+++ src/tag.c
@@ -120,10 +120,39 @@
120120
id = db_last_insert_rowid();
121121
}
122122
return id;
123123
}
124124
125
+/*
126
+** Insert a tag into the database.
127
+*/
128
+void tag_insert(
129
+ const char *zTag, /* Name of the tag (w/o the "+" or "-" prefix */
130
+ int addFlag, /* True to add. False to remove */
131
+ const char *zValue, /* Value if the tag is really a property */
132
+ int srcId, /* Artifact that contains this tag */
133
+ double mtime, /* Timestamp. Use default if <=0.0 */
134
+ int rid /* Artifact to which the tag is to attached */
135
+){
136
+ Stmt s;
137
+ int tagid = tag_findid(zTag, 1);
138
+ if( mtime<=0.0 ){
139
+ mtime = db_double(0.0, "SELECT julianday('now')");
140
+ }
141
+ db_prepare(&s,
142
+ "REPLACE INTO tagxref(tagid,addFlag,srcId,value,mtime,rid)"
143
+ " VALUES(%d,%d,%d,%Q,:mtime,%d)",
144
+ tagid, addFlag, srcId, zValue, rid
145
+ );
146
+ db_bind_double(&s, ":mtime", mtime);
147
+ db_step(&s);
148
+ db_finalize(&s);
149
+ if( strncmp(zTag, "br", 2)==0 ){
150
+ tag_propagate(rid, tagid, 1, zValue, mtime);
151
+ }
152
+}
153
+
125154
126155
/*
127156
** COMMAND: test-addtag
128157
** %fossil test-addtag TAGNAME UUID ?VALUE?
129158
**
@@ -133,31 +162,45 @@
133162
** use only.
134163
*/
135164
void addtag_cmd(void){
136165
const char *zTag;
137166
const char *zValue;
138
- int tagid;
139167
int rid;
140
- double now;
141168
db_must_be_within_tree();
142169
if( g.argc!=4 && g.argc!=5 ){
143170
usage("TAGNAME UUID ?VALUE?");
144171
}
145172
zTag = g.argv[2];
146173
rid = name_to_rid(g.argv[3]);
147174
if( rid==0 ){
148175
fossil_fatal("no such object: %s", g.argv[3]);
149176
}
150
- db_begin_transaction();
151
- tagid = tag_findid(zTag, 1);
152177
zValue = g.argc==5 ? g.argv[4] : 0;
153
- db_multi_exec(
154
- "REPLACE INTO tagxref(tagid,addFlag,srcId,value,mtime,rid)"
155
- " VALUES(%d,1,-1,%Q,julianday('now'),%d)",
156
- tagid, rid, zValue, rid
157
- );
158
- if( strncmp(zTag, "br", 2)==0 ){
159
- now = db_double(0.0, "SELECT julianday('now')");
160
- tag_propagate(rid, tagid, 1, zValue, now);
161
- }
178
+ db_begin_transaction();
179
+ tag_insert(zTag, 1, zValue, -1, 0.0, rid);
180
+ db_end_transaction(0);
181
+}
182
+/*
183
+** COMMAND: test-deltag
184
+** %fossil test-deltag TAGNAME UUID
185
+**
186
+** Cancel a tag to the rebuildable tables of the local repository.
187
+** No tag artifact is created so the cancellation is undone the next
188
+** time the repository is rebuilt. This routine is for testing
189
+** use only.
190
+*/
191
+void deltag_cmd(void){
192
+ const char *zTag;
193
+ int rid;
194
+ db_must_be_within_tree();
195
+ if( g.argc!=4 ){
196
+ usage("TAGNAME UUID");
197
+ }
198
+ zTag = g.argv[2];
199
+ rid = name_to_rid(g.argv[3]);
200
+ if( rid==0 ){
201
+ fossil_fatal("no such object: %s", g.argv[3]);
202
+ }
203
+ db_begin_transaction();
204
+ tag_insert(zTag, 0, 0, -1, 0.0, rid);
162205
db_end_transaction(0);
163206
}
164207
--- src/tag.c
+++ src/tag.c
@@ -120,10 +120,39 @@
120 id = db_last_insert_rowid();
121 }
122 return id;
123 }
124
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
126 /*
127 ** COMMAND: test-addtag
128 ** %fossil test-addtag TAGNAME UUID ?VALUE?
129 **
@@ -133,31 +162,45 @@
133 ** use only.
134 */
135 void addtag_cmd(void){
136 const char *zTag;
137 const char *zValue;
138 int tagid;
139 int rid;
140 double now;
141 db_must_be_within_tree();
142 if( g.argc!=4 && g.argc!=5 ){
143 usage("TAGNAME UUID ?VALUE?");
144 }
145 zTag = g.argv[2];
146 rid = name_to_rid(g.argv[3]);
147 if( rid==0 ){
148 fossil_fatal("no such object: %s", g.argv[3]);
149 }
150 db_begin_transaction();
151 tagid = tag_findid(zTag, 1);
152 zValue = g.argc==5 ? g.argv[4] : 0;
153 db_multi_exec(
154 "REPLACE INTO tagxref(tagid,addFlag,srcId,value,mtime,rid)"
155 " VALUES(%d,1,-1,%Q,julianday('now'),%d)",
156 tagid, rid, zValue, rid
157 );
158 if( strncmp(zTag, "br", 2)==0 ){
159 now = db_double(0.0, "SELECT julianday('now')");
160 tag_propagate(rid, tagid, 1, zValue, now);
161 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162 db_end_transaction(0);
163 }
164
--- src/tag.c
+++ src/tag.c
@@ -120,10 +120,39 @@
120 id = db_last_insert_rowid();
121 }
122 return id;
123 }
124
125 /*
126 ** Insert a tag into the database.
127 */
128 void tag_insert(
129 const char *zTag, /* Name of the tag (w/o the "+" or "-" prefix */
130 int addFlag, /* True to add. False to remove */
131 const char *zValue, /* Value if the tag is really a property */
132 int srcId, /* Artifact that contains this tag */
133 double mtime, /* Timestamp. Use default if <=0.0 */
134 int rid /* Artifact to which the tag is to attached */
135 ){
136 Stmt s;
137 int tagid = tag_findid(zTag, 1);
138 if( mtime<=0.0 ){
139 mtime = db_double(0.0, "SELECT julianday('now')");
140 }
141 db_prepare(&s,
142 "REPLACE INTO tagxref(tagid,addFlag,srcId,value,mtime,rid)"
143 " VALUES(%d,%d,%d,%Q,:mtime,%d)",
144 tagid, addFlag, srcId, zValue, rid
145 );
146 db_bind_double(&s, ":mtime", mtime);
147 db_step(&s);
148 db_finalize(&s);
149 if( strncmp(zTag, "br", 2)==0 ){
150 tag_propagate(rid, tagid, 1, zValue, mtime);
151 }
152 }
153
154
155 /*
156 ** COMMAND: test-addtag
157 ** %fossil test-addtag TAGNAME UUID ?VALUE?
158 **
@@ -133,31 +162,45 @@
162 ** use only.
163 */
164 void addtag_cmd(void){
165 const char *zTag;
166 const char *zValue;
 
167 int rid;
 
168 db_must_be_within_tree();
169 if( g.argc!=4 && g.argc!=5 ){
170 usage("TAGNAME UUID ?VALUE?");
171 }
172 zTag = g.argv[2];
173 rid = name_to_rid(g.argv[3]);
174 if( rid==0 ){
175 fossil_fatal("no such object: %s", g.argv[3]);
176 }
 
 
177 zValue = g.argc==5 ? g.argv[4] : 0;
178 db_begin_transaction();
179 tag_insert(zTag, 1, zValue, -1, 0.0, rid);
180 db_end_transaction(0);
181 }
182 /*
183 ** COMMAND: test-deltag
184 ** %fossil test-deltag TAGNAME UUID
185 **
186 ** Cancel a tag to the rebuildable tables of the local repository.
187 ** No tag artifact is created so the cancellation is undone the next
188 ** time the repository is rebuilt. This routine is for testing
189 ** use only.
190 */
191 void deltag_cmd(void){
192 const char *zTag;
193 int rid;
194 db_must_be_within_tree();
195 if( g.argc!=4 ){
196 usage("TAGNAME UUID");
197 }
198 zTag = g.argv[2];
199 rid = name_to_rid(g.argv[3]);
200 if( rid==0 ){
201 fossil_fatal("no such object: %s", g.argv[3]);
202 }
203 db_begin_transaction();
204 tag_insert(zTag, 0, 0, -1, 0.0, rid);
205 db_end_transaction(0);
206 }
207
+77 -24
--- src/timeline.c
+++ src/timeline.c
@@ -75,11 +75,11 @@
7575
}
7676
}
7777
7878
/*
7979
** Output a timeline in the web format given a query. The query
80
-** should return 4 columns:
80
+** should return these columns:
8181
**
8282
** 0. rid
8383
** 1. UUID
8484
** 2. Date/Time
8585
** 3. Comment string
@@ -187,10 +187,44 @@
187187
}
188188
db_finalize(&q);
189189
blob_appendf(pOut, "];\n");
190190
return 0;
191191
}
192
+
193
+/*
194
+** Return a pointer to a constant string that forms the basis
195
+** for a timeline query for the WWW interface.
196
+*/
197
+const char *timeline_query_for_www(void){
198
+ static const char zBaseSql[] =
199
+ @ SELECT
200
+ @ blob.rid,
201
+ @ uuid,
202
+ @ datetime(event.mtime,'localtime'),
203
+ @ coalesce((SELECT value FROM tagxref
204
+ @ WHERE rid=blob.rid
205
+ @ AND tagid=(SELECT tagid FROM tag WHERE tagname='comment')),
206
+ @ comment),
207
+ @ coalesce((SELECT value FROM tagxref
208
+ @ WHERE rid=blob.rid
209
+ @ AND tagid=(SELECT tagid FROM tag WHERE tagname='user')),
210
+ @ user),
211
+ @ (SELECT count(*) FROM plink WHERE pid=blob.rid AND isprim=1),
212
+ @ (SELECT count(*) FROM plink WHERE cid=blob.rid),
213
+ @ NOT EXISTS (SELECT 1 FROM plink WHERE pid=blob.rid),
214
+ @ (SELECT value FROM tagxref
215
+ @ WHERE rid=blob.rid
216
+ @ AND tagid=(SELECT tagid FROM tag WHERE tagname='bgcolor')
217
+ @ UNION ALL
218
+ @ SELECT value FROM tagxref
219
+ @ WHERE rid=blob.rid
220
+ @ AND tagid=(SELECT tagid FROM tag WHERE tagname='br-bgcolor'))
221
+ @ FROM event JOIN blob
222
+ @ WHERE blob.rid=event.objid
223
+ ;
224
+ return zBaseSql;
225
+}
192226
193227
/*
194228
** WEBPAGE: timeline
195229
**
196230
** Query parameters:
@@ -213,38 +247,25 @@
213247
int objid = atoi(PD("e","0"));
214248
int relatedEvents = P("r")!=0;
215249
int afterFlag = P("a")!=0;
216250
int firstEvent;
217251
int lastEvent;
218
- int clr1, clr2; /* Tag IDs for specifying background colors */
219252
220253
/* To view the timeline, must have permission to read project data.
221254
*/
222255
login_check_credentials();
223256
if( !g.okRead ){ login_needed(); return; }
224257
225258
style_header("Timeline");
226
- clr1 = db_int(0, "SELECT tagid FROM tag WHERE tagname='br-bg-color'");
227
- clr2 = db_int(0, "SELECT tagid FROM tag WHERE tagname='bg-color'");
228259
if( !g.okHistory &&
229260
db_exists("SELECT 1 FROM user"
230261
" WHERE login='anonymous'"
231262
" AND cap LIKE '%%h%%'") ){
232263
@ <p><b>Note:</b> You will be able to access <u>much</u> more
233264
@ historical information if <a href="%s(g.zBaseURL)/login">login</a>.</p>
234265
}
235
- zSQL = mprintf(
236
- "SELECT blob.rid, uuid, datetime(event.mtime,'localtime'), comment, user,"
237
- " (SELECT count(*) FROM plink WHERE pid=blob.rid AND isprim=1),"
238
- " (SELECT count(*) FROM plink WHERE cid=blob.rid),"
239
- " NOT EXISTS (SELECT 1 FROM plink WHERE pid=blob.rid),"
240
- " (SELECT value FROM tagxref WHERE rid=blob.rid AND tagid=%d"
241
- " UNION ALL"
242
- " SELECT value FROM tagxref WHERE rid=blob.rid AND tagid=%d)"
243
- " FROM event JOIN blob"
244
- " WHERE event.type='ci' AND blob.rid=event.objid", clr2, clr1
245
- );
266
+ zSQL = mprintf("%s", timeline_query_for_www());
246267
if( zUser ){
247268
zSQL = mprintf("%z AND event.user=%Q", zSQL, zUser);
248269
}
249270
if( objid ){
250271
char *z = db_text(0, "SELECT datetime(event.mtime) FROM event"
@@ -367,10 +388,19 @@
367388
/*
368389
** The input query q selects various records. Print a human-readable
369390
** summary of those records.
370391
**
371392
** Limit the number of entries printed to nLine.
393
+**
394
+** The query should return these columns:
395
+**
396
+** 0. rid
397
+** 1. uuid
398
+** 2. Date/Time
399
+** 3. Comment string and user
400
+** 4. Number of non-merge children
401
+** 5. Number of parents
372402
*/
373403
void print_timeline(Stmt *q, int mxLine){
374404
int nLine = 0;
375405
char zPrevDate[20];
376406
zPrevDate[0] = 0;
@@ -409,10 +439,38 @@
409439
}
410440
nLine += comment_print(zFree, 9, 79);
411441
sqlite3_free(zFree);
412442
}
413443
}
444
+
445
+/*
446
+** Return a pointer to a static string that forms the basis for
447
+** a timeline query for display on a TTY.
448
+*/
449
+const char *timeline_query_for_tty(void){
450
+ static const char zBaseSql[] =
451
+ @ SELECT
452
+ @ blob.rid,
453
+ @ uuid,
454
+ @ datetime(event.mtime,'localtime'),
455
+ @ coalesce((SELECT value FROM tagxref
456
+ @ WHERE rid=blob.rid
457
+ @ AND tagid=(SELECT tagid FROM tag WHERE tagname='comment')),
458
+ @ comment)
459
+ @ || ' (by ' ||
460
+ @ coalesce((SELECT value FROM tagxref
461
+ @ WHERE rid=blob.rid
462
+ @ AND tagid=(SELECT tagid FROM tag WHERE tagname='user')),
463
+ @ user)
464
+ @ || ')',
465
+ @ (SELECT count(*) FROM plink WHERE pid=blob.rid AND isprim),
466
+ @ (SELECT count(*) FROM plink WHERE cid=blob.rid)
467
+ @ FROM event, blob
468
+ @ WHERE blob.rid=event.objid
469
+ ;
470
+ return zBaseSql;
471
+}
414472
415473
416474
/*
417475
** COMMAND: timeline
418476
**
@@ -492,19 +550,14 @@
492550
if( mode==3 || mode==4 ){
493551
fossil_fatal("cannot compute descendents or ancestors of a date");
494552
}
495553
zDate = mprintf("(SELECT julianday(%Q, 'utc'))", zOrigin);
496554
}
497
- zSQL = mprintf(
498
- "SELECT blob.rid, uuid, datetime(event.mtime,'localtime'),"
499
- " comment || ' (by ' || user || ')',"
500
- " (SELECT count(*) FROM plink WHERE pid=blob.rid AND isprim),"
501
- " (SELECT count(*) FROM plink WHERE cid=blob.rid)"
502
- " FROM event, blob"
503
- " WHERE event.type='ci' AND blob.rid=event.objid"
504
- " AND event.mtime %s %s",
505
- (mode==1 || mode==4) ? "<=" : ">=", zDate
555
+ zSQL = mprintf("%s AND event.mtime %s %s",
556
+ timeline_query_for_tty(),
557
+ (mode==1 || mode==4) ? "<=" : ">=",
558
+ zDate
506559
);
507560
if( mode==3 || mode==4 ){
508561
db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
509562
if( mode==3 ){
510563
compute_descendents(objid, n);
511564
--- src/timeline.c
+++ src/timeline.c
@@ -75,11 +75,11 @@
75 }
76 }
77
78 /*
79 ** Output a timeline in the web format given a query. The query
80 ** should return 4 columns:
81 **
82 ** 0. rid
83 ** 1. UUID
84 ** 2. Date/Time
85 ** 3. Comment string
@@ -187,10 +187,44 @@
187 }
188 db_finalize(&q);
189 blob_appendf(pOut, "];\n");
190 return 0;
191 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
193 /*
194 ** WEBPAGE: timeline
195 **
196 ** Query parameters:
@@ -213,38 +247,25 @@
213 int objid = atoi(PD("e","0"));
214 int relatedEvents = P("r")!=0;
215 int afterFlag = P("a")!=0;
216 int firstEvent;
217 int lastEvent;
218 int clr1, clr2; /* Tag IDs for specifying background colors */
219
220 /* To view the timeline, must have permission to read project data.
221 */
222 login_check_credentials();
223 if( !g.okRead ){ login_needed(); return; }
224
225 style_header("Timeline");
226 clr1 = db_int(0, "SELECT tagid FROM tag WHERE tagname='br-bg-color'");
227 clr2 = db_int(0, "SELECT tagid FROM tag WHERE tagname='bg-color'");
228 if( !g.okHistory &&
229 db_exists("SELECT 1 FROM user"
230 " WHERE login='anonymous'"
231 " AND cap LIKE '%%h%%'") ){
232 @ <p><b>Note:</b> You will be able to access <u>much</u> more
233 @ historical information if <a href="%s(g.zBaseURL)/login">login</a>.</p>
234 }
235 zSQL = mprintf(
236 "SELECT blob.rid, uuid, datetime(event.mtime,'localtime'), comment, user,"
237 " (SELECT count(*) FROM plink WHERE pid=blob.rid AND isprim=1),"
238 " (SELECT count(*) FROM plink WHERE cid=blob.rid),"
239 " NOT EXISTS (SELECT 1 FROM plink WHERE pid=blob.rid),"
240 " (SELECT value FROM tagxref WHERE rid=blob.rid AND tagid=%d"
241 " UNION ALL"
242 " SELECT value FROM tagxref WHERE rid=blob.rid AND tagid=%d)"
243 " FROM event JOIN blob"
244 " WHERE event.type='ci' AND blob.rid=event.objid", clr2, clr1
245 );
246 if( zUser ){
247 zSQL = mprintf("%z AND event.user=%Q", zSQL, zUser);
248 }
249 if( objid ){
250 char *z = db_text(0, "SELECT datetime(event.mtime) FROM event"
@@ -367,10 +388,19 @@
367 /*
368 ** The input query q selects various records. Print a human-readable
369 ** summary of those records.
370 **
371 ** Limit the number of entries printed to nLine.
 
 
 
 
 
 
 
 
 
372 */
373 void print_timeline(Stmt *q, int mxLine){
374 int nLine = 0;
375 char zPrevDate[20];
376 zPrevDate[0] = 0;
@@ -409,10 +439,38 @@
409 }
410 nLine += comment_print(zFree, 9, 79);
411 sqlite3_free(zFree);
412 }
413 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
414
415
416 /*
417 ** COMMAND: timeline
418 **
@@ -492,19 +550,14 @@
492 if( mode==3 || mode==4 ){
493 fossil_fatal("cannot compute descendents or ancestors of a date");
494 }
495 zDate = mprintf("(SELECT julianday(%Q, 'utc'))", zOrigin);
496 }
497 zSQL = mprintf(
498 "SELECT blob.rid, uuid, datetime(event.mtime,'localtime'),"
499 " comment || ' (by ' || user || ')',"
500 " (SELECT count(*) FROM plink WHERE pid=blob.rid AND isprim),"
501 " (SELECT count(*) FROM plink WHERE cid=blob.rid)"
502 " FROM event, blob"
503 " WHERE event.type='ci' AND blob.rid=event.objid"
504 " AND event.mtime %s %s",
505 (mode==1 || mode==4) ? "<=" : ">=", zDate
506 );
507 if( mode==3 || mode==4 ){
508 db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
509 if( mode==3 ){
510 compute_descendents(objid, n);
511
--- src/timeline.c
+++ src/timeline.c
@@ -75,11 +75,11 @@
75 }
76 }
77
78 /*
79 ** Output a timeline in the web format given a query. The query
80 ** should return these columns:
81 **
82 ** 0. rid
83 ** 1. UUID
84 ** 2. Date/Time
85 ** 3. Comment string
@@ -187,10 +187,44 @@
187 }
188 db_finalize(&q);
189 blob_appendf(pOut, "];\n");
190 return 0;
191 }
192
193 /*
194 ** Return a pointer to a constant string that forms the basis
195 ** for a timeline query for the WWW interface.
196 */
197 const char *timeline_query_for_www(void){
198 static const char zBaseSql[] =
199 @ SELECT
200 @ blob.rid,
201 @ uuid,
202 @ datetime(event.mtime,'localtime'),
203 @ coalesce((SELECT value FROM tagxref
204 @ WHERE rid=blob.rid
205 @ AND tagid=(SELECT tagid FROM tag WHERE tagname='comment')),
206 @ comment),
207 @ coalesce((SELECT value FROM tagxref
208 @ WHERE rid=blob.rid
209 @ AND tagid=(SELECT tagid FROM tag WHERE tagname='user')),
210 @ user),
211 @ (SELECT count(*) FROM plink WHERE pid=blob.rid AND isprim=1),
212 @ (SELECT count(*) FROM plink WHERE cid=blob.rid),
213 @ NOT EXISTS (SELECT 1 FROM plink WHERE pid=blob.rid),
214 @ (SELECT value FROM tagxref
215 @ WHERE rid=blob.rid
216 @ AND tagid=(SELECT tagid FROM tag WHERE tagname='bgcolor')
217 @ UNION ALL
218 @ SELECT value FROM tagxref
219 @ WHERE rid=blob.rid
220 @ AND tagid=(SELECT tagid FROM tag WHERE tagname='br-bgcolor'))
221 @ FROM event JOIN blob
222 @ WHERE blob.rid=event.objid
223 ;
224 return zBaseSql;
225 }
226
227 /*
228 ** WEBPAGE: timeline
229 **
230 ** Query parameters:
@@ -213,38 +247,25 @@
247 int objid = atoi(PD("e","0"));
248 int relatedEvents = P("r")!=0;
249 int afterFlag = P("a")!=0;
250 int firstEvent;
251 int lastEvent;
 
252
253 /* To view the timeline, must have permission to read project data.
254 */
255 login_check_credentials();
256 if( !g.okRead ){ login_needed(); return; }
257
258 style_header("Timeline");
 
 
259 if( !g.okHistory &&
260 db_exists("SELECT 1 FROM user"
261 " WHERE login='anonymous'"
262 " AND cap LIKE '%%h%%'") ){
263 @ <p><b>Note:</b> You will be able to access <u>much</u> more
264 @ historical information if <a href="%s(g.zBaseURL)/login">login</a>.</p>
265 }
266 zSQL = mprintf("%s", timeline_query_for_www());
 
 
 
 
 
 
 
 
 
 
267 if( zUser ){
268 zSQL = mprintf("%z AND event.user=%Q", zSQL, zUser);
269 }
270 if( objid ){
271 char *z = db_text(0, "SELECT datetime(event.mtime) FROM event"
@@ -367,10 +388,19 @@
388 /*
389 ** The input query q selects various records. Print a human-readable
390 ** summary of those records.
391 **
392 ** Limit the number of entries printed to nLine.
393 **
394 ** The query should return these columns:
395 **
396 ** 0. rid
397 ** 1. uuid
398 ** 2. Date/Time
399 ** 3. Comment string and user
400 ** 4. Number of non-merge children
401 ** 5. Number of parents
402 */
403 void print_timeline(Stmt *q, int mxLine){
404 int nLine = 0;
405 char zPrevDate[20];
406 zPrevDate[0] = 0;
@@ -409,10 +439,38 @@
439 }
440 nLine += comment_print(zFree, 9, 79);
441 sqlite3_free(zFree);
442 }
443 }
444
445 /*
446 ** Return a pointer to a static string that forms the basis for
447 ** a timeline query for display on a TTY.
448 */
449 const char *timeline_query_for_tty(void){
450 static const char zBaseSql[] =
451 @ SELECT
452 @ blob.rid,
453 @ uuid,
454 @ datetime(event.mtime,'localtime'),
455 @ coalesce((SELECT value FROM tagxref
456 @ WHERE rid=blob.rid
457 @ AND tagid=(SELECT tagid FROM tag WHERE tagname='comment')),
458 @ comment)
459 @ || ' (by ' ||
460 @ coalesce((SELECT value FROM tagxref
461 @ WHERE rid=blob.rid
462 @ AND tagid=(SELECT tagid FROM tag WHERE tagname='user')),
463 @ user)
464 @ || ')',
465 @ (SELECT count(*) FROM plink WHERE pid=blob.rid AND isprim),
466 @ (SELECT count(*) FROM plink WHERE cid=blob.rid)
467 @ FROM event, blob
468 @ WHERE blob.rid=event.objid
469 ;
470 return zBaseSql;
471 }
472
473
474 /*
475 ** COMMAND: timeline
476 **
@@ -492,19 +550,14 @@
550 if( mode==3 || mode==4 ){
551 fossil_fatal("cannot compute descendents or ancestors of a date");
552 }
553 zDate = mprintf("(SELECT julianday(%Q, 'utc'))", zOrigin);
554 }
555 zSQL = mprintf("%s AND event.mtime %s %s",
556 timeline_query_for_tty(),
557 (mode==1 || mode==4) ? "<=" : ">=",
558 zDate
 
 
 
 
 
559 );
560 if( mode==3 || mode==4 ){
561 db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
562 if( mode==3 ){
563 compute_descendents(objid, n);
564
+3 -5
--- src/update.c
+++ src/update.c
@@ -68,16 +68,14 @@
6868
}
6969
}else{
7070
compute_leaves(vid);
7171
if( db_int(0, "SELECT count(*) FROM leaves")>1 ){
7272
db_prepare(&q,
73
- "SELECT blob.rid, uuid, datetime(event.mtime,'localtime'),"
74
- " comment || ' (by ' || user || ')', 1, 1"
75
- " FROM event, blob"
76
- " WHERE event.type='ci' AND blob.rid=event.objid"
73
+ "%s "
7774
" AND event.objid IN leaves"
78
- " ORDER BY event.mtime DESC"
75
+ " ORDER BY event.mtime DESC",
76
+ timeline_query_for_tty()
7977
);
8078
print_timeline(&q, 100);
8179
db_finalize(&q);
8280
fossil_fatal("Multiple descendents");
8381
}
8482
--- src/update.c
+++ src/update.c
@@ -68,16 +68,14 @@
68 }
69 }else{
70 compute_leaves(vid);
71 if( db_int(0, "SELECT count(*) FROM leaves")>1 ){
72 db_prepare(&q,
73 "SELECT blob.rid, uuid, datetime(event.mtime,'localtime'),"
74 " comment || ' (by ' || user || ')', 1, 1"
75 " FROM event, blob"
76 " WHERE event.type='ci' AND blob.rid=event.objid"
77 " AND event.objid IN leaves"
78 " ORDER BY event.mtime DESC"
 
79 );
80 print_timeline(&q, 100);
81 db_finalize(&q);
82 fossil_fatal("Multiple descendents");
83 }
84
--- src/update.c
+++ src/update.c
@@ -68,16 +68,14 @@
68 }
69 }else{
70 compute_leaves(vid);
71 if( db_int(0, "SELECT count(*) FROM leaves")>1 ){
72 db_prepare(&q,
73 "%s "
 
 
 
74 " AND event.objid IN leaves"
75 " ORDER BY event.mtime DESC",
76 timeline_query_for_tty()
77 );
78 print_timeline(&q, 100);
79 db_finalize(&q);
80 fossil_fatal("Multiple descendents");
81 }
82

Keyboard Shortcuts

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