Fossil SCM

Change behavior of Fossil's tag handling. 1. All subcommands of command tag prepends a prefix "sym-" infront of every tag name passed to them. Tags beginning with "sym-" are special in Fossil as they might serve as replacement of a UUID they are attached to. Further, "tag list" will only list all tags beginning with "sym-" but with that prefix removed during display as default. All subcommands can get passed an option "--raw", that prevent the prepending of the prefix "sym-" in front of the tag name. "tag list" will report all tags without removeing any prefix if called with option "--raw". 2. If a command takes a tag name that may be confused with a UUID, the command did interpret that parameter as a UUID instead as a tag name. Such tags might now be prefixed with a "tag:" to enforce the command to take them as tag name instead of a UUID. For example: fossil tag add abcde $uuid : fossil update tag:abcde without the prefix "tag:" fossil would try to update to a UUID beginning with abcde. If no such UUID was found, fossil will complain and exit.

cle 2008-07-27 18:35 trunk
Commit d1c993802524c5a47d2e6219f9f1380f6ccff857
2 files changed +10 -3 +57 -15
+10 -3
--- src/name.c
+++ src/name.c
@@ -46,27 +46,34 @@
4646
int sz;
4747
sz = blob_size(pName);
4848
if( sz>UUID_SIZE || sz<4 || !validate16(blob_buffer(pName), sz) ){
4949
Stmt q;
5050
Blob uuid;
51
+ static const char prefix[] = "tag:";
52
+ static const int preflen = sizeof(prefix)-1;
53
+ const char *zName = blob_str(pName);
54
+
55
+ if( strncmp(zName, prefix, preflen)==0 ){
56
+ zName += preflen;
57
+ }
5158
5259
db_prepare(&q,
5360
"SELECT (SELECT uuid FROM blob WHERE rid=objid)"
5461
" FROM tagxref JOIN event ON rid=objid"
55
- " WHERE tagid=(SELECT tagid FROM tag WHERE tagname='sym-'||%B)"
62
+ " WHERE tagid=(SELECT tagid FROM tag WHERE tagname='sym-'||%Q)"
5663
" AND tagtype>0"
5764
" AND value IS NULL"
5865
" ORDER BY event.mtime DESC",
59
- pName
66
+ zName
6067
);
6168
blob_zero(&uuid);
6269
if( db_step(&q)==SQLITE_ROW ){
6370
db_column_blob(&q, 0, &uuid);
6471
}
6572
db_finalize(&q);
6673
if( blob_size(&uuid)==0 ){
67
- fossil_error(iErrPriority, "not a valid object name: %b", pName);
74
+ fossil_error(iErrPriority, "not a valid object name: %s", zName);
6875
blob_reset(&uuid);
6976
return 1;
7077
}else{
7178
blob_reset(pName);
7279
*pName = uuid;
7380
--- src/name.c
+++ src/name.c
@@ -46,27 +46,34 @@
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='sym-'||%B)"
56 " AND tagtype>0"
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
--- src/name.c
+++ src/name.c
@@ -46,27 +46,34 @@
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 static const char prefix[] = "tag:";
52 static const int preflen = sizeof(prefix)-1;
53 const char *zName = blob_str(pName);
54
55 if( strncmp(zName, prefix, preflen)==0 ){
56 zName += preflen;
57 }
58
59 db_prepare(&q,
60 "SELECT (SELECT uuid FROM blob WHERE rid=objid)"
61 " FROM tagxref JOIN event ON rid=objid"
62 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname='sym-'||%Q)"
63 " AND tagtype>0"
64 " AND value IS NULL"
65 " ORDER BY event.mtime DESC",
66 zName
67 );
68 blob_zero(&uuid);
69 if( db_step(&q)==SQLITE_ROW ){
70 db_column_blob(&q, 0, &uuid);
71 }
72 db_finalize(&q);
73 if( blob_size(&uuid)==0 ){
74 fossil_error(iErrPriority, "not a valid object name: %s", zName);
75 blob_reset(&uuid);
76 return 1;
77 }else{
78 blob_reset(pName);
79 *pName = uuid;
80
+57 -15
--- src/tag.c
+++ src/tag.c
@@ -273,11 +273,11 @@
273273
if( name_to_uuid(&uuid, 9) ){
274274
return;
275275
}
276276
rid = name_to_rid(blob_str(&uuid));
277277
blob_zero(&ctrl);
278
-
278
+
279279
if( validate16(zTagname, strlen(zTagname)) ){
280280
fossil_fatal("invalid tag name \"%s\" - might be confused with a UUID",
281281
zTagname);
282282
}
283283
zDate = db_text(0, "SELECT datetime('now')");
@@ -305,77 +305,109 @@
305305
** COMMAND: tag
306306
** Usage: %fossil tag SUBCOMMAND ...
307307
**
308308
** Run various subcommands to control tags and properties
309309
**
310
-** %fossil tag add TAGNAME UUID ?VALUE?
310
+** %fossil tag add ?--raw? TAGNAME UUID ?VALUE?
311311
**
312
-** Add a new tag or property to UUID.
312
+** Add a new tag or property to UUID. The tag will
313
+** be usable instead of a UUID in commands like
314
+** update and the like.
313315
**
314
-** %fossil tag branch TAGNAME UUID ?VALUE?
316
+** %fossil tag branch ?--raw? TAGNAME UUID ?VALUE?
315317
**
316318
** Add a new tag or property to UUID and make that
317319
** tag propagate to all direct children.
318320
**
319
-** %fossil tag delete TAGNAME UUID
321
+** %fossil tag delete ?--raw? TAGNAME UUID
320322
**
321323
** Delete the tag TAGNAME from UUID
322324
**
323
-** %fossil tag find TAGNAME
325
+** %fossil tag find ?--raw? TAGNAME
324326
**
325327
** List all baselines that use TAGNAME
326328
**
327
-** %fossil tag list ?UUID?
329
+** %fossil tag list ?--raw? ?UUID?
328330
**
329331
** List all tags, or if UUID is supplied, list
330332
** all tags and their values for UUID.
333
+**
334
+** The option ?--raw? is to expose the internal interface
335
+** for tag handling. This option is not necessary for the
336
+** normal use.
337
+**
338
+** If you use a tagname that might be confused with a UUID,
339
+** you have to explicitly disambiguate it by prefixing it
340
+** with "tag:". For instance:
341
+**
342
+** fossil update cfcfcfee
343
+**
344
+** is not the same as:
345
+**
346
+** fossil update tag:cfcfcfee
347
+**
348
+** The first will be taken as UUID and fossil will complain
349
+** if no such revision was found, and the second one expect
350
+** "cfcfcfee" to be a tag/branch name!
351
+**
331352
*/
332353
void tag_cmd(void){
333354
int n;
355
+ int raw = find_option("raw","",0)!=0;
356
+ const char *prefix = raw ? "" : "sym-";
357
+ int preflen = strlen(prefix);
358
+ Blob tagname;
359
+
334360
db_find_and_open_repository(1);
335361
if( g.argc<3 ){
336362
goto tag_cmd_usage;
337363
}
338364
n = strlen(g.argv[2]);
339365
if( n==0 ){
340366
goto tag_cmd_usage;
341367
}
368
+
369
+ blob_set(&tagname, prefix);
342370
343371
if( strncmp(g.argv[2],"add",n)==0 ){
344372
char *zValue;
345373
if( g.argc!=5 && g.argc!=6 ){
346374
usage("add TAGNAME UUID ?VALUE?");
347375
}
376
+ blob_append(&tagname, g.argv[3], strlen(g.argv[3]));
348377
zValue = g.argc==6 ? g.argv[5] : 0;
349
- tag_add_artifact(g.argv[3], g.argv[4], zValue, 1);
378
+ tag_add_artifact(blob_str(&tagname), g.argv[4], zValue, 1);
350379
}else
351380
352381
if( strncmp(g.argv[2],"branch",n)==0 ){
353382
char *zValue;
354383
if( g.argc!=5 && g.argc!=6 ){
355384
usage("branch TAGNAME UUID ?VALUE?");
356385
}
386
+ blob_append(&tagname, g.argv[3], strlen(g.argv[3]));
357387
zValue = g.argc==6 ? g.argv[5] : 0;
358
- tag_add_artifact(g.argv[3], g.argv[4], zValue, 2);
388
+ tag_add_artifact(blob_str(&tagname), g.argv[4], zValue, 2);
359389
}else
360390
361391
if( strncmp(g.argv[2],"delete",n)==0 ){
362392
if( g.argc!=5 ){
363393
usage("delete TAGNAME UUID");
364394
}
365
- tag_add_artifact(g.argv[3], g.argv[4], 0, 0);
395
+ blob_append(&tagname, g.argv[3], strlen(g.argv[3]));
396
+ tag_add_artifact(blob_str(&tagname), g.argv[4], 0, 0);
366397
}else
367398
368399
if( strncmp(g.argv[2],"find",n)==0 ){
369400
Stmt q;
370401
if( g.argc!=4 ){
371402
usage("find TAGNAME");
372403
}
404
+ blob_append(&tagname, g.argv[3], strlen(g.argv[3]));
373405
db_prepare(&q,
374406
"SELECT blob.uuid FROM tagxref, blob"
375
- " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
376
- " AND blob.rid=tagxref.rid", g.argv[3]
407
+ " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%B)"
408
+ " AND blob.rid=tagxref.rid", &tagname
377409
);
378410
while( db_step(&q)==SQLITE_ROW ){
379411
printf("%s\n", db_column_text(&q, 0));
380412
}
381413
db_finalize(&q);
@@ -391,11 +423,14 @@
391423
" WHERE tagid=tag.tagid"
392424
" AND tagtype>0)"
393425
" ORDER BY tagname"
394426
);
395427
while( db_step(&q)==SQLITE_ROW ){
396
- printf("%s\n", db_column_text(&q, 0));
428
+ const char *name = db_column_text(&q, 0);
429
+ if( raw || strncmp(name, prefix, preflen)==0 ){
430
+ printf("%s\n", name+preflen);
431
+ }
397432
}
398433
db_finalize(&q);
399434
}else if( g.argc==4 ){
400435
int rid = name_to_rid(g.argv[3]);
401436
db_prepare(&q,
@@ -408,13 +443,17 @@
408443
);
409444
while( db_step(&q)==SQLITE_ROW ){
410445
const char *zName = db_column_text(&q, 0);
411446
const char *zValue = db_column_text(&q, 1);
412447
if( zValue ){
413
- printf("%s=%s\n", zName, zValue);
448
+ if( raw || strncmp(zName, prefix, preflen)==0 ){
449
+ printf("%s=%s\n", zName+preflen, zValue);
450
+ }
414451
}else{
415
- printf("%s\n", zName);
452
+ if( raw || strncmp(zName, prefix, preflen)==0 ){
453
+ printf("%s\n", zName+preflen);
454
+ }
416455
}
417456
}
418457
db_finalize(&q);
419458
}else{
420459
usage("tag list ?UUID?");
@@ -421,10 +460,13 @@
421460
}
422461
}else
423462
{
424463
goto tag_cmd_usage;
425464
}
465
+
466
+ /* Cleanup */
467
+ blob_reset(&tagname);
426468
return;
427469
428470
tag_cmd_usage:
429471
usage("add|branch|delete|find|list ...");
430472
}
431473
--- src/tag.c
+++ src/tag.c
@@ -273,11 +273,11 @@
273 if( name_to_uuid(&uuid, 9) ){
274 return;
275 }
276 rid = name_to_rid(blob_str(&uuid));
277 blob_zero(&ctrl);
278
279 if( validate16(zTagname, strlen(zTagname)) ){
280 fossil_fatal("invalid tag name \"%s\" - might be confused with a UUID",
281 zTagname);
282 }
283 zDate = db_text(0, "SELECT datetime('now')");
@@ -305,77 +305,109 @@
305 ** COMMAND: tag
306 ** Usage: %fossil tag SUBCOMMAND ...
307 **
308 ** Run various subcommands to control tags and properties
309 **
310 ** %fossil tag add TAGNAME UUID ?VALUE?
311 **
312 ** Add a new tag or property to UUID.
 
 
313 **
314 ** %fossil tag branch TAGNAME UUID ?VALUE?
315 **
316 ** Add a new tag or property to UUID and make that
317 ** tag propagate to all direct children.
318 **
319 ** %fossil tag delete TAGNAME UUID
320 **
321 ** Delete the tag TAGNAME from UUID
322 **
323 ** %fossil tag find TAGNAME
324 **
325 ** List all baselines that use TAGNAME
326 **
327 ** %fossil tag list ?UUID?
328 **
329 ** List all tags, or if UUID is supplied, list
330 ** all tags and their values for UUID.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
331 */
332 void tag_cmd(void){
333 int n;
 
 
 
 
 
334 db_find_and_open_repository(1);
335 if( g.argc<3 ){
336 goto tag_cmd_usage;
337 }
338 n = strlen(g.argv[2]);
339 if( n==0 ){
340 goto tag_cmd_usage;
341 }
 
 
342
343 if( strncmp(g.argv[2],"add",n)==0 ){
344 char *zValue;
345 if( g.argc!=5 && g.argc!=6 ){
346 usage("add TAGNAME UUID ?VALUE?");
347 }
 
348 zValue = g.argc==6 ? g.argv[5] : 0;
349 tag_add_artifact(g.argv[3], g.argv[4], zValue, 1);
350 }else
351
352 if( strncmp(g.argv[2],"branch",n)==0 ){
353 char *zValue;
354 if( g.argc!=5 && g.argc!=6 ){
355 usage("branch TAGNAME UUID ?VALUE?");
356 }
 
357 zValue = g.argc==6 ? g.argv[5] : 0;
358 tag_add_artifact(g.argv[3], g.argv[4], zValue, 2);
359 }else
360
361 if( strncmp(g.argv[2],"delete",n)==0 ){
362 if( g.argc!=5 ){
363 usage("delete TAGNAME UUID");
364 }
365 tag_add_artifact(g.argv[3], g.argv[4], 0, 0);
 
366 }else
367
368 if( strncmp(g.argv[2],"find",n)==0 ){
369 Stmt q;
370 if( g.argc!=4 ){
371 usage("find TAGNAME");
372 }
 
373 db_prepare(&q,
374 "SELECT blob.uuid FROM tagxref, blob"
375 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
376 " AND blob.rid=tagxref.rid", g.argv[3]
377 );
378 while( db_step(&q)==SQLITE_ROW ){
379 printf("%s\n", db_column_text(&q, 0));
380 }
381 db_finalize(&q);
@@ -391,11 +423,14 @@
391 " WHERE tagid=tag.tagid"
392 " AND tagtype>0)"
393 " ORDER BY tagname"
394 );
395 while( db_step(&q)==SQLITE_ROW ){
396 printf("%s\n", db_column_text(&q, 0));
 
 
 
397 }
398 db_finalize(&q);
399 }else if( g.argc==4 ){
400 int rid = name_to_rid(g.argv[3]);
401 db_prepare(&q,
@@ -408,13 +443,17 @@
408 );
409 while( db_step(&q)==SQLITE_ROW ){
410 const char *zName = db_column_text(&q, 0);
411 const char *zValue = db_column_text(&q, 1);
412 if( zValue ){
413 printf("%s=%s\n", zName, zValue);
 
 
414 }else{
415 printf("%s\n", zName);
 
 
416 }
417 }
418 db_finalize(&q);
419 }else{
420 usage("tag list ?UUID?");
@@ -421,10 +460,13 @@
421 }
422 }else
423 {
424 goto tag_cmd_usage;
425 }
 
 
 
426 return;
427
428 tag_cmd_usage:
429 usage("add|branch|delete|find|list ...");
430 }
431
--- src/tag.c
+++ src/tag.c
@@ -273,11 +273,11 @@
273 if( name_to_uuid(&uuid, 9) ){
274 return;
275 }
276 rid = name_to_rid(blob_str(&uuid));
277 blob_zero(&ctrl);
278
279 if( validate16(zTagname, strlen(zTagname)) ){
280 fossil_fatal("invalid tag name \"%s\" - might be confused with a UUID",
281 zTagname);
282 }
283 zDate = db_text(0, "SELECT datetime('now')");
@@ -305,77 +305,109 @@
305 ** COMMAND: tag
306 ** Usage: %fossil tag SUBCOMMAND ...
307 **
308 ** Run various subcommands to control tags and properties
309 **
310 ** %fossil tag add ?--raw? TAGNAME UUID ?VALUE?
311 **
312 ** Add a new tag or property to UUID. The tag will
313 ** be usable instead of a UUID in commands like
314 ** update and the like.
315 **
316 ** %fossil tag branch ?--raw? TAGNAME UUID ?VALUE?
317 **
318 ** Add a new tag or property to UUID and make that
319 ** tag propagate to all direct children.
320 **
321 ** %fossil tag delete ?--raw? TAGNAME UUID
322 **
323 ** Delete the tag TAGNAME from UUID
324 **
325 ** %fossil tag find ?--raw? TAGNAME
326 **
327 ** List all baselines that use TAGNAME
328 **
329 ** %fossil tag list ?--raw? ?UUID?
330 **
331 ** List all tags, or if UUID is supplied, list
332 ** all tags and their values for UUID.
333 **
334 ** The option ?--raw? is to expose the internal interface
335 ** for tag handling. This option is not necessary for the
336 ** normal use.
337 **
338 ** If you use a tagname that might be confused with a UUID,
339 ** you have to explicitly disambiguate it by prefixing it
340 ** with "tag:". For instance:
341 **
342 ** fossil update cfcfcfee
343 **
344 ** is not the same as:
345 **
346 ** fossil update tag:cfcfcfee
347 **
348 ** The first will be taken as UUID and fossil will complain
349 ** if no such revision was found, and the second one expect
350 ** "cfcfcfee" to be a tag/branch name!
351 **
352 */
353 void tag_cmd(void){
354 int n;
355 int raw = find_option("raw","",0)!=0;
356 const char *prefix = raw ? "" : "sym-";
357 int preflen = strlen(prefix);
358 Blob tagname;
359
360 db_find_and_open_repository(1);
361 if( g.argc<3 ){
362 goto tag_cmd_usage;
363 }
364 n = strlen(g.argv[2]);
365 if( n==0 ){
366 goto tag_cmd_usage;
367 }
368
369 blob_set(&tagname, prefix);
370
371 if( strncmp(g.argv[2],"add",n)==0 ){
372 char *zValue;
373 if( g.argc!=5 && g.argc!=6 ){
374 usage("add TAGNAME UUID ?VALUE?");
375 }
376 blob_append(&tagname, g.argv[3], strlen(g.argv[3]));
377 zValue = g.argc==6 ? g.argv[5] : 0;
378 tag_add_artifact(blob_str(&tagname), g.argv[4], zValue, 1);
379 }else
380
381 if( strncmp(g.argv[2],"branch",n)==0 ){
382 char *zValue;
383 if( g.argc!=5 && g.argc!=6 ){
384 usage("branch TAGNAME UUID ?VALUE?");
385 }
386 blob_append(&tagname, g.argv[3], strlen(g.argv[3]));
387 zValue = g.argc==6 ? g.argv[5] : 0;
388 tag_add_artifact(blob_str(&tagname), g.argv[4], zValue, 2);
389 }else
390
391 if( strncmp(g.argv[2],"delete",n)==0 ){
392 if( g.argc!=5 ){
393 usage("delete TAGNAME UUID");
394 }
395 blob_append(&tagname, g.argv[3], strlen(g.argv[3]));
396 tag_add_artifact(blob_str(&tagname), g.argv[4], 0, 0);
397 }else
398
399 if( strncmp(g.argv[2],"find",n)==0 ){
400 Stmt q;
401 if( g.argc!=4 ){
402 usage("find TAGNAME");
403 }
404 blob_append(&tagname, g.argv[3], strlen(g.argv[3]));
405 db_prepare(&q,
406 "SELECT blob.uuid FROM tagxref, blob"
407 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%B)"
408 " AND blob.rid=tagxref.rid", &tagname
409 );
410 while( db_step(&q)==SQLITE_ROW ){
411 printf("%s\n", db_column_text(&q, 0));
412 }
413 db_finalize(&q);
@@ -391,11 +423,14 @@
423 " WHERE tagid=tag.tagid"
424 " AND tagtype>0)"
425 " ORDER BY tagname"
426 );
427 while( db_step(&q)==SQLITE_ROW ){
428 const char *name = db_column_text(&q, 0);
429 if( raw || strncmp(name, prefix, preflen)==0 ){
430 printf("%s\n", name+preflen);
431 }
432 }
433 db_finalize(&q);
434 }else if( g.argc==4 ){
435 int rid = name_to_rid(g.argv[3]);
436 db_prepare(&q,
@@ -408,13 +443,17 @@
443 );
444 while( db_step(&q)==SQLITE_ROW ){
445 const char *zName = db_column_text(&q, 0);
446 const char *zValue = db_column_text(&q, 1);
447 if( zValue ){
448 if( raw || strncmp(zName, prefix, preflen)==0 ){
449 printf("%s=%s\n", zName+preflen, zValue);
450 }
451 }else{
452 if( raw || strncmp(zName, prefix, preflen)==0 ){
453 printf("%s\n", zName+preflen);
454 }
455 }
456 }
457 db_finalize(&q);
458 }else{
459 usage("tag list ?UUID?");
@@ -421,10 +460,13 @@
460 }
461 }else
462 {
463 goto tag_cmd_usage;
464 }
465
466 /* Cleanup */
467 blob_reset(&tagname);
468 return;
469
470 tag_cmd_usage:
471 usage("add|branch|delete|find|list ...");
472 }
473

Keyboard Shortcuts

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