-C The\sVVA()\smacro\sin\sjson1.c\smust\sbe\sactive\sduring\sSQLITE_COVERAGE_TEST\sbecause\nit\saffects\sthe\soutcome\sof\stestcase()\smacros.
-D 2021-11-01T12:53:01.613
+C Add\s--remove\ssubcommand\sto\sshell's\s.archive\scommand
+D 2021-11-01T17:22:52.884
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F src/resolve.c ae65c88f5d0d4bc0052b203773d407efa2387c2bd6b202f87178006c7bb8632c
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
F src/select.c 32d25b5af6c708aa63373c78c2e59681910387a7a78c08ec3086cadc77d41627
-F src/shell.c.in 185e4b905c3a399e9376597a04cf668f6f992513290978ac978cf4991954d89f
+F src/shell.c.in a91cf2a1e3987e769e2286c4835d3f18b3c2d21cc9405699d2e4a2b06dc65c20
F src/sqlite.h.in 99786216caf1c57aa3d70f95a7f84566dff6a9eeb50174799ea3b387eafd2a22
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h d8f6f67ae9ad990a70dd03c093bcdc8883e159ff4bfd16a496f8fb80c6840b5a
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P ca2703c339f76101f25051a2ed380398b018782883bfee68b5f2d69a1de9091a
-R 588c2ceaec3a392d5b7d700177ec9bbe
-U drh
-Z 9b594d25e284ecd39d9843606ef5aab4
+P 92c3d253797f9bde4670984d60bbd50b7b28540d2b5f503f318843580bab8765
+R b00d6d0ab1960f3d74e9a78eaa3a2c49
+T *branch * archive_remove
+T *sym-archive_remove *
+T -sym-trunk *
+U larrybr
+Z 7d1554c5ac914a1993ecf6506b6cbae4
" -c, --create Create a new archive",
" -u, --update Add or update files with changed mtime",
" -i, --insert Like -u but always add even if unchanged",
+ " -r, --remove Remove files from archive",
" -t, --list List contents of archive",
" -x, --extract Extract files from archive",
" Optional arguments:",
#define AR_CMD_EXTRACT 4
#define AR_CMD_LIST 5
#define AR_CMD_HELP 6
+#define AR_CMD_REMOVE 7
/*
** Other (non-command) switches.
*/
-#define AR_SWITCH_VERBOSE 7
-#define AR_SWITCH_FILE 8
-#define AR_SWITCH_DIRECTORY 9
-#define AR_SWITCH_APPEND 10
-#define AR_SWITCH_DRYRUN 11
+#define AR_SWITCH_VERBOSE 8
+#define AR_SWITCH_FILE 9
+#define AR_SWITCH_DIRECTORY 10
+#define AR_SWITCH_APPEND 11
+#define AR_SWITCH_DRYRUN 12
static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
switch( eSwitch ){
case AR_CMD_CREATE:
case AR_CMD_EXTRACT:
case AR_CMD_LIST:
+ case AR_CMD_REMOVE:
case AR_CMD_UPDATE:
case AR_CMD_INSERT:
case AR_CMD_HELP:
{ "extract", 'x', AR_CMD_EXTRACT, 0 },
{ "insert", 'i', AR_CMD_INSERT, 0 },
{ "list", 't', AR_CMD_LIST, 0 },
+ { "remove", 'r', AR_CMD_REMOVE, 0 },
{ "update", 'u', AR_CMD_UPDATE, 0 },
{ "help", 'h', AR_CMD_HELP, 0 },
{ "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
/*
** This function assumes that all arguments within the ArCommand.azArg[]
-** array refer to archive members, as for the --extract or --list commands.
-** It checks that each of them are present. If any specified file is not
-** present in the archive, an error is printed to stderr and an error
-** code returned. Otherwise, if all specified arguments are present in
-** the archive, SQLITE_OK is returned.
+** array refer to archive members, as for the --extract, --list or --remove
+** commands. It checks that each of them are present. If any specified file
+** is not present in the archive, an error is printed to stderr and an
+** error code returned. Otherwise, if all specified arguments are present
+** in the archive, SQLITE_OK is returned.
**
** This function strips any trailing '/' characters from each argument.
** This is consistent with the way the [tar] command seems to work on
}
+/*
+** Implementation of .ar "Remove" command.
+*/
+static int arRemoveCommand(ArCommand *pAr){
+ int rc;
+ char *zSql = 0;
+ char *zWhere = 0;
+
+ if( pAr->nArg ){
+ /* Verify that args actually exist within the archive before proceeding.
+ ** And formulate a WHERE clause to match them. */
+ rc = arCheckEntries(pAr);
+ arWhereClause(&rc, pAr, &zWhere);
+ }
+ if( rc==SQLITE_OK ){
+ zSql = sqlite3_mprintf("DELETE FROM %s WHERE %s;",
+ pAr->zSrcTable, zWhere);
+ if( pAr->bDryRun ){
+ utf8_printf(pAr->p->out, "%s\n", zSql);
+ }else{
+ char *zErr = 0;
+ rc = sqlite3_exec(pAr->db, "SAVEPOINT ar;", 0, 0, 0);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
+ if( rc!=SQLITE_OK ){
+ sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
+ }else{
+ rc = sqlite3_exec(pAr->db, "RELEASE ar;", 0, 0, 0);
+ }
+ }
+ if( zErr ){
+ utf8_printf(stdout, "ERROR: %s\n", zErr);
+ sqlite3_free(zErr);
+ }
+ }
+ }
+ sqlite3_free(zWhere);
+ sqlite3_free(zSql);
+ return rc;
+}
+
/*
** Implementation of .ar "eXtract" command.
*/
int flags;
if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT
- || cmd.eCmd==AR_CMD_UPDATE ){
+ || cmd.eCmd==AR_CMD_REMOVE || cmd.eCmd==AR_CMD_UPDATE ){
flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
}else{
flags = SQLITE_OPEN_READONLY;
rc = arCreateOrUpdateCommand(&cmd, 1, 0);
break;
+ case AR_CMD_REMOVE:
+ rc = arRemoveCommand(&cmd);
+ break;
+
default:
assert( cmd.eCmd==AR_CMD_UPDATE );
rc = arCreateOrUpdateCommand(&cmd, 1, 1);