You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2012/08/16 12:18:03 UTC

svn commit: r1373783 [11/50] - in /subversion/branches/compressed-pristines: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ contrib/client-side/emacs/ contrib/client-side/svn-push/ contrib/client-side/svnmerge/ cont...

Modified: subversion/branches/compressed-pristines/subversion/libsvn_client/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_client/mergeinfo.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_client/mergeinfo.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_client/mergeinfo.c Thu Aug 16 10:17:48 2012
@@ -217,8 +217,9 @@ svn_client__get_wc_mergeinfo(svn_mergein
   if (limit_abspath)
     SVN_ERR_ASSERT(svn_dirent_is_absolute(limit_abspath));
 
-  SVN_ERR(svn_wc__node_get_base_rev(&base_revision, ctx->wc_ctx,
-                                    local_abspath, scratch_pool));
+  SVN_ERR(svn_wc__node_get_base(&base_revision, NULL, NULL, NULL, ctx->wc_ctx,
+                                local_abspath,
+                                scratch_pool, scratch_pool));
 
   iterpool = svn_pool_create(scratch_pool);
   while (TRUE)
@@ -284,9 +285,9 @@ svn_client__get_wc_mergeinfo(svn_mergein
                                           walk_relpath, result_pool);
           local_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
 
-          SVN_ERR(svn_wc__node_get_base_rev(&parent_base_rev,
-                                            ctx->wc_ctx, local_abspath,
-                                            scratch_pool));
+          SVN_ERR(svn_wc__node_get_base(&parent_base_rev, NULL, NULL, NULL,
+                                        ctx->wc_ctx, local_abspath,
+                                        scratch_pool, scratch_pool));
           SVN_ERR(svn_wc__node_get_changed_info(&parent_changed_rev,
                                                 NULL, NULL,
                                                 ctx->wc_ctx, local_abspath,
@@ -372,7 +373,6 @@ svn_client__get_wc_mergeinfo_catalog(svn
   const char *target_repos_rel_path;
   svn_mergeinfo_t mergeinfo;
   const char *repos_root;
-  svn_node_kind_t kind;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
   *mergeinfo_cat = NULL;
@@ -388,12 +388,9 @@ svn_client__get_wc_mergeinfo_catalog(svn
       return SVN_NO_ERROR;
     }
 
-  SVN_ERR(svn_client__path_relative_to_root(&target_repos_rel_path,
-                                            ctx->wc_ctx,
-                                            local_abspath,
-                                            NULL, FALSE,
-                                            NULL, scratch_pool,
-                                            scratch_pool));
+  SVN_ERR(svn_wc__node_get_repos_relpath(&target_repos_rel_path,
+                                         ctx->wc_ctx, local_abspath,
+                                         scratch_pool, scratch_pool));
 
   /* Get the mergeinfo for the LOCAL_ABSPATH target and set *INHERITED and
      *WALKED_PATH. */
@@ -413,38 +410,37 @@ svn_client__get_wc_mergeinfo_catalog(svn
     }
 
   /* If LOCAL_ABSPATH is a directory and we want the subtree mergeinfo too,
-     then get it. */
-  SVN_ERR(svn_wc_read_kind(&kind, ctx->wc_ctx, local_abspath, FALSE,
-                           scratch_pool));
-  if (kind == svn_node_dir && include_descendants)
+     then get it.
+
+     With WC-NG it is cheaper to do a single db transaction, than first
+     looking if we really have a directory. */
+  if (include_descendants)
     {
       apr_hash_t *mergeinfo_props;
       apr_hash_index_t *hi;
-      svn_opt_revision_t opt;
-
-      opt.kind = svn_opt_revision_unspecified;
 
-      SVN_ERR(svn_client_propget4(&mergeinfo_props,
-                                  SVN_PROP_MERGEINFO,
-                                  local_abspath,
-                                  &opt, &opt,
-                                  NULL, svn_depth_infinity, NULL,
-                                  ctx, scratch_pool, scratch_pool));
+      SVN_ERR(svn_wc__prop_retrieve_recursive(&mergeinfo_props,
+                                              ctx->wc_ctx, local_abspath,
+                                              SVN_PROP_MERGEINFO,
+                                              scratch_pool, scratch_pool));
 
       /* Convert *mergeinfo_props into a proper svn_mergeinfo_catalog_t */
       for (hi = apr_hash_first(scratch_pool, mergeinfo_props);
            hi;
            hi = apr_hash_next(hi))
         {
-          const char *key_path = svn__apr_hash_index_key(hi);
+          const char *node_abspath = svn__apr_hash_index_key(hi);
           svn_string_t *propval = svn__apr_hash_index_val(hi);
           svn_mergeinfo_t subtree_mergeinfo;
+          const char *repos_relpath;
+
+          if (strcmp(node_abspath, local_abspath) == 0)
+            continue; /* Already parsed in svn_client__get_wc_mergeinfo */
+
+          SVN_ERR(svn_wc__node_get_repos_relpath(&repos_relpath,
+                                                 ctx->wc_ctx, node_abspath,
+                                                 result_pool, scratch_pool));
 
-          SVN_ERR(svn_client__path_relative_to_root(&key_path, ctx->wc_ctx,
-                                                    key_path,
-                                                    NULL, FALSE,
-                                                    NULL, result_pool,
-                                                    scratch_pool));
           SVN_ERR(svn_mergeinfo_parse(&subtree_mergeinfo, propval->data,
                                       result_pool));
 
@@ -454,7 +450,7 @@ svn_client__get_wc_mergeinfo_catalog(svn
           if (*mergeinfo_cat == NULL)
             *mergeinfo_cat = apr_hash_make(result_pool);
 
-          apr_hash_set(*mergeinfo_cat, key_path,
+          apr_hash_set(*mergeinfo_cat, repos_relpath,
                        APR_HASH_KEY_STRING, subtree_mergeinfo);
         }
     }
@@ -506,7 +502,7 @@ svn_client__get_repos_mergeinfo_catalog(
                                         apr_pool_t *scratch_pool)
 {
   svn_error_t *err;
-  svn_mergeinfo_t repos_mergeinfo_cat;
+  svn_mergeinfo_catalog_t repos_mergeinfo_cat;
   apr_array_header_t *rel_paths = apr_array_make(scratch_pool, 1,
                                                  sizeof(const char *));
   const char *old_session_url;
@@ -1050,15 +1046,13 @@ get_mergeinfo(svn_mergeinfo_catalog_t *m
               apr_pool_t *scratch_pool)
 {
   svn_ra_session_t *ra_session;
-  svn_revnum_t rev;
   const char *local_abspath;
-  const char *url;
   svn_boolean_t use_url = svn_path_is_url(path_or_url);
-  svn_revnum_t peg_rev;
+  svn_client__pathrev_t *peg_loc;
 
-  SVN_ERR(svn_client__ra_session_from_path(&ra_session, &peg_rev, &url,
-                                           path_or_url, NULL, peg_revision,
-                                           peg_revision, ctx, scratch_pool));
+  SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &peg_loc,
+                                            path_or_url, NULL, peg_revision,
+                                            peg_revision, ctx, scratch_pool));
 
   /* If PATH_OR_URL is as working copy path determine if we will need to
      contact the repository for the requested PEG_REVISION. */
@@ -1070,10 +1064,9 @@ get_mergeinfo(svn_mergeinfo_catalog_t *m
 
       SVN_ERR(svn_client__wc_node_get_origin(&origin, local_abspath, ctx,
                                              scratch_pool, scratch_pool));
-      rev = origin ? origin->rev : SVN_INVALID_REVNUM;
       if (!origin
-          || strcmp(origin->url, url) != 0
-          || peg_rev != rev)
+          || strcmp(origin->url, peg_loc->url) != 0
+          || peg_loc->rev != origin->rev)
       {
         use_url = TRUE; /* Don't rely on local mergeinfo */
       }
@@ -1087,15 +1080,13 @@ get_mergeinfo(svn_mergeinfo_catalog_t *m
 
   if (use_url)
     {
-      rev = peg_rev;
       SVN_ERR(svn_client__get_repos_mergeinfo_catalog(
-        mergeinfo_catalog, ra_session, url, rev, svn_mergeinfo_inherited,
-        FALSE, include_descendants,
+        mergeinfo_catalog, ra_session, peg_loc->url, peg_loc->rev,
+        svn_mergeinfo_inherited, FALSE, include_descendants,
         result_pool, scratch_pool));
     }
   else /* ! svn_path_is_url() */
     {
-      /* Acquire return values. */
       SVN_ERR(svn_client__get_wc_or_repos_mergeinfo_catalog(
         mergeinfo_catalog, NULL, NULL, include_descendants, FALSE,
         ignore_invalid_mergeinfo, svn_mergeinfo_inherited,
@@ -1267,7 +1258,7 @@ struct filter_log_entry_baton_t
   /* A rangelist describing all the revisions potentially merged or
      potentially eligible for merging (see FILTERING_MERGED) based on
      the target's explicit or inherited mergeinfo. */
-  const apr_array_header_t *rangelist;
+  const svn_rangelist_t *rangelist;
 
   /* The wrapped svn_log_entry_receiver_t callback and baton which
      filter_log_entry_with_rangelist() is acting as a filter for. */
@@ -1299,7 +1290,7 @@ filter_log_entry_with_rangelist(void *ba
                                 apr_pool_t *pool)
 {
   struct filter_log_entry_baton_t *fleb = baton;
-  apr_array_header_t *intersection, *this_rangelist;
+  svn_rangelist_t *intersection, *this_rangelist;
 
   if (fleb->ctx->cancel_func)
     SVN_ERR(fleb->ctx->cancel_func(fleb->ctx->cancel_baton));
@@ -1340,7 +1331,7 @@ filter_log_entry_with_rangelist(void *ba
     {
       apr_hash_index_t *hi;
       svn_boolean_t all_subtrees_have_this_rev = TRUE;
-      apr_array_header_t *this_rev_rangelist =
+      svn_rangelist_t *this_rev_rangelist =
         svn_rangelist__initialize(log_entry->revision - 1,
                                   log_entry->revision, TRUE, pool);
       apr_pool_t *iterpool = svn_pool_create(pool);
@@ -1413,7 +1404,7 @@ filter_log_entry_with_rangelist(void *ba
           if (ancestor_is_self /* Explicit mergeinfo on TARGET_PATH_AFFECTED */
               && (change->action != 'M'))
             {
-              apr_array_header_t *rangelist = apr_hash_get(
+              svn_rangelist_t *rangelist = apr_hash_get(
                 nearest_ancestor_mergeinfo, path, APR_HASH_KEY_STRING);
               svn_merge_range_t *youngest_range = APR_ARRAY_IDX(
                 rangelist, rangelist->nelts - 1, svn_merge_range_t *);
@@ -1432,7 +1423,7 @@ filter_log_entry_with_rangelist(void *ba
                    hi2 = apr_hash_next(hi2))
                 {
                   const char *mergeinfo_path = svn__apr_hash_index_key(hi2);
-                  apr_array_header_t *rangelist = svn__apr_hash_index_val(hi2);
+                  svn_rangelist_t *rangelist = svn__apr_hash_index_val(hi2);
 
                   /* Does the mergeinfo for PATH reflect if
                      LOG_ENTRY->REVISION was previously merged
@@ -1506,8 +1497,8 @@ static svn_error_t *
 logs_for_mergeinfo_rangelist(const char *source_url,
                              const apr_array_header_t *merge_source_fspaths,
                              svn_boolean_t filtering_merged,
-                             const apr_array_header_t *rangelist,
-                             svn_mergeinfo_t target_mergeinfo_catalog,
+                             const svn_rangelist_t *rangelist,
+                             svn_mergeinfo_catalog_t target_mergeinfo_catalog,
                              const char *target_fspath,
                              svn_boolean_t discover_changed_paths,
                              const apr_array_header_t *revprops,
@@ -1599,17 +1590,23 @@ svn_client_mergeinfo_get_merged(apr_hash
                         peg_revision, FALSE, FALSE, ctx, pool, pool));
   if (mergeinfo_cat)
     {
-      const char *path_or_url_repos_rel;
+      const char *repos_relpath;
+
+      if (! svn_path_is_url(path_or_url))
+        {
+          SVN_ERR(svn_dirent_get_absolute(&path_or_url, path_or_url, pool));
+          SVN_ERR(svn_wc__node_get_repos_relpath(&repos_relpath,
+                                                 ctx->wc_ctx, path_or_url,
+                                                 pool, pool));
+        }
+      else
+        {
+          repos_relpath = svn_uri_skip_ancestor(repos_root, path_or_url, pool);
+
+          SVN_ERR_ASSERT(repos_relpath != NULL); /* Or get_mergeinfo failed */
+        }
 
-      if (! svn_path_is_url(path_or_url)
-          && ! svn_dirent_is_absolute(path_or_url))
-        SVN_ERR(svn_dirent_get_absolute(&path_or_url, path_or_url, pool));
-
-      SVN_ERR(svn_client__path_relative_to_root(&path_or_url_repos_rel,
-                                                ctx->wc_ctx, path_or_url,
-                                                repos_root, FALSE, NULL,
-                                                pool, pool));
-      mergeinfo = apr_hash_get(mergeinfo_cat, path_or_url_repos_rel,
+      mergeinfo = apr_hash_get(mergeinfo_cat, repos_relpath,
                                APR_HASH_KEY_STRING);
     }
   else
@@ -1624,33 +1621,35 @@ svn_client_mergeinfo_get_merged(apr_hash
 
 
 svn_error_t *
-svn_client_mergeinfo_log(svn_boolean_t finding_merged,
-                         const char *target_path_or_url,
-                         const svn_opt_revision_t *target_peg_revision,
-                         const char *source_path_or_url,
-                         const svn_opt_revision_t *source_peg_revision,
-                         svn_log_entry_receiver_t log_receiver,
-                         void *log_receiver_baton,
-                         svn_boolean_t discover_changed_paths,
-                         svn_depth_t depth,
-                         const apr_array_header_t *revprops,
-                         svn_client_ctx_t *ctx,
-                         apr_pool_t *scratch_pool)
+svn_client_mergeinfo_log2(svn_boolean_t finding_merged,
+                          const char *target_path_or_url,
+                          const svn_opt_revision_t *target_peg_revision,
+                          const char *source_path_or_url,
+                          const svn_opt_revision_t *source_peg_revision,
+                          const svn_opt_revision_t *source_start_revision,
+                          const svn_opt_revision_t *source_end_revision,
+                          svn_log_entry_receiver_t log_receiver,
+                          void *log_receiver_baton,
+                          svn_boolean_t discover_changed_paths,
+                          svn_depth_t depth,
+                          const apr_array_header_t *revprops,
+                          svn_client_ctx_t *ctx,
+                          apr_pool_t *scratch_pool)
 {
-  apr_pool_t *sesspool = svn_pool_create(scratch_pool);
   const char *log_target = NULL;
   const char *repos_root;
   const char *target_repos_rel;
   svn_mergeinfo_catalog_t target_mergeinfo_cat;
 
-  /* A hash of paths, at or under TARGET_PATH_OR_URL, mapped to rangelists.  Not
-     technically mergeinfo, so not using the svn_mergeinfo_t type. */
+  /* A hash of paths, at or under TARGET_PATH_OR_URL, mapped to
+     rangelists.  Not technically mergeinfo, so not using the
+     svn_mergeinfo_t type. */
   apr_hash_t *inheritable_subtree_merges;
 
   svn_mergeinfo_t source_history;
   svn_mergeinfo_t target_history;
-  apr_array_header_t *master_noninheritable_rangelist;
-  apr_array_header_t *master_inheritable_rangelist;
+  svn_rangelist_t *master_noninheritable_rangelist;
+  svn_rangelist_t *master_inheritable_rangelist;
   apr_array_header_t *merge_source_fspaths =
     apr_array_make(scratch_pool, 1, sizeof(const char *));
   apr_hash_index_t *hi_catalog;
@@ -1663,6 +1662,21 @@ svn_client_mergeinfo_log(svn_boolean_t f
       SVN_ERR_UNSUPPORTED_FEATURE, NULL,
       _("Only depths 'infinity' and 'empty' are currently supported"));
 
+  /* Validate and sanitize the incoming source operative revision range. */
+  if (!((source_start_revision->kind == svn_opt_revision_unspecified) ||
+        (source_start_revision->kind == svn_opt_revision_number) ||
+        (source_start_revision->kind == svn_opt_revision_date) ||
+        (source_start_revision->kind == svn_opt_revision_head)))
+    return svn_error_create(SVN_ERR_CLIENT_BAD_REVISION, NULL, NULL);
+  if (!((source_end_revision->kind == svn_opt_revision_unspecified) ||
+        (source_end_revision->kind == svn_opt_revision_number) ||
+        (source_end_revision->kind == svn_opt_revision_date) ||
+        (source_end_revision->kind == svn_opt_revision_head)))
+    return svn_error_create(SVN_ERR_CLIENT_BAD_REVISION, NULL, NULL);
+  if ((source_end_revision->kind == svn_opt_revision_unspecified)
+      && (source_start_revision->kind != svn_opt_revision_unspecified))
+    source_end_revision = source_start_revision;
+
   /* We need the union of TARGET_PATH_OR_URL@TARGET_PEG_REVISION's mergeinfo
      and MERGE_SOURCE_URL's history.  It's not enough to do path
      matching, because renames in the history of MERGE_SOURCE_URL
@@ -1676,15 +1690,22 @@ svn_client_mergeinfo_log(svn_boolean_t f
                         ctx, scratch_pool, scratch_pool));
 
   if (!svn_path_is_url(target_path_or_url))
-    SVN_ERR(svn_dirent_get_absolute(&target_path_or_url, target_path_or_url, scratch_pool));
+    {
+      SVN_ERR(svn_dirent_get_absolute(&target_path_or_url,
+                                      target_path_or_url, scratch_pool));
+      SVN_ERR(svn_wc__node_get_repos_relpath(&target_repos_rel,
+                                             ctx->wc_ctx, target_path_or_url,
+                                             scratch_pool, scratch_pool));
+    }
+  else
+    {
+      target_repos_rel = svn_uri_skip_ancestor(repos_root, target_path_or_url,
+                                               scratch_pool);
 
-  SVN_ERR(svn_client__path_relative_to_root(&target_repos_rel,
-                                            ctx->wc_ctx,
-                                            target_path_or_url,
-                                            repos_root,
-                                            FALSE /* leading_slash */, NULL,
-                                            scratch_pool,
-                                            scratch_pool));
+      /* TARGET_REPOS_REL should be non-NULL, else get_mergeinfo
+         should have failed.  */
+      SVN_ERR_ASSERT(target_repos_rel != NULL); 
+    }
 
   if (!target_mergeinfo_cat)
     {
@@ -1711,56 +1732,67 @@ svn_client_mergeinfo_log(svn_boolean_t f
   /* Open RA sessions to the repository for the source and target.
    * ### TODO: As the source and target must be in the same repository, we
    * should share a single session, tracking the two URLs separately. */
-  if (!finding_merged)
-    {
-      svn_ra_session_t *target_session;
-      svn_client__pathrev_t *pathrev;
-
-      SVN_ERR(svn_client__ra_session_from_path2(
-                &target_session, &pathrev,
-                target_path_or_url, NULL,
-                target_peg_revision, target_peg_revision,
-                ctx, sesspool));
-      SVN_ERR(svn_client__get_history_as_mergeinfo(
-                &target_history, NULL,
-                pathrev, SVN_INVALID_REVNUM, SVN_INVALID_REVNUM,
-                target_session, ctx, scratch_pool));
-    }
   {
-    svn_ra_session_t *source_session;
+    apr_pool_t *sesspool = svn_pool_create(scratch_pool);
+    svn_ra_session_t *source_session, *target_session;
     svn_client__pathrev_t *pathrev;
+    svn_revnum_t start_rev, end_rev, youngest_rev = SVN_INVALID_REVNUM;
+    
+    if (! finding_merged)
+      {
+        SVN_ERR(svn_client__ra_session_from_path2(&target_session, &pathrev,
+                                                  target_path_or_url, NULL,
+                                                  target_peg_revision,
+                                                  target_peg_revision,
+                                                  ctx, sesspool));
+        SVN_ERR(svn_client__get_history_as_mergeinfo(&target_history, NULL,
+                                                     pathrev,
+                                                     SVN_INVALID_REVNUM,
+                                                     SVN_INVALID_REVNUM,
+                                                     target_session, ctx,
+                                                     scratch_pool));
+      }
+    
+    SVN_ERR(svn_client__ra_session_from_path2(&source_session, &pathrev,
+                                              source_path_or_url, NULL,
+                                              source_peg_revision,
+                                              source_peg_revision,
+                                              ctx, sesspool));
+    SVN_ERR(svn_client__get_revision_number(&start_rev, &youngest_rev,
+                                            ctx->wc_ctx, source_path_or_url,
+                                            source_session,
+                                            source_start_revision,
+                                            sesspool));
+    SVN_ERR(svn_client__get_revision_number(&end_rev, &youngest_rev,
+                                            ctx->wc_ctx, source_path_or_url,
+                                            source_session,
+                                            source_end_revision,
+                                            sesspool));
+    SVN_ERR(svn_client__get_history_as_mergeinfo(&source_history, NULL,
+                                                 pathrev, end_rev, start_rev,
+                                                 source_session, ctx,
+                                                 scratch_pool));
 
-    SVN_ERR(svn_client__ra_session_from_path2(
-              &source_session, &pathrev,
-              source_path_or_url, NULL,
-              source_peg_revision, source_peg_revision,
-              ctx, sesspool));
-    SVN_ERR(svn_client__get_history_as_mergeinfo(
-              &source_history, NULL,
-              pathrev, SVN_INVALID_REVNUM, SVN_INVALID_REVNUM,
-              source_session, ctx, scratch_pool));
+    /* Close the source and target sessions. */
+    svn_pool_destroy(sesspool);
   }
-  /* Close the source and target sessions. */
-  svn_pool_destroy(sesspool);
 
-  /* Separate the explicit or inherited mergeinfo on TARGET_PATH_OR_URL, and possibly
-     its explicit subtree mergeinfo, into their inheritable and non-inheritable
-     parts. */
-  master_noninheritable_rangelist =
-    apr_array_make(scratch_pool, 64, sizeof(svn_merge_range_t *));
+  /* Separate the explicit or inherited mergeinfo on TARGET_PATH_OR_URL,
+     and possibly its explicit subtree mergeinfo, into their
+     inheritable and non-inheritable parts. */
+  master_noninheritable_rangelist = apr_array_make(scratch_pool, 64,
+                                                   sizeof(svn_merge_range_t *));
   master_inheritable_rangelist = apr_array_make(scratch_pool, 64,
                                                 sizeof(svn_merge_range_t *));
   inheritable_subtree_merges = apr_hash_make(scratch_pool);
 
   iterpool = svn_pool_create(scratch_pool);
 
-  for (hi_catalog = apr_hash_first(scratch_pool,
-                                   target_mergeinfo_cat);
+  for (hi_catalog = apr_hash_first(scratch_pool, target_mergeinfo_cat);
        hi_catalog;
        hi_catalog = apr_hash_next(hi_catalog))
     {
-      svn_mergeinfo_t subtree_mergeinfo =
-        svn__apr_hash_index_val(hi_catalog);
+      svn_mergeinfo_t subtree_mergeinfo = svn__apr_hash_index_val(hi_catalog);
       svn_mergeinfo_t subtree_history;
       svn_mergeinfo_t subtree_source_history;
       svn_mergeinfo_t subtree_inheritable_mergeinfo;
@@ -1774,9 +1806,9 @@ svn_client_mergeinfo_log(svn_boolean_t f
 
       if (is_subtree)
         {
-          /* If SUBTREE_PATH is a proper subtree of TARGET_PATH_OR_URL then make
-             a copy of SOURCE_HISTORY that is path adjusted for the
-             subtree.  */
+          /* If SUBTREE_PATH is a proper subtree of TARGET_PATH_OR_URL
+             then make a copy of SOURCE_HISTORY that is path adjusted
+             for the subtree.  */
           const char *subtree_rel_path =
             subtree_path + strlen(target_repos_rel) + 1;
 
@@ -1852,7 +1884,7 @@ svn_client_mergeinfo_log(svn_boolean_t f
         {
           /* The inheritable rangelist merged from SUBTREE_SOURCE_HISTORY
              to SUBTREE_PATH. */
-          apr_array_header_t *subtree_merged_rangelist =
+          svn_rangelist_t *subtree_merged_rangelist =
             apr_array_make(scratch_pool, 1, sizeof(svn_merge_range_t *));
 
           SVN_ERR(svn_rangelist__merge_many(master_inheritable_rangelist,
@@ -1889,9 +1921,9 @@ svn_client_mergeinfo_log(svn_boolean_t f
            hi;
            hi = apr_hash_next(hi))
         {
-          apr_array_header_t *deleted_rangelist;
-          apr_array_header_t *added_rangelist;
-          apr_array_header_t *subtree_merged_rangelist =
+          svn_rangelist_t *deleted_rangelist;
+          svn_rangelist_t *added_rangelist;
+          svn_rangelist_t *subtree_merged_rangelist =
             svn__apr_hash_index_val(hi);
 
           svn_pool_clear(iterpool);
@@ -1927,15 +1959,15 @@ svn_client_mergeinfo_log(svn_boolean_t f
   else
     {
       /* Create the starting rangelist for what might be eligible. */
-      apr_array_header_t *source_master_rangelist =
+      svn_rangelist_t *source_master_rangelist =
         apr_array_make(scratch_pool, 1, sizeof(svn_merge_range_t *));
 
       SVN_ERR(svn_rangelist__merge_many(source_master_rangelist,
                                         source_history,
                                         scratch_pool, scratch_pool));
 
-      /* From what might be eligible subtract what we know is partially merged
-         and then merge that back. */
+      /* From what might be eligible subtract what we know is
+         partially merged and then merge that back. */
       SVN_ERR(svn_rangelist_remove(&source_master_rangelist,
                                    master_noninheritable_rangelist,
                                    source_master_rangelist,
@@ -1964,7 +1996,7 @@ svn_client_mergeinfo_log(svn_boolean_t f
         = APR_ARRAY_IDX(master_inheritable_rangelist,
                         master_inheritable_rangelist->nelts - 1,
                         svn_merge_range_t *);
-      apr_array_header_t *youngest_rangelist =
+      svn_rangelist_t *youngest_rangelist =
         svn_rangelist__initialize(youngest_range->end - 1,
                                   youngest_range->end,
                                   youngest_range->inheritable,
@@ -1975,9 +2007,9 @@ svn_client_mergeinfo_log(svn_boolean_t f
            hi = apr_hash_next(hi))
         {
           const char *key = svn__apr_hash_index_key(hi);
-          apr_array_header_t *subtree_merged_rangelist =
+          svn_rangelist_t *subtree_merged_rangelist =
             svn__apr_hash_index_val(hi);
-          apr_array_header_t *intersecting_rangelist;
+          svn_rangelist_t *intersecting_rangelist;
 
           svn_pool_clear(iterpool);
           SVN_ERR(svn_rangelist_intersect(&intersecting_rangelist,
@@ -2062,9 +2094,9 @@ svn_client_suggest_merge_sources(apr_arr
       mergeinfo = NULL;
     }
 
-  SVN_ERR(svn_client__get_copy_source(path_or_url, peg_revision,
-                                      &copyfrom_path, &copyfrom_rev,
-                                      ctx, pool));
+  SVN_ERR(svn_client__get_copy_source(&copyfrom_path, &copyfrom_rev,
+                                      path_or_url, peg_revision, ctx,
+                                      pool, pool));
   if (copyfrom_path)
     {
       APR_ARRAY_PUSH(list, const char *) =

Modified: subversion/branches/compressed-pristines/subversion/libsvn_client/mergeinfo.h
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_client/mergeinfo.h?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_client/mergeinfo.h (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_client/mergeinfo.h Thu Aug 16 10:17:48 2012
@@ -65,7 +65,7 @@ typedef struct svn_client__merge_path_t
      with the youngest start revisions come first.  In both the forward and
      reverse merge cases the ranges should never overlap.  This rangelist
      may be empty but should never be NULL unless ABSENT is true. */
-  apr_array_header_t *remaining_ranges;
+  svn_rangelist_t *remaining_ranges;
 
   svn_mergeinfo_t pre_merge_mergeinfo;  /* Explicit or inherited mergeinfo
                                            on ABSPATH prior to a merge.
@@ -300,7 +300,7 @@ svn_client__get_wc_or_repos_mergeinfo_ca
    If HAS_REV_ZERO_HISTORY is not NULL, then set *HAS_REV_ZERO_HISTORY to
    TRUE if the natural history includes revision 0, else to FALSE.
 
-   RA_SESSION is an open RA session to the repository in which URL lives;
+   RA_SESSION is an open RA session to the repository of PATHREV;
    it may be temporarily reparented by this function.
 */
 svn_error_t *

Modified: subversion/branches/compressed-pristines/subversion/libsvn_client/patch.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_client/patch.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_client/patch.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_client/patch.c Thu Aug 16 10:17:48 2012
@@ -47,6 +47,7 @@
 #include "private/svn_wc_private.h"
 #include "private/svn_dep_compat.h"
 #include "private/svn_string_private.h"
+#include "private/svn_subr_private.h"
 
 typedef struct hunk_info_t {
   /* The hunk. */
@@ -1019,6 +1020,7 @@ readline(target_content_t *content,
 {
   svn_stringbuf_t *line_raw;
   const char *eol_str;
+  svn_linenum_t max_line = (svn_linenum_t)content->lines->nelts + 1;
 
   if (content->eof || content->readline == NULL)
     {
@@ -1026,8 +1028,8 @@ readline(target_content_t *content,
       return SVN_NO_ERROR;
     }
 
-  SVN_ERR_ASSERT(content->current_line <= content->lines->nelts + 1);
-  if (content->current_line == content->lines->nelts + 1)
+  SVN_ERR_ASSERT(content->current_line <= max_line);
+  if (content->current_line == max_line)
     {
       apr_off_t offset;
 
@@ -1072,7 +1074,7 @@ seek_to_line(target_content_t *content, 
   saved_line = content->current_line;
   saved_eof = content->eof;
 
-  if (line <= content->lines->nelts)
+  if (line <= (svn_linenum_t)content->lines->nelts)
     {
       apr_off_t offset;
 

Modified: subversion/branches/compressed-pristines/subversion/libsvn_client/prop_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_client/prop_commands.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_client/prop_commands.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_client/prop_commands.c Thu Aug 16 10:17:48 2012
@@ -743,7 +743,7 @@ recursive_propget_receiver(void *baton,
    Treat DEPTH as in svn_client_propget3().
 */
 static svn_error_t *
-get_prop_from_wc(apr_hash_t *props,
+get_prop_from_wc(apr_hash_t **props,
                  const char *propname,
                  const char *target_abspath,
                  svn_boolean_t pristine,
@@ -764,12 +764,24 @@ get_prop_from_wc(apr_hash_t *props,
   if (depth == svn_depth_unknown)
     depth = svn_depth_infinity;
 
-  rb.props = props;
+  if (!pristine && depth == svn_depth_infinity
+      && (!changelists || changelists->nelts == 0))
+    {
+      /* Handle this common svn:mergeinfo case more efficient than the target
+         list handling in the recursive retrieval. */
+      SVN_ERR(svn_wc__prop_retrieve_recursive(
+                            props, ctx->wc_ctx, target_abspath, propname,
+                            result_pool, scratch_pool));
+      return SVN_NO_ERROR;
+    }
+
+  *props = apr_hash_make(result_pool);
+  rb.props = *props;
   rb.pool = result_pool;
   rb.wc_ctx = ctx->wc_ctx;
 
   SVN_ERR(svn_wc__prop_list_recursive(ctx->wc_ctx, target_abspath,
-                                      propname, depth, FALSE, pristine,
+                                      propname, depth, pristine,
                                       changelists,
                                       recursive_propget_receiver, &rb,
                                       ctx->cancel_func, ctx->cancel_baton,
@@ -802,8 +814,6 @@ svn_client_propget4(apr_hash_t **props,
                                                         target);
   revision = svn_cl__rev_default_to_peg(revision, peg_revision);
 
-  *props = apr_hash_make(result_pool);
-
   if (! svn_path_is_url(target)
       && SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(peg_revision->kind)
       && SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(revision->kind))
@@ -840,28 +850,30 @@ svn_client_propget4(apr_hash_t **props,
       else if (err)
         return svn_error_trace(err);
 
-      SVN_ERR(get_prop_from_wc(*props, propname, target,
+      SVN_ERR(get_prop_from_wc(props, propname, target,
                                pristine, kind,
                                depth, changelists, ctx, scratch_pool,
                                result_pool));
     }
   else
     {
-      const char *url;
+      svn_client__pathrev_t *loc;
       svn_ra_session_t *ra_session;
       svn_node_kind_t kind;
 
       /* Get an RA plugin for this filesystem object. */
-      SVN_ERR(svn_client__ra_session_from_path(&ra_session, &revnum,
-                                               &url, target, NULL,
-                                               peg_revision,
-                                               revision, ctx, scratch_pool));
-
-      SVN_ERR(svn_ra_check_path(ra_session, "", revnum, &kind, scratch_pool));
-
-      SVN_ERR(remote_propget(*props, propname, url, "",
-                             kind, revnum, ra_session,
+      SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &loc,
+                                                target, NULL,
+                                                peg_revision,
+                                                revision, ctx, scratch_pool));
+
+      SVN_ERR(svn_ra_check_path(ra_session, "", loc->rev, &kind, scratch_pool));
+
+      *props = apr_hash_make(result_pool);
+      SVN_ERR(remote_propget(*props, propname, loc->url, "",
+                             kind, loc->rev, ra_session,
                              depth, result_pool, scratch_pool));
+      revnum = loc->rev;
     }
 
   if (actual_revnum)
@@ -1088,8 +1100,6 @@ svn_client_proplist3(const char *path_or
                      svn_client_ctx_t *ctx,
                      apr_pool_t *pool)
 {
-  const char *url;
-
   peg_revision = svn_cl__rev_default_to_head_or_working(peg_revision,
                                                         path_or_url);
   revision = svn_cl__rev_default_to_peg(revision, peg_revision);
@@ -1149,8 +1159,7 @@ svn_client_proplist3(const char *path_or
             }
 
           SVN_ERR(svn_wc__prop_list_recursive(ctx->wc_ctx, local_abspath, NULL,
-                                              depth,
-                                              FALSE, pristine, changelists,
+                                              depth, pristine, changelists,
                                               recursive_proplist_receiver, &rb,
                                               ctx->cancel_func,
                                               ctx->cancel_baton, pool));
@@ -1172,17 +1181,17 @@ svn_client_proplist3(const char *path_or
       svn_ra_session_t *ra_session;
       svn_node_kind_t kind;
       apr_pool_t *subpool = svn_pool_create(pool);
-      svn_revnum_t revnum;
+      svn_client__pathrev_t *loc;
 
       /* Get an RA session for this URL. */
-      SVN_ERR(svn_client__ra_session_from_path(&ra_session, &revnum,
-                                               &url, path_or_url, NULL,
-                                               peg_revision,
-                                               revision, ctx, pool));
+      SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &loc,
+                                                path_or_url, NULL,
+                                                peg_revision,
+                                                revision, ctx, pool));
 
-      SVN_ERR(svn_ra_check_path(ra_session, "", revnum, &kind, pool));
+      SVN_ERR(svn_ra_check_path(ra_session, "", loc->rev, &kind, pool));
 
-      SVN_ERR(remote_proplist(url, "", kind, revnum, ra_session, depth,
+      SVN_ERR(remote_proplist(loc->url, "", kind, loc->rev, ra_session, depth,
                               receiver, receiver_baton, pool, subpool));
       svn_pool_destroy(subpool);
     }

Modified: subversion/branches/compressed-pristines/subversion/libsvn_client/ra.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_client/ra.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_client/ra.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_client/ra.c Thu Aug 16 10:17:48 2012
@@ -52,6 +52,13 @@ typedef struct callback_baton_t
      this base directory. */
   const char *base_dir_abspath;
 
+  /* TEMPORARY: Is 'base_dir_abspath' a versioned path?  cmpilato
+     suspects that the commit-to-multiple-disjoint-working-copies
+     code is getting this all wrong, sometimes passing an unversioned
+     (or versioned in a foreign wc) path here which sorta kinda
+     happens to work most of the time but is ultimately incorrect.  */
+  svn_boolean_t base_dir_isversioned;
+
   /* An array of svn_client_commit_item3_t * structures, present only
      during working copy commits. */
   const apr_array_header_t *commit_items;
@@ -234,6 +241,30 @@ invalidate_wc_props(void *baton,
 }
 
 
+/* This implements the `svn_ra_get_wc_contents_func_t' interface. */
+static svn_error_t *
+get_wc_contents(void *baton,
+                svn_stream_t **contents,
+                const svn_checksum_t *checksum,
+                apr_pool_t *pool)
+{
+  callback_baton_t *cb = baton;
+
+  if (! (cb->base_dir_abspath && cb->base_dir_isversioned))
+    {
+      *contents = NULL;
+      return SVN_NO_ERROR;
+    }
+
+  return svn_error_trace(
+             svn_wc__get_pristine_contents_by_checksum(contents,
+                                                       cb->ctx->wc_ctx,
+                                                       cb->base_dir_abspath,
+                                                       checksum,
+                                                       pool, pool));
+}
+
+
 static svn_error_t *
 cancel_callback(void *baton)
 {
@@ -266,7 +297,7 @@ svn_client__open_ra_session_internal(svn
                                      svn_client_ctx_t *ctx,
                                      apr_pool_t *pool)
 {
-  svn_ra_callbacks2_t *cbtable = apr_pcalloc(pool, sizeof(*cbtable));
+  svn_ra_callbacks2_t *cbtable;
   callback_baton_t *cb = apr_pcalloc(pool, sizeof(*cb));
   const char *uuid = NULL;
 
@@ -274,6 +305,7 @@ svn_client__open_ra_session_internal(svn
   SVN_ERR_ASSERT(base_dir_abspath == NULL
                         || svn_dirent_is_absolute(base_dir_abspath));
 
+  SVN_ERR(svn_ra_create_callbacks(&cbtable, pool));
   cbtable->open_tmp_file = open_tmp_file;
   cbtable->get_wc_prop = use_admin ? get_wc_prop : NULL;
   cbtable->set_wc_prop = read_only_wc ? NULL : set_wc_prop;
@@ -284,6 +316,7 @@ svn_client__open_ra_session_internal(svn
   cbtable->progress_baton = ctx->progress_baton;
   cbtable->cancel_func = ctx->cancel_func ? cancel_callback : NULL;
   cbtable->get_client_string = get_client_string;
+  cbtable->get_wc_contents = get_wc_contents;
 
   cb->base_dir_abspath = base_dir_abspath;
   cb->commit_items = commit_items;
@@ -303,7 +336,10 @@ svn_client__open_ra_session_internal(svn
           uuid = NULL;
         }
       else
-        SVN_ERR(err);
+        {
+          SVN_ERR(err);
+          cb->base_dir_isversioned = TRUE;
+        }
     }
 
   /* If the caller allows for auto-following redirections, and the
@@ -457,7 +493,8 @@ svn_client__ra_session_from_path2(svn_ra
                                                initial_url,
                                                base_dir_abspath, NULL,
                                                base_dir_abspath != NULL,
-                                               FALSE, ctx, pool));
+                                               base_dir_abspath == NULL,
+                                               ctx, pool));
 
   /* If we got a CORRECTED_URL, we'll want to refer to that as the
      URL-ized form of PATH_OR_URL from now on. */
@@ -478,31 +515,6 @@ svn_client__ra_session_from_path2(svn_ra
   return SVN_NO_ERROR;
 }
 
-svn_error_t *
-svn_client__ra_session_from_path(svn_ra_session_t **ra_session_p,
-                                 svn_revnum_t *rev_p,
-                                 const char **url_p,
-                                 const char *path_or_url,
-                                 const char *base_dir_abspath,
-                                 const svn_opt_revision_t *peg_revision,
-                                 const svn_opt_revision_t *revision,
-                                 svn_client_ctx_t *ctx,
-                                 apr_pool_t *pool)
-{
-  svn_client__pathrev_t *resolved_loc;
-
-  SVN_ERR(svn_client__ra_session_from_path2(ra_session_p, &resolved_loc,
-                                            path_or_url, base_dir_abspath,
-                                            peg_revision, revision,
-                                            ctx, pool));
-  if (rev_p)
-    *rev_p = resolved_loc->rev;
-  if (url_p)
-    *url_p = resolved_loc->url;
-
-  return SVN_NO_ERROR;
-}
-
 
 svn_error_t *
 svn_client__ensure_ra_session_url(const char **old_session_url,
@@ -569,6 +581,7 @@ svn_client__repos_location_segments(apr_
 {
   struct gls_receiver_baton_t gls_receiver_baton;
   const char *old_session_url;
+  svn_error_t *err;
 
   *segments = apr_array_make(pool, 8, sizeof(svn_location_segment_t *));
   gls_receiver_baton.segments = *segments;
@@ -576,11 +589,12 @@ svn_client__repos_location_segments(apr_
   gls_receiver_baton.pool = pool;
   SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url, ra_session,
                                             url, pool));
-  SVN_ERR(svn_ra_get_location_segments(ra_session, "", peg_revision,
-                                       start_revision, end_revision,
-                                       gls_receiver, &gls_receiver_baton,
-                                       pool));
-  SVN_ERR(svn_ra_reparent(ra_session, old_session_url, pool));
+  err = svn_ra_get_location_segments(ra_session, "", peg_revision,
+                                     start_revision, end_revision,
+                                     gls_receiver, &gls_receiver_baton,
+                                     pool);
+  SVN_ERR(svn_error_compose_create(
+            err, svn_ra_reparent(ra_session, old_session_url, pool)));
   qsort((*segments)->elts, (*segments)->nelts,
         (*segments)->elt_size, compare_segments);
   return SVN_NO_ERROR;
@@ -677,14 +691,16 @@ svn_client__repos_location(svn_client__p
 {
   const char *old_session_url;
   const char *op_url;
+  svn_error_t *err;
 
   SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url, ra_session,
                                             peg_loc->url, scratch_pool));
-  SVN_ERR(repos_locations(&op_url, NULL, ra_session,
-                          peg_loc->url, peg_loc->rev,
-                          op_revnum, SVN_INVALID_REVNUM,
-                          result_pool, scratch_pool));
-  SVN_ERR(svn_ra_reparent(ra_session, old_session_url, scratch_pool));
+  err = repos_locations(&op_url, NULL, ra_session,
+                        peg_loc->url, peg_loc->rev,
+                        op_revnum, SVN_INVALID_REVNUM,
+                        result_pool, scratch_pool);
+  SVN_ERR(svn_error_compose_create(
+            err, svn_ra_reparent(ra_session, old_session_url, scratch_pool)));
 
   *op_loc_p = svn_client__pathrev_create(peg_loc->repos_root_url,
                                          peg_loc->repos_uuid,
@@ -833,12 +849,12 @@ svn_error_t *
 svn_client__get_youngest_common_ancestor(svn_client__pathrev_t **ancestor_p,
                                          const svn_client__pathrev_t *loc1,
                                          const svn_client__pathrev_t *loc2,
+                                         svn_ra_session_t *session,
                                          svn_client_ctx_t *ctx,
                                          apr_pool_t *result_pool,
                                          apr_pool_t *scratch_pool)
 {
-  apr_pool_t *sesspool = svn_pool_create(scratch_pool);
-  svn_ra_session_t *session;
+  apr_pool_t *sesspool = NULL;
   apr_hash_t *history1, *history2;
   apr_hash_index_t *hi;
   svn_revnum_t yc_revision = SVN_INVALID_REVNUM;
@@ -853,7 +869,11 @@ svn_client__get_youngest_common_ancestor
     }
 
   /* Open an RA session for the two locations. */
-  SVN_ERR(svn_client_open_ra_session(&session, loc1->url, ctx, sesspool));
+  if (session == NULL)
+    {
+      sesspool = svn_pool_create(scratch_pool);
+      SVN_ERR(svn_client_open_ra_session(&session, loc1->url, ctx, sesspool));
+    }
 
   /* We're going to cheat and use history-as-mergeinfo because it
      saves us a bunch of annoying custom data comparisons and such. */
@@ -869,8 +889,9 @@ svn_client__get_youngest_common_ancestor
                                                SVN_INVALID_REVNUM,
                                                SVN_INVALID_REVNUM,
                                                session, ctx, scratch_pool));
-  /* Close the source and target sessions. */
-  svn_pool_destroy(sesspool);
+  /* Close the ra session if we opened one. */
+  if (sesspool)
+    svn_pool_destroy(sesspool);
 
   /* Loop through the first location's history, check for overlapping
      paths and ranges in the second location's history, and
@@ -879,8 +900,8 @@ svn_client__get_youngest_common_ancestor
     {
       const char *path = svn__apr_hash_index_key(hi);
       apr_ssize_t path_len = svn__apr_hash_index_klen(hi);
-      apr_array_header_t *ranges1 = svn__apr_hash_index_val(hi);
-      apr_array_header_t *ranges2, *common;
+      svn_rangelist_t *ranges1 = svn__apr_hash_index_val(hi);
+      svn_rangelist_t *ranges2, *common;
 
       ranges2 = apr_hash_get(history2, path, path_len);
       if (ranges2)
@@ -949,7 +970,7 @@ svn_client__youngest_common_ancestor(con
                               ctx, scratch_pool));
 
   SVN_ERR(svn_client__get_youngest_common_ancestor(
-            &ancestor, loc1, loc2, ctx, result_pool, scratch_pool));
+            &ancestor, loc1, loc2, session, ctx, result_pool, scratch_pool));
 
   if (ancestor)
     {
@@ -964,3 +985,149 @@ svn_client__youngest_common_ancestor(con
   svn_pool_destroy(sesspool);
   return SVN_NO_ERROR;
 }
+
+
+struct ra_ev2_baton {
+  /* The working copy context, from the client context.  */
+  svn_wc_context_t *wc_ctx;
+
+  /* For a given REPOS_RELPATH, provide a LOCAL_ABSPATH that represents
+     that repository node.  */
+  apr_hash_t *relpath_map;
+};
+
+
+svn_error_t *
+svn_client__ra_provide_base(svn_stream_t **contents,
+                            svn_revnum_t *revision,
+                            void *baton,
+                            const char *repos_relpath,
+                            apr_pool_t *result_pool,
+                            apr_pool_t *scratch_pool)
+{
+  struct ra_ev2_baton *reb = baton;
+  const char *local_abspath;
+  svn_error_t *err;
+
+  local_abspath = apr_hash_get(reb->relpath_map, repos_relpath,
+                               APR_HASH_KEY_STRING);
+  if (!local_abspath)
+    {
+      *contents = NULL;
+      return SVN_NO_ERROR;
+    }
+
+  err = svn_wc_get_pristine_contents2(contents, reb->wc_ctx, local_abspath,
+                                      result_pool, scratch_pool);
+  if (err)
+    {
+      if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
+        return svn_error_trace(err);
+
+      svn_error_clear(err);
+      *contents = NULL;
+      return SVN_NO_ERROR;
+    }
+
+  if (*contents != NULL)
+    {
+      /* The pristine contents refer to the BASE, or to the pristine of
+         a copy/move to this location. Fetch the correct revision.  */
+      SVN_ERR(svn_wc__node_get_commit_base(revision, NULL, NULL, NULL,
+                                           reb->wc_ctx, local_abspath,
+                                           scratch_pool, scratch_pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_client__ra_provide_props(apr_hash_t **props,
+                             svn_revnum_t *revision,
+                             void *baton,
+                             const char *repos_relpath,
+                             apr_pool_t *result_pool,
+                             apr_pool_t *scratch_pool)
+{
+  struct ra_ev2_baton *reb = baton;
+  const char *local_abspath;
+  svn_error_t *err;
+
+  local_abspath = apr_hash_get(reb->relpath_map, repos_relpath,
+                               APR_HASH_KEY_STRING);
+  if (!local_abspath)
+    {
+      *props = NULL;
+      return SVN_NO_ERROR;
+    }
+
+  err = svn_wc_get_pristine_props(props, reb->wc_ctx, local_abspath,
+                                  result_pool, scratch_pool);
+  if (err)
+    {
+      if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
+        return svn_error_trace(err);
+
+      svn_error_clear(err);
+      *props = NULL;
+      return SVN_NO_ERROR;
+    }
+
+  if (*props != NULL)
+    {
+      /* The pristine props refer to the BASE, or to the pristine props of
+         a copy/move to this location. Fetch the correct revision.  */
+      SVN_ERR(svn_wc__node_get_commit_base(revision, NULL, NULL, NULL,
+                                           reb->wc_ctx, local_abspath,
+                                           scratch_pool, scratch_pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_client__ra_get_copysrc_kind(svn_kind_t *kind,
+                                void *baton,
+                                const char *repos_relpath,
+                                svn_revnum_t src_revision,
+                                apr_pool_t *scratch_pool)
+{
+  struct ra_ev2_baton *reb = baton;
+  svn_node_kind_t node_kind;
+  const char *local_abspath;
+
+  local_abspath = apr_hash_get(reb->relpath_map, repos_relpath,
+                               APR_HASH_KEY_STRING);
+  if (!local_abspath)
+    {
+      *kind = svn_kind_unknown;
+      return SVN_NO_ERROR;
+    }
+
+  /* ### what to do with SRC_REVISION?  */
+
+  SVN_ERR(svn_wc_read_kind(&node_kind, reb->wc_ctx, local_abspath, FALSE,
+                           scratch_pool));
+  *kind = svn__kind_from_node_kind(node_kind, FALSE);
+
+  return SVN_NO_ERROR;
+}
+
+
+void *
+svn_client__ra_make_cb_baton(svn_wc_context_t *wc_ctx,
+                             apr_hash_t *relpath_map,
+                             apr_pool_t *result_pool)
+{
+  struct ra_ev2_baton *reb = apr_palloc(result_pool, sizeof(*reb));
+
+  SVN_ERR_ASSERT_NO_RETURN(wc_ctx != NULL);
+  SVN_ERR_ASSERT_NO_RETURN(relpath_map != NULL);
+
+  reb->wc_ctx = wc_ctx;
+  reb->relpath_map = relpath_map;
+
+  return reb;
+}

Modified: subversion/branches/compressed-pristines/subversion/libsvn_client/relocate.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_client/relocate.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_client/relocate.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_client/relocate.c Thu Aug 16 10:17:48 2012
@@ -139,7 +139,6 @@ relocate_externals(const char *local_abs
                    apr_array_header_t *ext_desc,
                    const char *old_parent_repos_root_url,
                    const char *new_parent_repos_root_url,
-                   svn_boolean_t ignore_externals,
                    svn_client_ctx_t *ctx,
                    apr_pool_t *scratch_pool)
 {
@@ -199,7 +198,7 @@ relocate_externals(const char *local_abs
         SVN_ERR(svn_client_relocate2(target_abspath,
                                      old_parent_repos_root_url,
                                      new_parent_repos_root_url,
-                                     ignore_externals, ctx, iterpool));
+                                     FALSE, ctx, iterpool));
     }
 
   svn_pool_destroy(iterpool);
@@ -281,8 +280,7 @@ svn_client_relocate2(const char *wcroot_
                                                   iterpool));
       if (ext_desc->nelts)
         SVN_ERR(relocate_externals(this_abspath, ext_desc, old_repos_root_url,
-                                   new_repos_root_url, ignore_externals, ctx,
-                                   iterpool));
+                                   new_repos_root_url, ctx, iterpool));
     }
 
   svn_pool_destroy(iterpool);

Modified: subversion/branches/compressed-pristines/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_client/repos_diff.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_client/repos_diff.c Thu Aug 16 10:17:48 2012
@@ -47,6 +47,7 @@
 
 #include "client.h"
 
+#include "private/svn_subr_private.h"
 #include "private/svn_wc_private.h"
 
 /* Overall crawler editor baton.  */
@@ -142,12 +143,12 @@ struct dir_baton {
   /* A cache of any property changes (svn_prop_t) received for this dir. */
   apr_array_header_t *propchanges;
 
-  /* The pristine-property list attached to this directory. */
-  apr_hash_t *pristine_props;
-
   /* The pool passed in by add_dir, open_dir, or open_root.
      Also, the pool this dir baton is allocated in. */
   apr_pool_t *pool;
+
+  /* Base revision of directory. */
+  svn_revnum_t base_revision;
 };
 
 /* File level baton.
@@ -215,6 +216,7 @@ make_dir_baton(const char *path,
                struct dir_baton *parent_baton,
                struct edit_baton *edit_baton,
                svn_boolean_t added,
+               svn_revnum_t base_revision,
                apr_pool_t *pool)
 {
   apr_pool_t *dir_pool = svn_pool_create(pool);
@@ -229,6 +231,7 @@ make_dir_baton(const char *path,
   dir_baton->pool = dir_pool;
   dir_baton->path = apr_pstrdup(dir_pool, path);
   dir_baton->propchanges  = apr_array_make(pool, 1, sizeof(svn_prop_t));
+  dir_baton->base_revision = base_revision;
 
   return dir_baton;
 }
@@ -359,14 +362,13 @@ get_file_from_ra(struct file_baton *b,
    corresponding property in PRISTINE_PROPS.
 
      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
+     spurious conflicts'.  When communicating with the repository via ra_serf,
+     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
      on FILE_BATON->PATH when using the DAV providers, not just the change(s).
-     (Specifically ra_neon does this for diff/merge and ra_serf does it
-     for diff/merge/update/switch).
+     (Specifically ra_serf does it for diff/merge/update/switch).
 
      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
@@ -459,10 +461,8 @@ open_root(void *edit_baton,
           void **root_baton)
 {
   struct edit_baton *eb = edit_baton;
-  struct dir_baton *b = make_dir_baton("", NULL, eb, FALSE, pool);
-
-  SVN_ERR(svn_ra_get_dir2(eb->ra_session, NULL, NULL, &b->pristine_props,
-                          b->path, base_revision, 0, pool));
+  struct dir_baton *b = make_dir_baton("", NULL, eb, FALSE, base_revision,
+                                       pool);
 
   *root_baton = b;
   return SVN_NO_ERROR;
@@ -659,8 +659,7 @@ add_directory(const char *path,
 
   /* ### TODO: support copyfrom? */
 
-  b = make_dir_baton(path, pb, eb, TRUE, pool);
-  b->pristine_props = eb->empty_hash;
+  b = make_dir_baton(path, pb, eb, TRUE, SVN_INVALID_REVNUM, pool);
   *child_baton = b;
 
   /* Skip *everything* within a newly tree-conflicted directory,
@@ -745,7 +744,8 @@ open_directory(const char *path,
   struct edit_baton *eb = pb->edit_baton;
   struct dir_baton *b;
 
-  b = make_dir_baton(path, pb, pb->edit_baton, FALSE, pool);
+  b = make_dir_baton(path, pb, pb->edit_baton, FALSE, base_revision, pool);
+
   *child_baton = b;
 
   /* Skip *everything* within a newly tree-conflicted directory
@@ -756,9 +756,6 @@ open_directory(const char *path,
       return SVN_NO_ERROR;
     }
 
-  SVN_ERR(svn_ra_get_dir2(eb->ra_session, NULL, NULL, &b->pristine_props,
-                          b->path, base_revision, 0, pool));
-
   SVN_ERR(eb->diff_callbacks->dir_opened(
                 &b->tree_conflicted, &b->skip,
                 &b->skip_children, b->path, base_revision,
@@ -840,9 +837,8 @@ window_handler(svn_txdelta_window_t *win
 
   if (!window)
     {
-      b->result_md5_checksum = svn_checksum__from_digest(b->result_digest,
-                                                         svn_checksum_md5,
-                                                         b->pool);
+      b->result_md5_checksum = svn_checksum__from_digest_md5(b->result_digest,
+                                                             b->pool);
     }
 
   return SVN_NO_ERROR;
@@ -1092,6 +1088,7 @@ close_directory(void *dir_baton,
   svn_wc_notify_state_t prop_state = svn_wc_notify_state_unknown;
   svn_boolean_t skipped = FALSE;
   apr_pool_t *scratch_pool;
+  apr_hash_t *pristine_props;
 
   /* Skip *everything* within a newly tree-conflicted directory. */
   if (b->skip)
@@ -1102,17 +1099,28 @@ close_directory(void *dir_baton,
 
   scratch_pool = b->pool;
 
-  if (!b->added && b->propchanges->nelts > 0)
-    remove_non_prop_changes(b->pristine_props, b->propchanges);
+  if (b->added)
+    {
+      pristine_props = eb->empty_hash;
+    }
+  else
+    {
+      SVN_ERR(svn_ra_get_dir2(eb->ra_session, NULL, NULL, &pristine_props,
+                              b->path, b->base_revision, 0, scratch_pool));
+    }
+
+  if (b->propchanges->nelts > 0)
+    {
+      remove_non_prop_changes(pristine_props, b->propchanges);
+    }
 
-  /* Report any prop changes. */
   if (b->propchanges->nelts > 0)
     {
       svn_boolean_t tree_conflicted = FALSE;
       SVN_ERR(eb->diff_callbacks->dir_props_changed(
                &prop_state, &tree_conflicted,
                b->path, b->added,
-               b->propchanges, b->pristine_props,
+               b->propchanges, pristine_props,
                b->edit_baton->diff_cmd_baton, scratch_pool));
       if (tree_conflicted)
         b->tree_conflicted = TRUE;

Modified: subversion/branches/compressed-pristines/subversion/libsvn_client/resolved.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_client/resolved.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_client/resolved.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_client/resolved.c Thu Aug 16 10:17:48 2012
@@ -55,12 +55,14 @@ svn_client_resolve(const char *path,
 
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
 
-  SVN_ERR(svn_wc_resolved_conflict5(ctx->wc_ctx, local_abspath,
+  SVN_ERR(svn_wc__resolve_conflicts(ctx->wc_ctx, local_abspath,
                                     depth,
                                     TRUE /* resolve_text */,
                                     "" /* resolve_prop (ALL props) */,
                                     TRUE /* resolve_tree */,
                                     conflict_choice,
+                                    ctx->conflict_func2,
+                                    ctx->conflict_baton2,
                                     ctx->cancel_func, ctx->cancel_baton,
                                     ctx->notify_func2, ctx->notify_baton2,
                                     pool));

Modified: subversion/branches/compressed-pristines/subversion/libsvn_client/revisions.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_client/revisions.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_client/revisions.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_client/revisions.c Thu Aug 16 10:17:48 2012
@@ -91,9 +91,9 @@ svn_client__get_revision_number(svn_revn
         if (svn_path_is_url(local_abspath))
           goto invalid_rev_arg;
 
-        err = svn_wc__node_get_commit_base_rev(revnum, wc_ctx,
-                                               local_abspath,
-                                               scratch_pool);
+        err = svn_wc__node_get_commit_base(revnum, NULL, NULL, NULL,
+                                           wc_ctx, local_abspath,
+                                           scratch_pool, scratch_pool);
 
         /* Return the same error as older code did (before and at r935091).
            At least svn_client_proplist3 promises SVN_ERR_ENTRY_NOT_FOUND. */

Modified: subversion/branches/compressed-pristines/subversion/libsvn_client/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_client/status.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_client/status.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_client/status.c Thu Aug 16 10:17:48 2012
@@ -292,40 +292,56 @@ svn_client_status5(svn_revnum_t *result_
   sb.wc_ctx = ctx->wc_ctx;
 
   SVN_ERR(svn_dirent_get_absolute(&target_abspath, path, pool));
-  {
-    svn_node_kind_t kind;
 
-    SVN_ERR(svn_wc_read_kind(&kind, ctx->wc_ctx, target_abspath, FALSE, pool));
+  if (update)
+    {
+      /* The status editor only works on directories, so get the ancestor
+         if necessary */
 
-    /* Dir must be a working copy directory or the status editor fails */
-    if (kind == svn_node_dir)
-      {
-        dir_abspath = target_abspath;
-        target_basename = "";
-        dir = path;
-      }
-    else
-      {
-        dir_abspath = svn_dirent_dirname(target_abspath, pool);
-        target_basename = svn_dirent_basename(target_abspath, NULL);
-        dir = svn_dirent_dirname(path, pool);
-
-        if (kind != svn_node_file)
-          {
-            err = svn_wc_read_kind(&kind, ctx->wc_ctx, dir_abspath, FALSE,
-                                   pool);
-
-            svn_error_clear(err);
-
-            if (err || kind != svn_node_dir)
-              {
-                return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL,
-                                         _("'%s' is not a working copy"),
-                                         svn_dirent_local_style(path, pool));
-              }
-          }
-      }
-  }
+      svn_node_kind_t kind;
+ 
+      SVN_ERR(svn_wc_read_kind(&kind, ctx->wc_ctx, target_abspath, FALSE,
+                               pool));
+ 
+      /* Dir must be a working copy directory or the status editor fails */
+      if (kind == svn_node_dir)
+        {
+          dir_abspath = target_abspath;
+          target_basename = "";
+          dir = path;
+        }
+      else
+        {
+          dir_abspath = svn_dirent_dirname(target_abspath, pool);
+          target_basename = svn_dirent_basename(target_abspath, NULL);
+          dir = svn_dirent_dirname(path, pool);
+ 
+          if (kind == svn_node_file)
+            {
+              if (depth == svn_depth_empty)
+                depth = svn_depth_files;
+            }
+          else
+            {
+              err = svn_wc_read_kind(&kind, ctx->wc_ctx, dir_abspath, FALSE,
+                                     pool);
+ 
+              svn_error_clear(err);
+ 
+              if (err || kind != svn_node_dir)
+                {
+                  return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL,
+                                           _("'%s' is not a working copy"),
+                                           svn_dirent_local_style(path, pool));
+                }
+            }
+        }
+    }
+  else
+    {
+      dir = path;
+      dir_abspath = target_abspath;
+    }
 
   if (svn_dirent_is_absolute(dir))
     {
@@ -516,13 +532,13 @@ svn_client_status5(svn_revnum_t *result_
   */
   if (SVN_DEPTH_IS_RECURSIVE(depth) && (! ignore_externals))
     {
-      apr_hash_t *externals_new;
-      SVN_ERR(svn_wc__externals_gather_definitions(&externals_new, NULL,
-                                                   ctx->wc_ctx, target_abspath,
-                                                   depth, pool, pool));
+      apr_hash_t *external_map;
+      SVN_ERR(svn_wc__externals_defined_below(&external_map,
+                                              ctx->wc_ctx, target_abspath,
+                                              pool, pool));
 
 
-      SVN_ERR(svn_client__do_external_status(ctx, externals_new,
+      SVN_ERR(svn_client__do_external_status(ctx, external_map,
                                              depth, get_all,
                                              update, no_ignore,
                                              status_func, status_baton, pool));
@@ -625,7 +641,6 @@ svn_client__create_status(svn_client_sta
   if (status->file_external)
     {
       (*cst)->switched = FALSE;
-      (*cst)->node_status = (*cst)->text_status;
     }
 
   (*cst)->lock = status->lock;

Modified: subversion/branches/compressed-pristines/subversion/libsvn_client/switch.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_client/switch.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_client/switch.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_client/switch.c Thu Aug 16 10:17:48 2012
@@ -73,7 +73,8 @@ switch_internal(svn_revnum_t *result_rev
 {
   const svn_ra_reporter3_t *reporter;
   void *report_baton;
-  const char *url, *target, *source_root, *switch_rev_url;
+  const char *anchor_url, *target;
+  svn_client__pathrev_t *switch_loc;
   svn_ra_session_t *ra_session;
   svn_revnum_t revnum;
   svn_error_t *err = SVN_NO_ERROR;
@@ -141,8 +142,9 @@ switch_internal(svn_revnum_t *result_rev
   else
     target = "";
 
-  SVN_ERR(svn_wc__node_get_url(&url, ctx->wc_ctx, anchor_abspath, pool, pool));
-  if (! url)
+  SVN_ERR(svn_wc__node_get_url(&anchor_url, ctx->wc_ctx, anchor_abspath,
+                               pool, pool));
+  if (! anchor_url)
     return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
                              _("Directory '%s' has no URL"),
                              svn_dirent_local_style(anchor_abspath, pool));
@@ -175,20 +177,17 @@ switch_internal(svn_revnum_t *result_rev
     }
 
   /* Open an RA session to 'source' URL */
-  SVN_ERR(svn_client__ra_session_from_path(&ra_session, &revnum,
-                                           &switch_rev_url,
-                                           switch_url, anchor_abspath,
-                                           peg_revision, revision,
-                                           ctx, pool));
-
-  SVN_ERR(svn_ra_get_repos_root2(ra_session, &source_root, pool));
+  SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &switch_loc,
+                                            switch_url, anchor_abspath,
+                                            peg_revision, revision,
+                                            ctx, pool));
 
   /* Disallow a switch operation to change the repository root of the
      target. */
-  if (! svn_uri__is_ancestor(source_root, url))
+  if (! svn_uri__is_ancestor(switch_loc->repos_root_url, anchor_url))
     return svn_error_createf(SVN_ERR_WC_INVALID_SWITCH, NULL,
                              _("'%s'\nis not the same repository as\n'%s'"),
-                             url, source_root);
+                             anchor_url, switch_loc->repos_root_url);
 
   /* If we're not ignoring ancestry, then error out if the switch
      source and target don't have a common ancestory.
@@ -197,30 +196,29 @@ switch_internal(svn_revnum_t *result_rev
      ### okay? */
   if (! ignore_ancestry)
     {
-      const char *target_url;
-      svn_revnum_t target_rev;
-      svn_client__pathrev_t *switch_loc, *target_loc, *yca;
-
-      SVN_ERR(svn_client__pathrev_create_with_session(
-                &switch_loc, ra_session, revnum, switch_rev_url, pool));
-      SVN_ERR(svn_wc__node_get_url(&target_url, ctx->wc_ctx, local_abspath,
-                                   pool, pool));
-      SVN_ERR(svn_wc__node_get_base_rev(&target_rev, ctx->wc_ctx,
-                                        local_abspath, pool));
-      SVN_ERR(svn_client__pathrev_create_with_session(
-                &target_loc, ra_session, target_rev, target_url, pool));
-      /* ### It would be nice if this function could reuse the existing
+      svn_client__pathrev_t *target_base_loc, *yca;
+
+      SVN_ERR(svn_client__wc_node_get_base(&target_base_loc, local_abspath,
+                                           ctx->wc_ctx, pool, pool));
+
+      if (!target_base_loc)
+        yca = NULL; /* Not versioned */
+      else
+        {
+          /* ### It would be nice if this function could reuse the existing
              ra session instead of opening two for its own use. */
-      SVN_ERR(svn_client__get_youngest_common_ancestor(
-                &yca, switch_loc, target_loc, ctx, pool, pool));
+          SVN_ERR(svn_client__get_youngest_common_ancestor(
+                  &yca, switch_loc, target_base_loc, ra_session, ctx,
+                  pool, pool));
+        }
       if (! yca)
         return svn_error_createf(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
                                  _("'%s' shares no common ancestry with '%s'"),
-                                 switch_url, local_abspath);
+                                 switch_url,
+                                 svn_dirent_dirname(local_abspath, pool));
     }
 
-
-  SVN_ERR(svn_ra_reparent(ra_session, url, pool));
+  SVN_ERR(svn_ra_reparent(ra_session, anchor_url, pool));
 
   /* Fetch the switch (update) editor.  If REVISION is invalid, that's
      okay; the RA driver will call editor->set_target_revision() later on. */
@@ -228,12 +226,12 @@ switch_internal(svn_revnum_t *result_rev
                                 SVN_RA_CAPABILITY_DEPTH, pool));
 
   dfb.ra_session = ra_session;
-  SVN_ERR(svn_ra_get_session_url(ra_session, &dfb.anchor_url, pool));
-  dfb.target_revision = revnum;
+  dfb.anchor_url = anchor_url;
+  dfb.target_revision = switch_loc->rev;
 
   SVN_ERR(svn_wc__get_switch_editor(&switch_editor, &switch_edit_baton,
                                     &revnum, ctx->wc_ctx, anchor_abspath,
-                                    target, switch_rev_url, use_commit_times,
+                                    target, switch_loc->url, use_commit_times,
                                     depth,
                                     depth_is_sticky, allow_unver_obstructions,
                                     server_supports_depth,
@@ -247,10 +245,11 @@ switch_internal(svn_revnum_t *result_rev
 
   /* Tell RA to do an update of URL+TARGET to REVISION; if we pass an
      invalid revnum, that means RA will use the latest revision. */
-  SVN_ERR(svn_ra_do_switch2(ra_session, &reporter, &report_baton, revnum,
+  SVN_ERR(svn_ra_do_switch2(ra_session, &reporter, &report_baton,
+                            switch_loc->rev,
                             target,
                             depth_is_sticky ? depth : svn_depth_unknown,
-                            switch_rev_url,
+                            switch_loc->url,
                             switch_editor, switch_edit_baton, pool));
 
   /* Drive the reporter structure, describing the revisions within
@@ -291,7 +290,8 @@ switch_internal(svn_revnum_t *result_rev
 
       SVN_ERR(svn_client__handle_externals(new_externals,
                                            new_depths,
-                                           source_root, local_abspath,
+                                           switch_loc->repos_root_url,
+                                           local_abspath,
                                            depth, use_sleep,
                                            ctx, pool));
     }

Modified: subversion/branches/compressed-pristines/subversion/libsvn_client/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_client/update.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_client/update.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_client/update.c Thu Aug 16 10:17:48 2012
@@ -191,10 +191,9 @@ update_internal(svn_revnum_t *result_rev
   void *update_edit_baton;
   const svn_ra_reporter3_t *reporter;
   void *report_baton;
-  const char *anchor_url;
   const char *corrected_url;
   const char *target;
-  const char *repos_root;
+  svn_client__pathrev_t *anchor_loc;
   svn_error_t *err;
   svn_revnum_t revnum;
   svn_boolean_t use_commit_times;
@@ -207,7 +206,7 @@ update_internal(svn_revnum_t *result_rev
   apr_array_header_t *preserved_exts;
   struct svn_client__dirent_fetcher_baton_t dfb;
   svn_boolean_t server_supports_depth;
-  svn_boolean_t tree_conflicted;
+  svn_boolean_t text_conflicted, prop_conflicted, tree_conflicted;
   svn_config_t *cfg = ctx->config ? apr_hash_get(ctx->config,
                                                  SVN_CONFIG_CATEGORY_CONFIG,
                                                  APR_HASH_KEY_STRING) : NULL;
@@ -221,39 +220,34 @@ update_internal(svn_revnum_t *result_rev
   else
     target = "";
 
-  /* Get full URL from the ANCHOR. */
-  SVN_ERR(svn_wc__node_get_url(&anchor_url, ctx->wc_ctx, anchor_abspath,
-                               pool, pool));
-  if (! anchor_url)
-    return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
-                             _("'%s' has no URL"),
-                             svn_dirent_local_style(anchor_abspath, pool));
-
-  /* Check if our anchor exists in BASE. If it doesn't we can't update.
-     ### For performance reasons this should be handled with the same query
-     ### as retrieving the anchor url. */
-  SVN_ERR(svn_wc__node_get_base_rev(&revnum, ctx->wc_ctx, anchor_abspath,
-                                    pool));
-
-  /* It does not make sense to update tree-conflict victims. */
-  err = svn_wc_conflicted_p3(NULL, NULL, &tree_conflicted,
+  /* Check if our anchor exists in BASE. If it doesn't we can't update. */
+  SVN_ERR(svn_client__wc_node_get_base(&anchor_loc, anchor_abspath,
+                                       ctx->wc_ctx, pool, pool));
+
+  /* It does not make sense to update conflict victims. */
+  err = svn_wc_conflicted_p3(&text_conflicted, &prop_conflicted,
+                             &tree_conflicted,
                              ctx->wc_ctx, local_abspath, pool);
   if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
     {
       svn_error_clear(err);
+      text_conflicted = FALSE;
+      prop_conflicted = FALSE;
       tree_conflicted = FALSE;
     }
   else
     SVN_ERR(err);
 
-  if (!SVN_IS_VALID_REVNUM(revnum) || tree_conflicted)
+  if (! anchor_loc
+      || text_conflicted || prop_conflicted || tree_conflicted)
     {
       if (ctx->notify_func2)
         {
           svn_wc_notify_t *nt;
 
           nt = svn_wc_create_notify(local_abspath,
-                                    tree_conflicted
+                                    (text_conflicted || prop_conflicted
+                                                     || tree_conflicted)
                                       ? svn_wc_notify_skip_conflicted
                                       : svn_wc_notify_update_skip_working_only,
                                     pool);
@@ -330,29 +324,30 @@ update_internal(svn_revnum_t *result_rev
 
   /* Open an RA session for the URL */
   SVN_ERR(svn_client__open_ra_session_internal(&ra_session, &corrected_url,
-                                               anchor_url,
+                                               anchor_loc->url,
                                                anchor_abspath, NULL, TRUE,
                                                TRUE, ctx, pool));
 
-  SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root, pool));
-
   /* If we got a corrected URL from the RA subsystem, we'll need to
      relocate our working copy first. */
   if (corrected_url)
     {
-      const char *current_repos_root;
-      const char *current_uuid;
+      const char *new_repos_root_url;
 
       /* To relocate everything inside our repository we need the old and new
-         repos root. ### And we should only perform relocates on the wcroot */
-      SVN_ERR(svn_wc__node_get_repos_info(&current_repos_root, &current_uuid,
-                                          ctx->wc_ctx, anchor_abspath,
-                                          pool, pool));
-
-      /* ### Check uuid here before calling relocate? */
-      SVN_ERR(svn_client_relocate2(anchor_abspath, current_repos_root,
-                                   repos_root, ignore_externals, ctx, pool));
-      anchor_url = corrected_url;
+         repos root. */
+      SVN_ERR(svn_ra_get_repos_root2(ra_session, &new_repos_root_url, pool));
+
+      /* svn_client_relocate2() will check the uuid */
+      SVN_ERR(svn_client_relocate2(anchor_abspath, anchor_loc->url,
+                                   new_repos_root_url, ignore_externals,
+                                   ctx, pool));
+
+      /* Store updated repository root for externals */
+      anchor_loc->repos_root_url = new_repos_root_url;
+      /* ### We should update anchor_loc->repos_uuid too, although currently
+       * we don't use it. */
+      anchor_loc->url = corrected_url;
     }
 
   /* ### todo: shouldn't svn_client__get_revision_number be able
@@ -366,7 +361,7 @@ update_internal(svn_revnum_t *result_rev
 
   dfb.ra_session = ra_session;
   dfb.target_revision = revnum;
-  dfb.anchor_url = anchor_url;
+  dfb.anchor_url = anchor_loc->url;
 
   /* Fetch the update editor.  If REVISION is invalid, that's okay;
      the RA driver will call editor->set_target_revision later on. */
@@ -428,7 +423,7 @@ update_internal(svn_revnum_t *result_rev
 
       SVN_ERR(svn_client__handle_externals(new_externals,
                                            new_depths,
-                                           repos_root, local_abspath,
+                                           anchor_loc->repos_root_url, local_abspath,
                                            depth, use_sleep,
                                            ctx, pool));
     }
@@ -567,7 +562,7 @@ svn_client_update4(apr_array_header_t **
                    apr_pool_t *pool)
 {
   int i;
-  apr_pool_t *subpool = svn_pool_create(pool);
+  apr_pool_t *iterpool = svn_pool_create(pool);
   const char *path = NULL;
   svn_boolean_t sleep = FALSE;
 
@@ -590,12 +585,12 @@ svn_client_update4(apr_array_header_t **
       const char *local_abspath;
       path = APR_ARRAY_IDX(paths, i, const char *);
 
-      svn_pool_clear(subpool);
+      svn_pool_clear(iterpool);
 
       if (ctx->cancel_func)
         SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
 
-      SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, subpool));
+      SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, iterpool));
       err = svn_client__update_internal(&result_rev, local_abspath,
                                         revision, depth, depth_is_sticky,
                                         ignore_externals,
@@ -603,7 +598,8 @@ svn_client_update4(apr_array_header_t **
                                         adds_as_modification,
                                         make_parents,
                                         FALSE, &sleep,
-                                        ctx, subpool);
+                                        ctx,
+                                        iterpool);
 
       if (err)
         {
@@ -620,15 +616,15 @@ svn_client_update4(apr_array_header_t **
               svn_wc_notify_t *notify;
               notify = svn_wc_create_notify(path,
                                             svn_wc_notify_skip,
-                                            subpool);
-              (*ctx->notify_func2)(ctx->notify_baton2, notify, subpool);
+                                            iterpool);
+              (*ctx->notify_func2)(ctx->notify_baton2, notify, iterpool);
             }
         }
       if (result_revs)
         APR_ARRAY_PUSH(*result_revs, svn_revnum_t) = result_rev;
     }
+  svn_pool_destroy(iterpool);
 
-  svn_pool_destroy(subpool);
   if (sleep)
     svn_io_sleep_for_timestamps((paths->nelts == 1) ? path : NULL, pool);