]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Improve parsing of ".ar" commands. Add new test file for the same.
authordan <dan@noemail.net>
Sat, 9 Dec 2017 17:58:02 +0000 (17:58 +0000)
committerdan <dan@noemail.net>
Sat, 9 Dec 2017 17:58:02 +0000 (17:58 +0000)
FossilOrigin-Name: 840401cc8ce3a09e0663b46973ecd2856d9607be71d2d1e9b21f7df7a82dcbe5

manifest
manifest.uuid
src/shell.c.in
test/shell8.test [new file with mode: 0644]

index ab01f7195cc28cd3889532a7c5e4ef12c1f6d862..98adac2007aadde2c4b1192660728b8ea6f1da98 100644 (file)
--- a/manifest
+++ b/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
index 245ee49a8fa3fa341cae7b6f0f151734f7779554..d1e1c772f35fb085a3c39237610d6d14a7afa527 100644 (file)
@@ -1 +1 @@
-0cc699d14adfe8c7b7be50c180186562861806c47425c80c935bce43ee5c5c12
\ No newline at end of file
+840401cc8ce3a09e0663b46973ecd2856d9607be71d2d1e9b21f7df7a82dcbe5
\ No newline at end of file
index fe58460fe19637e19ccc8ba5934dcd4decc81391..b8471fea9fa3b943e45374ded75c9227855fcfe9 100644 (file)
@@ -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;
 
-  if( cmd=='c' ){
-    return arCreateCommand(pState, &azArg[2], nArg-2, bVerbose);
-  }
+      case AR_CMD_LIST:
+        rc = arListCommand(pState, &cmd);
+        break;
 
-  if( cmd=='x' ){
-    if( nArg!=2 ) goto usage;
-    return arExtractCommand(pState, bVerbose);
+      default:
+        assert( cmd.eCmd==AR_CMD_UPDATE );
+        rc = arUpdateCmd(pState, &cmd);
+        break;
+    }
   }
 
- usage:
-  raw_printf(stderr, "Usage %s sub-command ?args...?\n", azArg[0]);
-  return SQLITE_ERROR;
+  return rc;
 }
 
 
diff --git a/test/shell8.test b/test/shell8.test
new file mode 100644 (file)
index 0000000..4c412b4
--- /dev/null
@@ -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