Author: stsp Date: Tue Sep 25 14:26:10 2012 New Revision: 1389878 URL: http://svn.apache.org/viewvc?rev=1389878&view=rev Log: Fix working copy access via a symlink which points to a working copy nested within an unrelated working copy of an unsupported format.
This patch fixes special_tests 19 and 20 on the 1.7.x branch when run within a format 30 working copy (backport nomination will follow). To reproduce the problem fixed by this commit with just a trunk client: - Check out a working copy WC1. - Check out one nested working copy WC2 within WC1's root dir. - Use sqlite3 to set "pragma user_version = 31" in WC1's .svn/wc.db. - Create a symlink S with WC1 which points at WC2. - Try to run 'svn status' on the symlink S. * subversion/libsvn_wc/wc_db_wcroot.c (svn_wc__db_wcroot_parse_local_abspath): If we find an unsupported working copy after traversing upwards from a symlink, and the symlink points to a directory, try to find a working copy at that directory instead. Modified: subversion/trunk/subversion/libsvn_wc/wc_db_wcroot.c 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=1389878&r1=1389877&r2=1389878&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_wc/wc_db_wcroot.c (original) +++ subversion/trunk/subversion/libsvn_wc/wc_db_wcroot.c Tue Sep 25 14:26:10 2012 @@ -599,11 +599,22 @@ try_symlink_as_dir: inside the wcroot, but we know the abspath is this directory (ie. where we found it). */ - SVN_ERR(svn_wc__db_pdh_create_wcroot(wcroot, + err = svn_wc__db_pdh_create_wcroot(wcroot, apr_pstrdup(db->state_pool, local_abspath), sdb, wc_id, FORMAT_FROM_SDB, db->auto_upgrade, db->enforce_empty_wq, - db->state_pool, scratch_pool)); + db->state_pool, scratch_pool); + if (err && err->apr_err == SVN_ERR_WC_UNSUPPORTED_FORMAT && + kind == svn_kind_symlink) + { + /* We found an unsupported WC after traversing upwards from a + * symlink. Fall through to code below to check if the symlink + * points at a supported WC. */ + svn_error_clear(err); + *wcroot = NULL; + } + else + SVN_ERR(err); } else { @@ -615,16 +626,17 @@ try_symlink_as_dir: db->state_pool, scratch_pool)); } - { - const char *dir_relpath; + if (*wcroot) + { + const char *dir_relpath; + + /* The subdirectory's relpath is easily computed relative to the + wcroot that we just found. */ + dir_relpath = compute_relpath(*wcroot, local_dir_abspath, NULL); - /* The subdirectory's relpath is easily computed relative to the - wcroot that we just found. */ - dir_relpath = compute_relpath(*wcroot, local_dir_abspath, NULL); - - /* And the result local_relpath may include a filename. */ - *local_relpath = svn_relpath_join(dir_relpath, build_relpath, result_pool); - } + /* And the result local_relpath may include a filename. */ + *local_relpath = svn_relpath_join(dir_relpath, build_relpath, result_pool); + } if (kind == svn_kind_symlink) { @@ -638,33 +650,38 @@ try_symlink_as_dir: * points to a directory, try to find a wcroot in that directory * instead. */ - err = svn_wc__db_read_info_internal(&status, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, - NULL, &conflicted, NULL, NULL, NULL, - NULL, NULL, NULL, - *wcroot, *local_relpath, - scratch_pool, scratch_pool); - if (err) + if (*wcroot) { - if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND - && !SVN_WC__ERR_IS_NOT_CURRENT_WC(err)) - return svn_error_trace(err); + err = svn_wc__db_read_info_internal(&status, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, &conflicted, + NULL, NULL, NULL, NULL, NULL, + NULL, *wcroot, *local_relpath, + scratch_pool, scratch_pool); + if (err) + { + if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND + && !SVN_WC__ERR_IS_NOT_CURRENT_WC(err)) + return svn_error_trace(err); - svn_error_clear(err); - retry_if_dir = TRUE; /* The symlink is unversioned. */ + svn_error_clear(err); + retry_if_dir = TRUE; /* The symlink is unversioned. */ + } + else + { + /* The symlink is versioned, or obstructs a versioned node. + * Ignore non-conflicted not-present/excluded nodes. + * This allows the symlink to redirect the wcroot query to a + * directory, regardless of 'invisible' nodes in this WC. */ + retry_if_dir = ((status == svn_wc__db_status_not_present || + status == svn_wc__db_status_excluded || + status == svn_wc__db_status_server_excluded) + && !conflicted); + } } else - { - /* The symlink is versioned, or obstructs a versioned node. - * Ignore non-conflicted not-present/excluded nodes. - * This allows the symlink to redirect the wcroot query to a - * directory, regardless of 'invisible' nodes in this WC. */ - retry_if_dir = ((status == svn_wc__db_status_not_present || - status == svn_wc__db_status_excluded || - status == svn_wc__db_status_server_excluded) - && !conflicted); - } + retry_if_dir = TRUE; if (retry_if_dir) {