You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by sv...@apache.org on 2012/07/01 06:01:30 UTC

svn commit: r1355849 - in /subversion/branches/1.7.x: ./ STATUS subversion/libsvn_repos/replay.c subversion/tests/cmdline/README subversion/tests/cmdline/svnsync_tests.py subversion/tests/cmdline/svntest/sandbox.py

Author: svn-role
Date: Sun Jul  1 04:01:29 2012
New Revision: 1355849

URL: http://svn.apache.org/viewvc?rev=1355849&view=rev
Log:
Merge the r1293945 group from trunk:

 * r1293945, r1293972, r1293976, r1293998, r1294136, r1294236;
   r1294134, r1294147, r1294586
   Two interdependent changes:
   Fix issue #4121: copy followed by delete of unreadable child.
   Fix svn:// authz in Python tests.
   Justification:
     User resorted to patching the commit editor to work around this.
     Tests are broken.
   Notes:
     r1293945,r1293972,r1293976 are cosmetics.
     r1293998 is the fix.
     r1294136 is a test.
     r1294236 fixes an uninitialized variable.
   Notes:
     r1294134 extends a test to demonstrate its brokenness.
     r1294147 fixes said brokenness.
     r1294586 fixes r1294147 for Windows.
   Votes:
     +1: danielsh, stsp, rhuijben

Modified:
    subversion/branches/1.7.x/   (props changed)
    subversion/branches/1.7.x/STATUS
    subversion/branches/1.7.x/subversion/libsvn_repos/replay.c
    subversion/branches/1.7.x/subversion/tests/cmdline/README
    subversion/branches/1.7.x/subversion/tests/cmdline/svnsync_tests.py
    subversion/branches/1.7.x/subversion/tests/cmdline/svntest/sandbox.py

Propchange: subversion/branches/1.7.x/
------------------------------------------------------------------------------
  Merged /subversion/trunk:r1293945,1293972,1293976,1293998,1294134,1294136,1294147,1294236,1294586

Modified: subversion/branches/1.7.x/STATUS
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/STATUS?rev=1355849&r1=1355848&r2=1355849&view=diff
==============================================================================
--- subversion/branches/1.7.x/STATUS (original)
+++ subversion/branches/1.7.x/STATUS Sun Jul  1 04:01:29 2012
@@ -104,23 +104,3 @@ Veto-blocked changes:
 
 Approved changes:
 =================
-
- * r1293945, r1293972, r1293976, r1293998, r1294136, r1294236;
-   r1294134, r1294147, r1294586
-   Two interdependent changes:
-   Fix issue #4121: copy followed by delete of unreadable child.
-   Fix svn:// authz in Python tests.
-   Justification:
-     User resorted to patching the commit editor to work around this.
-     Tests are broken.
-   Notes:
-     r1293945,r1293972,r1293976 are cosmetics.
-     r1293998 is the fix.
-     r1294136 is a test.
-     r1294236 fixes an uninitialized variable.
-   Notes:
-     r1294134 extends a test to demonstrate its brokenness.
-     r1294147 fixes said brokenness.
-     r1294586 fixes r1294147 for Windows.
-   Votes:
-     +1: danielsh, stsp, rhuijben

Modified: subversion/branches/1.7.x/subversion/libsvn_repos/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/libsvn_repos/replay.c?rev=1355849&r1=1355848&r2=1355849&view=diff
==============================================================================
--- subversion/branches/1.7.x/subversion/libsvn_repos/replay.c (original)
+++ subversion/branches/1.7.x/subversion/libsvn_repos/replay.c Sun Jul  1 04:01:29 2012
@@ -352,6 +352,116 @@ is_within_base_path(const char *path, co
   return FALSE;
 }
 
+/* Given PATH deleted under ROOT, return in READABLE whether the path was
+   readable prior to the deletion.  Consult COPIES (a stack of 'struct
+   copy_info') and AUTHZ_READ_FUNC. */
+static svn_error_t *
+was_readable(svn_boolean_t *readable,
+             svn_fs_root_t *root,
+             const char *path,
+             apr_array_header_t *copies,
+             svn_repos_authz_func_t authz_read_func,
+             void *authz_read_baton,
+             apr_pool_t *result_pool,
+             apr_pool_t *scratch_pool)
+{
+  svn_fs_root_t *inquire_root;
+  const char *inquire_path;
+  struct copy_info *info = NULL;
+  const char *relpath;
+
+  /* Short circuit. */
+  if (! authz_read_func)
+    {
+      *readable = TRUE;
+      return SVN_NO_ERROR;
+    }
+
+  if (copies->nelts != 0)
+    info = &APR_ARRAY_IDX(copies, copies->nelts - 1, struct copy_info);
+
+  /* Are we under a copy? */
+  if (info && (relpath = svn_relpath_skip_ancestor(info->path, path)))
+    {
+      SVN_ERR(svn_fs_revision_root(&inquire_root, svn_fs_root_fs(root),
+                                   info->copyfrom_rev, scratch_pool));
+      inquire_path = svn_fspath__join(info->copyfrom_path, relpath,
+                                      scratch_pool);
+    }
+  else
+    {
+      /* Compute the revision that ROOT is based on.  (Note that ROOT is not
+         r0's root, since this function is only called for deletions.)
+         ### Need a more succinct way to express this */
+      svn_revnum_t inquire_rev = SVN_INVALID_REVNUM;
+      if (svn_fs_is_txn_root(root))
+        inquire_rev = svn_fs_txn_root_base_revision(root);
+      if (svn_fs_is_revision_root(root))
+        inquire_rev =  svn_fs_revision_root_revision(root)-1;
+      SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(inquire_rev));
+
+      SVN_ERR(svn_fs_revision_root(&inquire_root, svn_fs_root_fs(root),
+                                   inquire_rev, scratch_pool));
+      inquire_path = path;
+    }
+
+  SVN_ERR(authz_read_func(readable, inquire_root, inquire_path,
+                          authz_read_baton, result_pool));
+
+  return SVN_NO_ERROR;
+}
+
+/* Initialize COPYFROM_ROOT, COPYFROM_PATH, and COPYFROM_REV with the
+   revision root, fspath, and revnum of the copyfrom of CHANGE, which
+   corresponds to PATH under ROOT.  If the copyfrom info is valid
+   (i.e., is not (NULL, SVN_INVALID_REVNUM)), then initialize SRC_READABLE
+   too, consulting AUTHZ_READ_FUNC and AUTHZ_READ_BATON if provided. */
+static svn_error_t *
+fill_copyfrom(svn_fs_root_t **copyfrom_root,
+              const char **copyfrom_path,
+              svn_revnum_t *copyfrom_rev,
+              svn_boolean_t *src_readable,
+              svn_fs_root_t *root,
+              svn_fs_path_change2_t *change,
+              svn_repos_authz_func_t authz_read_func,
+              void *authz_read_baton,
+              const char *path,
+              apr_pool_t *result_pool,
+              apr_pool_t *scratch_pool)
+{
+  if (! change->copyfrom_known)
+    {
+      SVN_ERR(svn_fs_copied_from(&(change->copyfrom_rev),
+                                 &(change->copyfrom_path),
+                                 root, path, result_pool));
+      change->copyfrom_known = TRUE;
+    }
+  *copyfrom_rev = change->copyfrom_rev;
+  *copyfrom_path = change->copyfrom_path;
+
+  if (*copyfrom_path && SVN_IS_VALID_REVNUM(*copyfrom_rev))
+    {
+      SVN_ERR(svn_fs_revision_root(copyfrom_root,
+                                   svn_fs_root_fs(root),
+                                   *copyfrom_rev, result_pool));
+
+      if (authz_read_func)
+        {
+          SVN_ERR(authz_read_func(src_readable, *copyfrom_root,
+                                  *copyfrom_path,
+                                  authz_read_baton, result_pool));
+        }
+      else
+        *src_readable = TRUE;
+    }
+  else
+    {
+      *copyfrom_root = NULL;
+      /* SRC_READABLE left uninitialized */
+    }
+  return SVN_NO_ERROR;
+}
+
 static svn_error_t *
 path_driver_cb_func(void **dir_baton,
                     void *parent_baton,
@@ -368,7 +478,6 @@ path_driver_cb_func(void **dir_baton,
   void *file_baton = NULL;
   svn_revnum_t copyfrom_rev;
   const char *copyfrom_path;
-  svn_boolean_t src_readable = TRUE;
   svn_fs_root_t *source_root = cb->compare_root;
   const char *source_fspath = NULL;
   const char *base_path = cb->base_path;
@@ -419,8 +528,18 @@ path_driver_cb_func(void **dir_baton,
 
   /* Handle any deletions. */
   if (do_delete)
-    SVN_ERR(editor->delete_entry(edit_path, SVN_INVALID_REVNUM,
-                                 parent_baton, pool));
+    {
+      svn_boolean_t readable;
+
+      /* Issue #4121: delete under under a copy, of a path that was unreadable
+         at its pre-copy location. */
+      SVN_ERR(was_readable(&readable, root, edit_path, cb->copies,
+                            cb->authz_read_func, cb->authz_read_baton,
+                            pool, pool));
+      if (readable)
+        SVN_ERR(editor->delete_entry(edit_path, SVN_INVALID_REVNUM,
+                                     parent_baton, pool));
+    }
 
   /* Fetch the node kind if it makes sense to do so. */
   if (! do_delete || do_add)
@@ -437,31 +556,14 @@ path_driver_cb_func(void **dir_baton,
   /* Handle any adds/opens. */
   if (do_add)
     {
-      svn_fs_root_t *copyfrom_root = NULL;
-      /* Was this node copied? */
-      if (! change->copyfrom_known)
-        {
-          SVN_ERR(svn_fs_copied_from(&(change->copyfrom_rev),
-                                     &(change->copyfrom_path),
-                                     root, edit_path, pool));
-          change->copyfrom_known = TRUE;
-        }
-      copyfrom_rev = change->copyfrom_rev;
-      copyfrom_path = change->copyfrom_path;
+      svn_boolean_t src_readable;
+      svn_fs_root_t *copyfrom_root;
 
-      if (copyfrom_path && SVN_IS_VALID_REVNUM(copyfrom_rev))
-        {
-          SVN_ERR(svn_fs_revision_root(&copyfrom_root,
-                                       svn_fs_root_fs(root),
-                                       copyfrom_rev, pool));
-
-          if (cb->authz_read_func)
-            {
-              SVN_ERR(cb->authz_read_func(&src_readable, copyfrom_root,
-                                          copyfrom_path,
-                                          cb->authz_read_baton, pool));
-            }
-        }
+      /* Was this node copied? */
+      SVN_ERR(fill_copyfrom(&copyfrom_root, &copyfrom_path, &copyfrom_rev,
+                            &src_readable, root, change,
+                            cb->authz_read_func, cb->authz_read_baton,
+                            edit_path, pool, pool));
 
       /* If we have a copyfrom path, and we can't read it or we're just
          ignoring it, or the copyfrom rev is prior to the low water mark

Modified: subversion/branches/1.7.x/subversion/tests/cmdline/README
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/tests/cmdline/README?rev=1355849&r1=1355848&r2=1355849&view=diff
==============================================================================
--- subversion/branches/1.7.x/subversion/tests/cmdline/README (original)
+++ subversion/branches/1.7.x/subversion/tests/cmdline/README Sun Jul  1 04:01:29 2012
@@ -333,7 +333,8 @@ svntest/tree.py.  It will explain the ge
 
 Finally, try copying-and-pasting a simple test and then edit from
 there.  Don't forget to add your test to the 'test_list' variable at
-the bottom of the file.
+the bottom of the file. To avoid renumbering of existing tests, you
+should add new tests to the end of the list.
 
 
 Testing Compatability With Previous Release

Modified: subversion/branches/1.7.x/subversion/tests/cmdline/svnsync_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/tests/cmdline/svnsync_tests.py?rev=1355849&r1=1355848&r2=1355849&view=diff
==============================================================================
--- subversion/branches/1.7.x/subversion/tests/cmdline/svnsync_tests.py (original)
+++ subversion/branches/1.7.x/subversion/tests/cmdline/svnsync_tests.py Sun Jul  1 04:01:29 2012
@@ -394,25 +394,32 @@ def basic_authz(sbox):
 
   run_init(dest_sbox.repo_url, sbox.repo_url)
 
+  args = map(lambda x: x.authz_name(), [sbox, sbox, dest_sbox])
   svntest.main.file_write(sbox.authz_file,
-                          "[svnsync-basic-authz:/]\n"
+                          "[%s:/]\n"
                           "* = r\n"
                           "\n"
-                          "[svnsync-basic-authz:/A/B]\n"
+                          "[%s:/A/B]\n"
                           "* = \n"
                           "\n"
-                          "[svnsync-basic-authz-1:/]\n"
-                          "* = rw\n")
+                          "[%s:/]\n"
+                          "* = rw\n" % tuple(args))
 
   run_sync(dest_sbox.repo_url)
 
   lambda_url = dest_sbox.repo_url + '/A/B/lambda'
+  iota_url = dest_sbox.repo_url + '/iota'
 
   # this file should have been blocked by authz
   svntest.actions.run_and_verify_svn(None,
                                      [], svntest.verify.AnyOutput,
                                      'cat',
                                      lambda_url)
+  # this file should have been synced
+  svntest.actions.run_and_verify_svn(None,
+                                     svntest.verify.AnyOutput, [],
+                                     'cat',
+                                     iota_url)
 
 #----------------------------------------------------------------------
 @Skip(svntest.main.is_ra_type_file)
@@ -465,29 +472,17 @@ def copy_from_unreadable_dir(sbox):
 
   svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)
 
-  fp = open(sbox.authz_file, 'w')
-
-  # For mod_dav_svn's parent path setup we need per-repos permissions in
-  # the authz file...
-  if sbox.repo_url.startswith('http'):
-    fp.write("[svnsync-copy-from-unreadable-dir:/]\n" +
-             "* = r\n" +
-             "\n" +
-             "[svnsync-copy-from-unreadable-dir:/A/B]\n" +
-             "* = \n" +
-             "\n" +
-             "[svnsync-copy-from-unreadable-dir-1:/]\n" +
-             "* = rw")
-
-  # Otherwise we can just go with the permissions needed for the source
-  # repository.
-  else:
-    fp.write("[/]\n" +
-             "* = r\n" +
-             "\n" +
-             "[/A/B]\n" +
-             "* =\n")
-  fp.close()
+  args = map(lambda x: x.authz_name(), [sbox, sbox, dest_sbox])
+  open(sbox.authz_file, 'w').write(
+             "[%s:/]\n"
+             "* = r\n"
+             "\n"
+             "[%s:/A/B]\n"
+             "* = \n"
+             "\n"
+             "[%s:/]\n"
+             "* = rw"
+             % tuple(args))
 
   run_init(dest_sbox.repo_url, sbox.repo_url)
 
@@ -591,29 +586,17 @@ def copy_with_mod_from_unreadable_dir(sb
 
   svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)
 
-  fp = open(sbox.authz_file, 'w')
-
-  # For mod_dav_svn's parent path setup we need per-repos permissions in
-  # the authz file...
-  if sbox.repo_url.startswith('http'):
-    fp.write("[svnsync-copy-with-mod-from-unreadable-dir:/]\n" +
-             "* = r\n" +
-             "\n" +
-             "[svnsync-copy-with-mod-from-unreadable-dir:/A/B]\n" +
-             "* = \n" +
-             "\n" +
-             "[svnsync-copy-with-mod-from-unreadable-dir-1:/]\n" +
-             "* = rw")
-
-  # Otherwise we can just go with the permissions needed for the source
-  # repository.
-  else:
-    fp.write("[/]\n" +
-             "* = r\n" +
-             "\n" +
-             "[/A/B]\n" +
-             "* =\n")
-  fp.close()
+  args = map(lambda x: x.authz_name(), [sbox, sbox, dest_sbox])
+  open(sbox.authz_file, 'w').write(
+             "[%s:/]\n"
+             "* = r\n"
+             "\n"
+             "[%s:/A/B]\n"
+             "* = \n"
+             "\n"
+             "[%s:/]\n"
+             "* = rw"
+             % tuple(args))
 
   run_init(dest_sbox.repo_url, sbox.repo_url)
 
@@ -695,29 +678,17 @@ def copy_with_mod_from_unreadable_dir_an
 
   svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)
 
-  fp = open(sbox.authz_file, 'w')
-
-  # For mod_dav_svn's parent path setup we need per-repos permissions in
-  # the authz file...
-  if sbox.repo_url.startswith('http'):
-    fp.write("[svnsync-copy-with-mod-from-unreadable-dir-and-copy:/]\n" +
-             "* = r\n" +
-             "\n" +
-             "[svnsync-copy-with-mod-from-unreadable-dir-and-copy:/A/B]\n" +
-             "* = \n" +
-             "\n" +
-             "[svnsync-copy-with-mod-from-unreadable-dir-and-copy-1:/]\n" +
-             "* = rw")
-
-  # Otherwise we can just go with the permissions needed for the source
-  # repository.
-  else:
-    fp.write("[/]\n" +
-             "* = r\n" +
-             "\n" +
-             "[/A/B]\n" +
-             "* =\n")
-  fp.close()
+  args = map(lambda x: x.authz_name(), [sbox, sbox, dest_sbox])
+  open(sbox.authz_file, 'w').write(
+             "[%s:/]\n"
+             "* = r\n"
+             "\n"
+             "[%s:/A/B]\n"
+             "* = \n"
+             "\n"
+             "[%s:/]\n"
+             "* = rw"
+             % tuple(args))
 
   run_init(dest_sbox.repo_url, sbox.repo_url)
 
@@ -1021,6 +992,46 @@ def fd_leak_sync_from_serf_to_local(sbox
   import resource
   resource.setrlimit(resource.RLIMIT_NOFILE, (128, 128))
   run_test(sbox, "largemods.dump", is_src_ra_local=None, is_dest_ra_local=True)
+@Issue(4121)
+@Skip(svntest.main.is_ra_type_file)
+def copy_delete_unreadable_child(sbox):
+  "copy, then rm at-src-unreadable child"
+
+  ## Prepare the source: Greek tree (r1), cp+rm (r2).
+  sbox.build("copy-delete-unreadable-child")
+  svntest.actions.run_and_verify_svnmucc(None, None, [], 
+                                         '-m', 'r2',
+                                         '-U', sbox.repo_url,
+                                         'cp', 'HEAD', '/', 'branch',
+                                         'rm', 'branch/A')
+
+  ## Create the destination.
+  dest_sbox = sbox.clone_dependent()
+  build_repos(dest_sbox)
+  svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)
+
+  ## Lock down the source.
+  args = map(lambda x: x.authz_name(), [sbox, sbox])
+  write_restrictive_svnserve_conf(sbox.repo_dir, anon_access='read')
+  svntest.main.file_write(sbox.authz_file,
+      "[%s:/]\n"
+      "* = r\n"
+      "[%s:/A]\n"
+      "* =  \n"
+      % tuple(args)
+  )
+
+  dest_url = svntest.main.file_scheme_prefix \
+             + svntest.main.pathname2url(os.path.abspath(dest_sbox.repo_dir))
+  run_init(dest_url, sbox.repo_url)
+  run_sync(dest_url)
+
+  # sanity check
+  svntest.actions.run_and_verify_svn(None, 
+                                     ["iota\n"], [],
+                                     'ls', dest_url+'/branch@2')
+
+
 ########################################################################
 # Run the tests
 
@@ -1062,6 +1073,7 @@ test_list = [ None,
               descend_into_replace,
               delete_revprops,
               fd_leak_sync_from_serf_to_local,
+              copy_delete_unreadable_child,
              ]
 serial_only = True
 

Modified: subversion/branches/1.7.x/subversion/tests/cmdline/svntest/sandbox.py
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/tests/cmdline/svntest/sandbox.py?rev=1355849&r1=1355848&r2=1355849&view=diff
==============================================================================
--- subversion/branches/1.7.x/subversion/tests/cmdline/svntest/sandbox.py (original)
+++ subversion/branches/1.7.x/subversion/tests/cmdline/svntest/sandbox.py Sun Jul  1 04:01:29 2012
@@ -101,6 +101,14 @@ class Sandbox:
     svntest.actions.make_repo_and_wc(self, create_wc, read_only)
     self._is_built = True
 
+  def authz_name(self, repo_dir=None):
+    "return this sandbox's name for use in an authz file"
+    repo_dir = repo_dir or self.repo_dir
+    if self.repo_url.startswith("http"):
+      return os.path.basename(repo_dir)
+    else:
+      return repo_dir.replace('\\', '/')
+
   def add_test_path(self, path, remove=True):
     self.test_paths.append(path)
     if remove: