You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2017/05/14 20:22:49 UTC

svn commit: r1795116 - in /subversion/trunk/subversion: libsvn_fs_fs/tree.c libsvn_fs_x/dag_cache.c tests/libsvn_fs/fs-test.c

Author: stefan2
Date: Sun May 14 20:22:49 2017
New Revision: 1795116

URL: http://svn.apache.org/viewvc?rev=1795116&view=rev
Log:
Fix issue #4677.

When non-exitent paths are allowed as a result of a DAG-walk
(as opposed to creating a "path not found" error on those),
we may encounter file nodes in the "parent" path.  Those are
not an error but simply an indication that there won't be any
sub-paths.

* subversion/libsvn_fs_fs/tree.c
  (open_path): If n/a paths are allowed, non-dir parents are, too.

* subversion/libsvn_fs_x/dag_cache.c
  (svn_fs_x__get_dag_path): Same.

* subversion/tests/libsvn_fs/fs-test.c
  (closest_copy_test_svn_4677): Add regression test.
  (test_funcs): Register new test.

Modified:
    subversion/trunk/subversion/libsvn_fs_fs/tree.c
    subversion/trunk/subversion/libsvn_fs_x/dag_cache.c
    subversion/trunk/subversion/tests/libsvn_fs/fs-test.c

Modified: subversion/trunk/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/tree.c?rev=1795116&r1=1795115&r2=1795116&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/tree.c Sun May 14 20:22:49 2017
@@ -1143,8 +1143,20 @@ open_path(parent_path_t **parent_path_p,
 
       /* The path isn't finished yet; we'd better be in a directory.  */
       if (svn_fs_fs__dag_node_kind(child) != svn_node_dir)
-        SVN_ERR_W(SVN_FS__ERR_NOT_DIRECTORY(fs, path_so_far->data),
-                  apr_psprintf(iterpool, _("Failure opening '%s'"), path));
+        {
+          /* Since this is not a directory and we are looking for some
+             sub-path, that sub-path will not exist.  That will be o.k.,
+             if we are just here to check for the path's existence. */
+          if (flags & open_path_allow_null)
+            {
+              parent_path = NULL;
+              break;
+            }
+
+          /* It's really a problem ... */
+          SVN_ERR_W(SVN_FS__ERR_NOT_DIRECTORY(fs, path_so_far->data),
+                    apr_psprintf(iterpool, _("Failure opening '%s'"), path));
+        }
 
       rest = next;
       here = child;

Modified: subversion/trunk/subversion/libsvn_fs_x/dag_cache.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/dag_cache.c?rev=1795116&r1=1795115&r2=1795116&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/dag_cache.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/dag_cache.c Sun May 14 20:22:49 2017
@@ -890,6 +890,16 @@ svn_fs_x__get_dag_path(svn_fs_x__dag_pat
     {
       svn_pool_clear(iterpool);
 
+      /* If the current node is not a directory and we are just here to
+       * check for the path's existence, then that's o.k.
+       * Otherwise, non-dir nodes will cause an error in dag_step. */
+      if (   (flags & svn_fs_x__dag_path_allow_null)
+          && (svn_fs_x__dag_node_kind(dag_path->node) != svn_node_dir))
+        {
+          dag_path = NULL;
+          break;
+        }
+
       /* Find the sub-node. */
       SVN_ERR(dag_step(&here, root, dag_path->node, entry, &path, change_set,
                        TRUE, iterpool));

Modified: subversion/trunk/subversion/tests/libsvn_fs/fs-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_fs/fs-test.c?rev=1795116&r1=1795115&r2=1795116&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_fs/fs-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_fs/fs-test.c Sun May 14 20:22:49 2017
@@ -7317,6 +7317,58 @@ test_rep_sharing_strict_content_check(co
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+closest_copy_test_svn_4677(const svn_test_opts_t *opts,
+                           apr_pool_t *pool)
+{
+  svn_fs_t *fs;
+  svn_fs_txn_t *txn;
+  svn_fs_root_t *txn_root, *rev_root, *croot;
+  svn_revnum_t after_rev;
+  const char *cpath;
+  apr_pool_t *spool = svn_pool_create(pool);
+
+  /* Prepare a filesystem. */
+  SVN_ERR(svn_test__create_fs(&fs, "test-repo-svn-4677",
+                              opts, pool));
+
+  /* In first txn, create file A/foo. */
+  SVN_ERR(svn_fs_begin_txn(&txn, fs, 0, spool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, spool));
+  SVN_ERR(svn_fs_make_dir(txn_root, "A", spool));
+  SVN_ERR(svn_fs_make_file(txn_root, "A/foo", spool));
+  SVN_ERR(test_commit_txn(&after_rev, txn, NULL, spool));
+  svn_pool_clear(spool);
+  SVN_ERR(svn_fs_revision_root(&rev_root, fs, after_rev, spool));
+
+  /* Move A to B, and commit. */
+  SVN_ERR(svn_fs_begin_txn(&txn, fs, after_rev, spool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, spool));
+  SVN_ERR(svn_fs_copy(rev_root, "A", txn_root, "B", spool));
+  SVN_ERR(svn_fs_delete(txn_root, "A", spool));
+  SVN_ERR(test_commit_txn(&after_rev, txn, NULL, spool));
+  svn_pool_clear(spool);
+  SVN_ERR(svn_fs_revision_root(&rev_root, fs, after_rev, spool));
+
+  /* Replace file B/foo with directory B/foo, add B/foo/bar, and commit. */
+  SVN_ERR(svn_fs_begin_txn(&txn, fs, after_rev, spool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, spool));
+  SVN_ERR(svn_fs_delete(txn_root, "B/foo", spool));
+  SVN_ERR(svn_fs_make_dir(txn_root, "B/foo", spool));
+  SVN_ERR(svn_fs_make_file(txn_root, "B/foo/bar", spool));
+  SVN_ERR(test_commit_txn(&after_rev, txn, NULL, spool));
+  svn_pool_clear(spool);
+  SVN_ERR(svn_fs_revision_root(&rev_root, fs, after_rev, spool));
+
+  /* B/foo/bar has been copied.
+     Issue 4677 was caused by returning an error in this situation. */
+  SVN_ERR(svn_fs_closest_copy(&croot, &cpath, rev_root, "B/foo/bar", spool));
+  SVN_TEST_ASSERT(cpath == NULL);
+  SVN_TEST_ASSERT(croot == NULL);
+
+  return SVN_NO_ERROR;
+}
+
 /* ------------------------------------------------------------------------ */
 
 /* The test table.  */
@@ -7459,6 +7511,8 @@ static struct svn_test_descriptor_t test
                        "test clearing the cache while streaming a rep"),
     SVN_TEST_OPTS_PASS(test_rep_sharing_strict_content_check,
                        "test rep-sharing on content rather than SHA1"),
+    SVN_TEST_OPTS_PASS(closest_copy_test_svn_4677,
+                       "test issue SVN-4677 regression"),
     SVN_TEST_NULL
   };