Fossil SCM
The tag add/cancel subcommands now accept any artifact type which is recorded in the timeline: check-in, wiki, technote, forum, ticket, control. They also now explicitly reject any tags beginning with the internal-use prefixes (wiki-, tkt-, event-). The tag find/list subcommands have not yet been updated to support the new types.
Commit
d1f6b9d4a7ba4e91391ffde6e51efd6e2082a7b64a5d911ae92a5fed93cc30a6
Parent
b051ada90d4a669…
1 file changed
+80
-22
+80
-22
| --- src/tag.c | ||
| +++ src/tag.c | ||
| @@ -363,45 +363,71 @@ | ||
| 363 | 363 | assert( blob_is_reset(&ctrl) ); |
| 364 | 364 | if( g.localOpen ){ |
| 365 | 365 | manifest_to_disk(rid); |
| 366 | 366 | } |
| 367 | 367 | } |
| 368 | + | |
| 369 | +/* | |
| 370 | +** If zTag is NULL or valid for use as a tag for the `tag add` and | |
| 371 | +** `tag cancel` commands, returns without side effects, else emits a | |
| 372 | +** fatal error message. We reject certain prefixes to avoid that | |
| 373 | +** clients cause undue grief by improperly tagging artifacts as being, | |
| 374 | +** e.g., wiki pages or tickets. | |
| 375 | +*/ | |
| 376 | +static void tag_cmd_tagname_check(const char *zTag){ | |
| 377 | + if(zTag && *zTag && | |
| 378 | + (strncmp(zTag,"wiki-",5)==0 | |
| 379 | + || strncmp(zTag,"tkt-",4)==0 | |
| 380 | + || strncmp(zTag,"event-",6)==0)){ | |
| 381 | + fossil_fatal("Invalid prefix for tag name: %s", zTag); | |
| 382 | + } | |
| 383 | +} | |
| 368 | 384 | |
| 369 | 385 | /* |
| 370 | 386 | ** COMMAND: tag |
| 371 | 387 | ** |
| 372 | 388 | ** Usage: %fossil tag SUBCOMMAND ... |
| 373 | 389 | ** |
| 374 | 390 | ** Run various subcommands to control tags and properties. |
| 375 | 391 | ** |
| 376 | -** > fossil tag add ?OPTIONS? TAGNAME CHECK-IN ?VALUE? | |
| 392 | +** > fossil tag add ?OPTIONS? TAGNAME ARTIFACT-ID ?VALUE? | |
| 377 | 393 | ** |
| 378 | -** Add a new tag or property to CHECK-IN. The tag will | |
| 379 | -** be usable instead of a CHECK-IN in commands such as | |
| 380 | -** update and merge. If the --propagate flag is present, | |
| 381 | -** the tag value propagates to all descendants of CHECK-IN | |
| 394 | +** Add a new tag or property to an artifact referenced by | |
| 395 | +** ARTIFACT-ID. For checkins, the tag will be usable instead | |
| 396 | +** of a CHECK-IN in commands such as update and merge. If the | |
| 397 | +** --propagate flag is present and ARTIFACT-ID refers to a | |
| 398 | +** wiki page, forum post, tech-note, or check-in, the tag | |
| 399 | +** propagates to all descendants of that artifact. | |
| 382 | 400 | ** |
| 383 | 401 | ** Options: |
| 384 | -** --raw Raw tag name. | |
| 385 | -** --propagate Propagating tag. | |
| 386 | -** --date-override DATETIME Set date and time added. | |
| 387 | -** --user-override USER Name USER when adding the tag. | |
| 388 | -** -n|--dryrun Display the tag text, but do not | |
| 389 | -** actually insert it into the database. | |
| 402 | +** --raw Raw tag name. Ignored for | |
| 403 | +** non-CHECK-IN artifacts. | |
| 404 | +** --propagate Propagating tag. | |
| 405 | +** --date-override DATETIME Set date and time added. | |
| 406 | +** --user-override USER Name USER when adding the tag. | |
| 407 | +** -n|--dryrun Display the tag text, but do not | |
| 408 | +** actually insert it into the database. | |
| 390 | 409 | ** |
| 391 | 410 | ** The --date-override and --user-override options support |
| 392 | 411 | ** importing history from other SCM systems. DATETIME has |
| 393 | 412 | ** the form 'YYYY-MMM-DD HH:MM:SS'. |
| 394 | 413 | ** |
| 395 | -** > fossil tag cancel ?--raw? TAGNAME CHECK-IN | |
| 414 | +** Note that fossil uses some tag prefixes internally and this | |
| 415 | +** command will reject tags with these prefixes to avoid | |
| 416 | +** causing problems or confusion: "wiki-", "tkt-", "event-". | |
| 417 | +** | |
| 418 | +** > fossil tag cancel ?--raw? TAGNAME ARTIFACT-ID | |
| 396 | 419 | ** |
| 397 | -** Remove the tag TAGNAME from CHECK-IN, and also remove | |
| 398 | -** the propagation of the tag to any descendants. Use the | |
| 399 | -** the -n|--dryrun option to see what would have happened. | |
| 420 | +** Remove the tag TAGNAME from the artifact referenced by | |
| 421 | +** ARTIFACT-ID, and also remove the propagation of the tag to | |
| 422 | +** any descendants. Use the the -n|--dryrun option to see | |
| 423 | +** what would have happened. Certain tag name prefixes are | |
| 424 | +** forbidden, as documented for the 'add' subcommand. | |
| 400 | 425 | ** |
| 401 | 426 | ** Options: |
| 402 | -** --raw Raw tag name. | |
| 427 | +** --raw Raw tag name. Ignored for | |
| 428 | +** non-CHECK-IN artifacts. | |
| 403 | 429 | ** --date-override DATETIME Set date and time deleted. |
| 404 | 430 | ** --user-override USER Name USER when deleting the tag. |
| 405 | 431 | ** -n|--dryrun Display the control artifact, but do |
| 406 | 432 | ** not insert it into the database. |
| 407 | 433 | ** |
| @@ -461,21 +487,37 @@ | ||
| 461 | 487 | |
| 462 | 488 | if( strncmp(g.argv[2],"add",n)==0 ){ |
| 463 | 489 | char *zValue; |
| 464 | 490 | int dryRun = 0; |
| 465 | 491 | int fRaw = find_option("raw","",0)!=0; |
| 466 | - const char *zPrefix = fRaw ? "" : "sym-"; | |
| 492 | + const char *zPrefix = ""; | |
| 467 | 493 | int fPropagate = find_option("propagate","",0)!=0; |
| 468 | 494 | const char *zDateOvrd = find_option("date-override",0,1); |
| 469 | 495 | const char *zUserOvrd = find_option("user-override",0,1); |
| 496 | + const char *zTag; | |
| 497 | + const char *zObjId; | |
| 498 | + int objType; | |
| 470 | 499 | if( find_option("dryrun","n",0)!=0 ) dryRun = TAG_ADD_DRYRUN; |
| 471 | 500 | if( g.argc!=5 && g.argc!=6 ){ |
| 472 | - usage("add ?options? TAGNAME CHECK-IN ?VALUE?"); | |
| 501 | + usage("add ?options? TAGNAME ARTIFACT-ID ?VALUE?"); | |
| 473 | 502 | } |
| 503 | + zTag = g.argv[3]; | |
| 504 | + tag_cmd_tagname_check(zTag); | |
| 505 | + zObjId = g.argv[4]; | |
| 474 | 506 | zValue = g.argc==6 ? g.argv[5] : 0; |
| 507 | + objType = whatis_rid_type(symbolic_name_to_rid(zObjId, 0)); | |
| 508 | + switch(objType){ | |
| 509 | + case 0: | |
| 510 | + fossil_fatal("Cannot resolve artifact ID: %s", zObjId); | |
| 511 | + break; | |
| 512 | + case CFTYPE_MANIFEST: | |
| 513 | + zPrefix = fRaw ? "" : "sym-"; | |
| 514 | + break; | |
| 515 | + default: break; | |
| 516 | + } | |
| 475 | 517 | db_begin_transaction(); |
| 476 | - tag_add_artifact(zPrefix, g.argv[3], g.argv[4], zValue, | |
| 518 | + tag_add_artifact(zPrefix, zTag, zObjId, zValue, | |
| 477 | 519 | 1+fPropagate+dryRun,zDateOvrd,zUserOvrd); |
| 478 | 520 | db_end_transaction(0); |
| 479 | 521 | }else |
| 480 | 522 | |
| 481 | 523 | if( strncmp(g.argv[2],"branch",n)==0 ){ |
| @@ -484,19 +526,35 @@ | ||
| 484 | 526 | }else |
| 485 | 527 | |
| 486 | 528 | if( strncmp(g.argv[2],"cancel",n)==0 ){ |
| 487 | 529 | int dryRun = 0; |
| 488 | 530 | int fRaw = find_option("raw","",0)!=0; |
| 489 | - const char *zPrefix = fRaw ? "" : "sym-"; | |
| 531 | + const char *zPrefix = ""; | |
| 490 | 532 | const char *zDateOvrd = find_option("date-override",0,1); |
| 491 | 533 | const char *zUserOvrd = find_option("user-override",0,1); |
| 534 | + const char *zTag; | |
| 535 | + const char *zObjId; | |
| 536 | + int objType; | |
| 492 | 537 | if( find_option("dryrun","n",0)!=0 ) dryRun = TAG_ADD_DRYRUN; |
| 493 | 538 | if( g.argc!=5 ){ |
| 494 | - usage("cancel ?options? TAGNAME CHECK-IN"); | |
| 539 | + usage("cancel ?options? TAGNAME ARTIFACT-ID"); | |
| 540 | + } | |
| 541 | + zTag = g.argv[3]; | |
| 542 | + tag_cmd_tagname_check(zTag); | |
| 543 | + zObjId = g.argv[4]; | |
| 544 | + objType = whatis_rid_type(symbolic_name_to_rid(zObjId, 0)); | |
| 545 | + switch(objType){ | |
| 546 | + case 0: | |
| 547 | + fossil_fatal("Cannot resolve artifact ID: %s", zObjId); | |
| 548 | + break; | |
| 549 | + case CFTYPE_MANIFEST: | |
| 550 | + zPrefix = fRaw ? "" : "sym-"; | |
| 551 | + break; | |
| 552 | + default: break; | |
| 495 | 553 | } |
| 496 | 554 | db_begin_transaction(); |
| 497 | - tag_add_artifact(zPrefix, g.argv[3], g.argv[4], 0, dryRun, | |
| 555 | + tag_add_artifact(zPrefix, zTag, zObjId, 0, dryRun, | |
| 498 | 556 | zDateOvrd, zUserOvrd); |
| 499 | 557 | db_end_transaction(0); |
| 500 | 558 | }else |
| 501 | 559 | |
| 502 | 560 | if( strncmp(g.argv[2],"find",n)==0 ){ |
| 503 | 561 |
| --- src/tag.c | |
| +++ src/tag.c | |
| @@ -363,45 +363,71 @@ | |
| 363 | assert( blob_is_reset(&ctrl) ); |
| 364 | if( g.localOpen ){ |
| 365 | manifest_to_disk(rid); |
| 366 | } |
| 367 | } |
| 368 | |
| 369 | /* |
| 370 | ** COMMAND: tag |
| 371 | ** |
| 372 | ** Usage: %fossil tag SUBCOMMAND ... |
| 373 | ** |
| 374 | ** Run various subcommands to control tags and properties. |
| 375 | ** |
| 376 | ** > fossil tag add ?OPTIONS? TAGNAME CHECK-IN ?VALUE? |
| 377 | ** |
| 378 | ** Add a new tag or property to CHECK-IN. The tag will |
| 379 | ** be usable instead of a CHECK-IN in commands such as |
| 380 | ** update and merge. If the --propagate flag is present, |
| 381 | ** the tag value propagates to all descendants of CHECK-IN |
| 382 | ** |
| 383 | ** Options: |
| 384 | ** --raw Raw tag name. |
| 385 | ** --propagate Propagating tag. |
| 386 | ** --date-override DATETIME Set date and time added. |
| 387 | ** --user-override USER Name USER when adding the tag. |
| 388 | ** -n|--dryrun Display the tag text, but do not |
| 389 | ** actually insert it into the database. |
| 390 | ** |
| 391 | ** The --date-override and --user-override options support |
| 392 | ** importing history from other SCM systems. DATETIME has |
| 393 | ** the form 'YYYY-MMM-DD HH:MM:SS'. |
| 394 | ** |
| 395 | ** > fossil tag cancel ?--raw? TAGNAME CHECK-IN |
| 396 | ** |
| 397 | ** Remove the tag TAGNAME from CHECK-IN, and also remove |
| 398 | ** the propagation of the tag to any descendants. Use the |
| 399 | ** the -n|--dryrun option to see what would have happened. |
| 400 | ** |
| 401 | ** Options: |
| 402 | ** --raw Raw tag name. |
| 403 | ** --date-override DATETIME Set date and time deleted. |
| 404 | ** --user-override USER Name USER when deleting the tag. |
| 405 | ** -n|--dryrun Display the control artifact, but do |
| 406 | ** not insert it into the database. |
| 407 | ** |
| @@ -461,21 +487,37 @@ | |
| 461 | |
| 462 | if( strncmp(g.argv[2],"add",n)==0 ){ |
| 463 | char *zValue; |
| 464 | int dryRun = 0; |
| 465 | int fRaw = find_option("raw","",0)!=0; |
| 466 | const char *zPrefix = fRaw ? "" : "sym-"; |
| 467 | int fPropagate = find_option("propagate","",0)!=0; |
| 468 | const char *zDateOvrd = find_option("date-override",0,1); |
| 469 | const char *zUserOvrd = find_option("user-override",0,1); |
| 470 | if( find_option("dryrun","n",0)!=0 ) dryRun = TAG_ADD_DRYRUN; |
| 471 | if( g.argc!=5 && g.argc!=6 ){ |
| 472 | usage("add ?options? TAGNAME CHECK-IN ?VALUE?"); |
| 473 | } |
| 474 | zValue = g.argc==6 ? g.argv[5] : 0; |
| 475 | db_begin_transaction(); |
| 476 | tag_add_artifact(zPrefix, g.argv[3], g.argv[4], zValue, |
| 477 | 1+fPropagate+dryRun,zDateOvrd,zUserOvrd); |
| 478 | db_end_transaction(0); |
| 479 | }else |
| 480 | |
| 481 | if( strncmp(g.argv[2],"branch",n)==0 ){ |
| @@ -484,19 +526,35 @@ | |
| 484 | }else |
| 485 | |
| 486 | if( strncmp(g.argv[2],"cancel",n)==0 ){ |
| 487 | int dryRun = 0; |
| 488 | int fRaw = find_option("raw","",0)!=0; |
| 489 | const char *zPrefix = fRaw ? "" : "sym-"; |
| 490 | const char *zDateOvrd = find_option("date-override",0,1); |
| 491 | const char *zUserOvrd = find_option("user-override",0,1); |
| 492 | if( find_option("dryrun","n",0)!=0 ) dryRun = TAG_ADD_DRYRUN; |
| 493 | if( g.argc!=5 ){ |
| 494 | usage("cancel ?options? TAGNAME CHECK-IN"); |
| 495 | } |
| 496 | db_begin_transaction(); |
| 497 | tag_add_artifact(zPrefix, g.argv[3], g.argv[4], 0, dryRun, |
| 498 | zDateOvrd, zUserOvrd); |
| 499 | db_end_transaction(0); |
| 500 | }else |
| 501 | |
| 502 | if( strncmp(g.argv[2],"find",n)==0 ){ |
| 503 |
| --- src/tag.c | |
| +++ src/tag.c | |
| @@ -363,45 +363,71 @@ | |
| 363 | assert( blob_is_reset(&ctrl) ); |
| 364 | if( g.localOpen ){ |
| 365 | manifest_to_disk(rid); |
| 366 | } |
| 367 | } |
| 368 | |
| 369 | /* |
| 370 | ** If zTag is NULL or valid for use as a tag for the `tag add` and |
| 371 | ** `tag cancel` commands, returns without side effects, else emits a |
| 372 | ** fatal error message. We reject certain prefixes to avoid that |
| 373 | ** clients cause undue grief by improperly tagging artifacts as being, |
| 374 | ** e.g., wiki pages or tickets. |
| 375 | */ |
| 376 | static void tag_cmd_tagname_check(const char *zTag){ |
| 377 | if(zTag && *zTag && |
| 378 | (strncmp(zTag,"wiki-",5)==0 |
| 379 | || strncmp(zTag,"tkt-",4)==0 |
| 380 | || strncmp(zTag,"event-",6)==0)){ |
| 381 | fossil_fatal("Invalid prefix for tag name: %s", zTag); |
| 382 | } |
| 383 | } |
| 384 | |
| 385 | /* |
| 386 | ** COMMAND: tag |
| 387 | ** |
| 388 | ** Usage: %fossil tag SUBCOMMAND ... |
| 389 | ** |
| 390 | ** Run various subcommands to control tags and properties. |
| 391 | ** |
| 392 | ** > fossil tag add ?OPTIONS? TAGNAME ARTIFACT-ID ?VALUE? |
| 393 | ** |
| 394 | ** Add a new tag or property to an artifact referenced by |
| 395 | ** ARTIFACT-ID. For checkins, the tag will be usable instead |
| 396 | ** of a CHECK-IN in commands such as update and merge. If the |
| 397 | ** --propagate flag is present and ARTIFACT-ID refers to a |
| 398 | ** wiki page, forum post, tech-note, or check-in, the tag |
| 399 | ** propagates to all descendants of that artifact. |
| 400 | ** |
| 401 | ** Options: |
| 402 | ** --raw Raw tag name. Ignored for |
| 403 | ** non-CHECK-IN artifacts. |
| 404 | ** --propagate Propagating tag. |
| 405 | ** --date-override DATETIME Set date and time added. |
| 406 | ** --user-override USER Name USER when adding the tag. |
| 407 | ** -n|--dryrun Display the tag text, but do not |
| 408 | ** actually insert it into the database. |
| 409 | ** |
| 410 | ** The --date-override and --user-override options support |
| 411 | ** importing history from other SCM systems. DATETIME has |
| 412 | ** the form 'YYYY-MMM-DD HH:MM:SS'. |
| 413 | ** |
| 414 | ** Note that fossil uses some tag prefixes internally and this |
| 415 | ** command will reject tags with these prefixes to avoid |
| 416 | ** causing problems or confusion: "wiki-", "tkt-", "event-". |
| 417 | ** |
| 418 | ** > fossil tag cancel ?--raw? TAGNAME ARTIFACT-ID |
| 419 | ** |
| 420 | ** Remove the tag TAGNAME from the artifact referenced by |
| 421 | ** ARTIFACT-ID, and also remove the propagation of the tag to |
| 422 | ** any descendants. Use the the -n|--dryrun option to see |
| 423 | ** what would have happened. Certain tag name prefixes are |
| 424 | ** forbidden, as documented for the 'add' subcommand. |
| 425 | ** |
| 426 | ** Options: |
| 427 | ** --raw Raw tag name. Ignored for |
| 428 | ** non-CHECK-IN artifacts. |
| 429 | ** --date-override DATETIME Set date and time deleted. |
| 430 | ** --user-override USER Name USER when deleting the tag. |
| 431 | ** -n|--dryrun Display the control artifact, but do |
| 432 | ** not insert it into the database. |
| 433 | ** |
| @@ -461,21 +487,37 @@ | |
| 487 | |
| 488 | if( strncmp(g.argv[2],"add",n)==0 ){ |
| 489 | char *zValue; |
| 490 | int dryRun = 0; |
| 491 | int fRaw = find_option("raw","",0)!=0; |
| 492 | const char *zPrefix = ""; |
| 493 | int fPropagate = find_option("propagate","",0)!=0; |
| 494 | const char *zDateOvrd = find_option("date-override",0,1); |
| 495 | const char *zUserOvrd = find_option("user-override",0,1); |
| 496 | const char *zTag; |
| 497 | const char *zObjId; |
| 498 | int objType; |
| 499 | if( find_option("dryrun","n",0)!=0 ) dryRun = TAG_ADD_DRYRUN; |
| 500 | if( g.argc!=5 && g.argc!=6 ){ |
| 501 | usage("add ?options? TAGNAME ARTIFACT-ID ?VALUE?"); |
| 502 | } |
| 503 | zTag = g.argv[3]; |
| 504 | tag_cmd_tagname_check(zTag); |
| 505 | zObjId = g.argv[4]; |
| 506 | zValue = g.argc==6 ? g.argv[5] : 0; |
| 507 | objType = whatis_rid_type(symbolic_name_to_rid(zObjId, 0)); |
| 508 | switch(objType){ |
| 509 | case 0: |
| 510 | fossil_fatal("Cannot resolve artifact ID: %s", zObjId); |
| 511 | break; |
| 512 | case CFTYPE_MANIFEST: |
| 513 | zPrefix = fRaw ? "" : "sym-"; |
| 514 | break; |
| 515 | default: break; |
| 516 | } |
| 517 | db_begin_transaction(); |
| 518 | tag_add_artifact(zPrefix, zTag, zObjId, zValue, |
| 519 | 1+fPropagate+dryRun,zDateOvrd,zUserOvrd); |
| 520 | db_end_transaction(0); |
| 521 | }else |
| 522 | |
| 523 | if( strncmp(g.argv[2],"branch",n)==0 ){ |
| @@ -484,19 +526,35 @@ | |
| 526 | }else |
| 527 | |
| 528 | if( strncmp(g.argv[2],"cancel",n)==0 ){ |
| 529 | int dryRun = 0; |
| 530 | int fRaw = find_option("raw","",0)!=0; |
| 531 | const char *zPrefix = ""; |
| 532 | const char *zDateOvrd = find_option("date-override",0,1); |
| 533 | const char *zUserOvrd = find_option("user-override",0,1); |
| 534 | const char *zTag; |
| 535 | const char *zObjId; |
| 536 | int objType; |
| 537 | if( find_option("dryrun","n",0)!=0 ) dryRun = TAG_ADD_DRYRUN; |
| 538 | if( g.argc!=5 ){ |
| 539 | usage("cancel ?options? TAGNAME ARTIFACT-ID"); |
| 540 | } |
| 541 | zTag = g.argv[3]; |
| 542 | tag_cmd_tagname_check(zTag); |
| 543 | zObjId = g.argv[4]; |
| 544 | objType = whatis_rid_type(symbolic_name_to_rid(zObjId, 0)); |
| 545 | switch(objType){ |
| 546 | case 0: |
| 547 | fossil_fatal("Cannot resolve artifact ID: %s", zObjId); |
| 548 | break; |
| 549 | case CFTYPE_MANIFEST: |
| 550 | zPrefix = fRaw ? "" : "sym-"; |
| 551 | break; |
| 552 | default: break; |
| 553 | } |
| 554 | db_begin_transaction(); |
| 555 | tag_add_artifact(zPrefix, zTag, zObjId, 0, dryRun, |
| 556 | zDateOvrd, zUserOvrd); |
| 557 | db_end_transaction(0); |
| 558 | }else |
| 559 | |
| 560 | if( strncmp(g.argv[2],"find",n)==0 ){ |
| 561 |