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 2012/10/08 22:21:31 UTC

svn commit: r1395754 - in /subversion/trunk/subversion: libsvn_wc/wc_db_wcroot.c tests/cmdline/special_tests.py

Author: stsp
Date: Mon Oct  8 20:21:30 2012
New Revision: 1395754

URL: http://svn.apache.org/viewvc?rev=1395754&view=rev
Log:
Fix adding symlinks pointing at working copy roots to version control,
which had been broken since r1395027.

Fixes special_tests 23, "externals as symlink targets", which adds
a symlink pointing at an external. This test failed because the
symlink path itself was cached as wcroot when adding the symlink
to the external's parent WC. The code then tried a propset on the
symlink path to set the svn:special prop and was redirected at the
external working copy which it didnt' have a lock for.

We can fix this by never caching a symlink itself as a WC root but
caching the directory the symlink points to as a WC root instead.

* subversion/libsvn_wc/wc_db_wcroot.c
  (read_link_target): New helper function to calculate the absolute path
   of a symlink target.
  (svn_wc__db_wcroot_parse_local_abspath): When retrying the scan through a
   symlink, resolve the symlink and scan up from the link target, rather
   than treating the symlink itself as a directory. If the symlink points
   at a WC root, this prevents the symlink itself from being added to the
   WC root cache -- the cache should only contain directories anyway.

* subversion/tests/cmdline/special_tests.py
  (symlink_to_wc_basic): When operating on a WC through a symlink, we'll
   now see the resolved symlink target path as Working Copy Root path
   in 'svn info' output. Adjust test expectations accordingly. This test
   was expecting to see the symlink itself as WC root path.

Modified:
    subversion/trunk/subversion/libsvn_wc/wc_db_wcroot.c
    subversion/trunk/subversion/tests/cmdline/special_tests.py

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=1395754&r1=1395753&r2=1395754&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db_wcroot.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db_wcroot.c Mon Oct  8 20:21:30 2012
@@ -26,6 +26,7 @@
 #include <assert.h>
 
 #include "svn_dirent_uri.h"
+#include "svn_path.h"
 
 #include "wc.h"
 #include "adm_files.h"
@@ -353,6 +354,40 @@ compute_relpath(const svn_wc__db_wcroot_
 }
 
 
+/* Return in *LINK_TARGET_ABSPATH the absolute path the symlink at
+ * LOCAL_ABSPATH is pointing to. Perform all allocations in POOL. */
+static svn_error_t *
+read_link_target(const char **link_target_abspath,
+                 const char *local_abspath,
+                 apr_pool_t *pool)
+{
+  svn_string_t *link_target;
+  const char *canon_link_target;
+
+  SVN_ERR(svn_io_read_link(&link_target, local_abspath, pool));
+  canon_link_target = svn_dirent_canonicalize(link_target->data, pool);
+                
+  if (!svn_dirent_is_absolute(canon_link_target))
+    {
+      /* Treat symlink as relative to LOCAL_ABSPATH's parent directory. */
+      canon_link_target = svn_dirent_join(svn_dirent_dirname(local_abspath,
+                                                             pool),
+                                          canon_link_target, pool);
+      SVN_ERR(svn_dirent_get_absolute(link_target_abspath, canon_link_target,
+                                      pool));
+    }
+  else if (svn_path_is_backpath_present(canon_link_target))
+    {
+      /* Collapse any .. in the symlink part of the path. */
+      SVN_ERR(svn_dirent_get_absolute(link_target_abspath, canon_link_target,
+                                      pool));
+    }
+  else
+    *link_target_abspath = canon_link_target;
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_wc__db_wcroot_parse_local_abspath(svn_wc__db_wcroot_t **wcroot,
                                       const char **local_relpath,
@@ -543,6 +578,8 @@ svn_wc__db_wcroot_parse_local_abspath(sv
                   if (found_wcroot)
                     break;
 
+                  SVN_ERR(read_link_target(&local_abspath, local_abspath,
+                                           scratch_pool));
 try_symlink_as_dir:
                   kind = svn_kind_dir;
                   moved_upwards = FALSE;
@@ -692,7 +729,8 @@ try_symlink_as_dir:
                                              scratch_pool));
           if (resolved_kind == svn_node_dir)
             {
-              local_abspath = original_abspath;
+              SVN_ERR(read_link_target(&local_abspath, original_abspath,
+                                       scratch_pool));
               goto try_symlink_as_dir;
             }
         }

Modified: subversion/trunk/subversion/tests/cmdline/special_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/special_tests.py?rev=1395754&r1=1395753&r2=1395754&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/special_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/special_tests.py Mon Oct  8 20:21:30 2012
@@ -819,7 +819,7 @@ def symlink_to_wc_basic(sbox):
   wc_uuid = svntest.actions.get_wc_uuid(wc_dir)
   expected_info = [{
       'Path' : re.escape(os.path.join(symlink_path)),
-      'Working Copy Root Path' : re.escape(os.path.abspath(symlink_path)),
+      'Working Copy Root Path' : re.escape(os.path.abspath(wc_dir)),
       'Repository Root' : sbox.repo_url,
       'Repository UUID' : wc_uuid,
       'Revision' : '1',
@@ -828,7 +828,7 @@ def symlink_to_wc_basic(sbox):
   }, {
       'Name' : 'iota',
       'Path' : re.escape(os.path.join(symlink_path, 'iota')),
-      'Working Copy Root Path' : re.escape(os.path.abspath(symlink_path)),
+      'Working Copy Root Path' : re.escape(os.path.abspath(wc_dir)),
       'Repository Root' : sbox.repo_url,
       'Repository UUID' : wc_uuid,
       'Revision' : '1',