You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2012/05/14 16:07:47 UTC

svn commit: r1338209 [1/4] - in /subversion/branches/ev2-export: ./ build/ac-macros/ subversion/bindings/javahl/src/org/apache/subversion/javahl/ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_ra_serf/ subve...

Author: hwright
Date: Mon May 14 14:07:45 2012
New Revision: 1338209

URL: http://svn.apache.org/viewvc?rev=1338209&view=rev
Log:
On the ev2-export branch:
Bring up-to-date with trunk.

Modified:
    subversion/branches/ev2-export/   (props changed)
    subversion/branches/ev2-export/build/ac-macros/swig.m4
    subversion/branches/ev2-export/configure.ac
    subversion/branches/ev2-export/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java
    subversion/branches/ev2-export/subversion/include/private/svn_client_private.h
    subversion/branches/ev2-export/subversion/include/private/svn_wc_private.h
    subversion/branches/ev2-export/subversion/include/svn_wc.h
    subversion/branches/ev2-export/subversion/include/svn_xml.h
    subversion/branches/ev2-export/subversion/libsvn_client/commit_util.c
    subversion/branches/ev2-export/subversion/libsvn_client/externals.c
    subversion/branches/ev2-export/subversion/libsvn_client/merge.c
    subversion/branches/ev2-export/subversion/libsvn_client/mergeinfo.c
    subversion/branches/ev2-export/subversion/libsvn_client/switch.c
    subversion/branches/ev2-export/subversion/libsvn_client/update.c
    subversion/branches/ev2-export/subversion/libsvn_client/util.c
    subversion/branches/ev2-export/subversion/libsvn_ra_serf/blame.c
    subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c
    subversion/branches/ev2-export/subversion/libsvn_ra_serf/get_deleted_rev.c
    subversion/branches/ev2-export/subversion/libsvn_ra_serf/getdate.c
    subversion/branches/ev2-export/subversion/libsvn_ra_serf/getlocations.c
    subversion/branches/ev2-export/subversion/libsvn_ra_serf/getlocationsegments.c
    subversion/branches/ev2-export/subversion/libsvn_ra_serf/getlocks.c
    subversion/branches/ev2-export/subversion/libsvn_ra_serf/locks.c
    subversion/branches/ev2-export/subversion/libsvn_ra_serf/log.c
    subversion/branches/ev2-export/subversion/libsvn_ra_serf/options.c
    subversion/branches/ev2-export/subversion/libsvn_ra_serf/property.c
    subversion/branches/ev2-export/subversion/libsvn_ra_serf/ra_serf.h
    subversion/branches/ev2-export/subversion/libsvn_ra_serf/replay.c
    subversion/branches/ev2-export/subversion/libsvn_ra_serf/serf.c
    subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c
    subversion/branches/ev2-export/subversion/libsvn_ra_serf/xml.c
    subversion/branches/ev2-export/subversion/libsvn_subr/lock.c
    subversion/branches/ev2-export/subversion/libsvn_subr/xml.c
    subversion/branches/ev2-export/subversion/libsvn_wc/conflicts.c
    subversion/branches/ev2-export/subversion/libsvn_wc/node.c
    subversion/branches/ev2-export/subversion/libsvn_wc/questions.c
    subversion/branches/ev2-export/subversion/libsvn_wc/status.c
    subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.c
    subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.h
    subversion/branches/ev2-export/subversion/libsvn_wc/workqueue.h
    subversion/branches/ev2-export/subversion/svn/conflict-callbacks.c
    subversion/branches/ev2-export/subversion/svn/resolve-cmd.c
    subversion/branches/ev2-export/subversion/svnserve/serve.c
    subversion/branches/ev2-export/subversion/tests/cmdline/davautocheck.sh
    subversion/branches/ev2-export/subversion/tests/cmdline/lock_tests.py
    subversion/branches/ev2-export/subversion/tests/cmdline/special_tests.py
    subversion/branches/ev2-export/subversion/tests/cmdline/svntest/err.py
    subversion/branches/ev2-export/tools/dev/gen-py-errors.py
    subversion/branches/ev2-export/tools/dist/release.py

Propchange: subversion/branches/ev2-export/
------------------------------------------------------------------------------
  Merged /subversion/trunk:r1336971-1338207

Modified: subversion/branches/ev2-export/build/ac-macros/swig.m4
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/build/ac-macros/swig.m4?rev=1338209&r1=1338208&r2=1338209&view=diff
==============================================================================
--- subversion/branches/ev2-export/build/ac-macros/swig.m4 (original)
+++ subversion/branches/ev2-export/build/ac-macros/swig.m4 Mon May 14 14:07:45 2012
@@ -187,7 +187,7 @@ AC_DEFUN(SVN_FIND_SWIG,
     for var_name in arch archdir CC LDSHARED DLEXT LIBS LIBRUBYARG \
                     rubyhdrdir sitedir sitelibdir sitearchdir libdir
     do
-      rbconfig_tmp=`$rbconfig "print Config::CONFIG@<:@'$var_name'@:>@"`
+      rbconfig_tmp=`$rbconfig "print RbConfig::CONFIG@<:@'$var_name'@:>@"`
       eval "rbconfig_$var_name=\"$rbconfig_tmp\""
     done
 

Modified: subversion/branches/ev2-export/configure.ac
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/configure.ac?rev=1338209&r1=1338208&r2=1338209&view=diff
==============================================================================
--- subversion/branches/ev2-export/configure.ac (original)
+++ subversion/branches/ev2-export/configure.ac Mon May 14 14:07:45 2012
@@ -1184,12 +1184,12 @@ if test "$RUBY" != "none"; then
       AC_PATH_PROGS(RDOC, rdoc rdoc1.8 rdoc18, none)
     fi
     AC_CACHE_CHECK([for Ruby major version], [svn_cv_ruby_major],[
-    svn_cv_ruby_major="`$RUBY -rrbconfig -e 'print Config::CONFIG.fetch(%q(MAJOR))'`"
+    svn_cv_ruby_major="`$RUBY -rrbconfig -e 'print RbConfig::CONFIG.fetch(%q(MAJOR))'`"
     ])
     RUBY_MAJOR="$svn_cv_ruby_major"
 
     AC_CACHE_CHECK([for Ruby minor version], [svn_cv_ruby_minor],[
-    svn_cv_ruby_minor="`$RUBY -rrbconfig -e 'print Config::CONFIG.fetch(%q(MINOR))'`"
+    svn_cv_ruby_minor="`$RUBY -rrbconfig -e 'print RbConfig::CONFIG.fetch(%q(MINOR))'`"
     ])
     RUBY_MINOR="$svn_cv_ruby_minor"
 

Modified: subversion/branches/ev2-export/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java?rev=1338209&r1=1338208&r2=1338209&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java (original)
+++ subversion/branches/ev2-export/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java Mon May 14 14:07:45 2012
@@ -547,7 +547,10 @@ public class ClientNotifyInformation ext
         skip_conflicted ("skipped conflicted path"),
 
         /** The lock on a file was removed during update */
-        update_broken_lock ("broken lock removed");
+        update_broken_lock ("broken lock removed"),
+
+        /** Operation failed because a node is obstructed */
+        failed_obstructed ("failed by obstruction");
 
 
         /**

Modified: subversion/branches/ev2-export/subversion/include/private/svn_client_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/include/private/svn_client_private.h?rev=1338209&r1=1338208&r2=1338209&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/include/private/svn_client_private.h (original)
+++ subversion/branches/ev2-export/subversion/include/private/svn_client_private.h Mon May 14 14:07:45 2012
@@ -144,9 +144,33 @@ svn_client__youngest_common_ancestor(con
                                      apr_pool_t *result_pool,
                                      apr_pool_t *scratch_pool);
 
-/* Set *ORIGIN_P to the origin of the WC node at WC_ABSPATH.  If the node
+/* Get the repository location of the base node at LOCAL_ABSPATH.
+ *
+ * A pathrev_t wrapper around svn_wc__node_get_base().
+ *
+ * Set *BASE_P to the location that this node was checked out at or last
+ * updated/switched to, regardless of any uncommitted changes (delete,
+ * replace and/or copy-here/move-here).
+ *
+ * If there is no base node at LOCAL_ABSPATH (such as when there is a
+ * locally added/copied/moved-here node that is not part of a replace),
+ * set *BASE_P to NULL.
+ */
+svn_error_t *
+svn_client__wc_node_get_base(svn_client__pathrev_t **base_p,
+                             const char *wc_abspath,
+                             svn_client_ctx_t *ctx,
+                             apr_pool_t *result_pool,
+                             apr_pool_t *scratch_pool);
+
+/* Get the original location of the WC node at LOCAL_ABSPATH.
+ *
+ * A pathrev_t wrapper around svn_wc__node_get_origin().
+ *
+ * Set *ORIGIN_P to the origin of the WC node at WC_ABSPATH.  If the node
  * is a local copy, give the copy-from location.  If the node is locally
- * added or deleted, set *ORIGIN_P to NULL. */
+ * added or deleted, set *ORIGIN_P to NULL.
+ */
 svn_error_t *
 svn_client__wc_node_get_origin(svn_client__pathrev_t **origin_p,
                                const char *wc_abspath,

Modified: subversion/branches/ev2-export/subversion/include/private/svn_wc_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/include/private/svn_wc_private.h?rev=1338209&r1=1338208&r2=1338209&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/include/private/svn_wc_private.h (original)
+++ subversion/branches/ev2-export/subversion/include/private/svn_wc_private.h Mon May 14 14:07:45 2012
@@ -1051,23 +1051,14 @@ svn_wc__get_tmpdir(const char **tmpdir_a
  * ### it's caller will eventually move into a wc and maybe wc_db api.
  */
 svn_error_t *
-svn_wc__node_get_commit_status(svn_node_kind_t *kind,
-                               svn_boolean_t *added,
+svn_wc__node_get_commit_status(svn_boolean_t *added,
                                svn_boolean_t *deleted,
-                               svn_boolean_t *replaced,
-                               svn_boolean_t *not_present,
-                               svn_boolean_t *excluded,
+                               svn_boolean_t *is_replace_root,
                                svn_boolean_t *is_op_root,
-                               svn_boolean_t *symlink,
                                svn_revnum_t *revision,
-                               const char **repos_relpath,
                                svn_revnum_t *original_revision,
                                const char **original_repos_relpath,
-                               svn_boolean_t *conflicted,
-                               const char **changelist,
-                               svn_boolean_t *props_mod,
                                svn_boolean_t *update_root,
-                               const char **lock_token,
                                svn_wc_context_t *wc_ctx,
                                const char *local_abspath,
                                apr_pool_t *result_pool,

Modified: subversion/branches/ev2-export/subversion/include/svn_wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/include/svn_wc.h?rev=1338209&r1=1338208&r2=1338209&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/include/svn_wc.h (original)
+++ subversion/branches/ev2-export/subversion/include/svn_wc.h Mon May 14 14:07:45 2012
@@ -1223,7 +1223,11 @@ typedef enum svn_wc_notify_action_t
 
   /** Just the lock on a file was removed during update.
    * @since New in 1.8. */
-  svn_wc_notify_update_broken_lock
+  svn_wc_notify_update_broken_lock,
+
+  /** Operation failed because a node is obstructed.
+   * @since New in 1.8. */
+  svn_wc_notify_failed_obstruction
 
 } svn_wc_notify_action_t;
 
@@ -2623,24 +2627,22 @@ svn_wc_has_binary_prop(svn_boolean_t *ha
  * with regard to the base revision, else set @a *modified_p to zero.
  * @a local_abspath is the absolute path to the file.
  *
- * If @a force_comparison is @c TRUE, this function will not allow
- * early return mechanisms that avoid actual content comparison.
- * Instead, if there is a text base, a full byte-by-byte comparison
- * will be done, and the entry checksum verified as well.  (This means
- * that if the text base is much longer than the working file, every
- * byte of the text base will still be examined.)
+ * This function uses some heuristics to avoid byte-by-byte comparisons
+ * against the base text (eg. file size and its modification time).
  *
  * If @a local_abspath does not exist, consider it unmodified.  If it exists
  * but is not under revision control (not even scheduled for
  * addition), return the error #SVN_ERR_ENTRY_NOT_FOUND.
  *
+ * @a unused is ignored.
+ *
  * @since New in 1.7.
  */
 svn_error_t *
 svn_wc_text_modified_p2(svn_boolean_t *modified_p,
                         svn_wc_context_t *wc_ctx,
                         const char *local_abspath,
-                        svn_boolean_t force_comparison,
+                        svn_boolean_t unused,
                         apr_pool_t *scratch_pool);
 
 /** Similar to svn_wc_text_modified_p2(), but with a relative path and

Modified: subversion/branches/ev2-export/subversion/include/svn_xml.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/include/svn_xml.h?rev=1338209&r1=1338208&r2=1338209&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/include/svn_xml.h (original)
+++ subversion/branches/ev2-export/subversion/include/svn_xml.h Mon May 14 14:07:45 2012
@@ -228,7 +228,7 @@ svn_xml_signal_bailout(svn_error_t *erro
  */
 const char *
 svn_xml_get_attr_value(const char *name,
-                       const char **atts);
+                       const char *const *atts);
 
 
 

Modified: subversion/branches/ev2-export/subversion/libsvn_client/commit_util.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/commit_util.c?rev=1338209&r1=1338208&r2=1338209&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/commit_util.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/commit_util.c Mon May 14 14:07:45 2012
@@ -266,80 +266,6 @@ look_up_committable(svn_client__committa
       apr_hash_get(committables->by_path, path, APR_HASH_KEY_STRING);
 }
 
-/* Helper for harvest_committables().
- * If ENTRY is a dir, return an SVN_ERR_WC_FOUND_CONFLICT error when
- * encountering a tree-conflicted immediate child node. However, do
- * not consider immediate children that are outside the bounds of DEPTH.
- *
- * TODO ### WC_CTX and LOCAL_ABSPATH ...
- * ENTRY, DEPTH, CHANGELISTS and POOL are the same ones
- * originally received by harvest_committables().
- *
- * Tree-conflicts information is stored in the victim's immediate parent.
- * In some cases of an absent tree-conflicted victim, the tree-conflict
- * information in its parent dir is the only indication that the node
- * is under version control. This function is necessary for this
- * particular case. In all other cases, this simply bails out a little
- * bit earlier. */
-static svn_error_t *
-bail_on_tree_conflicted_children(svn_wc_context_t *wc_ctx,
-                                 const char *local_abspath,
-                                 svn_node_kind_t kind,
-                                 svn_depth_t depth,
-                                 apr_hash_t *changelists,
-                                 svn_wc_notify_func2_t notify_func,
-                                 void *notify_baton,
-                                 apr_pool_t *pool)
-{
-  apr_hash_t *conflicts;
-  apr_hash_index_t *hi;
-
-  if ((depth == svn_depth_empty)
-      || (kind != svn_node_dir))
-    /* There can't possibly be tree-conflicts information here. */
-    return SVN_NO_ERROR;
-
-  SVN_ERR(svn_wc__get_all_tree_conflicts(&conflicts, wc_ctx, local_abspath,
-                                         pool, pool));
-  if (!conflicts)
-    return SVN_NO_ERROR;
-
-  for (hi = apr_hash_first(pool, conflicts); hi; hi = apr_hash_next(hi))
-    {
-      const svn_wc_conflict_description2_t *conflict =
-          svn__apr_hash_index_val(hi);
-
-      if ((conflict->node_kind == svn_node_dir) &&
-          (depth == svn_depth_files))
-        continue;
-
-      /* So we've encountered a conflict that is included in DEPTH.
-         Bail out. But if there are CHANGELISTS, avoid bailing out
-         on an item that doesn't match the CHANGELISTS. */
-      if (!svn_wc__changelist_match(wc_ctx, local_abspath, changelists, pool))
-        continue;
-
-      /* At this point, a conflict was found, and either there were no
-         changelists, or the changelists matched. Bail out already! */
-
-      if (notify_func != NULL)
-        {
-          notify_func(notify_baton,
-                      svn_wc_create_notify(local_abspath,
-                                           svn_wc_notify_failed_conflict,
-                                           pool),
-                      pool);
-        }
-
-      return svn_error_createf(
-               SVN_ERR_WC_FOUND_CONFLICT, NULL,
-               _("Aborting commit: '%s' remains in conflict"),
-               svn_dirent_local_style(conflict->local_abspath, pool));
-    }
-
-  return SVN_NO_ERROR;
-}
-
 /* Helper function for svn_client__harvest_committables().
  * Determine whether we are within a tree-conflicted subtree of the
  * working copy and return an SVN_ERR_WC_FOUND_CONFLICT error if so. */
@@ -430,19 +356,43 @@ bail_on_tree_conflicted_ancestor(svn_wc_
 
    Any items added to COMMITTABLES are allocated from the COMITTABLES
    hash pool, not POOL.  SCRATCH_POOL is used for temporary allocations. */
+
+struct harvest_baton
+{
+  /* Static data */
+  const char *root_abspath;
+  svn_client__committables_t *committables;
+  apr_hash_t *lock_tokens;
+  const char *commit_relpath; /* Valid for the harvest root */
+  svn_depth_t depth;
+  svn_boolean_t just_locked;
+  apr_hash_t *changelists;
+  apr_hash_t *danglers;
+  svn_client__check_url_kind_t check_url_func;
+  void *check_url_baton;
+  svn_wc_notify_func2_t notify_func;
+  void *notify_baton;
+  svn_wc_context_t *wc_ctx;
+  apr_pool_t *result_pool;
+
+  /* Harvester state */
+  const char *skip_below_abspath; /* If non-NULL, skip everything below */
+};
+
+static svn_error_t *
+harvest_status_callback(void *status_baton,
+                        const char *local_abspath,
+                        const svn_wc_status3_t *status,
+                        apr_pool_t *scratch_pool);
+
 static svn_error_t *
 harvest_committables(const char *local_abspath,
                      svn_client__committables_t *committables,
                      apr_hash_t *lock_tokens,
-                     const char *repos_root_url,
-                     const char *commit_relpath,
-                     svn_boolean_t copy_mode_root,
+                     const char *copy_mode_relpath,
                      svn_depth_t depth,
                      svn_boolean_t just_locked,
                      apr_hash_t *changelists,
-                     svn_boolean_t skip_files,
-                     svn_boolean_t skip_dirs,
-                     svn_boolean_t is_explicit_target,
                      apr_hash_t *danglers,
                      svn_client__check_url_kind_t check_url_func,
                      void *check_url_baton,
@@ -450,38 +400,221 @@ harvest_committables(const char *local_a
                      void *cancel_baton,
                      svn_wc_notify_func2_t notify_func,
                      void *notify_baton,
-                     svn_client_ctx_t *ctx,
+                     svn_wc_context_t *wc_ctx,
                      apr_pool_t *result_pool,
                      apr_pool_t *scratch_pool)
 {
-  svn_wc_context_t *wc_ctx = ctx->wc_ctx;
-  svn_boolean_t text_mod = FALSE;
-  svn_boolean_t prop_mod = FALSE;
+  struct harvest_baton baton;
+
+  baton.root_abspath = local_abspath;
+  baton.committables = committables;
+  baton.lock_tokens = lock_tokens;
+  baton.commit_relpath = copy_mode_relpath;
+  baton.depth = depth;
+  baton.just_locked = just_locked;
+  baton.changelists = changelists;
+  baton.danglers = danglers;
+  baton.check_url_func = check_url_func;
+  baton.check_url_baton = check_url_baton;
+  baton.notify_func = notify_func;
+  baton.notify_baton = notify_baton;
+  baton.wc_ctx = wc_ctx;
+  baton.result_pool = result_pool;
+
+  baton.skip_below_abspath = NULL;
+
+  SVN_ERR(svn_wc_walk_status(wc_ctx,
+                             local_abspath,
+                             depth,
+                             (copy_mode_relpath != NULL) /* get_all */,
+                             FALSE /* no_ignore */,
+                             FALSE /* ignore_text_mods */,
+                             NULL /* ignore_patterns */,
+                             harvest_status_callback,
+                             &baton,
+                             cancel_func, cancel_baton,
+                             scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+harvest_not_present_for_copy(svn_wc_context_t *wc_ctx,
+                             const char *local_abspath,
+                             svn_client__committables_t *committables,
+                             const char *repos_root_url,
+                             const char *commit_relpath,
+                             svn_client__check_url_kind_t check_url_func,
+                             void *check_url_baton,
+                             apr_pool_t *result_pool,
+                             apr_pool_t *scratch_pool)
+{
+  const apr_array_header_t *children;
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  int i;
+
+  /* A function to retrieve not present children would be nice to have */
+  SVN_ERR(svn_wc__node_get_children_of_working_node(
+                                    &children, wc_ctx, local_abspath, TRUE,
+                                    scratch_pool, iterpool));
+      
+  for (i = 0; i < children->nelts; i++)
+    {
+      const char *this_abspath = APR_ARRAY_IDX(children, i, const char *);
+      const char *name = svn_dirent_basename(this_abspath, NULL);
+      const char *this_commit_relpath;
+      svn_boolean_t not_present;
+      svn_node_kind_t kind;
+
+      svn_pool_clear(iterpool);
+
+      SVN_ERR(svn_wc__node_is_status_not_present(&not_present, wc_ctx,
+                                                  this_abspath, scratch_pool));
+
+      if (!not_present)
+        continue;
+
+      if (commit_relpath == NULL)
+        this_commit_relpath = NULL;
+      else
+        this_commit_relpath = svn_relpath_join(commit_relpath, name,
+                                              iterpool);
+
+      /* We should check if we should really add a delete operation */
+      if (check_url_func)
+        {
+          svn_revnum_t parent_rev;
+          const char *parent_repos_relpath;
+          const char *parent_repos_root_url;
+          const char *node_url;
+
+          /* Determine from what parent we would be the deleted child */
+          SVN_ERR(svn_wc__node_get_origin(
+                              NULL, &parent_rev, &parent_repos_relpath,
+                              &parent_repos_root_url, NULL, NULL,
+                              wc_ctx,
+                              svn_dirent_dirname(this_abspath,
+                                                  scratch_pool),
+                              FALSE, scratch_pool, scratch_pool));
+
+          node_url = svn_path_url_add_component2(
+                        svn_path_url_add_component2(parent_repos_root_url,
+                                                    parent_repos_relpath,
+                                                    scratch_pool),
+                        svn_dirent_basename(this_abspath, NULL),
+                        iterpool);
+
+          SVN_ERR(check_url_func(check_url_baton, &kind,
+                                 node_url, parent_rev, iterpool));
+
+          if (kind == svn_node_none)
+            continue; /* This node can't be deleted */
+        }
+      else
+        SVN_ERR(svn_wc_read_kind(&kind, wc_ctx, this_abspath, TRUE,
+                                 scratch_pool));
+
+      SVN_ERR(add_committable(committables, this_abspath, kind,
+                              repos_root_url,
+                              this_commit_relpath,
+                              SVN_INVALID_REVNUM,
+                              NULL /* copyfrom_relpath */,
+                              SVN_INVALID_REVNUM /* copyfrom_rev */,
+                              SVN_CLIENT_COMMIT_ITEM_DELETE,
+                              result_pool, scratch_pool));
+    }
+
+  svn_pool_destroy(iterpool);
+  return SVN_NO_ERROR;
+}
+
+/* Implements svn_wc_status_func4_t */
+static svn_error_t *
+harvest_status_callback(void *status_baton,
+                        const char *local_abspath,
+                        const svn_wc_status3_t *status,
+                        apr_pool_t *scratch_pool)
+{
   apr_byte_t state_flags = 0;
-  svn_node_kind_t working_kind;
-  svn_node_kind_t db_kind;
-  const char *node_relpath;
-  const char *node_lock_token;
   svn_revnum_t node_rev;
   const char *cf_relpath = NULL;
   svn_revnum_t cf_rev = SVN_INVALID_REVNUM;
   svn_boolean_t matches_changelists;
-  svn_boolean_t is_special;
   svn_boolean_t is_added;
   svn_boolean_t is_deleted;
   svn_boolean_t is_replaced;
-  svn_boolean_t is_not_present;
-  svn_boolean_t is_excluded;
   svn_boolean_t is_op_root;
-  svn_boolean_t is_symlink;
-  svn_boolean_t conflicted;
-  const char *node_changelist;
   svn_boolean_t is_update_root;
   svn_revnum_t original_rev;
   const char *original_relpath;
-  svn_boolean_t copy_mode = (commit_relpath != NULL);
+  svn_boolean_t copy_mode;
+
+  struct harvest_baton *baton = status_baton;
+  svn_boolean_t is_harvest_root = 
+                (strcmp(baton->root_abspath, local_abspath) == 0);
+  svn_client__committables_t *committables = baton->committables;
+  apr_hash_t *lock_tokens = baton->lock_tokens;
+  const char *repos_root_url = status->repos_root_url;
+  const char *commit_relpath = NULL;
+  svn_boolean_t copy_mode_root = (baton->commit_relpath && is_harvest_root);
+  svn_boolean_t just_locked = baton->just_locked;
+  apr_hash_t *changelists = baton->changelists;
+  apr_hash_t *danglers = baton->danglers;
+  svn_wc_notify_func2_t notify_func = baton->notify_func;
+  void *notify_baton = baton->notify_baton;
+  svn_wc_context_t *wc_ctx = baton->wc_ctx;
+  apr_pool_t *result_pool = baton->result_pool;
+
+  if (baton->commit_relpath)
+    commit_relpath = svn_relpath_join(
+                        baton->commit_relpath,
+                        svn_dirent_skip_ancestor(baton->root_abspath,
+                                                 local_abspath),
+                        scratch_pool);
+
+  copy_mode = (commit_relpath != NULL);
+
+  if (baton->skip_below_abspath
+      && svn_dirent_is_ancestor(baton->skip_below_abspath, local_abspath))
+    {
+      return SVN_NO_ERROR;
+    }
+  else
+    baton->skip_below_abspath = NULL; /* We have left the skip tree */
 
-  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+  /* Return early for nodes that don't have a committable status */
+  switch (status->node_status)
+    {
+      case svn_wc_status_unversioned:
+      case svn_wc_status_ignored:
+      case svn_wc_status_external:
+      case svn_wc_status_none:
+        /* Unversioned nodes aren't committable, but are reported by the status
+           walker.
+           But if the unversioned node is the root of the walk, we have a user
+           error */
+        if (is_harvest_root)
+          return svn_error_createf(
+                       SVN_ERR_ILLEGAL_TARGET, NULL,
+                       _("'%s' is not under version control"),
+                       svn_dirent_local_style(local_abspath, scratch_pool));
+        return SVN_NO_ERROR;
+      case svn_wc_status_normal:
+        /* Status normal nodes aren't modified, so we don't have to commit them
+           when we perform a normal commit. But if a node is conflicted we want
+           to stop the commit and if we are collecting lock tokens we want to
+           look further anyway.
+
+           When in copy mode we need to compare the revision of the node against
+           the parent node to copy mixed-revision base nodes properly */
+        if (!copy_mode && !status->conflicted
+            && !(just_locked && status->lock))
+          return SVN_NO_ERROR;
+        break;
+      default:
+        /* Fall through */
+        break;
+    }
 
   /* Early out if the item is already marked as committable. */
   if (look_up_committable(committables, local_abspath, scratch_pool))
@@ -492,74 +625,71 @@ harvest_committables(const char *local_a
   SVN_ERR_ASSERT((copy_mode_root && copy_mode) || ! copy_mode_root);
   SVN_ERR_ASSERT((just_locked && lock_tokens) || !just_locked);
 
-  if (cancel_func)
-    SVN_ERR(cancel_func(cancel_baton));
-
-  /* Return error on unknown path kinds.  We check both the entry and
-     the node itself, since a path might have changed kind since its
-     entry was written. */
-  SVN_ERR(svn_wc__node_get_commit_status(&db_kind, &is_added, &is_deleted,
-                                         &is_replaced,
-                                         &is_not_present, &is_excluded,
-                                         &is_op_root, &is_symlink,
-                                         &node_rev, &node_relpath,
-                                         &original_rev, &original_relpath,
-                                         &conflicted,
-                                         &node_changelist,
-                                         &prop_mod, &is_update_root,
-                                         &node_lock_token,
-                                         wc_ctx, local_abspath,
-                                         scratch_pool, scratch_pool));
-
-  if ((skip_files && db_kind == svn_node_file) || is_excluded)
-    return SVN_NO_ERROR;
-
-  if (!node_relpath && commit_relpath)
-    node_relpath = commit_relpath;
-
-  SVN_ERR(svn_io_check_special_path(local_abspath, &working_kind, &is_special,
-                                    scratch_pool));
-
-  /* ### In 1.6 an obstructed dir would fail when locking before we
-         got here.  Locking now doesn't fail so perhaps we should do
-         some sort of checking here. */
-
-  if ((working_kind != svn_node_file)
-      && (working_kind != svn_node_dir)
-      && (working_kind != svn_node_none))
-    {
-      return svn_error_createf
-        (SVN_ERR_NODE_UNKNOWN_KIND, NULL,
-         _("Unknown entry kind for '%s'"),
-         svn_dirent_local_style(local_abspath, scratch_pool));
-    }
-
   /* Save the result for reuse. */
   matches_changelists = ((changelists == NULL)
-                         || (node_changelist != NULL
-                             && apr_hash_get(changelists, node_changelist,
+                         || (status->changelist != NULL
+                             && apr_hash_get(changelists, status->changelist,
                                              APR_HASH_KEY_STRING) != NULL));
 
   /* Early exit. */
-  if (working_kind != svn_node_dir && working_kind != svn_node_none
-      && ! matches_changelists)
+  if (status->kind != svn_node_dir && ! matches_changelists)
     {
       return SVN_NO_ERROR;
     }
 
-  /* Verify that the node's type has not changed before attempting to
-     commit. */
-  if ((((!is_symlink) && (is_special))
-#ifdef HAVE_SYMLINK
-       || (is_symlink && (! is_special))
-#endif /* HAVE_SYMLINK */
-       ) && (working_kind != svn_node_none))
-    {
-      return svn_error_createf
-        (SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
-         _("Entry '%s' has unexpectedly changed special status"),
-         svn_dirent_local_style(local_abspath, scratch_pool));
+  /* If NODE is in our changelist, then examine it for conflicts. We
+     need to bail out if any conflicts exist.
+     The status walker checked for conflict marker removal. */
+  if (status->conflicted && matches_changelists)
+    {
+      if (notify_func != NULL)
+        {
+          notify_func(notify_baton,
+                      svn_wc_create_notify(local_abspath,
+                                           svn_wc_notify_failed_conflict,
+                                           scratch_pool),
+                      scratch_pool);
+        }
+
+      return svn_error_createf(
+            SVN_ERR_WC_FOUND_CONFLICT, NULL,
+            _("Aborting commit: '%s' remains in conflict"),
+            svn_dirent_local_style(local_abspath, scratch_pool));
     }
+  else if (status->node_status == svn_wc_status_obstructed)
+    {
+      /* A node's type has changed before attempting to commit.
+         This also catches symlink vs non symlink changes */
+
+      if (notify_func != NULL)
+        {
+          notify_func(notify_baton,
+                      svn_wc_create_notify(local_abspath,
+                                           svn_wc_notify_failed_obstruction,
+                                           scratch_pool),
+                      scratch_pool);
+        }
+
+      return svn_error_createf(
+                    SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
+                    _("Node '%s' has unexpectedly changed kind"),
+                    svn_dirent_local_style(local_abspath, scratch_pool));
+    }
+
+  if (status->conflicted && status->kind == svn_node_unknown)
+    return SVN_NO_ERROR; /* Ignore delete-delete conflict */
+
+  /* Return error on unknown path kinds.  We check both the entry and
+     the node itself, since a path might have changed kind since its
+     entry was written. */
+  SVN_ERR(svn_wc__node_get_commit_status(&is_added, &is_deleted,
+                                         &is_replaced,
+                                         &is_op_root,
+                                         &node_rev,
+                                         &original_rev, &original_relpath,
+                                         &is_update_root,
+                                         wc_ctx, local_abspath,
+                                         scratch_pool, scratch_pool));
 
   /* Handle file externals.
    * (IS_UPDATE_ROOT is more generally defined, but at the moment this
@@ -568,54 +698,42 @@ harvest_committables(const char *local_a
    * Don't copy files that svn:externals brought into the WC. So in copy_mode,
    * even explicit targets are skipped.
    *
-   * Exclude file externals from recursion. Hande file externals only when
-   * passed as explicit target. Note that svn_client_commit6() passes all
-   * committable externals in as explicit targets iff they count.
-   *
-   * Also note that dir externals will never be reached recursively by this
-   * function, since svn_wc__node_get_children_of_working_node() (used below
-   * to recurse) does not return switched subdirs. */
+   * Hande file externals only when passed as explicit target. Note that
+   * svn_client_commit6() passes all committable externals in as explicit
+   * targets iff they count.
+   */
   if (is_update_root
-      && db_kind == svn_node_file
-      && (copy_mode
-          || ! is_explicit_target))
+      && status->kind == svn_node_file
+      && (copy_mode || ! is_harvest_root))
     {
       return SVN_NO_ERROR;
     }
 
-  /* If NODE is in our changelist, then examine it for conflicts. We
-     need to bail out if any conflicts exist.  */
-  if (conflicted && matches_changelists)
+  if (status->node_status == svn_wc_status_missing && matches_changelists)
     {
-      svn_boolean_t tc, pc, treec;
-
-      SVN_ERR(svn_wc_conflicted_p3(&tc, &pc, &treec, wc_ctx,
-                                   local_abspath, scratch_pool));
-      if (tc || pc || treec)
+      /* Added files and directories must exist. See issue #3198. */
+      if (is_added && is_op_root)
         {
           if (notify_func != NULL)
             {
               notify_func(notify_baton,
                           svn_wc_create_notify(local_abspath,
-                                               svn_wc_notify_failed_conflict,
+                                               svn_wc_notify_failed_missing,
                                                scratch_pool),
                           scratch_pool);
             }
-
           return svn_error_createf(
-            SVN_ERR_WC_FOUND_CONFLICT, NULL,
-            _("Aborting commit: '%s' remains in conflict"),
-            svn_dirent_local_style(local_abspath, scratch_pool));
+             SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+             _("'%s' is scheduled for addition, but is missing"),
+             svn_dirent_local_style(local_abspath, scratch_pool));
         }
+
+      return SVN_NO_ERROR;
     }
 
   if (is_deleted && !is_op_root /* && !is_added */)
     return SVN_NO_ERROR; /* Not an operational delete and not an add. */
 
-  if (node_relpath == NULL)
-    SVN_ERR(svn_wc__node_get_repos_relpath(&node_relpath,
-                                           wc_ctx, local_abspath,
-                                           scratch_pool, scratch_pool));
   /* Check for the deletion case.
      * We delete explicitly deleted nodes (duh!)
      * We delete not-present children of copies
@@ -624,36 +742,6 @@ harvest_committables(const char *local_a
 
   if (is_deleted || is_replaced)
     state_flags |= SVN_CLIENT_COMMIT_ITEM_DELETE;
-  else if (is_not_present)
-    {
-      if (! copy_mode)
-        return SVN_NO_ERROR;
-
-      /* We should check if we should really add a delete operation */
-      if (check_url_func)
-        {
-          svn_client__pathrev_t *origin;
-          const char *repos_url;
-          svn_node_kind_t kind;
-
-          /* Determine from what parent we would be the deleted child */
-          SVN_ERR(svn_client__wc_node_get_origin(
-                    &origin, svn_dirent_dirname(local_abspath, scratch_pool),
-                    ctx, scratch_pool, scratch_pool));
-
-          repos_url = svn_path_url_add_component2(
-                        origin->url, svn_dirent_basename(local_abspath, NULL),
-                        scratch_pool);
-
-          SVN_ERR(check_url_func(check_url_baton, &kind, repos_url, origin->rev,
-                                 scratch_pool));
-
-          if (kind == svn_node_none)
-            return SVN_NO_ERROR; /* This node can't be deleted */
-        }
-
-      state_flags |= SVN_CLIENT_COMMIT_ITEM_DELETE;
-    }
 
   /* Check for adds and copies */
   if (is_added && is_op_root)
@@ -670,95 +758,70 @@ harvest_committables(const char *local_a
         }
     }
 
-  /* Further additions occur in copy mode. */
-  if (copy_mode
-      && (!is_added || copy_mode_root)
-      && !(state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE))
+  /* Further copies may occur in copy mode. */
+  else if (copy_mode
+           && !(state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE))
     {
       svn_revnum_t dir_rev;
 
-      if (!copy_mode_root)
+      if (!copy_mode_root && !status->switched)
         SVN_ERR(svn_wc__node_get_base(&dir_rev, NULL, NULL, NULL, wc_ctx,
                                       svn_dirent_dirname(local_abspath,
                                                          scratch_pool),
                                       scratch_pool, scratch_pool));
 
-      if (copy_mode_root || node_rev != dir_rev)
+      if (copy_mode_root || status->switched || node_rev != dir_rev)
         {
-          state_flags |= SVN_CLIENT_COMMIT_ITEM_ADD;
-
-          SVN_ERR(svn_wc__node_get_origin(NULL, &cf_rev,
-                                      &cf_relpath, NULL,
-                                      NULL, NULL,
-                                      wc_ctx, local_abspath, FALSE,
-                                      scratch_pool, scratch_pool));
+          state_flags |= (SVN_CLIENT_COMMIT_ITEM_ADD
+                          | SVN_CLIENT_COMMIT_ITEM_IS_COPY);
 
-          if (cf_relpath)
-            state_flags |= SVN_CLIENT_COMMIT_ITEM_IS_COPY;
+          if (status->copied)
+            {
+              /* Copy from original location */
+              cf_rev = original_rev;
+              cf_relpath = original_relpath;
+            }
+          else
+            {
+              /* Copy BASE location, to represent a mixed-rev or switch copy */
+              cf_rev = status->revision;
+              cf_relpath = status->repos_relpath;
+            }
         }
     }
 
-  /* If an add is scheduled to occur, dig around for some more
-     information about it. */
-  if (state_flags & SVN_CLIENT_COMMIT_ITEM_ADD)
+  if (!(state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE)
+      || (state_flags & SVN_CLIENT_COMMIT_ITEM_ADD))
     {
-      /* First of all, the working file or directory must exist.
-         See issue #3198. */
-      if (working_kind == svn_node_none)
+      svn_boolean_t text_mod = FALSE;
+      svn_boolean_t prop_mod = FALSE;
+
+      if (status->kind == svn_node_file)
         {
-          if (notify_func != NULL)
+          /* Check for text modifications on files */
+          if ((state_flags & SVN_CLIENT_COMMIT_ITEM_ADD)
+              && ! (state_flags & SVN_CLIENT_COMMIT_ITEM_IS_COPY))
             {
-              notify_func(notify_baton,
-                          svn_wc_create_notify(local_abspath,
-                                               svn_wc_notify_failed_missing,
-                                               scratch_pool),
-                          scratch_pool);
+              text_mod = TRUE; /* Local added files are always modified */
             }
-          return svn_error_createf(
-             SVN_ERR_WC_PATH_NOT_FOUND, NULL,
-             _("'%s' is scheduled for addition, but is missing"),
-             svn_dirent_local_style(local_abspath, scratch_pool));
-        }
-
-      /* Regular adds of files have text mods, but for copies we have
-         to test for textual mods.  Directories simply don't have text! */
-      if (db_kind == svn_node_file)
-        {
-          /* Check for text mods.  */
-          if (state_flags & SVN_CLIENT_COMMIT_ITEM_IS_COPY)
-            SVN_ERR(svn_wc_text_modified_p2(&text_mod, wc_ctx, local_abspath,
-                                            FALSE, scratch_pool));
           else
-            text_mod = TRUE;
+            text_mod = (status->text_status != svn_wc_status_normal);
         }
-    }
 
-  /* Else, if we aren't deleting this item, we'll have to look for
-     local text or property mods to determine if the path might be
-     committable. */
-  else if (! (state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE))
-    {
-      /* Check for text mods on files.  If EOL_PROP_CHANGED is TRUE,
-         then we need to force a translated byte-for-byte comparison
-         against the text-base so that a timestamp comparison won't
-         bail out early.  Depending on how the svn:eol-style prop was
-         changed, we might have to send new text to the server to
-         match the new newline style.  */
-      if (db_kind == svn_node_file)
-        SVN_ERR(svn_wc_text_modified_p2(&text_mod, wc_ctx, local_abspath,
-                                        FALSE, scratch_pool));
-    }
-
-  /* Set text/prop modification flags accordingly. */
-  if (text_mod)
-    state_flags |= SVN_CLIENT_COMMIT_ITEM_TEXT_MODS;
-  if (prop_mod)
-    state_flags |= SVN_CLIENT_COMMIT_ITEM_PROP_MODS;
+      prop_mod = (status->prop_status != svn_wc_status_normal
+                  && status->prop_status != svn_wc_status_none);
+
+      /* Set text/prop modification flags accordingly. */
+      if (text_mod)
+        state_flags |= SVN_CLIENT_COMMIT_ITEM_TEXT_MODS;
+      if (prop_mod)
+        state_flags |= SVN_CLIENT_COMMIT_ITEM_PROP_MODS;
+    }
 
   /* If the entry has a lock token and it is already a commit candidate,
      or the caller wants unmodified locked items to be treated as
      such, note this fact. */
-  if (node_lock_token && lock_tokens && (state_flags || just_locked))
+  if (status->lock && lock_tokens && (state_flags || just_locked))
     {
       state_flags |= SVN_CLIENT_COMMIT_ITEM_LOCK_TOKEN;
     }
@@ -769,11 +832,12 @@ harvest_committables(const char *local_a
       if (matches_changelists)
         {
           /* Finally, add the committable item. */
-          SVN_ERR(add_committable(committables, local_abspath, db_kind,
+          SVN_ERR(add_committable(committables, local_abspath,
+                                  status->kind,
                                   repos_root_url,
                                   copy_mode
                                       ? commit_relpath
-                                      : node_relpath,
+                                      : status->repos_relpath,
                                   copy_mode
                                       ? SVN_INVALID_REVNUM
                                       : node_rev,
@@ -784,11 +848,11 @@ harvest_committables(const char *local_a
           if (state_flags & SVN_CLIENT_COMMIT_ITEM_LOCK_TOKEN)
             apr_hash_set(lock_tokens,
                          svn_path_url_add_component2(
-                             repos_root_url, node_relpath,
-                             apr_hash_pool_get(lock_tokens)),
+                             repos_root_url, status->repos_relpath,
+                             result_pool),
                          APR_HASH_KEY_STRING,
-                         apr_pstrdup(apr_hash_pool_get(lock_tokens),
-                                     node_lock_token));
+                         apr_pstrdup(result_pool,
+                                     status->lock->token));
         }
     }
 
@@ -820,7 +884,7 @@ harvest_committables(const char *local_a
     }
 
   /* Make sure we check for dangling children on additions */
-  if (state_flags && is_added && is_explicit_target && danglers)
+  if (state_flags && is_added && is_harvest_root && danglers)
     {
       /* If a node is added, it's parent must exist in the repository at the
          time of committing */
@@ -858,63 +922,26 @@ harvest_committables(const char *local_a
         }
     }
 
-  if (db_kind != svn_node_dir || depth <= svn_depth_empty)
-    return SVN_NO_ERROR;
-
-  SVN_ERR(bail_on_tree_conflicted_children(wc_ctx, local_abspath,
-                                           db_kind, depth, changelists,
-                                           notify_func, notify_baton,
-                                           scratch_pool));
-
-  /* Recursively handle each node according to depth, except when the
-     node is only being deleted. */
-  if ((! (state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE))
-      || (state_flags & SVN_CLIENT_COMMIT_ITEM_ADD))
+  if ((state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE)
+      && !(state_flags & SVN_CLIENT_COMMIT_ITEM_ADD))
     {
-      const apr_array_header_t *children;
-      apr_pool_t *iterpool = svn_pool_create(scratch_pool);
-      int i;
-      svn_depth_t depth_below_here = depth;
-
-      if (depth < svn_depth_infinity)
-        depth_below_here = svn_depth_empty; /* Stop recursing */
-
-      SVN_ERR(svn_wc__node_get_children_of_working_node(
-                &children, wc_ctx, local_abspath, copy_mode,
-                scratch_pool, iterpool));
-      for (i = 0; i < children->nelts; i++)
-        {
-          const char *this_abspath = APR_ARRAY_IDX(children, i, const char *);
-          const char *name = svn_dirent_basename(this_abspath, NULL);
-          const char *this_commit_relpath;
-
-          svn_pool_clear(iterpool);
-
-          if (commit_relpath == NULL)
-            this_commit_relpath = NULL;
-          else
-            this_commit_relpath = svn_relpath_join(commit_relpath, name,
-                                                   iterpool);
-
-          SVN_ERR(harvest_committables(this_abspath,
-                                       committables, lock_tokens,
-                                       repos_root_url,
-                                       this_commit_relpath,
-                                       FALSE, /* COPY_MODE_ROOT */
-                                       depth_below_here,
-                                       just_locked,
-                                       changelists,
-                                       (depth < svn_depth_files),
-                                       (depth < svn_depth_immediates),
-                                       FALSE, /* IS_EXPLICIT_TARGET */
-                                       danglers,
-                                       check_url_func, check_url_baton,
-                                       cancel_func, cancel_baton,
-                                       notify_func, notify_baton,
-                                       ctx, result_pool, iterpool));
-        }
+      /* Skip all descendants */
+      if (status->kind == svn_node_dir)
+        baton->skip_below_abspath = apr_pstrdup(baton->result_pool,
+                                                local_abspath);
+      return SVN_NO_ERROR;
+    }
 
-      svn_pool_destroy(iterpool);
+  /* Recursively handle each node according to depth, except when the
+     node is only being deleted, or is in an added tree (as added trees
+     use the normal commit handling). */
+  if (copy_mode && !is_added && !is_deleted && status->kind == svn_node_dir)
+    {
+      SVN_ERR(harvest_not_present_for_copy(wc_ctx, local_abspath, committables,
+                                           repos_root_url, commit_relpath,
+                                           baton->check_url_func,
+                                           baton->check_url_baton,
+                                           result_pool, scratch_pool));
     }
 
   return SVN_NO_ERROR;
@@ -1062,7 +1089,6 @@ svn_client__harvest_committables(svn_cli
   int i;
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
   apr_hash_t *changelist_hash = NULL;
-  svn_wc_context_t *wc_ctx = ctx->wc_ctx;
   struct handle_descendants_baton hdb;
   apr_hash_index_t *hi;
 
@@ -1107,8 +1133,6 @@ svn_client__harvest_committables(svn_cli
   for (i = 0; i < targets->nelts; ++i)
     {
       const char *target_abspath;
-      svn_node_kind_t kind;
-      const char *repos_root_url;
 
       svn_pool_clear(iterpool);
 
@@ -1117,34 +1141,6 @@ svn_client__harvest_committables(svn_cli
                                        APR_ARRAY_IDX(targets, i, const char *),
                                        iterpool);
 
-      SVN_ERR(svn_wc_read_kind(&kind, wc_ctx, target_abspath,
-                               FALSE, /* show_hidden */
-                               iterpool));
-      if (kind == svn_node_none)
-        {
-          /* If a target of the commit is a tree-conflicted node that
-           * has no entry (e.g. locally deleted), issue a proper tree-
-           * conflicts error instead of a "not under version control". */
-          const svn_wc_conflict_description2_t *conflict;
-          SVN_ERR(svn_wc__get_tree_conflict(&conflict, wc_ctx, target_abspath,
-                                            iterpool, iterpool));
-          if (conflict != NULL)
-            return svn_error_createf(
-                       SVN_ERR_WC_FOUND_CONFLICT, NULL,
-                       _("Aborting commit: '%s' remains in conflict"),
-                       svn_dirent_local_style(conflict->local_abspath,
-                                              iterpool));
-          else
-            return svn_error_createf(
-                       SVN_ERR_ILLEGAL_TARGET, NULL,
-                       _("'%s' is not under version control"),
-                       svn_dirent_local_style(target_abspath, iterpool));
-        }
-
-      SVN_ERR(svn_wc__node_get_repos_info(&repos_root_url, NULL, wc_ctx,
-                                          target_abspath,
-                                          result_pool, iterpool));
-
       /* Handle our TARGET. */
       /* Make sure this isn't inside a working copy subtree that is
        * marked as tree-conflicted. */
@@ -1155,17 +1151,13 @@ svn_client__harvest_committables(svn_cli
 
       SVN_ERR(harvest_committables(target_abspath,
                                    *committables, *lock_tokens,
-                                   repos_root_url,
-                                   NULL /* COMMIT_RELPATH */,
-                                   FALSE /* COPY_MODE_ROOT */,
+                                   NULL /* COPY_MODE_RELPATH */,
                                    depth, just_locked, changelist_hash,
-                                   FALSE, FALSE,
-                                   TRUE /* IS_EXPLICIT_TARGET */,
                                    danglers,
                                    check_url_func, check_url_baton,
                                    ctx->cancel_func, ctx->cancel_baton,
                                    ctx->notify_func2, ctx->notify_baton2,
-                                   ctx, result_pool, iterpool));
+                                   ctx->wc_ctx, result_pool, iterpool));
     }
 
   hdb.wc_ctx = ctx->wc_ctx;
@@ -1247,14 +1239,10 @@ harvest_copy_committables(void *baton, v
   /* Handle this SRC. */
   SVN_ERR(harvest_committables(pair->src_abspath_or_url,
                                btn->committables, NULL,
-                               repos_root_url,
                                commit_relpath,
-                               TRUE,  /* COPY_MODE_ROOT */
                                svn_depth_infinity,
                                FALSE,  /* JUST_LOCKED */
-                               NULL,
-                               FALSE, FALSE, /* skip files, dirs */
-                               TRUE, /* IS_EXPLICIT_TARGET (don't care) */
+                               NULL /* changelists */,
                                NULL,
                                btn->check_url_func,
                                btn->check_url_baton,
@@ -1262,7 +1250,7 @@ harvest_copy_committables(void *baton, v
                                btn->ctx->cancel_baton,
                                btn->ctx->notify_func2,
                                btn->ctx->notify_baton2,
-                               btn->ctx, btn->result_pool, pool));
+                               btn->ctx->wc_ctx, btn->result_pool, pool));
 
   hdb.wc_ctx = btn->ctx->wc_ctx;
   hdb.cancel_func = btn->ctx->cancel_func;

Modified: subversion/branches/ev2-export/subversion/libsvn_client/externals.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/externals.c?rev=1338209&r1=1338208&r2=1338209&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/externals.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/externals.c Mon May 14 14:07:45 2012
@@ -313,9 +313,6 @@ switch_file_external(const char *local_a
                      const svn_opt_revision_t *revision,
                      const char *def_dir_abspath,
                      svn_ra_session_t *ra_session,
-                     const char *ra_session_url,
-                     svn_revnum_t ra_revnum,
-                     const char *repos_root_url,
                      svn_boolean_t *timestamp_sleep,
                      svn_client_ctx_t *ctx,
                      apr_pool_t *scratch_pool)
@@ -437,8 +434,7 @@ switch_file_external(const char *local_a
     void *report_baton;
     const svn_delta_editor_t *switch_editor;
     void *switch_baton;
-    const char *switch_rev_url;
-    const char *repos_uuid;
+    svn_client__pathrev_t *switch_loc;
     svn_revnum_t revnum;
     /* ### TODO: Provide the real definition path (now available in
        ### def_dir_abspath) after switching to the new externals store.
@@ -447,22 +443,20 @@ switch_file_external(const char *local_a
     const char *definition_abspath = svn_dirent_dirname(local_abspath,subpool);
 
     /* Open an RA session to 'source' URL */
-    SVN_ERR(svn_client__ra_session_from_path(&ra_session, &revnum,
-                                             &switch_rev_url,
-                                             url, dir_abspath,
-                                             peg_revision, revision,
-                                             ctx, subpool));
+    SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &switch_loc,
+                                              url, dir_abspath,
+                                              peg_revision, revision,
+                                              ctx, subpool));
 
     SVN_ERR(svn_ra_reparent(ra_session, url, subpool));
-    SVN_ERR(svn_ra_get_uuid2(ra_session, &repos_uuid, subpool));
 
     SVN_ERR(svn_wc__get_file_external_editor(&switch_editor, &switch_baton,
                                              &revnum, ctx->wc_ctx,
                                              local_abspath,
                                              definition_abspath /* wri */,
-                                             switch_rev_url,
-                                             repos_root_url,
-                                             repos_uuid,
+                                             switch_loc->url,
+                                             switch_loc->repos_root_url,
+                                             switch_loc->repos_uuid,
                                              use_commit_times,
                                              diff3_cmd, preserved_exts,
                                              definition_abspath /* def */,
@@ -477,16 +471,17 @@ switch_file_external(const char *local_a
 
     /* 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,
-                            target, svn_depth_unknown, url,
-                            switch_editor, switch_baton, subpool));
-
-  SVN_ERR(svn_wc__crawl_file_external(ctx->wc_ctx, local_abspath,
-                                      reporter, report_baton,
-                                      TRUE,  use_commit_times,
-                                      ctx->cancel_func, ctx->cancel_baton,
-                                      ctx->notify_func2, ctx->notify_baton2,
-                                      subpool));
+    SVN_ERR(svn_ra_do_switch2(ra_session, &reporter, &report_baton,
+                              switch_loc->rev,
+                              target, svn_depth_unknown, url,
+                              switch_editor, switch_baton, subpool));
+
+    SVN_ERR(svn_wc__crawl_file_external(ctx->wc_ctx, local_abspath,
+                                        reporter, report_baton,
+                                        TRUE,  use_commit_times,
+                                        ctx->cancel_func, ctx->cancel_baton,
+                                        ctx->notify_func2, ctx->notify_baton2,
+                                        subpool));
 
     if (ctx->notify_func2)
       {
@@ -603,10 +598,7 @@ handle_external_item_change(const struct
                             apr_pool_t *scratch_pool)
 {
   svn_ra_session_t *ra_session;
-  svn_revnum_t ra_revnum;
-  const char *ra_session_url;
-  const char *repos_root_url;
-  const char *repos_uuid;
+  svn_client__pathrev_t *new_loc;
   const char *new_url;
   svn_node_kind_t ext_kind;
 
@@ -627,29 +619,25 @@ handle_external_item_change(const struct
 
   /* Determine if the external is a file or directory. */
   /* Get the RA connection. */
-  SVN_ERR(svn_client__ra_session_from_path(&ra_session,
-                                           &ra_revnum,
-                                           &ra_session_url,
-                                           new_url, NULL,
-                                           &(new_item->peg_revision),
-                                           &(new_item->revision), eb->ctx,
-                                           scratch_pool));
-
-  SVN_ERR(svn_ra_get_uuid2(ra_session, &repos_uuid, scratch_pool));
-  SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root_url, scratch_pool));
-  SVN_ERR(svn_ra_check_path(ra_session, "", ra_revnum, &ext_kind,
+  SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &new_loc,
+                                            new_url, NULL,
+                                            &(new_item->peg_revision),
+                                            &(new_item->revision), eb->ctx,
+                                            scratch_pool));
+
+  SVN_ERR(svn_ra_check_path(ra_session, "", new_loc->rev, &ext_kind,
                             scratch_pool));
 
   if (svn_node_none == ext_kind)
     return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
                              _("URL '%s' at revision %ld doesn't exist"),
-                             ra_session_url, ra_revnum);
+                             new_loc->url, new_loc->rev);
 
   if (svn_node_dir != ext_kind && svn_node_file != ext_kind)
     return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
                              _("URL '%s' at revision %ld is not a file "
                                "or a directory"),
-                             ra_session_url, ra_revnum);
+                             new_loc->url, new_loc->rev);
 
 
   /* Not protecting against recursive externals.  Detecting them in
@@ -687,7 +675,7 @@ handle_external_item_change(const struct
                                     scratch_pool));
         break;
       case svn_node_file:
-        if (strcmp(eb->repos_root_url, repos_root_url))
+        if (strcmp(eb->repos_root_url, new_loc->repos_root_url))
           {
             const char *local_repos_root_url;
             const char *local_repos_uuid;
@@ -707,11 +695,11 @@ handle_external_item_change(const struct
                                                 eb->ctx->wc_ctx,
                                                 parent_dir_abspath,
                                                 scratch_pool, scratch_pool));
-            ext_repos_relpath = svn_uri_skip_ancestor(repos_root_url,
+            ext_repos_relpath = svn_uri_skip_ancestor(new_loc->repos_root_url,
                                                       new_url, scratch_pool);
             if (local_repos_uuid == NULL || local_repos_root_url == NULL ||
                 ext_repos_relpath == NULL ||
-                strcmp(local_repos_uuid, repos_uuid) != 0)
+                strcmp(local_repos_uuid, new_loc->repos_uuid) != 0)
               return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
                         _("Unsupported external: URL of file external '%s' "
                           "is not in repository '%s'"),
@@ -720,16 +708,12 @@ handle_external_item_change(const struct
             new_url = svn_path_url_add_component2(local_repos_root_url,
                                                   ext_repos_relpath,
                                                   scratch_pool);
-            SVN_ERR(svn_client__ra_session_from_path(&ra_session,
-                                                     &ra_revnum,
-                                                     &ra_session_url,
-                                                     new_url,
-                                                     NULL,
-                                                     &(new_item->peg_revision),
-                                                     &(new_item->revision),
-                                                     eb->ctx, scratch_pool));
-            SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root_url,
-                                           scratch_pool));
+            SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &new_loc,
+                                                      new_url,
+                                                      NULL,
+                                                      &(new_item->peg_revision),
+                                                      &(new_item->revision),
+                                                      eb->ctx, scratch_pool));
           }
 
         SVN_ERR(switch_file_external(local_abspath,
@@ -738,9 +722,6 @@ handle_external_item_change(const struct
                                      &new_item->revision,
                                      parent_dir_abspath,
                                      ra_session,
-                                     ra_session_url,
-                                     ra_revnum,
-                                     repos_root_url,
                                      eb->timestamp_sleep, eb->ctx,
                                      scratch_pool));
         break;

Modified: subversion/branches/ev2-export/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/merge.c?rev=1338209&r1=1338208&r2=1338209&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/merge.c Mon May 14 14:07:45 2012
@@ -8431,18 +8431,18 @@ remove_noop_subtree_ranges(const merge_s
   return SVN_NO_ERROR;
 }
 
-/* Helper for do_merge() when the merge target is a directory.
-
-   Perform a merge of changes in SOURCE to the working copy path
+/* Perform a merge of changes in SOURCE to the working copy path
    TARGET_ABSPATH. Both URLs in SOURCE, and TARGET_ABSPATH all represent
    directories -- for the single file case, the caller should use
    do_file_merge().
 
-   MERGE_B is the merge_cmd_baton_t created by do_merge() that describes
-   the merge being performed.  If MERGE_B->sources_ancestral is set, then
+   MERGE_B describes the merge being performed.  As this function is for a
+   mergeinfo-aware merge, MERGE_B->sources_ancestral should be TRUE, and
    SOURCE->url1@rev1 must be a historical ancestor of SOURCE->url2@rev2, or
    vice-versa (see `MERGEINFO MERGE SOURCE NORMALIZATION' for more
-   requirements around SOURCE in this case).
+   requirements around SOURCE).
+
+   Mergeinfo changes will be recorded unless MERGE_B->dry_run is true.
 
    If mergeinfo is being recorded, SQUELCH_MERGEINFO_NOTIFICATIONS is FALSE,
    and MERGE_B->CTX->NOTIFY_FUNC2 is not NULL, then call
@@ -8469,15 +8469,15 @@ remove_noop_subtree_ranges(const merge_s
    meet one or more of the criteria described in get_mergeinfo_paths()).
 */
 static svn_error_t *
-do_directory_merge(svn_mergeinfo_catalog_t result_catalog,
-                   const merge_source_t *source,
-                   const char *target_abspath,
-                   svn_depth_t depth,
-                   svn_boolean_t squelch_mergeinfo_notifications,
-                   svn_boolean_t abort_on_conflicts,
-                   notification_receiver_baton_t *notify_b,
-                   merge_cmd_baton_t *merge_b,
-                   apr_pool_t *scratch_pool)
+do_mergeinfo_aware_dir_merge(svn_mergeinfo_catalog_t result_catalog,
+                             const merge_source_t *source,
+                             const char *target_abspath,
+                             svn_depth_t depth,
+                             svn_boolean_t squelch_mergeinfo_notifications,
+                             svn_boolean_t abort_on_conflicts,
+                             notification_receiver_baton_t *notify_b,
+                             merge_cmd_baton_t *merge_b,
+                             apr_pool_t *scratch_pool)
 {
   svn_error_t *err = SVN_NO_ERROR;
   svn_error_t *merge_conflict_err = SVN_NO_ERROR;
@@ -8496,23 +8496,6 @@ do_directory_merge(svn_mergeinfo_catalog
   svn_ra_session_t *ra_session;
   svn_client__merge_path_t *target_merge_path;
   svn_boolean_t is_rollback = (source->loc1->rev > source->loc2->rev);
-  const char *primary_url = is_rollback ? source->loc1->url : source->loc2->url;
-  svn_boolean_t honor_mergeinfo = HONOR_MERGEINFO(merge_b);
-
-  /* Note that this is not a single-file merge. */
-  notify_b->is_single_file_merge = FALSE;
-
-  /* Initialize NOTIFY_B->CHILDREN_WITH_MERGEINFO. See the comment
-     'THE CHILDREN_WITH_MERGEINFO ARRAY' at the start of this file. */
-  notify_b->children_with_mergeinfo =
-    apr_array_make(scratch_pool, 0, sizeof(svn_client__merge_path_t *));
-
-  /* If we are not honoring mergeinfo we can skip right to the
-     business of merging changes! */
-  if (!honor_mergeinfo)
-    return do_mergeinfo_unaware_dir_merge(source,
-                                          target_abspath, depth,
-                                          notify_b, merge_b, scratch_pool);
 
   /*** If we get here, we're dealing with related sources from the
        same repository as the target -- merge tracking might be
@@ -8550,7 +8533,7 @@ do_directory_merge(svn_mergeinfo_catalog
   range.end = source->loc2->rev;
   range.inheritable = TRUE;
 
-  if (honor_mergeinfo && !merge_b->reintegrate_merge)
+  if (!merge_b->reintegrate_merge)
     {
       svn_revnum_t new_range_start, start_rev;
       apr_pool_t *iterpool = svn_pool_create(scratch_pool);
@@ -8743,11 +8726,11 @@ do_directory_merge(svn_mergeinfo_catalog
   /* Record mergeinfo where appropriate.*/
   if (RECORD_MERGEINFO(merge_b))
     {
-      const char *mergeinfo_path;
+      const svn_client__pathrev_t *primary_loc
+        = is_rollback ? source->loc1 : source->loc2;
+      const char *mergeinfo_path
+        = svn_client__pathrev_fspath(primary_loc, scratch_pool);
 
-      /* ### Leaks merge_conflict_err */
-      SVN_ERR(svn_ra__get_fspath_relative_to_root(ra_session, &mergeinfo_path,
-                                                  primary_url, scratch_pool));
       err = record_mergeinfo_for_dir_merge(result_catalog,
                                            &range,
                                            mergeinfo_path,
@@ -8785,6 +8768,44 @@ do_directory_merge(svn_mergeinfo_catalog
   return svn_error_compose_create(err, merge_conflict_err);
 }
 
+/* Helper for do_merge() when the merge target is a directory.
+
+*/
+static svn_error_t *
+do_directory_merge(svn_mergeinfo_catalog_t result_catalog,
+                   const merge_source_t *source,
+                   const char *target_abspath,
+                   svn_depth_t depth,
+                   svn_boolean_t squelch_mergeinfo_notifications,
+                   svn_boolean_t abort_on_conflicts,
+                   notification_receiver_baton_t *notify_b,
+                   merge_cmd_baton_t *merge_b,
+                   apr_pool_t *scratch_pool)
+{
+  /* Note that this is not a single-file merge. */
+  notify_b->is_single_file_merge = FALSE;
+
+  /* Initialize NOTIFY_B->CHILDREN_WITH_MERGEINFO. See the comment
+     'THE CHILDREN_WITH_MERGEINFO ARRAY' at the start of this file. */
+  notify_b->children_with_mergeinfo =
+    apr_array_make(scratch_pool, 0, sizeof(svn_client__merge_path_t *));
+
+  /* If we are not honoring mergeinfo we can skip right to the
+     business of merging changes! */
+  if (HONOR_MERGEINFO(merge_b))
+    SVN_ERR(do_mergeinfo_aware_dir_merge(result_catalog,
+                                         source, target_abspath, depth,
+                                         squelch_mergeinfo_notifications,
+                                         abort_on_conflicts,
+                                         notify_b, merge_b, scratch_pool));
+  else
+    SVN_ERR(do_mergeinfo_unaware_dir_merge(source,
+                                           target_abspath, depth,
+                                           notify_b, merge_b, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
 /** Ensure that *RA_SESSION is opened to URL, either by reusing
  * *RA_SESSION if it is non-null and already opened to URL's
  * repository, or by allocating a new *RA_SESSION in POOL.
@@ -9098,7 +9119,7 @@ do_merge(apr_hash_t **modified_subtrees,
    to represent the changed mergeinfo.
 
    The merge is between SOURCE->url1@rev1 (in URL1_RA_SESSION1) and
-   SOURCE->url2@rev2 (in URL2_RA_SESSION2); YC_REV is their youngest
+   SOURCE->url2@rev2 (in URL2_RA_SESSION2); YCA is their youngest
    common ancestor.
    SAME_REPOS must be true if and only if the source URLs are in the same
    repository as the target working copy.  Other arguments are as in
@@ -9114,7 +9135,7 @@ merge_cousins_and_supplement_mergeinfo(c
                                        svn_ra_session_t *URL1_ra_session,
                                        svn_ra_session_t *URL2_ra_session,
                                        const merge_source_t *source,
-                                       svn_revnum_t yc_rev,
+                                       const svn_client__pathrev_t *yca,
                                        svn_boolean_t same_repos,
                                        svn_depth_t depth,
                                        svn_boolean_t ignore_ancestry,
@@ -9139,13 +9160,13 @@ merge_cousins_and_supplement_mergeinfo(c
 
   SVN_ERR(normalize_merge_sources_internal(
             &remove_sources, source->loc1,
-            svn_rangelist__initialize(source->loc1->rev, yc_rev, TRUE,
+            svn_rangelist__initialize(source->loc1->rev, yca->rev, TRUE,
                                       scratch_pool),
             URL1_ra_session, ctx, scratch_pool, subpool));
 
   SVN_ERR(normalize_merge_sources_internal(
             &add_sources, source->loc2,
-            svn_rangelist__initialize(yc_rev, source->loc2->rev, TRUE,
+            svn_rangelist__initialize(yca->rev, source->loc2->rev, TRUE,
                                       scratch_pool),
             URL2_ra_session, ctx, scratch_pool, subpool));
 
@@ -9535,7 +9556,7 @@ merge_locked(const char *source1,
                                                        ra_session1,
                                                        ra_session2,
                                                        &source,
-                                                       yca->rev,
+                                                       yca,
                                                        same_repos,
                                                        depth,
                                                        ignore_ancestry, force,
@@ -10790,7 +10811,7 @@ merge_reintegrate_locked(const char *sou
   err = merge_cousins_and_supplement_mergeinfo(target,
                                                target_ra_session,
                                                source_ra_session,
-                                               source, yc_ancestor->rev,
+                                               source, yc_ancestor,
                                                TRUE /* same_repos */,
                                                svn_depth_infinity,
                                                FALSE /* ignore_ancestry */,
@@ -11517,7 +11538,7 @@ do_symmetric_merge_locked(const svn_clie
 
       err = merge_cousins_and_supplement_mergeinfo(target,
                                                    ra_session, ra_session,
-                                                   &source, merge->yca->rev,
+                                                   &source, merge->yca,
                                                    TRUE /* same_repos */,
                                                    depth, ignore_ancestry,
                                                    force, record_only,

Modified: subversion/branches/ev2-export/subversion/libsvn_client/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/mergeinfo.c?rev=1338209&r1=1338208&r2=1338209&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/mergeinfo.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/mergeinfo.c Mon May 14 14:07:45 2012
@@ -1051,13 +1051,12 @@ 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);
+  const char *peg_url;
   svn_revnum_t peg_rev;
 
-  SVN_ERR(svn_client__ra_session_from_path(&ra_session, &peg_rev, &url,
+  SVN_ERR(svn_client__ra_session_from_path(&ra_session, &peg_rev, &peg_url,
                                            path_or_url, NULL, peg_revision,
                                            peg_revision, ctx, scratch_pool));
 
@@ -1071,10 +1070,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_url) != 0
+          || peg_rev != origin->rev)
       {
         use_url = TRUE; /* Don't rely on local mergeinfo */
       }
@@ -1088,9 +1086,8 @@ 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,
+        mergeinfo_catalog, ra_session, peg_url, peg_rev, svn_mergeinfo_inherited,
         FALSE, include_descendants,
         result_pool, scratch_pool));
     }

Modified: subversion/branches/ev2-export/subversion/libsvn_client/switch.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/switch.c?rev=1338209&r1=1338208&r2=1338209&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/switch.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/switch.c Mon May 14 14:07:45 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(&target_rev, NULL, NULL, NULL, ctx->wc_ctx,
-                                    local_abspath, pool, 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, 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, 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. */
@@ -229,11 +227,11 @@ switch_internal(svn_revnum_t *result_rev
 
   dfb.ra_session = ra_session;
   SVN_ERR(svn_ra_get_session_url(ra_session, &dfb.anchor_url, pool));
-  dfb.target_revision = revnum;
+  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/ev2-export/subversion/libsvn_client/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/update.c?rev=1338209&r1=1338208&r2=1338209&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/update.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/update.c Mon May 14 14:07:45 2012
@@ -191,11 +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_url;
-  const char *repos_relpath;
+  svn_client__pathrev_t *anchor_loc;
   svn_error_t *err;
   svn_revnum_t revnum;
   svn_boolean_t use_commit_times;
@@ -223,8 +221,8 @@ update_internal(svn_revnum_t *result_rev
     target = "";
 
   /* Check if our anchor exists in BASE. If it doesn't we can't update. */
-  SVN_ERR(svn_wc__node_get_base(&revnum, &repos_relpath, &repos_root_url, NULL,
-                                ctx->wc_ctx, anchor_abspath, pool, pool));
+  SVN_ERR(svn_client__wc_node_get_base(&anchor_loc, anchor_abspath,
+                                       ctx, pool, pool));
 
   /* It does not make sense to update conflict victims. */
   err = svn_wc_conflicted_p3(&text_conflicted, &prop_conflicted,
@@ -240,7 +238,7 @@ update_internal(svn_revnum_t *result_rev
   else
     SVN_ERR(err);
 
-  if (!SVN_IS_VALID_REVNUM(revnum)
+  if (! anchor_loc
       || text_conflicted || prop_conflicted || tree_conflicted)
     {
       if (ctx->notify_func2)
@@ -258,13 +256,6 @@ update_internal(svn_revnum_t *result_rev
         }
       return SVN_NO_ERROR;
     }
-  else if (! repos_relpath)
-      return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
-                               _("'%s' has no URL"),
-                               svn_dirent_local_style(anchor_abspath, pool));
-
-  anchor_url = svn_path_url_add_component2(repos_root_url, repos_relpath,
-                                           pool);
 
   /* We may need to crop the tree if the depth is sticky */
   if (depth_is_sticky && depth < svn_depth_infinity)
@@ -333,7 +324,7 @@ 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));
 
@@ -348,13 +339,15 @@ update_internal(svn_revnum_t *result_rev
       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, repos_root_url,
+      SVN_ERR(svn_client_relocate2(anchor_abspath, anchor_loc->url,
                                    new_repos_root_url, ignore_externals,
                                    ctx, pool));
 
       /* Store updated repository root for externals */
-      repos_root_url = new_repos_root_url;
-      anchor_url = corrected_url;
+      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
@@ -368,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. */
@@ -430,7 +423,7 @@ update_internal(svn_revnum_t *result_rev
 
       SVN_ERR(svn_client__handle_externals(new_externals,
                                            new_depths,
-                                           repos_root_url, local_abspath,
+                                           anchor_loc->repos_root_url, local_abspath,
                                            depth, use_sleep,
                                            ctx, pool));
     }