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 2011/04/14 13:49:44 UTC

svn commit: r1092145 - in /subversion/trunk/subversion: include/private/svn_wc_private.h libsvn_client/commit_util.c libsvn_client/copy.c libsvn_client/merge.c libsvn_client/mergeinfo.c libsvn_wc/node.c

Author: rhuijben
Date: Thu Apr 14 11:49:43 2011
New Revision: 1092145

URL: http://svn.apache.org/viewvc?rev=1092145&view=rev
Log:
Reduce the number of DB operations to retrieve a URL from libsvn_client,
by introducing a svn_wc__node_get_origin() function.

In several places we retrieved the url in more than one way to determine
which one to use, while generally wc_db can simply answer the question:
"Where did this node come from?"

* subversion/include/private/svn_wc_private.h
  (svn_wc__node_get_origin): New function.

* subversion/libsvn_client/commit_util.c
  (harvest_committables): Use svn_wc__node_get_origin() for simplification.

* subversion/libsvn_client/copy.c
  (calculate_target_mergeinfo): Use Use svn_wc__node_get_origin() for
    simplification.

* subversion/libsvn_client/merge.c
  (get_full_mergeinfo): Get the origin instead of relying on a specific error.

* subversion/libsvn_client/mergeinfo.c
  (svn_client__get_wc_or_repos_mergeinfo_catalog):
     Use svn_wc__node_get_origin() instead of 3 (or more) db calls.

* subversion/libsvn_client/url.c
  (svn_client__entry_location): Use svn_wc__node_get_origin() for all
    common cases.

* subversion/libsvn_wc/node.c
  (svn_wc__node_get_origin): New function.

Modified:
    subversion/trunk/subversion/include/private/svn_wc_private.h
    subversion/trunk/subversion/libsvn_client/commit_util.c
    subversion/trunk/subversion/libsvn_client/copy.c
    subversion/trunk/subversion/libsvn_client/merge.c
    subversion/trunk/subversion/libsvn_client/mergeinfo.c
    subversion/trunk/subversion/libsvn_wc/node.c

Modified: subversion/trunk/subversion/include/private/svn_wc_private.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_wc_private.h?rev=1092145&r1=1092144&r2=1092145&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_wc_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_wc_private.h Thu Apr 14 11:49:43 2011
@@ -321,6 +321,38 @@ svn_wc__node_get_url(const char **url,
                      apr_pool_t *scratch_pool);
 
 /**
+ * Retrieves the origin of the node as it is known in the repository. For
+ * added nodes this retrieves where the node is copied from, and the repository
+ * location for other nodes.
+ *
+ * All output arguments may be NULL.
+ *
+ * If @a is_copy is not NULL, sets @a *is_copy to TRUE if the origin is a copy
+ * of the original node.
+ *
+ * If not NULL, sets @a revision, @a repos_relpath, @a repos_root_url and
+ * @a repos_uuid to the original (if a copy) or their current values.
+ *
+ * If @a scan_deleted is TRUE, determine the origin of the deleted node. If
+ * @a scan_deleted is FALSE, return NULL, SVN_INVALID_REVNUM or FALSE for
+ * deleted nodes.
+ *
+ * Allocate the result in @a result_pool. Perform temporary allocations in
+ * @a scratch_pool */
+svn_error_t *
+svn_wc__node_get_origin(svn_boolean_t *is_copy,
+                        svn_revnum_t *revision,
+                        const char **repos_relpath,
+                        const char **repos_root_url,
+                        const char **repos_uuid,
+                        svn_wc_context_t *wc_ctx,
+                        const char *local_abspath,
+                        svn_boolean_t scan_deleted,
+                        apr_pool_t *result_pool,
+                        apr_pool_t *scratch_pool);
+
+
+/**
  * Set @a *repos_relpath to the corresponding repos_relpath for @a
  * local_abspath, using @a wc_ctx. If the node is added, return the
  * repos_relpath it will have in the repository.

Modified: subversion/trunk/subversion/libsvn_client/commit_util.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/commit_util.c?rev=1092145&r1=1092144&r2=1092145&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/commit_util.c (original)
+++ subversion/trunk/subversion/libsvn_client/commit_util.c Thu Apr 14 11:49:43 2011
@@ -504,26 +504,11 @@ harvest_committables(svn_wc_context_t *w
     }
 
   /* Further additions occur in copy mode. */
-  if (copy_mode && !(state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE))
+  if (copy_mode
+      && (!is_added || copy_mode_root)
+      && !(state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE))
     {
       svn_revnum_t dir_rev;
-      const char *node_copyfrom_relpath;
-      svn_revnum_t node_copyfrom_rev;
-
-      if (is_added)
-        {
-          SVN_ERR(svn_wc__node_get_copyfrom_info(NULL,
-                                                 &node_copyfrom_relpath,
-                                                 NULL, &node_copyfrom_rev,
-                                                 NULL,
-                                                 wc_ctx, local_abspath,
-                                                 scratch_pool, scratch_pool));
-        }
-       else
-        {
-          node_copyfrom_relpath = NULL;
-          node_copyfrom_rev = SVN_INVALID_REVNUM;
-        }
 
       if (!copy_mode_root)
         SVN_ERR(svn_wc__node_get_base_rev(&dir_rev, wc_ctx,
@@ -534,18 +519,15 @@ harvest_committables(svn_wc_context_t *w
       if (copy_mode_root || node_rev != dir_rev)
         {
           state_flags |= SVN_CLIENT_COMMIT_ITEM_ADD;
-          if (node_copyfrom_relpath)
-            {
-              state_flags |= SVN_CLIENT_COMMIT_ITEM_IS_COPY;
-              cf_relpath = node_copyfrom_relpath;
-              cf_rev = node_copyfrom_rev;
-            }
-          else if (node_rev != SVN_INVALID_REVNUM)
-            {
-              state_flags |= SVN_CLIENT_COMMIT_ITEM_IS_COPY;
-              cf_relpath = node_relpath;
-              cf_rev = node_rev;
-            }
+
+          SVN_ERR(svn_wc__node_get_origin(NULL, &cf_rev,
+                                      &cf_relpath, NULL,
+                                      NULL,
+                                      wc_ctx, local_abspath, FALSE,
+                                      scratch_pool, scratch_pool));
+
+          if (cf_relpath)
+            state_flags |= SVN_CLIENT_COMMIT_ITEM_IS_COPY;
         }
     }
 

Modified: subversion/trunk/subversion/libsvn_client/copy.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/copy.c?rev=1092145&r1=1092144&r2=1092145&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/copy.c (original)
+++ subversion/trunk/subversion/libsvn_client/copy.c Thu Apr 14 11:49:43 2011
@@ -91,29 +91,24 @@ calculate_target_mergeinfo(svn_ra_sessio
      bother checking. */
   if (local_abspath)
     {
-      svn_boolean_t is_added;
-      const char *is_copied;
+      const char *repos_root_url;
+      const char *repos_relpath;
 
       SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
-      SVN_ERR(svn_wc__node_is_added(&is_added, ctx->wc_ctx,
-                                    local_abspath, pool));
-      if (is_added)
-        SVN_ERR(svn_wc__node_get_copyfrom_info(&is_copied, NULL, NULL,
-                                               NULL, NULL, ctx->wc_ctx,
-                                               local_abspath, pool, pool));
+      SVN_ERR(svn_wc__node_get_origin(NULL, &src_revnum,
+                                      &repos_relpath, &repos_root_url,
+                                      NULL,
+                                      ctx->wc_ctx, local_abspath, FALSE,
+                                      pool, pool));
 
-      if (is_added && ! is_copied)
+      if (repos_relpath)
         {
-          locally_added = TRUE;
+          src_url = svn_path_url_add_component2(repos_root_url, repos_relpath,
+                                                pool);
         }
       else
-        {
-          SVN_ERR(svn_client__entry_location(&src_url, &src_revnum,
-                                             ctx->wc_ctx, local_abspath,
-                                             svn_opt_revision_working,
-                                             pool, pool));
-        }
+        locally_added = TRUE;
     }
 
   if (! locally_added)

Modified: subversion/trunk/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/merge.c?rev=1092145&r1=1092144&r2=1092145&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/merge.c (original)
+++ subversion/trunk/subversion/libsvn_client/merge.c Thu Apr 14 11:49:43 2011
@@ -3478,50 +3478,45 @@ get_full_mergeinfo(svn_mergeinfo_t *reco
 
   if (implicit_mergeinfo)
     {
-      const char *session_url = NULL, *url;
+      const char *repos_root;
+      const char *repos_relpath;
+      const char *session_url = NULL;
       svn_revnum_t target_rev;
-      svn_error_t *err;
 
       /* Assert that we have sane input. */
       SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(start)
                  && SVN_IS_VALID_REVNUM(end)
                  && (start > end));
 
-      *implicit_mergeinfo = NULL;
-
       /* Retrieve the origin (original_*) of the node, or just the
          url if the node was not copied. */
-      err = svn_client__entry_location(&url, &target_rev, 
-                                       ctx->wc_ctx, target_abspath,
-                                       svn_opt_revision_working,
-                                       scratch_pool, scratch_pool);
-      
-      if (err)
+      SVN_ERR(svn_wc__node_get_origin(FALSE, &target_rev, &repos_relpath,
+                                      &repos_root, NULL,
+                                      ctx->wc_ctx, target_abspath, FALSE,
+                                      scratch_pool, scratch_pool));
+
+      if (! repos_relpath)
         {
-            if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
-            {
-              /* We've been asked to operate on a target which has no location
-               * in the repository. Either it's unversioned (but attempts to
-               * merge into unversioned targets should not get as far as here),
-               * or it is locally added, in which case the target's implicit
-               * mergeinfo is empty. */
-              svn_error_clear(err);
-              *implicit_mergeinfo = apr_hash_make(result_pool);
-            }
-          else
-            return svn_error_return(err);
+          /* We've been asked to operate on a target which has no location
+           * in the repository. Either it's unversioned (but attempts to
+           * merge into unversioned targets should not get as far as here),
+           * or it is locally added, in which case the target's implicit
+           * mergeinfo is empty. */
+          *implicit_mergeinfo = apr_hash_make(result_pool);
         }
-
-      if (target_rev <= end)
+      else if (target_rev <= end)
         {
           /* We're asking about a range outside our natural history
              altogether.  That means our implicit mergeinfo is empty. */
           *implicit_mergeinfo = apr_hash_make(result_pool);
         }
-
-      if (*implicit_mergeinfo == NULL)
+      else
         {
           svn_opt_revision_t peg_revision;
+          const char *url;
+
+          url = svn_path_url_add_component2(repos_root, repos_relpath,
+                                            scratch_pool);
 
           /* Temporarily point our RA_SESSION at our target URL so we can
              fetch so-called "implicit mergeinfo" (that is, natural

Modified: subversion/trunk/subversion/libsvn_client/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/mergeinfo.c?rev=1092145&r1=1092144&r2=1092145&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/mergeinfo.c (original)
+++ subversion/trunk/subversion/libsvn_client/mergeinfo.c Thu Apr 14 11:49:43 2011
@@ -533,23 +533,24 @@ svn_client__get_wc_or_repos_mergeinfo_ca
   svn_revnum_t target_rev;
   const char *local_abspath;
   const char *repos_root;
-  svn_boolean_t is_added;
+  const char *repos_relpath;
 
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, target_wcpath,
                                   scratch_pool));
-  SVN_ERR(svn_wc__node_is_added(&is_added, ctx->wc_ctx, local_abspath,
-                                scratch_pool));
-  SVN_ERR(svn_wc__node_get_repos_info(&repos_root, NULL,
-                                      ctx->wc_ctx, local_abspath, FALSE, FALSE,
-                                      scratch_pool, scratch_pool));
 
   /* We may get an entry with abbreviated information from TARGET_WCPATH's
      parent if TARGET_WCPATH is missing.  These limited entries do not have
      a URL and without that we cannot get accurate mergeinfo for
      TARGET_WCPATH. */
-  SVN_ERR(svn_client__entry_location(&url, &target_rev, ctx->wc_ctx,
-                                     local_abspath, svn_opt_revision_working,
-                                     scratch_pool, scratch_pool));
+  SVN_ERR(svn_wc__node_get_origin(NULL, &target_rev, &repos_relpath,
+                                  &repos_root, NULL,
+                                  ctx->wc_ctx, local_abspath, FALSE,
+                                  scratch_pool, scratch_pool));
+
+  if (repos_relpath)
+    url = svn_path_url_add_component2(repos_root, repos_relpath, scratch_pool);
+  else
+    url = NULL;
 
   if (repos_only)
     *target_mergeinfo_catalog = NULL;
@@ -568,7 +569,7 @@ svn_client__get_wc_or_repos_mergeinfo_ca
   if (*target_mergeinfo_catalog == NULL)
     {
       /* No need to check the repos if this is a local addition. */
-      if (!is_added)
+      if (url != NULL)
         {
           apr_hash_t *original_props;
 

Modified: subversion/trunk/subversion/libsvn_wc/node.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/node.c?rev=1092145&r1=1092144&r2=1092145&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/node.c (original)
+++ subversion/trunk/subversion/libsvn_wc/node.c Thu Apr 14 11:49:43 2011
@@ -1535,6 +1535,114 @@ svn_wc__get_absent_subtrees(apr_hash_t *
 }
 
 svn_error_t *
+svn_wc__node_get_origin(svn_boolean_t *is_copy,
+                        svn_revnum_t *revision,
+                        const char **repos_relpath,
+                        const char **repos_root_url,
+                        const char **repos_uuid,
+                        svn_wc_context_t *wc_ctx,
+                        const char *local_abspath,
+                        svn_boolean_t scan_deleted,
+                        apr_pool_t *result_pool,
+                        apr_pool_t *scratch_pool)
+{
+  const char *original_repos_relpath;
+  const char *original_repos_root_url;
+  const char *original_repos_uuid;
+  svn_revnum_t original_revision;
+  svn_wc__db_status_t status;
+
+  const char *tmp_repos_relpath;
+
+  if (!repos_relpath)
+    repos_relpath = &tmp_repos_relpath;
+
+  SVN_ERR(svn_wc__db_read_info(&status, NULL, revision, repos_relpath,
+                               repos_root_url, repos_uuid, NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL, NULL,
+                               &original_repos_relpath,
+                               &original_repos_root_url,
+                               &original_repos_uuid, &original_revision,
+                               NULL, NULL, is_copy, NULL, NULL,
+                               wc_ctx->db, local_abspath,
+                               result_pool, scratch_pool));
+
+  if (*repos_relpath)
+    {
+      return SVN_NO_ERROR; /* Returned BASE information */
+    }
+
+  if (status == svn_wc__db_status_deleted && !scan_deleted)
+    {
+      if (is_copy)
+        *is_copy = FALSE; /* Deletes are stored in working; default to FALSE */
+
+      return SVN_NO_ERROR; /* No info */
+    }
+
+  if (original_repos_relpath)
+    {
+      *repos_relpath = original_repos_relpath;
+      if (revision)
+        *revision = original_revision;
+      if (repos_root_url)
+        *repos_root_url = original_repos_root_url;
+      if (repos_uuid)
+        *repos_uuid = original_repos_uuid;
+
+      return SVN_NO_ERROR;
+    }
+
+  {
+    svn_boolean_t scan_working = FALSE;
+
+    if (status == svn_wc__db_status_added)
+      scan_working = TRUE;
+    else if (status == svn_wc__db_status_deleted)
+      /* Is this a BASE or a WORKING delete? */
+      SVN_ERR(svn_wc__db_info_below_working(NULL, &scan_working, NULL,
+                                            wc_ctx->db, local_abspath,
+                                            scratch_pool));
+
+    if (scan_working)
+      {
+        const char *op_root_abspath;
+      
+        SVN_ERR(svn_wc__db_scan_addition(&status, &op_root_abspath, NULL,
+                                         NULL, NULL, &original_repos_relpath,
+                                         repos_root_url,
+                                         repos_uuid,
+                                         revision,
+                                         wc_ctx->db, local_abspath,
+                                         result_pool, scratch_pool));
+
+        if (status == svn_wc__db_status_added)
+          return SVN_NO_ERROR; /* Local addition */
+
+        *repos_relpath = svn_relpath_join(
+                                original_repos_relpath,
+                                svn_dirent_skip_ancestor(op_root_abspath,
+                                                         local_abspath),
+                                result_pool);
+      }
+    else /* Deleted, excluded, not-present, absent, ... */
+      {
+        if (is_copy)
+          *is_copy = FALSE;
+
+        SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, revision, repos_relpath,
+                                         repos_root_url, repos_uuid, NULL,
+                                         NULL, NULL, NULL, NULL, NULL, NULL,
+                                         NULL, NULL, NULL,
+                                         wc_ctx->db, local_abspath,
+                                         result_pool, scratch_pool));
+      }
+
+    return SVN_NO_ERROR;
+  }
+}
+
+svn_error_t *
 svn_wc__node_get_commit_status(svn_node_kind_t *kind,
                                svn_boolean_t *added,
                                svn_boolean_t *deleted,