-C zap\strailing\swhitespace
-D 2021-11-01T22:33:20.802
+C Add\sglobbing\soption\sto\sshell's\s.archive\scommand.
+D 2021-11-02T00:18:11.885
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 74dc1a088b1840b89615e99da33c3419f2808ce213f809006accce890c1ed99b
+F src/shell.c.in 9e3b9543d26a0c3eef9ad0408d4cd78bff5e2af57820d11617a5c1e8c8ab984d
F src/sqlite.h.in 99786216caf1c57aa3d70f95a7f84566dff6a9eeb50174799ea3b387eafd2a22
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h d8f6f67ae9ad990a70dd03c093bcdc8883e159ff4bfd16a496f8fb80c6840b5a
F test/shell5.test 6e4aa0e531dcb8dcf74b7920a2a7442c6712d4dff8422bbc81f768f9dee8a0e3
F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3
F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f
-F test/shell8.test b109236471b68749b0dd23d075626373397e609562a3f4c49548a4c971ef105b
+F test/shell8.test 388471d16e4de767333107e30653983f186232c0e863f4490bb230419e830aae
F test/shmlock.test 3dbf017d34ab0c60abe6a44e447d3552154bd0c87b41eaf5ceacd408dd13fda5
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 978d5ed4379b631a79cd46a75d9b5b403f3ec4ce7d9d52ed36a5678cdf04f7f2
-R aa5d515bd539d5a906c526319f66022b
+P f2a908e9c86efb11bb179ce7121f0d510f952284891abfa69517b773fd88324c
+R eecc379f0265e2d49eed240d5e55a92c
U larrybr
-Z 19de7df3053f6a11c3c0364e259c1387
+Z d62c3b222b587fc248ac413fb1d62a07
" -f FILE, --file FILE Use archive FILE (default is current db)",
" -a FILE, --append FILE Open FILE using the apndvfs VFS",
" -C DIR, --directory DIR Read/extract files from directory DIR",
+ " -g, --glob Use glob matching for names in archive",
" -n, --dryrun Show the SQL that would have occurred",
" Examples:",
" .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar",
u8 bZip; /* True if the archive is a ZIP */
u8 bDryRun; /* True if --dry-run */
u8 bAppend; /* True if --append */
+ u8 bGlob; /* True if --glob */
u8 fromCmdLine; /* Run from -A instead of .archive */
int nArg; /* Number of command arguments */
char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
#define AR_SWITCH_DIRECTORY 10
#define AR_SWITCH_APPEND 11
#define AR_SWITCH_DRYRUN 12
+#define AR_SWITCH_GLOB 13
static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
switch( eSwitch ){
case AR_SWITCH_DRYRUN:
pAr->bDryRun = 1;
break;
+ case AR_SWITCH_GLOB:
+ pAr->bGlob = 1;
+ break;
case AR_SWITCH_VERBOSE:
pAr->bVerbose = 1;
break;
{ "append", 'a', AR_SWITCH_APPEND, 1 },
{ "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
{ "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
+ { "glob", 'g', AR_SWITCH_GLOB, 0 },
};
int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
struct ArSwitch *pEnd = &aSwitch[nSwitch];
/*
** This function assumes that all arguments within the ArCommand.azArg[]
** 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
+** 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.
+** in the archive, SQLITE_OK is returned. Here, "present" means either an
+** exact equality when pAr->bGlob is false or a "name GLOB pattern" match
+* when pAr->bGlob is true.
**
** This function strips any trailing '/' characters from each argument.
** This is consistent with the way the [tar] command seems to work on
if( pAr->nArg ){
int i, j;
sqlite3_stmt *pTest = 0;
+ const char *zSel = (pAr->bGlob)
+ ? "SELECT name FROM %s WHERE glob($name,name)"
+ : "SELECT name FROM %s WHERE name=$name";
- shellPreparePrintf(pAr->db, &rc, &pTest,
- "SELECT name FROM %s WHERE name=$name",
- pAr->zSrcTable
- );
+ shellPreparePrintf(pAr->db, &rc, &pTest, zSel, pAr->zSrcTable);
j = sqlite3_bind_parameter_index(pTest, "$name");
for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
char *z = pAr->azArg[i];
** identify all archive members that match the command arguments held
** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning.
** The caller is responsible for eventually calling sqlite3_free() on
-** any non-NULL (*pzWhere) value.
+** any non-NULL (*pzWhere) value. Here, "match" means strict equality
+** when pAr->bGlob is false and GLOB match when pAr->bGlob is true.
*/
static void arWhereClause(
int *pRc,
- ArCommand *pAr,
+ ArCommand *pAr,
char **pzWhere /* OUT: New WHERE clause */
){
char *zWhere = 0;
+ const char *zSameOp = (pAr->bGlob)? "GLOB" : "=";
if( *pRc==SQLITE_OK ){
if( pAr->nArg==0 ){
zWhere = sqlite3_mprintf("1");
for(i=0; i<pAr->nArg; i++){
const char *z = pAr->azArg[i];
zWhere = sqlite3_mprintf(
- "%z%s name = '%q' OR substr(name,1,%d) = '%q/'",
- zWhere, zSep, z, strlen30(z)+1, z
+ "%z%s name %s '%q' OR substr(name,1,%d) %s '%q/'",
+ zWhere, zSep, zSameOp, z, strlen30(z)+1, zSameOp, z
);
if( zWhere==0 ){
*pRc = SQLITE_NOMEM;