You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2013/02/28 15:56:25 UTC

svn commit: r1451221 - in /subversion/trunk/subversion: libsvn_wc/ tests/libsvn_wc/

Author: rhuijben
Date: Thu Feb 28 14:56:24 2013
New Revision: 1451221

URL: http://svn.apache.org/r1451221
Log:
Add a new svn_wc__db_scan_moved() function based on the internal scan_added()
which allows access to a bit more information. Use this information to fix
a case where a specific move could never be committed.

* subversion/libsvn_wc/adm_files.c
  (svn_wc__internal_ensure_adm): Update caller.

* subversion/libsvn_wc/adm_ops.c
  (check_can_add_to_parent): Update caller.

* subversion/libsvn_wc/copy.c
  (copy_or_move): Update caller.

* subversion/libsvn_wc/entries.c
  (get_info_for_deleted,
   read_one_entry): Update caller.

* subversion/libsvn_wc/info.c
  (build_info_for_node): Update caller. Only read moved_from for
    op-roots, like how we handle copies.

* subversion/libsvn_wc/node.c
  (svn_wc__internal_get_repos_info): Update caller.
  (svn_wc__internal_get_origin): Update caller.
  (svn_wc__node_was_moved_here): Use new api.

* subversion/libsvn_wc/status.c
  (read_info): Use different output argument of svn_wc__db_scan_addition.
  (assemble_status): Reduce scope of err. Use new api for obtaining moved
    from information.

* subversion/libsvn_wc/update_editor.c
  (check_tree_conflict,
   add_directory,
   add_file): Update caller.

* subversion/libsvn_wc/wc_db.c
  (svn_wc__db_scan_addition): Remove two arguments. Tell implementation which
    arguments are not needed to avoid additional queries in generic cases.
  (svn_wc__db_scan_moved): New function.

* subversion/libsvn_wc/wc_db.h
  (svn_wc__db_scan_addition): Remove moved_from handling additional
    information as no api user is really depending on it.
  (svn_wc__db_scan_moved): New function.

* subversion/tests/libsvn_wc/db-test.c
  (test_scan_addition): Update caller. Also call svn_wc__db_scan_moved.

* subversion/tests/libsvn_wc/op-depth-test.c
  (nested_move_commit): Use new api.
  (test_funcs): Remove XFail from commit_moved_descendant.

Modified:
    subversion/trunk/subversion/libsvn_wc/adm_files.c
    subversion/trunk/subversion/libsvn_wc/adm_ops.c
    subversion/trunk/subversion/libsvn_wc/copy.c
    subversion/trunk/subversion/libsvn_wc/entries.c
    subversion/trunk/subversion/libsvn_wc/info.c
    subversion/trunk/subversion/libsvn_wc/node.c
    subversion/trunk/subversion/libsvn_wc/status.c
    subversion/trunk/subversion/libsvn_wc/update_editor.c
    subversion/trunk/subversion/libsvn_wc/wc_db.c
    subversion/trunk/subversion/libsvn_wc/wc_db.h
    subversion/trunk/subversion/tests/libsvn_wc/db-test.c
    subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c

Modified: subversion/trunk/subversion/libsvn_wc/adm_files.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/adm_files.c?rev=1451221&r1=1451220&r2=1451221&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/adm_files.c (original)
+++ subversion/trunk/subversion/libsvn_wc/adm_files.c Thu Feb 28 14:56:24 2013
@@ -460,8 +460,8 @@ svn_wc__internal_ensure_adm(svn_wc__db_t
                                              &db_repos_relpath,
                                              &db_repos_root_url,
                                              &db_repos_uuid,
-                                             NULL, NULL, NULL, NULL, NULL,
-                                             NULL, db, local_abspath,
+                                             NULL, NULL, NULL, NULL,
+                                             db, local_abspath,
                                              scratch_pool, scratch_pool));
           else
             SVN_ERR(svn_wc__db_scan_base_repos(&db_repos_relpath,

Modified: subversion/trunk/subversion/libsvn_wc/adm_ops.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/adm_ops.c?rev=1451221&r1=1451220&r2=1451221&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/adm_ops.c (original)
+++ subversion/trunk/subversion/libsvn_wc/adm_ops.c Thu Feb 28 14:56:24 2013
@@ -626,7 +626,7 @@ check_can_add_to_parent(const char **rep
       if (parent_status == svn_wc__db_status_added)
         SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, NULL,
                                          repos_root_url, repos_uuid, NULL,
-                                         NULL, NULL, NULL, NULL, NULL,
+                                         NULL, NULL, NULL,
                                          db, parent_abspath,
                                          result_pool, scratch_pool));
       else

Modified: subversion/trunk/subversion/libsvn_wc/copy.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/copy.c?rev=1451221&r1=1451220&r2=1451221&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/copy.c (original)
+++ subversion/trunk/subversion/libsvn_wc/copy.c Thu Feb 28 14:56:24 2013
@@ -619,7 +619,7 @@ copy_or_move(svn_boolean_t *move_degrade
           SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, NULL,
                                            &src_repos_root_url,
                                            &src_repos_uuid, NULL, NULL, NULL,
-                                           NULL, NULL, NULL,
+                                           NULL,
                                            db, src_abspath,
                                            scratch_pool, scratch_pool));
         else
@@ -636,7 +636,7 @@ copy_or_move(svn_boolean_t *move_degrade
           SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, NULL,
                                            &dst_repos_root_url,
                                            &dst_repos_uuid, NULL, NULL, NULL,
-                                           NULL, NULL, NULL,
+                                           NULL,
                                            db, dstdir_abspath,
                                            scratch_pool, scratch_pool));
         else

Modified: subversion/trunk/subversion/libsvn_wc/entries.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/entries.c?rev=1451221&r1=1451220&r2=1451221&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/entries.c (original)
+++ subversion/trunk/subversion/libsvn_wc/entries.c Thu Feb 28 14:56:24 2013
@@ -278,7 +278,7 @@ get_info_for_deleted(svn_wc_entry_t *ent
                                        &parent_repos_relpath,
                                        &entry->repos,
                                        &entry->uuid,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
+                                       NULL, NULL, NULL, NULL,
                                        db, parent_abspath,
                                        result_pool, scratch_pool));
 
@@ -610,7 +610,6 @@ read_one_entry(const svn_wc_entry_t **ne
                                            &scanned_original_relpath,
                                            NULL, NULL, /* original_root|uuid */
                                            &original_revision,
-                                           NULL, NULL,
                                            db,
                                            entry_abspath,
                                            result_pool, scratch_pool));
@@ -712,7 +711,7 @@ read_one_entry(const svn_wc_entry_t **ne
                                              NULL, NULL, NULL,
                                              &parent_repos_relpath,
                                              &parent_root_url,
-                                             NULL, NULL, NULL, NULL,
+                                             NULL, NULL,
                                              db, parent_abspath,
                                              scratch_pool,
                                              scratch_pool);

Modified: subversion/trunk/subversion/libsvn_wc/info.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/info.c?rev=1451221&r1=1451220&r2=1451221&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/info.c (original)
+++ subversion/trunk/subversion/libsvn_wc/info.c Thu Feb 28 14:56:24 2013
@@ -144,19 +144,27 @@ build_info_for_node(svn_wc__info2_t **in
 
           if (op_root)
             {
+              svn_error_t *err;
               wc_info->copyfrom_url =
                     svn_path_url_add_component2(tmpinfo->repos_root_URL,
                                                 original_repos_relpath,
                                                 result_pool);
 
               wc_info->copyfrom_rev = original_revision;
-            }
 
-          SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, NULL, NULL, NULL, NULL,
-                                           NULL, NULL, NULL,
-                                           &wc_info->moved_from_abspath, NULL,
-                                           db, local_abspath,
-                                           result_pool, scratch_pool));
+              err = svn_wc__db_scan_moved(&wc_info->moved_from_abspath,
+                                          NULL, NULL, NULL,
+                                          db, local_abspath,
+                                          result_pool, scratch_pool);
+
+              if (err)
+                {
+                   if (err->apr_err != SVN_ERR_WC_PATH_UNEXPECTED_STATUS)
+                      return svn_error_trace(err);
+                   svn_error_clear(err);
+                   wc_info->moved_from_abspath = NULL;
+                }
+            }
         }
       else if (op_root)
         {
@@ -164,7 +172,7 @@ build_info_for_node(svn_wc__info2_t **in
           SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, &repos_relpath,
                                            &tmpinfo->repos_root_URL,
                                            &tmpinfo->repos_UUID,
-                                           NULL, NULL, NULL, NULL, NULL, NULL,
+                                           NULL, NULL, NULL, NULL,
                                            db, local_abspath,
                                            result_pool, scratch_pool));
 
@@ -246,7 +254,7 @@ build_info_for_node(svn_wc__info2_t **in
                                            &tmpinfo->repos_root_URL,
                                            &tmpinfo->repos_UUID,
                                            NULL, NULL, NULL,
-                                           &tmpinfo->rev, NULL, NULL,
+                                           &tmpinfo->rev,
                                            db, added_abspath,
                                            result_pool, scratch_pool));
 

Modified: subversion/trunk/subversion/libsvn_wc/node.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/node.c?rev=1451221&r1=1451220&r2=1451221&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/node.c (original)
+++ subversion/trunk/subversion/libsvn_wc/node.c Thu Feb 28 14:56:24 2013
@@ -204,7 +204,6 @@ svn_wc__internal_get_repos_info(svn_revn
                                                     ? &op_root_abspath : NULL,
                                            repos_relpath, repos_root_url,
                                            repos_uuid, NULL, NULL, NULL, NULL,
-                                           NULL, NULL,
                                            db, svn_dirent_dirname(
                                                    wrk_del_abspath,
                                                    scratch_pool),
@@ -229,7 +228,6 @@ svn_wc__internal_get_repos_info(svn_revn
                                                     ? &op_root_abspath : NULL,
                                        repos_relpath, repos_root_url,
                                        repos_uuid, NULL, NULL, NULL, NULL,
-                                       NULL, NULL,
                                        db, local_abspath,
                                        result_pool, scratch_pool));
     }
@@ -1024,7 +1022,7 @@ svn_wc__internal_get_origin(svn_boolean_
         SVN_ERR(svn_wc__db_scan_addition(&status, &op_root_abspath, NULL,
                                          NULL, NULL, &original_repos_relpath,
                                          repos_root_url,
-                                         repos_uuid, revision, NULL, NULL,
+                                         repos_uuid, revision,
                                          db, local_abspath,
                                          result_pool, scratch_pool));
 
@@ -1387,36 +1385,27 @@ svn_wc__node_was_moved_here(const char *
                             apr_pool_t *result_pool,
                             apr_pool_t *scratch_pool)
 {
-  svn_boolean_t is_added;
+  svn_error_t *err;
 
   if (moved_from_abspath)
     *moved_from_abspath = NULL;
   if (delete_op_root_abspath)
     *delete_op_root_abspath = NULL;
 
-  SVN_ERR(svn_wc__node_is_added(&is_added, wc_ctx, local_abspath,
-                                scratch_pool));
-  if (is_added && (moved_from_abspath || delete_op_root_abspath))
+  err = svn_wc__db_scan_moved(moved_from_abspath, NULL, NULL,
+                              delete_op_root_abspath,
+                              wc_ctx->db, local_abspath,
+                              result_pool, scratch_pool);
+
+  if (err)
     {
-      svn_wc__db_status_t status;
-      const char *db_moved_from_abspath;
-      const char *db_delete_op_root_abspath;
-
-      SVN_ERR(svn_wc__db_scan_addition(&status, NULL,
-                                       NULL, NULL, NULL, NULL, NULL,
-                                       NULL, NULL, &db_moved_from_abspath,
-                                       &db_delete_op_root_abspath,
-                                       wc_ctx->db, local_abspath,
-                                       scratch_pool, scratch_pool));
-      if (status == svn_wc__db_status_moved_here)
-        {
-          if (moved_from_abspath)
-            *moved_from_abspath = apr_pstrdup(result_pool,
-                                              db_moved_from_abspath);
-          if (delete_op_root_abspath)
-            *delete_op_root_abspath = apr_pstrdup(result_pool,
-                                                  db_delete_op_root_abspath);
-        }
+      /* Return error for not added nodes */
+      if (err->apr_err != SVN_ERR_WC_PATH_UNEXPECTED_STATUS)
+        return svn_error_trace(err);
+
+      /* Path not moved here */
+      svn_error_clear(err);
+      return SVN_NO_ERROR;
     }
 
   return SVN_NO_ERROR;

Modified: subversion/trunk/subversion/libsvn_wc/status.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/status.c?rev=1451221&r1=1451220&r2=1451221&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/status.c (original)
+++ subversion/trunk/subversion/libsvn_wc/status.c Thu Feb 28 14:56:24 2013
@@ -346,16 +346,14 @@ read_info(const struct svn_wc__db_info_t
    * cheaply as svn_wc__db_read_children_info() does. */
   if (mtb->status == svn_wc__db_status_added)
     {
-      const char *moved_from_abspath = NULL;
       svn_wc__db_status_t status;
 
       SVN_ERR(svn_wc__db_scan_addition(&status, NULL, NULL, NULL, NULL,
                                        NULL, NULL, NULL, NULL,
-                                       &moved_from_abspath,
-                                       NULL,
                                        db, local_abspath,
                                        result_pool, scratch_pool));
-      mtb->moved_here = (moved_from_abspath != NULL);
+
+      mtb->moved_here = (status == svn_wc__db_status_moved_here);
       mtb->incomplete = (status == svn_wc__db_status_incomplete);
     }
 
@@ -421,7 +419,7 @@ get_repos_root_url_relpath(const char **
       SVN_ERR(svn_wc__db_scan_addition(NULL, NULL,
                                        repos_relpath, repos_root_url,
                                        repos_uuid, NULL, NULL, NULL, NULL,
-                                       NULL, NULL, db, local_abspath,
+                                       db, local_abspath,
                                        result_pool, scratch_pool));
     }
   else if (info->have_base)
@@ -484,7 +482,6 @@ assemble_status(svn_wc_status3_t **statu
   svn_boolean_t switched_p = FALSE;
   svn_boolean_t copied = FALSE;
   svn_boolean_t conflicted;
-  svn_error_t *err;
   const char *moved_from_abspath = NULL;
   svn_filesize_t filesize = (dirent && (dirent->kind == svn_node_file))
                                 ? dirent->filesize
@@ -605,6 +602,7 @@ assemble_status(svn_wc_status3_t **statu
             text_modified_p = FALSE;
           else
             {
+              svn_error_t *err;
               err = svn_wc__internal_file_modified_p(&text_modified_p,
                                                      db, local_abspath,
                                                      FALSE, scratch_pool);
@@ -687,12 +685,24 @@ assemble_status(svn_wc_status3_t **statu
 
           /* Get moved-from info (only for potential op-roots of a move). */
           if (info->moved_here && info->op_root)
-            SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, NULL, NULL, NULL,
-                                             NULL, NULL, NULL, NULL,
-                                             &moved_from_abspath,
-                                             NULL,
-                                             db, local_abspath,
-                                             result_pool, scratch_pool));
+            {
+              svn_error_t *err;
+              err = svn_wc__db_scan_moved(&moved_from_abspath, NULL, NULL, NULL,
+                                          db, local_abspath,
+                                          result_pool, scratch_pool);
+
+              if (err)
+                {
+                  if (err->apr_err != SVN_ERR_WC_PATH_UNEXPECTED_STATUS)
+                    svn_error_trace(err);
+
+                  svn_error_clear(err);
+                  /* We are no longer moved... So most likely we are somehow
+                     changing the db for things like resolving conflicts. */
+
+                  moved_from_abspath = NULL;
+                }
+            }
         }
     }
 

Modified: subversion/trunk/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/update_editor.c?rev=1451221&r1=1451220&r2=1451221&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/update_editor.c Thu Feb 28 14:56:24 2013
@@ -1463,7 +1463,7 @@ check_tree_conflict(svn_skel_t **pconfli
             if (working_status == svn_wc__db_status_added)
               SVN_ERR(svn_wc__db_scan_addition(&working_status, NULL, NULL,
                                                NULL, NULL, NULL, NULL,
-                                               NULL, NULL, NULL, NULL,
+                                               NULL, NULL,
                                                eb->db, local_abspath,
                                                scratch_pool, scratch_pool));
 
@@ -2187,7 +2187,7 @@ add_directory(const char *path,
       /* Is the local add a copy? */
       if (status == svn_wc__db_status_added)
         SVN_ERR(svn_wc__db_scan_addition(&add_status, NULL, NULL, NULL, NULL,
-                                         NULL, NULL, NULL, NULL, NULL, NULL,
+                                         NULL, NULL, NULL, NULL,
                                          eb->db, db->local_abspath,
                                          pool, pool));
 
@@ -3274,7 +3274,7 @@ add_file(const char *path,
       /* Is the local node a copy or move */
       if (status == svn_wc__db_status_added)
         SVN_ERR(svn_wc__db_scan_addition(&status, NULL, NULL, NULL, NULL, NULL,
-                                         NULL, NULL, NULL, NULL, NULL,
+                                         NULL, NULL, NULL,
                                          eb->db, fb->local_abspath,
                                          scratch_pool, scratch_pool));
 
@@ -5172,7 +5172,7 @@ svn_wc_add_repos_file4(svn_wc_context_t 
           /* The parent is an addition, scan upwards to find the right info */
           SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, NULL,
                                            &repos_root_url, &repos_uuid,
-                                           NULL, NULL, NULL, NULL, NULL, NULL,
+                                           NULL, NULL, NULL, NULL,
                                            wc_ctx->db, dir_abspath,
                                            scratch_pool, scratch_pool));
         }

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1451221&r1=1451220&r2=1451221&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Thu Feb 28 14:56:24 2013
@@ -11738,8 +11738,6 @@ svn_wc__db_scan_addition(svn_wc__db_stat
                          const char **original_root_url,
                          const char **original_uuid,
                          svn_revnum_t *original_revision,
-                         const char **moved_from_abspath,
-                         const char **moved_from_op_root_abspath,
                          svn_wc__db_t *db,
                          const char *local_abspath,
                          apr_pool_t *result_pool,
@@ -11747,15 +11745,13 @@ svn_wc__db_scan_addition(svn_wc__db_stat
 {
   svn_wc__db_wcroot_t *wcroot;
   const char *local_relpath;
-  const char *op_root_relpath;
+  const char *op_root_relpath = NULL;
   apr_int64_t repos_id = INVALID_REPOS_ID;
   apr_int64_t original_repos_id = INVALID_REPOS_ID;
   apr_int64_t *repos_id_p
     = (repos_root_url || repos_uuid) ? &repos_id : NULL;
   apr_int64_t *original_repos_id_p
     = (original_root_url || original_uuid) ? &original_repos_id : NULL;
-  const char *moved_from_relpath;
-  const char *moved_from_op_root_relpath;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
@@ -11763,10 +11759,14 @@ svn_wc__db_scan_addition(svn_wc__db_stat
                               local_abspath, scratch_pool, scratch_pool));
   VERIFY_USABLE_WCROOT(wcroot);
 
-  SVN_ERR(scan_addition(status, &op_root_relpath, repos_relpath, repos_id_p,
+  SVN_ERR(scan_addition(status,
+                        op_root_abspath
+                                ? &op_root_relpath
+                                : NULL,
+                        repos_relpath, repos_id_p,
                         original_repos_relpath, original_repos_id_p,
-                        original_revision, &moved_from_relpath,
-                        &moved_from_op_root_relpath, NULL,
+                        original_revision,
+                        NULL, NULL, NULL,
                         wcroot, local_relpath, result_pool, scratch_pool));
 
   if (op_root_abspath)
@@ -11781,25 +11781,82 @@ svn_wc__db_scan_addition(svn_wc__db_stat
                                       wcroot->sdb, original_repos_id,
                                       result_pool));
 
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__db_scan_moved(const char **moved_from_abspath,
+                      const char **op_root_abspath,
+                      const char **op_root_moved_from_abspath,
+                      const char **moved_from_delete_abspath,
+                      svn_wc__db_t *db,
+                      const char *local_abspath,
+                      apr_pool_t *result_pool,
+                      apr_pool_t *scratch_pool)
+{
+  svn_wc__db_wcroot_t *wcroot;
+  const char *local_relpath;
+  svn_wc__db_status_t status;
+  const char *op_root_relpath = NULL;
+  const char *moved_from_relpath = NULL;
+  const char *moved_from_op_root_relpath = NULL;
+  int moved_from_op_depth = -1;
+
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+
+  SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
+                              local_abspath, scratch_pool, scratch_pool));
+  VERIFY_USABLE_WCROOT(wcroot);
+
+  SVN_ERR(scan_addition(&status,
+                        op_root_abspath
+                                ? &op_root_relpath
+                                : NULL,
+                        NULL, NULL,
+                        NULL, NULL, NULL,
+                        moved_from_abspath
+                            ? &moved_from_relpath
+                            : NULL,
+                        (op_root_moved_from_abspath
+                         || moved_from_delete_abspath)
+                            ? &moved_from_op_root_relpath
+                            : NULL,
+                        moved_from_delete_abspath
+                            ? &moved_from_op_depth
+                            : NULL,
+                        wcroot, local_relpath, scratch_pool, scratch_pool));
+
+  if (status != svn_wc__db_status_moved_here)
+    return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
+                             _("Path '%s' was not moved here"),
+                             path_for_error_message(wcroot, local_relpath,
+                                                    scratch_pool));
+
+  if (op_root_abspath)
+    *op_root_abspath = svn_dirent_join(wcroot->abspath, op_root_relpath,
+                                       result_pool);
+
   if (moved_from_abspath)
-    {
-      if (moved_from_relpath)
-        *moved_from_abspath = svn_dirent_join(wcroot->abspath,
-                                              moved_from_relpath,
-                                              result_pool);
-      else
-        *moved_from_abspath = NULL;
-    }
+    *moved_from_abspath = svn_dirent_join(wcroot->abspath, moved_from_relpath,
+                                          result_pool);
+
+  if (op_root_moved_from_abspath)
+    *op_root_moved_from_abspath = svn_dirent_join(wcroot->abspath,
+                                                  moved_from_op_root_relpath,
+                                                  result_pool);
 
-  if (moved_from_op_root_abspath)
+  /* The deleted node is either where we moved from, or one of its ancestors */
+  if (moved_from_delete_abspath)
     {
-      if (moved_from_op_root_relpath)
-        *moved_from_op_root_abspath =
-          svn_dirent_join(wcroot->abspath,
-                          moved_from_op_root_relpath,
-                          result_pool);
-      else
-        *moved_from_op_root_abspath = NULL;
+      const char *tmp = moved_from_op_root_relpath;
+
+      SVN_ERR_ASSERT(moved_from_op_depth >= 0);
+
+      while (relpath_depth(tmp) > moved_from_op_depth)
+        tmp = svn_relpath_dirname(tmp, scratch_pool);
+
+      *moved_from_delete_abspath = svn_dirent_join(wcroot->abspath, tmp,
+                                                   scratch_pool);
     }
 
   return SVN_NO_ERROR;

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.h?rev=1451221&r1=1451220&r2=1451221&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.h Thu Feb 28 14:56:24 2013
@@ -2641,12 +2641,6 @@ svn_wc__db_scan_base_repos(const char **
        BASE node. And again, the REPOS_* values are implied by this node's
        position in the subtree under the ancestor unshadowed BASE node.
        ORIGINAL_* will indicate the source of the move.
-       Additionally, information about the local move source is provided.
-       If MOVED_FROM_ABSPATH is not NULL, set *MOVED_FROM_ABSPATH to the
-       absolute path of the move source node in the working copy.
-       If MOVED_FROM_OP_ROOT_ABSPATH is not NULL, set
-       *MOVED_FROM_OP_ROOT_ABSPATH to the absolute path of the op-root of the
-       delete-half of the move.
 
    All OUT parameters may be NULL to indicate a lack of interest in
    that piece of information.
@@ -2677,13 +2671,46 @@ svn_wc__db_scan_addition(svn_wc__db_stat
                          const char **original_root_url,
                          const char **original_uuid,
                          svn_revnum_t *original_revision,
-                         const char **moved_from_abspath,
-                         const char **moved_from_oproot_abspath,
                          svn_wc__db_t *db,
                          const char *local_abspath,
                          apr_pool_t *result_pool,
                          apr_pool_t *scratch_pool);
 
+/* Scan the working copy for move information of the node LOCAL_ABSPATH.
+ * If LOCAL_ABSPATH return a SVN_ERR_WC_PATH_UNEXPECTED_STATUS error.
+ *
+ * If not NULL *MOVED_FROM_ABSPATH will be set to the previous location
+ * of LOCAL_ABSPATH, before it or an ancestror was moved.
+ *
+ * If not NULL *OP_ROOT_ABSPATH will be set to the new location of the
+ * path that was actually moved
+ *
+ * If not NULL *OP_ROOT_MOVED_FROM_ABSPATH will be set to the old location
+ * of the path that was actually moved.
+ *
+ * If not NULL *MOVED_FROM_DELETE_ABSPATH will be set to the ancestor of the
+ * moved from location that deletes the original location
+ *
+ * Given a working copy
+ * A/B/C
+ * svn mv A/B D
+ * svn rm A
+ *
+ * You can call this function on D and D/C. When called on D/C all output
+ *              MOVED_FROM_ABSPATH will be A/B/C
+ *              OP_ROOT_ABSPATH will be D
+ *              OP_ROOT_MOVED_FROM_ABSPATH will be A/B
+ *              MOVED_FROM_DELETE_ABSPATH will be A
+ */
+svn_error_t *
+svn_wc__db_scan_moved(const char **moved_from_abspath,
+                      const char **op_root_abspath,
+                      const char **op_root_moved_from_abspath,
+                      const char **moved_from_delete_abspath,
+                      svn_wc__db_t *db,
+                      const char *local_abspath,
+                      apr_pool_t *result_pool,
+                      apr_pool_t *scratch_pool);
 
 /* Scan upwards for additional information about a deleted node.
 

Modified: subversion/trunk/subversion/tests/libsvn_wc/db-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_wc/db-test.c?rev=1451221&r1=1451220&r2=1451221&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_wc/db-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_wc/db-test.c Thu Feb 28 14:56:24 2013
@@ -925,6 +925,8 @@ test_scan_addition(apr_pool_t *pool)
   const char *original_uuid;
   svn_revnum_t original_revision;
   const char *moved_from_abspath;
+  const char *move_op_root_abspath;
+  const char *move_op_root_src;
   const char *delete_op_root_abspath;
 
   SVN_ERR(create_open(&db, &local_abspath, "test_scan_addition", pool));
@@ -934,7 +936,7 @@ test_scan_addition(apr_pool_t *pool)
             &status, &op_root_abspath,
             &repos_relpath, &repos_root_url, &repos_uuid,
             &original_repos_relpath, &original_root_url, &original_uuid,
-            &original_revision, NULL, NULL,
+            &original_revision,
             db, svn_dirent_join(local_abspath, "J", pool),
             pool, pool));
   SVN_TEST_ASSERT(status == svn_wc__db_status_added);
@@ -952,7 +954,7 @@ test_scan_addition(apr_pool_t *pool)
             &status, &op_root_abspath,
             &repos_relpath, &repos_root_url, &repos_uuid,
             &original_repos_relpath, &original_root_url, &original_uuid,
-            &original_revision, NULL, NULL,
+            &original_revision,
             db, svn_dirent_join(local_abspath, "J/J-a", pool),
             pool, pool));
   SVN_TEST_ASSERT(status == svn_wc__db_status_added);
@@ -970,7 +972,14 @@ test_scan_addition(apr_pool_t *pool)
             &status, &op_root_abspath,
             &repos_relpath, &repos_root_url, &repos_uuid,
             &original_repos_relpath, &original_root_url, &original_uuid,
-            &original_revision, &moved_from_abspath, &delete_op_root_abspath,
+            &original_revision,
+            db, svn_dirent_join(local_abspath, "J/J-d", pool),
+            pool, pool));
+  SVN_ERR(svn_wc__db_scan_moved(
+            &moved_from_abspath,
+            &move_op_root_abspath,
+            &move_op_root_src,
+            &delete_op_root_abspath,
             db, svn_dirent_join(local_abspath, "J/J-d", pool),
             pool, pool));
   SVN_TEST_ASSERT(status == svn_wc__db_status_moved_here);
@@ -978,6 +987,10 @@ test_scan_addition(apr_pool_t *pool)
                                    op_root_abspath, pool));
   SVN_TEST_ASSERT(validate_abspath(local_abspath, "moved/file",
                                    moved_from_abspath, pool));
+  SVN_TEST_ASSERT(validate_abspath(local_abspath, "J/J-d",
+                                   move_op_root_abspath, pool));
+  SVN_TEST_ASSERT(validate_abspath(local_abspath, "moved/file",
+                                   move_op_root_src, pool));
   SVN_TEST_ASSERT(validate_abspath(local_abspath, "moved/file",
                                    delete_op_root_abspath, pool));
   SVN_TEST_STRING_ASSERT(repos_relpath, "J/J-d");
@@ -993,7 +1006,7 @@ test_scan_addition(apr_pool_t *pool)
             &status, &op_root_abspath,
             &repos_relpath, &repos_root_url, &repos_uuid,
             &original_repos_relpath, &original_root_url, &original_uuid,
-            &original_revision, NULL, NULL,
+            &original_revision,
             db, svn_dirent_join(local_abspath, "J/J-b", pool),
             pool, pool));
   SVN_TEST_ASSERT(status == svn_wc__db_status_copied);
@@ -1012,7 +1025,7 @@ test_scan_addition(apr_pool_t *pool)
             &status, &op_root_abspath,
             &repos_relpath, &repos_root_url, &repos_uuid,
             &original_repos_relpath, &original_root_url, &original_uuid,
-            &original_revision, NULL, NULL,
+            &original_revision,
             db, svn_dirent_join(local_abspath, "J/J-b/J-b-a", pool),
             pool, pool));
   SVN_TEST_ASSERT(status == svn_wc__db_status_copied);
@@ -1031,7 +1044,7 @@ test_scan_addition(apr_pool_t *pool)
             &status, &op_root_abspath,
             &repos_relpath, &repos_root_url, &repos_uuid,
             &original_repos_relpath, &original_root_url, &original_uuid,
-            &original_revision, NULL, NULL,
+            &original_revision,
             db, svn_dirent_join(local_abspath, "J/J-b/J-b-b", pool),
             pool, pool));
   SVN_TEST_ASSERT(status == svn_wc__db_status_copied);

Modified: subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c?rev=1451221&r1=1451220&r2=1451221&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c Thu Feb 28 14:56:24 2013
@@ -5380,10 +5380,9 @@ nested_move_commit(const svn_test_opts_t
   {
     const char *moved_from;
     const char *expected_from;
-    SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                                     NULL, NULL, &moved_from, NULL,
-                                     b.wc_ctx->db, sbox_wc_path(&b, "C2"),
-                                     pool, pool));
+    SVN_ERR(svn_wc__db_scan_moved(&moved_from, NULL, NULL, NULL,
+                                  b.wc_ctx->db, sbox_wc_path(&b, "C2"),
+                                  pool, pool));
 
     expected_from = sbox_wc_path(&b, "A/B/C");
 
@@ -5446,10 +5445,9 @@ nested_move_commit(const svn_test_opts_t
   {
     const char *moved_from;
     const char *expected_from;
-    SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                                     NULL, NULL, &moved_from, NULL,
-                                     b.wc_ctx->db, sbox_wc_path(&b, "C2"),
-                                     pool, pool));
+    SVN_ERR(svn_wc__db_scan_moved(&moved_from, NULL, NULL, NULL,
+                                  b.wc_ctx->db, sbox_wc_path(&b, "C2"),
+                                  pool, pool));
 
     /* C2 is the A2/B/C->C2 move. */
     expected_from = sbox_wc_path(&b, "A2/B/C");
@@ -5505,10 +5503,9 @@ nested_move_commit(const svn_test_opts_t
   {
     const char *moved_from;
     const char *expected_from;
-    SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                                     NULL, NULL, &moved_from, NULL,
-                                     b.wc_ctx->db, sbox_wc_path(&b, "C2"),
-                                     pool, pool));
+    SVN_ERR(svn_wc__db_scan_moved(&moved_from, NULL, NULL, NULL,
+                                  b.wc_ctx->db, sbox_wc_path(&b, "C2"),
+                                  pool, pool));
 
     expected_from = sbox_wc_path(&b, "A2/B/C");
 
@@ -7507,8 +7504,8 @@ struct svn_test_descriptor_t test_funcs[
                        "layered_moved_to"),
     SVN_TEST_OPTS_PASS(update_within_move,
                        "update_within_move"),
-    SVN_TEST_OPTS_XFAIL(commit_moved_descendant,
-                        "commit_moved_descendant"),
+    SVN_TEST_OPTS_PASS(commit_moved_descendant,
+                       "commit_moved_descendant"),
     SVN_TEST_OPTS_XFAIL(commit_moved_away_descendant,
                         "commit_moved_away_descendant"),
     SVN_TEST_OPTS_PASS(finite_move_update_bump,