subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rhuij...@apache.org
Subject svn commit: r1660874 - in /subversion/trunk: ./ subversion/libsvn_wc/ tools/dev/wc-ng/
Date Thu, 19 Feb 2015 13:10:28 GMT
Author: rhuijben
Date: Thu Feb 19 13:10:27 2015
New Revision: 1660874

URL: http://svn.apache.org/r1660874
Log:
Make it easier to run the sql static verifications on a working copy
by creating a private api and adding a small helper tool using this
api.

If you need a typical example you could use
[[
$ svn-wc-db-tester svn-test-work/libsvn_wc/db-test/test_getting_info
J/J-e (depth=2) DBV0061: Moved to without target
K/K-b (depth=1) DBV0061: Moved to without target
svn-wc-db-tester: E155035: Found one or more potential wc.db inconsistencies
]]

* build.conf
  (svn-wc-db-tester): New tool.
  (__MORE__): Add new tools.
  (x509-parser): Add description.

* subversion/libsvn_wc/wc-checks.sql
  (STMT_STATIC_VERIFY): Extend. Separate id from message to support api.

* subversion/libsvn_wc/wc_db.c
  (svn_wc__db_verify_db_full_internal,
   svn_wc__db_verify_db_full): New functions.

* subversion/libsvn_wc/wc_db.h
  (svn_wc__db_verify_cb_t): New typedef.
  (svn_wc__db_verify_db_full): New function.

* subversion/libsvn_wc/wc_db_private.h
  (svn_wc__db_verify_db_full_internal): New function.

* subversion/libsvn_wc/wc_db_wcroot.c
  (verify_sqlite): Rename to...
  (verify_db_cb): ... this. Implement svn_wc__db_verify_cb_t.
  (close_wcroot): Update caller.

* tools/dev/wc-ng/svn-wc-db-tester.c
  New file, based on the svnraisetreeconflict code.

Added:
    subversion/trunk/tools/dev/wc-ng/svn-wc-db-tester.c   (with props)
Modified:
    subversion/trunk/build.conf
    subversion/trunk/subversion/libsvn_wc/wc-checks.sql
    subversion/trunk/subversion/libsvn_wc/wc_db.c
    subversion/trunk/subversion/libsvn_wc/wc_db.h
    subversion/trunk/subversion/libsvn_wc/wc_db_private.h
    subversion/trunk/subversion/libsvn_wc/wc_db_wcroot.c

Modified: subversion/trunk/build.conf
URL: http://svn.apache.org/viewvc/subversion/trunk/build.conf?rev=1660874&r1=1660873&r2=1660874&view=diff
==============================================================================
--- subversion/trunk/build.conf (original)
+++ subversion/trunk/build.conf Thu Feb 19 13:10:27 2015
@@ -1354,6 +1354,15 @@ libs = libsvn_wc libsvn_subr apriconv ap
 msvc-force-static = yes
 testing = skip
 
+[svn-wc-db-tester]
+type = exe
+path = tools/dev/wc-ng
+sources = svn-wc-db-tester.c
+install = test
+libs = libsvn_wc libsvn_subr apr
+msvc-force-static = yes
+testing = skip
+
 # ----------------------------------------------------------------------------
 #
 # EXTERNAL TARGETS (NO BUILD NEEDED)
@@ -1513,7 +1522,7 @@ type = project
 path = build/win32
 libs = __ALL_TESTS__
        diff diff3 diff4 fsfs-access-map svnauth 
-       svn-populate-node-origins-index
+       svn-populate-node-origins-index x509-parser svn-wc-db-tester
 
 [__LIBS__]
 type = project
@@ -1628,6 +1637,7 @@ libs = libsvn_wc libsvn_subr apriconv ap
 install = tools
 
 [x509-parser]
+description = Tool to verify x509 certificates
 type = exe
 path = tools/dev
 sources = x509-parser.c

Modified: subversion/trunk/subversion/libsvn_wc/wc-checks.sql
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc-checks.sql?rev=1660874&r1=1660873&r2=1660874&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-checks.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-checks.sql Thu Feb 19 13:10:27 2015
@@ -76,21 +76,25 @@ BEGIN
 END;
 
 -- STMT_STATIC_VERIFY
-/* A parent node must exist for every normal node except the root.
-   That node must exist at a lower or equal op-depth */
-SELECT local_relpath, op_depth, 'SV001: No ancestor in NODES'
+SELECT local_relpath, op_depth, 1, 'Invalid parent relpath set in NODES'
 FROM nodes n WHERE local_relpath != ''
- AND file_external IS NULL
- AND NOT EXISTS(SELECT 1 from nodes i
-                WHERE i.wc_id=n.wc_id
-                  AND i.local_relpath=n.parent_relpath
-                  AND i.op_depth <= n.op_depth)
+ AND (parent_relpath IS NULL
+      OR NOT IS_STRICT_DESCENDANT_OF(local_relpath, parent_relpath)
+      OR relpath_depth(local_relpath) != relpath_depth(parent_relpath)+1)
+
+UNION ALL
+
+SELECT local_relpath, -1, 2, 'Invalid parent relpath set in ACTUAL'
+FROM actual_node a WHERE local_relpath != ''
+ AND (parent_relpath IS NULL
+      OR NOT IS_STRICT_DESCENDANT_OF(local_relpath, parent_relpath)
+      OR relpath_depth(local_relpath) != relpath_depth(parent_relpath)+1)
 
 UNION ALL
 
 /* All ACTUAL nodes must have an equivalent NODE in NODES
    or be only one level deep (delete-delete tc) */
-SELECT local_relpath, -1, 'SV002: No ancestor in ACTUAL'
+SELECT local_relpath, -1, 10, 'No ancestor in ACTUAL'
 FROM actual_node a WHERE local_relpath != ''
  AND NOT EXISTS(SELECT 1 from nodes i
                 WHERE i.wc_id=a.wc_id
@@ -102,7 +106,7 @@ FROM actual_node a WHERE local_relpath !
 UNION ALL
 /* Verify if the ACTUAL data makes sense for the related node.
    Only conflict data is valid if there is none */
-SELECT a.local_relpath, -1, 'SV003: Bad or Unneeded actual data'
+SELECT a.local_relpath, -1, 11, 'Bad or Unneeded actual data'
 FROM actual_node a
 LEFT JOIN nodes n on n.wc_id = a.wc_id AND n.local_relpath = a.local_relpath
    AND n.op_depth = (SELECT MAX(op_depth) from nodes i
@@ -116,9 +120,21 @@ WHERE (a.properties IS NOT NULL
                   AND i.local_relpath=a.parent_relpath)
 
 UNION ALL
+
+/* A parent node must exist for every normal node except the root.
+   That node must exist at a lower or equal op-depth */
+SELECT local_relpath, op_depth, 20, 'No ancestor in NODES'
+FROM nodes n WHERE local_relpath != ''
+ AND file_external IS NULL
+ AND NOT EXISTS(SELECT 1 from nodes i
+                WHERE i.wc_id=n.wc_id
+                  AND i.local_relpath=n.parent_relpath
+                  AND i.op_depth <= n.op_depth)
+
+UNION ALL
 /* If a node is not present in the working copy (normal, add, copy) it doesn't
    have revision details stored on this record */
-SELECT local_relpath, op_depth, 'SV004: Unneeded node data'
+SELECT local_relpath, op_depth, 21, 'Unneeded node data'
 FROM nodes
 WHERE presence NOT IN (MAP_NORMAL, MAP_INCOMPLETE)
 AND (properties IS NOT NULL
@@ -137,7 +153,7 @@ AND (properties IS NOT NULL
 UNION ALL
 /* base-deleted nodes don't have a repository location. They are just
    shadowing without a replacement */
-SELECT local_relpath, op_depth, 'SV005: Unneeded base-deleted node data'
+SELECT local_relpath, op_depth, 22, 'Unneeded base-deleted node data'
 FROM nodes
 WHERE presence IN (MAP_BASE_DELETED)
 AND (repos_id IS NOT NULL
@@ -146,7 +162,7 @@ AND (repos_id IS NOT NULL
 
 UNION ALL
 /* Verify if type specific data is set (or not set for wrong type) */
-SELECT local_relpath, op_depth, 'SV006: Kind specific data invalid on normal'
+SELECT local_relpath, op_depth, 23, 'Kind specific data invalid on normal'
 FROM nodes
 WHERE presence IN (MAP_NORMAL, MAP_INCOMPLETE)
 AND (kind IS NULL
@@ -166,7 +182,7 @@ AND (kind IS NULL
 UNION ALL
 /* Local-adds are always their own operation (read: they don't have
    op-depth descendants, nor are op-depth descendants */
-SELECT local_relpath, op_depth, 'SV007: Invalid op-depth for local add'
+SELECT local_relpath, op_depth, 24, 'Invalid op-depth for local add'
 FROM nodes
 WHERE presence IN (MAP_NORMAL, MAP_INCOMPLETE)
   AND repos_path IS NULL
@@ -176,7 +192,7 @@ UNION ALL
 /* op-depth descendants are only valid if they have a direct parent
    node at the same op-depth. Only certain types allow further
    descendants */
-SELECT local_relpath, op_depth, 'SV008: Node missing ancestor'
+SELECT local_relpath, op_depth, 25, 'Node missing op-depth ancestor'
 FROM nodes n
 WHERE op_depth < relpath_depth(local_relpath)
   AND file_external IS NULL
@@ -190,7 +206,7 @@ WHERE op_depth < relpath_depth(local_rel
 UNION ALL
 /* Present op-depth descendants have the repository location implied by their
    ancestor */
-SELECT n.local_relpath, n.op_depth, 'SV009: Copied descendant mismatch'
+SELECT n.local_relpath, n.op_depth, 26, 'Copied descendant mismatch'
 FROM nodes n
 JOIN nodes p
   ON p.wc_id=n.wc_id AND p.local_relpath=n.parent_relpath
@@ -206,7 +222,7 @@ WHERE n.op_depth > 0 AND n.presence IN (
 UNION ALL
 /* Only certain presence values are valid as op-root.
    Note that the wc-root always has presence normal or incomplete */
-SELECT n.local_relpath, n.op_depth, 'SV010: Invalid op-root presence'
+SELECT n.local_relpath, n.op_depth, 27, 'Invalid op-root presence'
 FROM nodes n
 WHERE n.op_depth = relpath_depth(local_relpath)
   AND presence NOT IN (MAP_NORMAL, MAP_INCOMPLETE, MAP_BASE_DELETED)
@@ -214,7 +230,7 @@ WHERE n.op_depth = relpath_depth(local_r
 UNION ALL
 /* If a node is shadowed, all its present op-depth descendants
    must be shadowed at the same op-depth as well */
-SELECT n.local_relpath, n.op_depth, 'SV011: Incomplete shadowing'
+SELECT n.local_relpath, n.op_depth, 28, 'Incomplete shadowing'
 FROM nodes n
 JOIN nodes s ON s.wc_id=n.wc_id AND s.local_relpath=n.local_relpath
  AND s.op_depth = relpath_depth(s.local_relpath)
@@ -235,7 +251,7 @@ WHERE n.presence IN (MAP_NORMAL, MAP_INC
 
 UNION ALL
 /* A base-delete is only valid if it directly deletes a present node */
-SELECT s.local_relpath, s.op_depth, 'SV012: Invalid base-delete'
+SELECT s.local_relpath, s.op_depth, 29, 'Invalid base-delete'
 FROM nodes s
 LEFT JOIN nodes n ON n.wc_id=s.wc_id AND n.local_relpath=s.local_relpath
  AND n.op_depth = (SELECT MAX(op_depth) FROM nodes d
@@ -245,8 +261,16 @@ WHERE s.presence = MAP_BASE_DELETED
   AND n.presence NOT IN (MAP_NORMAL, MAP_INCOMPLETE)
 
 UNION ALL
+/* Moves are stored in the working layers, not in BASE */
+SELECT n.local_relpath, n.op_depth, 30, 'Invalid data for BASE'
+FROM nodes n
+WHERE n.op_depth = 0
+  AND (n.moved_to IS NOT NULL
+       OR n.moved_here IS NOT NULL)
+
+UNION ALL
 /* If moved_here is set on an op-root, there must be a proper moved_to */
-SELECT d.local_relpath, d.op_depth, 'SV013: Moved here without origin'
+SELECT d.local_relpath, d.op_depth, 60, 'Moved here without origin'
 FROM nodes d
 WHERE d.op_depth = relpath_depth(d.local_relpath)
   AND d.moved_here = 1
@@ -255,18 +279,10 @@ WHERE d.op_depth = relpath_depth(d.local
 
 UNION ALL
 /* If moved_to is set there should be an moved op root at the target */
-SELECT s.local_relpath, s.op_depth, 'SV014: Moved to without target'
+SELECT s.local_relpath, s.op_depth, 61, 'Moved to without target'
 FROM nodes s
 WHERE s.moved_to IS NOT NULL
   AND NOT EXISTS(SELECT 1 FROM nodes d
                  WHERE d.wc_id = s.wc_id AND d.local_relpath = s.moved_to
                    AND d.op_depth = relpath_depth(d.local_relpath)
                    AND d.moved_here =1 AND d.repos_path IS NOT NULL)
-
-UNION ALL
-/* Moves are stored in the working layers, not in BASE */
-SELECT n.local_relpath, n.op_depth, 'SV015: Invalid data for BASE'
-FROM nodes n
-WHERE n.op_depth = 0
-  AND (n.moved_to IS NOT NULL
-       OR n.moved_here IS NOT NULL)

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1660874&r1=1660873&r2=1660874&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Thu Feb 19 13:10:27 2015
@@ -16088,6 +16088,69 @@ svn_wc__db_verify(svn_wc__db_t *db,
   return SVN_NO_ERROR;
 }
 
+
+svn_error_t *
+svn_wc__db_verify_db_full_internal(svn_wc__db_wcroot_t *wcroot,
+                                   svn_wc__db_verify_cb_t callback,
+                                   void *baton,
+                                   apr_pool_t *scratch_pool)
+{
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
+  svn_error_t *err = NULL;
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_STATIC_VERIFY));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+  while (have_row)
+    {
+      const char *local_relpath;
+      int op_depth = svn_sqlite__column_int(stmt, 1);
+      int id = svn_sqlite__column_int(stmt, 2);
+      const char *msg;
+
+      svn_pool_clear(iterpool);
+
+      local_relpath =  svn_sqlite__column_text(stmt, 0, iterpool);
+      msg = svn_sqlite__column_text(stmt, 3, scratch_pool);
+
+      err = callback(baton, wcroot->abspath, local_relpath, op_depth,
+                     id, msg, iterpool);
+
+      if (err)
+        break;
+
+      SVN_ERR(svn_sqlite__step(&have_row, stmt));
+    }
+
+  svn_pool_destroy(iterpool);
+
+  return svn_error_trace(
+            svn_error_compose_create(err, svn_sqlite__reset(stmt)));
+}
+
+svn_error_t *
+svn_wc__db_verify_db_full(svn_wc__db_t *db,
+                          const char *wri_abspath,
+                          svn_wc__db_verify_cb_t callback,
+                          void *baton,
+                          apr_pool_t *scratch_pool)
+{
+  svn_wc__db_wcroot_t *wcroot;
+  const char *local_relpath;
+
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
+
+  SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
+                              wri_abspath, scratch_pool, scratch_pool));
+  VERIFY_USABLE_WCROOT(wcroot);
+
+  return svn_error_trace(
+            svn_wc__db_verify_db_full_internal(wcroot, callback, baton,
+                                               scratch_pool));
+}
+
 svn_error_t *
 svn_wc__db_bump_format(int *result_format,
                        svn_boolean_t *bumped_format,

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.h?rev=1660874&r1=1660873&r2=1660874&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.h Thu Feb 19 13:10:27 2015
@@ -3527,6 +3527,28 @@ svn_wc__required_lock_for_resolve(const
                                   apr_pool_t *scratch_pool);
 /* @} */
 
+typedef svn_error_t * (*svn_wc__db_verify_cb_t)(void *baton,
+                                                const char *wc_abspath,
+                                                const char *local_relpath,
+                                                int op_depth,
+                                                int id,
+                                                const char *description,
+                                                apr_pool_t *scratch_pool);
+
+/* Checks the database for FULL-correctness according to the spec.
+
+   Note that typical 1.7-1.9 databases WILL PRODUCE warnings.
+
+   This is mainly useful for WC-NG developers, as there will be
+   warnings without the database being corrupt
+*/
+svn_error_t *
+svn_wc__db_verify_db_full(svn_wc__db_t *db,
+                          const char *wri_abspath,
+                          svn_wc__db_verify_cb_t callback,
+                          void *baton,
+                          apr_pool_t *scratch_pool);
+
 
 #ifdef __cplusplus
 }

Modified: subversion/trunk/subversion/libsvn_wc/wc_db_private.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db_private.h?rev=1660874&r1=1660873&r2=1660874&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db_private.h (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db_private.h Thu Feb 19 13:10:27 2015
@@ -511,4 +511,10 @@ svn_wc__db_update_move_list_notify(svn_w
                                    void *notify_baton,
                                    apr_pool_t *scratch_pool);
 
+svn_error_t *
+svn_wc__db_verify_db_full_internal(svn_wc__db_wcroot_t *wcroot,
+                                   svn_wc__db_verify_cb_t callback,
+                                   void *baton,
+                                   apr_pool_t *scratch_pool);
+
 #endif /* WC_DB_PRIVATE_H */

Modified: subversion/trunk/subversion/libsvn_wc/wc_db_wcroot.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db_wcroot.c?rev=1660874&r1=1660873&r2=1660874&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db_wcroot.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db_wcroot.c Thu Feb 19 13:10:27 2015
@@ -164,32 +164,23 @@ svn_wc__db_verify_no_work(svn_sqlite__db
 }
 
 #if defined(VERIFY_ON_CLOSE) && defined(SVN_DEBUG)
+/* Implements svn_wc__db_verify_cb_t */
 static svn_error_t *
-verify_sqlite(svn_sqlite__db_t *sdb,
-              const char *wc_abspath,
-              apr_pool_t *scratch_pool)
+verify_db_cb(void *baton,
+             const char *wc_abspath,
+             const char *local_relpath,
+             int op_depth,
+             int id,
+             const char *msg,
+             apr_pool_t *scratch_pool)
 {
-  svn_sqlite__stmt_t *stmt;
-  svn_boolean_t have_row;
+  if (op_depth >= 0)
+    SVN_DBG(("DB-VRFY: %s: %s (%d): SV%04d %s",
+              wc_abspath, local_relpath, op_depth, id, msg));
+  else
+    SVN_DBG(("DB-VRFY: %s: %s: SV%04d %s",
+              wc_abspath, local_relpath, id, msg));
 
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_STATIC_VERIFY));
-  SVN_ERR(svn_sqlite__step(&have_row, stmt));
-
-  while (have_row)
-    {
-      const char *item = svn_sqlite__column_text(stmt, 0, scratch_pool);
-      int op_depth = svn_sqlite__column_int(stmt, 1);
-      const char *msg = svn_sqlite__column_text(stmt, 2, scratch_pool);
-
-      if (op_depth >= 0)
-        SVN_DBG(("DB-VRFY: %s: %s:%d: %s", wc_abspath, item, op_depth, msg));
-      else
-        SVN_DBG(("DB-VRFY: %s: %s: %s", wc_abspath, item, msg));
-
-      SVN_ERR(svn_sqlite__step(&have_row, stmt));
-    }
-
-  SVN_ERR(svn_sqlite__reset(stmt));
   return SVN_NO_ERROR;
 }
 #endif
@@ -208,8 +199,8 @@ close_wcroot(void *data)
     {
       apr_pool_t *scratch_pool = svn_pool_create(NULL);
 
-      svn_error_clear(verify_sqlite(wcroot->sdb, wcroot->abspath,
-                                    scratch_pool));
+      svn_error_clear(svn_wc__db_verify_db_full_internal(
+                                    wcroot, verify_db_cb, NULL, scratch_pool));
 
       svn_pool_destroy(scratch_pool);
     }

Added: subversion/trunk/tools/dev/wc-ng/svn-wc-db-tester.c
URL: http://svn.apache.org/viewvc/subversion/trunk/tools/dev/wc-ng/svn-wc-db-tester.c?rev=1660874&view=auto
==============================================================================
--- subversion/trunk/tools/dev/wc-ng/svn-wc-db-tester.c (added)
+++ subversion/trunk/tools/dev/wc-ng/svn-wc-db-tester.c Thu Feb 19 13:10:27 2015
@@ -0,0 +1,269 @@
+/* svn-wc-db-tester.c
+ *
+ * This is a crude command line tool that makes it possible to
+ * run the wc-db validation checks directly.
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+
+#include "svn_cmdline.h"
+#include "svn_pools.h"
+#include "svn_wc.h"
+#include "svn_utf.h"
+#include "svn_path.h"
+#include "svn_opt.h"
+#include "svn_version.h"
+
+#include "private/svn_wc_private.h"
+#include "private/svn_cmdline_private.h"
+
+#include "../../subversion/libsvn_wc/wc.h"
+#include "../../subversion/libsvn_wc/wc_db.h"
+
+#include "svn_private_config.h"
+
+#define OPT_VERSION SVN_OPT_FIRST_LONGOPT_ID
+
+static svn_error_t *
+version(apr_pool_t *pool)
+{
+  return svn_opt_print_help4(NULL, "svn-wc-db-tester", TRUE, FALSE, FALSE,
+                             NULL, NULL, NULL, NULL, NULL, NULL, pool);
+}
+
+static void
+usage(apr_pool_t *pool)
+{
+  svn_error_clear(svn_cmdline_fprintf
+                  (stderr, pool,
+                   _("Type 'svn-wc-db-tester --help' for usage.\n")));
+}
+
+struct verify_baton
+{
+  svn_boolean_t found_err;
+};
+
+static svn_error_t *
+verify_cb(void *baton,
+          const char *wc_abspath,
+          const char *local_relpath,
+          int op_depth,
+          int id,
+          const char *msg,
+          apr_pool_t *scratch_pool)
+{
+  struct verify_baton *vb = baton;
+
+  if (op_depth >= 0)
+    {
+      SVN_ERR(svn_cmdline_printf(scratch_pool, "%s (depth=%d) DBV%04d: %s\n",
+                                 local_relpath, op_depth, id, msg));
+    }
+  else
+    {
+      SVN_ERR(svn_cmdline_printf(scratch_pool, "%s DBV%04d: %s\n",
+                                 local_relpath, id, msg));
+    }
+
+  vb->found_err = TRUE;
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+verify_db(int argc, const char *path, apr_pool_t *pool)
+{
+  const char *local_abspath;
+  svn_wc_context_t *wc_ctx;
+  struct verify_baton vb = { FALSE };
+
+  /* Read the parameters */
+  path = svn_dirent_internal_style(path, pool);
+
+  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
+
+  SVN_ERR(svn_wc_context_create(&wc_ctx, NULL, pool, pool));
+
+  SVN_ERR(svn_wc__db_verify_db_full(wc_ctx->db, local_abspath,
+                                    verify_cb, &vb, pool));
+
+  if (vb.found_err)
+    return svn_error_create(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
+              _("Found one or more potential wc.db inconsistencies"));
+
+  return SVN_NO_ERROR;
+}
+
+
+static void
+help(const apr_getopt_option_t *options, apr_pool_t *pool)
+{
+  svn_error_clear
+    (svn_cmdline_fprintf
+     (stdout, pool,
+      _("usage: svn-wc-db-tester [OPTIONS] WC_PATH\n\n"
+        "  Run verifications on the working copy\n"
+        "\n"
+        "  WC_PATH's parent directory must be a working copy, otherwise a\n"
+        "  tree conflict cannot be raised.\n"
+        "\n"
+        "Valid options:\n")));
+  while (options->description)
+    {
+      const char *optstr;
+      svn_opt_format_option(&optstr, options, TRUE, pool);
+      svn_error_clear(svn_cmdline_fprintf(stdout, pool, "  %s\n", optstr));
+      ++options;
+    }
+}
+
+
+/* Version compatibility check */
+static svn_error_t *
+check_lib_versions(void)
+{
+  static const svn_version_checklist_t checklist[] =
+    {
+      { "svn_subr",   svn_subr_version },
+      { "svn_wc",     svn_wc_version },
+      { NULL, NULL }
+    };
+  SVN_VERSION_DEFINE(my_version);
+
+  return svn_ver_check_list2(&my_version, checklist, svn_ver_equal);
+}
+
+/*
+ * On success, leave *EXIT_CODE untouched and return SVN_NO_ERROR. On error,
+ * either return an error to be displayed, or set *EXIT_CODE to non-zero and
+ * return SVN_NO_ERROR.
+ */
+static svn_error_t *
+sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
+{
+  apr_getopt_t *os;
+  const apr_getopt_option_t options[] =
+    {
+      {"help", 'h', 0, N_("display this help")},
+      {"version", OPT_VERSION, 0,
+       N_("show program version information")},
+      {0,             0,  0,  0}
+    };
+  apr_array_header_t *remaining_argv;
+
+  /* Check library versions */
+  SVN_ERR(check_lib_versions());
+
+#if defined(WIN32) || defined(__CYGWIN__)
+  /* Set the working copy administrative directory name. */
+  if (getenv("SVN_ASP_DOT_NET_HACK"))
+    {
+      SVN_ERR(svn_wc_set_adm_dir("_svn", pool));
+    }
+#endif
+
+  SVN_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool));
+
+  os->interleave = 1;
+  while (1)
+    {
+      int opt;
+      const char *arg;
+      apr_status_t status = apr_getopt_long(os, options, &opt, &arg);
+      if (APR_STATUS_IS_EOF(status))
+        break;
+      if (status != APR_SUCCESS)
+        {
+          usage(pool);
+          *exit_code = EXIT_FAILURE;
+          return SVN_NO_ERROR;
+        }
+
+      switch (opt)
+        {
+        case 'h':
+          help(options, pool);
+          return SVN_NO_ERROR;
+        case OPT_VERSION:
+          SVN_ERR(version(pool));
+          return SVN_NO_ERROR;
+        default:
+          usage(pool);
+          *exit_code = EXIT_FAILURE;
+          return SVN_NO_ERROR;
+        }
+    }
+
+  /* Convert the remaining arguments to UTF-8. */
+  remaining_argv = apr_array_make(pool, 0, sizeof(const char *));
+  while (os->ind < argc)
+    {
+      const char *s;
+
+      SVN_ERR(svn_utf_cstring_to_utf8(&s, os->argv[os->ind++], pool));
+      APR_ARRAY_PUSH(remaining_argv, const char *) = s;
+    }
+
+  if (remaining_argv->nelts != 1)
+    {
+      usage(pool);
+      *exit_code = EXIT_FAILURE;
+      return SVN_NO_ERROR;
+    }
+
+  /* Do the main task */
+  SVN_ERR(verify_db(remaining_argv->nelts,
+                    APR_ARRAY_IDX(remaining_argv, 0, const char *),
+                    pool));
+
+  return SVN_NO_ERROR;
+}
+
+int
+main(int argc, const char *argv[])
+{
+  apr_pool_t *pool;
+  int exit_code = EXIT_SUCCESS;
+  svn_error_t *err;
+
+  /* Initialize the app. */
+  if (svn_cmdline_init("svn-wc-db-tester", stderr) != EXIT_SUCCESS)
+    return EXIT_FAILURE;
+
+  /* Create our top-level pool.  Use a separate mutexless allocator,
+   * given this application is single threaded.
+   */
+  pool = apr_allocator_owner_get(svn_pool_create_allocator(FALSE));
+
+  err = sub_main(&exit_code, argc, argv, pool);
+
+  /* Flush stdout and report if it fails. It would be flushed on exit anyway
+     but this makes sure that output is not silently lost if it fails. */
+  err = svn_error_compose_create(err, svn_cmdline_fflush(stdout));
+
+  if (err)
+    {
+      exit_code = EXIT_FAILURE;
+      svn_cmdline_handle_exit_error(err, NULL, "svn-wc-db-tester: ");
+    }
+
+  svn_pool_destroy(pool);
+  return exit_code;
+}

Propchange: subversion/trunk/tools/dev/wc-ng/svn-wc-db-tester.c
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message