subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From s...@apache.org
Subject svn commit: r1779687 - in /subversion/trunk/subversion: include/svn_client.h libsvn_client/conflicts.c svn/cl.h svn/conflict-callbacks.c svn/resolve-cmd.c
Date Fri, 20 Jan 2017 22:45:09 GMT
Author: stsp
Date: Fri Jan 20 22:45:09 2017
New Revision: 1779687

URL: http://svn.apache.org/viewvc?rev=1779687&view=rev
Log:
Reintroduce the svn_client_conflict_walk() API.

This new implementation is based on the conflict walk we implemented in
the 'svn' command line client. The command line client now relies on the
client library to walk conflicts in the working copy.

This avoids forcing other clients to reimplement the status walk logic which
is rather complex since it needs to handle new tree conflicts which may appear
when another tree conflict gets resolved. It should make the transtion to the
new conflict API easier for third party clients since the new resolver can now
be invoked in a similar way to the old libsvn_wc conflict handler.

Suggested by: ivan
(during the October 2016 hackathon in Berlin)

* subversion/include/svn_client.h
  (svn_client_conflict_walk_func_t, svn_client_conflict_walk): Declare.

* subversion/libsvn_client/conflicts.c
  (conflict_status_walker_baton, tree_conflict_collector,
   handle_tree_conflict_resolution_failure, conflict_status_walker,
   svn_client_conflict_walk): New implementation of a conflict status walker.
   Based on, and very similar to, code from svn/resolve-cmd.c.

* subversion/svn/cl.h,
  subversion/svn/conflict-callbacks.c
  (svn_cl__resolve_conflict): Remove now unused output paramer 'resolved',
   and redundant parameter config (ctx->config can be used instead).

* subversion/svn/resolve-cmd.c
  (conflict_status_walker_baton): Replace with...
  (conflict_walker_baton): ... this, which contains only a subset of the fields.
  (tree_conflict_collector, handle_tree_conflict_resolution_failure,
   conflict_status_walker, walk_conflicts): Remove.
  (conflict_walker): A callback for the new conflict walker.
  (svn_cl__walk_conflicts): Use the new conflict walker provided by the
   libsvn_client library instead of the previous inline implementation.

Modified:
    subversion/trunk/subversion/include/svn_client.h
    subversion/trunk/subversion/libsvn_client/conflicts.c
    subversion/trunk/subversion/svn/cl.h
    subversion/trunk/subversion/svn/conflict-callbacks.c
    subversion/trunk/subversion/svn/resolve-cmd.c

Modified: subversion/trunk/subversion/include/svn_client.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_client.h?rev=1779687&r1=1779686&r2=1779687&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_client.h (original)
+++ subversion/trunk/subversion/include/svn_client.h Fri Jan 20 22:45:09 2017
@@ -4563,6 +4563,40 @@ svn_client_conflict_get(svn_client_confl
                         apr_pool_t *scratch_pool);
 
 /**
+ * Callback for svn_client_conflict_conflict_walk();
+ *
+ * The lifetime of @a conflict is limited. Its allocation in
+ * memory will not persist beyond this callback's execution.
+ * 
+ * @since New in 1.10.
+ */
+typedef svn_error_t *(*svn_client_conflict_walk_func_t)(
+  void *baton,
+  svn_client_conflict_t *conflict,
+  apr_pool_t *scratch_pool);
+
+/**
+ * Walk all conflicts within the specified @a depth of @a local_abspath.
+ * Pass each conflict found during the walk to the @conflict_walk_func
+ * callback, along with @a conflict_walk_func_baton.
+ * Use cancellation and notification support provided by client context @a ctx.
+ * 
+ * This callback may choose to resolve the conflict. If the act of resolving
+ * a conflict creates new conflicts within the walked working copy (as might
+ * be the case for some tree conflicts), the callback will be invoked for each
+ * such new conflict as well.
+ * 
+ * @since New in 1.10.
+ */
+svn_error_t *
+svn_client_conflict_walk(const char *local_abspath,
+                         svn_depth_t depth,
+                         svn_client_conflict_walk_func_t conflict_walk_func,
+                         void *conflict_walk_func_baton,
+                         svn_client_ctx_t *ctx,
+                         apr_pool_t *scratch_pool);
+
+/**
 * Indicate the types of conflicts present on the working copy node
 * described by @a conflict. Any output argument may be @c NULL if
 * the caller is not interested in the status of a particular type.

Modified: subversion/trunk/subversion/libsvn_client/conflicts.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/conflicts.c?rev=1779687&r1=1779686&r2=1779687&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/conflicts.c (original)
+++ subversion/trunk/subversion/libsvn_client/conflicts.c Fri Jan 20 22:45:09 2017
@@ -10230,3 +10230,246 @@ svn_client_conflict_get(svn_client_confl
 
   return SVN_NO_ERROR;
 }
+
+/* Baton for conflict_status_walker */
+struct conflict_status_walker_baton
+{
+  svn_client_conflict_walk_func_t conflict_walk_func;
+  void *conflict_walk_func_baton;
+  svn_client_ctx_t *ctx;
+  svn_wc_notify_func2_t notify_func;
+  void *notify_baton;
+  svn_boolean_t resolved_a_tree_conflict;
+  apr_hash_t *unresolved_tree_conflicts;
+};
+
+/* Implements svn_wc_notify_func2_t to collect new conflicts caused by
+   resolving a tree conflict. */
+static void
+tree_conflict_collector(void *baton,
+                        const svn_wc_notify_t *notify,
+                        apr_pool_t *pool)
+{
+  struct conflict_status_walker_baton *cswb = baton;
+
+  if (cswb->notify_func)
+    cswb->notify_func(cswb->notify_baton, notify, pool);
+
+  if (cswb->unresolved_tree_conflicts
+      && (notify->action == svn_wc_notify_tree_conflict
+          || notify->prop_state == svn_wc_notify_state_conflicted
+          || notify->content_state == svn_wc_notify_state_conflicted))
+    {
+      if (!svn_hash_gets(cswb->unresolved_tree_conflicts, notify->path))
+        {
+          const char *tc_abspath;
+          apr_pool_t *hash_pool;
+ 
+          hash_pool = apr_hash_pool_get(cswb->unresolved_tree_conflicts);
+          tc_abspath = apr_pstrdup(hash_pool, notify->path);
+          svn_hash_sets(cswb->unresolved_tree_conflicts, tc_abspath, "");
+        }
+    }
+}
+
+/* 
+ * Record a tree conflict resolution failure due to error condition ERR
+ * in the RESOLVE_LATER hash table. If the hash table is not available
+ * (meaning the caller does not wish to retry resolution later), or if
+ * the error condition does not indicate circumstances where another
+ * existing tree conflict is blocking the resolution attempt, then
+ * return the error ERR itself.
+ */
+static svn_error_t *
+handle_tree_conflict_resolution_failure(const char *local_abspath,
+                                        svn_error_t *err,
+                                        apr_hash_t *unresolved_tree_conflicts)
+{
+  const char *dup_abspath;
+
+  if (!unresolved_tree_conflicts
+      || (err->apr_err != SVN_ERR_WC_OBSTRUCTED_UPDATE
+          && err->apr_err != SVN_ERR_WC_FOUND_CONFLICT))
+    return svn_error_trace(err); /* Give up. Do not retry resolution later. */
+
+  svn_error_clear(err);
+  dup_abspath = apr_pstrdup(apr_hash_pool_get(unresolved_tree_conflicts),
+                            local_abspath);
+
+  svn_hash_sets(unresolved_tree_conflicts, dup_abspath, dup_abspath);
+
+  return SVN_NO_ERROR; /* Caller may retry after resolving other conflicts. */
+}
+
+/* Implements svn_wc_status4_t to walk all conflicts to resolve.
+ */
+static svn_error_t *
+conflict_status_walker(void *baton,
+                       const char *local_abspath,
+                       const svn_wc_status3_t *status,
+                       apr_pool_t *scratch_pool)
+{
+  struct conflict_status_walker_baton *cswb = baton;
+  svn_client_conflict_t *conflict;
+  svn_error_t *err;
+  svn_boolean_t tree_conflicted;
+
+  if (!status->conflicted)
+    return SVN_NO_ERROR;
+
+  SVN_ERR(svn_client_conflict_get(&conflict, local_abspath, cswb->ctx,
+                                  scratch_pool, scratch_pool));
+  SVN_ERR(svn_client_conflict_get_conflicted(NULL, NULL, &tree_conflicted,
+                                             conflict, scratch_pool,
+                                             scratch_pool));
+  err = cswb->conflict_walk_func(cswb->conflict_walk_func_baton,
+                                 conflict, scratch_pool);
+  if (err)
+    {
+      if (tree_conflicted)
+        SVN_ERR(handle_tree_conflict_resolution_failure(
+                  local_abspath, err, cswb->unresolved_tree_conflicts));
+
+      else
+        return svn_error_trace(err);
+    }
+
+  if (tree_conflicted)
+    {
+      svn_client_conflict_option_id_t resolution;
+
+      resolution = svn_client_conflict_tree_get_resolution(conflict);
+      if (resolution != svn_client_conflict_option_unspecified &&
+          resolution != svn_client_conflict_option_postpone)
+        cswb->resolved_a_tree_conflict = TRUE;
+    }
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_conflict_walk(const char *local_abspath,
+                         svn_depth_t depth,
+                         svn_client_conflict_walk_func_t conflict_walk_func,
+                         void *conflict_walk_func_baton,
+                         svn_client_ctx_t *ctx,
+                         apr_pool_t *scratch_pool)
+{
+  struct conflict_status_walker_baton cswb;
+  apr_pool_t *iterpool = NULL;
+  svn_error_t *err = SVN_NO_ERROR;
+
+  if (depth == svn_depth_unknown)
+    depth = svn_depth_infinity;
+
+  cswb.conflict_walk_func = conflict_walk_func;
+  cswb.conflict_walk_func_baton = conflict_walk_func_baton;
+  cswb.ctx = ctx;
+  cswb.resolved_a_tree_conflict = FALSE;
+  cswb.unresolved_tree_conflicts = apr_hash_make(scratch_pool);
+
+  if (ctx->notify_func2)
+    ctx->notify_func2(ctx->notify_baton2,
+                      svn_wc_create_notify(
+                        local_abspath,
+                        svn_wc_notify_conflict_resolver_starting,
+                        scratch_pool),
+                      scratch_pool);
+
+  /* Swap in our notify_func wrapper. We must revert this before returning! */
+  cswb.notify_func = ctx->notify_func2;
+  cswb.notify_baton = ctx->notify_baton2;
+  ctx->notify_func2 = tree_conflict_collector;
+  ctx->notify_baton2 = &cswb;
+
+  err = svn_wc_walk_status(ctx->wc_ctx,
+                           local_abspath,
+                           depth,
+                           FALSE /* get_all */,
+                           FALSE /* no_ignore */,
+                           TRUE /* ignore_text_mods */,
+                           NULL /* ignore_patterns */,
+                           conflict_status_walker, &cswb,
+                           ctx->cancel_func, ctx->cancel_baton,
+                           scratch_pool);
+
+  /* If we got new tree conflicts (or delayed conflicts) during the initial
+     walk, we now walk them one by one as closure. */
+  while (!err && cswb.unresolved_tree_conflicts &&
+         apr_hash_count(cswb.unresolved_tree_conflicts))
+    {
+      apr_hash_index_t *hi;
+      svn_wc_status3_t *status = NULL;
+      const char *tc_abspath = NULL;
+
+      if (iterpool)
+        svn_pool_clear(iterpool);
+      else
+        iterpool = svn_pool_create(scratch_pool);
+
+      hi = apr_hash_first(scratch_pool, cswb.unresolved_tree_conflicts);
+      cswb.unresolved_tree_conflicts = apr_hash_make(scratch_pool);
+      cswb.resolved_a_tree_conflict = FALSE;
+
+      for (; hi && !err; hi = apr_hash_next(hi))
+        {
+          svn_pool_clear(iterpool);
+
+          tc_abspath = apr_hash_this_key(hi);
+
+          if (ctx->cancel_func)
+            {
+              err = ctx->cancel_func(ctx->cancel_baton);
+              if (err)
+                break;
+            }
+
+          err = svn_error_trace(svn_wc_status3(&status, ctx->wc_ctx,
+                                               tc_abspath,
+                                               iterpool, iterpool));
+          if (err)
+            break;
+
+          err = svn_error_trace(conflict_status_walker(&cswb, tc_abspath,
+                                                       status, scratch_pool));
+          if (err)
+            break;
+        }
+  
+      if (!err && !cswb.resolved_a_tree_conflict && tc_abspath &&
+          apr_hash_count(cswb.unresolved_tree_conflicts))
+        {
+          /* None of the remaining conflicts got resolved, without any error.
+           * Disable the 'unresolved_tree_conflicts' cache and try again. */
+          cswb.unresolved_tree_conflicts = NULL;
+
+          /* Run the most recent resolve operation again.
+           * We still have status and tc_abspath for that one.
+           * This should uncover the error which prevents resolution. */
+          err = svn_error_trace(conflict_status_walker(&cswb, tc_abspath,
+                                                       status, scratch_pool));
+          SVN_ERR_ASSERT(err != NULL);
+
+          err = svn_error_createf(
+                    SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, err,
+                    _("Unable to resolve pending conflict on '%s'"),
+                    svn_dirent_local_style(tc_abspath, scratch_pool));
+          break;
+        }
+    }
+
+  if (iterpool)
+    svn_pool_destroy(iterpool);
+
+  ctx->notify_func2 = cswb.notify_func;
+  ctx->notify_baton2 = cswb.notify_baton;
+
+  if (!err && ctx->notify_func2)
+    ctx->notify_func2(ctx->notify_baton2,
+                      svn_wc_create_notify(local_abspath,
+                                          svn_wc_notify_conflict_resolver_done,
+                                          scratch_pool),
+                      scratch_pool);
+
+  return svn_error_trace(err);
+}

Modified: subversion/trunk/subversion/svn/cl.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/cl.h?rev=1779687&r1=1779686&r2=1779687&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/cl.h (original)
+++ subversion/trunk/subversion/svn/cl.h Fri Jan 20 22:45:09 2017
@@ -384,14 +384,12 @@ svn_cl__print_conflict_stats(svn_cl__con
  * TODO: more docs
  */
 svn_error_t *
-svn_cl__resolve_conflict(svn_boolean_t *resolved,
-                         svn_boolean_t *quit,
+svn_cl__resolve_conflict(svn_boolean_t *quit,
                          svn_boolean_t *external_failed,
                          svn_boolean_t *printed_summary,
                          svn_client_conflict_t *conflict,
                          svn_cl__accept_t accept_which,
                          const char *editor_cmd,
-                         apr_hash_t *config,
                          const char *path_prefix,
                          svn_cmdline_prompt_baton_t *pb,
                          svn_cl__conflict_stats_t *conflict_stats,

Modified: subversion/trunk/subversion/svn/conflict-callbacks.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/conflict-callbacks.c?rev=1779687&r1=1779686&r2=1779687&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/conflict-callbacks.c (original)
+++ subversion/trunk/subversion/svn/conflict-callbacks.c Fri Jan 20 22:45:09 2017
@@ -1875,14 +1875,12 @@ resolve_conflict_interactively(svn_boole
 }
 
 svn_error_t *
-svn_cl__resolve_conflict(svn_boolean_t *resolved,
-                         svn_boolean_t *quit,
+svn_cl__resolve_conflict(svn_boolean_t *quit,
                          svn_boolean_t *external_failed,
                          svn_boolean_t *printed_summary,
                          svn_client_conflict_t *conflict,
                          svn_cl__accept_t accept_which,
                          const char *editor_cmd,
-                         apr_hash_t *config,
                          const char *path_prefix,
                          svn_cmdline_prompt_baton_t *pb,
                          svn_cl__conflict_stats_t *conflict_stats,
@@ -2006,7 +2004,8 @@ svn_cl__resolve_conflict(svn_boolean_t *
               svn_error_t *err;
 
               err = svn_cmdline__edit_file_externally(local_abspath,
-                                                      editor_cmd, config,
+                                                      editor_cmd,
+                                                      ctx->config,
                                                       scratch_pool);
               if (err && (err->apr_err == SVN_ERR_CL_NO_EXTERNAL_EDITOR ||
                           err->apr_err == SVN_ERR_EXTERNAL_PROGRAM))
@@ -2054,7 +2053,7 @@ svn_cl__resolve_conflict(svn_boolean_t *
 
               err = svn_cl__merge_file_externally(base_abspath, their_abspath,
                                                   my_abspath, local_abspath,
-                                                  local_abspath, config,
+                                                  local_abspath, ctx->config,
                                                   &remains_in_conflict,
                                                   scratch_pool);
               if (err && (err->apr_err == SVN_ERR_CL_NO_EXTERNAL_MERGE_TOOL ||
@@ -2086,20 +2085,21 @@ svn_cl__resolve_conflict(svn_boolean_t *
    * option or the option did not apply, then prompt. */
   if (option_id == svn_client_conflict_option_unspecified)
     {
+      svn_boolean_t resolved = FALSE;
       svn_boolean_t postponed = FALSE;
       svn_boolean_t printed_description = FALSE;
       svn_error_t *err;
 
       *quit = FALSE;
 
-      while (!*resolved && !postponed && !*quit)
+      while (!resolved && !postponed && !*quit)
         {
-          err = resolve_conflict_interactively(resolved, &postponed, quit,
+          err = resolve_conflict_interactively(&resolved, &postponed, quit,
                                                external_failed,
                                                printed_summary,
                                                &printed_description,
                                                conflict,
-                                               editor_cmd, config,
+                                               editor_cmd, ctx->config,
                                                path_prefix, pb,
                                                conflict_stats, ctx,
                                                scratch_pool, scratch_pool);
@@ -2115,20 +2115,13 @@ svn_cl__resolve_conflict(svn_boolean_t *
           SVN_ERR(err);
         }
     }
-  else if (option_id == svn_client_conflict_option_postpone)
-    {
-      *resolved = FALSE;
-    }
   else
-    {
-      SVN_ERR(mark_conflict_resolved(conflict, option_id,
-                                     text_conflicted,
-                                     props_conflicted->nelts > 0 ? "" : NULL,
-                                     tree_conflicted,
-                                     path_prefix, conflict_stats,
-                                     ctx, scratch_pool));
-      *resolved = TRUE;
-    }
+    SVN_ERR(mark_conflict_resolved(conflict, option_id,
+                                   text_conflicted,
+                                   props_conflicted->nelts > 0 ? "" : NULL,
+                                   tree_conflicted,
+                                   path_prefix, conflict_stats,
+                                   ctx, scratch_pool));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/trunk/subversion/svn/resolve-cmd.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/resolve-cmd.c?rev=1779687&r1=1779686&r2=1779687&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/resolve-cmd.c (original)
+++ subversion/trunk/subversion/svn/resolve-cmd.c Fri Jan 20 22:45:09 2017
@@ -39,295 +39,32 @@
 
 /*** Code. ***/
 
-/* Baton for conflict_status_walker */
-struct conflict_status_walker_baton
+struct conflict_walker_baton
 {
   svn_client_ctx_t *ctx;
-  svn_wc_notify_func2_t notify_func;
-  void *notify_baton;
-  svn_boolean_t resolved_one;
-  apr_hash_t *resolve_later;
   svn_cl__accept_t accept_which;
   svn_boolean_t *quit;
   svn_boolean_t *external_failed;
   svn_boolean_t *printed_summary;
   const char *editor_cmd;
-  apr_hash_t *config;
   const char *path_prefix;
   svn_cmdline_prompt_baton_t *pb;
   svn_cl__conflict_stats_t *conflict_stats;
 };
 
-/* Implements svn_wc_notify_func2_t to collect new conflicts caused by
-   resolving a tree conflict. */
-static void
-tree_conflict_collector(void *baton,
-                        const svn_wc_notify_t *notify,
-                        apr_pool_t *pool)
-{
-  struct conflict_status_walker_baton *cswb = baton;
-
-  if (cswb->notify_func)
-    cswb->notify_func(cswb->notify_baton, notify, pool);
-
-  if (cswb->resolve_later
-      && (notify->action == svn_wc_notify_tree_conflict
-          || notify->prop_state == svn_wc_notify_state_conflicted
-          || notify->content_state == svn_wc_notify_state_conflicted))
-    {
-      if (!svn_hash_gets(cswb->resolve_later, notify->path))
-        {
-          const char *dup_path;
-
-          dup_path = apr_pstrdup(apr_hash_pool_get(cswb->resolve_later),
-                                 notify->path);
-
-          svn_hash_sets(cswb->resolve_later, dup_path, dup_path);
-        }
-    }
-}
-
-/* 
- * Record a tree conflict resolution failure due to error condition ERR
- * in the RESOLVE_LATER hash table. If the hash table is not available
- * (meaning the caller does not wish to retry resolution later), or if
- * the error condition does not indicate circumstances where another
- * existing tree conflict is blocking the resolution attempt, then
- * return the error ERR itself.
- */
+/* Implements svn_client_conflict_walk_func_t. */
 static svn_error_t *
-handle_tree_conflict_resolution_failure(const char *local_abspath,
-                                        svn_error_t *err,
-                                        apr_hash_t *resolve_later)
+conflict_walker(void *baton, svn_client_conflict_t *conflict,
+                apr_pool_t *scratch_pool)
 {
-  const char *dup_abspath;
-
-  if (!resolve_later
-      || (err->apr_err != SVN_ERR_WC_OBSTRUCTED_UPDATE
-          && err->apr_err != SVN_ERR_WC_FOUND_CONFLICT))
-    return svn_error_trace(err); /* Give up. Do not retry resolution later. */
-
-  svn_error_clear(err);
-  dup_abspath = apr_pstrdup(apr_hash_pool_get(resolve_later),
-                            local_abspath);
-
-  svn_hash_sets(resolve_later, dup_abspath, dup_abspath);
-
-  return SVN_NO_ERROR; /* Caller may retry after resolving other conflicts. */
-}
-
-/* Implements svn_wc_status4_t to walk all conflicts to resolve.
- */
-static svn_error_t *
-conflict_status_walker(void *baton,
-                       const char *local_abspath,
-                       const svn_wc_status3_t *status,
-                       apr_pool_t *scratch_pool)
-{
-  struct conflict_status_walker_baton *cswb = baton;
-  apr_pool_t *iterpool;
-  svn_boolean_t resolved = FALSE;
-  svn_client_conflict_t *conflict;
-  svn_error_t *err;
-  svn_boolean_t tree_conflicted;
-
-  if (!status->conflicted)
-    return SVN_NO_ERROR;
-
-  iterpool = svn_pool_create(scratch_pool);
-
-  SVN_ERR(svn_client_conflict_get(&conflict, local_abspath, cswb->ctx,
-                                  iterpool, iterpool));
-  SVN_ERR(svn_client_conflict_get_conflicted(NULL, NULL, &tree_conflicted,
-                                             conflict, iterpool, iterpool));
-  err = svn_cl__resolve_conflict(&resolved, cswb->quit, cswb->external_failed,
-                                 cswb->printed_summary, conflict,
-                                 cswb->accept_which, cswb->editor_cmd,
-                                 cswb->config, cswb->path_prefix,
-                                 cswb->pb, cswb->conflict_stats,
-                                 cswb->ctx, scratch_pool);
-  if (err)
-    {
-      if (tree_conflicted)
-        SVN_ERR(handle_tree_conflict_resolution_failure(local_abspath, err,
-                                                        cswb->resolve_later));
-
-      else
-        return svn_error_trace(err);
-    }
-
-  if (resolved)
-    cswb->resolved_one = TRUE;
-
-  svn_pool_destroy(iterpool);
-
-  /* If the has user decided to quit resolution, cancel the status walk. */
-  if (*cswb->quit)
-    return svn_error_create(SVN_ERR_CANCELLED, NULL, NULL);
-
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-walk_conflicts(svn_client_ctx_t *ctx,
-               const char *local_abspath,
-               svn_depth_t depth,
-               svn_cl__accept_t accept_which,
-               svn_boolean_t *quit,
-               svn_boolean_t *external_failed,
-               svn_boolean_t *printed_summary,
-               const char *editor_cmd,
-               apr_hash_t *config,
-               const char *path_prefix,
-               svn_cmdline_prompt_baton_t *pb,
-               svn_cl__conflict_stats_t *conflict_stats,
-               apr_pool_t *scratch_pool)
-{
-  struct conflict_status_walker_baton cswb;
-  apr_pool_t *iterpool = NULL;
-  svn_error_t *err;
-
-  if (depth == svn_depth_unknown)
-    depth = svn_depth_infinity;
-
-  cswb.ctx = ctx;
-
-  cswb.resolved_one = FALSE;
-  cswb.resolve_later = (depth != svn_depth_empty)
-                          ? apr_hash_make(scratch_pool)
-                          : NULL;
-
-  cswb.accept_which = accept_which;
-  cswb.quit = quit;
-  cswb.external_failed = external_failed;
-  cswb.printed_summary = printed_summary;
-  cswb.editor_cmd = editor_cmd;
-  cswb.config = config;
-  cswb.path_prefix = path_prefix;
-  cswb.pb = pb;
-  cswb.conflict_stats = conflict_stats;
-
-
-  /* ### call notify.c code */
-  if (ctx->notify_func2)
-    ctx->notify_func2(ctx->notify_baton2,
-                      svn_wc_create_notify(
-                        local_abspath,
-                        svn_wc_notify_conflict_resolver_starting,
-                        scratch_pool),
-                      scratch_pool);
-
-  cswb.notify_func = ctx->notify_func2;
-  cswb.notify_baton = ctx->notify_baton2;
-  ctx->notify_func2 = tree_conflict_collector;
-  ctx->notify_baton2 = &cswb;
-
-  err = svn_wc_walk_status(ctx->wc_ctx,
-                           local_abspath,
-                           depth,
-                           FALSE /* get_all */,
-                           FALSE /* no_ignore */,
-                           TRUE /* ignore_text_mods */,
-                           NULL /* ignore_patterns */,
-                           conflict_status_walker, &cswb,
-                           ctx->cancel_func, ctx->cancel_baton,
-                           scratch_pool);
-
-  /* If we got new tree conflicts (or delayed conflicts) during the initial
-     walk, we now walk them one by one as closure. */
-  while (!err && cswb.resolve_later && apr_hash_count(cswb.resolve_later))
-    {
-      apr_hash_index_t *hi;
-      svn_wc_status3_t *status = NULL;
-      const char *tc_abspath = NULL;
-
-      if (iterpool)
-        svn_pool_clear(iterpool);
-      else
-        iterpool = svn_pool_create(scratch_pool);
-
-      hi = apr_hash_first(scratch_pool, cswb.resolve_later);
-      cswb.resolve_later = apr_hash_make(scratch_pool);
-      cswb.resolved_one = FALSE;
-
-      for (; hi && !err; hi = apr_hash_next(hi))
-        {
-          svn_pool_clear(iterpool);
-
-          tc_abspath = apr_hash_this_key(hi);
-
-          if (ctx->cancel_func)
-            SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
-
-          SVN_ERR(svn_wc_status3(&status, ctx->wc_ctx, tc_abspath,
-                                 iterpool, iterpool));
-          err = svn_error_trace(conflict_status_walker(&cswb, tc_abspath,
-                                                       status, scratch_pool));
-        }
-
-      /* None of the remaining conflicts got resolved, and non did provide
-         an error...
-
-         We can fix that if we disable the 'resolve_later' option...
-       */
-      if (!cswb.resolved_one && !err && tc_abspath
-          && apr_hash_count(cswb.resolve_later))
-        {
-          /* Run the last resolve operation again. We still have status
-             and tc_abspath for that one. */
-
-          cswb.resolve_later = NULL; /* Produce proper error! */
-
-          /* Recreate the error */
-          err = svn_error_trace(conflict_status_walker(&cswb, tc_abspath,
-                                                       status, scratch_pool));
-
-          SVN_ERR_ASSERT(err != NULL);
-
-          err = svn_error_createf(
-                    SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, err,
-                    _("Unable to resolve pending conflict on '%s'"),
-                    svn_dirent_local_style(tc_abspath, scratch_pool));
-          break;
-        }
-    }
-
-  if (iterpool)
-    svn_pool_destroy(iterpool);
-
-  if (err)
-    {
-      if (err->apr_err == SVN_ERR_CANCELLED)
-        {
-          /* If QUIT is set, the user has selected the 'q' option at
-           * the conflict prompt and the status walk was aborted.
-           * This is not an error condition. */
-          if (quit)
-            {
-              svn_error_clear(err);
-              err = SVN_NO_ERROR;
-            }
-        }
-      else if (err->apr_err != SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE)
-        err = svn_error_createf(
-                    SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, err,
-                    _("Unable to resolve conflicts on '%s'"),
-                    svn_dirent_local_style(local_abspath, scratch_pool));
-
-      SVN_ERR(err);
-    }
-
-  ctx->notify_func2 = cswb.notify_func;
-  ctx->notify_baton2 = cswb.notify_baton;
-
-  /* ### call notify.c code */
-  if (ctx->notify_func2)
-    ctx->notify_func2(ctx->notify_baton2,
-                      svn_wc_create_notify(local_abspath,
-                                          svn_wc_notify_conflict_resolver_done,
-                                          scratch_pool),
-                      scratch_pool);
+  struct conflict_walker_baton *cwb = baton;
 
+  SVN_ERR(svn_cl__resolve_conflict(cwb->quit, cwb->external_failed,
+                                   cwb->printed_summary, conflict,
+                                   cwb->accept_which, cwb->editor_cmd,
+                                   cwb->path_prefix, cwb->pb,
+                                   cwb->conflict_stats,
+                                   cwb->ctx, scratch_pool));
   return SVN_NO_ERROR;
 }
 
@@ -343,6 +80,7 @@ svn_cl__walk_conflicts(apr_array_header_
   svn_boolean_t external_failed = FALSE;
   svn_boolean_t printed_summary = FALSE;
   svn_cmdline_prompt_baton_t *pb = apr_palloc(scratch_pool, sizeof(*pb));
+  struct conflict_walker_baton cwb = { 0 };
   const char *path_prefix;
   svn_error_t *err;
   int i;
@@ -353,6 +91,16 @@ svn_cl__walk_conflicts(apr_array_header_
   pb->cancel_func = ctx->cancel_func;
   pb->cancel_baton = ctx->cancel_baton;
 
+  cwb.ctx = ctx;
+  cwb.accept_which = opt_state->accept_which;
+  cwb.quit = &quit;
+  cwb.external_failed = &external_failed;
+  cwb.printed_summary = &printed_summary;
+  cwb.editor_cmd = opt_state->editor_cmd;
+  cwb.path_prefix = path_prefix;
+  cwb.pb = pb;
+  cwb.conflict_stats = conflict_stats;
+
   iterpool = svn_pool_create(scratch_pool);
   for (i = 0; i < targets->nelts; i++)
     {
@@ -368,27 +116,20 @@ svn_cl__walk_conflicts(apr_array_header_
 
       if (opt_state->depth == svn_depth_empty)
         {
-          svn_boolean_t resolved;
+          svn_boolean_t resolved; /*### not needed */
 
           SVN_ERR(svn_client_conflict_get(&conflict, local_abspath, ctx,
                                           iterpool, iterpool));
-          err = svn_cl__resolve_conflict(&resolved,
-                                         &quit, &external_failed,
+          err = svn_cl__resolve_conflict(&quit, &external_failed,
                                          &printed_summary,
                                          conflict, opt_state->accept_which,
                                          opt_state->editor_cmd,
-                                         ctx->config, path_prefix,
-                                         pb, conflict_stats,
+                                         path_prefix, pb, conflict_stats,
                                          ctx, iterpool);
         }
       else
-        {
-          err = walk_conflicts(ctx, local_abspath, opt_state->depth,
-                               opt_state->accept_which,
-                               &quit, &external_failed, &printed_summary,
-                               opt_state->editor_cmd, ctx->config,
-                               path_prefix, pb, conflict_stats, iterpool);
-        }
+        err = svn_client_conflict_walk(local_abspath, opt_state->depth,
+                                       conflict_walker, &cwb, ctx, iterpool);
 
       if (err)
         {



Mime
View raw message