From: drh Date: Mon, 25 Mar 2019 14:24:19 +0000 (+0000) Subject: For the ".archive --update" command in the CLI, only update files if their X-Git-Tag: version-3.28.0~97 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b17ea9123063ef103e177f0578394f951b3524d8;p=thirdparty%2Fsqlite.git For the ".archive --update" command in the CLI, only update files if their mtime or mode has changed. To force an update, use the new --insert instead. FossilOrigin-Name: 191a023ae708490eca61b3a42a3df41bb6709079f3905881abb82ebd46182607 --- diff --git a/manifest b/manifest index 96ae5513c2..ea0eb78148 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C We\slearn\sthat\sreaddir_r()\sis\sdeprecated\sin\sfavor\sof\splain\sold\sreaddir(),\swhich\nis\snow\ssuppose\sto\sbe\sthreadsafe\susing\sthread-local\sstorage.\s\sSo\sremove\sthe\nuse\sof\sreaddir_r()\sfrom\sthe\stest\scode.\s\s(SQLite\sitself\snever\scalls\sreaddir()\nor\sreaddir_r()). -D 2019-03-22T13:53:25.635 +C For\sthe\s".archive\s--update"\scommand\sin\sthe\sCLI,\sonly\supdate\sfiles\sif\stheir\nmtime\sor\smode\shas\schanged.\s\sTo\sforce\san\supdate,\suse\sthe\snew\s--insert\sinstead. +D 2019-03-25T14:24:19.101 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -517,7 +517,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 09419ad5c432190b69be7c0c326e03abb548a97c2c50675b81b459e1b382d1d2 F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93 F src/select.c 9263f5c30dd44c7ac2eb29f40a7ec64322a96885b71c00de6bc30b756c2e1c49 -F src/shell.c.in 576ba793cf166ea7055b7a1a2bea058242ca532ba84753e789b9c88790019b70 +F src/shell.c.in 652ba411c798b64a0c71079e16b022b6cd530a4c1161e220e4cd8a0a127dba60 F src/sqlite.h.in e33a4df7e32d742aac29623b38a1edd7e07a2b964a5d0257e2923c8a724faddc F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 960f1b86c3610fa23cb6a267572a97dcf286e77aa0dd3b9b23292ffaa1ea8683 @@ -1807,7 +1807,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P b99f8512c06b9d47e48b028781265512ce8b812ae4e6af0a7139a093cf9a8f74 -R 721d1f8fcb0f28693679b1b90e33dd94 +P 7a0a26ed380dd0bdda50b0204b30b53bbbbc70f278eba02f91541ac6c691aef2 +R e5d0aae7927eed4a86cf78b0bf846424 U drh -Z 1ebe3d96da2eb6b085008de1980229a2 +Z 1d4ed68130e2fc4467c4c956c87b0a62 diff --git a/manifest.uuid b/manifest.uuid index 2611c359a0..1994a59352 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7a0a26ed380dd0bdda50b0204b30b53bbbbc70f278eba02f91541ac6c691aef2 \ No newline at end of file +191a023ae708490eca61b3a42a3df41bb6709079f3905881abb82ebd46182607 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 007d9bb0be..c8fd3ae889 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -3452,7 +3452,8 @@ static const char *(azHelp[]) = { ".archive ... Manage SQL archives", " Each command must have exactly one of the following options:", " -c, --create Create a new archive", - " -u, --update Update or add files to an existing archive", + " -u, --update Add files or update files with newer mtime", + " -i, --insert Like -u but always add even if mtime unchanged", " -t, --list List contents of archive", " -x, --extract Extract files from archive", " Optional arguments:", @@ -5387,19 +5388,20 @@ static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){ ** Values for ArCommand.eCmd. */ #define AR_CMD_CREATE 1 -#define AR_CMD_EXTRACT 2 -#define AR_CMD_LIST 3 -#define AR_CMD_UPDATE 4 -#define AR_CMD_HELP 5 +#define AR_CMD_UPDATE 2 +#define AR_CMD_INSERT 3 +#define AR_CMD_EXTRACT 4 +#define AR_CMD_LIST 5 +#define AR_CMD_HELP 6 /* ** Other (non-command) switches. */ -#define AR_SWITCH_VERBOSE 6 -#define AR_SWITCH_FILE 7 -#define AR_SWITCH_DIRECTORY 8 -#define AR_SWITCH_APPEND 9 -#define AR_SWITCH_DRYRUN 10 +#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 static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){ switch( eSwitch ){ @@ -5407,6 +5409,7 @@ static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){ case AR_CMD_EXTRACT: case AR_CMD_LIST: case AR_CMD_UPDATE: + case AR_CMD_INSERT: case AR_CMD_HELP: if( pAr->eCmd ){ return arErrorMsg(pAr, "multiple command options"); @@ -5453,6 +5456,7 @@ static int arParseCommand( } aSwitch[] = { { "create", 'c', AR_CMD_CREATE, 0 }, { "extract", 'x', AR_CMD_EXTRACT, 0 }, + { "insert", 'i', AR_CMD_INSERT, 0 }, { "list", 't', AR_CMD_LIST, 0 }, { "update", 'u', AR_CMD_UPDATE, 0 }, { "help", 'h', AR_CMD_HELP, 0 }, @@ -5788,7 +5792,12 @@ static int arExecSql(ArCommand *pAr, const char *zSql){ /* -** Implementation of .ar "create" and "update" commands. +** Implementation of .ar "create", "insert", and "update" commands. +** +** create -> Create a new SQL archive +** insert -> Insert or reinsert all files listed +** update -> Insert files that have changed or that were not +** previously in the archive ** ** Create the "sqlar" table in the database if it does not already exist. ** Then add each file in the azFile[] array to the archive. Directories @@ -5796,11 +5805,14 @@ static int arExecSql(ArCommand *pAr, const char *zSql){ ** printed on stdout for each file archived. ** ** The create command is the same as update, except that it drops -** any existing "sqlar" table before beginning. +** any existing "sqlar" table before beginning. The "insert" command +** always overwrites every file named on the command-line, where as +** "update" only overwrites if the size or mtime or mode has changed. */ static int arCreateOrUpdateCommand( ArCommand *pAr, /* Command arguments and options */ - int bUpdate /* true for a --create. false for --update */ + int bUpdate, /* true for a --create. */ + int bOnlyIfChanged /* Only update if file has changed */ ){ const char *zCreate = "CREATE TABLE IF NOT EXISTS sqlar(\n" @@ -5822,22 +5834,24 @@ static int arCreateOrUpdateCommand( " WHEN 'd' THEN 0\n" " ELSE -1 END,\n" " sqlar_compress(data)\n" - " FROM fsdir(%Q,%Q)\n" - " WHERE lsmode(mode) NOT LIKE '?%%';", + " FROM fsdir(%Q,%Q) AS disk\n" + " WHERE lsmode(mode) NOT LIKE '?%%'%s;" + , "REPLACE INTO %s(name,mode,mtime,data)\n" " SELECT\n" " %s,\n" " mode,\n" " mtime,\n" " data\n" - " FROM fsdir(%Q,%Q)\n" - " WHERE lsmode(mode) NOT LIKE '?%%';" + " FROM fsdir(%Q,%Q) AS disk\n" + " WHERE lsmode(mode) NOT LIKE '?%%'%s;" }; int i; /* For iterating through azFile[] */ int rc; /* Return code */ const char *zTab = 0; /* SQL table into which to insert */ char *zSql; char zTemp[50]; + char *zExists = 0; arExecSql(pAr, "PRAGMA page_size=512"); rc = arExecSql(pAr, "SAVEPOINT ar;"); @@ -5868,10 +5882,21 @@ static int arCreateOrUpdateCommand( } rc = arExecSql(pAr, zCreate); } + if( bOnlyIfChanged ){ + zExists = sqlite3_mprintf( + " AND NOT EXISTS(" + "SELECT 1 FROM %s AS mem" + " WHERE mem.name=disk.name" + " AND mem.mtime=disk.mtime" + " AND mem.mode=disk.mode)", zTab); + }else{ + zExists = sqlite3_mprintf(""); + } + if( zExists==0 ) rc = SQLITE_NOMEM; for(i=0; inArg && rc==SQLITE_OK; i++){ char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab, pAr->bVerbose ? "shell_putsnl(name)" : "name", - pAr->azArg[i], pAr->zDir); + pAr->azArg[i], pAr->zDir, zExists); rc = arExecSql(pAr, zSql2); sqlite3_free(zSql2); } @@ -5886,6 +5911,7 @@ end_ar_transaction: sqlite3_free(zSql); } } + sqlite3_free(zExists); return rc; } @@ -5924,7 +5950,8 @@ static int arDotCommand( }else if( cmd.zFile ){ int flags; if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS; - if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_UPDATE ){ + if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT + || cmd.eCmd==AR_CMD_UPDATE ){ flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE; }else{ flags = SQLITE_OPEN_READONLY; @@ -5961,7 +5988,7 @@ static int arDotCommand( switch( cmd.eCmd ){ case AR_CMD_CREATE: - rc = arCreateOrUpdateCommand(&cmd, 0); + rc = arCreateOrUpdateCommand(&cmd, 0, 0); break; case AR_CMD_EXTRACT: @@ -5976,9 +6003,13 @@ static int arDotCommand( arUsage(pState->out); break; + case AR_CMD_INSERT: + rc = arCreateOrUpdateCommand(&cmd, 1, 0); + break; + default: assert( cmd.eCmd==AR_CMD_UPDATE ); - rc = arCreateOrUpdateCommand(&cmd, 1); + rc = arCreateOrUpdateCommand(&cmd, 1, 1); break; } }