subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From prabh...@apache.org
Subject svn commit: r1457684 [5/22] - in /subversion/branches/verify-keep-going: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ notes/ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apache/subversion/javahl/ subve...
Date Mon, 18 Mar 2013 09:35:29 GMT
Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/externals.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/externals.c?rev=1457684&r1=1457683&r2=1457684&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/externals.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/externals.c Mon Mar 18 09:35:24 2013
@@ -235,17 +235,11 @@ switch_dir_external(const char *local_ab
               if (! svn_uri__is_ancestor(repos_root_url, url))
                 {
                   const char *repos_root;
-                  svn_ra_session_t *ra_session;
 
                   /* ... then figure out precisely which repository
                       root URL that target URL *is* a child of ... */
-                  SVN_ERR(svn_client__open_ra_session_internal(&ra_session,
-                                                               NULL, url, NULL,
-                                                               NULL, FALSE,
-                                                               TRUE, ctx,
-                                                               subpool));
-                  SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root,
-                                                 subpool));
+                  SVN_ERR(svn_client_get_repos_root(&repos_root, NULL, url,
+                                                    ctx, subpool, subpool));
 
                   /* ... and use that to try to relocate the external
                      working copy to the target location.  */
@@ -416,8 +410,8 @@ switch_file_external(const char *local_a
                                                scratch_pool));
   }
 
-  SVN_ERR(svn_wc_read_kind(&kind, ctx->wc_ctx, local_abspath, FALSE,
-                           scratch_pool));
+  SVN_ERR(svn_wc_read_kind2(&kind, ctx->wc_ctx, local_abspath,
+                            TRUE, FALSE, scratch_pool));
 
   SVN_ERR(svn_wc__read_external_info(&external_kind, NULL, NULL, NULL, NULL,
                                      ctx->wc_ctx, local_abspath, local_abspath,
@@ -500,10 +494,13 @@ 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,
+    SVN_ERR(svn_ra_do_switch3(ra_session, &reporter, &report_baton,
                               switch_loc->rev,
                               target, svn_depth_unknown, url,
-                              switch_editor, switch_baton, scratch_pool));
+                              FALSE /* send_copyfrom */,
+                              TRUE /* ignore_ancestry */,
+                              switch_editor, switch_baton,
+                              scratch_pool, scratch_pool));
 
     SVN_ERR(svn_wc__crawl_file_external(ctx->wc_ctx, local_abspath,
                                         reporter, report_baton,
@@ -606,7 +603,7 @@ handle_external_item_removal(const svn_c
                                      local_abspath, FALSE,
                                      scratch_pool, scratch_pool));
 
-  SVN_ERR(svn_wc_read_kind(&kind, ctx->wc_ctx, local_abspath, FALSE,
+  SVN_ERR(svn_wc_read_kind2(&kind, ctx->wc_ctx, local_abspath, TRUE, FALSE,
                            scratch_pool));
 
   if (external_kind != kind)
@@ -1016,12 +1013,12 @@ svn_client__handle_externals(apr_hash_t 
        * external and the DEFINING_ABSPATH which we can remove? */
       parent_abspath = item_abspath;
       do {
-        svn_wc_status3_t *parent_status;
+        svn_node_kind_t kind;
 
         parent_abspath = svn_dirent_dirname(parent_abspath, iterpool);
-        SVN_ERR(svn_wc_status3(&parent_status, ctx->wc_ctx, parent_abspath,
-                               iterpool, iterpool));
-        if (parent_status->node_status == svn_wc_status_unversioned)
+        SVN_ERR(svn_wc_read_kind2(&kind, ctx->wc_ctx, parent_abspath,
+                                  TRUE, FALSE, iterpool));
+        if (kind == svn_node_none)
           {
             svn_error_t *err;
 
@@ -1076,7 +1073,7 @@ svn_client__export_externals(apr_hash_t 
 
       SVN_ERR(svn_wc_parse_externals_description3(&items, local_abspath,
                                                   desc_text, FALSE,
-                                                  scratch_pool));
+                                                  iterpool));
 
       if (! items->nelts)
         continue;
@@ -1141,187 +1138,3 @@ svn_client__export_externals(apr_hash_t 
   return SVN_NO_ERROR;
 }
 
-
-svn_error_t *
-svn_client__do_external_status(svn_client_ctx_t *ctx,
-                               apr_hash_t *external_map,
-                               svn_depth_t depth,
-                               svn_boolean_t get_all,
-                               svn_boolean_t update,
-                               svn_boolean_t no_ignore,
-                               const char *anchor_abspath,
-                               const char *anchor_relpath,
-                               svn_client_status_func_t status_func,
-                               void *status_baton,
-                               apr_pool_t *scratch_pool)
-{
-  apr_hash_index_t *hi;
-  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
-
-  /* Loop over the hash of new values (we don't care about the old
-     ones).  This is a mapping of versioned directories to property
-     values. */
-  for (hi = apr_hash_first(scratch_pool, external_map);
-       hi;
-       hi = apr_hash_next(hi))
-    {
-      svn_node_kind_t external_kind;
-      const char *local_abspath = svn__apr_hash_index_key(hi);
-      const char *defining_abspath = svn__apr_hash_index_val(hi);
-      svn_node_kind_t kind;
-      svn_opt_revision_t opt_rev;
-      const char *status_path;
-
-      svn_pool_clear(iterpool);
-
-      /* Obtain information on the expected external. */
-      SVN_ERR(svn_wc__read_external_info(&external_kind, NULL, NULL, NULL,
-                                         &opt_rev.value.number,
-                                         ctx->wc_ctx, defining_abspath,
-                                         local_abspath, FALSE,
-                                         iterpool, iterpool));
-
-      if (external_kind != svn_node_dir)
-        continue;
-
-      SVN_ERR(svn_io_check_path(local_abspath, &kind, iterpool));
-      if (kind != svn_node_dir)
-        continue;
-
-      if (SVN_IS_VALID_REVNUM(opt_rev.value.number))
-        opt_rev.kind = svn_opt_revision_number;
-      else
-        opt_rev.kind = svn_opt_revision_unspecified;
-
-      /* Tell the client we're starting an external status set. */
-      if (ctx->notify_func2)
-        ctx->notify_func2(
-               ctx->notify_baton2,
-               svn_wc_create_notify(local_abspath,
-                                    svn_wc_notify_status_external,
-                                    iterpool), iterpool);
-
-      status_path = local_abspath;
-      if (anchor_abspath)
-        {
-          status_path = svn_dirent_join(anchor_relpath,
-                           svn_dirent_skip_ancestor(anchor_abspath,
-                                                    status_path),
-                           iterpool);
-        }
-
-      /* And then do the status. */
-      SVN_ERR(svn_client_status5(NULL, ctx, status_path, &opt_rev, depth,
-                                 get_all, update, no_ignore, FALSE, FALSE,
-                                 NULL, status_func, status_baton,
-                                 iterpool));
-    }
-
-  /* Destroy SUBPOOL and (implicitly) ITERPOOL. */
-  svn_pool_destroy(iterpool);
-
-  return SVN_NO_ERROR;
-}
-
-/* Walk through all the external items and list them. */
-static svn_error_t *
-list_external_items(apr_array_header_t *external_items,
-                    const char *externals_parent_url,
-                    svn_depth_t depth,
-                    apr_uint32_t dirent_fields,
-                    svn_boolean_t fetch_locks,
-                    svn_client_list_func2_t list_func,
-                    void *baton,
-                    svn_client_ctx_t *ctx,
-                    apr_pool_t *scratch_pool)
-{
-  const char *externals_parent_repos_root_url;
-  apr_pool_t *iterpool;
-  int i;
-
-  SVN_ERR(svn_client_get_repos_root(&externals_parent_repos_root_url, 
-                                    NULL /* uuid */,
-                                    externals_parent_url, ctx, 
-                                    scratch_pool, scratch_pool));
-
-  iterpool = svn_pool_create(scratch_pool);
-
-  for (i = 0; i < external_items->nelts; i++)
-    {
-      const char *resolved_url;
-
-      svn_wc_external_item2_t *item = 
-          APR_ARRAY_IDX(external_items, i, svn_wc_external_item2_t *);
-
-      svn_pool_clear(iterpool);
-
-      SVN_ERR(svn_wc__resolve_relative_external_url(
-                  &resolved_url, 
-                  item,
-                  externals_parent_repos_root_url,
-                  externals_parent_url,
-                  iterpool, iterpool));
-
-      /* List the external */
-      SVN_ERR(wrap_external_error(ctx, item->target_dir,
-                                  svn_client__list_internal(
-                                                resolved_url,
-                                                &item->peg_revision,
-                                                &item->revision,
-                                                depth, dirent_fields, 
-                                                fetch_locks,
-                                                TRUE,
-                                                externals_parent_url,
-                                                item->target_dir,
-                                                list_func, baton, ctx,
-                                                iterpool),
-                                  iterpool));
-    
-    }
-  svn_pool_destroy(iterpool);
-
-  return SVN_NO_ERROR;
-}
-      
-    
-svn_error_t * 
-svn_client__list_externals(apr_hash_t *externals, 
-                           svn_depth_t depth,
-                           apr_uint32_t dirent_fields,
-                           svn_boolean_t fetch_locks,
-                           svn_client_list_func2_t list_func,
-                           void *baton,
-                           svn_client_ctx_t *ctx,
-                           apr_pool_t *scratch_pool)
-{
-  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
-  apr_hash_index_t *hi;
-
-  for (hi = apr_hash_first(scratch_pool, externals);
-       hi;
-       hi = apr_hash_next(hi))
-    {
-      const char *externals_parent_url = svn__apr_hash_index_key(hi);
-      svn_string_t *externals_desc = svn__apr_hash_index_val(hi);
-      apr_array_header_t *external_items;
-
-      svn_pool_clear(iterpool);
-
-      SVN_ERR(svn_wc_parse_externals_description3(&external_items, 
-                                                  externals_parent_url,
-                                                  externals_desc->data, 
-                                                  FALSE, iterpool));
-
-      if (! external_items->nelts)
-        continue;
-
-      SVN_ERR(list_external_items(external_items, externals_parent_url, depth,
-                                  dirent_fields, fetch_locks, list_func,
-                                  baton, ctx, iterpool));
-
-    }
-  svn_pool_destroy(iterpool);
-
-  return SVN_NO_ERROR;
-}
-

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/import.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/import.c?rev=1457684&r1=1457683&r2=1457684&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/import.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/import.c Mon Mar 18 09:35:24 2013
@@ -803,13 +803,10 @@ svn_client_import5(const char *path,
   const char *local_abspath;
   apr_array_header_t *new_entries = apr_array_make(scratch_pool, 4,
                                                    sizeof(const char *));
-  const char *temp;
-  const char *dir;
   apr_hash_t *commit_revprops;
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
   apr_hash_t *autoprops = NULL;
   apr_array_header_t *global_ignores;
-  apr_hash_t *local_ignores_hash;
   apr_array_header_t *local_ignores_arr;
 
   if (svn_path_is_url(path))
@@ -848,9 +845,8 @@ svn_client_import5(const char *path,
 
   SVN_ERR(svn_io_check_path(local_abspath, &kind, scratch_pool));
 
-  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, url, NULL,
-                                               NULL, FALSE, TRUE, ctx,
-                                               scratch_pool));
+  SVN_ERR(svn_client_open_ra_session2(&ra_session, url, NULL,
+                                      ctx, scratch_pool, iterpool));
 
   /* Figure out all the path components we need to create just to have
      a place to stick our imported tree. */
@@ -866,11 +862,12 @@ svn_client_import5(const char *path,
 
   while (kind == svn_node_none)
     {
+      const char *dir;
+
       svn_pool_clear(iterpool);
 
-      svn_uri_split(&temp, &dir, url, scratch_pool);
+      svn_uri_split(&url, &dir, url, scratch_pool);
       APR_ARRAY_PUSH(new_entries, const char *) = dir;
-      url = temp;
       SVN_ERR(svn_ra_reparent(ra_session, url, iterpool));
 
       SVN_ERR(svn_ra_check_path(ra_session, "", SVN_INVALID_REVNUM, &kind,
@@ -878,37 +875,21 @@ svn_client_import5(const char *path,
     }
 
   /* Reverse the order of the components we added to our NEW_ENTRIES array. */
-  if (new_entries->nelts)
-    {
-      int i, j;
-      const char *component;
-      for (i = 0; i < (new_entries->nelts / 2); i++)
-        {
-          j = new_entries->nelts - i - 1;
-          component =
-            APR_ARRAY_IDX(new_entries, i, const char *);
-          APR_ARRAY_IDX(new_entries, i, const char *) =
-            APR_ARRAY_IDX(new_entries, j, const char *);
-          APR_ARRAY_IDX(new_entries, j, const char *) =
-            component;
-        }
-    }
+  svn_sort__array_reverse(new_entries, scratch_pool);
 
   /* The repository doesn't know about the reserved administrative
      directory. */
-  if (new_entries->nelts
-      /* What's this, what's this?  This assignment is here because we
-         use the value to construct the error message just below.  It
-         may not be aesthetically pleasing, but it's less ugly than
-         calling APR_ARRAY_IDX twice. */
-      && svn_wc_is_adm_dir(temp = APR_ARRAY_IDX(new_entries,
-                                                new_entries->nelts - 1,
-                                                const char *),
-                           scratch_pool))
-    return svn_error_createf
-      (SVN_ERR_CL_ADM_DIR_RESERVED, NULL,
-       _("'%s' is a reserved name and cannot be imported"),
-       svn_dirent_local_style(temp, scratch_pool));
+  if (new_entries->nelts)
+    {
+      const char *last_component
+        = APR_ARRAY_IDX(new_entries, new_entries->nelts - 1, const char *);
+
+      if (svn_wc_is_adm_dir(last_component, scratch_pool))
+        return svn_error_createf
+          (SVN_ERR_CL_ADM_DIR_RESERVED, NULL,
+           _("'%s' is a reserved name and cannot be imported"),
+           svn_dirent_local_style(last_component, scratch_pool));
+    }
 
   SVN_ERR(svn_client__ensure_revprop_table(&commit_revprops, revprop_table,
                                            log_msg, ctx, scratch_pool));
@@ -936,6 +917,7 @@ svn_client_import5(const char *path,
     {
       svn_opt_revision_t rev;
       apr_array_header_t *config_ignores;
+      apr_hash_t *local_ignores_hash;
 
       SVN_ERR(svn_client__get_inherited_ignores(&global_ignores, url, ctx,
                                                 scratch_pool, iterpool));

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/iprops.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/iprops.c?rev=1457684&r1=1457683&r2=1457684&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/iprops.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/iprops.c Mon Mar 18 09:35:24 2013
@@ -199,12 +199,9 @@ get_inheritable_props(apr_hash_t **wcroo
               if (! session_pool)
                 session_pool = svn_pool_create(scratch_pool);
 
-              SVN_ERR(svn_client__open_ra_session_internal(&ra_session,
-                                                           NULL, url,
-                                                           NULL, NULL,
-                                                           FALSE, TRUE,
-                                                           ctx,
-                                                           session_pool));
+              SVN_ERR(svn_client_open_ra_session2(&ra_session, url, NULL,
+                                                  ctx,
+                                                  session_pool, iterpool));
             }
 
           err = svn_ra_get_inherited_props(ra_session, &inherited_props,

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/list.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/list.c?rev=1457684&r1=1457683&r2=1457684&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/list.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/list.c Mon Mar 18 09:35:24 2013
@@ -33,8 +33,36 @@
 
 #include "private/svn_fspath.h"
 #include "private/svn_ra_private.h"
+#include "private/svn_wc_private.h"
 #include "svn_private_config.h"
 
+/* Prototypes for referencing before declaration */
+static svn_error_t * 
+list_externals(apr_hash_t *externals, 
+               svn_depth_t depth,
+               apr_uint32_t dirent_fields,
+               svn_boolean_t fetch_locks,
+               svn_client_list_func2_t list_func,
+               void *baton,
+               svn_client_ctx_t *ctx,
+               apr_pool_t *scratch_pool);
+
+static svn_error_t *
+list_internal(const char *path_or_url,
+              const svn_opt_revision_t *peg_revision,
+              const svn_opt_revision_t *revision,
+              svn_depth_t depth,
+              apr_uint32_t dirent_fields,
+              svn_boolean_t fetch_locks,
+              svn_boolean_t include_externals,
+              const char *external_parent_url,
+              const char *external_target,
+              svn_client_list_func2_t list_func,
+              void *baton,
+              svn_client_ctx_t *ctx,
+              apr_pool_t *pool);
+
+
 /* Get the directory entries of DIR at REV (relative to the root of
    RA_SESSION), getting at least the fields specified by DIRENT_FIELDS.
    Use the cancellation function/baton of CTX to check for cancellation.
@@ -203,10 +231,9 @@ svn_client__ra_stat_compatible(svn_ra_se
                  doesn't support svn_ra_reparent anyway, so don't try it. */
               svn_uri_split(&parent_url, &base_name, session_url, subpool);
 
-              SVN_ERR(svn_client__open_ra_session_internal(&parent_session,
-                                                           NULL, parent_url,
-                                                           NULL, NULL, FALSE,
-                                                           TRUE, ctx, subpool));
+              SVN_ERR(svn_client_open_ra_session2(&parent_session, parent_url,
+                                                  NULL, ctx,
+                                                  subpool, subpool));
 
               /* Get all parent's entries, no props. */
               SVN_ERR(svn_ra_get_dir2(parent_session, &parent_ents, NULL,
@@ -273,20 +300,53 @@ svn_client__ra_stat_compatible(svn_ra_se
   return SVN_NO_ERROR;
 }
 
-svn_error_t *
-svn_client__list_internal(const char *path_or_url,
-                          const svn_opt_revision_t *peg_revision,
-                          const svn_opt_revision_t *revision,
-                          svn_depth_t depth,
-                          apr_uint32_t dirent_fields,
-                          svn_boolean_t fetch_locks,
-                          svn_boolean_t include_externals,
-                          const char *external_parent_url,
-                          const char *external_target,
-                          svn_client_list_func2_t list_func,
-                          void *baton,
-                          svn_client_ctx_t *ctx,
-                          apr_pool_t *pool)
+/* List the file/directory entries for PATH_OR_URL at REVISION.
+   The actual node revision selected is determined by the path as 
+   it exists in PEG_REVISION.  
+   
+   If DEPTH is svn_depth_infinity, then list all file and directory entries 
+   recursively.  Else if DEPTH is svn_depth_files, list all files under 
+   PATH_OR_URL (if any), but not subdirectories.  Else if DEPTH is
+   svn_depth_immediates, list all files and include immediate
+   subdirectories (at svn_depth_empty).  Else if DEPTH is
+   svn_depth_empty, just list PATH_OR_URL with none of its entries.
+ 
+   DIRENT_FIELDS controls which fields in the svn_dirent_t's are
+   filled in.  To have them totally filled in use SVN_DIRENT_ALL,
+   otherwise simply bitwise OR together the combination of SVN_DIRENT_*
+   fields you care about.
+ 
+   If FETCH_LOCKS is TRUE, include locks when reporting directory entries.
+ 
+   If INCLUDE_EXTERNALS is TRUE, also list all external items 
+   reached by recursion.  DEPTH value passed to the original list target
+   applies for the externals also.  EXTERNAL_PARENT_URL is url of the 
+   directory which has the externals definitions.  EXTERNAL_TARGET is the
+   target subdirectory of externals definitions.
+
+   Report directory entries by invoking LIST_FUNC/BATON. 
+   Pass EXTERNAL_PARENT_URL and EXTERNAL_TARGET to LIST_FUNC when external
+   items are listed, otherwise both are set to NULL.
+ 
+   Use authentication baton cached in CTX to authenticate against the
+   repository.
+ 
+   Use POOL for all allocations.
+*/
+static svn_error_t *
+list_internal(const char *path_or_url,
+              const svn_opt_revision_t *peg_revision,
+              const svn_opt_revision_t *revision,
+              svn_depth_t depth,
+              apr_uint32_t dirent_fields,
+              svn_boolean_t fetch_locks,
+              svn_boolean_t include_externals,
+              const char *external_parent_url,
+              const char *external_target,
+              svn_client_list_func2_t list_func,
+              void *baton,
+              svn_client_ctx_t *ctx,
+              apr_pool_t *pool)
 {
   svn_ra_session_t *ra_session;
   svn_client__pathrev_t *loc;
@@ -361,14 +421,145 @@ svn_client__list_internal(const char *pa
     {
       /* The 'externals' hash populated by get_dir_contents() is processed 
          here. */
-      SVN_ERR(svn_client__list_externals(externals, depth, dirent_fields, 
-                                         fetch_locks, list_func, baton,
-                                         ctx, pool));
+      SVN_ERR(list_externals(externals, depth, dirent_fields, 
+                             fetch_locks, list_func, baton,
+                             ctx, pool));
     } 
   
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+wrap_list_error(const svn_client_ctx_t *ctx,
+                const char *target_abspath,
+                svn_error_t *err,
+                apr_pool_t *scratch_pool)
+{
+  if (err && err->apr_err != SVN_ERR_CANCELLED)
+    {
+      if (ctx->notify_func2)
+        {
+          svn_wc_notify_t *notifier = svn_wc_create_notify(
+                                            target_abspath,
+                                            svn_wc_notify_failed_external,
+                                            scratch_pool);
+          notifier->err = err;
+          ctx->notify_func2(ctx->notify_baton2, notifier, scratch_pool);
+        }
+      svn_error_clear(err);
+      return SVN_NO_ERROR;
+    }
+
+  return err;
+}
+
+
+/* Walk through all the external items and list them. */
+static svn_error_t *
+list_external_items(apr_array_header_t *external_items,
+                    const char *externals_parent_url,
+                    svn_depth_t depth,
+                    apr_uint32_t dirent_fields,
+                    svn_boolean_t fetch_locks,
+                    svn_client_list_func2_t list_func,
+                    void *baton,
+                    svn_client_ctx_t *ctx,
+                    apr_pool_t *scratch_pool)
+{
+  const char *externals_parent_repos_root_url;
+  apr_pool_t *iterpool;
+  int i;
+
+  SVN_ERR(svn_client_get_repos_root(&externals_parent_repos_root_url,
+                                    NULL /* uuid */,
+                                    externals_parent_url, ctx,
+                                    scratch_pool, scratch_pool));
+
+  iterpool = svn_pool_create(scratch_pool);
+
+  for (i = 0; i < external_items->nelts; i++)
+    {
+      const char *resolved_url;
+
+      svn_wc_external_item2_t *item =
+          APR_ARRAY_IDX(external_items, i, svn_wc_external_item2_t *);
+
+      svn_pool_clear(iterpool);
+
+      SVN_ERR(svn_wc__resolve_relative_external_url(
+                  &resolved_url,
+                  item,
+                  externals_parent_repos_root_url,
+                  externals_parent_url,
+                  iterpool, iterpool));
+
+      /* List the external */
+      SVN_ERR(wrap_list_error(ctx, item->target_dir,
+                              list_internal(resolved_url,
+                                            &item->peg_revision,
+                                            &item->revision,
+                                            depth, dirent_fields,
+                                            fetch_locks,
+                                            TRUE,
+                                            externals_parent_url,
+                                            item->target_dir,
+                                            list_func, baton, ctx,
+                                            iterpool),
+                              iterpool));
+
+    }
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+
+/* List external items defined on each external in EXTERNALS, a const char *
+   externals_parent_url(url of the directory which has the externals
+   definitions) of all externals mapping to the svn_string_t * externals_desc
+   (externals description text). All other options are the same as those 
+   passed to svn_client_list(). */
+static svn_error_t *
+list_externals(apr_hash_t *externals,
+               svn_depth_t depth,
+               apr_uint32_t dirent_fields,
+               svn_boolean_t fetch_locks,
+               svn_client_list_func2_t list_func,
+               void *baton,
+               svn_client_ctx_t *ctx,
+               apr_pool_t *scratch_pool)
+{
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  apr_hash_index_t *hi;
+
+  for (hi = apr_hash_first(scratch_pool, externals);
+       hi;
+       hi = apr_hash_next(hi))
+    {
+      const char *externals_parent_url = svn__apr_hash_index_key(hi);
+      svn_string_t *externals_desc = svn__apr_hash_index_val(hi);
+      apr_array_header_t *external_items;
+
+      svn_pool_clear(iterpool);
+
+      SVN_ERR(svn_wc_parse_externals_description3(&external_items,
+                                                  externals_parent_url,
+                                                  externals_desc->data,
+                                                  FALSE, iterpool));
+
+      if (! external_items->nelts)
+        continue;
+
+      SVN_ERR(list_external_items(external_items, externals_parent_url, depth,
+                                  dirent_fields, fetch_locks, list_func,
+                                  baton, ctx, iterpool));
+
+    }
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+
+
 svn_error_t *
 svn_client_list3(const char *path_or_url,
                  const svn_opt_revision_t *peg_revision,
@@ -383,11 +574,11 @@ svn_client_list3(const char *path_or_url
                  apr_pool_t *pool)
 {
 
-  return svn_error_trace(svn_client__list_internal(path_or_url, peg_revision,
-                                                   revision, 
-                                                   depth, dirent_fields, 
-                                                   fetch_locks, 
-                                                   include_externals, 
-                                                   NULL, NULL, list_func,
-                                                   baton, ctx, pool));
+  return svn_error_trace(list_internal(path_or_url, peg_revision,
+                                       revision,
+                                       depth, dirent_fields,
+                                       fetch_locks,
+                                       include_externals,
+                                       NULL, NULL, list_func,
+                                       baton, ctx, pool));
 }

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/locking_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/locking_commands.c?rev=1457684&r1=1457683&r2=1457684&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/locking_commands.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/locking_commands.c Mon Mar 18 09:35:24 2013
@@ -304,6 +304,7 @@ organize_lock_targets(const char **commo
           const char *target_url;
           struct wc_lock_item_t *wli;
           const char *local_abspath;
+          svn_node_kind_t kind;
 
           svn_pool_clear(iterpool);
 
@@ -311,16 +312,17 @@ organize_lock_targets(const char **commo
           local_abspath = svn_dirent_join(common_dirent, rel_target, scratch_pool);
           wli = apr_pcalloc(scratch_pool, sizeof(*wli));
 
-          SVN_ERR(svn_wc__node_get_base(&wli->revision, &repos_relpath,
+          SVN_ERR(svn_wc__node_get_base(&kind, &wli->revision, &repos_relpath,
                                         &repos_root_url, NULL,
                                         &wli->lock_token,
                                         wc_ctx, local_abspath,
+                                        FALSE /* ignore_enoent */,
+                                        FALSE /* show_hidden */,
                                         result_pool, iterpool));
 
-          /* Node exists in BASE? */
-          if (! repos_root_url || !repos_relpath)
-            return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
-                                     _("The node '%s' was not found."),
+          if (kind != svn_node_file)
+            return svn_error_createf(SVN_ERR_WC_NOT_FILE, NULL,
+                                     _("The node '%s' is not a file"),
                                      svn_dirent_local_style(local_abspath,
                                                             iterpool));
 
@@ -491,10 +493,8 @@ svn_client_lock(const apr_array_header_t
   /* Open an RA session to the common parent of TARGETS. */
   if (base_dir)
     SVN_ERR(svn_dirent_get_absolute(&base_dir_abspath, base_dir, pool));
-  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL,
-                                               common_parent_url, base_dir,
-                                               NULL, FALSE, FALSE,
-                                               ctx, pool));
+  SVN_ERR(svn_client_open_ra_session2(&ra_session, common_parent_url,
+                                      base_dir_abspath, ctx, pool, pool));
 
   cb.base_dir_abspath = base_dir_abspath;
   cb.urls_to_paths = urls_to_paths;
@@ -531,10 +531,8 @@ svn_client_unlock(const apr_array_header
   /* Open an RA session. */
   if (base_dir)
     SVN_ERR(svn_dirent_get_absolute(&base_dir_abspath, base_dir, pool));
-  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL,
-                                               common_parent_url,
-                                               base_dir_abspath, NULL, FALSE,
-                                               FALSE, ctx, pool));
+  SVN_ERR(svn_client_open_ra_session2(&ra_session, common_parent_url,
+                                      base_dir_abspath, ctx, pool, pool));
 
   /* If break_lock is not set, lock tokens are required by the server.
      If the targets were all URLs, ensure that we provide lock tokens,

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/merge.c?rev=1457684&r1=1457683&r2=1457684&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/merge.c Mon Mar 18 09:35:24 2013
@@ -1404,11 +1404,8 @@ record_tree_conflict(merge_cmd_baton_t *
   return SVN_NO_ERROR;
 }
 
-/* Record the add for future processing and (later) produce the
+/* Record the add for future processing and produce the
    update_add notification
-
-   Originally a helper for notification_receiver: Cache the roots of
-   subtrees added under TARGET_ABSPATH.
  */
 static svn_error_t *
 record_update_add(merge_cmd_baton_t *merge_b,
@@ -1442,8 +1439,8 @@ record_update_add(merge_cmd_baton_t *mer
   return SVN_NO_ERROR;
 }
 
-/* Record the update for future processing and (later) produce the
-   update_add notification */
+/* Record the update for future processing and produce the
+   update_update notification */
 static svn_error_t *
 record_update_update(merge_cmd_baton_t *merge_b,
                      const char *local_abspath,
@@ -1476,7 +1473,7 @@ record_update_update(merge_cmd_baton_t *
   return SVN_NO_ERROR;
 }
 
-/* Record the delete for future processing and (later) produce the
+/* Record the delete for future processing and for (later) producing the
    update_delete notification */
 static svn_error_t *
 record_update_delete(merge_cmd_baton_t *merge_b,
@@ -1598,7 +1595,7 @@ mark_dir_edited(merge_cmd_baton_t *merge
                             local_abspath,
                             (db->tree_conflict_reason == CONFLICT_REASON_SKIP)
                                 ? svn_wc_notify_skip
-                                : svn_wc_notify_state_obstructed,
+                                : svn_wc_notify_update_skip_obstruction,
                             scratch_pool);
           notify->kind = svn_node_dir;
           notify->content_state = notify->prop_state = db->skip_reason;
@@ -3463,6 +3460,37 @@ notify_merge_completed(const char *targe
                      || notify->action == svn_wc_notify_tree_conflict)
 
 
+/* Remove merge source gaps from range used for merge notifications.
+   See http://subversion.tigris.org/issues/show_bug.cgi?id=4138
+
+   If IMPLICIT_SRC_GAP is not NULL then it is a rangelist containing a
+   single range (see the implicit_src_gap member of merge_cmd_baton_t).
+   RANGE describes a (possibly reverse) merge.
+
+   If IMPLICIT_SRC_GAP is not NULL and it's sole range intersects with
+   the older revision in *RANGE, then remove IMPLICIT_SRC_GAP's range
+   from *RANGE. */
+static void
+remove_source_gap(svn_merge_range_t *range,
+                  apr_array_header_t *implicit_src_gap)
+{
+  if (implicit_src_gap)
+    {
+      svn_merge_range_t *gap_range =
+        APR_ARRAY_IDX(implicit_src_gap, 0, svn_merge_range_t *);
+      if (range->start < range->end)
+        {
+          if (gap_range->start == range->start)
+            range->start = gap_range->end;
+        }
+      else /* Reverse merge */
+        {
+          if (gap_range->start == range->end)
+            range->end = gap_range->end;
+        }
+    }
+}
+
 /* Notify that we're starting a merge
  *
  * This calls the client's notification receiver (as found in the client
@@ -3554,9 +3582,16 @@ notify_merge_begin(merge_cmd_baton_t *me
                                 scratch_pool);
 
   if (SVN_IS_VALID_REVNUM(n_range.start))
-    notify->merge_range = &n_range;
+    {
+      /* If the merge source has a gap, then don't mention
+         those gap revisions in the notification. */
+      remove_source_gap(&n_range, merge_b->implicit_src_gap);
+      notify->merge_range = &n_range;
+    }
   else
-    notify->merge_range = NULL;
+    {
+      notify->merge_range = NULL;
+    }
 
   (*merge_b->ctx->notify_func2)(merge_b->ctx->notify_baton2, notify,
                                 scratch_pool);
@@ -4595,8 +4630,11 @@ calculate_remaining_ranges(svn_client__m
      So in the name of user friendliness, return an error suggesting a helpful
      course of action.
   */
-  SVN_ERR(svn_wc__node_get_base(&child_base_revision, NULL, NULL, NULL, NULL,
+  SVN_ERR(svn_wc__node_get_base(NULL, &child_base_revision,
+                                NULL, NULL, NULL, NULL,
                                 ctx->wc_ctx, child->abspath,
+                                TRUE /* ignore_enoent */,
+                                FALSE /* show_hidden */,
                                 scratch_pool, scratch_pool));
   /* If CHILD has no base revision then it hasn't been committed yet, so it
      can't have any "future" history. */
@@ -4690,6 +4728,10 @@ find_gaps_in_merge_source_history(svn_re
   /* Start by assuming there is no gap. */
   *gap_start = *gap_end = SVN_INVALID_REVNUM;
 
+  /* Easy out: There can't be a gap between adjacent revisions. */
+  if (abs(source->loc1->rev - source->loc2->rev) == 1)
+    return SVN_NO_ERROR;
+
   /* Get SOURCE as mergeinfo. */
   SVN_ERR(svn_client__get_history_as_mergeinfo(&implicit_src_mergeinfo, NULL,
                                                primary_src,
@@ -5276,20 +5318,64 @@ record_skips_in_mergeinfo(const char *me
   return SVN_NO_ERROR;
 }
 
+/* Data for reporting when a merge aborted because of raising conflicts.
+ *
+ * ### TODO: More info, including the ranges (or other parameters) the user
+ *     needs to complete the merge.
+ */
+typedef struct conflict_report_t
+{
+  const char *target_abspath;
+  /* The revision range during which conflicts were raised */
+  svn_merge_range_t *r;
+  svn_boolean_t was_last_range;
+} conflict_report_t;
+
+/* Return a new conflict_report_t containing deep copies of the parameters,
+ * allocated in RESULT_POOL. */
+static conflict_report_t *
+conflict_report_create(const char *target_abspath,
+                       const svn_merge_range_t *conflicted_range,
+                       svn_boolean_t was_last_range,
+                       apr_pool_t *result_pool)
+{
+  conflict_report_t *report = apr_palloc(result_pool, sizeof(*report));
+
+  report->target_abspath = apr_pstrdup(result_pool, target_abspath);
+  report->r = svn_merge_range_dup(conflicted_range, result_pool);
+  report->was_last_range = was_last_range;
+  return report;
+}
+
+/* Return a deep copy of REPORT, allocated in RESULT_POOL. */
+static conflict_report_t *
+conflict_report_dup(const conflict_report_t *report,
+                    apr_pool_t *result_pool)
+{
+  conflict_report_t *new = apr_pmemdup(result_pool, report, sizeof(*new));
+
+  new->target_abspath = apr_pstrdup(result_pool, report->target_abspath);
+  new->r = svn_merge_range_dup(report->r, result_pool);
+  return new;
+}
+
 /* Create and return an error structure appropriate for the unmerged
    revisions range(s). */
 static APR_INLINE svn_error_t *
-make_merge_conflict_error(const char *target_wcpath,
-                          svn_merge_range_t *r,
+make_merge_conflict_error(conflict_report_t *report,
                           apr_pool_t *scratch_pool)
 {
-  return svn_error_createf
-    (SVN_ERR_WC_FOUND_CONFLICT, NULL,
-     _("One or more conflicts were produced while merging r%ld:%ld into\n"
-       "'%s' --\n"
-       "resolve all conflicts and rerun the merge to apply the remaining\n"
-       "unmerged revisions"),
-     r->start, r->end, svn_dirent_local_style(target_wcpath, scratch_pool));
+  assert(!report || svn_dirent_is_absolute(report->target_abspath));
+
+  if (report && ! report->was_last_range)
+    return svn_error_createf(SVN_ERR_WC_FOUND_CONFLICT, NULL,
+       _("One or more conflicts were produced while merging r%ld:%ld into\n"
+         "'%s' --\n"
+         "resolve all conflicts and rerun the merge to apply the remaining\n"
+         "unmerged revisions"),
+       report->r->start, report->r->end,
+       svn_dirent_local_style(report->target_abspath, scratch_pool));
+  return SVN_NO_ERROR;
 }
 
 /* Helper for do_directory_merge().
@@ -5935,9 +6021,9 @@ insert_parent_and_sibs_of_sw_absent_del_
             {
               svn_node_kind_t child_kind;
 
-              SVN_ERR(svn_wc_read_kind(&child_kind,
-                                       ctx->wc_ctx,
-                                       child_abspath, FALSE, iterpool));
+              SVN_ERR(svn_wc_read_kind2(&child_kind,
+                                        ctx->wc_ctx, child_abspath,
+                                        FALSE, FALSE, iterpool));
               if (child_kind != svn_node_file)
                 continue;
             }
@@ -6406,10 +6492,9 @@ get_mergeinfo_paths(apr_array_header_t *
           svn_node_kind_t immediate_child_kind;
 
           svn_pool_clear(iterpool);
-          SVN_ERR(svn_wc_read_kind(&immediate_child_kind,
-                                   ctx->wc_ctx,
-                                   immediate_child_abspath, FALSE,
-                                   iterpool));
+          SVN_ERR(svn_wc_read_kind2(&immediate_child_kind,
+                                    ctx->wc_ctx, immediate_child_abspath,
+                                    FALSE, FALSE, iterpool));
           if ((immediate_child_kind == svn_node_dir
                && depth == svn_depth_immediates)
               || (immediate_child_kind == svn_node_file
@@ -6506,10 +6591,9 @@ get_mergeinfo_paths(apr_array_header_t *
                   if (depth == svn_depth_files)
                     {
                       svn_node_kind_t child_kind;
-                      SVN_ERR(svn_wc_read_kind(&child_kind,
-                                               ctx->wc_ctx,
-                                               child_abspath, FALSE,
-                                               iterpool));
+                      SVN_ERR(svn_wc_read_kind2(&child_kind,
+                                                ctx->wc_ctx, child_abspath,
+                                                FALSE, FALSE, iterpool));
                       if (child_kind != svn_node_file)
                         continue;
                     }
@@ -7223,11 +7307,12 @@ do_file_merge(svn_mergeinfo_catalog_t re
   range.start = source->loc1->rev;
   range.end = source->loc2->rev;
   range.inheritable = TRUE;
+
+  merge_target = svn_client__merge_path_create(target_abspath, scratch_pool);
+
   if (honor_mergeinfo)
     {
       svn_error_t *err;
-      merge_target = svn_client__merge_path_create(target_abspath,
-                                                   scratch_pool);
 
       /* Fetch mergeinfo. */
       err = get_full_mergeinfo(&target_mergeinfo,
@@ -7836,15 +7921,9 @@ log_find_operative_subtree_revs(void *ba
                     svn_dirent_join(log_baton->merge_target_abspath,
                                     rel_path, iterpool);
 
-                  /* ### ptb - svn_wc_read_kind is very tolerant when we ask
-                     ### it about unversioned, non-existent, and missing WC
-                     ### paths, simply setting *NODE_KIND svn_kind_none in
-                     ### those cases.  Is there any legitimate error we
-                     ### might encounter during a merge where we'd want
-                     ### to clear the error and continue? */
-                  SVN_ERR(svn_wc_read_kind(&node_kind, log_baton->wc_ctx,
-                                           wc_child_abspath, FALSE,
-                                           iterpool));
+                  SVN_ERR(svn_wc_read_kind2(&node_kind, log_baton->wc_ctx,
+                                            wc_child_abspath, FALSE, FALSE,
+                                            iterpool));
                 }
               else
                 {
@@ -8104,8 +8183,8 @@ flag_subtrees_needing_mergeinfo(svn_bool
           /* We need to record mergeinfo, but should that mergeinfo be
              non-inheritable? */
           svn_node_kind_t path_kind;
-          SVN_ERR(svn_wc_read_kind(&path_kind, merge_b->ctx->wc_ctx,
-                                   child->abspath, FALSE, iterpool));
+          SVN_ERR(svn_wc_read_kind2(&path_kind, merge_b->ctx->wc_ctx,
+                                    child->abspath, FALSE, FALSE, iterpool));
 
           /* Only directories can have non-inheritable mergeinfo. */
           if (path_kind == svn_node_dir)
@@ -8273,8 +8352,13 @@ record_mergeinfo_for_dir_merge(svn_merge
             continue;
 
           if (!squelch_mergeinfo_notifications)
-            notify_mergeinfo_recording(child->abspath, merged_range,
-                                      merge_b->ctx, iterpool);
+            {
+              /* If the merge source has a gap, then don't mention
+                 those gap revisions in the notification. */
+              remove_source_gap(&range, merge_b->implicit_src_gap);
+              notify_mergeinfo_recording(child->abspath, &range,
+                                         merge_b->ctx, iterpool);
+            }
 
           /* If we are here we know we will be recording some mergeinfo, but
              before we do, set override mergeinfo on skipped paths so they
@@ -8522,8 +8606,8 @@ record_mergeinfo_for_added_subtrees(
           const char *added_path_mergeinfo_fspath;
           svn_client__pathrev_t *added_path_pathrev;
 
-          SVN_ERR(svn_wc_read_kind(&added_path_kind, merge_b->ctx->wc_ctx,
-                                   added_abspath, FALSE, iterpool));
+          SVN_ERR(svn_wc_read_kind2(&added_path_kind, merge_b->ctx->wc_ctx,
+                                    added_abspath, FALSE, FALSE, iterpool));
 
           /* Calculate the naive mergeinfo describing the merge. */
           merge_mergeinfo = apr_hash_make(iterpool);
@@ -9379,6 +9463,7 @@ do_directory_merge(svn_mergeinfo_catalog
 static svn_error_t *
 ensure_ra_session_url(svn_ra_session_t **ra_session,
                       const char *url,
+                      const char *wri_abspath,
                       svn_client_ctx_t *ctx,
                       apr_pool_t *pool)
 {
@@ -9394,7 +9479,8 @@ ensure_ra_session_url(svn_ra_session_t *
   if (! *ra_session || (err && err->apr_err == SVN_ERR_RA_ILLEGAL_URL))
     {
       svn_error_clear(err);
-      err = svn_client_open_ra_session(ra_session, url, ctx, pool);
+      err = svn_client_open_ra_session2(ra_session, url, wri_abspath,
+                                        ctx, pool, pool);
     }
   SVN_ERR(err);
 
@@ -9412,6 +9498,14 @@ ensure_ra_session_url(svn_ra_session_t *
    by the merge.  Keys and values of the hash are both (const char *)
    absolute paths.  The contents of the hash are allocated in RESULT_POOL.
 
+   If the merge raises any conflicts while merging a revision range, return
+   early and set *CONFLICT_REPORT to describe the details.  (In this case,
+   notify that the merge is complete if and only if this was the last
+   revision range of the merge.)  If there are no conflicts, set
+   *CONFLICT_REPORT to NULL.  A revision range here can be one specified
+   in MERGE_SOURCES or an internally generated sub-range of one of those
+   when merge tracking is in use.
+
    For every (const merge_source_t *) merge source in MERGE_SOURCES, if
    SOURCE->ANCESTRAL is set, then the "left" and "right" side are
    ancestrally related.  (See 'MERGEINFO MERGE SOURCE NORMALIZATION'
@@ -9468,6 +9562,8 @@ ensure_ra_session_url(svn_ra_session_t *
 static svn_error_t *
 do_merge(apr_hash_t **modified_subtrees,
          svn_mergeinfo_catalog_t result_catalog,
+         conflict_report_t **conflict_report,
+         svn_boolean_t *use_sleep,
          const apr_array_header_t *merge_sources,
          const merge_target_t *target,
          svn_ra_session_t *src_session,
@@ -9483,7 +9579,6 @@ do_merge(apr_hash_t **modified_subtrees,
          svn_boolean_t squelch_mergeinfo_notifications,
          svn_depth_t depth,
          const apr_array_header_t *merge_options,
-         svn_boolean_t *use_sleep,
          svn_client_ctx_t *ctx,
          apr_pool_t *result_pool,
          apr_pool_t *scratch_pool)
@@ -9500,6 +9595,8 @@ do_merge(apr_hash_t **modified_subtrees,
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(target->abspath));
 
+  *conflict_report = NULL;
+
   /* Check from some special conditions when in record-only mode
      (which is a merge-tracking thing). */
   if (record_only)
@@ -9612,7 +9709,6 @@ do_merge(apr_hash_t **modified_subtrees,
       merge_source_t *source =
         APR_ARRAY_IDX(merge_sources, i, merge_source_t *);
       svn_merge_range_t *conflicted_range;
-      svn_error_t *err;
 
       svn_pool_clear(iterpool);
 
@@ -9624,9 +9720,9 @@ do_merge(apr_hash_t **modified_subtrees,
 
       /* Establish RA sessions to our URLs, reuse where possible. */
       SVN_ERR(ensure_ra_session_url(&ra_session1, source->loc1->url,
-                                    ctx, scratch_pool));
+                                    target->abspath, ctx, scratch_pool));
       SVN_ERR(ensure_ra_session_url(&ra_session2, source->loc2->url,
-                                    ctx, scratch_pool));
+                                    target->abspath, ctx, scratch_pool));
 
       /* Populate the portions of the merge context baton that need to
          be reset for each merge source iteration. */
@@ -9657,45 +9753,48 @@ do_merge(apr_hash_t **modified_subtrees,
       /* Call our merge helpers based on SRC1's kind. */
       if (src1_kind != svn_node_dir)
         {
-          err = do_file_merge(result_catalog, &conflicted_range,
-                              source, target->abspath,
-                              processor,
-                              sources_related,
-                              squelch_mergeinfo_notifications,
-                              &merge_cmd_baton, iterpool, iterpool);
+          SVN_ERR(do_file_merge(result_catalog, &conflicted_range,
+                                source, target->abspath,
+                                processor,
+                                sources_related,
+                                squelch_mergeinfo_notifications,
+                                &merge_cmd_baton, iterpool, iterpool));
         }
       else /* Directory */
         {
-          err = do_directory_merge(result_catalog, &conflicted_range,
-                                   source, target->abspath,
-                                   processor,
-                                   depth, squelch_mergeinfo_notifications,
-                                   &merge_cmd_baton, iterpool, iterpool);
+          SVN_ERR(do_directory_merge(result_catalog, &conflicted_range,
+                                     source, target->abspath,
+                                     processor,
+                                     depth, squelch_mergeinfo_notifications,
+                                     &merge_cmd_baton, iterpool, iterpool));
         }
+      /* The final mergeinfo on TARGET_WCPATH may itself elide. */
+      if (! dry_run)
+        SVN_ERR(svn_client__elide_mergeinfo(target->abspath, NULL,
+                                            ctx, iterpool));
+
       /* If conflicts occurred while merging any but the very last
        * range of a multi-pass merge, we raise an error that aborts
        * the merge. The user will be asked to resolve conflicts
        * before merging subsequent revision ranges. */
-      if (conflicted_range
-          && (i < merge_sources->nelts - 1
-              || conflicted_range->end != source->loc2->rev))
-        {
-          err = svn_error_compose_create(
-                  err, make_merge_conflict_error(
-                         target->abspath, conflicted_range, scratch_pool));
+      if (conflicted_range)
+        {
+          *conflict_report = conflict_report_create(
+                               target->abspath, conflicted_range,
+                               (i == merge_sources->nelts - 1
+                                && conflicted_range->end == source->loc2->rev),
+                               result_pool);
+          break;
         }
-      SVN_ERR(err);
-
-      /* The final mergeinfo on TARGET_WCPATH may itself elide. */
-      if (! dry_run)
-        SVN_ERR(svn_client__elide_mergeinfo(target->abspath, NULL,
-                                            ctx, iterpool));
     }
 
-  /* Let everyone know we're finished here. */
-  notify_merge_completed(target->abspath, ctx, iterpool);
+  if (! *conflict_report || (*conflict_report)->was_last_range)
+    {
+      /* Let everyone know we're finished here. */
+      notify_merge_completed(target->abspath, ctx, iterpool);
+    }
 
-    /* Does the caller want to know what the merge has done? */
+  /* Does the caller want to know what the merge has done? */
   if (modified_subtrees)
     {
       *modified_subtrees =
@@ -9724,6 +9823,9 @@ do_merge(apr_hash_t **modified_subtrees,
    merge (unless this is record-only), followed by record-only merges
    to represent the changed mergeinfo.
 
+   Set *CONFLICT_REPORT to indicate if there were any conflicts, as in
+   do_merge().
+
    The diff to be merged is between SOURCE->loc1 (in URL1_RA_SESSION1)
    and SOURCE->loc2 (in URL2_RA_SESSION2); YCA is their youngest
    common ancestor.
@@ -9741,7 +9843,9 @@ do_merge(apr_hash_t **modified_subtrees,
    SCRATCH_POOL is used for all temporary allocations.
  */
 static svn_error_t *
-merge_cousins_and_supplement_mergeinfo(const merge_target_t *target,
+merge_cousins_and_supplement_mergeinfo(conflict_report_t **conflict_report,
+                                       svn_boolean_t *use_sleep,
+                                       const merge_target_t *target,
                                        svn_ra_session_t *URL1_ra_session,
                                        svn_ra_session_t *URL2_ra_session,
                                        const merge_source_t *source,
@@ -9753,8 +9857,8 @@ merge_cousins_and_supplement_mergeinfo(c
                                        svn_boolean_t record_only,
                                        svn_boolean_t dry_run,
                                        const apr_array_header_t *merge_options,
-                                       svn_boolean_t *use_sleep,
                                        svn_client_ctx_t *ctx,
+                                       apr_pool_t *result_pool,
                                        apr_pool_t *scratch_pool)
 {
   apr_array_header_t *remove_sources, *add_sources;
@@ -9784,20 +9888,30 @@ merge_cousins_and_supplement_mergeinfo(c
                                       scratch_pool),
             URL2_ra_session, ctx, scratch_pool, subpool));
 
+  *conflict_report = NULL;
+
   /* If this isn't a record-only merge, we'll first do a stupid
      point-to-point merge... */
   if (! record_only)
     {
       apr_array_header_t *faux_sources =
         apr_array_make(scratch_pool, 1, sizeof(merge_source_t *));
+
       modified_subtrees = apr_hash_make(scratch_pool);
       APR_ARRAY_PUSH(faux_sources, const merge_source_t *) = source;
-      SVN_ERR(do_merge(&modified_subtrees, NULL, faux_sources, target,
+      SVN_ERR(do_merge(&modified_subtrees, NULL, conflict_report, use_sleep,
+                       faux_sources, target,
                        URL1_ra_session, TRUE, same_repos,
                        FALSE /*ignore_mergeinfo*/, diff_ignore_ancestry,
                        force_delete, dry_run, FALSE, NULL, TRUE,
-                       FALSE, depth, merge_options, use_sleep, ctx,
+                       FALSE, depth, merge_options, ctx,
                        scratch_pool, subpool));
+      if (*conflict_report)
+        {
+          *conflict_report = conflict_report_dup(*conflict_report, result_pool);
+          if (! (*conflict_report)->was_last_range)
+            return SVN_NO_ERROR;
+        }
     }
   else if (! same_repos)
     {
@@ -9825,21 +9939,35 @@ merge_cousins_and_supplement_mergeinfo(c
 
       notify_mergeinfo_recording(target->abspath, NULL, ctx, scratch_pool);
       svn_pool_clear(subpool);
-      SVN_ERR(do_merge(NULL, add_result_catalog, add_sources, target,
+      SVN_ERR(do_merge(NULL, add_result_catalog, conflict_report, use_sleep,
+                       add_sources, target,
                        URL1_ra_session, TRUE, same_repos,
                        FALSE /*ignore_mergeinfo*/, diff_ignore_ancestry,
                        force_delete, dry_run, TRUE,
                        modified_subtrees, TRUE,
-                       TRUE, depth, merge_options, use_sleep, ctx,
+                       TRUE, depth, merge_options, ctx,
                        scratch_pool, subpool));
+      if (*conflict_report)
+        {
+          *conflict_report = conflict_report_dup(*conflict_report, result_pool);
+          if (! (*conflict_report)->was_last_range)
+            return SVN_NO_ERROR;
+        }
       svn_pool_clear(subpool);
-      SVN_ERR(do_merge(NULL, remove_result_catalog, remove_sources, target,
+      SVN_ERR(do_merge(NULL, remove_result_catalog, conflict_report, use_sleep,
+                       remove_sources, target,
                        URL1_ra_session, TRUE, same_repos,
                        FALSE /*ignore_mergeinfo*/, diff_ignore_ancestry,
                        force_delete, dry_run, TRUE,
                        modified_subtrees, TRUE,
-                       TRUE, depth, merge_options, use_sleep, ctx,
+                       TRUE, depth, merge_options, ctx,
                        scratch_pool, subpool));
+      if (*conflict_report)
+        {
+          *conflict_report = conflict_report_dup(*conflict_report, result_pool);
+          if (! (*conflict_report)->was_last_range)
+            return SVN_NO_ERROR;
+        }
       SVN_ERR(svn_mergeinfo_catalog_merge(add_result_catalog,
                                           remove_result_catalog,
                                           scratch_pool, scratch_pool));
@@ -9877,8 +10005,8 @@ ensure_wc_is_suitable_merge_target(const
                              _("Path '%s' does not exist"),
                              svn_dirent_local_style(target_abspath,
                                                     scratch_pool));
-  SVN_ERR(svn_wc_read_kind(&target_kind, ctx->wc_ctx, target_abspath, FALSE,
-                           scratch_pool));
+  SVN_ERR(svn_wc_read_kind2(&target_kind, ctx->wc_ctx, target_abspath,
+                            FALSE, FALSE, scratch_pool));
   if (target_kind != svn_node_dir && target_kind != svn_node_file)
     return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
                              _("Merge target '%s' does not exist in the "
@@ -10056,7 +10184,8 @@ open_target_wc(merge_target_t **target_p
  * IGNORE_MERGEINFO and DIFF_IGNORE_ANCESTRY are as in do_merge().
  */
 static svn_error_t *
-merge_locked(const char *source1,
+merge_locked(conflict_report_t **conflict_report,
+             const char *source1,
              const svn_opt_revision_t *revision1,
              const char *source2,
              const svn_opt_revision_t *revision2,
@@ -10070,6 +10199,7 @@ merge_locked(const char *source1,
              svn_boolean_t allow_mixed_rev,
              const apr_array_header_t *merge_options,
              svn_client_ctx_t *ctx,
+             apr_pool_t *result_pool,
              apr_pool_t *scratch_pool)
 {
   merge_target_t *target;
@@ -10174,7 +10304,9 @@ merge_locked(const char *source1,
           source.loc2 = source2_loc;
           source.ancestral = FALSE;
 
-          err = merge_cousins_and_supplement_mergeinfo(target,
+          err = merge_cousins_and_supplement_mergeinfo(conflict_report,
+                                                       &use_sleep,
+                                                       target,
                                                        ra_session1,
                                                        ra_session2,
                                                        &source,
@@ -10185,7 +10317,8 @@ merge_locked(const char *source1,
                                                        force_delete,
                                                        record_only, dry_run,
                                                        merge_options,
-                                                       &use_sleep, ctx,
+                                                       ctx,
+                                                       result_pool,
                                                        scratch_pool);
           /* Close our temporary RA sessions (this could've happened
              after the second call to normalize_merge_sources() inside
@@ -10195,9 +10328,7 @@ merge_locked(const char *source1,
           if (use_sleep)
             svn_io_sleep_for_timestamps(target->abspath, scratch_pool);
 
-          if (err)
-              return svn_error_trace(err);
-
+          SVN_ERR(err);
           return SVN_NO_ERROR;
         }
     }
@@ -10214,11 +10345,12 @@ merge_locked(const char *source1,
       APR_ARRAY_PUSH(merge_sources, merge_source_t *) = &source;
     }
 
-  err = do_merge(NULL, NULL, merge_sources, target,
+  err = do_merge(NULL, NULL, conflict_report, &use_sleep,
+                 merge_sources, target,
                  ra_session1, sources_related, same_repos,
                  ignore_mergeinfo, diff_ignore_ancestry, force_delete, dry_run,
                  record_only, NULL, FALSE, FALSE, depth, merge_options,
-                 &use_sleep, ctx, scratch_pool, scratch_pool);
+                 ctx, result_pool, scratch_pool);
 
   /* Close our temporary RA sessions. */
   svn_pool_destroy(sesspool);
@@ -10226,9 +10358,7 @@ merge_locked(const char *source1,
   if (use_sleep)
     svn_io_sleep_for_timestamps(target->abspath, scratch_pool);
 
-  if (err)
-    return svn_error_trace(err);
-
+  SVN_ERR(err);
   return SVN_NO_ERROR;
 }
 
@@ -10244,8 +10374,8 @@ get_target_and_lock_abspath(const char *
   svn_node_kind_t kind;
   SVN_ERR(svn_dirent_get_absolute(target_abspath, target_wcpath,
                                   result_pool));
-  SVN_ERR(svn_wc_read_kind(&kind, ctx->wc_ctx, *target_abspath, FALSE,
-                           result_pool));
+  SVN_ERR(svn_wc_read_kind2(&kind, ctx->wc_ctx, *target_abspath,
+                            FALSE, FALSE, result_pool));
   if (kind == svn_node_dir)
     *lock_abspath = *target_abspath;
   else
@@ -10272,6 +10402,7 @@ svn_client_merge5(const char *source1,
                   apr_pool_t *pool)
 {
   const char *target_abspath, *lock_abspath;
+  conflict_report_t *conflict_report;
 
   /* Sanity check our input -- we require specified revisions,
    * and either 2 paths or 2 URLs. */
@@ -10294,19 +10425,22 @@ svn_client_merge5(const char *source1,
 
   if (!dry_run)
     SVN_WC__CALL_WITH_WRITE_LOCK(
-      merge_locked(source1, revision1, source2, revision2,
+      merge_locked(&conflict_report,
+                   source1, revision1, source2, revision2,
                    target_abspath, depth, ignore_mergeinfo,
                    diff_ignore_ancestry,
                    force_delete, record_only, dry_run,
-                   allow_mixed_rev, merge_options, ctx, pool),
+                   allow_mixed_rev, merge_options, ctx, pool, pool),
       ctx->wc_ctx, lock_abspath, FALSE /* lock_anchor */, pool);
   else
-    SVN_ERR(merge_locked(source1, revision1, source2, revision2,
+    SVN_ERR(merge_locked(&conflict_report,
+                   source1, revision1, source2, revision2,
                    target_abspath, depth, ignore_mergeinfo,
                    diff_ignore_ancestry,
                    force_delete, record_only, dry_run,
-                   allow_mixed_rev, merge_options, ctx, pool));
+                   allow_mixed_rev, merge_options, ctx, pool, pool));
 
+  SVN_ERR(make_merge_conflict_error(conflict_report, pool));
   return SVN_NO_ERROR;
 }
 
@@ -11291,9 +11425,9 @@ open_reintegrate_source_and_target(svn_r
   SVN_ERR(open_target_wc(&target, target_abspath,
                          FALSE, FALSE, FALSE,
                          ctx, scratch_pool, scratch_pool));
-  SVN_ERR(svn_client_open_ra_session(target_ra_session_p,
-                                     target->loc.url,
-                                     ctx, scratch_pool));
+  SVN_ERR(svn_client_open_ra_session2(target_ra_session_p,
+                                      target->loc.url, target->abspath,
+                                      ctx, result_pool, scratch_pool));
   if (! target->loc.url)
     return svn_error_createf(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
                              _("Can't reintegrate into '%s' because it is "
@@ -11324,13 +11458,15 @@ open_reintegrate_source_and_target(svn_r
 
 /* The body of svn_client_merge_reintegrate(), which see for details. */
 static svn_error_t *
-merge_reintegrate_locked(const char *source_path_or_url,
+merge_reintegrate_locked(conflict_report_t **conflict_report,
+                         const char *source_path_or_url,
                          const svn_opt_revision_t *source_peg_revision,
                          const char *target_abspath,
                          svn_boolean_t diff_ignore_ancestry,
                          svn_boolean_t dry_run,
                          const apr_array_header_t *merge_options,
                          svn_client_ctx_t *ctx,
+                         apr_pool_t *result_pool,
                          apr_pool_t *scratch_pool)
 {
   svn_ra_session_t *target_ra_session, *source_ra_session;
@@ -11363,7 +11499,9 @@ merge_reintegrate_locked(const char *sou
      ### isn't "ancestral" even if it is (in the degenerate case where
      ### source-left equals YCA). */
   source->ancestral = FALSE;
-  err = merge_cousins_and_supplement_mergeinfo(target,
+  err = merge_cousins_and_supplement_mergeinfo(conflict_report,
+                                               &use_sleep,
+                                               target,
                                                target_ra_session,
                                                source_ra_session,
                                                source, yc_ancestor,
@@ -11373,15 +11511,14 @@ merge_reintegrate_locked(const char *sou
                                                FALSE /* force_delete */,
                                                FALSE /* record_only */,
                                                dry_run,
-                                               merge_options, &use_sleep,
-                                               ctx, scratch_pool);
+                                               merge_options,
+                                               ctx,
+                                               result_pool, scratch_pool);
 
   if (use_sleep)
     svn_io_sleep_for_timestamps(target_abspath, scratch_pool);
 
-  if (err)
-    return svn_error_trace(err);
-
+  SVN_ERR(err);
   return SVN_NO_ERROR;
 }
 
@@ -11395,23 +11532,27 @@ svn_client_merge_reintegrate(const char 
                              apr_pool_t *pool)
 {
   const char *target_abspath, *lock_abspath;
+  conflict_report_t *conflict_report;
 
   SVN_ERR(get_target_and_lock_abspath(&target_abspath, &lock_abspath,
                                       target_wcpath, ctx, pool));
 
   if (!dry_run)
     SVN_WC__CALL_WITH_WRITE_LOCK(
-      merge_reintegrate_locked(source_path_or_url, source_peg_revision,
+      merge_reintegrate_locked(&conflict_report,
+                               source_path_or_url, source_peg_revision,
                                target_abspath,
                                FALSE /*diff_ignore_ancestry*/,
-                               dry_run, merge_options, ctx, pool),
+                               dry_run, merge_options, ctx, pool, pool),
       ctx->wc_ctx, lock_abspath, FALSE /* lock_anchor */, pool);
   else
-    SVN_ERR(merge_reintegrate_locked(source_path_or_url, source_peg_revision,
+    SVN_ERR(merge_reintegrate_locked(&conflict_report,
+                                     source_path_or_url, source_peg_revision,
                                      target_abspath,
                                      FALSE /*diff_ignore_ancestry*/,
-                                     dry_run, merge_options, ctx, pool));
+                                     dry_run, merge_options, ctx, pool, pool));
 
+  SVN_ERR(make_merge_conflict_error(conflict_report, pool));
   return SVN_NO_ERROR;
 }
 
@@ -11421,7 +11562,8 @@ svn_client_merge_reintegrate(const char 
  * IGNORE_MERGEINFO and DIFF_IGNORE_ANCESTRY are as in do_merge().
  */
 static svn_error_t *
-merge_peg_locked(const char *source_path_or_url,
+merge_peg_locked(conflict_report_t **conflict_report,
+                 const char *source_path_or_url,
                  const svn_opt_revision_t *source_peg_revision,
                  const svn_rangelist_t *ranges_to_merge,
                  const char *target_abspath,
@@ -11434,6 +11576,7 @@ merge_peg_locked(const char *source_path
                  svn_boolean_t allow_mixed_rev,
                  const apr_array_header_t *merge_options,
                  svn_client_ctx_t *ctx,
+                 apr_pool_t *result_pool,
                  apr_pool_t *scratch_pool)
 {
   merge_target_t *target;
@@ -11447,12 +11590,12 @@ merge_peg_locked(const char *source_path
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(target_abspath));
 
-  /* Create a short lived session pool */
-  sesspool = svn_pool_create(scratch_pool);
-
   SVN_ERR(open_target_wc(&target, target_abspath,
                          allow_mixed_rev, TRUE, TRUE,
-                         ctx, sesspool, sesspool));
+                         ctx, scratch_pool, scratch_pool));
+
+  /* Create a short lived session pool */
+  sesspool = svn_pool_create(scratch_pool);
 
   /* Open an RA session to our source URL, and determine its root URL. */
   SVN_ERR(svn_client__ra_session_from_path2(
@@ -11464,26 +11607,28 @@ merge_peg_locked(const char *source_path
   SVN_ERR(normalize_merge_sources(&merge_sources, source_path_or_url,
                                   source_loc,
                                   ranges_to_merge, ra_session, ctx,
-                                  sesspool, sesspool));
+                                  scratch_pool, scratch_pool));
 
   /* Check for same_repos. */
   same_repos = is_same_repos(&target->loc, source_loc, TRUE /* strict_urls */);
 
   /* Do the real merge!  (We say with confidence that our merge
      sources are both ancestral and related.) */
-  err = do_merge(NULL, NULL, merge_sources, target, ra_session,
+  err = do_merge(NULL, NULL, conflict_report, &use_sleep,
+                 merge_sources, target, ra_session,
                  TRUE /*sources_related*/, same_repos, ignore_mergeinfo,
                  diff_ignore_ancestry, force_delete, dry_run,
                  record_only, NULL, FALSE, FALSE, depth, merge_options,
-                 &use_sleep, ctx, sesspool, sesspool);
-
-  if (use_sleep)
-    svn_io_sleep_for_timestamps(target_abspath, sesspool);
+                 ctx, result_pool, scratch_pool);
 
   /* We're done with our RA session. */
   svn_pool_destroy(sesspool);
 
-  return svn_error_trace(err);
+  if (use_sleep)
+    svn_io_sleep_for_timestamps(target_abspath, scratch_pool);
+
+  SVN_ERR(err);
+  return SVN_NO_ERROR;
 }
 
 svn_error_t *
@@ -11503,6 +11648,7 @@ svn_client_merge_peg5(const char *source
                       apr_pool_t *pool)
 {
   const char *target_abspath, *lock_abspath;
+  conflict_report_t *conflict_report;
 
   /* No ranges to merge?  No problem. */
   if (ranges_to_merge->nelts == 0)
@@ -11513,21 +11659,24 @@ svn_client_merge_peg5(const char *source
 
   if (!dry_run)
     SVN_WC__CALL_WITH_WRITE_LOCK(
-      merge_peg_locked(source_path_or_url, source_peg_revision,
+      merge_peg_locked(&conflict_report,
+                       source_path_or_url, source_peg_revision,
                        ranges_to_merge,
                        target_abspath, depth, ignore_mergeinfo,
                        diff_ignore_ancestry,
                        force_delete, record_only, dry_run,
-                       allow_mixed_rev, merge_options, ctx, pool),
+                       allow_mixed_rev, merge_options, ctx, pool, pool),
       ctx->wc_ctx, lock_abspath, FALSE /* lock_anchor */, pool);
   else
-    SVN_ERR(merge_peg_locked(source_path_or_url, source_peg_revision,
+    SVN_ERR(merge_peg_locked(&conflict_report,
+                       source_path_or_url, source_peg_revision,
                        ranges_to_merge,
                        target_abspath, depth, ignore_mergeinfo,
                        diff_ignore_ancestry,
                        force_delete, record_only, dry_run,
-                       allow_mixed_rev, merge_options, ctx, pool));
+                       allow_mixed_rev, merge_options, ctx, pool, pool));
 
+  SVN_ERR(make_merge_conflict_error(conflict_report, pool));
   return SVN_NO_ERROR;
 }
 
@@ -12023,9 +12172,10 @@ svn_client_find_automatic_merge(svn_clie
                          ctx, result_pool, scratch_pool));
 
   /* Open RA sessions to the source and target trees. */
-  SVN_ERR(svn_client_open_ra_session(&s_t->target_ra_session,
-                                     s_t->target->loc.url,
-                                     ctx, result_pool));
+  SVN_ERR(svn_client_open_ra_session2(&s_t->target_ra_session,
+                                      s_t->target->loc.url,
+                                      s_t->target->abspath,
+                                      ctx, result_pool, scratch_pool));
   /* ### check for null URL (i.e. added path) here, like in reintegrate? */
   SVN_ERR(svn_client__ra_session_from_path2(
             &s_t->source_ra_session, &s_t->source,
@@ -12080,7 +12230,8 @@ svn_client_find_automatic_merge(svn_clie
  * eliminate already-cherry-picked revisions from the source.
  */
 static svn_error_t *
-do_automatic_merge_locked(const svn_client_automatic_merge_t *merge,
+do_automatic_merge_locked(conflict_report_t **conflict_report,
+                          const svn_client_automatic_merge_t *merge,
                           const char *target_abspath,
                           svn_depth_t depth,
                           svn_boolean_t diff_ignore_ancestry,
@@ -12089,6 +12240,7 @@ do_automatic_merge_locked(const svn_clie
                           svn_boolean_t dry_run,
                           const apr_array_header_t *merge_options,
                           svn_client_ctx_t *ctx,
+                          apr_pool_t *result_pool,
                           apr_pool_t *scratch_pool)
 {
   merge_target_t *target;
@@ -12128,11 +12280,11 @@ do_automatic_merge_locked(const svn_clie
                                   "cannot be used with this kind of merge"));
 
       SVN_ERR(ensure_ra_session_url(&base_ra_session, merge->base->url,
-                                    ctx, scratch_pool));
+                                    target->abspath, ctx, scratch_pool));
       SVN_ERR(ensure_ra_session_url(&right_ra_session, merge->right->url,
-                                    ctx, scratch_pool));
+                                    target->abspath, ctx, scratch_pool));
       SVN_ERR(ensure_ra_session_url(&target_ra_session, target->loc.url,
-                                    ctx, scratch_pool));
+                                    target->abspath, ctx, scratch_pool));
 
       /* Check for and reject any abnormalities -- such as revisions that
        * have not yet been merged in the opposite direction -- that a
@@ -12150,7 +12302,9 @@ do_automatic_merge_locked(const svn_clie
       source.loc2 = merge->right;
       source.ancestral = ! merge->is_reintegrate_like;
 
-      err = merge_cousins_and_supplement_mergeinfo(target,
+      err = merge_cousins_and_supplement_mergeinfo(conflict_report,
+                                                   &use_sleep,
+                                                   target,
                                                    base_ra_session,
                                                    right_ra_session,
                                                    &source, merge->yca,
@@ -12159,8 +12313,9 @@ do_automatic_merge_locked(const svn_clie
                                                    FALSE /*diff_ignore_ancestry*/,
                                                    force_delete, record_only,
                                                    dry_run,
-                                                   merge_options, &use_sleep,
-                                                   ctx, scratch_pool);
+                                                   merge_options,
+                                                   ctx,
+                                                   result_pool, scratch_pool);
     }
   else /* ! merge->is_reintegrate_like */
     {
@@ -12179,19 +12334,20 @@ do_automatic_merge_locked(const svn_clie
       /* Normalize our merge sources, do_merge() requires this.  See the
          'MERGEINFO MERGE SOURCE NORMALIZATION' global comment. */
       SVN_ERR(ensure_ra_session_url(&ra_session, merge->right->url,
-                                    ctx, scratch_pool));
+                                    target->abspath, ctx, scratch_pool));
       SVN_ERR(normalize_merge_sources_internal(
         &merge_sources, merge->right,
         svn_rangelist__initialize(merge->yca->rev, merge->right->rev, TRUE,
                                   scratch_pool),
         ra_session, ctx, scratch_pool, scratch_pool));
 
-      err = do_merge(NULL, NULL, merge_sources, target, ra_session,
+      err = do_merge(NULL, NULL, conflict_report, &use_sleep,
+                     merge_sources, target, ra_session,
                      TRUE /*related*/, TRUE /*same_repos*/,
                      FALSE /*ignore_mergeinfo*/, diff_ignore_ancestry,
                      force_delete, dry_run,
                      record_only, NULL, FALSE, FALSE, depth, merge_options,
-                     &use_sleep, ctx, scratch_pool, scratch_pool);
+                     ctx, result_pool, scratch_pool);
     }
 
   if (use_sleep)
@@ -12215,25 +12371,29 @@ svn_client_do_automatic_merge(const svn_
                               apr_pool_t *pool)
 {
   const char *target_abspath, *lock_abspath;
+  conflict_report_t *conflict_report;
 
   SVN_ERR(get_target_and_lock_abspath(&target_abspath, &lock_abspath,
                                       target_wcpath, ctx, pool));
 
   if (!dry_run)
     SVN_WC__CALL_WITH_WRITE_LOCK(
-      do_automatic_merge_locked(merge,
+      do_automatic_merge_locked(&conflict_report,
+                                merge,
                                 target_abspath, depth,
                                 diff_ignore_ancestry,
                                 force_delete, record_only, dry_run,
-                                merge_options, ctx, pool),
+                                merge_options, ctx, pool, pool),
       ctx->wc_ctx, lock_abspath, FALSE /* lock_anchor */, pool);
   else
-    SVN_ERR(do_automatic_merge_locked(merge,
+    SVN_ERR(do_automatic_merge_locked(&conflict_report,
+                                merge,
                                 target_abspath, depth,
                                 diff_ignore_ancestry,
                                 force_delete, record_only, dry_run,
-                                merge_options, ctx, pool));
+                                merge_options, ctx, pool, pool));
 
+  SVN_ERR(make_merge_conflict_error(conflict_report, pool));
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/mergeinfo.c?rev=1457684&r1=1457683&r2=1457684&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/mergeinfo.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/mergeinfo.c Mon Mar 18 09:35:24 2013
@@ -161,6 +161,9 @@ svn_client__record_wc_mergeinfo_catalog(
       apr_array_header_t *sorted_cat =
         svn_sort__hash(result_catalog, svn_sort_compare_items_as_paths,
                        scratch_pool);
+
+      /* Write the mergeinfo out in sorted order of the paths (presumably just
+       * so that the notifications are in a predictable, convenient order). */
       for (i = 0; i < sorted_cat->nelts; i++)
         {
           svn_sort__item_t elt = APR_ARRAY_IDX(sorted_cat, i,
@@ -217,8 +220,10 @@ 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(&base_revision, NULL, NULL, NULL, NULL,
+  SVN_ERR(svn_wc__node_get_base(NULL, &base_revision, NULL, NULL, NULL, NULL,
                                 ctx->wc_ctx, local_abspath,
+                                TRUE /* ignore_enoent */,
+                                FALSE /* show_hidden */,
                                 scratch_pool, scratch_pool));
 
   iterpool = svn_pool_create(scratch_pool);
@@ -286,9 +291,15 @@ 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(&parent_base_rev, NULL, NULL, NULL,
-                                        NULL, ctx->wc_ctx, local_abspath,
+          SVN_ERR(svn_wc__node_get_base(NULL, &parent_base_rev, NULL, NULL,
+                                        NULL, NULL,
+                                        ctx->wc_ctx, local_abspath,
+                                        TRUE, FALSE,
                                         scratch_pool, scratch_pool));
+
+          /* ### This checks the WORKING changed_rev, so invalid on replacement
+             ### not even reliable in case an ancestor was copied from a
+             ### different location */
           SVN_ERR(svn_wc__node_get_changed_info(&parent_changed_rev,
                                                 NULL, NULL,
                                                 ctx->wc_ctx, local_abspath,
@@ -677,9 +688,9 @@ svn_client__get_wc_or_repos_mergeinfo_ca
               if (! ra_session)
                 {
                   sesspool = svn_pool_create(scratch_pool);
-                  SVN_ERR(svn_client__open_ra_session_internal(
-                              &ra_session, NULL, url, NULL, NULL, FALSE,
-                              TRUE, ctx, sesspool));
+                  SVN_ERR(svn_client_open_ra_session2(&ra_session, url, NULL,
+                                                      ctx,
+                                                      sesspool, sesspool));
                 }
 
               SVN_ERR(svn_client__get_repos_mergeinfo_catalog(

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/mergeinfo.h
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/mergeinfo.h?rev=1457684&r1=1457683&r2=1457684&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/mergeinfo.h (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/mergeinfo.h Mon Mar 18 09:35:24 2013
@@ -339,7 +339,12 @@ svn_client__record_wc_mergeinfo(const ch
                                 svn_client_ctx_t *ctx,
                                 apr_pool_t *scratch_pool);
 
-/* Write mergeinfo into the WC.  RESULT_CATALOG maps (const char *) WC paths
+/* Write mergeinfo into the WC.
+ *
+ * For each path in RESULT_CATALOG, set the SVN_PROP_MERGEINFO
+ * property to represent the given mergeinfo, or remove the property
+ * if the given mergeinfo is null, and notify the change.  Leave
+ * other paths unchanged.  RESULT_CATALOG maps (const char *) WC paths
  * to (svn_mergeinfo_t) mergeinfo. */
 svn_error_t *
 svn_client__record_wc_mergeinfo_catalog(apr_hash_t *result_catalog,



Mime
View raw message