subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From stef...@apache.org
Subject svn commit: r1727838 - in /subversion/trunk/subversion: include/private/svn_fs_util.h libsvn_fs/fs-loader.c libsvn_fs_util/fs-util.c tests/cmdline/svnadmin_tests.py
Date Sun, 31 Jan 2016 16:18:26 GMT
Author: stefan2
Date: Sun Jan 31 16:18:26 2016
New Revision: 1727838

URL: http://svn.apache.org/viewvc?rev=1727838&view=rev
Log:
Add the ability to emulate the old svn_fs_paths_changed2 through
svn_fs_paths_changed3.  So, we've got a two-way emulation now and
we enable both for now such that all callers of the old API will
be redirected: old API -> new API -> old API vtable entry.

As a bonus, the enumated svn_fs_paths_changed2 now correctly reports
the IDs for in-revision nodes in FSFS.  It also fails earlier on
corrupted change lists.  Both is only true for "enumlated" mode.

* subversion/include/private/svn_fs_util.h
  (svn_fs__get_deleted_node): Declare a new private utility API needed
                              to handle ID creation edge cases.

* subversion/libsvn_fs_util/fs-util.c
  (svn_fs__prop_lists_equal): Implement.

* subversion/libsvn_fs/fs-loader.c
  (SVN_FS_ENUMLATE_PATHS_CHANGED): Declare new control macro as we did
                                   already for the new API.
  (add_changed_path_baton_t,
   add_changed_path): Callback implementation to emulate the old API
                      based on the new one.
  (svn_fs_paths_changed2): Emulate when necessary or forced to do so.

* subversion/tests/cmdline/svnadmin_tests.py
  (verify_invalid_path_changes): The correct ID construction in emulated
                                 mode creates fewer repetitions of the
                                 same error during verification.  Update
                                 test expectations accordingly.

Modified:
    subversion/trunk/subversion/include/private/svn_fs_util.h
    subversion/trunk/subversion/libsvn_fs/fs-loader.c
    subversion/trunk/subversion/libsvn_fs_util/fs-util.c
    subversion/trunk/subversion/tests/cmdline/svnadmin_tests.py

Modified: subversion/trunk/subversion/include/private/svn_fs_util.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_fs_util.h?rev=1727838&r1=1727837&r2=1727838&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_fs_util.h (original)
+++ subversion/trunk/subversion/include/private/svn_fs_util.h Sun Jan 31 16:18:26 2016
@@ -244,6 +244,22 @@ svn_fs__prop_lists_equal(apr_hash_t *a,
                          apr_hash_t *b,
                          apr_pool_t *pool);
 
+/* Determine the previous location of PATH under ROOT and return it as
+ * *NODE_PATH under *NODE_ROOT.  This may be called for arbitrary nodes
+ * but is intended for nodes that got deleted in ROOT, i.e. when standard
+ * navigation fails.  It also works if ROOT is transaction root.
+ *
+ * Allocate *NODE_PATH and *NODE_ROOT in RESULT_POOL while using
+ * SCRATCH_POOL for temporaries.
+ */
+svn_error_t *
+svn_fs__get_deleted_node(svn_fs_root_t **node_root,
+                         const char **node_path,
+                         svn_fs_root_t *root,
+                         const char *path,
+                         apr_pool_t *result_pool,
+                         apr_pool_t *scratch_pool);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/trunk/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs/fs-loader.c?rev=1727838&r1=1727837&r2=1727838&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/trunk/subversion/libsvn_fs/fs-loader.c Sun Jan 31 16:18:26 2016
@@ -59,6 +59,14 @@
 
 #define FS_TYPE_FILENAME "fs-type"
 
+/* If a FS backend does not implement the PATHS_CHANGED vtable function,
+   it will get emulated.  However, if this macro is defined to non-null
+   then the API will always be emulated when feasible, i.e. the calls
+   get "re-directed" to the old API implementation. */
+#ifndef SVN_FS_ENUMLATE_PATHS_CHANGED
+#define SVN_FS_ENUMLATE_PATHS_CHANGED TRUE
+#endif
+
 /* If a FS backend does not implement the REPORT_CHANGES vtable function,
    it will get emulated.  However, if this macro is defined to non-null
    then the API will always be emulated when feasible, i.e. the calls
@@ -1046,12 +1054,77 @@ svn_fs_revision_root_revision(svn_fs_roo
   return root->is_txn_root ? SVN_INVALID_REVNUM : root->rev;
 }
 
+/* Baton type to be used with add_changed_path.
+   It contains extra parameters in and out of svn_fs_paths_changed2. */
+typedef struct add_changed_path_baton_t
+{
+  svn_fs_root_t *root;
+  apr_hash_t *changes;
+} add_changed_path_baton_t;
+
+/* Implements svn_fs_path_change_receiver_t.
+   Take the CHANGE, convert it into a svn_fs_path_change2_t and add
+   it to the CHANGES hash in the add_changed_path_baton_t BATON. */
+static svn_error_t *
+add_changed_path(void *baton,
+                 svn_fs_path_change3_t *change,
+                 apr_pool_t *scratch_pool)
+{
+  add_changed_path_baton_t *b = baton;
+  apr_pool_t *result_pool = apr_hash_pool_get(b->changes);
+
+  svn_fs_path_change2_t *copy;
+  const svn_fs_id_t *id_copy;
+
+  svn_fs_root_t *root = b->root;
+  const char *path = change->path.data;
+  if (change->change_kind == svn_fs_path_change_delete)
+    SVN_ERR(svn_fs__get_deleted_node(&root, &path, root, path,
+                                     scratch_pool, scratch_pool));
+
+  SVN_ERR(svn_fs_node_id(&id_copy, root, path, result_pool));
+
+  copy = svn_fs_path_change2_create(id_copy, change->change_kind,
+                                    result_pool);
+  copy->copyfrom_known = change->copyfrom_known;
+  if (copy->copyfrom_known && SVN_IS_VALID_REVNUM(change->copyfrom_rev))
+    {
+      copy->copyfrom_rev = change->copyfrom_rev;
+      copy->copyfrom_path = apr_pstrdup(result_pool, change->copyfrom_path);
+    }
+  copy->mergeinfo_mod = change->mergeinfo_mod;
+  copy->node_kind = change->node_kind;
+  copy->prop_mod = change->prop_mod;
+  copy->text_mod = change->text_mod;
+
+  svn_hash_sets(b->changes, apr_pstrmemdup(result_pool, change->path.data,
+                                           change->path.len), copy);
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_fs_paths_changed2(apr_hash_t **changed_paths_p,
                       svn_fs_root_t *root,
                       apr_pool_t *pool)
 {
-  return root->vtable->paths_changed(changed_paths_p, root, pool);
+  svn_boolean_t emulate =    !root->vtable->paths_changed
+                          || SVN_FS_ENUMLATE_PATHS_CHANGED;
+
+  if (emulate)
+    {
+      add_changed_path_baton_t baton;
+      baton.root = root;
+      baton.changes = svn_hash__make(pool);
+      SVN_ERR(svn_fs_paths_changed3(root, add_changed_path, &baton, pool));
+      *changed_paths_p = baton.changes;
+    }
+  else
+    {
+      SVN_ERR(root->vtable->paths_changed(changed_paths_p, root, pool));
+    }
+
+  return SVN_NO_ERROR;
 }
 
 svn_error_t *

Modified: subversion/trunk/subversion/libsvn_fs_util/fs-util.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_util/fs-util.c?rev=1727838&r1=1727837&r2=1727838&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_util/fs-util.c (original)
+++ subversion/trunk/subversion/libsvn_fs_util/fs-util.c Sun Jan 31 16:18:26 2016
@@ -347,3 +347,61 @@ svn_fs__prop_lists_equal(apr_hash_t *a,
   /* No difference found. */
   return TRUE;
 }
+
+svn_error_t *
+svn_fs__get_deleted_node(svn_fs_root_t **node_root,
+                         const char **node_path,
+                         svn_fs_root_t *root,
+                         const char *path,
+                         apr_pool_t *result_pool,
+                         apr_pool_t *scratch_pool)
+{
+  const char *parent_path, *name;
+  svn_fs_root_t *copy_root;
+  const char *copy_path;
+
+  /* History traversal does not work with transaction roots.
+   * Therefore, do it "by hand". */
+
+  /* If the parent got copied in ROOT, PATH got copied with it.
+   * Otherwise, we will find the node at PATH in the revision prior to ROOT.
+   */
+  svn_fspath__split(&parent_path, &name, path, scratch_pool);
+  SVN_ERR(svn_fs_closest_copy(&copy_root, &copy_path, root, parent_path,
+                              scratch_pool));
+
+  /* Copied in ROOT? */
+  if (   copy_root
+      && (   svn_fs_revision_root_revision(copy_root)
+          == svn_fs_revision_root_revision(root)))
+    {
+      svn_revnum_t copyfrom_rev;
+      const char *copyfrom_path;
+      const char *rel_path;
+      SVN_ERR(svn_fs_copied_from(&copyfrom_rev, &copyfrom_path,
+                                 copy_root, copy_path, scratch_pool));
+
+      SVN_ERR(svn_fs_revision_root(node_root, svn_fs_root_fs(root),
+                                   copyfrom_rev, result_pool));
+      rel_path = svn_fspath__skip_ancestor(copy_path, path);
+      *node_path = svn_fspath__join(copyfrom_path, rel_path, result_pool);
+    }
+  else
+    {
+      svn_revnum_t revision;
+      svn_revnum_t previous_rev;
+
+      /* Determine the latest revision before ROOT. */
+      revision = svn_fs_revision_root_revision(root);
+      if (SVN_IS_VALID_REVNUM(revision))
+        previous_rev = revision - 1;
+      else
+        previous_rev = svn_fs_txn_root_base_revision(root);
+
+      SVN_ERR(svn_fs_revision_root(node_root, svn_fs_root_fs(root),
+                                   previous_rev, result_pool));
+      *node_path = apr_pstrdup(result_pool, path);
+    }
+
+  return SVN_NO_ERROR;
+}

Modified: subversion/trunk/subversion/tests/cmdline/svnadmin_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/svnadmin_tests.py?rev=1727838&r1=1727837&r2=1727838&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/svnadmin_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/svnadmin_tests.py Sun Jan 31 16:18:26 2016
@@ -2286,35 +2286,134 @@ def verify_invalid_path_changes(sbox):
                                                         "--keep-going",
                                                         sbox.repo_dir)
 
-  exp_out = svntest.verify.RegexListOutput([".*Verified revision 0.",
-                                           ".*Verified revision 1.",
-                                           ".*Verified revision 3.",
-                                           ".*Verified revision 5.",
-                                           ".*Verified revision 7.",
-                                           ".*Verified revision 8.",
-                                           ".*Verified revision 9.",
-                                           ".*Verified revision 11.",
-                                           ".*Verified revision 13.",
-                                           ".*Verified revision 15.",
-                                           ".*Verified revision 17.",
-                                           ".*Verified revision 19.",
-                                           ".*",
-                                           ".*Summary.*",
-                                           ".*r2: E160020:.*",
-                                           ".*r2: E160020:.*",
-                                           ".*r4: E160013:.*",
-                                           ".*r6: E160013:.*",
-                                           ".*r6: E160013:.*",
-                                           ".*r10: E160013:.*",
-                                           ".*r10: E160013:.*",
-                                           ".*r12: E145001:.*",
-                                           ".*r12: E145001:.*",
-                                           ".*r14: E160013:.*",
-                                           ".*r14: E160013:.*",
-                                           ".*r16: E145001:.*",
-                                           ".*r16: E145001:.*",
-                                           ".*r18: E160013:.*",
-                                           ".*r18: E160013:.*"])
+  # Errors generated by FSFS when CHANGED_PATHS is not forced into emulation
+  exp_out1 = svntest.verify.RegexListOutput([".*Verified revision 0.",
+                                             ".*Verified revision 1.",
+                                             ".*Verified revision 3.",
+                                             ".*Verified revision 5.",
+                                             ".*Verified revision 7.",
+                                             ".*Verified revision 8.",
+                                             ".*Verified revision 9.",
+                                             ".*Verified revision 11.",
+                                             ".*Verified revision 13.",
+                                             ".*Verified revision 15.",
+                                             ".*Verified revision 17.",
+                                             ".*Verified revision 19.",
+                                             ".*",
+                                             ".*Summary.*",
+                                             ".*r2: E160020:.*",
+                                             ".*r2: E160020:.*",
+                                             ".*r4: E160013:.*",
+                                             ".*r6: E160013:.*",
+                                             ".*r6: E160013:.*",
+                                             ".*r10: E160013:.*",
+                                             ".*r10: E160013:.*",
+                                             ".*r12: E145001:.*",
+                                             ".*r12: E145001:.*",
+                                             ".*r14: E160013:.*",
+                                             ".*r14: E160013:.*",
+                                             ".*r16: E145001:.*",
+                                             ".*r16: E145001:.*",
+                                             ".*r18: E160013:.*",
+                                             ".*r18: E160013:.*"])
+
+  exp_err1 = svntest.verify.RegexListOutput([".*Error verifying revision 2.",
+                                             "svnadmin: E160020:.*",
+                                             "svnadmin: E160020:.*",
+                                             ".*Error verifying revision 4.",
+                                             "svnadmin: E160013:.*",
+                                             ".*Error verifying revision 6.",
+                                             "svnadmin: E160013:.*",
+                                             "svnadmin: E160013:.*",
+                                             ".*Error verifying revision 10.",
+                                             "svnadmin: E160013:.*",
+                                             "svnadmin: E160013:.*",
+                                             ".*Error verifying revision 12.",
+                                             "svnadmin: E145001:.*",
+                                             "svnadmin: E145001:.*",
+                                             ".*Error verifying revision 14.",
+                                             "svnadmin: E160013:.*",
+                                             "svnadmin: E160013:.*",
+                                             ".*Error verifying revision 16.",
+                                             "svnadmin: E145001:.*",
+                                             "svnadmin: E145001:.*",
+                                             ".*Error verifying revision 18.",
+                                             "svnadmin: E160013:.*",
+                                             "svnadmin: E160013:.*",
+                                             "svnadmin: E205012:.*"], False)
+
+  # If CHANGED_PATHS is emulated, FSFS fails earlier, generating fewer
+  # of the same messages per revision.
+  exp_out2 = svntest.verify.RegexListOutput([".*Verified revision 0.",
+                                             ".*Verified revision 1.",
+                                             ".*Verified revision 3.",
+                                             ".*Verified revision 5.",
+                                             ".*Verified revision 7.",
+                                             ".*Verified revision 8.",
+                                             ".*Verified revision 9.",
+                                             ".*Verified revision 11.",
+                                             ".*Verified revision 13.",
+                                             ".*Verified revision 15.",
+                                             ".*Verified revision 17.",
+                                             ".*Verified revision 19.",
+                                             ".*",
+                                             ".*Summary.*",
+                                             ".*r2: E160020:.*",
+                                             ".*r2: E160020:.*",
+                                             ".*r4: E160013:.*",
+                                             ".*r6: E160013:.*",
+                                             ".*r10: E160013:.*",
+                                             ".*r10: E160013:.*",
+                                             ".*r12: E145001:.*",
+                                             ".*r12: E145001:.*",
+                                             ".*r14: E160013:.*",
+                                             ".*r16: E145001:.*",
+                                             ".*r16: E145001:.*",
+                                             ".*r18: E160013:.*"])
+
+  exp_err2 = svntest.verify.RegexListOutput([".*Error verifying revision 2.",
+                                             "svnadmin: E160020:.*",
+                                             "svnadmin: E160020:.*",
+                                             ".*Error verifying revision 4.",
+                                             "svnadmin: E160013:.*",
+                                             ".*Error verifying revision 6.",
+                                             "svnadmin: E160013:.*",
+                                             ".*Error verifying revision 10.",
+                                             "svnadmin: E160013:.*",
+                                             "svnadmin: E160013:.*",
+                                             ".*Error verifying revision 12.",
+                                             "svnadmin: E145001:.*",
+                                             "svnadmin: E145001:.*",
+                                             ".*Error verifying revision 14.",
+                                             "svnadmin: E160013:.*",
+                                             ".*Error verifying revision 16.",
+                                             "svnadmin: E145001:.*",
+                                             "svnadmin: E145001:.*",
+                                             ".*Error verifying revision 18.",
+                                             "svnadmin: E160013:.*",
+                                             "svnadmin: E205012:.*"], False)
+
+  # Determine which pattern to use.
+  # Note that index() will throw an exception if the string can't be found.
+  try:
+    rev6_line = errput.index('* Error verifying revision 6.\n');
+    rev10_line = errput.index('* Error verifying revision 10.\n');
+
+    error_count = 0
+    for line in errput[rev6_line+1:rev10_line]:
+      if "svnadmin: E" in line:
+        error_count = error_count + 1
+
+    if error_count == 1:
+      exp_out = exp_out2
+      exp_err = exp_err2
+    else:
+      exp_out = exp_out1
+      exp_err = exp_err1
+  except ValueError:
+    exp_out = exp_out1
+    exp_err = exp_err1
+
   if (svntest.main.fs_has_rep_sharing()):
     exp_out.insert(0, ".*Verifying.*metadata.*")
   if svntest.main.options.fsfs_sharding is not None:
@@ -2323,32 +2422,6 @@ def verify_invalid_path_changes(sbox):
   if svntest.main.is_fs_log_addressing():
     exp_out.insert(0, ".*Verifying.*metadata.*")
 
-  exp_err = svntest.verify.RegexListOutput([".*Error verifying revision 2.",
-                                            "svnadmin: E160020:.*",
-                                            "svnadmin: E160020:.*",
-                                            ".*Error verifying revision 4.",
-                                            "svnadmin: E160013:.*",
-                                            ".*Error verifying revision 6.",
-                                            "svnadmin: E160013:.*",
-                                            "svnadmin: E160013:.*",
-                                            ".*Error verifying revision 10.",
-                                            "svnadmin: E160013:.*",
-                                            "svnadmin: E160013:.*",
-                                            ".*Error verifying revision 12.",
-                                            "svnadmin: E145001:.*",
-                                            "svnadmin: E145001:.*",
-                                            ".*Error verifying revision 14.",
-                                            "svnadmin: E160013:.*",
-                                            "svnadmin: E160013:.*",
-                                            ".*Error verifying revision 16.",
-                                            "svnadmin: E145001:.*",
-                                            "svnadmin: E145001:.*",
-                                            ".*Error verifying revision 18.",
-                                            "svnadmin: E160013:.*",
-                                            "svnadmin: E160013:.*",
-                                            "svnadmin: E205012:.*"], False)
-
-
   if svntest.verify.verify_outputs("Unexpected error while running 'svnadmin verify'.",
                                    output, errput, exp_out, exp_err):
     raise svntest.Failure



Mime
View raw message