Index: src/name.c ================================================================== --- src/name.c +++ src/name.c @@ -934,16 +934,21 @@ "UPDATE description SET isPrivate=1 WHERE rid IN private" ); } /* -** Print the content of the description table on stdout +** Print the content of the description table on stdout. +** +** The description table is computed using the WHERE clause zWhere if +** the zWhere parameter is not NULL. If zWhere is NULL, then this +** routine assumes that the description table already exists and is +** populated and merely prints the contents. */ int describe_artifacts_to_stdout(const char *zWhere, const char *zLabel){ Stmt q; int cnt = 0; - describe_artifacts(zWhere); + if( zWhere!=0 ) describe_artifacts(zWhere); db_prepare(&q, "SELECT uuid, summary, isPrivate\n" " FROM description\n" " ORDER BY ctime, type;" ); @@ -956,11 +961,11 @@ if( db_column_int(&q,2) ) fossil_print(" (unpublished)"); fossil_print("\n"); cnt++; } db_finalize(&q); - db_multi_exec("DELETE FROM description;"); + if( zWhere!=0 ) db_multi_exec("DELETE FROM description;"); return cnt; } /* ** COMMAND: test-describe-artifacts Index: src/purge.c ================================================================== --- src/purge.c +++ src/purge.c @@ -22,11 +22,11 @@ #include "config.h" #include "purge.h" #include /* -** SQL code used to initialize the schema of a bundle. +** SQL code used to initialize the schema of the graveyard. ** ** The purgeevent table contains one entry for each purge event. For each ** purge event, multiple artifacts might have been removed. Each removed ** artifact is stored as an entry in the purgeitem table. ** @@ -52,10 +52,19 @@ @ desc TEXT, -- Brief description of this artifact @ data BLOB -- Compressed artifact content @ ); ; +/* +** Flags for the purge_artifact_list() function. +*/ +#if INTERFACE +#define PURGE_MOVETO_GRAVEYARD 0x0001 /* Move artifacts in graveyard */ +#define PURGE_EXPLAIN_ONLY 0x0002 /* Show what would have happened */ +#define PURGE_PRINT_SUMMARY 0x0004 /* Print a summary report at end */ +#endif + /* ** This routine purges multiple artifacts from the repository, transfering ** those artifacts into the PURGEITEM table. ** ** Prior to invoking this routine, the caller must create a (TEMP) table @@ -81,17 +90,17 @@ ** (j) TICKETCHNG ** (7) If any ticket artifacts were removed (6j) then rebuild the ** corresponding ticket entries. Possibly remove entries from ** the ticket table. ** -** Stops 1-4 (saving the purged artifacts into the graveyard) are only +** Steps 1-4 (saving the purged artifacts into the graveyard) are only ** undertaken if the moveToGraveyard flag is true. */ int purge_artifact_list( const char *zTab, /* TEMP table containing list of RIDS to be purged */ const char *zNote, /* Text of the purgeevent.pnotes field */ - int moveToGraveyard /* Move purged artifacts into the graveyard */ + unsigned purgeFlags /* zero or more PURGE_* flags */ ){ int peid = 0; /* New purgeevent ID */ Stmt q; /* General-use prepared statement */ char *z; @@ -98,10 +107,20 @@ assert( g.repositoryOpen ); /* Main database must already be open */ db_begin_transaction(); z = sqlite3_mprintf("IN \"%w\"", zTab); describe_artifacts(z); sqlite3_free(z); + describe_artifacts_to_stdout(0, 0); + + /* The explain-only flags causes this routine to list the artifacts + ** that would have been purged but to not actually make any changes + ** to the repository. + */ + if( purgeFlags & PURGE_EXPLAIN_ONLY ){ + db_end_transaction(0); + return 0; + } /* Make sure we are not removing a manifest that is the baseline of some ** manifest that is being left behind. This step is not strictly necessary. ** is is just a safety check. */ if( purge_baseline_out_from_under_delta(zTab) ){ @@ -121,11 +140,11 @@ } db_finalize(&q); /* Construct the graveyard and copy the artifacts to be purged into the ** graveyard */ - if( moveToGraveyard ){ + if( purgeFlags & PURGE_MOVETO_GRAVEYARD ){ db_multi_exec(zPurgeInit /*works-like:"%w%w"*/, db_name("repository"), db_name("repository")); db_multi_exec( "INSERT INTO purgeevent(ctime,pnotes) VALUES(now(),%Q)", zNote ); @@ -189,10 +208,17 @@ db_finalize(&q); /* db_multi_exec("DROP TABLE \"%w_tickets\"", zTab); */ /* Mission accomplished */ db_end_transaction(0); + + if( purgeFlags & PURGE_PRINT_SUMMARY ){ + fossil_print("%d artifacts purged\n", + db_int(0, "SELECT count(*) FROM \"%w\";", zTab)); + fossil_print("undoable using \"%s purge undo %d\".\n", + g.nameOfExe, peid); + } return peid; } /* ** The TEMP table named zTab contains RIDs for a set of check-ins. @@ -220,11 +246,11 @@ /* ** The TEMP table named zTab contains the RIDs for a set of check-in ** artifacts. Expand this set (by adding new entries to zTab) to include -** all other artifacts that are used the set of check-ins in +** all other artifacts that are used by the check-ins in ** the original list. ** ** If the bExclusive flag is true, then the set is only expanded by ** artifacts that are used exclusively by the check-ins in the set. ** When bExclusive is false, then all artifacts used by the check-ins @@ -426,60 +452,109 @@ /* ** COMMAND: purge ** ** The purge command removes content from a repository and stores that content ** in a "graveyard". The graveyard exists so that content can be recovered -** using the "fossil purge undo" command. +** using the "fossil purge undo" command. The "fossil purge obliterate" +** command empties the graveyard, making the content unrecoverable. +** +** ==== WARNING: This command can potentially destroy historical data and ==== +** ==== leave your repository in a goofy state. Know what you are doing! ==== +** ==== Make a backup of your repository before using this command! ==== +** +** ==== FURTHER WARNING: This command is a work-in-progress and may yet ==== +** ==== contains bugs. ==== +** +** fossil purge artifacts UUID... ?OPTIONS? +** +** Move arbitrary artifacts identified by the UUID list into the +** graveyard. ** ** fossil purge cat UUID... ** ** Write the content of one or more artifacts in the graveyard onto ** standard output. ** -** fossil purge ?checkins? TAGS... ?OPTIONS? +** fossil purge checkins TAGS... ?OPTIONS? ** -** Move the check-ins identified by TAGS and all of their descendants -** out of the repository and into the graveyard. The "checkins" -** subcommand keyword is optional and can be omitted as long as TAGS -** does not conflict with any other subcommand. -** +** Move the check-ins or branches identified by TAGS and all of +** their descendants out of the repository and into the graveyard. ** If TAGS includes a branch name then it means all the check-ins ** on the most recent occurrence of that branch. ** -** --explain Make no changes, but show what would happen. -** --dry-run Make no changes. +** fossil purge files NAME ... ?OPTIONS? +** +** Move all instances of files called NAME into the graveyard. +** NAME should be the name of the file relative to the root of the +** repository. If NAME is a directory, then all files within that +** directory are moved. ** ** fossil purge list|ls ?-l? ** ** Show the graveyard of prior purges. The -l option gives more ** detail in the output. ** -** fossil purge obliterate ID... +** fossil purge obliterate ID... ?--force? ** ** Remove one or more purge events from the graveyard. Once a purge -** event is obliterated, it can no longer be undone. +** event is obliterated, it can no longer be undone. The --force +** option suppresses the confirmation prompt. +** +** fossil purge tickets NAME ... ?OPTIONS? +** +** TBD... ** ** fossil purge undo ID ** ** Restore the content previously removed by purge ID. ** +** fossil purge wiki NAME ... ?OPTIONS? +** +** TBD... +** +** COMMON OPTIONS: +** +** --explain Make no changes, but show what would happen. +** --dry-run An alias for --explain +** ** SUMMARY: +** fossil purge artifacts UUID.. [OPTIONS] ** fossil purge cat UUID... -** fossil purge [checkins] TAGS... [--explain] +** fossil purge checkins TAGS... [OPTIONS] +** fossil purge files FILENAME... [OPTIONS] ** fossil purge list ** fossil purge obliterate ID... +** fossil purge tickets NAME... [OPTIONS] ** fossil purge undo ID +** fossil purge wiki NAME... [OPTIONS] */ void purge_cmd(void){ + int purgeFlags = PURGE_MOVETO_GRAVEYARD | PURGE_PRINT_SUMMARY; const char *zSubcmd; int n; + int i; Stmt q; + if( g.argc<3 ) usage("SUBCOMMAND ?ARGS?"); zSubcmd = g.argv[2]; db_find_and_open_repository(0,0); n = (int)strlen(zSubcmd); - if( strncmp(zSubcmd, "cat", n)==0 ){ + if( find_option("explain",0,0)!=0 || find_option("dry-run",0,0)!=0 ){ + purgeFlags |= PURGE_EXPLAIN_ONLY; + } + if( strncmp(zSubcmd, "artifacts", n)==0 ){ + verify_all_options(); + db_begin_transaction(); + db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)"); + for(i=3; i=g.argc ) usage("[checkin] TAGS... [--explain]"); - db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)"); - for(; i