Fossil SCM

The "tag" command allows tag artifacts to be inserted for creating and cancelling tags and properties. Timeline responds to bgcolor, br-bgcolor, comment, and user properties.

drh 2007-09-22 15:50 trunk
Commit 3b5514ed825c5cd629359a712b357254a81fe719
+68 -7
--- src/info.c
+++ src/info.c
@@ -114,11 +114,12 @@
114114
static int showDescendents(int pid, int depth, const char *zTitle){
115115
Stmt q;
116116
int cnt = 0;
117117
db_prepare(&q,
118118
"SELECT plink.cid, blob.uuid, datetime(plink.mtime, 'localtime'),"
119
- " event.user, event.comment"
119
+ " coalesce(event.euser,event.user),"
120
+ " coalesce(event.comment,event.ecomment)"
120121
" FROM plink, blob, event"
121122
" WHERE plink.pid=%d"
122123
" AND blob.rid=plink.cid"
123124
" AND event.objid=plink.cid"
124125
" ORDER BY plink.mtime ASC",
@@ -149,10 +150,11 @@
149150
if( n==0 ){
150151
db_multi_exec("DELETE FROM leaves WHERE rid=%d", cid);
151152
@ <b>leaf</b>
152153
}
153154
}
155
+ db_finalize(&q);
154156
if( cnt ){
155157
@ </ul>
156158
}
157159
return cnt;
158160
}
@@ -164,11 +166,12 @@
164166
static void showAncestors(int pid, int depth, const char *zTitle){
165167
Stmt q;
166168
int cnt = 0;
167169
db_prepare(&q,
168170
"SELECT plink.pid, blob.uuid, datetime(event.mtime, 'localtime'),"
169
- " event.user, event.comment"
171
+ " coalesce(event.euser,event.user),"
172
+ " coalesce(event.comment,event.ecomment)"
170173
" FROM plink, blob, event"
171174
" WHERE plink.cid=%d"
172175
" AND blob.rid=plink.pid"
173176
" AND event.objid=plink.pid"
174177
" ORDER BY event.mtime DESC",
@@ -192,10 +195,11 @@
192195
@ %s(zCom) (by %s(zUser) on %s(zDate))
193196
if( depth ){
194197
showAncestors(cid, depth-1, 0);
195198
}
196199
}
200
+ db_finalize(&q);
197201
if( cnt ){
198202
@ </ul>
199203
}
200204
}
201205
@@ -206,11 +210,12 @@
206210
static void showLeaves(void){
207211
Stmt q;
208212
int cnt = 0;
209213
db_prepare(&q,
210214
"SELECT blob.uuid, datetime(event.mtime, 'localtime'),"
211
- " event.user, event.comment"
215
+ " coalesce(event.euser, event.user),"
216
+ " coalesce(event.ecomment,event.comment)"
212217
" FROM leaves, plink, blob, event"
213218
" WHERE plink.cid=leaves.rid"
214219
" AND blob.rid=leaves.rid"
215220
" AND event.objid=leaves.rid"
216221
" ORDER BY event.mtime DESC"
@@ -227,10 +232,61 @@
227232
}
228233
@ <li>
229234
hyperlink_to_uuid(zUuid);
230235
@ %s(zCom) (by %s(zUser) on %s(zDate))
231236
}
237
+ db_finalize(&q);
238
+ if( cnt ){
239
+ @ </ul>
240
+ }
241
+}
242
+
243
+/*
244
+** Show information about all tags on a given node.
245
+*/
246
+static void showTags(int rid){
247
+ Stmt q;
248
+ int cnt = 0;
249
+ db_prepare(&q,
250
+ "SELECT tag.tagid, tagname, srcid, blob.uuid, value,"
251
+ " datetime(tagxref.mtime,'localtime'), addflag"
252
+ " FROM tagxref JOIN tag ON tagxref.tagid=tag.tagid"
253
+ " LEFT JOIN blob ON blob.rid=tagxref.srcid"
254
+ " WHERE tagxref.rid=%d"
255
+ " ORDER BY tagname", rid
256
+ );
257
+ while( db_step(&q)==SQLITE_ROW ){
258
+ int tagid = db_column_int(&q, 0);
259
+ const char *zTagname = db_column_text(&q, 1);
260
+ int srcid = db_column_int(&q, 2);
261
+ const char *zUuid = db_column_text(&q, 3);
262
+ const char *zValue = db_column_text(&q, 4);
263
+ const char *zDate = db_column_text(&q, 5);
264
+ int addFlag = db_column_int(&q, 6);
265
+ cnt++;
266
+ if( cnt==1 ){
267
+ @ <h2>Tags And Properties</h2>
268
+ @ <ul>
269
+ }
270
+ @ <li>
271
+ @ <b>%h(zTagname)</b>
272
+ if( zValue ){
273
+ @ = %h(zValue)<i>
274
+ }else if( !addFlag ){
275
+ @ <i>Cancelled
276
+ }else{
277
+ @ <i>
278
+ }
279
+ if( srcid==0 ){
280
+ @ Inherited
281
+ }else if( zUuid ){
282
+ @ From
283
+ hyperlink_to_uuid(zUuid);
284
+ }
285
+ @ on %s(zDate)</i>
286
+ }
287
+ db_finalize(&q);
232288
if( cnt ){
233289
@ </ul>
234290
}
235291
}
236292
@@ -266,21 +322,22 @@
266322
if( db_step(&q)==SQLITE_ROW ){
267323
const char *zUuid = db_column_text(&q, 0);
268324
@ <h2>Version %s(zUuid)</h2>
269325
@ <ul>
270326
@ <li><b>Date:</b> %s(db_column_text(&q, 1))</li>
271
- @ <li><b>User:</b> %s(db_column_text(&q, 2))</li>
272
- @ <li><b>Comment:</b> %s(db_column_text(&q, 3))</li>
327
+ @ <li><b>Original&nbsp;User:</b> %s(db_column_text(&q, 2))</li>
328
+ @ <li><b>Original&nbsp;Comment:</b> %s(db_column_text(&q, 3))</li>
273329
@ <li><a href="%s(g.zBaseURL)/vdiff/%d(rid)">diff</a></li>
274330
@ <li><a href="%s(g.zBaseURL)/zip/%s(zUuid).zip">ZIP archive</a></li>
275331
@ <li><a href="%s(g.zBaseURL)/fview/%d(rid)">manifest</a></li>
276332
if( g.okSetup ){
277333
@ <li><b>Record ID:</b> %d(rid)</li>
278334
}
279335
@ </ul>
280336
}
281337
db_finalize(&q);
338
+ showTags(rid);
282339
@ <p><h2>Changes:</h2>
283340
@ <ul>
284341
db_prepare(&q,
285342
"SELECT name, pid, fid"
286343
" FROM mlink, filename"
@@ -324,11 +381,13 @@
324381
style_header("File History");
325382
326383
zPrevDate[0] = 0;
327384
db_prepare(&q,
328385
"SELECT a.uuid, substr(b.uuid,1,10), datetime(event.mtime,'localtime'),"
329
- " event.comment, event.user, mlink.pid, mlink.fid"
386
+ " coalesce(event.ecomment, event.comment),"
387
+ " coalesce(event.euser, event.user),"
388
+ " mlink.pid, mlink.fid"
330389
" FROM mlink, blob a, blob b, event"
331390
" WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)"
332391
" AND a.rid=mlink.mid"
333392
" AND b.rid=mlink.fid"
334393
" AND event.objid=mlink.mid"
@@ -449,11 +508,13 @@
449508
static void object_description(int rid, int linkToView){
450509
Stmt q;
451510
int cnt = 0;
452511
db_prepare(&q,
453512
"SELECT filename.name, datetime(event.mtime), substr(a.uuid,1,10),"
454
- " event.comment, event.user, b.uuid"
513
+ " coalesce(event.comment,event.ecomment),"
514
+ " coalesce(event.euser,event.user),"
515
+ " b.uuid"
455516
" FROM mlink, filename, event, blob a, blob b"
456517
" WHERE filename.fnid=mlink.fnid"
457518
" AND event.objid=mlink.mid"
458519
" AND a.rid=mlink.fid"
459520
" AND b.rid=mlink.mid"
460521
--- src/info.c
+++ src/info.c
@@ -114,11 +114,12 @@
114 static int showDescendents(int pid, int depth, const char *zTitle){
115 Stmt q;
116 int cnt = 0;
117 db_prepare(&q,
118 "SELECT plink.cid, blob.uuid, datetime(plink.mtime, 'localtime'),"
119 " event.user, event.comment"
 
120 " FROM plink, blob, event"
121 " WHERE plink.pid=%d"
122 " AND blob.rid=plink.cid"
123 " AND event.objid=plink.cid"
124 " ORDER BY plink.mtime ASC",
@@ -149,10 +150,11 @@
149 if( n==0 ){
150 db_multi_exec("DELETE FROM leaves WHERE rid=%d", cid);
151 @ <b>leaf</b>
152 }
153 }
 
154 if( cnt ){
155 @ </ul>
156 }
157 return cnt;
158 }
@@ -164,11 +166,12 @@
164 static void showAncestors(int pid, int depth, const char *zTitle){
165 Stmt q;
166 int cnt = 0;
167 db_prepare(&q,
168 "SELECT plink.pid, blob.uuid, datetime(event.mtime, 'localtime'),"
169 " event.user, event.comment"
 
170 " FROM plink, blob, event"
171 " WHERE plink.cid=%d"
172 " AND blob.rid=plink.pid"
173 " AND event.objid=plink.pid"
174 " ORDER BY event.mtime DESC",
@@ -192,10 +195,11 @@
192 @ %s(zCom) (by %s(zUser) on %s(zDate))
193 if( depth ){
194 showAncestors(cid, depth-1, 0);
195 }
196 }
 
197 if( cnt ){
198 @ </ul>
199 }
200 }
201
@@ -206,11 +210,12 @@
206 static void showLeaves(void){
207 Stmt q;
208 int cnt = 0;
209 db_prepare(&q,
210 "SELECT blob.uuid, datetime(event.mtime, 'localtime'),"
211 " event.user, event.comment"
 
212 " FROM leaves, plink, blob, event"
213 " WHERE plink.cid=leaves.rid"
214 " AND blob.rid=leaves.rid"
215 " AND event.objid=leaves.rid"
216 " ORDER BY event.mtime DESC"
@@ -227,10 +232,61 @@
227 }
228 @ <li>
229 hyperlink_to_uuid(zUuid);
230 @ %s(zCom) (by %s(zUser) on %s(zDate))
231 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232 if( cnt ){
233 @ </ul>
234 }
235 }
236
@@ -266,21 +322,22 @@
266 if( db_step(&q)==SQLITE_ROW ){
267 const char *zUuid = db_column_text(&q, 0);
268 @ <h2>Version %s(zUuid)</h2>
269 @ <ul>
270 @ <li><b>Date:</b> %s(db_column_text(&q, 1))</li>
271 @ <li><b>User:</b> %s(db_column_text(&q, 2))</li>
272 @ <li><b>Comment:</b> %s(db_column_text(&q, 3))</li>
273 @ <li><a href="%s(g.zBaseURL)/vdiff/%d(rid)">diff</a></li>
274 @ <li><a href="%s(g.zBaseURL)/zip/%s(zUuid).zip">ZIP archive</a></li>
275 @ <li><a href="%s(g.zBaseURL)/fview/%d(rid)">manifest</a></li>
276 if( g.okSetup ){
277 @ <li><b>Record ID:</b> %d(rid)</li>
278 }
279 @ </ul>
280 }
281 db_finalize(&q);
 
282 @ <p><h2>Changes:</h2>
283 @ <ul>
284 db_prepare(&q,
285 "SELECT name, pid, fid"
286 " FROM mlink, filename"
@@ -324,11 +381,13 @@
324 style_header("File History");
325
326 zPrevDate[0] = 0;
327 db_prepare(&q,
328 "SELECT a.uuid, substr(b.uuid,1,10), datetime(event.mtime,'localtime'),"
329 " event.comment, event.user, mlink.pid, mlink.fid"
 
 
330 " FROM mlink, blob a, blob b, event"
331 " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)"
332 " AND a.rid=mlink.mid"
333 " AND b.rid=mlink.fid"
334 " AND event.objid=mlink.mid"
@@ -449,11 +508,13 @@
449 static void object_description(int rid, int linkToView){
450 Stmt q;
451 int cnt = 0;
452 db_prepare(&q,
453 "SELECT filename.name, datetime(event.mtime), substr(a.uuid,1,10),"
454 " event.comment, event.user, b.uuid"
 
 
455 " FROM mlink, filename, event, blob a, blob b"
456 " WHERE filename.fnid=mlink.fnid"
457 " AND event.objid=mlink.mid"
458 " AND a.rid=mlink.fid"
459 " AND b.rid=mlink.mid"
460
--- src/info.c
+++ src/info.c
@@ -114,11 +114,12 @@
114 static int showDescendents(int pid, int depth, const char *zTitle){
115 Stmt q;
116 int cnt = 0;
117 db_prepare(&q,
118 "SELECT plink.cid, blob.uuid, datetime(plink.mtime, 'localtime'),"
119 " coalesce(event.euser,event.user),"
120 " coalesce(event.comment,event.ecomment)"
121 " FROM plink, blob, event"
122 " WHERE plink.pid=%d"
123 " AND blob.rid=plink.cid"
124 " AND event.objid=plink.cid"
125 " ORDER BY plink.mtime ASC",
@@ -149,10 +150,11 @@
150 if( n==0 ){
151 db_multi_exec("DELETE FROM leaves WHERE rid=%d", cid);
152 @ <b>leaf</b>
153 }
154 }
155 db_finalize(&q);
156 if( cnt ){
157 @ </ul>
158 }
159 return cnt;
160 }
@@ -164,11 +166,12 @@
166 static void showAncestors(int pid, int depth, const char *zTitle){
167 Stmt q;
168 int cnt = 0;
169 db_prepare(&q,
170 "SELECT plink.pid, blob.uuid, datetime(event.mtime, 'localtime'),"
171 " coalesce(event.euser,event.user),"
172 " coalesce(event.comment,event.ecomment)"
173 " FROM plink, blob, event"
174 " WHERE plink.cid=%d"
175 " AND blob.rid=plink.pid"
176 " AND event.objid=plink.pid"
177 " ORDER BY event.mtime DESC",
@@ -192,10 +195,11 @@
195 @ %s(zCom) (by %s(zUser) on %s(zDate))
196 if( depth ){
197 showAncestors(cid, depth-1, 0);
198 }
199 }
200 db_finalize(&q);
201 if( cnt ){
202 @ </ul>
203 }
204 }
205
@@ -206,11 +210,12 @@
210 static void showLeaves(void){
211 Stmt q;
212 int cnt = 0;
213 db_prepare(&q,
214 "SELECT blob.uuid, datetime(event.mtime, 'localtime'),"
215 " coalesce(event.euser, event.user),"
216 " coalesce(event.ecomment,event.comment)"
217 " FROM leaves, plink, blob, event"
218 " WHERE plink.cid=leaves.rid"
219 " AND blob.rid=leaves.rid"
220 " AND event.objid=leaves.rid"
221 " ORDER BY event.mtime DESC"
@@ -227,10 +232,61 @@
232 }
233 @ <li>
234 hyperlink_to_uuid(zUuid);
235 @ %s(zCom) (by %s(zUser) on %s(zDate))
236 }
237 db_finalize(&q);
238 if( cnt ){
239 @ </ul>
240 }
241 }
242
243 /*
244 ** Show information about all tags on a given node.
245 */
246 static void showTags(int rid){
247 Stmt q;
248 int cnt = 0;
249 db_prepare(&q,
250 "SELECT tag.tagid, tagname, srcid, blob.uuid, value,"
251 " datetime(tagxref.mtime,'localtime'), addflag"
252 " FROM tagxref JOIN tag ON tagxref.tagid=tag.tagid"
253 " LEFT JOIN blob ON blob.rid=tagxref.srcid"
254 " WHERE tagxref.rid=%d"
255 " ORDER BY tagname", rid
256 );
257 while( db_step(&q)==SQLITE_ROW ){
258 int tagid = db_column_int(&q, 0);
259 const char *zTagname = db_column_text(&q, 1);
260 int srcid = db_column_int(&q, 2);
261 const char *zUuid = db_column_text(&q, 3);
262 const char *zValue = db_column_text(&q, 4);
263 const char *zDate = db_column_text(&q, 5);
264 int addFlag = db_column_int(&q, 6);
265 cnt++;
266 if( cnt==1 ){
267 @ <h2>Tags And Properties</h2>
268 @ <ul>
269 }
270 @ <li>
271 @ <b>%h(zTagname)</b>
272 if( zValue ){
273 @ = %h(zValue)<i>
274 }else if( !addFlag ){
275 @ <i>Cancelled
276 }else{
277 @ <i>
278 }
279 if( srcid==0 ){
280 @ Inherited
281 }else if( zUuid ){
282 @ From
283 hyperlink_to_uuid(zUuid);
284 }
285 @ on %s(zDate)</i>
286 }
287 db_finalize(&q);
288 if( cnt ){
289 @ </ul>
290 }
291 }
292
@@ -266,21 +322,22 @@
322 if( db_step(&q)==SQLITE_ROW ){
323 const char *zUuid = db_column_text(&q, 0);
324 @ <h2>Version %s(zUuid)</h2>
325 @ <ul>
326 @ <li><b>Date:</b> %s(db_column_text(&q, 1))</li>
327 @ <li><b>Original&nbsp;User:</b> %s(db_column_text(&q, 2))</li>
328 @ <li><b>Original&nbsp;Comment:</b> %s(db_column_text(&q, 3))</li>
329 @ <li><a href="%s(g.zBaseURL)/vdiff/%d(rid)">diff</a></li>
330 @ <li><a href="%s(g.zBaseURL)/zip/%s(zUuid).zip">ZIP archive</a></li>
331 @ <li><a href="%s(g.zBaseURL)/fview/%d(rid)">manifest</a></li>
332 if( g.okSetup ){
333 @ <li><b>Record ID:</b> %d(rid)</li>
334 }
335 @ </ul>
336 }
337 db_finalize(&q);
338 showTags(rid);
339 @ <p><h2>Changes:</h2>
340 @ <ul>
341 db_prepare(&q,
342 "SELECT name, pid, fid"
343 " FROM mlink, filename"
@@ -324,11 +381,13 @@
381 style_header("File History");
382
383 zPrevDate[0] = 0;
384 db_prepare(&q,
385 "SELECT a.uuid, substr(b.uuid,1,10), datetime(event.mtime,'localtime'),"
386 " coalesce(event.ecomment, event.comment),"
387 " coalesce(event.euser, event.user),"
388 " mlink.pid, mlink.fid"
389 " FROM mlink, blob a, blob b, event"
390 " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)"
391 " AND a.rid=mlink.mid"
392 " AND b.rid=mlink.fid"
393 " AND event.objid=mlink.mid"
@@ -449,11 +508,13 @@
508 static void object_description(int rid, int linkToView){
509 Stmt q;
510 int cnt = 0;
511 db_prepare(&q,
512 "SELECT filename.name, datetime(event.mtime), substr(a.uuid,1,10),"
513 " coalesce(event.comment,event.ecomment),"
514 " coalesce(event.euser,event.user),"
515 " b.uuid"
516 " FROM mlink, filename, event, blob a, blob b"
517 " WHERE filename.fnid=mlink.fnid"
518 " AND event.objid=mlink.mid"
519 " AND a.rid=mlink.fid"
520 " AND b.rid=mlink.mid"
521
+55 -27
--- src/manifest.c
+++ src/manifest.c
@@ -19,22 +19,31 @@
1919
** [email protected]
2020
** http://www.hwaci.com/drh/
2121
**
2222
*******************************************************************************
2323
**
24
-** This file contains code used to cross link manifests
24
+** This file contains code used to cross link control files and
25
+** manifests.
2526
*/
2627
#include "config.h"
2728
#include "manifest.h"
2829
#include <assert.h>
2930
3031
#if INTERFACE
32
+/*
33
+** Types of control files
34
+*/
35
+#define CFTYPE_MANIFEST 1
36
+#define CFTYPE_CLUSTER 2
37
+#define CFTYPE_CONTROL 3
38
+
3139
/*
3240
** A parsed manifest or cluster.
3341
*/
3442
struct Manifest {
3543
Blob content; /* The original content blob */
44
+ int type; /* Type of file */
3645
char *zComment; /* Decoded comment */
3746
double rDate; /* Time in the "D" line */
3847
char *zUser; /* Name of the user */
3948
char *zRepoCksum; /* MD5 checksum of the baseline content */
4049
int nFile; /* Number of F lines */
@@ -244,10 +253,14 @@
244253
if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error;
245254
defossilize(zName);
246255
if( zName[0]!='-' && zName[0]!='+' ){
247256
goto manifest_syntax_error;
248257
}
258
+ if( validate16(&zName[1], strlen(&zName[1])) ){
259
+ /* Do not allow tags whose names look like UUIDs */
260
+ goto manifest_syntax_error;
261
+ }
249262
if( p->nTag>=p->nTagAlloc ){
250263
p->nTagAlloc = p->nTagAlloc*2 + 10;
251264
p->aTag = realloc(p->aTag, p->nTagAlloc*sizeof(p->aTag[0]) );
252265
if( p->aTag==0 ) fossil_panic("out of memory");
253266
}
@@ -347,21 +360,24 @@
347360
if( !seenHeader ) goto manifest_syntax_error;
348361
349362
if( p->nFile>0 ){
350363
if( p->nCChild>0 ) goto manifest_syntax_error;
351364
if( p->rDate==0.0 ) goto manifest_syntax_error;
365
+ p->type = CFTYPE_MANIFEST;
352366
}else if( p->nCChild>0 ){
353367
if( p->rDate>0.0 ) goto manifest_syntax_error;
354368
if( p->zComment!=0 ) goto manifest_syntax_error;
355369
if( p->zUser!=0 ) goto manifest_syntax_error;
356370
if( p->nTag>0 ) goto manifest_syntax_error;
357371
if( p->nParent>0 ) goto manifest_syntax_error;
358372
if( p->zRepoCksum!=0 ) goto manifest_syntax_error;
373
+ p->type = CFTYPE_CLUSTER;
359374
}else if( p->nTag>0 ){
360375
if( p->rDate<=0.0 ) goto manifest_syntax_error;
361376
if( p->zRepoCksum!=0 ) goto manifest_syntax_error;
362377
if( p->nParent>0 ) goto manifest_syntax_error;
378
+ p->type = CFTYPE_CONTROL;
363379
}else{
364380
goto manifest_syntax_error;
365381
}
366382
367383
md5sum_init();
@@ -481,37 +497,49 @@
481497
482498
if( manifest_parse(&m, pContent)==0 ){
483499
return 0;
484500
}
485501
db_begin_transaction();
486
- if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d", rid) ){
487
- for(i=0; i<m.nParent; i++){
488
- int pid = uuid_to_rid(m.azParent[i], 1);
489
- db_multi_exec("INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime)"
490
- "VALUES(%d, %d, %d, %.17g)", pid, rid, i==0, m.rDate);
491
- if( i==0 ){
492
- add_mlink(pid, 0, rid, &m);
493
- }
494
- }
495
- db_prepare(&q, "SELECT cid FROM plink WHERE pid=%d AND isprim", rid);
496
- while( db_step(&q)==SQLITE_ROW ){
497
- int cid = db_column_int(&q, 0);
498
- add_mlink(rid, &m, cid, 0);
499
- }
500
- db_finalize(&q);
501
- db_multi_exec(
502
- "INSERT INTO event(type,mtime,objid,user,comment)"
503
- "VALUES('ci',%.17g,%d,%Q,%Q)",
504
- m.rDate, rid, m.zUser, m.zComment
505
- );
506
- }
507
- for(i=0; i<m.nCChild; i++){
508
- int rid;
509
- rid = uuid_to_rid(m.azCChild[i], 1);
510
- if( rid>0 ){
511
- db_multi_exec("DELETE FROM unclustered WHERE rid=%d", rid);
502
+ if( m.type==CFTYPE_MANIFEST ){
503
+ if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d", rid) ){
504
+ for(i=0; i<m.nParent; i++){
505
+ int pid = uuid_to_rid(m.azParent[i], 1);
506
+ db_multi_exec("INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime)"
507
+ "VALUES(%d, %d, %d, %.17g)", pid, rid, i==0, m.rDate);
508
+ if( i==0 ){
509
+ add_mlink(pid, 0, rid, &m);
510
+ }
511
+ }
512
+ db_prepare(&q, "SELECT cid FROM plink WHERE pid=%d AND isprim", rid);
513
+ while( db_step(&q)==SQLITE_ROW ){
514
+ int cid = db_column_int(&q, 0);
515
+ add_mlink(rid, &m, cid, 0);
516
+ }
517
+ db_finalize(&q);
518
+ db_multi_exec(
519
+ "INSERT INTO event(type,mtime,objid,user,comment)"
520
+ "VALUES('ci',%.17g,%d,%Q,%Q)",
521
+ m.rDate, rid, m.zUser, m.zComment
522
+ );
523
+ }
524
+ }
525
+ if( m.type==CFTYPE_CLUSTER ){
526
+ for(i=0; i<m.nCChild; i++){
527
+ int mid;
528
+ mid = uuid_to_rid(m.azCChild[i], 1);
529
+ if( mid>0 ){
530
+ db_multi_exec("DELETE FROM unclustered WHERE rid=%d", mid);
531
+ }
532
+ }
533
+ }
534
+ if( m.type==CFTYPE_CONTROL || m.type==CFTYPE_MANIFEST ){
535
+ for(i=0; i<m.nTag; i++){
536
+ int tid;
537
+ tid = uuid_to_rid(m.aTag[i].zUuid, 1);
538
+ tag_insert(&m.aTag[i].zName[1], m.aTag[i].zName[0]=='+',
539
+ m.aTag[i].zValue, rid, m.rDate, tid);
512540
}
513541
}
514542
db_end_transaction(0);
515543
manifest_clear(&m);
516544
return 1;
517545
}
518546
--- src/manifest.c
+++ src/manifest.c
@@ -19,22 +19,31 @@
19 ** [email protected]
20 ** http://www.hwaci.com/drh/
21 **
22 *******************************************************************************
23 **
24 ** This file contains code used to cross link manifests
 
25 */
26 #include "config.h"
27 #include "manifest.h"
28 #include <assert.h>
29
30 #if INTERFACE
 
 
 
 
 
 
 
31 /*
32 ** A parsed manifest or cluster.
33 */
34 struct Manifest {
35 Blob content; /* The original content blob */
 
36 char *zComment; /* Decoded comment */
37 double rDate; /* Time in the "D" line */
38 char *zUser; /* Name of the user */
39 char *zRepoCksum; /* MD5 checksum of the baseline content */
40 int nFile; /* Number of F lines */
@@ -244,10 +253,14 @@
244 if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error;
245 defossilize(zName);
246 if( zName[0]!='-' && zName[0]!='+' ){
247 goto manifest_syntax_error;
248 }
 
 
 
 
249 if( p->nTag>=p->nTagAlloc ){
250 p->nTagAlloc = p->nTagAlloc*2 + 10;
251 p->aTag = realloc(p->aTag, p->nTagAlloc*sizeof(p->aTag[0]) );
252 if( p->aTag==0 ) fossil_panic("out of memory");
253 }
@@ -347,21 +360,24 @@
347 if( !seenHeader ) goto manifest_syntax_error;
348
349 if( p->nFile>0 ){
350 if( p->nCChild>0 ) goto manifest_syntax_error;
351 if( p->rDate==0.0 ) goto manifest_syntax_error;
 
352 }else if( p->nCChild>0 ){
353 if( p->rDate>0.0 ) goto manifest_syntax_error;
354 if( p->zComment!=0 ) goto manifest_syntax_error;
355 if( p->zUser!=0 ) goto manifest_syntax_error;
356 if( p->nTag>0 ) goto manifest_syntax_error;
357 if( p->nParent>0 ) goto manifest_syntax_error;
358 if( p->zRepoCksum!=0 ) goto manifest_syntax_error;
 
359 }else if( p->nTag>0 ){
360 if( p->rDate<=0.0 ) goto manifest_syntax_error;
361 if( p->zRepoCksum!=0 ) goto manifest_syntax_error;
362 if( p->nParent>0 ) goto manifest_syntax_error;
 
363 }else{
364 goto manifest_syntax_error;
365 }
366
367 md5sum_init();
@@ -481,37 +497,49 @@
481
482 if( manifest_parse(&m, pContent)==0 ){
483 return 0;
484 }
485 db_begin_transaction();
486 if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d", rid) ){
487 for(i=0; i<m.nParent; i++){
488 int pid = uuid_to_rid(m.azParent[i], 1);
489 db_multi_exec("INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime)"
490 "VALUES(%d, %d, %d, %.17g)", pid, rid, i==0, m.rDate);
491 if( i==0 ){
492 add_mlink(pid, 0, rid, &m);
493 }
494 }
495 db_prepare(&q, "SELECT cid FROM plink WHERE pid=%d AND isprim", rid);
496 while( db_step(&q)==SQLITE_ROW ){
497 int cid = db_column_int(&q, 0);
498 add_mlink(rid, &m, cid, 0);
499 }
500 db_finalize(&q);
501 db_multi_exec(
502 "INSERT INTO event(type,mtime,objid,user,comment)"
503 "VALUES('ci',%.17g,%d,%Q,%Q)",
504 m.rDate, rid, m.zUser, m.zComment
505 );
506 }
507 for(i=0; i<m.nCChild; i++){
508 int rid;
509 rid = uuid_to_rid(m.azCChild[i], 1);
510 if( rid>0 ){
511 db_multi_exec("DELETE FROM unclustered WHERE rid=%d", rid);
 
 
 
 
 
 
 
 
 
 
 
 
512 }
513 }
514 db_end_transaction(0);
515 manifest_clear(&m);
516 return 1;
517 }
518
--- src/manifest.c
+++ src/manifest.c
@@ -19,22 +19,31 @@
19 ** [email protected]
20 ** http://www.hwaci.com/drh/
21 **
22 *******************************************************************************
23 **
24 ** This file contains code used to cross link control files and
25 ** manifests.
26 */
27 #include "config.h"
28 #include "manifest.h"
29 #include <assert.h>
30
31 #if INTERFACE
32 /*
33 ** Types of control files
34 */
35 #define CFTYPE_MANIFEST 1
36 #define CFTYPE_CLUSTER 2
37 #define CFTYPE_CONTROL 3
38
39 /*
40 ** A parsed manifest or cluster.
41 */
42 struct Manifest {
43 Blob content; /* The original content blob */
44 int type; /* Type of file */
45 char *zComment; /* Decoded comment */
46 double rDate; /* Time in the "D" line */
47 char *zUser; /* Name of the user */
48 char *zRepoCksum; /* MD5 checksum of the baseline content */
49 int nFile; /* Number of F lines */
@@ -244,10 +253,14 @@
253 if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error;
254 defossilize(zName);
255 if( zName[0]!='-' && zName[0]!='+' ){
256 goto manifest_syntax_error;
257 }
258 if( validate16(&zName[1], strlen(&zName[1])) ){
259 /* Do not allow tags whose names look like UUIDs */
260 goto manifest_syntax_error;
261 }
262 if( p->nTag>=p->nTagAlloc ){
263 p->nTagAlloc = p->nTagAlloc*2 + 10;
264 p->aTag = realloc(p->aTag, p->nTagAlloc*sizeof(p->aTag[0]) );
265 if( p->aTag==0 ) fossil_panic("out of memory");
266 }
@@ -347,21 +360,24 @@
360 if( !seenHeader ) goto manifest_syntax_error;
361
362 if( p->nFile>0 ){
363 if( p->nCChild>0 ) goto manifest_syntax_error;
364 if( p->rDate==0.0 ) goto manifest_syntax_error;
365 p->type = CFTYPE_MANIFEST;
366 }else if( p->nCChild>0 ){
367 if( p->rDate>0.0 ) goto manifest_syntax_error;
368 if( p->zComment!=0 ) goto manifest_syntax_error;
369 if( p->zUser!=0 ) goto manifest_syntax_error;
370 if( p->nTag>0 ) goto manifest_syntax_error;
371 if( p->nParent>0 ) goto manifest_syntax_error;
372 if( p->zRepoCksum!=0 ) goto manifest_syntax_error;
373 p->type = CFTYPE_CLUSTER;
374 }else if( p->nTag>0 ){
375 if( p->rDate<=0.0 ) goto manifest_syntax_error;
376 if( p->zRepoCksum!=0 ) goto manifest_syntax_error;
377 if( p->nParent>0 ) goto manifest_syntax_error;
378 p->type = CFTYPE_CONTROL;
379 }else{
380 goto manifest_syntax_error;
381 }
382
383 md5sum_init();
@@ -481,37 +497,49 @@
497
498 if( manifest_parse(&m, pContent)==0 ){
499 return 0;
500 }
501 db_begin_transaction();
502 if( m.type==CFTYPE_MANIFEST ){
503 if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d", rid) ){
504 for(i=0; i<m.nParent; i++){
505 int pid = uuid_to_rid(m.azParent[i], 1);
506 db_multi_exec("INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime)"
507 "VALUES(%d, %d, %d, %.17g)", pid, rid, i==0, m.rDate);
508 if( i==0 ){
509 add_mlink(pid, 0, rid, &m);
510 }
511 }
512 db_prepare(&q, "SELECT cid FROM plink WHERE pid=%d AND isprim", rid);
513 while( db_step(&q)==SQLITE_ROW ){
514 int cid = db_column_int(&q, 0);
515 add_mlink(rid, &m, cid, 0);
516 }
517 db_finalize(&q);
518 db_multi_exec(
519 "INSERT INTO event(type,mtime,objid,user,comment)"
520 "VALUES('ci',%.17g,%d,%Q,%Q)",
521 m.rDate, rid, m.zUser, m.zComment
522 );
523 }
524 }
525 if( m.type==CFTYPE_CLUSTER ){
526 for(i=0; i<m.nCChild; i++){
527 int mid;
528 mid = uuid_to_rid(m.azCChild[i], 1);
529 if( mid>0 ){
530 db_multi_exec("DELETE FROM unclustered WHERE rid=%d", mid);
531 }
532 }
533 }
534 if( m.type==CFTYPE_CONTROL || m.type==CFTYPE_MANIFEST ){
535 for(i=0; i<m.nTag; i++){
536 int tid;
537 tid = uuid_to_rid(m.aTag[i].zUuid, 1);
538 tag_insert(&m.aTag[i].zName[1], m.aTag[i].zName[0]=='+',
539 m.aTag[i].zValue, rid, m.rDate, tid);
540 }
541 }
542 db_end_transaction(0);
543 manifest_clear(&m);
544 return 1;
545 }
546
+30 -3
--- src/name.c
+++ src/name.c
@@ -33,20 +33,47 @@
3333
3434
/*
3535
** This routine takes a user-entered UUID which might be in mixed
3636
** case and might only be a prefix of the full UUID and converts it
3737
** into the full-length UUID in canonical form.
38
+**
39
+** If the input is not a UUID or a UUID prefix, then try to resolve
40
+** the name as a tag.
3841
**
3942
** Return the number of errors.
4043
*/
4144
int name_to_uuid(Blob *pName, int iErrPriority){
4245
int rc;
4346
int sz;
4447
sz = blob_size(pName);
4548
if( sz>UUID_SIZE || sz<4 || !validate16(blob_buffer(pName), sz) ){
46
- fossil_error(iErrPriority, "not a valid object name: %b", pName);
47
- return 1;
49
+ Stmt q;
50
+ Blob uuid;
51
+
52
+ db_prepare(&q,
53
+ "SELECT (SELECT uuid FROM blob WHERE rid=objid)"
54
+ " FROM tagxref JOIN event ON rid=objid"
55
+ " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%B)"
56
+ " AND addflag"
57
+ " AND value IS NULL"
58
+ " ORDER BY event.mtime DESC",
59
+ pName
60
+ );
61
+ blob_zero(&uuid);
62
+ if( db_step(&q)==SQLITE_ROW ){
63
+ db_column_blob(&q, 0, &uuid);
64
+ }
65
+ db_finalize(&q);
66
+ if( blob_size(&uuid)==0 ){
67
+ fossil_error(iErrPriority, "not a valid object name: %b", pName);
68
+ blob_reset(&uuid);
69
+ return 1;
70
+ }else{
71
+ blob_reset(pName);
72
+ *pName = uuid;
73
+ return 0;
74
+ }
4875
}
4976
blob_materialize(pName);
5077
canonical16(blob_buffer(pName), sz);
5178
if( sz==UUID_SIZE ){
5279
rc = db_int(1, "SELECT 0 FROM blob WHERE uuid=%B", pName);
@@ -120,11 +147,11 @@
120147
return rid;
121148
}
122149
}
123150
blob_init(&name, zName, -1);
124151
if( name_to_uuid(&name, 1) ){
125
- fossil_panic("%s", g.zErrMsg);
152
+ fossil_fatal("%s", g.zErrMsg);
126153
}
127154
rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &name);
128155
blob_reset(&name);
129156
return rid;
130157
}
131158
--- src/name.c
+++ src/name.c
@@ -33,20 +33,47 @@
33
34 /*
35 ** This routine takes a user-entered UUID which might be in mixed
36 ** case and might only be a prefix of the full UUID and converts it
37 ** into the full-length UUID in canonical form.
 
 
 
38 **
39 ** Return the number of errors.
40 */
41 int name_to_uuid(Blob *pName, int iErrPriority){
42 int rc;
43 int sz;
44 sz = blob_size(pName);
45 if( sz>UUID_SIZE || sz<4 || !validate16(blob_buffer(pName), sz) ){
46 fossil_error(iErrPriority, "not a valid object name: %b", pName);
47 return 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48 }
49 blob_materialize(pName);
50 canonical16(blob_buffer(pName), sz);
51 if( sz==UUID_SIZE ){
52 rc = db_int(1, "SELECT 0 FROM blob WHERE uuid=%B", pName);
@@ -120,11 +147,11 @@
120 return rid;
121 }
122 }
123 blob_init(&name, zName, -1);
124 if( name_to_uuid(&name, 1) ){
125 fossil_panic("%s", g.zErrMsg);
126 }
127 rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &name);
128 blob_reset(&name);
129 return rid;
130 }
131
--- src/name.c
+++ src/name.c
@@ -33,20 +33,47 @@
33
34 /*
35 ** This routine takes a user-entered UUID which might be in mixed
36 ** case and might only be a prefix of the full UUID and converts it
37 ** into the full-length UUID in canonical form.
38 **
39 ** If the input is not a UUID or a UUID prefix, then try to resolve
40 ** the name as a tag.
41 **
42 ** Return the number of errors.
43 */
44 int name_to_uuid(Blob *pName, int iErrPriority){
45 int rc;
46 int sz;
47 sz = blob_size(pName);
48 if( sz>UUID_SIZE || sz<4 || !validate16(blob_buffer(pName), sz) ){
49 Stmt q;
50 Blob uuid;
51
52 db_prepare(&q,
53 "SELECT (SELECT uuid FROM blob WHERE rid=objid)"
54 " FROM tagxref JOIN event ON rid=objid"
55 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%B)"
56 " AND addflag"
57 " AND value IS NULL"
58 " ORDER BY event.mtime DESC",
59 pName
60 );
61 blob_zero(&uuid);
62 if( db_step(&q)==SQLITE_ROW ){
63 db_column_blob(&q, 0, &uuid);
64 }
65 db_finalize(&q);
66 if( blob_size(&uuid)==0 ){
67 fossil_error(iErrPriority, "not a valid object name: %b", pName);
68 blob_reset(&uuid);
69 return 1;
70 }else{
71 blob_reset(pName);
72 *pName = uuid;
73 return 0;
74 }
75 }
76 blob_materialize(pName);
77 canonical16(blob_buffer(pName), sz);
78 if( sz==UUID_SIZE ){
79 rc = db_int(1, "SELECT 0 FROM blob WHERE uuid=%B", pName);
@@ -120,11 +147,11 @@
147 return rid;
148 }
149 }
150 blob_init(&name, zName, -1);
151 if( name_to_uuid(&name, 1) ){
152 fossil_fatal("%s", g.zErrMsg);
153 }
154 rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &name);
155 blob_reset(&name);
156 return rid;
157 }
158
+18
--- src/schema.c
+++ src/schema.c
@@ -156,11 +156,15 @@
156156
@ CREATE TABLE event(
157157
@ type TEXT, -- Type of event
158158
@ mtime DATETIME, -- Date and time when the event occurs
159159
@ objid INTEGER PRIMARY KEY, -- Associated record ID
160160
@ uid INTEGER REFERENCES user, -- User who caused the event
161
+@ bgcolor TEXT, -- Color set by 'bgcolor' property
162
+@ brbgcolor TEXT, -- Color set by 'br-bgcolor' property
163
+@ euser TEXT, -- User set by 'user' property
161164
@ user TEXT, -- Name of the user
165
+@ ecomment TEXT, -- Comment set by 'comment' property
162166
@ comment TEXT -- Comment describing the event
163167
@ );
164168
@ CREATE INDEX event_i1 ON event(mtime);
165169
@
166170
@ -- A record of phantoms. A phantom is a record for which we know the
@@ -199,10 +203,14 @@
199203
@ --
200204
@ CREATE TABLE tag(
201205
@ tagid INTEGER PRIMARY KEY, -- Numeric tag ID
202206
@ tagname TEXT UNIQUE -- Tag name. Prefixed by 'v' or 'b'
203207
@ );
208
+@ INSERT INTO tag VALUES(1, 'bgcolor'); -- TAG_BGCOLOR
209
+@ INSERT INTO tag VALUES(2, 'br-bgcolor'); -- TAG_BR_BGCOLOR
210
+@ INSERT INTO tag VALUES(3, 'comment'); -- TAG_COMMENT
211
+@ INSERT INTO tag VALUES(4, 'user'); -- TAG_USER
204212
@
205213
@ -- Assignments of tags to baselines. Note that we allow tags to
206214
@ -- have values assigned to them. So we are not really dealing with
207215
@ -- tags here. These are really properties. But we are going to
208216
@ -- keep calling them tags because in many cases the value is ignored.
@@ -217,10 +225,20 @@
217225
@ UNIQUE(rid, tagid)
218226
@ );
219227
@ CREATE INDEX tagxref_i1 ON tagxref(tagid);
220228
;
221229
230
+/*
231
+** Predefined tagid values
232
+*/
233
+#if INTERFACE
234
+# define TAG_BGCOLOR 1
235
+# define TAG_BR_BGCOLOR 2
236
+# define TAG_COMMENT 3
237
+# define TAG_USER 4
238
+#endif
239
+
222240
/*
223241
** The schema for the locate FOSSIL database file found at the root
224242
** of very check-out. This database contains the complete state of
225243
** the checkout.
226244
*/
227245
--- src/schema.c
+++ src/schema.c
@@ -156,11 +156,15 @@
156 @ CREATE TABLE event(
157 @ type TEXT, -- Type of event
158 @ mtime DATETIME, -- Date and time when the event occurs
159 @ objid INTEGER PRIMARY KEY, -- Associated record ID
160 @ uid INTEGER REFERENCES user, -- User who caused the event
 
 
 
161 @ user TEXT, -- Name of the user
 
162 @ comment TEXT -- Comment describing the event
163 @ );
164 @ CREATE INDEX event_i1 ON event(mtime);
165 @
166 @ -- A record of phantoms. A phantom is a record for which we know the
@@ -199,10 +203,14 @@
199 @ --
200 @ CREATE TABLE tag(
201 @ tagid INTEGER PRIMARY KEY, -- Numeric tag ID
202 @ tagname TEXT UNIQUE -- Tag name. Prefixed by 'v' or 'b'
203 @ );
 
 
 
 
204 @
205 @ -- Assignments of tags to baselines. Note that we allow tags to
206 @ -- have values assigned to them. So we are not really dealing with
207 @ -- tags here. These are really properties. But we are going to
208 @ -- keep calling them tags because in many cases the value is ignored.
@@ -217,10 +225,20 @@
217 @ UNIQUE(rid, tagid)
218 @ );
219 @ CREATE INDEX tagxref_i1 ON tagxref(tagid);
220 ;
221
 
 
 
 
 
 
 
 
 
 
222 /*
223 ** The schema for the locate FOSSIL database file found at the root
224 ** of very check-out. This database contains the complete state of
225 ** the checkout.
226 */
227
--- src/schema.c
+++ src/schema.c
@@ -156,11 +156,15 @@
156 @ CREATE TABLE event(
157 @ type TEXT, -- Type of event
158 @ mtime DATETIME, -- Date and time when the event occurs
159 @ objid INTEGER PRIMARY KEY, -- Associated record ID
160 @ uid INTEGER REFERENCES user, -- User who caused the event
161 @ bgcolor TEXT, -- Color set by 'bgcolor' property
162 @ brbgcolor TEXT, -- Color set by 'br-bgcolor' property
163 @ euser TEXT, -- User set by 'user' property
164 @ user TEXT, -- Name of the user
165 @ ecomment TEXT, -- Comment set by 'comment' property
166 @ comment TEXT -- Comment describing the event
167 @ );
168 @ CREATE INDEX event_i1 ON event(mtime);
169 @
170 @ -- A record of phantoms. A phantom is a record for which we know the
@@ -199,10 +203,14 @@
203 @ --
204 @ CREATE TABLE tag(
205 @ tagid INTEGER PRIMARY KEY, -- Numeric tag ID
206 @ tagname TEXT UNIQUE -- Tag name. Prefixed by 'v' or 'b'
207 @ );
208 @ INSERT INTO tag VALUES(1, 'bgcolor'); -- TAG_BGCOLOR
209 @ INSERT INTO tag VALUES(2, 'br-bgcolor'); -- TAG_BR_BGCOLOR
210 @ INSERT INTO tag VALUES(3, 'comment'); -- TAG_COMMENT
211 @ INSERT INTO tag VALUES(4, 'user'); -- TAG_USER
212 @
213 @ -- Assignments of tags to baselines. Note that we allow tags to
214 @ -- have values assigned to them. So we are not really dealing with
215 @ -- tags here. These are really properties. But we are going to
216 @ -- keep calling them tags because in many cases the value is ignored.
@@ -217,10 +225,20 @@
225 @ UNIQUE(rid, tagid)
226 @ );
227 @ CREATE INDEX tagxref_i1 ON tagxref(tagid);
228 ;
229
230 /*
231 ** Predefined tagid values
232 */
233 #if INTERFACE
234 # define TAG_BGCOLOR 1
235 # define TAG_BR_BGCOLOR 2
236 # define TAG_COMMENT 3
237 # define TAG_USER 4
238 #endif
239
240 /*
241 ** The schema for the locate FOSSIL database file found at the root
242 ** of very check-out. This database contains the complete state of
243 ** the checkout.
244 */
245
+196 -2
--- src/tag.c
+++ src/tag.c
@@ -42,11 +42,11 @@
4242
int addFlag, /* True to add the tag. False to delete it. */
4343
const char *zValue, /* Value of the tag. Might be NULL */
4444
double mtime /* Timestamp on the tag */
4545
){
4646
PQueue queue;
47
- Stmt s, ins;
47
+ Stmt s, ins, eventupdate;
4848
pqueue_init(&queue);
4949
pqueue_insert(&queue, pid, 0.0);
5050
db_prepare(&s,
5151
"SELECT cid, plink.mtime,"
5252
" coalesce(srcid=0 AND tagxref.mtime<:mtime, %d) AS doit"
@@ -61,13 +61,19 @@
6161
"VALUES(%d,1,0,%Q,:mtime,:rid)",
6262
tagid, zValue
6363
);
6464
db_bind_double(&ins, ":mtime", mtime);
6565
}else{
66
+ zValue = 0;
6667
db_prepare(&ins,
6768
"DELETE FROM tagxref WHERE tagid=%d AND rid=:rid", tagid
6869
);
70
+ }
71
+ if( tagid==TAG_BR_BGCOLOR ){
72
+ db_prepare(&eventupdate,
73
+ "UPDATE event SET brbgcolor=%Q WHERE objid=:rid", zValue
74
+ );
6975
}
7076
while( (pid = pqueue_extract(&queue))!=0 ){
7177
db_bind_int(&s, ":pid", pid);
7278
while( db_step(&s)==SQLITE_ROW ){
7379
int doit = db_column_int(&s, 2);
@@ -76,17 +82,25 @@
7682
double mtime = db_column_double(&s, 1);
7783
pqueue_insert(&queue, cid, mtime);
7884
db_bind_int(&ins, ":rid", cid);
7985
db_step(&ins);
8086
db_reset(&ins);
87
+ if( tagid==TAG_BR_BGCOLOR ){
88
+ db_bind_int(&eventupdate, ":rid", cid);
89
+ db_step(&eventupdate);
90
+ db_reset(&eventupdate);
91
+ }
8192
}
8293
}
8394
db_reset(&s);
8495
}
8596
pqueue_clear(&queue);
8697
db_finalize(&ins);
8798
db_finalize(&s);
99
+ if( tagid==TAG_BR_BGCOLOR ){
100
+ db_finalize(&eventupdate);
101
+ }
88102
}
89103
90104
/*
91105
** Propagate all propagatable tags in pid to its children.
92106
*/
@@ -144,12 +158,33 @@
144158
tagid, addFlag, srcId, zValue, rid
145159
);
146160
db_bind_double(&s, ":mtime", mtime);
147161
db_step(&s);
148162
db_finalize(&s);
163
+ if( addFlag==0 ){
164
+ zValue = 0;
165
+ }
166
+ switch( tagid ){
167
+ case TAG_BGCOLOR: {
168
+ db_multi_exec("UPDATE event SET bgcolor=%Q WHERE objid=%d", zValue, rid);
169
+ break;
170
+ }
171
+ case TAG_BR_BGCOLOR: {
172
+ db_multi_exec("UPDATE event SET brbgcolor=%Q WHERE objid=%d", zValue,rid);
173
+ break;
174
+ }
175
+ case TAG_COMMENT: {
176
+ db_multi_exec("UPDATE event SET ecomment=%Q WHERE objid=%d", zValue, rid);
177
+ break;
178
+ }
179
+ case TAG_USER: {
180
+ db_multi_exec("UPDATE event SET euser=%Q WHERE objid=%d", zValue, rid);
181
+ break;
182
+ }
183
+ }
149184
if( strncmp(zTag, "br", 2)==0 ){
150
- tag_propagate(rid, tagid, 1, zValue, mtime);
185
+ tag_propagate(rid, tagid, addFlag, zValue, mtime);
151186
}
152187
}
153188
154189
155190
/*
@@ -202,5 +237,164 @@
202237
}
203238
db_begin_transaction();
204239
tag_insert(zTag, 0, 0, -1, 0.0, rid);
205240
db_end_transaction(0);
206241
}
242
+
243
+/*
244
+** Add a control record to the repository that either creates
245
+** or cancels a tag.
246
+*/
247
+static void tag_add_artifact(
248
+ const char *zTagname, /* The tag to add or cancel */
249
+ const char *zObjName, /* Name of object attached to */
250
+ const char *zValue, /* Value for the tag. Might be NULL */
251
+ int addFlag /* True to add. false to cancel */
252
+){
253
+ int rid;
254
+ int nrid;
255
+ char *zDate;
256
+ Blob uuid;
257
+ Blob ctrl;
258
+ Blob cksum;
259
+
260
+ user_select();
261
+ rid = name_to_rid(zObjName);
262
+ blob_zero(&uuid);
263
+ db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d", rid);
264
+ blob_zero(&ctrl);
265
+
266
+ if( validate16(zTagname, strlen(zTagname)) ){
267
+ fossil_fatal("invalid tag name \"%s\" - might be confused with a UUID",
268
+ zTagname);
269
+ }
270
+ zDate = db_text(0, "SELECT datetime('now')");
271
+ zDate[10] = 'T';
272
+ blob_appendf(&ctrl, "D %s\n", zDate);
273
+ blob_appendf(&ctrl, "T %c%F %b", addFlag ? '+' : '-', zTagname, &uuid);
274
+ if( addFlag && zValue && zValue[0] ){
275
+ blob_appendf(&ctrl, " %F\n", zValue);
276
+ }else{
277
+ blob_appendf(&ctrl, "\n");
278
+ }
279
+ blob_appendf(&ctrl, "U %F\n", g.zLogin);
280
+ md5sum_blob(&ctrl, &cksum);
281
+ blob_appendf(&ctrl, "Z %b\n", &cksum);
282
+ db_begin_transaction();
283
+ nrid = content_put(&ctrl, 0, 0);
284
+ manifest_crosslink(nrid, &ctrl);
285
+ db_end_transaction(0);
286
+}
287
+
288
+/*
289
+** COMMAND: tag
290
+** Usage: %fossil tag SUBCOMMAND ...
291
+**
292
+** Run various subcommands to control tags and properties
293
+**
294
+** %fossil tag add TAGNAME UUID ?VALUE?
295
+**
296
+** Add a new tag or property to UUID.
297
+**
298
+** %fossil tag delete TAGNAME UUID
299
+**
300
+** Delete the tag TAGNAME from UUID
301
+**
302
+** %fossil tag find TAGNAME
303
+**
304
+** List all baselines that use TAGNAME
305
+**
306
+** %fossil tag list ?UUID?
307
+**
308
+** List all tags, or if UUID is supplied, list
309
+** all tags and their values for UUID.
310
+*/
311
+void tag_cmd(void){
312
+ int n;
313
+ db_find_and_open_repository();
314
+ if( g.argc<3 ){
315
+ goto tag_cmd_usage;
316
+ }
317
+ n = strlen(g.argv[2]);
318
+ if( n==0 ){
319
+ goto tag_cmd_usage;
320
+ }
321
+
322
+ if( strncmp(g.argv[2],"add",n)==0 ){
323
+ char *zValue;
324
+ if( g.argc!=5 && g.argc!=6 ){
325
+ usage("tag add TAGNAME UUID ?VALUE?");
326
+ }
327
+ zValue = g.argc==6 ? g.argv[5] : 0;
328
+ tag_add_artifact(g.argv[3], g.argv[4], zValue, 1);
329
+ }else
330
+
331
+ if( strncmp(g.argv[2],"delete",n)==0 ){
332
+ if( g.argc!=5 ){
333
+ usage("tag delete TAGNAME UUID");
334
+ }
335
+ tag_add_artifact(g.argv[3], g.argv[4], 0, 0);
336
+ }else
337
+
338
+ if( strncmp(g.argv[2],"find",n)==0 ){
339
+ Stmt q;
340
+ if( g.argc!=4 ){
341
+ usage("tag find TAGNAME");
342
+ }
343
+ db_prepare(&q,
344
+ "SELECT blob.uuid FROM tagxref, blob"
345
+ " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
346
+ " AND blob.rid=tagxref.rid", g.argv[3]
347
+ );
348
+ while( db_step(&q)==SQLITE_ROW ){
349
+ printf("%s\n", db_column_text(&q, 0));
350
+ }
351
+ db_finalize(&q);
352
+ }else
353
+
354
+ if( strncmp(g.argv[2],"list",n)==0 ){
355
+ Stmt q;
356
+ if( g.argc==3 ){
357
+ db_prepare(&q,
358
+ "SELECT tagname"
359
+ " FROM tag"
360
+ " WHERE EXISTS(SELECT 1 FROM tagxref"
361
+ " WHERE tagid=tag.tagid"
362
+ " AND addflag)"
363
+ " ORDER BY tagname"
364
+ );
365
+ while( db_step(&q)==SQLITE_ROW ){
366
+ printf("%s\n", db_column_text(&q, 0));
367
+ }
368
+ db_finalize(&q);
369
+ }else if( g.argc==4 ){
370
+ int rid = name_to_rid(g.argv[3]);
371
+ db_prepare(&q,
372
+ "SELECT tagname, value"
373
+ " FROM tagxref, tag"
374
+ " WHERE tagxref.rid=%d AND tagxref.tagid=tag.tagid"
375
+ " AND addflag"
376
+ " ORDER BY tagname",
377
+ rid
378
+ );
379
+ while( db_step(&q)==SQLITE_ROW ){
380
+ const char *zName = db_column_text(&q, 0);
381
+ const char *zValue = db_column_text(&q, 1);
382
+ if( zValue ){
383
+ printf("%s=%s\n", zName, zValue);
384
+ }else{
385
+ printf("%s\n", zName);
386
+ }
387
+ }
388
+ db_finalize(&q);
389
+ }else{
390
+ usage("tag list ?UUID?");
391
+ }
392
+ }else
393
+ {
394
+ goto tag_cmd_usage;
395
+ }
396
+ return;
397
+
398
+tag_cmd_usage:
399
+ usage("add|delete|find|list ...");
400
+}
207401
--- src/tag.c
+++ src/tag.c
@@ -42,11 +42,11 @@
42 int addFlag, /* True to add the tag. False to delete it. */
43 const char *zValue, /* Value of the tag. Might be NULL */
44 double mtime /* Timestamp on the tag */
45 ){
46 PQueue queue;
47 Stmt s, ins;
48 pqueue_init(&queue);
49 pqueue_insert(&queue, pid, 0.0);
50 db_prepare(&s,
51 "SELECT cid, plink.mtime,"
52 " coalesce(srcid=0 AND tagxref.mtime<:mtime, %d) AS doit"
@@ -61,13 +61,19 @@
61 "VALUES(%d,1,0,%Q,:mtime,:rid)",
62 tagid, zValue
63 );
64 db_bind_double(&ins, ":mtime", mtime);
65 }else{
 
66 db_prepare(&ins,
67 "DELETE FROM tagxref WHERE tagid=%d AND rid=:rid", tagid
68 );
 
 
 
 
 
69 }
70 while( (pid = pqueue_extract(&queue))!=0 ){
71 db_bind_int(&s, ":pid", pid);
72 while( db_step(&s)==SQLITE_ROW ){
73 int doit = db_column_int(&s, 2);
@@ -76,17 +82,25 @@
76 double mtime = db_column_double(&s, 1);
77 pqueue_insert(&queue, cid, mtime);
78 db_bind_int(&ins, ":rid", cid);
79 db_step(&ins);
80 db_reset(&ins);
 
 
 
 
 
81 }
82 }
83 db_reset(&s);
84 }
85 pqueue_clear(&queue);
86 db_finalize(&ins);
87 db_finalize(&s);
 
 
 
88 }
89
90 /*
91 ** Propagate all propagatable tags in pid to its children.
92 */
@@ -144,12 +158,33 @@
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 /*
@@ -202,5 +237,164 @@
202 }
203 db_begin_transaction();
204 tag_insert(zTag, 0, 0, -1, 0.0, rid);
205 db_end_transaction(0);
206 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
207
--- src/tag.c
+++ src/tag.c
@@ -42,11 +42,11 @@
42 int addFlag, /* True to add the tag. False to delete it. */
43 const char *zValue, /* Value of the tag. Might be NULL */
44 double mtime /* Timestamp on the tag */
45 ){
46 PQueue queue;
47 Stmt s, ins, eventupdate;
48 pqueue_init(&queue);
49 pqueue_insert(&queue, pid, 0.0);
50 db_prepare(&s,
51 "SELECT cid, plink.mtime,"
52 " coalesce(srcid=0 AND tagxref.mtime<:mtime, %d) AS doit"
@@ -61,13 +61,19 @@
61 "VALUES(%d,1,0,%Q,:mtime,:rid)",
62 tagid, zValue
63 );
64 db_bind_double(&ins, ":mtime", mtime);
65 }else{
66 zValue = 0;
67 db_prepare(&ins,
68 "DELETE FROM tagxref WHERE tagid=%d AND rid=:rid", tagid
69 );
70 }
71 if( tagid==TAG_BR_BGCOLOR ){
72 db_prepare(&eventupdate,
73 "UPDATE event SET brbgcolor=%Q WHERE objid=:rid", zValue
74 );
75 }
76 while( (pid = pqueue_extract(&queue))!=0 ){
77 db_bind_int(&s, ":pid", pid);
78 while( db_step(&s)==SQLITE_ROW ){
79 int doit = db_column_int(&s, 2);
@@ -76,17 +82,25 @@
82 double mtime = db_column_double(&s, 1);
83 pqueue_insert(&queue, cid, mtime);
84 db_bind_int(&ins, ":rid", cid);
85 db_step(&ins);
86 db_reset(&ins);
87 if( tagid==TAG_BR_BGCOLOR ){
88 db_bind_int(&eventupdate, ":rid", cid);
89 db_step(&eventupdate);
90 db_reset(&eventupdate);
91 }
92 }
93 }
94 db_reset(&s);
95 }
96 pqueue_clear(&queue);
97 db_finalize(&ins);
98 db_finalize(&s);
99 if( tagid==TAG_BR_BGCOLOR ){
100 db_finalize(&eventupdate);
101 }
102 }
103
104 /*
105 ** Propagate all propagatable tags in pid to its children.
106 */
@@ -144,12 +158,33 @@
158 tagid, addFlag, srcId, zValue, rid
159 );
160 db_bind_double(&s, ":mtime", mtime);
161 db_step(&s);
162 db_finalize(&s);
163 if( addFlag==0 ){
164 zValue = 0;
165 }
166 switch( tagid ){
167 case TAG_BGCOLOR: {
168 db_multi_exec("UPDATE event SET bgcolor=%Q WHERE objid=%d", zValue, rid);
169 break;
170 }
171 case TAG_BR_BGCOLOR: {
172 db_multi_exec("UPDATE event SET brbgcolor=%Q WHERE objid=%d", zValue,rid);
173 break;
174 }
175 case TAG_COMMENT: {
176 db_multi_exec("UPDATE event SET ecomment=%Q WHERE objid=%d", zValue, rid);
177 break;
178 }
179 case TAG_USER: {
180 db_multi_exec("UPDATE event SET euser=%Q WHERE objid=%d", zValue, rid);
181 break;
182 }
183 }
184 if( strncmp(zTag, "br", 2)==0 ){
185 tag_propagate(rid, tagid, addFlag, zValue, mtime);
186 }
187 }
188
189
190 /*
@@ -202,5 +237,164 @@
237 }
238 db_begin_transaction();
239 tag_insert(zTag, 0, 0, -1, 0.0, rid);
240 db_end_transaction(0);
241 }
242
243 /*
244 ** Add a control record to the repository that either creates
245 ** or cancels a tag.
246 */
247 static void tag_add_artifact(
248 const char *zTagname, /* The tag to add or cancel */
249 const char *zObjName, /* Name of object attached to */
250 const char *zValue, /* Value for the tag. Might be NULL */
251 int addFlag /* True to add. false to cancel */
252 ){
253 int rid;
254 int nrid;
255 char *zDate;
256 Blob uuid;
257 Blob ctrl;
258 Blob cksum;
259
260 user_select();
261 rid = name_to_rid(zObjName);
262 blob_zero(&uuid);
263 db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d", rid);
264 blob_zero(&ctrl);
265
266 if( validate16(zTagname, strlen(zTagname)) ){
267 fossil_fatal("invalid tag name \"%s\" - might be confused with a UUID",
268 zTagname);
269 }
270 zDate = db_text(0, "SELECT datetime('now')");
271 zDate[10] = 'T';
272 blob_appendf(&ctrl, "D %s\n", zDate);
273 blob_appendf(&ctrl, "T %c%F %b", addFlag ? '+' : '-', zTagname, &uuid);
274 if( addFlag && zValue && zValue[0] ){
275 blob_appendf(&ctrl, " %F\n", zValue);
276 }else{
277 blob_appendf(&ctrl, "\n");
278 }
279 blob_appendf(&ctrl, "U %F\n", g.zLogin);
280 md5sum_blob(&ctrl, &cksum);
281 blob_appendf(&ctrl, "Z %b\n", &cksum);
282 db_begin_transaction();
283 nrid = content_put(&ctrl, 0, 0);
284 manifest_crosslink(nrid, &ctrl);
285 db_end_transaction(0);
286 }
287
288 /*
289 ** COMMAND: tag
290 ** Usage: %fossil tag SUBCOMMAND ...
291 **
292 ** Run various subcommands to control tags and properties
293 **
294 ** %fossil tag add TAGNAME UUID ?VALUE?
295 **
296 ** Add a new tag or property to UUID.
297 **
298 ** %fossil tag delete TAGNAME UUID
299 **
300 ** Delete the tag TAGNAME from UUID
301 **
302 ** %fossil tag find TAGNAME
303 **
304 ** List all baselines that use TAGNAME
305 **
306 ** %fossil tag list ?UUID?
307 **
308 ** List all tags, or if UUID is supplied, list
309 ** all tags and their values for UUID.
310 */
311 void tag_cmd(void){
312 int n;
313 db_find_and_open_repository();
314 if( g.argc<3 ){
315 goto tag_cmd_usage;
316 }
317 n = strlen(g.argv[2]);
318 if( n==0 ){
319 goto tag_cmd_usage;
320 }
321
322 if( strncmp(g.argv[2],"add",n)==0 ){
323 char *zValue;
324 if( g.argc!=5 && g.argc!=6 ){
325 usage("tag add TAGNAME UUID ?VALUE?");
326 }
327 zValue = g.argc==6 ? g.argv[5] : 0;
328 tag_add_artifact(g.argv[3], g.argv[4], zValue, 1);
329 }else
330
331 if( strncmp(g.argv[2],"delete",n)==0 ){
332 if( g.argc!=5 ){
333 usage("tag delete TAGNAME UUID");
334 }
335 tag_add_artifact(g.argv[3], g.argv[4], 0, 0);
336 }else
337
338 if( strncmp(g.argv[2],"find",n)==0 ){
339 Stmt q;
340 if( g.argc!=4 ){
341 usage("tag find TAGNAME");
342 }
343 db_prepare(&q,
344 "SELECT blob.uuid FROM tagxref, blob"
345 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
346 " AND blob.rid=tagxref.rid", g.argv[3]
347 );
348 while( db_step(&q)==SQLITE_ROW ){
349 printf("%s\n", db_column_text(&q, 0));
350 }
351 db_finalize(&q);
352 }else
353
354 if( strncmp(g.argv[2],"list",n)==0 ){
355 Stmt q;
356 if( g.argc==3 ){
357 db_prepare(&q,
358 "SELECT tagname"
359 " FROM tag"
360 " WHERE EXISTS(SELECT 1 FROM tagxref"
361 " WHERE tagid=tag.tagid"
362 " AND addflag)"
363 " ORDER BY tagname"
364 );
365 while( db_step(&q)==SQLITE_ROW ){
366 printf("%s\n", db_column_text(&q, 0));
367 }
368 db_finalize(&q);
369 }else if( g.argc==4 ){
370 int rid = name_to_rid(g.argv[3]);
371 db_prepare(&q,
372 "SELECT tagname, value"
373 " FROM tagxref, tag"
374 " WHERE tagxref.rid=%d AND tagxref.tagid=tag.tagid"
375 " AND addflag"
376 " ORDER BY tagname",
377 rid
378 );
379 while( db_step(&q)==SQLITE_ROW ){
380 const char *zName = db_column_text(&q, 0);
381 const char *zValue = db_column_text(&q, 1);
382 if( zValue ){
383 printf("%s=%s\n", zName, zValue);
384 }else{
385 printf("%s\n", zName);
386 }
387 }
388 db_finalize(&q);
389 }else{
390 usage("tag list ?UUID?");
391 }
392 }else
393 {
394 goto tag_cmd_usage;
395 }
396 return;
397
398 tag_cmd_usage:
399 usage("add|delete|find|list ...");
400 }
401
+4 -25
--- src/timeline.c
+++ src/timeline.c
@@ -198,28 +198,16 @@
198198
static const char zBaseSql[] =
199199
@ SELECT
200200
@ blob.rid,
201201
@ uuid,
202202
@ 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),
203
+ @ coalesce(ecomment, comment),
204
+ @ coalesce(euser, user),
211205
@ (SELECT count(*) FROM plink WHERE pid=blob.rid AND isprim=1),
212206
@ (SELECT count(*) FROM plink WHERE cid=blob.rid),
213207
@ 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'))
208
+ @ coalesce(bgcolor, brbgcolor)
221209
@ FROM event JOIN blob
222210
@ WHERE blob.rid=event.objid
223211
;
224212
return zBaseSql;
225213
}
@@ -450,20 +438,11 @@
450438
static const char zBaseSql[] =
451439
@ SELECT
452440
@ blob.rid,
453441
@ uuid,
454442
@ 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
- @ || ')',
443
+ @ coalesce(ecomment,comment) || ' (by ' || coalesce(euser,user) || ')',
465444
@ (SELECT count(*) FROM plink WHERE pid=blob.rid AND isprim),
466445
@ (SELECT count(*) FROM plink WHERE cid=blob.rid)
467446
@ FROM event, blob
468447
@ WHERE blob.rid=event.objid
469448
;
470449
--- src/timeline.c
+++ src/timeline.c
@@ -198,28 +198,16 @@
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 }
@@ -450,20 +438,11 @@
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
--- src/timeline.c
+++ src/timeline.c
@@ -198,28 +198,16 @@
198 static const char zBaseSql[] =
199 @ SELECT
200 @ blob.rid,
201 @ uuid,
202 @ datetime(event.mtime,'localtime'),
203 @ coalesce(ecomment, comment),
204 @ coalesce(euser, user),
 
 
 
 
 
 
205 @ (SELECT count(*) FROM plink WHERE pid=blob.rid AND isprim=1),
206 @ (SELECT count(*) FROM plink WHERE cid=blob.rid),
207 @ NOT EXISTS (SELECT 1 FROM plink WHERE pid=blob.rid),
208 @ coalesce(bgcolor, brbgcolor)
 
 
 
 
 
 
209 @ FROM event JOIN blob
210 @ WHERE blob.rid=event.objid
211 ;
212 return zBaseSql;
213 }
@@ -450,20 +438,11 @@
438 static const char zBaseSql[] =
439 @ SELECT
440 @ blob.rid,
441 @ uuid,
442 @ datetime(event.mtime,'localtime'),
443 @ coalesce(ecomment,comment) || ' (by ' || coalesce(euser,user) || ')',
 
 
 
 
 
 
 
 
 
444 @ (SELECT count(*) FROM plink WHERE pid=blob.rid AND isprim),
445 @ (SELECT count(*) FROM plink WHERE cid=blob.rid)
446 @ FROM event, blob
447 @ WHERE blob.rid=event.objid
448 ;
449

Keyboard Shortcuts

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