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 2015/03/04 14:43:12 UTC

svn commit: r1663991 - /subversion/trunk/subversion/libsvn_wc/wc_db.c

Author: rhuijben
Date: Wed Mar  4 13:43:11 2015
New Revision: 1663991

URL: http://svn.apache.org/r1663991
Log:
Properly calculate the after-commit repository path of adds/replacements.

When a switched node is replaced (or a not present node has a different
repository path), the node was recorded as committed at a different
url then where it was actually committed.

A regression test (involving file externals) will be added shortly.

* subversion/libsvn_wc/wc_db.c
  (determine_repos_info): Rename to...
  (determine_commit_repos_info): ... this, to make it clear that it
    follows commit rules. Properly follow the shadowing rules for
    calculating the commit paths.

  (commit_node): Update caller.

Modified:
    subversion/trunk/subversion/libsvn_wc/wc_db.c

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1663991&r1=1663990&r2=1663991&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Wed Mar  4 13:43:11 2015
@@ -11357,59 +11357,86 @@ svn_wc__db_global_relocate(svn_wc__db_t
 }
 
 
-/* Set *REPOS_ID and *REPOS_RELPATH to the BASE repository location of
+/* Helper for commit_node()
+   Set *REPOS_ID and *REPOS_RELPATH to the BASE repository location of
    (WCROOT, LOCAL_RELPATH), directly if its BASE row exists or implied from
    its parent's BASE row if not. In the latter case, error if the parent
    BASE row does not exist.  */
 static svn_error_t *
-determine_repos_info(apr_int64_t *repos_id,
-                     const char **repos_relpath,
-                     svn_wc__db_wcroot_t *wcroot,
-                     const char *local_relpath,
-                     apr_pool_t *result_pool,
-                     apr_pool_t *scratch_pool)
+determine_commit_repos_info(apr_int64_t *repos_id,
+                            const char **repos_relpath,
+                            svn_wc__db_wcroot_t *wcroot,
+                            const char *local_relpath,
+                            apr_pool_t *result_pool,
+                            apr_pool_t *scratch_pool)
 {
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
-  const char *repos_parent_relpath;
-  const char *local_parent_relpath, *name;
-
-  /* ### is it faster to fetch fewer columns? */
+  int op_depth;
 
   /* Prefer the current node's repository information.  */
   SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                    STMT_SELECT_BASE_NODE));
+                                    STMT_SELECT_NODE_INFO));
   SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
 
-  if (have_row)
-    {
-      SVN_ERR_ASSERT(!svn_sqlite__column_is_null(stmt, 0));
-      SVN_ERR_ASSERT(!svn_sqlite__column_is_null(stmt, 1));
+  if (!have_row)
+    return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND,
+                             svn_sqlite__reset(stmt),
+                             _("The node '%s' was not found."),
+                             path_for_error_message(wcroot, local_relpath,
+                                                    scratch_pool));
+
+  op_depth = svn_sqlite__column_int(stmt, 0);
 
-      *repos_id = svn_sqlite__column_int64(stmt, 0);
-      *repos_relpath = svn_sqlite__column_text(stmt, 1, result_pool);
+  if (op_depth > 0)
+    {
+      svn_wc__db_status_t presence = svn_sqlite__column_token(stmt, 3,
+                                                              presence_map);
 
-      return svn_error_trace(svn_sqlite__reset(stmt));
+      if (presence == svn_wc__db_status_base_deleted)
+        {
+          SVN_ERR(svn_sqlite__step_row(stmt)); /* There must be a row */
+          op_depth = svn_sqlite__column_int(stmt, 0);
+        }
+      else
+        {
+          const char *parent_repos_relpath;
+          const char *parent_relpath;
+          const char *name;
+
+          SVN_ERR(svn_sqlite__reset(stmt));
+
+          /* The repository relative path of an add/copy is based on its
+             ancestor, not on the shadowed base layer.
+
+             As this function is only used from the commit processing we know
+             the parent directory has only a BASE row, so we can just obtain
+             the information directly by recursing (once!)  */
+
+          svn_relpath_split(&parent_relpath, &name, local_relpath,
+                            scratch_pool);
+
+          SVN_ERR(determine_commit_repos_info(repos_id, &parent_repos_relpath,
+                                              wcroot, parent_relpath,
+                                              scratch_pool, scratch_pool));
+
+          *repos_relpath = svn_relpath_join(parent_repos_relpath, name,
+                                            result_pool);
+          return SVN_NO_ERROR;
+        }
     }
 
-  SVN_ERR(svn_sqlite__reset(stmt));
 
-  /* This was a child node within this wcroot. We want to look at the
-     BASE node of the directory.  */
-  svn_relpath_split(&local_parent_relpath, &name, local_relpath, scratch_pool);
-
-  /* The REPOS_ID will be the same (### until we support mixed-repos)  */
-  SVN_ERR(svn_wc__db_base_get_info_internal(NULL, NULL, NULL,
-                                            &repos_parent_relpath, repos_id,
-                                            NULL, NULL, NULL, NULL, NULL,
-                                            NULL, NULL, NULL, NULL, NULL,
-                                            wcroot, local_parent_relpath,
-                                            scratch_pool, scratch_pool));
+  SVN_ERR_ASSERT(op_depth == 0); /* And that row must be BASE */
 
-  *repos_relpath = svn_relpath_join(repos_parent_relpath, name, result_pool);
+  SVN_ERR_ASSERT(!svn_sqlite__column_is_null(stmt, 1));
+  SVN_ERR_ASSERT(!svn_sqlite__column_is_null(stmt, 2));
 
-  return SVN_NO_ERROR;
+  *repos_id = svn_sqlite__column_int64(stmt, 1);
+  *repos_relpath = svn_sqlite__column_text(stmt, 2, result_pool);
+
+  return svn_error_trace(svn_sqlite__reset(stmt));
 }
 
 static svn_error_t *
@@ -11616,9 +11643,9 @@ commit_node(svn_wc__db_wcroot_t *wcroot,
 
      For existing nodes, we should retain the (potentially-switched)
      repository information.  */
-  SVN_ERR(determine_repos_info(&repos_id, &repos_relpath,
-                               wcroot, local_relpath,
-                               scratch_pool, scratch_pool));
+  SVN_ERR(determine_commit_repos_info(&repos_id, &repos_relpath,
+                                      wcroot, local_relpath,
+                                      scratch_pool, scratch_pool));
 
   /* ### is it better to select only the data needed?  */
   SVN_ERR(svn_sqlite__get_statement(&stmt_info, wcroot->sdb,