Improve parsing of ".ar" commands. Add new test file for the same.
FossilOrigin-Name: 840401cc8ce3a09e0663b46973ecd2856d9607be71d2d1e9b21f7df7a82dcbe5
This commit is contained in:
parent
25c1218e73
commit
88be020916
13
manifest
13
manifest
@ -1,5 +1,5 @@
|
||||
C Add\sthe\s".ar\sx"\scommand\sto\sthe\sshell.\sFor\sextracting\sthe\scontents\sof\ssqlar\narchives.
|
||||
D 2017-12-07T21:03:33.903
|
||||
C Improve\sparsing\sof\s".ar"\scommands.\sAdd\snew\stest\sfile\sfor\sthe\ssame.
|
||||
D 2017-12-09T17:58:02.648
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F Makefile.in 6a879cbf01e37f9eac131414955f71774b566502d9a57ded1b8585b507503cb8
|
||||
@ -474,7 +474,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
|
||||
F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730
|
||||
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
|
||||
F src/select.c 17e220191860a64a18c084141e1a8b7309e166a6f2d42c02021af27ea080d157
|
||||
F src/shell.c.in 2f9ae0bee09bdd35922ab7ed264d88e1d7fb34d39d37fc633e6a3a1af60036be
|
||||
F src/shell.c.in 907661eeab82949420270b24f5989a399242cb8721e6140f73b3a46939fc4820
|
||||
F src/sqlite.h.in 8fd97993d48b50b9bade38c52f12d175942c9497c960905610c7b03a3e4b5818
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34
|
||||
@ -1214,6 +1214,7 @@ F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d
|
||||
F test/shell5.test 23939a4c51f0421330ea61dbd3c74f9c215f5f8d3d1a94846da6ffc777a35458
|
||||
F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3
|
||||
F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f
|
||||
F test/shell8.test 98b1d7b218060e557b3a789f3396635a0c03873ea652b3154c7f3f238d4a1a8f
|
||||
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
|
||||
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
|
||||
F test/shrink.test 1b4330b1fd9e818c04726d45cb28db73087535ce
|
||||
@ -1681,7 +1682,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 c9827a01a6e107f38f85c2b2c1c7a599e443067b106217e965b6936441ca619d
|
||||
R 4b2bb930e9456062f8914cba7a04cf63
|
||||
P 0cc699d14adfe8c7b7be50c180186562861806c47425c80c935bce43ee5c5c12
|
||||
R 0b3e6167ae82d64c1e021b537a83d40a
|
||||
U dan
|
||||
Z 4726613d4458219c808274490c55a044
|
||||
Z 9b95380c27ad603c463b4469d523a6d2
|
||||
|
@ -1 +1 @@
|
||||
0cc699d14adfe8c7b7be50c180186562861806c47425c80c935bce43ee5c5c12
|
||||
840401cc8ce3a09e0663b46973ecd2856d9607be71d2d1e9b21f7df7a82dcbe5
|
177
src/shell.c.in
177
src/shell.c.in
@ -4116,10 +4116,124 @@ static void shellReset(
|
||||
if( *pRc==SQLITE_OK ) *pRc = rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Structure representing a single ".ar" command.
|
||||
*/
|
||||
typedef struct ArCommand ArCommand;
|
||||
struct ArCommand {
|
||||
int eCmd; /* An AR_CMD_* value */
|
||||
const char *zFile; /* --file argument, or NULL */
|
||||
const char *zDir; /* --directory argument, or NULL */
|
||||
int bVerbose; /* True if --verbose */
|
||||
int nArg; /* Number of command arguments */
|
||||
char **azArg; /* Array of command arguments */
|
||||
};
|
||||
|
||||
/*
|
||||
** 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");
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
** Values for ArCommand.eCmd.
|
||||
*/
|
||||
#define AR_CMD_CREATE 1
|
||||
#define AR_CMD_EXTRACT 2
|
||||
#define AR_CMD_LIST 3
|
||||
#define AR_CMD_UPDATE 4
|
||||
|
||||
/*
|
||||
** Parse the command line for an ".ar" command. The results are written into
|
||||
** structure (*pAr). SQLITE_OK is returned if the command line is parsed
|
||||
** successfully, otherwise an error message is written to stderr and
|
||||
** SQLITE_ERROR returned.
|
||||
*/
|
||||
static int arParseCommand(
|
||||
char **azArg, /* Array of arguments passed to dot command */
|
||||
int nArg, /* Number of entries in azArg[] */
|
||||
ArCommand *pAr /* Populate this object */
|
||||
){
|
||||
if( nArg<=1 ){
|
||||
return arUsage();
|
||||
}else{
|
||||
char *z = azArg[1];
|
||||
memset(pAr, 0, sizeof(ArCommand));
|
||||
|
||||
if( z[0]!='-' ){
|
||||
/* Traditional style [tar] invocation */
|
||||
int i;
|
||||
int iArg = 2;
|
||||
for(i=0; z[i]; i++){
|
||||
switch( z[i] ){
|
||||
case 'c':
|
||||
if( pAr->eCmd ) return arUsage();
|
||||
pAr->eCmd = AR_CMD_CREATE;
|
||||
break;
|
||||
case 'x':
|
||||
if( pAr->eCmd ) return arUsage();
|
||||
pAr->eCmd = AR_CMD_EXTRACT;
|
||||
break;
|
||||
case 't':
|
||||
if( pAr->eCmd ) return arUsage();
|
||||
pAr->eCmd = AR_CMD_LIST;
|
||||
break;
|
||||
case 'u':
|
||||
if( pAr->eCmd ) return arUsage();
|
||||
pAr->eCmd = AR_CMD_UPDATE;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
pAr->bVerbose = 1;
|
||||
break;
|
||||
case 'f':
|
||||
if( iArg>=nArg ) return arUsage();
|
||||
pAr->zFile = azArg[iArg++];
|
||||
break;
|
||||
case 'C':
|
||||
if( iArg>=nArg ) return arUsage();
|
||||
pAr->zDir = azArg[iArg++];
|
||||
break;
|
||||
|
||||
default:
|
||||
return arUsage();
|
||||
}
|
||||
}
|
||||
|
||||
pAr->nArg = nArg-iArg;
|
||||
if( pAr->nArg>0 ){
|
||||
pAr->azArg = &azArg[iArg];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of .ar "Update" command.
|
||||
*/
|
||||
static int arUpdateCmd(ShellState *p, ArCommand *pAr){
|
||||
raw_printf(stderr, "todo...\n");
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of .ar "lisT" command.
|
||||
*/
|
||||
static int arListCommand(ShellState *p, ArCommand *pAr){
|
||||
raw_printf(stderr, "todo...\n");
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Implementation of .ar "eXtract" command.
|
||||
*/
|
||||
static int arExtractCommand(ShellState *p, int bVerbose){
|
||||
static int arExtractCommand(ShellState *p, ArCommand *pAr){
|
||||
const char *zSql1 =
|
||||
"SELECT name, writefile(name, "
|
||||
"CASE WHEN (data AND sz>=0 AND sz!=length(data)) THEN uncompress(data) "
|
||||
@ -4136,7 +4250,7 @@ static int arExtractCommand(ShellState *p, int bVerbose){
|
||||
|
||||
shellPrepare(p, &rc, zSql1, &pSql);
|
||||
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
|
||||
if( bVerbose ){
|
||||
if( pAr->bVerbose ){
|
||||
raw_printf(stdout, "%s\n", sqlite3_column_text(pSql, 0));
|
||||
}
|
||||
}
|
||||
@ -4167,9 +4281,7 @@ static int arExtractCommand(ShellState *p, int bVerbose){
|
||||
*/
|
||||
static int arCreateCommand(
|
||||
ShellState *p, /* Shell state pointer */
|
||||
char **azFile, /* Array of files to add to archive */
|
||||
int nFile, /* Number of entries in azFile[] */
|
||||
int bVerbose /* True to be verbose on stdout */
|
||||
ArCommand *pAr /* Command arguments and options */
|
||||
){
|
||||
const char *zSql =
|
||||
"WITH f(n, m, t, d) AS ("
|
||||
@ -4204,8 +4316,8 @@ static int arCreateCommand(
|
||||
shellPrepare(p, &rc, zInsert, &pInsert);
|
||||
shellPrepare(p, &rc, zSql, &pStmt);
|
||||
|
||||
for(i=0; i<nFile && rc==SQLITE_OK; i++){
|
||||
sqlite3_bind_text(pStmt, 1, azFile[i], -1, SQLITE_STATIC);
|
||||
for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
|
||||
sqlite3_bind_text(pStmt, 1, pAr->azArg[i], -1, SQLITE_STATIC);
|
||||
sqlite3_bind_int(pStmt, 2, S_IFDIR);
|
||||
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
int sz;
|
||||
@ -4213,7 +4325,7 @@ static int arCreateCommand(
|
||||
int mode = sqlite3_column_int(pStmt, 1);
|
||||
unsigned int mtime = sqlite3_column_int(pStmt, 2);
|
||||
|
||||
if( bVerbose ){
|
||||
if( pAr->bVerbose ){
|
||||
raw_printf(stdout, "%s\n", zName);
|
||||
}
|
||||
|
||||
@ -4280,38 +4392,31 @@ static int arDotCommand(
|
||||
char **azArg, /* Array of arguments passed to dot command */
|
||||
int nArg /* Number of entries in azArg[] */
|
||||
){
|
||||
int bVerbose = 0;
|
||||
char cmd = 0;
|
||||
int i;
|
||||
int n1;
|
||||
if( nArg<=1 ) goto usage;
|
||||
ArCommand cmd;
|
||||
int rc;
|
||||
rc = arParseCommand(azArg, nArg, &cmd);
|
||||
if( rc==SQLITE_OK ){
|
||||
switch( cmd.eCmd ){
|
||||
case AR_CMD_CREATE:
|
||||
rc = arCreateCommand(pState, &cmd);
|
||||
break;
|
||||
|
||||
n1 = strlen(azArg[1]);
|
||||
for(i=0; i<n1; i++){
|
||||
char c = azArg[1][i];
|
||||
if( c=='c' || c=='x' ){
|
||||
if( cmd ) goto usage;
|
||||
cmd = c;
|
||||
}
|
||||
else if( c=='v' ){
|
||||
bVerbose = 1;
|
||||
}else{
|
||||
goto usage;
|
||||
case AR_CMD_EXTRACT:
|
||||
rc = arExtractCommand(pState, &cmd);
|
||||
break;
|
||||
|
||||
case AR_CMD_LIST:
|
||||
rc = arListCommand(pState, &cmd);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert( cmd.eCmd==AR_CMD_UPDATE );
|
||||
rc = arUpdateCmd(pState, &cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( cmd=='c' ){
|
||||
return arCreateCommand(pState, &azArg[2], nArg-2, bVerbose);
|
||||
}
|
||||
|
||||
if( cmd=='x' ){
|
||||
if( nArg!=2 ) goto usage;
|
||||
return arExtractCommand(pState, bVerbose);
|
||||
}
|
||||
|
||||
usage:
|
||||
raw_printf(stderr, "Usage %s sub-command ?args...?\n", azArg[0]);
|
||||
return SQLITE_ERROR;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
83
test/shell8.test
Normal file
83
test/shell8.test
Normal file
@ -0,0 +1,83 @@
|
||||
# 2017 December 9
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Test the shell tool ".ar" command.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix shell8
|
||||
set CLI [test_find_cli]
|
||||
|
||||
proc populate_dir {dirname spec} {
|
||||
# First delete the current tree, if one exists.
|
||||
file delete -force $dirname
|
||||
|
||||
# Recreate the root of the new tree.
|
||||
file mkdir $dirname
|
||||
|
||||
# Add each file to the new tree.
|
||||
foreach {f d} $spec {
|
||||
set path [file join $dirname $f]
|
||||
file mkdir [file dirname $path]
|
||||
set fd [open $path w]
|
||||
puts -nonewline $fd $d
|
||||
close $fd
|
||||
}
|
||||
}
|
||||
|
||||
proc dir_to_list {dirname} {
|
||||
set res [list]
|
||||
foreach f [glob -nocomplain $dirname/*] {
|
||||
set mtime [file mtime $f]
|
||||
set perm [file attributes $f -perm]
|
||||
set relpath [file join {*}[lrange [file split $f] 1 end]]
|
||||
lappend res
|
||||
if {[file isdirectory $f]} {
|
||||
lappend res [list $relpath / $mtime $perm]
|
||||
lappend res {*}[dir_to_list $f]
|
||||
} else {
|
||||
set fd [open $f]
|
||||
set data [read $fd]
|
||||
close $fd
|
||||
lappend res [list $relpath $data $mtime $perm]
|
||||
}
|
||||
}
|
||||
lsort $res
|
||||
}
|
||||
|
||||
proc dir_compare {d1 d2} {
|
||||
set l1 [dir_to_list $d1]
|
||||
set l2 [dir_to_list $d1]
|
||||
string compare $l1 $l2
|
||||
}
|
||||
|
||||
populate_dir ar1 {
|
||||
file1 "abcd"
|
||||
file2 "efgh"
|
||||
dir1/file3 "ijkl"
|
||||
}
|
||||
|
||||
set expected [dir_to_list ar1]
|
||||
# puts "# $expected"
|
||||
do_test 1.1 {
|
||||
forcedelete test_ar.db
|
||||
|
||||
catchcmd test_ar.db ".ar c ar1"
|
||||
file delete -force ar1
|
||||
catchcmd test_ar.db ".ar x"
|
||||
|
||||
dir_to_list ar1
|
||||
} $expected
|
||||
|
||||
|
||||
|
||||
finish_test
|
Loading…
x
Reference in New Issue
Block a user