| | @@ -148,10 +148,13 @@ |
| 148 | 148 | return id; |
| 149 | 149 | } |
| 150 | 150 | |
| 151 | 151 | /* |
| 152 | 152 | ** Insert a tag into the database. |
| 153 | +** |
| 154 | +** Also translate zTag into a tagid and return the tagid. (In other words |
| 155 | +** if zTag is "bgcolor" then return TAG_BGCOLOR.) |
| 153 | 156 | */ |
| 154 | 157 | int tag_insert( |
| 155 | 158 | const char *zTag, /* Name of the tag (w/o the "+" or "-" prefix */ |
| 156 | 159 | int tagtype, /* 0:cancel 1:singleton 2:propagated */ |
| 157 | 160 | const char *zValue, /* Value if the tag is really a property */ |
| | @@ -228,10 +231,13 @@ |
| 228 | 231 | " SET mtime=julianday(%Q)," |
| 229 | 232 | " omtime=coalesce(omtime,mtime)" |
| 230 | 233 | " WHERE objid=%d", |
| 231 | 234 | zValue, rid); |
| 232 | 235 | } |
| 236 | + if( tagid==TAG_PARENT && tagtype==1 ){ |
| 237 | + manifest_reparent_checkin(rid, zValue); |
| 238 | + } |
| 233 | 239 | if( tagtype==1 ) tagtype = 0; |
| 234 | 240 | tag_propagate(rid, tagid, tagtype, rid, zValue, mtime); |
| 235 | 241 | return tagid; |
| 236 | 242 | } |
| 237 | 243 | |
| | @@ -273,13 +279,26 @@ |
| 273 | 279 | db_begin_transaction(); |
| 274 | 280 | tag_insert(zTag, tagtype, zValue, -1, 0.0, rid); |
| 275 | 281 | db_end_transaction(0); |
| 276 | 282 | } |
| 277 | 283 | |
| 284 | +/* |
| 285 | +** OR this value into the tagtype argument to tag_add_artifact to |
| 286 | +** cause the tag to be displayed on standard output rather than be |
| 287 | +** inserted. Used for --dryrun options and debugging. |
| 288 | +*/ |
| 289 | +#if INTERFACE |
| 290 | +#define TAG_ADD_DRYRUN 0x04 |
| 291 | +#endif |
| 292 | + |
| 278 | 293 | /* |
| 279 | 294 | ** Add a control record to the repository that either creates |
| 280 | 295 | ** or cancels a tag. |
| 296 | +** |
| 297 | +** tagtype should normally be 0, 1, or 2. But if the TAG_ADD_DRYRUN bit |
| 298 | +** is also set, then simply print the text of the tag on standard output |
| 299 | +** (for testing purposes) rather than create the tag. |
| 281 | 300 | */ |
| 282 | 301 | void tag_add_artifact( |
| 283 | 302 | const char *zPrefix, /* Prefix to prepend to tag name */ |
| 284 | 303 | const char *zTagname, /* The tag to add or cancel */ |
| 285 | 304 | const char *zObjName, /* Name of object attached to */ |
| | @@ -293,11 +312,16 @@ |
| 293 | 312 | char *zDate; |
| 294 | 313 | Blob uuid; |
| 295 | 314 | Blob ctrl; |
| 296 | 315 | Blob cksum; |
| 297 | 316 | static const char zTagtype[] = { '-', '+', '*' }; |
| 317 | + int dryRun = 0; |
| 298 | 318 | |
| 319 | + if( tagtype & TAG_ADD_DRYRUN ){ |
| 320 | + tagtype &= ~TAG_ADD_DRYRUN; |
| 321 | + dryRun = 1; |
| 322 | + } |
| 299 | 323 | assert( tagtype>=0 && tagtype<=2 ); |
| 300 | 324 | user_select(); |
| 301 | 325 | blob_zero(&uuid); |
| 302 | 326 | blob_append(&uuid, zObjName, -1); |
| 303 | 327 | if( name_to_uuid(&uuid, 9, "*") ){ |
| | @@ -327,12 +351,17 @@ |
| 327 | 351 | blob_appendf(&ctrl, "\n"); |
| 328 | 352 | } |
| 329 | 353 | blob_appendf(&ctrl, "U %F\n", zUserOvrd ? zUserOvrd : login_name()); |
| 330 | 354 | md5sum_blob(&ctrl, &cksum); |
| 331 | 355 | blob_appendf(&ctrl, "Z %b\n", &cksum); |
| 332 | | - nrid = content_put(&ctrl); |
| 333 | | - manifest_crosslink(nrid, &ctrl, MC_PERMIT_HOOKS); |
| 356 | + if( dryRun ){ |
| 357 | + fossil_print("%s", blob_str(&ctrl)); |
| 358 | + blob_reset(&ctrl); |
| 359 | + }else{ |
| 360 | + nrid = content_put(&ctrl); |
| 361 | + manifest_crosslink(nrid, &ctrl, MC_PERMIT_HOOKS); |
| 362 | + } |
| 334 | 363 | assert( blob_is_reset(&ctrl) ); |
| 335 | 364 | } |
| 336 | 365 | |
| 337 | 366 | /* |
| 338 | 367 | ** COMMAND: tag |
| | @@ -347,23 +376,26 @@ |
| 347 | 376 | ** be usable instead of a CHECK-IN in commands such as |
| 348 | 377 | ** update and merge. If the --propagate flag is present, |
| 349 | 378 | ** the tag value propagates to all descendants of CHECK-IN |
| 350 | 379 | ** |
| 351 | 380 | ** Options: |
| 352 | | -** --raw Raw tag name. |
| 353 | | -** --propagate Propagating tag. |
| 354 | | -** --date-override DATETIME Set date and time added. |
| 355 | | -** --user-override USER Name USER when adding the tag. |
| 381 | +** --raw Raw tag name. |
| 382 | +** --propagate Propagating tag. |
| 383 | +** --date-override DATETIME Set date and time added. |
| 384 | +** --user-override USER Name USER when adding the tag. |
| 385 | +** --dryrun|-n Display the tag text, but to not |
| 386 | +** actually insert it into the database. |
| 356 | 387 | ** |
| 357 | 388 | ** The --date-override and --user-override options support |
| 358 | 389 | ** importing history from other SCM systems. DATETIME has |
| 359 | 390 | ** the form 'YYYY-MMM-DD HH:MM:SS'. |
| 360 | 391 | ** |
| 361 | 392 | ** %fossil tag cancel ?--raw? TAGNAME CHECK-IN |
| 362 | 393 | ** |
| 363 | 394 | ** Remove the tag TAGNAME from CHECK-IN, and also remove |
| 364 | | -** the propagation of the tag to any descendants. |
| 395 | +** the propagation of the tag to any descendants. Use the |
| 396 | +** the --dryrun or -n options to see what would have happened. |
| 365 | 397 | ** |
| 366 | 398 | ** %fossil tag find ?OPTIONS? TAGNAME |
| 367 | 399 | ** |
| 368 | 400 | ** List all objects that use TAGNAME. TYPE can be "ci" for |
| 369 | 401 | ** check-ins or "e" for events. The limit option limits the number |
| | @@ -416,33 +448,37 @@ |
| 416 | 448 | goto tag_cmd_usage; |
| 417 | 449 | } |
| 418 | 450 | |
| 419 | 451 | if( strncmp(g.argv[2],"add",n)==0 ){ |
| 420 | 452 | char *zValue; |
| 453 | + int dryRun = 0; |
| 421 | 454 | const char *zDateOvrd = find_option("date-override",0,1); |
| 422 | 455 | const char *zUserOvrd = find_option("user-override",0,1); |
| 456 | + if( find_option("dryrun","n",0)!=0 ) dryRun = TAG_ADD_DRYRUN; |
| 423 | 457 | if( g.argc!=5 && g.argc!=6 ){ |
| 424 | | - usage("add ?--raw? ?--propagate? TAGNAME CHECK-IN ?VALUE?"); |
| 458 | + usage("add ?options? TAGNAME CHECK-IN ?VALUE?"); |
| 425 | 459 | } |
| 426 | 460 | zValue = g.argc==6 ? g.argv[5] : 0; |
| 427 | 461 | db_begin_transaction(); |
| 428 | 462 | tag_add_artifact(zPrefix, g.argv[3], g.argv[4], zValue, |
| 429 | | - 1+fPropagate,zDateOvrd,zUserOvrd); |
| 463 | + 1+fPropagate+dryRun,zDateOvrd,zUserOvrd); |
| 430 | 464 | db_end_transaction(0); |
| 431 | 465 | }else |
| 432 | 466 | |
| 433 | 467 | if( strncmp(g.argv[2],"branch",n)==0 ){ |
| 434 | 468 | fossil_fatal("the \"fossil tag branch\" command is discontinued\n" |
| 435 | 469 | "Use the \"fossil branch new\" command instead."); |
| 436 | 470 | }else |
| 437 | 471 | |
| 438 | 472 | if( strncmp(g.argv[2],"cancel",n)==0 ){ |
| 473 | + int dryRun = 0; |
| 474 | + if( find_option("dryrun","n",0)!=0 ) dryRun = TAG_ADD_DRYRUN; |
| 439 | 475 | if( g.argc!=5 ){ |
| 440 | | - usage("cancel ?--raw? TAGNAME CHECK-IN"); |
| 476 | + usage("cancel ?options? TAGNAME CHECK-IN"); |
| 441 | 477 | } |
| 442 | 478 | db_begin_transaction(); |
| 443 | | - tag_add_artifact(zPrefix, g.argv[3], g.argv[4], 0, 0, 0, 0); |
| 479 | + tag_add_artifact(zPrefix, g.argv[3], g.argv[4], 0, dryRun, 0, 0); |
| 444 | 480 | db_end_transaction(0); |
| 445 | 481 | }else |
| 446 | 482 | |
| 447 | 483 | if( strncmp(g.argv[2],"find",n)==0 ){ |
| 448 | 484 | Stmt q; |
| | @@ -546,10 +582,65 @@ |
| 546 | 582 | return; |
| 547 | 583 | |
| 548 | 584 | tag_cmd_usage: |
| 549 | 585 | usage("add|cancel|find|list ..."); |
| 550 | 586 | } |
| 587 | + |
| 588 | +/* |
| 589 | +** COMMAND: reparent* |
| 590 | +** |
| 591 | +** Usage: %fossil reparent [OPTIONS] CHECK-IN PARENT .... |
| 592 | +** |
| 593 | +** Create a "parent" tag that causes CHECK-IN to be interpreted as a |
| 594 | +** child of PARENT. If multiple PARENTs are listed, then the first is |
| 595 | +** the primary parent and others are merge ancestors. |
| 596 | +** |
| 597 | +** This is an experts-only command. It is used to patch up a repository |
| 598 | +** that has been damaged by a shun or that has been pieced together from |
| 599 | +** two or more separate repositories. You should never need to reparent |
| 600 | +** during normal operations. |
| 601 | +** |
| 602 | +** Reparenting is accomplished by adding a parent tag. So to undo the |
| 603 | +** reparenting operation, simply delete the tag. |
| 604 | +** |
| 605 | +** --test Make database entries but do not add the tag artifact. |
| 606 | +** So the reparent operation will be undone by the next |
| 607 | +** "fossil rebuild" command. |
| 608 | +** --dryrun | -n Print the tag that would have been created but do not |
| 609 | +** actually change the database in any way. |
| 610 | +*/ |
| 611 | +void reparent_cmd(void){ |
| 612 | + int bTest = find_option("test","",0)!=0; |
| 613 | + int rid; |
| 614 | + int i; |
| 615 | + Blob value; |
| 616 | + char *zUuid; |
| 617 | + int dryRun = 0; |
| 618 | + |
| 619 | + if( find_option("dryrun","n",0)!=0 ) dryRun = TAG_ADD_DRYRUN; |
| 620 | + db_find_and_open_repository(0, 0); |
| 621 | + verify_all_options(); |
| 622 | + if( g.argc<4 ){ |
| 623 | + usage("reparent [OPTIONS] PARENT ..."); |
| 624 | + } |
| 625 | + rid = name_to_typed_rid(g.argv[2], "ci"); |
| 626 | + blob_init(&value, 0, 0); |
| 627 | + for(i=3; i<g.argc; i++){ |
| 628 | + int pid = name_to_typed_rid(g.argv[i], "ci"); |
| 629 | + if( i>3 ) blob_append(&value, " ", 1); |
| 630 | + zUuid = rid_to_uuid(pid); |
| 631 | + blob_append(&value, zUuid, UUID_SIZE); |
| 632 | + fossil_free(zUuid); |
| 633 | + } |
| 634 | + if( bTest && !dryRun ){ |
| 635 | + tag_insert("parent", 1, blob_str(&value), -1, 0.0, rid); |
| 636 | + }else{ |
| 637 | + zUuid = rid_to_uuid(rid); |
| 638 | + tag_add_artifact("","parent",zUuid,blob_str(&value),1|dryRun,0,0); |
| 639 | + } |
| 640 | +} |
| 641 | + |
| 551 | 642 | |
| 552 | 643 | /* |
| 553 | 644 | ** WEBPAGE: taglist |
| 554 | 645 | ** |
| 555 | 646 | ** List all non-propagating symbolic tags. |
| 556 | 647 | |