Fossil SCM
Fix the "purge cat" command to work as documented. Add the "purge obliterate" command.
Commit
353bfbacb9d20c3db3dca4f2ea0d4ce4985a8200
Parent
eb3ae3d619cfb00…
1 file changed
+52
-23
+52
-23
| --- src/purge.c | ||
| +++ src/purge.c | ||
| @@ -409,33 +409,42 @@ | ||
| 409 | 409 | ** fossil purge cat UUID... |
| 410 | 410 | ** |
| 411 | 411 | ** Write the content of one or more artifacts in the graveyard onto |
| 412 | 412 | ** standard output. |
| 413 | 413 | ** |
| 414 | -** fossil purge [checkin] TAGS... [--explain] | |
| 414 | +** fossil purge ?checkins? TAGS... ?OPTIONS? | |
| 415 | 415 | ** |
| 416 | 416 | ** Move the checkins identified by TAGS and all of their descendants |
| 417 | -** out of the repository and into the graveyard. If a TAG is a branch | |
| 418 | -** name then it means all the checkins on that branch. If the --explain | |
| 419 | -** option appears, then the repository and graveyard are unchanged and | |
| 420 | -** an explaination of what would have happened is shown instead. The | |
| 421 | -** "checkin" subcommand keyword is only required if TAGS would be | |
| 422 | -** ambiguous with one of the other subcommands. | |
| 417 | +** out of the repository and into the graveyard. The "checkins" | |
| 418 | +** subcommand keyword is option and can be omitted as long as TAGS | |
| 419 | +** does not conflict with any other subcommand. | |
| 420 | +** | |
| 421 | +** If a TAGS includes a branch name then it means all the checkins | |
| 422 | +** on the most recent occurrance of that branch. | |
| 423 | +** | |
| 424 | +** --explain Make no changes, but show what would happen. | |
| 425 | +** --dry-run Make no chances. | |
| 423 | 426 | ** |
| 424 | -** fossil purge list|ls [-l] | |
| 427 | +** fossil purge list|ls ?-l? | |
| 425 | 428 | ** |
| 426 | 429 | ** Show the graveyard of prior purges. The -l option gives more |
| 427 | 430 | ** detail in the output. |
| 428 | 431 | ** |
| 432 | +** fossil purge obliterate ID... | |
| 433 | +** | |
| 434 | +** Remove one or more purge events from the graveyard. Once a purge | |
| 435 | +** event is obliterated, it can no longer be undone. | |
| 436 | +** | |
| 429 | 437 | ** fossil purge undo ID |
| 430 | 438 | ** |
| 431 | 439 | ** Restore the content previously removed by purge ID. |
| 432 | 440 | ** |
| 433 | 441 | ** SUMMARY: |
| 434 | 442 | ** fossil purge cat UUID... |
| 435 | -** fossil purge [checkin] TAGS... [--explain] | |
| 443 | +** fossil purge [checkins] TAGS... [--explain] | |
| 436 | 444 | ** fossil purge list |
| 445 | +** fossil purge obliterate ID... | |
| 437 | 446 | ** fossil purge undo ID |
| 438 | 447 | */ |
| 439 | 448 | void purge_cmd(void){ |
| 440 | 449 | const char *zSubcmd; |
| 441 | 450 | int n; |
| @@ -442,11 +451,26 @@ | ||
| 442 | 451 | Stmt q; |
| 443 | 452 | if( g.argc<3 ) usage("SUBCOMMAND ?ARGS?"); |
| 444 | 453 | zSubcmd = g.argv[2]; |
| 445 | 454 | db_find_and_open_repository(0,0); |
| 446 | 455 | n = (int)strlen(zSubcmd); |
| 447 | - if( strncmp(zSubcmd, "list", n)==0 || strcmp(zSubcmd,"ls")==0 ){ | |
| 456 | + if( strncmp(zSubcmd, "cat", n)==0 ){ | |
| 457 | + const char *zOutFile; | |
| 458 | + int i, piid; | |
| 459 | + Blob content; | |
| 460 | + if( g.argc<4 ) usage("cat UUID..."); | |
| 461 | + for(i=3; i<g.argc; i++){ | |
| 462 | + piid = db_int(0, "SELECT piid FROM purgeitem WHERE uuid LIKE '%q%%'", | |
| 463 | + g.argv[i]); | |
| 464 | + if( piid==0 ) fossil_fatal("no such item: %s", g.argv[3]); | |
| 465 | + purge_extract_item(piid, &content); | |
| 466 | + blob_write_to_file(&content, "-"); | |
| 467 | + blob_reset(&content); | |
| 468 | + } | |
| 469 | + /* The "checkins" subcommand goes here in alphabetical order, but it must | |
| 470 | + ** be moved to the end since it is the default case */ | |
| 471 | + }else if( strncmp(zSubcmd, "list", n)==0 || strcmp(zSubcmd,"ls")==0 ){ | |
| 448 | 472 | int showDetail = find_option("l","l",0)!=0; |
| 449 | 473 | if( db_int(-1,"PRAGMA table_info('purgeevent')")<0 ) return; |
| 450 | 474 | db_prepare(&q, "SELECT peid, datetime(ctime,'unixepoch','localtime')" |
| 451 | 475 | " FROM purgeevent"); |
| 452 | 476 | while( db_step(&q)==SQLITE_ROW ){ |
| @@ -454,10 +478,26 @@ | ||
| 454 | 478 | if( showDetail ){ |
| 455 | 479 | purge_list_event_content(db_column_int(&q,0)); |
| 456 | 480 | } |
| 457 | 481 | } |
| 458 | 482 | db_finalize(&q); |
| 483 | + }else if( strncmp(zSubcmd, "obliterate", n)==0 ){ | |
| 484 | + int i; | |
| 485 | + if( g.argc<4 ) usage("obliterate ID..."); | |
| 486 | + db_begin_transaction(); | |
| 487 | + for(i=3; i<g.argc; i++){ | |
| 488 | + int peid = atoi(g.argv[i]); | |
| 489 | + if( !db_exists("SELECT 1 FROM purgeevent WHERE peid=%d",peid) ){ | |
| 490 | + fossil_fatal("no such purge event: %s", g.argv[i]); | |
| 491 | + } | |
| 492 | + db_multi_exec( | |
| 493 | + "DELETE FROM purgeevent WHERE peid=%d;" | |
| 494 | + "DELETE FROM purgeitem WHERE peid=%d;", | |
| 495 | + peid, peid | |
| 496 | + ); | |
| 497 | + } | |
| 498 | + db_end_transaction(0); | |
| 459 | 499 | }else if( strncmp(zSubcmd, "undo", n)==0 ){ |
| 460 | 500 | int peid; |
| 461 | 501 | if( g.argc!=4 ) usage("undo ID"); |
| 462 | 502 | peid = atoi(g.argv[3]); |
| 463 | 503 | db_begin_transaction(); |
| @@ -475,33 +515,22 @@ | ||
| 475 | 515 | purge_item_resurrect(0, 0); |
| 476 | 516 | manifest_crosslink_end(0); |
| 477 | 517 | db_multi_exec("DELETE FROM purgeevent WHERE peid=%d", peid); |
| 478 | 518 | db_multi_exec("DELETE FROM purgeitem WHERE peid=%d", peid); |
| 479 | 519 | db_end_transaction(0); |
| 480 | - }else if( strncmp(zSubcmd, "cat", n)==0 ){ | |
| 481 | - const char *zOutFile; | |
| 482 | - int piid; | |
| 483 | - Blob content; | |
| 484 | - if( g.argc!=4 && g.argc!=5 ) usage("cat UUID [FILENAME]"); | |
| 485 | - zOutFile = g.argc==5 ? g.argv[4] : "-"; | |
| 486 | - piid = db_int(0, "SELECT piid FROM purgeitem WHERE uuid LIKE '%q%%'", | |
| 487 | - g.argv[3]); | |
| 488 | - if( piid==0 ) fossil_fatal("no such item: %s", g.argv[3]); | |
| 489 | - purge_extract_item(piid, &content); | |
| 490 | - blob_write_to_file(&content, zOutFile); | |
| 491 | - blob_reset(&content); | |
| 492 | 520 | }else{ |
| 521 | + /* The "checkins" command is the default and so must occur last */ | |
| 493 | 522 | int explainOnly = find_option("explain",0,0)!=0; |
| 494 | 523 | int dryRun = find_option("dry-run",0,0)!=0; |
| 495 | 524 | const char *zTag; |
| 496 | 525 | int i; |
| 497 | 526 | int vid; |
| 498 | 527 | int nCkin; |
| 499 | 528 | int nArtifact; |
| 500 | 529 | verify_all_options(); |
| 501 | 530 | db_begin_transaction(); |
| 502 | - i = strncmp(zSubcmd,"checkin",n)==0 ? 3 : 2; | |
| 531 | + i = strncmp(zSubcmd,"checkins",n)==0 ? 3 : 2; | |
| 503 | 532 | if( i>=g.argc ) usage("[checkin] TAGS... [--explain]"); |
| 504 | 533 | db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)"); |
| 505 | 534 | for(; i<g.argc; i++){ |
| 506 | 535 | int r = name_to_typed_rid(g.argv[i], "br"); |
| 507 | 536 | compute_descendants(r, 1000000000); |
| 508 | 537 |
| --- src/purge.c | |
| +++ src/purge.c | |
| @@ -409,33 +409,42 @@ | |
| 409 | ** fossil purge cat UUID... |
| 410 | ** |
| 411 | ** Write the content of one or more artifacts in the graveyard onto |
| 412 | ** standard output. |
| 413 | ** |
| 414 | ** fossil purge [checkin] TAGS... [--explain] |
| 415 | ** |
| 416 | ** Move the checkins identified by TAGS and all of their descendants |
| 417 | ** out of the repository and into the graveyard. If a TAG is a branch |
| 418 | ** name then it means all the checkins on that branch. If the --explain |
| 419 | ** option appears, then the repository and graveyard are unchanged and |
| 420 | ** an explaination of what would have happened is shown instead. The |
| 421 | ** "checkin" subcommand keyword is only required if TAGS would be |
| 422 | ** ambiguous with one of the other subcommands. |
| 423 | ** |
| 424 | ** fossil purge list|ls [-l] |
| 425 | ** |
| 426 | ** Show the graveyard of prior purges. The -l option gives more |
| 427 | ** detail in the output. |
| 428 | ** |
| 429 | ** fossil purge undo ID |
| 430 | ** |
| 431 | ** Restore the content previously removed by purge ID. |
| 432 | ** |
| 433 | ** SUMMARY: |
| 434 | ** fossil purge cat UUID... |
| 435 | ** fossil purge [checkin] TAGS... [--explain] |
| 436 | ** fossil purge list |
| 437 | ** fossil purge undo ID |
| 438 | */ |
| 439 | void purge_cmd(void){ |
| 440 | const char *zSubcmd; |
| 441 | int n; |
| @@ -442,11 +451,26 @@ | |
| 442 | Stmt q; |
| 443 | if( g.argc<3 ) usage("SUBCOMMAND ?ARGS?"); |
| 444 | zSubcmd = g.argv[2]; |
| 445 | db_find_and_open_repository(0,0); |
| 446 | n = (int)strlen(zSubcmd); |
| 447 | if( strncmp(zSubcmd, "list", n)==0 || strcmp(zSubcmd,"ls")==0 ){ |
| 448 | int showDetail = find_option("l","l",0)!=0; |
| 449 | if( db_int(-1,"PRAGMA table_info('purgeevent')")<0 ) return; |
| 450 | db_prepare(&q, "SELECT peid, datetime(ctime,'unixepoch','localtime')" |
| 451 | " FROM purgeevent"); |
| 452 | while( db_step(&q)==SQLITE_ROW ){ |
| @@ -454,10 +478,26 @@ | |
| 454 | if( showDetail ){ |
| 455 | purge_list_event_content(db_column_int(&q,0)); |
| 456 | } |
| 457 | } |
| 458 | db_finalize(&q); |
| 459 | }else if( strncmp(zSubcmd, "undo", n)==0 ){ |
| 460 | int peid; |
| 461 | if( g.argc!=4 ) usage("undo ID"); |
| 462 | peid = atoi(g.argv[3]); |
| 463 | db_begin_transaction(); |
| @@ -475,33 +515,22 @@ | |
| 475 | purge_item_resurrect(0, 0); |
| 476 | manifest_crosslink_end(0); |
| 477 | db_multi_exec("DELETE FROM purgeevent WHERE peid=%d", peid); |
| 478 | db_multi_exec("DELETE FROM purgeitem WHERE peid=%d", peid); |
| 479 | db_end_transaction(0); |
| 480 | }else if( strncmp(zSubcmd, "cat", n)==0 ){ |
| 481 | const char *zOutFile; |
| 482 | int piid; |
| 483 | Blob content; |
| 484 | if( g.argc!=4 && g.argc!=5 ) usage("cat UUID [FILENAME]"); |
| 485 | zOutFile = g.argc==5 ? g.argv[4] : "-"; |
| 486 | piid = db_int(0, "SELECT piid FROM purgeitem WHERE uuid LIKE '%q%%'", |
| 487 | g.argv[3]); |
| 488 | if( piid==0 ) fossil_fatal("no such item: %s", g.argv[3]); |
| 489 | purge_extract_item(piid, &content); |
| 490 | blob_write_to_file(&content, zOutFile); |
| 491 | blob_reset(&content); |
| 492 | }else{ |
| 493 | int explainOnly = find_option("explain",0,0)!=0; |
| 494 | int dryRun = find_option("dry-run",0,0)!=0; |
| 495 | const char *zTag; |
| 496 | int i; |
| 497 | int vid; |
| 498 | int nCkin; |
| 499 | int nArtifact; |
| 500 | verify_all_options(); |
| 501 | db_begin_transaction(); |
| 502 | i = strncmp(zSubcmd,"checkin",n)==0 ? 3 : 2; |
| 503 | if( i>=g.argc ) usage("[checkin] TAGS... [--explain]"); |
| 504 | db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)"); |
| 505 | for(; i<g.argc; i++){ |
| 506 | int r = name_to_typed_rid(g.argv[i], "br"); |
| 507 | compute_descendants(r, 1000000000); |
| 508 |
| --- src/purge.c | |
| +++ src/purge.c | |
| @@ -409,33 +409,42 @@ | |
| 409 | ** fossil purge cat UUID... |
| 410 | ** |
| 411 | ** Write the content of one or more artifacts in the graveyard onto |
| 412 | ** standard output. |
| 413 | ** |
| 414 | ** fossil purge ?checkins? TAGS... ?OPTIONS? |
| 415 | ** |
| 416 | ** Move the checkins identified by TAGS and all of their descendants |
| 417 | ** out of the repository and into the graveyard. The "checkins" |
| 418 | ** subcommand keyword is option and can be omitted as long as TAGS |
| 419 | ** does not conflict with any other subcommand. |
| 420 | ** |
| 421 | ** If a TAGS includes a branch name then it means all the checkins |
| 422 | ** on the most recent occurrance of that branch. |
| 423 | ** |
| 424 | ** --explain Make no changes, but show what would happen. |
| 425 | ** --dry-run Make no chances. |
| 426 | ** |
| 427 | ** fossil purge list|ls ?-l? |
| 428 | ** |
| 429 | ** Show the graveyard of prior purges. The -l option gives more |
| 430 | ** detail in the output. |
| 431 | ** |
| 432 | ** fossil purge obliterate ID... |
| 433 | ** |
| 434 | ** Remove one or more purge events from the graveyard. Once a purge |
| 435 | ** event is obliterated, it can no longer be undone. |
| 436 | ** |
| 437 | ** fossil purge undo ID |
| 438 | ** |
| 439 | ** Restore the content previously removed by purge ID. |
| 440 | ** |
| 441 | ** SUMMARY: |
| 442 | ** fossil purge cat UUID... |
| 443 | ** fossil purge [checkins] TAGS... [--explain] |
| 444 | ** fossil purge list |
| 445 | ** fossil purge obliterate ID... |
| 446 | ** fossil purge undo ID |
| 447 | */ |
| 448 | void purge_cmd(void){ |
| 449 | const char *zSubcmd; |
| 450 | int n; |
| @@ -442,11 +451,26 @@ | |
| 451 | Stmt q; |
| 452 | if( g.argc<3 ) usage("SUBCOMMAND ?ARGS?"); |
| 453 | zSubcmd = g.argv[2]; |
| 454 | db_find_and_open_repository(0,0); |
| 455 | n = (int)strlen(zSubcmd); |
| 456 | if( strncmp(zSubcmd, "cat", n)==0 ){ |
| 457 | const char *zOutFile; |
| 458 | int i, piid; |
| 459 | Blob content; |
| 460 | if( g.argc<4 ) usage("cat UUID..."); |
| 461 | for(i=3; i<g.argc; i++){ |
| 462 | piid = db_int(0, "SELECT piid FROM purgeitem WHERE uuid LIKE '%q%%'", |
| 463 | g.argv[i]); |
| 464 | if( piid==0 ) fossil_fatal("no such item: %s", g.argv[3]); |
| 465 | purge_extract_item(piid, &content); |
| 466 | blob_write_to_file(&content, "-"); |
| 467 | blob_reset(&content); |
| 468 | } |
| 469 | /* The "checkins" subcommand goes here in alphabetical order, but it must |
| 470 | ** be moved to the end since it is the default case */ |
| 471 | }else if( strncmp(zSubcmd, "list", n)==0 || strcmp(zSubcmd,"ls")==0 ){ |
| 472 | int showDetail = find_option("l","l",0)!=0; |
| 473 | if( db_int(-1,"PRAGMA table_info('purgeevent')")<0 ) return; |
| 474 | db_prepare(&q, "SELECT peid, datetime(ctime,'unixepoch','localtime')" |
| 475 | " FROM purgeevent"); |
| 476 | while( db_step(&q)==SQLITE_ROW ){ |
| @@ -454,10 +478,26 @@ | |
| 478 | if( showDetail ){ |
| 479 | purge_list_event_content(db_column_int(&q,0)); |
| 480 | } |
| 481 | } |
| 482 | db_finalize(&q); |
| 483 | }else if( strncmp(zSubcmd, "obliterate", n)==0 ){ |
| 484 | int i; |
| 485 | if( g.argc<4 ) usage("obliterate ID..."); |
| 486 | db_begin_transaction(); |
| 487 | for(i=3; i<g.argc; i++){ |
| 488 | int peid = atoi(g.argv[i]); |
| 489 | if( !db_exists("SELECT 1 FROM purgeevent WHERE peid=%d",peid) ){ |
| 490 | fossil_fatal("no such purge event: %s", g.argv[i]); |
| 491 | } |
| 492 | db_multi_exec( |
| 493 | "DELETE FROM purgeevent WHERE peid=%d;" |
| 494 | "DELETE FROM purgeitem WHERE peid=%d;", |
| 495 | peid, peid |
| 496 | ); |
| 497 | } |
| 498 | db_end_transaction(0); |
| 499 | }else if( strncmp(zSubcmd, "undo", n)==0 ){ |
| 500 | int peid; |
| 501 | if( g.argc!=4 ) usage("undo ID"); |
| 502 | peid = atoi(g.argv[3]); |
| 503 | db_begin_transaction(); |
| @@ -475,33 +515,22 @@ | |
| 515 | purge_item_resurrect(0, 0); |
| 516 | manifest_crosslink_end(0); |
| 517 | db_multi_exec("DELETE FROM purgeevent WHERE peid=%d", peid); |
| 518 | db_multi_exec("DELETE FROM purgeitem WHERE peid=%d", peid); |
| 519 | db_end_transaction(0); |
| 520 | }else{ |
| 521 | /* The "checkins" command is the default and so must occur last */ |
| 522 | int explainOnly = find_option("explain",0,0)!=0; |
| 523 | int dryRun = find_option("dry-run",0,0)!=0; |
| 524 | const char *zTag; |
| 525 | int i; |
| 526 | int vid; |
| 527 | int nCkin; |
| 528 | int nArtifact; |
| 529 | verify_all_options(); |
| 530 | db_begin_transaction(); |
| 531 | i = strncmp(zSubcmd,"checkins",n)==0 ? 3 : 2; |
| 532 | if( i>=g.argc ) usage("[checkin] TAGS... [--explain]"); |
| 533 | db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)"); |
| 534 | for(; i<g.argc; i++){ |
| 535 | int r = name_to_typed_rid(g.argv[i], "br"); |
| 536 | compute_descendants(r, 1000000000); |
| 537 |