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/05/29 16:32:09 UTC

svn commit: r1128881 - in /subversion/trunk/subversion: include/private/ libsvn_client/ libsvn_wc/

Author: rhuijben
Date: Sun May 29 14:32:09 2011
New Revision: 1128881

URL: http://svn.apache.org/viewvc?rev=1128881&view=rev
Log:
Add a new wc_db api which gathers all svn:externals properties and relevant
depths for an update/switch in a single transaction.

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

* subversion/libsvn_client/client.h
  (svn_client__crawl_for_externals): Remove function.
  (svn_client__gather_local_external_changes): Remove function.

* subversion/libsvn_client/externals.c
  (externals_crawl_proplist_receiver,
   svn_client__crawl_for_externals,
   svn_client__gather_local_external_changes): Remove functions.

* subversion/libsvn_client/relocate.c
  (includes): Add svn_wc_private.h
  (svn_client_relocate2): Update caller.

* subversion/libsvn_client/switch.c
  (switch_internal): Update caller.

* subversion/libsvn_client/update.c
  (update_internal): Update caller.

* subversion/libsvn_wc/externals.c
  (svn_wc__externals_gather_definitions): New function.

* subversion/libsvn_wc/wc-queries.sql
  (STMT_SELECT_EXTERNAL_PROPERTIES): New query.

* subversion/libsvn_wc/wc_db.c
  (svn_wc__db_externals_gather_definitions): New function.

* subversion/libsvn_wc/wc_db.h
  (svn_wc__db_externals_gather_definitions): New function.

Modified:
    subversion/trunk/subversion/include/private/svn_wc_private.h
    subversion/trunk/subversion/libsvn_client/client.h
    subversion/trunk/subversion/libsvn_client/externals.c
    subversion/trunk/subversion/libsvn_client/relocate.c
    subversion/trunk/subversion/libsvn_client/switch.c
    subversion/trunk/subversion/libsvn_client/update.c
    subversion/trunk/subversion/libsvn_wc/externals.c
    subversion/trunk/subversion/libsvn_wc/wc-queries.sql
    subversion/trunk/subversion/libsvn_wc/wc_db.c
    subversion/trunk/subversion/libsvn_wc/wc_db.h

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=1128881&r1=1128880&r2=1128881&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_wc_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_wc_private.h Sun May 29 14:32:09 2011
@@ -184,6 +184,27 @@ svn_wc__external_remove(svn_wc_context_t
                         void *cancel_baton,
                         apr_pool_t *scratch_pool);
 
+/* Gather all svn:externals property values from the actual properties on
+   directories below LOCAL_ABSPATH as a mapping of const char *local_abspath
+   to const char * values.
+
+   Use DEPTH as how it would be used to limit the externals property results
+   on update. (So any depth < infinity will only read svn:externals on
+   LOCAL_ABSPATH itself)
+
+   If DEPTHS is not NULL, set *depths to an apr_hash_t* mapping the same
+   local_abspaths to the const char * ambient depth of the node.
+
+   Allocate the result in RESULT_POOL and perform temporary allocations in
+   SCRATCH_POOL. */
+svn_error_t *
+svn_wc__externals_gather_definitions(apr_hash_t **externals,
+                                     apr_hash_t **ambient_depths,
+                                     svn_wc_context_t *wc_ctx,
+                                     const char *local_abspath,
+                                     svn_depth_t depth,
+                                     apr_pool_t *result_pool,
+                                     apr_pool_t *scratch_pool);
 
 /** Set @a *tree_conflict to a newly allocated @c
  * svn_wc_conflict_description_t structure describing the tree

Modified: subversion/trunk/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/client.h?rev=1128881&r1=1128880&r2=1128881&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/client.h (original)
+++ subversion/trunk/subversion/libsvn_client/client.h Sun May 29 14:32:09 2011
@@ -970,36 +970,6 @@ svn_client__do_external_status(svn_clien
                                void *status_baton,
                                apr_pool_t *pool);
 
-/* Set *EXTERNALS_P to a hash mapping const char * local absolute
-   paths to const svn_string_t * svn:externals property values, those
-   found by crawling LOCAL_ABSPATH to DEPTH. */
-svn_error_t *
-svn_client__crawl_for_externals(apr_hash_t **externals_p,
-                                const char *local_abspath,
-                                svn_depth_t depth,
-                                svn_client_ctx_t *ctx,
-                                apr_pool_t *result_pool,
-                                apr_pool_t *scratch_pool);
-
-/* Helper function to fix issue #2267,
- * "support svn:externals on locally added directories".
- *
- * Crawl all externals beneath ANCHOR_ABSPATH (this is cheap because we're
- * only crawling the WC DB itself). If there are externals within the
- * REQUESTED_DEPTH that weren't already picked up while we were crawling
- * the BASE tree, add them to the EXTERNALS_NEW hash with ambient depth
- * infinity. Facilitates populating externals in locally added directories.
- *
- * ### This is a bit of a hack. We should try to find a better solution
- * ### to this problem. */
-svn_error_t *
-svn_client__gather_local_external_changes(apr_hash_t *externals_new,
-                                          apr_hash_t *ambient_depths,
-                                          const char *anchor_abspath,
-                                          svn_depth_t requested_depth,
-                                          svn_client_ctx_t *ctx,
-                                          apr_pool_t *scratch_pool);
-
 /* Baton type for svn_wc__external_info_gatherer(). */
 typedef struct svn_client__external_func_baton_t
 {

Modified: subversion/trunk/subversion/libsvn_client/externals.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/externals.c?rev=1128881&r1=1128880&r2=1128881&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/externals.c (original)
+++ subversion/trunk/subversion/libsvn_client/externals.c Sun May 29 14:32:09 2011
@@ -1517,100 +1517,3 @@ svn_client__external_info_gatherer(void 
 }
 
 
-/* An implementation of svn_wc__proplist_receiver_t. Just squirrels away an
-   svn:externals property value into BATON (which is an apr_hash_t *
-   keyed on local absolute path).  */
-static svn_error_t *
-externals_crawl_proplist_receiver(void *baton,
-                                  const char *local_abspath,
-                                  apr_hash_t *props,
-                                  apr_pool_t *scratch_pool)
-{
-  apr_hash_t *externals_hash = baton;
-  const svn_string_t *propval;
-
-  propval = apr_hash_get(props, SVN_PROP_EXTERNALS, APR_HASH_KEY_STRING);
-
-  if (propval)
-    {
-      apr_pool_t *hash_pool = apr_hash_pool_get(externals_hash);
-
-      apr_hash_set(externals_hash, apr_pstrdup(hash_pool, local_abspath),
-                   APR_HASH_KEY_STRING, svn_string_dup(propval, hash_pool));
-    }
-
-  return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
-svn_client__crawl_for_externals(apr_hash_t **externals_p,
-                                const char *local_abspath,
-                                svn_depth_t depth,
-                                svn_client_ctx_t *ctx,
-                                apr_pool_t *result_pool,
-                                apr_pool_t *scratch_pool)
-{
-  apr_hash_t *externals_hash = apr_hash_make(result_pool);
-
-  SVN_ERR(svn_wc__prop_list_recursive(ctx->wc_ctx, local_abspath, NULL, depth,
-                                      FALSE /* base_props */,
-                                      FALSE /* pristine */,
-                                      externals_crawl_proplist_receiver,
-                                      externals_hash,
-                                      ctx->cancel_func,
-                                      ctx->cancel_baton,
-                                      scratch_pool));
-
-  *externals_p = externals_hash;
-  return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_client__gather_local_external_changes(apr_hash_t *externals_new,
-                                          apr_hash_t *ambient_depths,
-                                          const char *anchor_abspath,
-                                          svn_depth_t requested_depth,
-                                          svn_client_ctx_t *ctx,
-                                          apr_pool_t *scratch_pool)
-{
-  apr_hash_t *all_externals;
-  apr_hash_index_t *hi;
-
-  /* If there was no requested depth for this operation, use infinity.
-   * svn_client__crawl_for_externals() doesn't like depth 'unknown'. */
-  if (requested_depth == svn_depth_unknown)
-    requested_depth = svn_depth_infinity;
-
-  SVN_ERR(svn_client__crawl_for_externals(&all_externals, anchor_abspath,
-                                          requested_depth, ctx, scratch_pool,
-                                          scratch_pool));
-
-  for (hi = apr_hash_first(scratch_pool, all_externals);
-       hi;
-       hi = apr_hash_next(hi))
-    {
-      const char *local_abspath = svn__apr_hash_index_key(hi);
-      svn_string_t *propval = svn__apr_hash_index_val(hi);
-      apr_pool_t *hash_pool = apr_hash_pool_get(externals_new);
-
-      local_abspath = apr_pstrdup(hash_pool, local_abspath);
-
-      /* Override existing pristine definitions */
-      apr_hash_set(externals_new, local_abspath, APR_HASH_KEY_STRING,
-                   apr_pstrdup(hash_pool, propval->data));
-
-      /* Make sure that when using ambient depths, there is a depth for
-         every path */
-      if (ambient_depths
-          && !apr_hash_get(ambient_depths, local_abspath, APR_HASH_KEY_STRING))
-        {
-          apr_hash_set(ambient_depths, local_abspath, APR_HASH_KEY_STRING,
-                       svn_depth_to_word(svn_depth_infinity));
-        }
-    }
-
-  return SVN_NO_ERROR;
-}
-
-

Modified: subversion/trunk/subversion/libsvn_client/relocate.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/relocate.c?rev=1128881&r1=1128880&r2=1128881&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/relocate.c (original)
+++ subversion/trunk/subversion/libsvn_client/relocate.c Sun May 29 14:32:09 2011
@@ -35,6 +35,8 @@
 #include "svn_path.h"
 #include "client.h"
 
+#include "private/svn_wc_private.h"
+
 #include "svn_private_config.h"
 
 
@@ -258,8 +260,10 @@ svn_client_relocate2(const char *wcroot_
 
 
   /* Relocate externals, too (if any). */
-  SVN_ERR(svn_client__crawl_for_externals(&externals_hash, local_abspath,
-                                          svn_depth_infinity, ctx, pool, pool));
+  SVN_ERR(svn_wc__externals_gather_definitions(&externals_hash, NULL,
+                                               ctx->wc_ctx, local_abspath,
+                                               svn_depth_infinity,
+                                               pool, pool));
   if (! apr_hash_count(externals_hash))
     return SVN_NO_ERROR;
 

Modified: subversion/trunk/subversion/libsvn_client/switch.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/switch.c?rev=1128881&r1=1128880&r2=1128881&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/switch.c (original)
+++ subversion/trunk/subversion/libsvn_client/switch.c Sun May 29 14:32:09 2011
@@ -287,14 +287,20 @@ switch_internal(svn_revnum_t *result_rev
      the primary operation. */
   if (SVN_DEPTH_IS_RECURSIVE(depth) && (! ignore_externals))
     {
-      SVN_ERR(svn_client__gather_local_external_changes(
-                efb.externals_new, efb.ambient_depths, local_abspath,
-                depth, ctx, pool));
-
-      err = svn_client__handle_externals(efb.externals_old,
-                                         efb.externals_new, efb.ambient_depths,
-                                         source_root, local_abspath,
-                                         depth, use_sleep, ctx, pool);
+      apr_hash_t *new_externals;
+      apr_hash_t *new_depths;
+      SVN_ERR(svn_wc__externals_gather_definitions(&new_externals,
+                                                   &new_depths,
+                                                   ctx->wc_ctx, local_abspath,
+                                                   depth, pool, pool));
+
+      new_depths = apr_hash_overlay(pool, new_depths, efb.ambient_depths);
+      SVN_ERR(svn_client__handle_externals(efb.externals_old,
+                                           new_externals,
+                                           new_depths,
+                                           source_root, local_abspath,
+                                           depth, use_sleep,
+                                           ctx, pool));
     }
 
   /* Sleep to ensure timestamp integrity (we do this regardless of

Modified: subversion/trunk/subversion/libsvn_client/update.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/update.c?rev=1128881&r1=1128880&r2=1128881&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/update.c (original)
+++ subversion/trunk/subversion/libsvn_client/update.c Sun May 29 14:32:09 2011
@@ -432,12 +432,17 @@ update_internal(svn_revnum_t *result_rev
      the primary operation.  */
   if (SVN_DEPTH_IS_RECURSIVE(depth) && (! ignore_externals))
     {
-      SVN_ERR(svn_client__gather_local_external_changes(
-                  efb.externals_new, efb.ambient_depths, local_abspath,
-                  depth, ctx, pool));
+      apr_hash_t *new_externals;
+      apr_hash_t *new_depths;
+      SVN_ERR(svn_wc__externals_gather_definitions(&new_externals,
+                                                   &new_depths,
+                                                   ctx->wc_ctx, local_abspath,
+                                                   depth, pool, pool));
+
+      new_depths = apr_hash_overlay(pool, new_depths, efb.ambient_depths);
       SVN_ERR(svn_client__handle_externals(efb.externals_old,
-                                           efb.externals_new,
-                                           efb.ambient_depths,
+                                           new_externals,
+                                           new_depths,
                                            repos_root, local_abspath,
                                            depth, use_sleep,
                                            ctx, pool));

Modified: subversion/trunk/subversion/libsvn_wc/externals.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/externals.c?rev=1128881&r1=1128880&r2=1128881&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/externals.c (original)
+++ subversion/trunk/subversion/libsvn_wc/externals.c Sun May 29 14:32:09 2011
@@ -1225,3 +1225,54 @@ svn_wc__external_remove(svn_wc_context_t
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_wc__externals_gather_definitions(apr_hash_t **externals,
+                                     apr_hash_t **depths,
+                                     svn_wc_context_t *wc_ctx,
+                                     const char *local_abspath,
+                                     svn_depth_t depth,
+                                     apr_pool_t *result_pool,
+                                     apr_pool_t *scratch_pool)
+{
+  if (depth == svn_depth_infinity
+      || depth == svn_depth_unknown)
+    {
+      return svn_error_return(
+        svn_wc__db_externals_gather_definitions(externals, depths,
+                                                wc_ctx->db, local_abspath,
+                                                result_pool, scratch_pool));
+    }
+  else
+    {
+      const svn_string_t *value;
+      *externals = apr_hash_make(result_pool);
+
+      local_abspath = apr_pstrdup(result_pool, local_abspath);
+
+      SVN_ERR(svn_wc_prop_get2(&value, wc_ctx, local_abspath,
+                               SVN_PROP_EXTERNALS, result_pool, scratch_pool));
+
+      if (value)
+        apr_hash_set(*externals, local_abspath, APR_HASH_KEY_STRING,
+                     value->data);
+
+      if (depths)
+        {
+          svn_depth_t node_depth;
+          *depths = apr_hash_make(result_pool);
+
+          SVN_ERR(svn_wc__db_read_info(NULL, NULL, NULL, NULL, NULL, NULL,
+                                       NULL, NULL, NULL, &node_depth, NULL,
+                                       NULL, NULL, NULL, NULL, NULL, NULL,
+                                       NULL, NULL, NULL, NULL, NULL, NULL,
+                                       NULL, NULL, NULL, NULL,
+                                       wc_ctx->db, local_abspath,
+                                       scratch_pool, scratch_pool));
+
+          apr_hash_set(*depths, local_abspath, APR_HASH_KEY_STRING,
+                       svn_depth_to_word(node_depth));
+        }
+
+      return SVN_NO_ERROR;
+    }
+}

Modified: subversion/trunk/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc-queries.sql?rev=1128881&r1=1128880&r2=1128881&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-queries.sql Sun May 29 14:32:09 2011
@@ -919,6 +919,20 @@ WHERE wc_id = ?1 AND local_relpath = ?2
 DELETE FROM externals
 WHERE wc_id = ?1 AND local_relpath = ?2
 
+-- STMT_SELECT_EXTERNAL_PROPERTIES
+SELECT IFNULL((SELECT properties FROM actual_node a
+               WHERE a.wc_id = ?1 AND A.local_relpath = n.local_relpath),
+              properties),
+       local_relpath, depth
+FROM nodes n
+WHERE wc_id = ?1
+  AND (?2 = ''
+       OR local_relpath = ?2
+       OR (local_relpath > ?2 || '/' AND local_relpath < ?2 || '0'))
+  AND kind = 'dir' AND presence='normal'
+  AND op_depth=(SELECT MAX(op_depth) FROM nodes o
+                WHERE o.wc_id = ?1 AND o.local_relpath = n.local_relpath)
+
 /* ------------------------------------------------------------------------- */
 
 /* these are used in entries.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=1128881&r1=1128880&r2=1128881&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Sun May 29 14:32:09 2011
@@ -3220,6 +3220,90 @@ svn_wc__db_externals_defined_below(apr_h
   return svn_error_return(svn_sqlite__reset(stmt));
 }
 
+svn_error_t *
+svn_wc__db_externals_gather_definitions(apr_hash_t **externals,
+                                        apr_hash_t **depths,
+                                        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;
+  svn_sqlite__stmt_t *stmt;
+  const char *local_relpath;
+  svn_boolean_t have_row;
+  svn_error_t *err = NULL;
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+
+  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, iterpool));
+  VERIFY_USABLE_WCROOT(wcroot);
+
+  *externals = apr_hash_make(result_pool);
+  if (depths != NULL)
+    *depths = apr_hash_make(result_pool);
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_SELECT_EXTERNAL_PROPERTIES));
+
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+  while (have_row)
+    {
+      apr_hash_t *node_props;
+      const svn_string_t *external_value;
+
+      svn_pool_clear(iterpool);
+      err = svn_sqlite__column_properties(&node_props, stmt, 0, iterpool,
+                                          iterpool);
+
+      if (err)
+        break;
+
+      external_value = node_props
+                            ? apr_hash_get(node_props, SVN_PROP_EXTERNALS,
+                                           APR_HASH_KEY_STRING)
+                            : NULL;
+
+      if (external_value)
+        {
+          const char *node_abspath;
+          const char *node_relpath = svn_sqlite__column_text(stmt, 1, NULL);
+
+          node_abspath = svn_dirent_join(wcroot->abspath, node_relpath,
+                                         result_pool);
+
+          apr_hash_set(*externals, node_abspath,
+                       APR_HASH_KEY_STRING,
+                       apr_pstrdup(result_pool, external_value->data));
+
+          if (depths)
+            {
+              const char *depth_word = svn_sqlite__column_text(stmt, 2, NULL);
+              svn_depth_t depth = svn_depth_unknown;
+
+              if (depth_word)
+                depth = svn_depth_from_word(depth_word);
+
+              apr_hash_set(*depths, node_abspath,
+                           APR_HASH_KEY_STRING,
+                           svn_depth_to_word(depth)); /* Use static string */
+            }
+        }
+
+      SVN_ERR(svn_sqlite__step(&have_row, stmt));
+    }
+
+  svn_pool_destroy(iterpool);
+
+  return svn_error_return(svn_error_compose_create(err,
+                                                   svn_sqlite__reset(stmt)));
+}
+
 /* Helper for svn_wc__db_op_copy to handle copying from one db to
    another */
 static svn_error_t *

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.h?rev=1128881&r1=1128880&r2=1128881&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.h Sun May 29 14:32:09 2011
@@ -1185,6 +1185,23 @@ svn_wc__db_externals_defined_below(apr_h
                                    apr_pool_t *result_pool,
                                    apr_pool_t *scratch_pool);
 
+/* Gather all svn:externals property values from the actual properties on
+   directories below LOCAL_ABSPATH as a mapping of const char *local_abspath
+   to const char * property values.
+
+   If DEPTHS is not NULL, set *depths to an apr_hash_t* mapping the same
+   local_abspaths to the const char * ambient depth of the node.
+
+   Allocate the result in RESULT_POOL and perform temporary allocations in
+   SCRATCH_POOL. */
+svn_error_t *
+svn_wc__db_externals_gather_definitions(apr_hash_t **externals,
+                                        apr_hash_t **depths,
+                                        svn_wc__db_t *db,
+                                        const char *local_abspath,
+                                        apr_pool_t *result_pool,
+                                        apr_pool_t *scratch_pool);
+
 /* @} */
 
 /* @defgroup svn_wc__db_op  Operations on WORKING tree