Fossil SCM

TH1 fossiltag command for accessing tag values. Has two subcommands: get and list, which do what they sound like.

bcsmith 2010-10-21 23:26 trunk
Commit 413ebeb12e24c09038f1aa188646d9dc51e00ba9
1 file changed +213 -1
+213 -1
--- src/th_main.c
+++ src/th_main.c
@@ -233,10 +233,209 @@
233233
Th_Trace("[hascap %.*h] => %d<br />\n", argl[1], argv[1], rc);
234234
}
235235
Th_SetResultInt(interp, rc);
236236
return TH_OK;
237237
}
238
+
239
+/*
240
+**
241
+** TH1 command: fossiltag list ?ARTIFACT-ID?
242
+**
243
+** Returns a list of tags on ARTIFACT-ID. Or, all tags,
244
+** if ARTIFACT-ID is not specified. Only uncancelled tags
245
+** are included in the result.
246
+**
247
+** Example:
248
+** <b>List of tags on thing:</b>
249
+** <th1>
250
+** puts [fossiltag list 2b4630f34]
251
+** </th1>
252
+*/
253
+static int fossiltagListCmd(
254
+ Th_Interp *interp,
255
+ void *p,
256
+ int argc,
257
+ const char **argv,
258
+ int *argl
259
+){
260
+ Stmt st;
261
+ char *zTagList = 0;
262
+ int nTagList = 0;
263
+ if( argc==3 ){
264
+ db_prepare(&st,
265
+ "SELECT tag.tagname FROM tag, tagxref "
266
+ " WHERE tagxref.rid=%d "
267
+ " AND tagxref.tagid=tag.tagid"
268
+ " AND tagxref.tagtype>0 ",
269
+ name_to_rid((char*)argv[2])
270
+ );
271
+ }
272
+ else {
273
+ db_prepare(&st,
274
+ "SELECT DISTINCT tag.tagname FROM tag, tagxref "
275
+ " WHERE "
276
+ " tagxref.tagid=tag.tagid"
277
+ " AND tagxref.tagtype>0 "
278
+ );
279
+ }
280
+ while( db_step(&st) == SQLITE_ROW ){
281
+ char *tagname = (char*)db_column_text(&st, 0);
282
+ Th_ListAppend(interp, &zTagList, &nTagList, tagname, -1);
283
+
284
+ }
285
+
286
+ Th_SetResult(interp, zTagList, nTagList);
287
+ Th_Free(interp, zTagList);
288
+ db_finalize(&st);
289
+ return TH_OK;
290
+}
291
+
292
+/*
293
+**
294
+** TH1 command: fossiltag get TAG-NAME ?ARTIFACT-ID? ?FALLBACK-VALUE?
295
+**
296
+** Returns the value of TAG-NAME on ARTIFACT-ID, or
297
+** one of the following:
298
+** if FALLBACK-VALUE provided and TAG-NAME not present,
299
+** then FALLBACK-VALUE is returned.
300
+** if FALLBACK-VALUE not provided, and TAG-NAME not present,
301
+** then 0 returned.
302
+** if TAG-NAME present, but has no value, then 1 is returned.
303
+**
304
+** Example:
305
+** <b>Check-in acceptance status:</b>
306
+** <th1>
307
+** set accept_out ""
308
+** if {[set out [fossiltag get "QA_acceptance" $check_in_id "<b>DID NOT PASS</b>"]]} {
309
+** set accept_out " * QA: ${out}"
310
+** }
311
+** if {[set out [fossiltag get "Unit_passed" $check_in_id "<b>DID NOT PASS UNIT TESTS</b>"]]} {
312
+** set accept_out "${accept_out}\n * Unit tests: ${out}"
313
+** }
314
+** if {[set out [fossiltag get "Signed_off_by" $check_in_id "<b>NOT SIGNED OFF</b>"]]} {
315
+** set accept_out "${accept_out}\n * Signed off by: ${out}"
316
+** }
317
+** puts [wiki $accept_out]
318
+** </th1>
319
+*/
320
+static int fossiltagGetCmd(
321
+ Th_Interp *interp,
322
+ void *p,
323
+ int argc,
324
+ const char **argv,
325
+ int *argl
326
+){
327
+ int rid = -1;
328
+ char *zTagValue = 0;
329
+ char *zDefault = 0;
330
+ int nDefault = 0;
331
+ db_open_local();
332
+ db_open_repository(0);
333
+ if( argc<3 ){
334
+ return Th_WrongNumArgs(interp, "fossiltag get TAG-NAME ?ARTIFACT-ID? ?FALLBACK-TEXT?");
335
+ }
336
+ /* if a fallback value was provided, place it in zDefault */
337
+ if( argc==5 ){
338
+ zDefault = (char*)argv[4];
339
+ nDefault = argl[4];
340
+ }
341
+ /* if an artifact-id (name) is given.. */
342
+ if( argc>=4 && strlen((char*)argv[3])){
343
+ rid =
344
+ db_int(0,
345
+ "SELECT blob.rid "
346
+ " FROM tag, tagxref, blob "
347
+ "WHERE tag.tagname=%Q AND blob.rid=%d"
348
+ " AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 "
349
+ " AND blob.rid=tagxref.rid ",
350
+ argv[2], name_to_rid((char*)argv[3])
351
+ );
352
+
353
+ if( g.thTrace ){
354
+ Th_Trace("[tagget] artifact-id: %s %d\n", argv[3], rid);
355
+ }
356
+ }
357
+ else { /* if no artifact-id is given, we select the most recent commit
358
+ containing TAG-NAME */
359
+ rid =
360
+ db_int(0,
361
+ "SELECT blob.rid "
362
+ " FROM tag, tagxref, event, blob "
363
+ "WHERE tag.tagname=%Q "
364
+ " AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 "
365
+ " AND event.objid=tagxref.rid "
366
+ " AND blob.rid=event.objid "
367
+ "ORDER BY event.mtime DESC ",
368
+ argv[2]
369
+ );
370
+ if( g.thTrace ){
371
+ Th_Trace("[tagget] artifact-rid: %d\n", rid);
372
+ }
373
+ }
374
+
375
+ /* return 0 or the fallback value, since we couldn't
376
+ find an artifact with TAG-NAME on it. */
377
+ if( rid==0 && argc==5 ){
378
+ if( g.thTrace ){
379
+ Th_Trace("[tagget] tag not on any artifact; returning default: %s\n", zDefault);
380
+ }
381
+ Th_SetResult(interp, zDefault, nDefault);
382
+ return TH_OK;
383
+ }
384
+ else if( rid==0 && argc<5 ){
385
+ if( g.thTrace ){
386
+ Th_Trace("[tagget] tag not on any artifact; ret: 0\n");
387
+ }
388
+ Th_SetResultInt(interp, 0);
389
+ return TH_OK;
390
+ }
391
+
392
+ zTagValue = db_text(zDefault,
393
+ "SELECT tagxref.value FROM tag, tagxref "
394
+ " WHERE tag.tagname=%Q "
395
+ " AND tagxref.tagid=tag.tagid "
396
+ " AND tagxref.rid=%d ",
397
+ argv[2], rid
398
+ );
399
+ if( zTagValue && strlen(zTagValue)==0 ){
400
+ if( g.thTrace ){
401
+ Th_Trace("[tagget] tag has no value; ret: 1\n");
402
+ }
403
+ Th_SetResultInt(interp, 1);
404
+ free(zTagValue);
405
+ }
406
+ else {
407
+ if( g.thTrace ){
408
+ Th_Trace("[tagget] returning tag value: %s\n", zTagValue);
409
+ }
410
+ Th_SetResult(interp, zTagValue, -1);
411
+ free(zTagValue);
412
+ }
413
+ return TH_OK;
414
+}
415
+
416
+/*
417
+** TH1 command: fossiltag list|get ...
418
+**
419
+** Provide TH1 commands for read-only interation with tags on
420
+** any taggable artifact. The tags are always raw.
421
+**
422
+*/
423
+static int fossiltagCmd(
424
+ Th_Interp *interp,
425
+ void *p,
426
+ int argc,
427
+ const char **argv,
428
+ int *argl
429
+){
430
+ Th_SubCommand aSub[] = {
431
+ { "list", fossiltagListCmd },
432
+ { "get", fossiltagGetCmd },
433
+ { 0, 0 }
434
+ };
435
+ return Th_CallSubCommand(interp, p, argc, argv, argl, aSub);
436
+}
238437
239438
/*
240439
** TH1 command: combobox NAME TEXT-LIST NUMLINES
241440
**
242441
** Generate an HTML combobox. NAME is both the name of the
@@ -350,10 +549,11 @@
350549
{"htmlize", htmlizeCmd, 0},
351550
{"date", dateCmd, 0},
352551
{"html", putsCmd, 0},
353552
{"puts", putsCmd, (void*)1},
354553
{"wiki", wikiCmd, 0},
554
+ {"fossiltag", fossiltagCmd, 0},
355555
};
356556
if( g.interp==0 ){
357557
int i;
358558
g.interp = Th_CreateInterp(&vtab);
359559
th_register_language(g.interp); /* Basic scripting commands. */
@@ -519,12 +719,24 @@
519719
/*
520720
** COMMAND: test-th-render
521721
*/
522722
void test_th_render(void){
523723
Blob in;
724
+ g.thTrace = find_option("th-trace", 0, 0)!=0;
725
+ if( g.thTrace ){
726
+ blob_zero(&g.thLog);
727
+ }
524728
if( g.argc<3 ){
525729
usage("FILE");
526730
}
527731
blob_zero(&in);
528
- blob_read_from_file(&in, g.argv[2]);
732
+ if( g.thTrace ){
733
+ blob_read_from_file(&in, g.argv[3]);
734
+ }
735
+ else{
736
+ blob_read_from_file(&in, g.argv[2]);
737
+ }
529738
Th_Render(blob_str(&in));
739
+ if( g.thTrace ){
740
+ fossil_print("%s", blob_materialize(&g.thLog));
741
+ }
530742
}
531743
--- src/th_main.c
+++ src/th_main.c
@@ -233,10 +233,209 @@
233 Th_Trace("[hascap %.*h] => %d<br />\n", argl[1], argv[1], rc);
234 }
235 Th_SetResultInt(interp, rc);
236 return TH_OK;
237 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
238
239 /*
240 ** TH1 command: combobox NAME TEXT-LIST NUMLINES
241 **
242 ** Generate an HTML combobox. NAME is both the name of the
@@ -350,10 +549,11 @@
350 {"htmlize", htmlizeCmd, 0},
351 {"date", dateCmd, 0},
352 {"html", putsCmd, 0},
353 {"puts", putsCmd, (void*)1},
354 {"wiki", wikiCmd, 0},
 
355 };
356 if( g.interp==0 ){
357 int i;
358 g.interp = Th_CreateInterp(&vtab);
359 th_register_language(g.interp); /* Basic scripting commands. */
@@ -519,12 +719,24 @@
519 /*
520 ** COMMAND: test-th-render
521 */
522 void test_th_render(void){
523 Blob in;
 
 
 
 
524 if( g.argc<3 ){
525 usage("FILE");
526 }
527 blob_zero(&in);
528 blob_read_from_file(&in, g.argv[2]);
 
 
 
 
 
529 Th_Render(blob_str(&in));
 
 
 
530 }
531
--- src/th_main.c
+++ src/th_main.c
@@ -233,10 +233,209 @@
233 Th_Trace("[hascap %.*h] => %d<br />\n", argl[1], argv[1], rc);
234 }
235 Th_SetResultInt(interp, rc);
236 return TH_OK;
237 }
238
239 /*
240 **
241 ** TH1 command: fossiltag list ?ARTIFACT-ID?
242 **
243 ** Returns a list of tags on ARTIFACT-ID. Or, all tags,
244 ** if ARTIFACT-ID is not specified. Only uncancelled tags
245 ** are included in the result.
246 **
247 ** Example:
248 ** <b>List of tags on thing:</b>
249 ** <th1>
250 ** puts [fossiltag list 2b4630f34]
251 ** </th1>
252 */
253 static int fossiltagListCmd(
254 Th_Interp *interp,
255 void *p,
256 int argc,
257 const char **argv,
258 int *argl
259 ){
260 Stmt st;
261 char *zTagList = 0;
262 int nTagList = 0;
263 if( argc==3 ){
264 db_prepare(&st,
265 "SELECT tag.tagname FROM tag, tagxref "
266 " WHERE tagxref.rid=%d "
267 " AND tagxref.tagid=tag.tagid"
268 " AND tagxref.tagtype>0 ",
269 name_to_rid((char*)argv[2])
270 );
271 }
272 else {
273 db_prepare(&st,
274 "SELECT DISTINCT tag.tagname FROM tag, tagxref "
275 " WHERE "
276 " tagxref.tagid=tag.tagid"
277 " AND tagxref.tagtype>0 "
278 );
279 }
280 while( db_step(&st) == SQLITE_ROW ){
281 char *tagname = (char*)db_column_text(&st, 0);
282 Th_ListAppend(interp, &zTagList, &nTagList, tagname, -1);
283
284 }
285
286 Th_SetResult(interp, zTagList, nTagList);
287 Th_Free(interp, zTagList);
288 db_finalize(&st);
289 return TH_OK;
290 }
291
292 /*
293 **
294 ** TH1 command: fossiltag get TAG-NAME ?ARTIFACT-ID? ?FALLBACK-VALUE?
295 **
296 ** Returns the value of TAG-NAME on ARTIFACT-ID, or
297 ** one of the following:
298 ** if FALLBACK-VALUE provided and TAG-NAME not present,
299 ** then FALLBACK-VALUE is returned.
300 ** if FALLBACK-VALUE not provided, and TAG-NAME not present,
301 ** then 0 returned.
302 ** if TAG-NAME present, but has no value, then 1 is returned.
303 **
304 ** Example:
305 ** <b>Check-in acceptance status:</b>
306 ** <th1>
307 ** set accept_out ""
308 ** if {[set out [fossiltag get "QA_acceptance" $check_in_id "<b>DID NOT PASS</b>"]]} {
309 ** set accept_out " * QA: ${out}"
310 ** }
311 ** if {[set out [fossiltag get "Unit_passed" $check_in_id "<b>DID NOT PASS UNIT TESTS</b>"]]} {
312 ** set accept_out "${accept_out}\n * Unit tests: ${out}"
313 ** }
314 ** if {[set out [fossiltag get "Signed_off_by" $check_in_id "<b>NOT SIGNED OFF</b>"]]} {
315 ** set accept_out "${accept_out}\n * Signed off by: ${out}"
316 ** }
317 ** puts [wiki $accept_out]
318 ** </th1>
319 */
320 static int fossiltagGetCmd(
321 Th_Interp *interp,
322 void *p,
323 int argc,
324 const char **argv,
325 int *argl
326 ){
327 int rid = -1;
328 char *zTagValue = 0;
329 char *zDefault = 0;
330 int nDefault = 0;
331 db_open_local();
332 db_open_repository(0);
333 if( argc<3 ){
334 return Th_WrongNumArgs(interp, "fossiltag get TAG-NAME ?ARTIFACT-ID? ?FALLBACK-TEXT?");
335 }
336 /* if a fallback value was provided, place it in zDefault */
337 if( argc==5 ){
338 zDefault = (char*)argv[4];
339 nDefault = argl[4];
340 }
341 /* if an artifact-id (name) is given.. */
342 if( argc>=4 && strlen((char*)argv[3])){
343 rid =
344 db_int(0,
345 "SELECT blob.rid "
346 " FROM tag, tagxref, blob "
347 "WHERE tag.tagname=%Q AND blob.rid=%d"
348 " AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 "
349 " AND blob.rid=tagxref.rid ",
350 argv[2], name_to_rid((char*)argv[3])
351 );
352
353 if( g.thTrace ){
354 Th_Trace("[tagget] artifact-id: %s %d\n", argv[3], rid);
355 }
356 }
357 else { /* if no artifact-id is given, we select the most recent commit
358 containing TAG-NAME */
359 rid =
360 db_int(0,
361 "SELECT blob.rid "
362 " FROM tag, tagxref, event, blob "
363 "WHERE tag.tagname=%Q "
364 " AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 "
365 " AND event.objid=tagxref.rid "
366 " AND blob.rid=event.objid "
367 "ORDER BY event.mtime DESC ",
368 argv[2]
369 );
370 if( g.thTrace ){
371 Th_Trace("[tagget] artifact-rid: %d\n", rid);
372 }
373 }
374
375 /* return 0 or the fallback value, since we couldn't
376 find an artifact with TAG-NAME on it. */
377 if( rid==0 && argc==5 ){
378 if( g.thTrace ){
379 Th_Trace("[tagget] tag not on any artifact; returning default: %s\n", zDefault);
380 }
381 Th_SetResult(interp, zDefault, nDefault);
382 return TH_OK;
383 }
384 else if( rid==0 && argc<5 ){
385 if( g.thTrace ){
386 Th_Trace("[tagget] tag not on any artifact; ret: 0\n");
387 }
388 Th_SetResultInt(interp, 0);
389 return TH_OK;
390 }
391
392 zTagValue = db_text(zDefault,
393 "SELECT tagxref.value FROM tag, tagxref "
394 " WHERE tag.tagname=%Q "
395 " AND tagxref.tagid=tag.tagid "
396 " AND tagxref.rid=%d ",
397 argv[2], rid
398 );
399 if( zTagValue && strlen(zTagValue)==0 ){
400 if( g.thTrace ){
401 Th_Trace("[tagget] tag has no value; ret: 1\n");
402 }
403 Th_SetResultInt(interp, 1);
404 free(zTagValue);
405 }
406 else {
407 if( g.thTrace ){
408 Th_Trace("[tagget] returning tag value: %s\n", zTagValue);
409 }
410 Th_SetResult(interp, zTagValue, -1);
411 free(zTagValue);
412 }
413 return TH_OK;
414 }
415
416 /*
417 ** TH1 command: fossiltag list|get ...
418 **
419 ** Provide TH1 commands for read-only interation with tags on
420 ** any taggable artifact. The tags are always raw.
421 **
422 */
423 static int fossiltagCmd(
424 Th_Interp *interp,
425 void *p,
426 int argc,
427 const char **argv,
428 int *argl
429 ){
430 Th_SubCommand aSub[] = {
431 { "list", fossiltagListCmd },
432 { "get", fossiltagGetCmd },
433 { 0, 0 }
434 };
435 return Th_CallSubCommand(interp, p, argc, argv, argl, aSub);
436 }
437
438 /*
439 ** TH1 command: combobox NAME TEXT-LIST NUMLINES
440 **
441 ** Generate an HTML combobox. NAME is both the name of the
@@ -350,10 +549,11 @@
549 {"htmlize", htmlizeCmd, 0},
550 {"date", dateCmd, 0},
551 {"html", putsCmd, 0},
552 {"puts", putsCmd, (void*)1},
553 {"wiki", wikiCmd, 0},
554 {"fossiltag", fossiltagCmd, 0},
555 };
556 if( g.interp==0 ){
557 int i;
558 g.interp = Th_CreateInterp(&vtab);
559 th_register_language(g.interp); /* Basic scripting commands. */
@@ -519,12 +719,24 @@
719 /*
720 ** COMMAND: test-th-render
721 */
722 void test_th_render(void){
723 Blob in;
724 g.thTrace = find_option("th-trace", 0, 0)!=0;
725 if( g.thTrace ){
726 blob_zero(&g.thLog);
727 }
728 if( g.argc<3 ){
729 usage("FILE");
730 }
731 blob_zero(&in);
732 if( g.thTrace ){
733 blob_read_from_file(&in, g.argv[3]);
734 }
735 else{
736 blob_read_from_file(&in, g.argv[2]);
737 }
738 Th_Render(blob_str(&in));
739 if( g.thTrace ){
740 fossil_print("%s", blob_materialize(&g.thLog));
741 }
742 }
743

Keyboard Shortcuts

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