-C Merge\slatest\strunk\schanges\sinto\sthis\sbranch.
-D 2017-12-14T13:55:01.572
+C Improve\serror\sand\susage\smessages\soutput\sby\sthe\sshell\s".ar"\scommand.
+D 2017-12-14T15:40:42.931
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in 6a879cbf01e37f9eac131414955f71774b566502d9a57ded1b8585b507503cb8
F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
F src/select.c 17e220191860a64a18c084141e1a8b7309e166a6f2d42c02021af27ea080d157
-F src/shell.c.in 12313c0500b9b1958507d3a432c192f73f86da112f0f37467636530696d13152
+F src/shell.c.in 4bdd2efe722005180365698f2a3de51e22ae1e9bb61c868006bc8f2c5e02eb98
F src/sqlite.h.in 364515dd186285f3c01f5cab42e7db7edc47c70e87b6a25de389a2e6b8c413fd
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 825e3c037b03fc09d581aeda0193ff1d4062404414c7354cb649f99aa9022d25 3765aaf712998af5ffb6bc680a0c1419f2b5deb47ecbc1835ba5879127c4dbe3
-R bf083f80c8163c105f680457377723eb
+P 803156cba8b056a1cb8d1bb186a57454afe72341abe7de1dfe529234c3415cd2
+R 69895ee1194373ab4ba11578d798fe26
U dan
-Z 36133c008e2dcaa09c3c6c120c31dee9
+Z 5ea750b0cf239f9442948a3eda934166
/*
** Print a usage message for the .ar command to stderr and return SQLITE_ERROR.
*/
-static int arUsage(void){
- /* todo */
- raw_printf(stderr, "error in .ar command line\n");
+static int arUsage(FILE *f){
+ raw_printf(f,
+"\n"
+"Usage: .ar [OPTION...] [FILE...]\n"
+"The .ar command manages sqlar archives.\n"
+"\n"
+"Examples:\n"
+" .ar -cf archive.sar foo bar # Create archive.sar from files foo and bar\n"
+" .ar -tf archive.sar # List members of archive.sar\n"
+" .ar -xvf archive.sar # Verbosely extract files from archive.sar\n"
+"\n"
+"Each command line must feature exactly one command option:\n"
+" -c, --create Create a new archive\n"
+" -u, --update Update or add files to an existing archive\n"
+" -t, --list List contents of archive\n"
+" -x, --extract Extract files from archive\n"
+"\n"
+"And zero or more optional options:\n"
+" -v, --verbose Print each filename as it is processed\n"
+" -f FILE, --file FILE Operate on archive FILE (default is current db)\n"
+" -C DIR, --directory DIR Change to directory DIR to read/extract files\n"
+"\n"
+"See also: http://sqlite.org/cli.html#sqlar_archive_support\n"
+"\n"
+);
+ return SQLITE_ERROR;
+}
+
+/*
+** Print an error message for the .ar command to stderr and return
+** SQLITE_ERROR.
+*/
+static int arErrorMsg(const char *zFmt, ...){
+ va_list ap;
+ char *z;
+ va_start(ap, zFmt);
+ z = sqlite3_vmprintf(zFmt, ap);
+ va_end(ap);
+ raw_printf(stderr, "Error: %s (try \".ar --help\")\n", z);
+ sqlite3_free(z);
return SQLITE_ERROR;
}
#define AR_CMD_EXTRACT 2
#define AR_CMD_LIST 3
#define AR_CMD_UPDATE 4
+#define AR_CMD_HELP 5
/*
** Other (non-command) switches.
*/
-#define AR_SWITCH_VERBOSE 5
-#define AR_SWITCH_FILE 6
-#define AR_SWITCH_DIRECTORY 7
+#define AR_SWITCH_VERBOSE 6
+#define AR_SWITCH_FILE 7
+#define AR_SWITCH_DIRECTORY 8
static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
switch( eSwitch ){
case AR_CMD_EXTRACT:
case AR_CMD_LIST:
case AR_CMD_UPDATE:
- if( pAr->eCmd ) return arUsage();
+ case AR_CMD_HELP:
+ if( pAr->eCmd ){
+ return arErrorMsg("multiple command options");
+ }
pAr->eCmd = eSwitch;
break;
{ 'x', "extract", AR_CMD_EXTRACT, 0 },
{ 't', "list", AR_CMD_LIST, 0 },
{ 'u', "update", AR_CMD_UPDATE, 0 },
+ { 'h', "help", AR_CMD_HELP, 0 },
{ 'v', "verbose", AR_SWITCH_VERBOSE, 0 },
{ 'f', "file", AR_SWITCH_FILE, 1 },
{ 'C', "directory", AR_SWITCH_DIRECTORY, 1 }
struct ArSwitch *pEnd = &aSwitch[nSwitch];
if( nArg<=1 ){
- return arUsage();
+ return arUsage(stderr);
}else{
char *z = azArg[1];
memset(pAr, 0, sizeof(ArCommand));
for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
if( z[i]==pOpt->cShort ) break;
}
- if( pOpt==pEnd ) return arUsage();
+ if( pOpt==pEnd ){
+ return arErrorMsg("unrecognized option: %c", z[i]);
+ }
if( pOpt->bArg ){
- if( iArg>=nArg ) return arUsage();
+ if( iArg>=nArg ){
+ return arErrorMsg("option requires an argument: %c",z[i]);
+ }
zArg = azArg[iArg++];
}
if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
if( z[i]==pOpt->cShort ) break;
}
- if( pOpt==pEnd ) return arUsage();
+ if( pOpt==pEnd ){
+ return arErrorMsg("unrecognized option: %c\n", z[i]);
+ }
if( pOpt->bArg ){
if( i<(n-1) ){
zArg = &z[i+1];
i = n;
}else{
- if( iArg>=(nArg-1) ) return arUsage();
+ if( iArg>=(nArg-1) ){
+ return arErrorMsg("option requires an argument: %c\n",z[i]);
+ }
zArg = azArg[++iArg];
}
}
const char *zLong = pOpt->zLong;
if( (n-2)<=strlen(zLong) && 0==memcmp(&z[2], zLong, n-2) ){
if( pMatch ){
- /* ambiguous option */
- return arUsage();
+ return arErrorMsg("ambiguous option: %s",z);
}else{
pMatch = pOpt;
}
}
if( pMatch==0 ){
- /* no such option. */
- return arUsage();
+ return arErrorMsg("unrecognized option: %s", z);
}
if( pMatch->bArg ){
- if( iArg>=(nArg-1) ) return arUsage();
+ if( iArg>=(nArg-1) ){
+ return arErrorMsg("option requires an argument: %s", z);
+ }
zArg = azArg[++iArg];
}
if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR;
}
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
if( pAr->bVerbose ){
- raw_printf(stdout, "%s\n", sqlite3_column_text(pSql, 0));
+ raw_printf(p->out, "%s\n", sqlite3_column_text(pSql, 0));
}
}
shellFinalize(&rc, pSql);
unsigned int mtime = sqlite3_column_int(pStmt, 2);
if( pAr->bVerbose ){
- raw_printf(stdout, "%s\n", zName);
+ raw_printf(p->out, "%s\n", zName);
}
sqlite3_bind_text(pInsert, 1, zName, -1, SQLITE_STATIC);
rc = arListCommand(pState, db, &cmd);
break;
+ case AR_CMD_HELP:
+ arUsage(pState->out);
+ break;
+
default:
assert( cmd.eCmd==AR_CMD_UPDATE );
rc = arUpdateCmd(pState, db, &cmd);