subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From stef...@apache.org
Subject svn commit: r1066452 [3/11] - in /subversion/branches/performance: ./ build/ build/ac-macros/ build/generator/ contrib/hook-scripts/ notes/ notes/api-errata/1.7/ subversion/bindings/javahl/tests/org/apache/subversion/javahl/ subversion/include/ subvers...
Date Wed, 02 Feb 2011 13:04:59 GMT
Modified: subversion/branches/performance/subversion/libsvn_client/export.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_client/export.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_client/export.c (original)
+++ subversion/branches/performance/subversion/libsvn_client/export.c Wed Feb  2 13:04:51 2011
@@ -110,16 +110,15 @@ append_basename_if_dir(const char **appe
   SVN_ERR(svn_io_check_resolved_path(*appendable_dirent_p, &local_kind, pool));
   if (local_kind == svn_node_dir)
     {
-      const char *basename2; /* _2 because it shadows basename() */
+      const char *base_name;
 
       if (is_uri)
-        basename2 = svn_path_uri_decode(svn_uri_basename(basename_of, NULL), pool);
+        base_name = svn_uri_basename(basename_of, pool);
       else
-        basename2 = svn_dirent_basename(basename_of, NULL);
+        base_name = svn_dirent_basename(basename_of, NULL);
 
       *appendable_dirent_p = svn_dirent_join(*appendable_dirent_p,
-                                             basename2,
-                                             pool);
+                                             base_name, pool);
     }
 
   return SVN_NO_ERROR;
@@ -882,11 +881,13 @@ change_dir_prop(void *dir_baton,
 /* Move the tmpfile to file, and send feedback. */
 static svn_error_t *
 close_file(void *file_baton,
-           const char *text_checksum,
+           const char *text_digest,
            apr_pool_t *pool)
 {
   struct file_baton *fb = file_baton;
   struct edit_baton *eb = fb->edit_baton;
+  svn_checksum_t *text_checksum;
+  svn_checksum_t *actual_checksum;
 
   /* Was a txdelta even sent? */
   if (! fb->tmppath)
@@ -894,22 +895,21 @@ close_file(void *file_baton,
 
   SVN_ERR(svn_stream_close(fb->tmp_stream));
 
-  if (text_checksum)
-    {
-      const char *actual_checksum =
-        svn_checksum_to_cstring(svn_checksum__from_digest(fb->text_digest,
-                                                          svn_checksum_md5,
-                                                          pool), pool);
+  SVN_ERR(svn_checksum_parse_hex(&text_checksum, svn_checksum_md5, text_digest,
+                                 pool));
+  actual_checksum = svn_checksum__from_digest(fb->text_digest,
+                                              svn_checksum_md5, pool);
 
-      if (actual_checksum && (strcmp(text_checksum, actual_checksum) != 0))
-        {
-          return svn_error_createf(SVN_ERR_CHECKSUM_MISMATCH, NULL,
+  if (!svn_checksum_match(text_checksum, actual_checksum))
+    {
+      return svn_error_createf(SVN_ERR_CHECKSUM_MISMATCH, NULL,
                           _("Checksum mismatch for '%s':\n"
                             "   expected:  %s\n"
                             "     actual:  %s\n"),
                           svn_dirent_local_style(fb->path, pool),
-                          text_checksum, actual_checksum);
-        }
+                          svn_checksum_to_cstring_display(text_checksum, pool),
+                          svn_checksum_to_cstring_display(actual_checksum,
+                                                          pool));
     }
 
   if ((! fb->eol_style_val) && (! fb->keywords_val) && (! fb->special))
@@ -984,6 +984,7 @@ svn_client_export5(svn_revnum_t *result_
 {
   svn_revnum_t edit_revision = SVN_INVALID_REVNUM;
   const char *url;
+  svn_boolean_t from_is_url = svn_path_is_url(from_path_or_url);
 
   SVN_ERR_ASSERT(peg_revision != NULL);
   SVN_ERR_ASSERT(revision != NULL);
@@ -996,8 +997,7 @@ svn_client_export5(svn_revnum_t *result_
                                                         from_path_or_url);
   revision = svn_cl__rev_default_to_peg(revision, peg_revision);
 
-  if (svn_path_is_url(from_path_or_url) ||
-      ! SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(revision->kind))
+  if (from_is_url || ! SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(revision->kind))
     {
       svn_revnum_t revnum;
       svn_ra_session_t *ra_session;
@@ -1036,14 +1036,16 @@ svn_client_export5(svn_revnum_t *result_
 
           if (svn_path_is_empty(to_path))
             {
-              to_path = svn_path_uri_decode(svn_uri_basename(from_path_or_url,
-                                                             NULL), pool);
+              if (from_is_url)
+                to_path = svn_uri_basename(from_path_or_url, pool);
+              else
+                to_path = svn_dirent_basename(from_path_or_url, NULL);
               eb->root_path = to_path;
             }
           else
             {
               SVN_ERR(append_basename_if_dir(&to_path, from_path_or_url,
-                                             TRUE, pool));
+                                             from_is_url, pool));
               eb->root_path = to_path;
             }
 

Modified: subversion/branches/performance/subversion/libsvn_client/externals.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_client/externals.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_client/externals.c (original)
+++ subversion/branches/performance/subversion/libsvn_client/externals.c Wed Feb  2 13:04:51 2011
@@ -565,23 +565,35 @@ resolve_relative_external_url(svn_wc_ext
                               apr_pool_t *pool)
 {
   const char *url = item->url;
-  apr_uri_t parent_dir_parsed_uri;
+  apr_uri_t parent_dir_uri;
   apr_status_t status;
 
-  if ((url[0] == '/') && (url[1] == '/'))
+  /* If the URL is already absolute, there is nothing to do. */
+  if (svn_path_is_url(url))
     {
-      /* "//schema-relative" and in some cases "///schema-relative".
-         This last format is supported on file:// schema relative. */
-      url = apr_pstrcat(
-                        pool,
-                        url[2] == '/' ? "///" : "//",
-                        svn_relpath_canonicalize(url+2, pool),
-                        (char *)NULL);
+      /* "http://server/path" */
+      item->url = svn_uri_canonicalize(url, pool);
+      return SVN_NO_ERROR;
     }
-  else if (svn_path_is_url(url) || *url == '/')
+
+  if (url[0] == '/')
     {
-      /* "http://server/path" and "/path" */
-      url = svn_uri_canonicalize(url, pool);
+      /* "/path", "//path", and "///path" */
+      int num_leading_slashes = 1;
+      if (url[1] == '/')
+        {
+          num_leading_slashes++;
+          if (url[2] == '/')
+            num_leading_slashes++;
+        }
+
+      /* "//schema-relative" and in some cases "///schema-relative".
+         This last format is supported on file:// schema relative. */
+      url = apr_pstrcat(pool,
+                        apr_pstrndup(pool, url, num_leading_slashes),
+                        svn_relpath_canonicalize(url + num_leading_slashes,
+                                                 pool),
+                        NULL);
     }
   else
     {
@@ -589,15 +601,8 @@ resolve_relative_external_url(svn_wc_ext
       url = svn_relpath_canonicalize(url, pool);
     }
 
-  /* If the URL is already absolute, there is nothing to do. */
-  if (svn_path_is_url(url))
-    {
-      item->url = url;
-      return SVN_NO_ERROR;
-    }
-
   /* Parse the parent directory URL into its parts. */
-  status = apr_uri_parse(pool, parent_dir_url, &parent_dir_parsed_uri);
+  status = apr_uri_parse(pool, parent_dir_url, &parent_dir_uri);
   if (status)
     return svn_error_createf(SVN_ERR_BAD_URL, 0,
                              _("Illegal parent directory URL '%s'"),
@@ -606,8 +611,10 @@ resolve_relative_external_url(svn_wc_ext
   /* If the parent directory URL is at the server root, then the URL
      may have no / after the hostname so apr_uri_parse() will leave
      the URL's path as NULL. */
-  if (! parent_dir_parsed_uri.path)
-    parent_dir_parsed_uri.path = apr_pstrmemdup(pool, "/", 1);
+  if (! parent_dir_uri.path)
+    parent_dir_uri.path = apr_pstrmemdup(pool, "/", 1);
+  parent_dir_uri.query = NULL;
+  parent_dir_uri.fragment = NULL;
 
   /* Handle URLs relative to the current directory or to the
      repository root.  The backpaths may only remove path elements,
@@ -625,15 +632,14 @@ resolve_relative_external_url(svn_wc_ext
          repository root's URL path into components.  */
       if (0 == strncmp("../", url, 3))
         {
-          base_components = svn_path_decompose(parent_dir_parsed_uri.path,
-                                               pool);
+          base_components = svn_path_decompose(parent_dir_uri.path, pool);
           relative_components = svn_path_decompose(url, pool);
         }
       else
         {
-          apr_uri_t repos_root_parsed_uri;
+          apr_uri_t repos_root_uri;
 
-          status = apr_uri_parse(pool, repos_root_url, &repos_root_parsed_uri);
+          status = apr_uri_parse(pool, repos_root_url, &repos_root_uri);
           if (status)
             return svn_error_createf(SVN_ERR_BAD_URL, 0,
                                      _("Illegal repository root URL '%s'"),
@@ -642,10 +648,10 @@ resolve_relative_external_url(svn_wc_ext
           /* If the repository root URL is at the server root, then
              the URL may have no / after the hostname so
              apr_uri_parse() will leave the URL's path as NULL. */
-          if (! repos_root_parsed_uri.path)
-            repos_root_parsed_uri.path = apr_pstrmemdup(pool, "/", 1);
+          if (! repos_root_uri.path)
+            repos_root_uri.path = apr_pstrmemdup(pool, "/", 1);
 
-          base_components = svn_path_decompose(repos_root_parsed_uri.path,
+          base_components = svn_path_decompose(repos_root_uri.path,
                                                pool);
           relative_components = svn_path_decompose(url + 2, pool);
         }
@@ -668,13 +674,9 @@ resolve_relative_external_url(svn_wc_ext
             APR_ARRAY_PUSH(base_components, const char *) = component;
         }
 
-      parent_dir_parsed_uri.path = (char *)svn_path_compose(base_components,
-                                                            pool);
-      parent_dir_parsed_uri.query = NULL;
-      parent_dir_parsed_uri.fragment = NULL;
-
-      item->url = apr_uri_unparse(pool, &parent_dir_parsed_uri, 0);
-
+      parent_dir_uri.path = (char *)svn_path_compose(base_components, pool);
+      item->url = svn_uri_canonicalize(apr_uri_unparse(pool, &parent_dir_uri,
+                                                       0), pool);
       return SVN_NO_ERROR;
     }
 
@@ -687,26 +689,24 @@ resolve_relative_external_url(svn_wc_ext
                                "backpaths, i.e. '..'"),
                              item->url);
 
-  /* Relative to the scheme. */
+  /* Relative to the scheme: Build a new URL from the parts we know.  */
   if (0 == strncmp("//", url, 2))
     {
       const char *scheme;
 
       SVN_ERR(uri_scheme(&scheme, repos_root_url, pool));
-      item->url = svn_uri_canonicalize(apr_pstrcat(pool,
-                                                   scheme,
-                                                   ":",
-                                                   url,
-                                                   (char *)NULL),
-                                       pool);
+      item->url = svn_uri_canonicalize(apr_pstrcat(pool, scheme, ":",
+                                                   url, NULL), pool);
       return SVN_NO_ERROR;
     }
 
-  /* Relative to the server root. */
+  /* Relative to the server root: Just replace the path portion of the
+     parent's URL.  */
   if (url[0] == '/')
     {
-      item->url = svn_uri_join(parent_dir_url, url, pool);
-
+      parent_dir_uri.path = (char *)url;
+      item->url = svn_uri_canonicalize(apr_uri_unparse(pool, &parent_dir_uri,
+                                                       0), pool);
       return SVN_NO_ERROR;
     }
 

Modified: subversion/branches/performance/subversion/libsvn_client/info.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_client/info.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_client/info.c (original)
+++ subversion/branches/performance/subversion/libsvn_client/info.c Wed Feb  2 13:04:51 2011
@@ -34,6 +34,7 @@
 #include "svn_wc.h"
 
 #include "svn_private_config.h"
+#include "private/svn_fspath.h"
 #include "private/svn_wc_private.h"
 
 
@@ -289,11 +290,9 @@ push_dir_info(svn_ra_session_t *ra_sessi
         SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
 
       path = svn_relpath_join(dir, name, subpool);
-      URL  = svn_path_url_add_component2(session_URL, name, subpool);
-
-      fs_path = svn_uri_is_child(repos_root, URL, subpool);
-      fs_path = apr_pstrcat(subpool, "/", fs_path, (char *)NULL);
-      fs_path = svn_path_uri_decode(fs_path, subpool);
+      URL = svn_path_url_add_component2(session_URL, name, subpool);
+      fs_path = svn_fspath__canonicalize(svn_uri_is_child(repos_root, URL,
+                                                          subpool), subpool);
 
       lock = apr_hash_get(locks, fs_path, APR_HASH_KEY_STRING);
 
@@ -537,7 +536,6 @@ svn_client_info3(const char *abspath_or_
   SVN_ERR(svn_ra_get_uuid2(ra_session, &repos_UUID, pool));
 
   svn_uri_split(&parent_url, &base_name, url, pool);
-  base_name = svn_path_uri_decode(base_name, pool);
 
   /* Get the dirent for the URL itself. */
   err = svn_ra_stat(ra_session, "", rev, &the_ent, pool);

Modified: subversion/branches/performance/subversion/libsvn_client/list.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_client/list.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_client/list.c (original)
+++ subversion/branches/performance/subversion/libsvn_client/list.c Wed Feb  2 13:04:51 2011
@@ -31,6 +31,7 @@
 
 #include "client.h"
 
+#include "private/svn_fspath.h"
 #include "svn_private_config.h"
 
 /* Get the directory entries of DIR at REV (relative to the root of
@@ -181,11 +182,6 @@ svn_client_list2(const char *path_or_url
                  doesn't support svn_ra_reparent anyway, so don't try it. */
               svn_uri_split(&parent_url, &base_name, url, pool);
 
-              /* 'base_name' is now the last component of an URL, but we want
-                 to use it as a plain file name. Therefore, we must URI-decode
-                 it. */
-              base_name = svn_path_uri_decode(base_name, pool);
-
               SVN_ERR(svn_client__open_ra_session_internal(&parent_session,
                                                            NULL, parent_url,
                                                            NULL, NULL, FALSE,

Modified: subversion/branches/performance/subversion/libsvn_client/locking_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_client/locking_commands.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_client/locking_commands.c (original)
+++ subversion/branches/performance/subversion/libsvn_client/locking_commands.c Wed Feb  2 13:04:51 2011
@@ -138,6 +138,58 @@ store_locks_callback(void *baton,
 }
 
 
+/* This is a wrapper around svn_uri_condense_targets() and
+ * svn_dirent_condense_targets() (the choice of which is made based on
+ * the value of TARGETS_ARE_URIS) which takes care of the
+ * single-target special case.
+ *
+ * Callers are expected to check for an empty *COMMON_PARENT (which
+ * means, "there was nothing common") for themselves.
+ */
+static svn_error_t *
+condense_targets(const char **common_parent,
+                 apr_array_header_t **target_relpaths,
+                 const apr_array_header_t *targets,
+                 svn_boolean_t targets_are_uris,
+                 svn_boolean_t remove_redundancies,
+                 apr_pool_t *scratch_pool,
+                 apr_pool_t *result_pool)
+{
+  if (targets_are_uris)
+    {
+      SVN_ERR(svn_uri_condense_targets(common_parent, target_relpaths,
+                                       targets, remove_redundancies,
+                                       result_pool, scratch_pool));
+    }
+  else
+    {
+      SVN_ERR(svn_dirent_condense_targets(common_parent, target_relpaths,
+                                          targets, remove_redundancies,
+                                          result_pool, scratch_pool));
+    }
+
+  /* svn_*_condense_targets leaves *TARGET_RELPATHS empty if TARGETS only
+     had 1 member, so we special case that. */
+  if (apr_is_empty_array(*target_relpaths))
+    {
+      const char *base_name;
+
+      if (targets_are_uris)
+        {
+          svn_uri_split(common_parent, &base_name,
+                        *common_parent, result_pool);
+        }
+      else
+        {
+          svn_dirent_split(common_parent, &base_name,
+                           *common_parent, result_pool);
+        }
+      APR_ARRAY_PUSH(*target_relpaths, const char *) = base_name;
+    }
+  
+  return SVN_NO_ERROR;
+}
+
 /* Set *COMMON_PARENT_URL to the nearest common parent URL of all TARGETS.
  * If TARGETS are local paths, then the entry for each path is examined
  * and *COMMON_PARENT is set to the common parent URL for all the
@@ -175,176 +227,160 @@ organize_lock_targets(const char **commo
                       svn_boolean_t do_lock,
                       svn_boolean_t force,
                       svn_client_ctx_t *ctx,
-                      apr_pool_t *pool)
+                      apr_pool_t *result_pool,
+                      apr_pool_t *scratch_pool)
 {
-  int i;
-  apr_array_header_t *rel_targets = apr_array_make(pool, 1,
-                                                   sizeof(const char *));
-  apr_hash_t *rel_targets_ret = apr_hash_make(pool);
-  apr_pool_t *subpool = svn_pool_create(pool);
+  const char *common_url = NULL;
+  const char *common_dirent = NULL;
+  apr_hash_t *rel_targets_ret = apr_hash_make(result_pool);
+  apr_hash_t *rel_fs_paths = NULL;
+  apr_array_header_t *rel_targets;
   svn_boolean_t url_mode;
+  int i;
 
+  SVN_ERR_ASSERT(targets->nelts);
   SVN_ERR(svn_client__assert_homogeneous_target_type(targets));
 
-  url_mode = ((targets->nelts >= 1) &&
-              svn_path_is_url(APR_ARRAY_IDX(targets, 0, const char *)));
+  url_mode = svn_path_is_url(APR_ARRAY_IDX(targets, 0, const char *));
 
-  /* Get the common parent and all paths */
   if (url_mode)
-    SVN_ERR(svn_uri_condense_targets(common_parent_url, &rel_targets,
-                                     targets, TRUE, pool, pool));
-  else
-    SVN_ERR(svn_dirent_condense_targets(common_parent_url, &rel_targets,
-                                        targets, TRUE, pool, pool));
-
-  /* svn_uri_condense_targets and svn_dirent_condense_targets leaves
-     URLs/paths empty if TARGETS only had 1 member, so we special case
-     that. */
-  if (apr_is_empty_array(rel_targets))
     {
-      const char *parent, *base;
-      if (url_mode)
-        svn_uri_split(&parent, &base, *common_parent_url, pool);
-      else
-        svn_dirent_split(&parent, &base, *common_parent_url, pool);
-
-      *common_parent_url = parent;
-      APR_ARRAY_PUSH(rel_targets, const char *) = base;
-    }
-
-  if (*common_parent_url == NULL || (*common_parent_url)[0] == '\0')
-    return svn_error_create
-      (SVN_ERR_UNSUPPORTED_FEATURE, NULL,
-       _("No common parent found, unable to operate on disjoint arguments"));
+      svn_revnum_t *invalid_revnum =
+        apr_palloc(result_pool, sizeof(*invalid_revnum));
 
-  if (url_mode)
-    {
-      svn_revnum_t *invalid_revnum;
-      invalid_revnum = apr_palloc(pool, sizeof(*invalid_revnum));
       *invalid_revnum = SVN_INVALID_REVNUM;
-      *base_dir = NULL;
 
+      /* Get the common parent URL and a bunch of relpaths, one per target. */
+      SVN_ERR(condense_targets(&common_url, &rel_targets, targets,
+                               TRUE, TRUE, scratch_pool, result_pool));
+      if (! (common_url && *common_url))
+        return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+                                _("No common parent found, unable to operate "
+                                  "on disjoint arguments"));
+
+      /* Create mapping of the target relpaths to either
+         SVN_INVALID_REVNUM (if our caller is locking) or to an empty
+         lock token string (if the caller is unlocking). */
       for (i = 0; i < rel_targets->nelts; i++)
         {
-          const char *target = APR_ARRAY_IDX(rel_targets, i, const char *);
-          apr_hash_set(rel_targets_ret, svn_path_uri_decode(target, pool),
+          apr_hash_set(rel_targets_ret,
+                       APR_ARRAY_IDX(rel_targets, i, const char *),
                        APR_HASH_KEY_STRING,
-                       do_lock ? (const void *) invalid_revnum
-                       : (const void *) "");
+                       do_lock ? (const void *)invalid_revnum
+                               : (const void *)"");
         }
-      *rel_fs_paths_p = NULL;
     }
-  else  /* common parent is a local path */
+  else
     {
-      apr_array_header_t *rel_urls;
-      apr_array_header_t *urls = apr_array_make(pool, 1,
-                                                sizeof(const char *));
-      apr_hash_t *urls_hash = apr_hash_make(pool);
-      const char *common_url;
-
-      *base_dir = *common_parent_url;
-
-      /* Get the url for each target and verify all paths. */
+      apr_array_header_t *rel_urls, *target_urls;
+      apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+      
+      /* Get the common parent dirent and a bunch of relpaths, one per
+         target. */
+      SVN_ERR(condense_targets(&common_dirent, &rel_targets, targets,
+                               FALSE, TRUE, scratch_pool, result_pool));
+      if (! (common_dirent && *common_dirent))
+        return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+                                _("No common parent found, unable to operate "
+                                  "on disjoint arguments"));
+
+      /* Get the URL for each target (which also serves to verify that
+         the dirent targets are sane).  */
+      target_urls = apr_array_make(scratch_pool, rel_targets->nelts,
+                                   sizeof(const char *));
       for (i = 0; i < rel_targets->nelts; i++)
         {
-          const char *target = APR_ARRAY_IDX(rel_targets, i, const char *);
-          const char *local_abspath;
-          const char *url;
-
-          svn_pool_clear(subpool);
-
-          local_abspath = svn_dirent_join(*common_parent_url, target, subpool);
+          const char *rel_target, *local_abspath, *target_url;
 
-          SVN_ERR(svn_wc__node_get_url(&url, ctx->wc_ctx, local_abspath,
-                                       pool, subpool));
+          svn_pool_clear(iterpool);
 
-          if (! url)
+          rel_target = APR_ARRAY_IDX(rel_targets, i, const char *);
+          local_abspath = svn_dirent_join(common_dirent, rel_target, iterpool);
+          SVN_ERR(svn_wc__node_get_url(&target_url, ctx->wc_ctx, local_abspath,
+                                       scratch_pool, iterpool));
+          if (! target_url)
             return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
                                      _("'%s' has no URL"),
-                                     svn_dirent_local_style(target, pool));
+                                     svn_dirent_local_style(local_abspath,
+                                                            iterpool));
 
-          APR_ARRAY_PUSH(urls, const char *) = url;
+          APR_ARRAY_PUSH(target_urls, const char *) = target_url;
         }
 
-      /* Condense our absolute urls and get the relative urls. */
-      SVN_ERR(svn_uri_condense_targets(&common_url, &rel_urls, urls,
-                                       FALSE, pool, pool));
-
-      /* svn_uri_condense_targets leaves URLs empty if TARGETS only
-         had 1 member, so we special case that (again). */
-      if (apr_is_empty_array(rel_urls))
-        {
-          const char *base_name = svn_uri_basename(common_url, pool);
-          common_url = svn_uri_dirname(common_url, pool);
-          APR_ARRAY_PUSH(rel_urls, const char *) = base_name;
-        }
-
-      /* If we have no common URL parent, bail (cross-repos lock attempt) */
-      if (common_url == NULL || (common_url)[0] == '\0')
-        return svn_error_create
-          (SVN_ERR_UNSUPPORTED_FEATURE, NULL,
-           _("Unable to lock/unlock across multiple repositories"));
+      /* Now that we have a bunch of URLs for our dirent targets,
+         condense those into a single common parent URL and a bunch of
+         paths relative to that. */
+      SVN_ERR(condense_targets(&common_url, &rel_urls, target_urls,
+                               TRUE, FALSE, scratch_pool, result_pool));
+      if (! (common_url && *common_url))
+        return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+                                _("Unable to lock/unlock across multiple "
+                                  "repositories"));
 
-      /* Now that we've got the relative URLs, gather our targets and
-         store the mapping between relative repository path and WC path. */
+      /* Now we need to create a couple of different hash mappings. */
+      rel_fs_paths = apr_hash_make(result_pool);
       for (i = 0; i < rel_targets->nelts; i++)
         {
-          const char *target = APR_ARRAY_IDX(rel_targets, i, const char *);
-          const char *url = APR_ARRAY_IDX(rel_urls, i, const char *);
-          const char *abs_path;
-          const char *decoded_url = svn_path_uri_decode(url, pool);
-
-          svn_pool_clear(subpool);
+          const char *rel_target, *rel_url, *abs_path;
 
-          apr_hash_set(urls_hash, decoded_url,
-                       APR_HASH_KEY_STRING,
-                       apr_pstrdup(pool, target));
+          svn_pool_clear(iterpool);
 
-          abs_path = svn_dirent_join(*common_parent_url, target, subpool);
+          /* First, we need to map our REL_URL (which is relative to
+             COMMON_URL) to our REL_TARGET (which is relative to
+             COMMON_DIRENT). */
+          rel_target = APR_ARRAY_IDX(rel_targets, i, const char *);
+          rel_url = APR_ARRAY_IDX(rel_urls, i, const char *);
+          apr_hash_set(rel_fs_paths, rel_url, APR_HASH_KEY_STRING,
+                       apr_pstrdup(result_pool, rel_target));
+
+          /* Then, we map our REL_URL (again) to either the base
+             revision of the dirent target with which it is associated
+             (if our caller is locking) or to a (possible empty) lock
+             token string (if the caller is unlocking). */
+          abs_path = svn_dirent_join(common_dirent, rel_target, iterpool);
 
           if (do_lock) /* Lock. */
             {
               svn_revnum_t *revnum;
-              revnum = apr_palloc(pool, sizeof(* revnum));
+              revnum = apr_palloc(result_pool, sizeof(* revnum));
               SVN_ERR(svn_wc__node_get_base_rev(revnum, ctx->wc_ctx,
-                                                abs_path, subpool));
-              apr_hash_set(rel_targets_ret, decoded_url,
+                                                abs_path, result_pool));
+              apr_hash_set(rel_targets_ret, rel_url,
                            APR_HASH_KEY_STRING, revnum);
             }
           else /* Unlock. */
             {
-              /* If not force, get the lock token. */
+              const char *lock_token = NULL;
+
+              /* If not forcing the unlock, get the lock token. */
               if (! force)
                 {
-                  const char *lock_token;
-
                   SVN_ERR(svn_wc__node_get_lock_info(&lock_token, NULL, NULL,
                                                      NULL, ctx->wc_ctx,
-                                                     abs_path, pool, subpool));
+                                                     abs_path, result_pool,
+                                                     iterpool));
                   if (! lock_token)
-                    return svn_error_createf
-                      (SVN_ERR_CLIENT_MISSING_LOCK_TOKEN, NULL,
-                       _("'%s' is not locked in this working copy"), target);
-
-                  apr_hash_set(rel_targets_ret, decoded_url,
-                               APR_HASH_KEY_STRING,
-                               lock_token);
-                }
-              else
-                {
-                  /* If breaking a lock, we shouldn't pass any lock token. */
-                  apr_hash_set(rel_targets_ret, decoded_url,
-                               APR_HASH_KEY_STRING, "");
+                    return svn_error_createf(
+                               SVN_ERR_CLIENT_MISSING_LOCK_TOKEN, NULL,
+                               _("'%s' is not locked in this working copy"),
+                               abs_path);
                 }
+
+              /* If breaking a lock, we shouldn't pass any lock token. */
+              apr_hash_set(rel_targets_ret, rel_url, APR_HASH_KEY_STRING,
+                           lock_token ? lock_token : "");
             }
         }
 
-      *rel_fs_paths_p = urls_hash;
-      *common_parent_url = common_url;
+      svn_pool_destroy(iterpool);
     }
 
+  /* Set our return variables. */
+  *common_parent_url = common_url;
+  *base_dir = common_dirent;
   *rel_targets_p = rel_targets_ret;
-  svn_pool_destroy(subpool);
+  *rel_fs_paths_p = rel_fs_paths;
+
   return SVN_NO_ERROR;
 }
 
@@ -408,7 +444,7 @@ svn_client_lock(const apr_array_header_t
 
   SVN_ERR(organize_lock_targets(&common_parent_url, &base_dir, &path_revs,
                                 &urls_to_paths, targets, TRUE, steal_lock,
-                                ctx, pool));
+                                ctx, pool, pool));
 
   /* Open an RA session to the common parent of TARGETS. */
   if (base_dir)
@@ -448,7 +484,7 @@ svn_client_unlock(const apr_array_header
 
   SVN_ERR(organize_lock_targets(&common_parent_url, &base_dir, &path_tokens,
                                 &urls_to_paths, targets, FALSE, break_lock,
-                                ctx, pool));
+                                ctx, pool, pool));
 
   /* Open an RA session. */
   if (base_dir)

Modified: subversion/branches/performance/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_client/merge.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/performance/subversion/libsvn_client/merge.c Wed Feb  2 13:04:51 2011
@@ -54,6 +54,7 @@
 
 #include "private/svn_wc_private.h"
 #include "private/svn_mergeinfo_private.h"
+#include "private/svn_fspath.h"
 
 #include "svn_private_config.h"
 
@@ -529,7 +530,9 @@ make_tree_conflict(svn_wc_conflict_descr
 }
 
 /* Record a tree conflict in the WC, unless this is a dry run or a record-
- * only merge.
+ * only merge, or if a tree conflict is already flagged for the VICTIM_PATH.
+ * (The latter can happen if a merge-tracking-aware merge is doing multiple
+ * editor drives because of a gap in the range of eligible revisions.)
  *
  * The tree conflict, with its victim specified by VICTIM_PATH, is
  * assumed to have happened during a merge using merge baton MERGE_B.
@@ -546,16 +549,25 @@ tree_conflict(merge_cmd_baton_t *merge_b
               svn_wc_conflict_action_t action,
               svn_wc_conflict_reason_t reason)
 {
+  const svn_wc_conflict_description2_t *existing_conflict;
   svn_wc_conflict_description2_t *conflict;
 
   if (merge_b->record_only || merge_b->dry_run)
     return SVN_NO_ERROR;
 
-  SVN_ERR(make_tree_conflict(&conflict, merge_b, victim_abspath,
-                             node_kind, action, reason));
+  SVN_ERR(svn_wc__get_tree_conflict(&existing_conflict, merge_b->ctx->wc_ctx,
+                                    victim_abspath, merge_b->pool,
+                                    merge_b->pool));
+  if (existing_conflict == NULL)
+    {
+      /* There is no existing tree conflict so it is safe to add one. */
+      SVN_ERR(make_tree_conflict(&conflict, merge_b, victim_abspath,
+                                 node_kind, action, reason));
+      SVN_ERR(svn_wc__add_tree_conflict(merge_b->ctx->wc_ctx, conflict,
+                                        merge_b->pool));
+    }
 
-  return svn_error_return(
-    svn_wc__add_tree_conflict(merge_b->ctx->wc_ctx, conflict, merge_b->pool));
+  return SVN_NO_ERROR;
 }
 
 /* Similar to tree_conflict(), but if this is an "add" action and there

Modified: subversion/branches/performance/subversion/libsvn_client/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_client/mergeinfo.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_client/mergeinfo.c (original)
+++ subversion/branches/performance/subversion/libsvn_client/mergeinfo.c Wed Feb  2 13:04:51 2011
@@ -41,6 +41,7 @@
 #include "private/svn_mergeinfo_private.h"
 #include "private/svn_wc_private.h"
 #include "private/svn_ra_private.h"
+#include "private/svn_fspath.h"
 #include "client.h"
 #include "mergeinfo.h"
 #include "svn_private_config.h"
@@ -1667,11 +1668,9 @@ svn_client_mergeinfo_get_merged(apr_hash
         {
           const char *key = svn__apr_hash_index_key(hi);
           void *val = svn__apr_hash_index_val(hi);
-          const char *source_url;
-
-          source_url = svn_path_uri_encode(key, pool);
-          source_url = svn_uri_join(repos_root, source_url + 1, pool);
-          apr_hash_set(full_path_mergeinfo, source_url,
+            
+          apr_hash_set(full_path_mergeinfo,
+                       svn_path_url_add_component2(repos_root, key + 1, pool),
                        APR_HASH_KEY_STRING, val);
         }
       *mergeinfo_p = full_path_mergeinfo;

Modified: subversion/branches/performance/subversion/libsvn_client/patch.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_client/patch.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_client/patch.c (original)
+++ subversion/branches/performance/subversion/libsvn_client/patch.c Wed Feb  2 13:04:51 2011
@@ -32,6 +32,7 @@
 #include "svn_client.h"
 #include "svn_dirent_uri.h"
 #include "svn_diff.h"
+#include "svn_hash.h"
 #include "svn_io.h"
 #include "svn_path.h"
 #include "svn_pools.h"
@@ -48,7 +49,7 @@
 
 typedef struct hunk_info_t {
   /* The hunk. */
-  const svn_diff_hunk_t *hunk;
+  svn_diff_hunk_t *hunk;
 
   /* The line where the hunk matched in the target file. */
   svn_linenum_t matched_line;
@@ -483,7 +484,7 @@ init_prop_target(prop_patch_target_t **p
 
   content_info = apr_pcalloc(result_pool, sizeof(*content_info));
 
-  /* All other fields in are FALSE or NULL due to apr_pcalloc().*/
+  /* All other fields are FALSE or NULL due to apr_pcalloc(). */
   content_info->current_line = 1;
   content_info->eol_style = svn_subst_eol_style_none;
   content_info->lines = apr_array_make(result_pool, 0,
@@ -834,7 +835,7 @@ seek_to_line(target_content_info_t *cont
  * Do temporary allocations in POOL. */
 static svn_error_t *
 match_hunk(svn_boolean_t *matched, target_content_info_t *content_info,
-           const svn_diff_hunk_t *hunk, int fuzz,
+           svn_diff_hunk_t *hunk, int fuzz,
            svn_boolean_t ignore_whitespace,
            svn_boolean_t match_modified, apr_pool_t *pool)
 {
@@ -861,12 +862,12 @@ match_hunk(svn_boolean_t *matched, targe
   trailing_context = svn_diff_hunk_get_trailing_context(hunk);
   if (match_modified)
     {
-      SVN_ERR(svn_diff_hunk_reset_modified_text(hunk));
+      svn_diff_hunk_reset_modified_text(hunk);
       hunk_length = svn_diff_hunk_get_modified_length(hunk);
     }
   else
     {
-      SVN_ERR(svn_diff_hunk_reset_original_text(hunk));
+      svn_diff_hunk_reset_original_text(hunk);
       hunk_length = svn_diff_hunk_get_original_length(hunk);
     }
   iterpool = svn_pool_create(pool);
@@ -950,7 +951,7 @@ match_hunk(svn_boolean_t *matched, targe
 static svn_error_t *
 scan_for_match(svn_linenum_t *matched_line,
                target_content_info_t *content_info,
-               const svn_diff_hunk_t *hunk, svn_boolean_t match_first,
+               svn_diff_hunk_t *hunk, svn_boolean_t match_first,
                svn_linenum_t upper_line, int fuzz,
                svn_boolean_t ignore_whitespace,
                svn_boolean_t match_modified,
@@ -1022,7 +1023,7 @@ scan_for_match(svn_linenum_t *matched_li
 static svn_error_t *
 match_existing_target(svn_boolean_t *match,
                       target_content_info_t *content_info,
-                      const svn_diff_hunk_t *hunk,
+                      svn_diff_hunk_t *hunk,
                       svn_stream_t *stream,
                       apr_pool_t *scratch_pool)
 {
@@ -1031,7 +1032,7 @@ match_existing_target(svn_boolean_t *mat
   svn_boolean_t eof;
   svn_boolean_t hunk_eof;
 
-  SVN_ERR(svn_diff_hunk_reset_modified_text(hunk));
+  svn_diff_hunk_reset_modified_text(hunk);
 
   iterpool = svn_pool_create(scratch_pool);
   do
@@ -1087,7 +1088,7 @@ match_existing_target(svn_boolean_t *mat
 static svn_error_t *
 get_hunk_info(hunk_info_t **hi, patch_target_t *target,
               target_content_info_t *content_info,
-              const svn_diff_hunk_t *hunk, int fuzz,
+              svn_diff_hunk_t *hunk, int fuzz,
               svn_boolean_t ignore_whitespace,
               svn_boolean_t is_prop_hunk,
               svn_cancel_func_t cancel_func, void *cancel_baton,
@@ -1301,7 +1302,7 @@ copy_lines_to_target(target_content_info
  * Do temporary allocations in POOL. */
 static svn_error_t *
 reject_hunk(patch_target_t *target, target_content_info_t *content_info,
-            const svn_diff_hunk_t *hunk, const char *prop_name,
+            svn_diff_hunk_t *hunk, const char *prop_name,
             apr_pool_t *pool)
 {
   const char *hunk_header;
@@ -1419,7 +1420,7 @@ apply_hunk(patch_target_t *target, targe
   /* Write the hunk's version to the patched result.
    * Don't write the lines which matched with fuzz. */
   lines_read = 0;
-  SVN_ERR(svn_diff_hunk_reset_modified_text(hi->hunk));
+  svn_diff_hunk_reset_modified_text(hi->hunk);
   iterpool = svn_pool_create(pool);
   do
     {
@@ -1701,6 +1702,9 @@ apply_one_patch(patch_target_t **patch_t
 
       svn_pool_clear(iterpool);
 
+      if (cancel_func)
+        SVN_ERR((cancel_func)(cancel_baton));
+
       hi = APR_ARRAY_IDX(target->content_info->hunks, i, hunk_info_t *);
       if (hi->already_applied)
         continue;
@@ -1935,8 +1939,7 @@ create_missing_parents(patch_target_t *t
 
       svn_pool_clear(iterpool);
 
-      component = APR_ARRAY_IDX(components, i,
-                                const char *);
+      component = APR_ARRAY_IDX(components, i, const char *);
       local_abspath = svn_dirent_join(local_abspath, component, scratch_pool);
 
       SVN_ERR(svn_wc_read_kind(&wc_kind, ctx->wc_ctx, local_abspath, TRUE,
@@ -1990,8 +1993,7 @@ create_missing_parents(patch_target_t *t
       for (i = 0; i < present_components; i++)
         {
           const char *component;
-          component = APR_ARRAY_IDX(components, i,
-                                    const char *);
+          component = APR_ARRAY_IDX(components, i, const char *);
           local_abspath = svn_dirent_join(local_abspath,
                                           component, scratch_pool);
         }
@@ -2011,10 +2013,9 @@ create_missing_parents(patch_target_t *t
 
           svn_pool_clear(iterpool);
 
-          component = APR_ARRAY_IDX(components, i,
-                                    const char *);
+          component = APR_ARRAY_IDX(components, i, const char *);
           local_abspath = svn_dirent_join(local_abspath, component,
-                                     scratch_pool);
+                                          scratch_pool);
           if (dry_run)
             {
               if (ctx->notify_func2)
@@ -2211,6 +2212,9 @@ install_patched_prop_targets(patch_targe
 
       svn_pool_clear(iterpool);
 
+      if (ctx->cancel_func)
+        SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
+
       /* For a deleted prop we only set the value to NULL. */
       if (prop_target->operation == svn_diff_op_deleted)
         {
@@ -2267,8 +2271,6 @@ install_patched_prop_targets(patch_targe
             {
               SVN_ERR(svn_io_file_create(target->local_abspath, "",
                                          scratch_pool));
-              if (ctx->cancel_func)
-                SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
               SVN_ERR(svn_wc_add_from_disk(ctx->wc_ctx, target->local_abspath,
                                            /* suppress notification */
                                            NULL, NULL,
@@ -2368,14 +2370,14 @@ find_existing_children(void *baton,
 
 /* Indicate in *EMPTY whether the directory at LOCAL_ABSPATH has any
  * versioned or unversioned children. Consider any DELETED_TARGETS,
- * as well as paths listed in DELETED_ABSPATHS_LIST (which may be NULL)
- * as already deleted. Use WC_CTX as the working copy context.
+ * as well as paths occuring as keys of DELETED_ABSPATHS_HASH (which may
+ * be NULL) as already deleted. Use WC_CTX as the working copy context.
  * Do temporary allocations in SCRATCH_POOL. */
 static svn_error_t *
 check_dir_empty(svn_boolean_t *empty, const char *local_abspath,
                 svn_wc_context_t *wc_ctx,
                 apr_array_header_t *deleted_targets,
-                apr_array_header_t *deleted_abspath_list,
+                apr_hash_t *deleted_abspath_hash,
                 apr_pool_t *scratch_pool)
 {
   struct status_baton btn;
@@ -2423,13 +2425,17 @@ check_dir_empty(svn_boolean_t *empty, co
               break;
            }
         }
-      if (! deleted && deleted_abspath_list)
+      if (! deleted && deleted_abspath_hash)
         {
-          for (j = 0; j < deleted_abspath_list->nelts; j++)
+          apr_hash_index_t *hi;
+
+          for (hi = apr_hash_first(scratch_pool, deleted_abspath_hash);
+               hi;
+               hi = apr_hash_next(hi))
             {
               const char *abspath;
 
-              abspath = APR_ARRAY_IDX(deleted_abspath_list, j, const char *);
+              abspath = svn__apr_hash_index_key(hi);
               if (! svn_path_compare_paths(found, abspath))
                {
                   deleted = TRUE;
@@ -2447,33 +2453,6 @@ check_dir_empty(svn_boolean_t *empty, co
   return SVN_NO_ERROR;
 }
 
-/* Push a copy of EMPTY_DIR, allocated in RESULT_POOL, onto the EMPTY_DIRS
- * array if no directory matching EMPTY_DIR is already in the array. */
-static void
-push_if_unique(apr_array_header_t *empty_dirs, const char *empty_dir,
-               apr_pool_t *result_pool)
-{
-  svn_boolean_t is_unique;
-  int i;
-
-  is_unique = TRUE;
-  for (i = 0; i < empty_dirs->nelts; i++)
-    {
-      const char *empty_dir2;
-
-      empty_dir2 = APR_ARRAY_IDX(empty_dirs, i, const char *);
-      if (strcmp(empty_dir, empty_dir2) == 0)
-        {
-          is_unique = FALSE;
-          break;
-        }
-    }
-
-  if (is_unique)
-    APR_ARRAY_PUSH(empty_dirs, const char *) = apr_pstrdup(result_pool,
-                                                           empty_dir);
-}
-
 /* Delete all directories from the working copy which are left empty
  * by deleted TARGETS. Use client context CTX.
  * If DRY_RUN is TRUE, do not modify the working copy.
@@ -2482,11 +2461,13 @@ static svn_error_t *
 delete_empty_dirs(apr_array_header_t *targets_info, svn_client_ctx_t *ctx,
                   svn_boolean_t dry_run, apr_pool_t *scratch_pool)
 {
-  apr_array_header_t *empty_dirs;
+  apr_hash_t *empty_dirs;
+  apr_hash_t *non_empty_dirs;
   apr_array_header_t *deleted_targets;
   apr_pool_t *iterpool;
   svn_boolean_t again;
   int i;
+  apr_hash_index_t *hi;
 
   /* Get a list of all deleted targets. */
   deleted_targets = apr_array_make(scratch_pool, 0, sizeof(patch_target_t *));
@@ -2504,7 +2485,8 @@ delete_empty_dirs(apr_array_header_t *ta
     return SVN_NO_ERROR;
 
   /* Look for empty parent directories of deleted targets. */
-  empty_dirs = apr_array_make(scratch_pool, 0, sizeof(const char *));
+  empty_dirs = apr_hash_make(scratch_pool);
+  non_empty_dirs = apr_hash_make(scratch_pool);
   iterpool = svn_pool_create(scratch_pool);
   for (i = 0; i < targets_info->nelts; i++)
     {
@@ -2519,17 +2501,24 @@ delete_empty_dirs(apr_array_header_t *ta
 
       target_info = APR_ARRAY_IDX(targets_info, i, patch_target_info_t *);
       parent = svn_dirent_dirname(target_info->local_abspath, iterpool);
+
+      if (apr_hash_get(non_empty_dirs, parent, APR_HASH_KEY_STRING))
+        continue;
+      else if (apr_hash_get(empty_dirs, parent, APR_HASH_KEY_STRING))
+        continue;
+
       SVN_ERR(check_dir_empty(&parent_empty, parent, ctx->wc_ctx,
                               deleted_targets, NULL, iterpool));
       if (parent_empty)
-        {
-          APR_ARRAY_PUSH(empty_dirs, const char *) =
-            apr_pstrdup(scratch_pool, parent);
-        }
+        apr_hash_set(empty_dirs, apr_pstrdup(scratch_pool, parent),
+                     APR_HASH_KEY_STRING, "");
+      else
+        apr_hash_set(non_empty_dirs, apr_pstrdup(scratch_pool, parent),
+                     APR_HASH_KEY_STRING, "");
     }
 
   /* We have nothing to do if there aren't any empty directories. */
-  if (empty_dirs->nelts == 0)
+  if (apr_hash_count(empty_dirs) == 0)
     {
       svn_pool_destroy(iterpool);
       return SVN_NO_ERROR;
@@ -2538,7 +2527,7 @@ delete_empty_dirs(apr_array_header_t *ta
   /* Determine the minimal set of empty directories we need to delete. */
   do
     {
-      apr_array_header_t *empty_dirs_copy;
+      apr_hash_t *empty_dirs_copy;
 
       svn_pool_clear(iterpool);
 
@@ -2548,32 +2537,43 @@ delete_empty_dirs(apr_array_header_t *ta
       /* Rebuild the empty dirs list, replacing empty dirs which have
        * an empty parent with their parent. */
       again = FALSE;
-      empty_dirs_copy = apr_array_copy(iterpool, empty_dirs);
-      apr_array_clear(empty_dirs);
-      for (i = 0; i < empty_dirs_copy->nelts; i++)
+      empty_dirs_copy = apr_hash_copy(iterpool, empty_dirs);
+      SVN_ERR(svn_hash__clear(empty_dirs, iterpool));
+
+      for (hi = apr_hash_first(iterpool, empty_dirs_copy);
+           hi;
+           hi = apr_hash_next(hi))
         {
           svn_boolean_t parent_empty;
           const char *empty_dir;
           const char *parent;
 
-          empty_dir = APR_ARRAY_IDX(empty_dirs_copy, i, const char *);
+          empty_dir = svn__apr_hash_index_key(hi);
           parent = svn_dirent_dirname(empty_dir, iterpool);
+
+          if (apr_hash_get(empty_dirs, parent, APR_HASH_KEY_STRING))
+            continue;
+
           SVN_ERR(check_dir_empty(&parent_empty, parent, ctx->wc_ctx,
                                   deleted_targets, empty_dirs_copy,
                                   iterpool));
           if (parent_empty)
             {
               again = TRUE;
-              push_if_unique(empty_dirs, parent, scratch_pool);
+              apr_hash_set(empty_dirs, apr_pstrdup(scratch_pool, parent),
+                           APR_HASH_KEY_STRING, "");
             }
           else
-            push_if_unique(empty_dirs, empty_dir, scratch_pool);
+            apr_hash_set(empty_dirs, apr_pstrdup(scratch_pool, empty_dir),
+                         APR_HASH_KEY_STRING, "");
         }
     }
   while (again);
 
   /* Finally, delete empty directories. */
-  for (i = 0; i < empty_dirs->nelts; i++)
+  for (hi = apr_hash_first(scratch_pool, empty_dirs);
+       hi;
+       hi = apr_hash_next(hi))
     {
       const char *empty_dir;
 
@@ -2582,7 +2582,12 @@ delete_empty_dirs(apr_array_header_t *ta
       if (ctx->cancel_func)
         SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
 
-      empty_dir = APR_ARRAY_IDX(empty_dirs, i, const char *);
+      empty_dir = svn__apr_hash_index_key(hi);
+      if (! dry_run)
+        SVN_ERR(svn_wc_delete4(ctx->wc_ctx, empty_dir, FALSE, FALSE,
+                               ctx->cancel_func, ctx->cancel_baton,
+                               NULL, NULL, /* no duplicate notification */
+                               iterpool));
       if (ctx->notify_func2)
         {
           svn_wc_notify_t *notify;
@@ -2591,11 +2596,6 @@ delete_empty_dirs(apr_array_header_t *ta
                                         iterpool);
           (*ctx->notify_func2)(ctx->notify_baton2, notify, iterpool);
         }
-      if (! dry_run)
-        SVN_ERR(svn_wc_delete4(ctx->wc_ctx, empty_dir, FALSE, FALSE,
-                               ctx->cancel_func, ctx->cancel_baton,
-                               NULL, NULL, /* no duplicate notification */
-                               iterpool));
     }
   svn_pool_destroy(iterpool);
 
@@ -2643,13 +2643,13 @@ apply_patches(void *baton,
 {
   svn_patch_t *patch;
   apr_pool_t *iterpool;
-  apr_file_t *patch_file;
+  svn_patch_file_t *patch_file;
   apr_array_header_t *targets_info;
   apply_patches_baton_t *btn = baton;
 
   /* Try to open the patch file. */
-  SVN_ERR(svn_io_file_open(&patch_file, btn->patch_abspath,
-                           APR_READ | APR_BINARY, 0, scratch_pool));
+  SVN_ERR(svn_diff_open_patch_file(&patch_file, btn->patch_abspath,
+                                   scratch_pool));
 
   /* Apply patches. */
   targets_info = apr_array_make(scratch_pool, 0,
@@ -2707,8 +2707,6 @@ apply_patches(void *baton,
                 }
               SVN_ERR(send_patch_notification(target, btn->ctx, iterpool));
             }
-
-          SVN_ERR(svn_diff_close_patch(patch, iterpool));
         }
     }
   while (patch);
@@ -2717,7 +2715,7 @@ apply_patches(void *baton,
   SVN_ERR(delete_empty_dirs(targets_info, btn->ctx, btn->dry_run,
                             scratch_pool));
 
-  SVN_ERR(svn_io_file_close(patch_file, iterpool));
+  SVN_ERR(svn_diff_close_patch_file(patch_file, iterpool));
   svn_pool_destroy(iterpool);
 
   return SVN_NO_ERROR;
@@ -2738,6 +2736,7 @@ svn_client_patch(const char *patch_abspa
                  apr_pool_t *scratch_pool)
 {
   apply_patches_baton_t baton;
+  svn_node_kind_t kind;
 
   if (strip_count < 0)
     return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
@@ -2747,6 +2746,22 @@ svn_client_patch(const char *patch_abspa
     return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
                              _("'%s' is not a local path"), local_abspath);
 
+  SVN_ERR(svn_io_check_path(patch_abspath, &kind, scratch_pool));
+  if (kind == svn_node_none)
+    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                             _("'%s' does not exist"), patch_abspath);
+  if (kind != svn_node_file)
+    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                             _("'%s' is not a file"), patch_abspath);
+
+  SVN_ERR(svn_io_check_path(local_abspath, &kind, scratch_pool));
+  if (kind == svn_node_none)
+    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                             _("'%s' does not exist"), local_abspath);
+  if (kind != svn_node_dir)
+    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                             _("'%s' is not a directory"), local_abspath);
+
   baton.patch_abspath = patch_abspath;
   baton.abs_wc_path = local_abspath;
   baton.dry_run = dry_run;

Modified: subversion/branches/performance/subversion/libsvn_client/prop_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_client/prop_commands.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_client/prop_commands.c (original)
+++ subversion/branches/performance/subversion/libsvn_client/prop_commands.c Wed Feb  2 13:04:51 2011
@@ -746,6 +746,9 @@ remote_propget(apr_hash_t *props,
 {
   apr_hash_t *dirents;
   apr_hash_t *prop_hash;
+  const svn_string_t *val;
+  const char *target_full_url =
+    svn_path_url_add_component2(target_prefix, target_relative, work_pool);
 
   if (kind == svn_node_dir)
     {
@@ -761,29 +764,22 @@ remote_propget(apr_hash_t *props,
     }
   else if (kind == svn_node_none)
     {
-      return svn_error_createf
-        (SVN_ERR_ENTRY_NOT_FOUND, NULL,
-         _("'%s' does not exist in revision %ld"),
-         svn_uri_join(target_prefix, target_relative, work_pool), revnum);
+      return svn_error_createf(SVN_ERR_ENTRY_NOT_FOUND, NULL,
+                               _("'%s' does not exist in revision %ld"),
+                               target_full_url, revnum);
     }
   else
     {
-      return svn_error_createf
-        (SVN_ERR_NODE_UNKNOWN_KIND, NULL,
-         _("Unknown node kind for '%s'"),
-         svn_uri_join(target_prefix, target_relative, work_pool));
-    }
-
-  {
-    svn_string_t *val = apr_hash_get(prop_hash, propname,
-                                     APR_HASH_KEY_STRING);
-    if (val)
-      {
-        apr_hash_set(props,
-                     svn_uri_join(target_prefix, target_relative, perm_pool),
-                     APR_HASH_KEY_STRING, svn_string_dup(val, perm_pool));
-      }
-  }
+      return svn_error_createf(SVN_ERR_NODE_UNKNOWN_KIND, NULL,
+                               _("Unknown node kind for '%s'"),
+                               target_full_url);
+    }
+
+  if ((val = apr_hash_get(prop_hash, propname, APR_HASH_KEY_STRING)))
+    {
+      apr_hash_set(props, apr_pstrdup(perm_pool, target_full_url),
+                   APR_HASH_KEY_STRING, svn_string_dup(val, perm_pool));
+    }
 
   if (depth >= svn_depth_files
       && kind == svn_node_dir
@@ -1071,6 +1067,8 @@ remote_proplist(const char *target_prefi
   apr_hash_t *dirents;
   apr_hash_t *prop_hash, *final_hash;
   apr_hash_index_t *hi;
+  const char *target_full_url =
+    svn_path_url_add_component2(target_prefix, target_relative, scratchpool);
 
   if (kind == svn_node_dir)
     {
@@ -1086,10 +1084,9 @@ remote_proplist(const char *target_prefi
     }
   else
     {
-      return svn_error_createf
-        (SVN_ERR_NODE_UNKNOWN_KIND, NULL,
-         _("Unknown node kind for '%s'"),
-         svn_uri_join(target_prefix, target_relative, pool));
+      return svn_error_createf(SVN_ERR_NODE_UNKNOWN_KIND, NULL,
+                               _("Unknown node kind for '%s'"),
+                               target_full_url);
     }
 
   /* Filter out non-regular properties, since the RA layer returns all
@@ -1115,9 +1112,7 @@ remote_proplist(const char *target_prefi
         }
     }
 
-  call_receiver(svn_uri_join(target_prefix, target_relative, scratchpool),
-                final_hash, receiver, receiver_baton,
-                pool);
+  call_receiver(target_full_url, final_hash, receiver, receiver_baton, pool);
 
   if (depth > svn_depth_empty
       && (kind == svn_node_dir) && (apr_hash_count(dirents) > 0))

Modified: subversion/branches/performance/subversion/libsvn_client/ra.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_client/ra.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_client/ra.c (original)
+++ subversion/branches/performance/subversion/libsvn_client/ra.c Wed Feb  2 13:04:51 2011
@@ -759,20 +759,10 @@ svn_client__repos_locations(const char *
          "repository or refers to an unrelated object"),
        path_or_url_local_style(path, pool), end_revnum);
 
-  /* Repository paths might be absolute, but we want to treat them as
-     relative.
-     ### Aren't they always absolute? */
-  if (start_path[0] == '/')
-    start_path = start_path + 1;
-  if (end_path[0] == '/')
-    end_path = end_path + 1;
-
   /* Set our return variables */
-  *start_url = svn_uri_join(repos_url, svn_path_uri_encode(start_path,
-                                                            pool), pool);
+  *start_url = svn_path_url_add_component2(repos_url, start_path + 1, pool);
   if (end->kind != svn_opt_revision_unspecified)
-    *end_url = svn_uri_join(repos_url, svn_path_uri_encode(end_path,
-                                                            pool), pool);
+    *end_url = svn_path_url_add_component2(repos_url, end_path + 1, pool);
 
   svn_pool_destroy(subpool);
   return SVN_NO_ERROR;

Modified: subversion/branches/performance/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_client/repos_diff.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/branches/performance/subversion/libsvn_client/repos_diff.c Wed Feb  2 13:04:51 2011
@@ -32,6 +32,8 @@
  * each file have been created the diff callback is invoked to display
  * the difference between the two files.  */
 
+#include <apr_uri.h>
+
 #include "svn_hash.h"
 #include "svn_wc.h"
 #include "svn_pools.h"
@@ -66,6 +68,10 @@ struct edit_baton {
   /* RA_SESSION is the open session for making requests to the RA layer */
   svn_ra_session_t *ra_session;
 
+  /* TRUE if RA_SESSION is open to a repository URL using the http or https
+     scheme. */
+  svn_boolean_t is_dav_session;
+
   /* The rev1 from the '-r Rev1:Rev2' command line option */
   svn_revnum_t revision;
 
@@ -1168,9 +1174,9 @@ change_file_prop(void *file_baton,
   if (b->skip)
     return SVN_NO_ERROR;
 
-  /* Issue #3657 'phantom svn:eol-style changes cause spurious merge text
-     conflicts'.  When communicating with the repository via ra_serf and
-     ra_neon, the change_dir_prop and change_file_prop svn_delta_editor_t
+  /* Issue #3657 'dav update report handler in skelta mode can cause
+     spurious conflicts'.  When communicating with the repository via ra_serf
+     and ra_neon, the change_dir_prop and change_file_prop svn_delta_editor_t
      callbacks are called (obviously) when a directory or file property has
      changed between the start and end of the edit.  Less obvious however,
      is that these callbacks may be made describing *all* of the properties
@@ -1178,11 +1184,24 @@ change_file_prop(void *file_baton,
      (Specifically ra_neon does this for diff/merge and ra_serf does it
      for diff/merge/update/switch).
 
-     Normally this is fairly harmless, but if it appears that the
-     svn:eol-style property has changed on a file, then we can get spurious
-     text conflicts (i.e. Issue #3657).  To prevent this, we populate
-     FILE_BATON->PRISTINE_PROPS only with actual property changes. */
-  if (value)
+     This means that the change_[file|dir]_prop svn_delta_editor_t callbacks
+     may be made where there are no property changes (i.e. a noop change of
+     NAME from VALUE to VALUE).  Normally this is harmless, but during a
+     merge it can result in spurious conflicts if the WC's pristine property
+     NAME has a value other than VALUE.  In an ideal world the mod_dav_svn
+     update report handler, when in 'skelta' mode and describing changes to
+     a path on which a property has changed, wouldn't ask the client to later
+     fetch all properties and figure out what has changed itself.  The server
+     already knows which properties have changed!
+
+     Regardless, such a change is not yet implemented, and even when it is,
+     the client should DTRT with regard to older servers which behave this
+     way.  Hence this little hack:  We populate FILE_BATON->PROPCHANGES only
+     with *actual* property changes.
+
+     See http://subversion.tigris.org/issues/show_bug.cgi?id=3657#desc9 and
+     http://svn.haxx.se/dev/archive-2010-08/0351.shtml for more details. */
+  if (value && b->edit_baton->is_dav_session)
     {
       const char *current_prop = svn_prop_get_value(b->pristine_props, name);
       if (current_prop && strcmp(current_prop, value->data) == 0)
@@ -1210,6 +1229,15 @@ change_dir_prop(void *dir_baton,
   if (db->skip)
     return SVN_NO_ERROR;
 
+  /* See the comment re issue #3657 in the change_file_prop() callback. */
+  if (value && db->edit_baton->is_dav_session)
+    {
+      const char *current_prop = svn_prop_get_value(db->pristine_props,
+                                                    name);
+      if (current_prop && strcmp(current_prop, value->data) == 0)
+        return SVN_NO_ERROR;
+    }
+
   propchange = apr_array_push(db->propchanges);
   propchange->name = apr_pstrdup(db->pool, name);
   propchange->value = value ? svn_string_dup(value, db->pool) : NULL;
@@ -1309,6 +1337,10 @@ svn_client__get_diff_editor(const char *
   svn_delta_editor_t *tree_editor = svn_delta_default_editor(subpool);
   struct edit_baton *eb = apr_palloc(subpool, sizeof(*eb));
   const char *target_abspath;
+  const char *session_url;
+  apr_status_t status;
+  apr_uri_t apr_uri;
+
   SVN_ERR(svn_dirent_get_absolute(&target_abspath, target, pool));
 
   eb->target = target;
@@ -1317,6 +1349,23 @@ svn_client__get_diff_editor(const char *
   eb->diff_cmd_baton = diff_cmd_baton;
   eb->dry_run = dry_run;
   eb->ra_session = ra_session;
+
+  SVN_ERR(svn_ra_get_session_url(ra_session, &session_url, subpool));
+  status = apr_uri_parse(subpool, session_url, &apr_uri);
+  if (status)
+    {
+      return svn_error_createf(SVN_ERR_BAD_URL, NULL,
+                               _("Unable to parse URL '%s'"), session_url);
+    }
+  else
+    {
+      if (svn_cstring_casecmp(apr_uri.scheme, "https") == 0
+          || svn_cstring_casecmp(apr_uri.scheme, "http") == 0)
+        eb->is_dav_session = TRUE;
+      else
+        eb->is_dav_session = FALSE;
+    }
+
   eb->revision = revision;
   eb->empty_file = NULL;
   eb->empty_hash = apr_hash_make(subpool);

Modified: subversion/branches/performance/subversion/libsvn_client/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_client/status.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_client/status.c (original)
+++ subversion/branches/performance/subversion/libsvn_client/status.c Wed Feb  2 13:04:51 2011
@@ -585,6 +585,9 @@ svn_client_status_dup(const svn_client_s
   if (status->changelist)
     st->changelist = apr_pstrdup(result_pool, status->changelist);
 
+  if (status->ood_changed_author)
+    st->ood_changed_author = apr_pstrdup(result_pool, status->ood_changed_author);
+
   if (status->repos_lock)
     st->repos_lock = svn_lock_dup(status->repos_lock, result_pool);
 

Modified: subversion/branches/performance/subversion/libsvn_client/switch.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_client/switch.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_client/switch.c (original)
+++ subversion/branches/performance/subversion/libsvn_client/switch.c Wed Feb  2 13:04:51 2011
@@ -170,11 +170,9 @@ switch_internal(svn_revnum_t *result_rev
   /* Disallow a switch operation to change the repository root of the
      target. */
   if (! svn_uri_is_ancestor(source_root, url))
-    return svn_error_createf
-      (SVN_ERR_WC_INVALID_SWITCH, NULL,
-       _("'%s'\n"
-         "is not the same repository as\n"
-         "'%s'"), url, source_root);
+    return svn_error_createf(SVN_ERR_WC_INVALID_SWITCH, NULL,
+                             _("'%s'\nis not the same repository as\n'%s'"),
+                             url, source_root);
 
   SVN_ERR(svn_ra_reparent(ra_session, url, pool));
 

Modified: subversion/branches/performance/subversion/libsvn_client/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_client/update.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_client/update.c (original)
+++ subversion/branches/performance/subversion/libsvn_client/update.c Wed Feb  2 13:04:51 2011
@@ -298,7 +298,7 @@ svn_client__update_internal(svn_revnum_t
 {
   const char *anchor_abspath, *lockroot_abspath;
   svn_error_t *err;
-  svn_opt_revision_t peg_revision = *((svn_opt_revision_t *)revision);
+  svn_opt_revision_t peg_revision = *revision;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
   SVN_ERR_ASSERT(! (innerupdate && make_parents));

Modified: subversion/branches/performance/subversion/libsvn_client/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_client/util.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_client/util.c (original)
+++ subversion/branches/performance/subversion/libsvn_client/util.c Wed Feb  2 13:04:51 2011
@@ -36,6 +36,7 @@
 
 #include "private/svn_client_private.h"
 #include "private/svn_wc_private.h"
+#include "private/svn_fspath.h"
 
 #include "client.h"
 
@@ -217,11 +218,10 @@ svn_client__path_relative_to_root(const 
                                      "root URL '%s'"),
                                    abspath_or_url, repos_root);
         }
-      rel_url = svn_path_uri_decode(rel_url, result_pool);
-      *rel_path = include_leading_slash
-                    ? apr_pstrcat(result_pool, "/", rel_url,
-                                  (char *)NULL)
-                    : rel_url;
+      if (include_leading_slash)
+        *rel_path = svn_fspath__canonicalize(rel_url, result_pool);
+      else
+        *rel_path = apr_pstrdup(result_pool, rel_url);
     }
 
   return SVN_NO_ERROR;

Modified: subversion/branches/performance/subversion/libsvn_delta/path_driver.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_delta/path_driver.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_delta/path_driver.c (original)
+++ subversion/branches/performance/subversion/libsvn_delta/path_driver.c Wed Feb  2 13:04:51 2011
@@ -31,6 +31,7 @@
 #include "svn_dirent_uri.h"
 #include "svn_path.h"
 #include "svn_sorts.h"
+#include "private/svn_fspath.h"
 
 
 /*** Helper functions. ***/



Mime
View raw message