You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2015/07/31 11:44:10 UTC

svn commit: r1693557 - in /subversion/trunk/subversion: include/svn_client.h libsvn_client/resolved.c

Author: stsp
Date: Fri Jul 31 09:44:10 2015
New Revision: 1693557

URL: http://svn.apache.org/r1693557
Log:
Bring back the svn_client_conflict_walk() API, this time implemented as a
thin wrapper on top of libsvn_wc's legacy conflict resolver, rather than
on top of the status walker. This avoids having to re-implement detection
of delayed or nested conflicts caused by tree conflict resolution.

The intention is to start using more svn_client_conflict APIs in the command
line client, which requires a conflict walk to implement its interactive mode.

Eventually, libsvn_wc will grow new conflict resolution abilities and we will
stop depending on legacy conflict resolution APIs within the new system.

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

* subversion/libsvn_client/resolved.c
  (svn_client_conflict_t): Add a 'resolution' field which stores the resolution
   option chosen by the user.
  (conflict_option_id_to_wc_conflict_choice): Move this helper function further
   up in the file to make it usable from more functions.
  (conflict_get_internal): Initialise conflict->resolution.
  (conflict_resolver_baton_t, conflict_resolver_func): New helper callback.
  (svn_client_conflict_walk): Implement on top of svn_wc__resolve_conflicts().
  (resolve_postpone, resolve_text_conflict, resolve_prop_conflict,
   resolve_tree_conflict): Store chosen resolution in conflict->resolution.

Modified:
    subversion/trunk/subversion/include/svn_client.h
    subversion/trunk/subversion/libsvn_client/resolved.c

Modified: subversion/trunk/subversion/include/svn_client.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_client.h?rev=1693557&r1=1693556&r2=1693557&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_client.h (original)
+++ subversion/trunk/subversion/include/svn_client.h Fri Jul 31 09:44:10 2015
@@ -4411,6 +4411,37 @@ svn_client_conflict_from_wc_description2
   apr_pool_t *scratch_pool);
 
 /**
+ * Callback for svn_client_conflict_walk_conflicts();
+ * 
+ * @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/resolved.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/resolved.c?rev=1693557&r1=1693556&r2=1693557&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/resolved.c (original)
+++ subversion/trunk/subversion/libsvn_client/resolved.c Fri Jul 31 09:44:10 2015
@@ -157,12 +157,61 @@ struct svn_client_conflict_t
   svn_client_ctx_t *ctx;
   apr_hash_t *prop_conflicts;
 
+  /* Indicates which option was chosen to resolve this conflict. */
+  svn_client_conflict_option_id_t resolution;
+
   /* For backwards compat. */
   const svn_wc_conflict_description2_t *legacy_text_conflict;
   const svn_wc_conflict_description2_t *legacy_prop_conflict;
   const svn_wc_conflict_description2_t *legacy_tree_conflict;
 };
 
+/*
+ * Return a legacy conflict choice corresponding to OPTION_ID.
+ * Return svn_wc_conflict_choose_undefined if no corresponding
+ * legacy conflict choice exists.
+ */
+static svn_wc_conflict_choice_t
+conflict_option_id_to_wc_conflict_choice(
+  svn_client_conflict_option_id_t option_id)
+{
+
+  switch (option_id)
+    {
+      case svn_client_conflict_option_undefined:
+        return svn_wc_conflict_choose_undefined;
+
+      case svn_client_conflict_option_postpone:
+        return svn_wc_conflict_choose_postpone;
+
+      case svn_client_conflict_option_base_text:
+        return svn_wc_conflict_choose_base;
+
+      case svn_client_conflict_option_incoming_new_text:
+        return svn_wc_conflict_choose_theirs_full;
+
+      case svn_client_conflict_option_working_text:
+        return svn_wc_conflict_choose_mine_full;
+
+      case svn_client_conflict_option_incoming_new_text_for_conflicted_hunks_only:
+        return svn_wc_conflict_choose_theirs_conflict;
+
+      case svn_client_conflict_option_working_text_for_conflicted_hunks_only:
+        return svn_wc_conflict_choose_mine_conflict;
+
+      case svn_client_conflict_option_merged_text:
+        return svn_wc_conflict_choose_merged;
+
+      case svn_client_conflict_option_unspecified:
+        return svn_wc_conflict_choose_unspecified;
+
+      default:
+        break;
+    }
+
+  return svn_wc_conflict_choose_undefined;
+}
+
 static void
 add_legacy_desc_to_conflict(const svn_wc_conflict_description2_t *desc,
                             svn_client_conflict_t *conflict,
@@ -206,12 +255,14 @@ conflict_get_internal(svn_client_conflic
     {
       /* Add a single legacy conflict descriptor. */
       (*conflict)->local_abspath = desc->local_abspath;
+      (*conflict)->resolution = svn_client_conflict_option_undefined;
       add_legacy_desc_to_conflict(desc, *conflict, result_pool);
 
       return SVN_NO_ERROR;
     }
 
   (*conflict)->local_abspath = apr_pstrdup(result_pool, local_abspath);
+  (*conflict)->resolution = svn_client_conflict_option_undefined;
   (*conflict)->ctx = ctx;
 
   /* Add all legacy conflict descriptors we can find. Eventually, this code
@@ -257,6 +308,87 @@ svn_client_conflict_from_wc_description2
                                                result_pool, scratch_pool));
 }
 
+/* Baton type for conflict_resolver_func(). */
+struct conflict_resolver_baton_t {
+
+  svn_client_conflict_walk_func_t *conflict_walk_func;
+  void *conflict_walk_func_baton;
+  svn_client_ctx_t *ctx;
+  
+} conflict_walk_baton_t;
+
+/* Implements svn_wc_conflict_resolver_func2_t for now because
+ * libsvn_wc does not support our new conflict type yet. */
+static svn_error_t *
+conflict_resolver_func(svn_wc_conflict_result_t **result,
+                       const svn_wc_conflict_description2_t *description,
+                       void *baton,
+                       apr_pool_t *result_pool,
+                       apr_pool_t *scratch_pool)
+{
+  struct conflict_resolver_baton_t *b = baton;
+  svn_client_conflict_t *conflict;
+  const char *local_abspath;
+  svn_wc_conflict_choice_t conflict_choice;
+
+  local_abspath = description->local_abspath;
+  SVN_ERR(svn_client_conflict_get(&conflict, local_abspath, b->ctx,
+                                  scratch_pool, scratch_pool));
+
+  SVN_ERR(b->conflict_walk_func(b->conflict_walk_func_baton,
+                                conflict, scratch_pool));
+
+  conflict_choice = conflict_option_id_to_wc_conflict_choice(
+                      conflict->resolution);
+  *result = svn_wc_create_conflict_result(conflict_choice, NULL,
+                                          result_pool);
+
+  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_resolver_baton_t b;
+  const char *lock_abspath;
+  svn_error_t *err;
+
+  b.conflict_walk_func = conflict_walk_func;
+  b.conflict_walk_func_baton = conflict_walk_func_baton;
+  b.ctx = ctx;
+
+  SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx,
+                                                 local_abspath,
+                                                 scratch_pool, scratch_pool));
+  /* ### TODO: svn_wc__resolve_conflicts() should be changed to support
+   * ### iteration without relying on svn_wc_conflict_resolver_func2_t */
+  err = svn_wc__resolve_conflicts(ctx->wc_ctx, local_abspath,
+                                  depth,
+                                  TRUE /* resolve_text */,
+                                  "" /* resolve_prop (ALL props) */,
+                                  TRUE /* resolve_tree */,
+                                  svn_wc_conflict_choose_unspecified,
+                                  conflict_resolver_func, &b,
+                                  ctx->cancel_func, ctx->cancel_baton,
+                                  ctx->notify_func2, ctx->notify_baton2,
+                                  scratch_pool);
+
+  err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx,
+                                                                 lock_abspath,
+                                                                 scratch_pool));
+  svn_io_sleep_for_timestamps(local_abspath, scratch_pool);
+
+  
+
+  return SVN_NO_ERROR;
+}
+
+/* Resolves conflict to OPTION and sets CONFLICT->RESOLUTION accordingly. */
 typedef svn_error_t *(*conflict_option_resolve_func_t)(
   svn_client_conflict_option_t *option,
   svn_client_conflict_t *conflict,
@@ -277,55 +409,10 @@ resolve_postpone(svn_client_conflict_opt
                  apr_pool_t *scratch_pool)
 {
   /* Nothing to do. */
+  conflict->resolution = svn_client_conflict_option_postpone;
   return SVN_NO_ERROR;
 }
 
-/*
- * Return a legacy conflict choice corresponding to OPTION_ID.
- * Return svn_wc_conflict_choose_undefined if no corresponding
- * legacy conflict choice exists.
- */
-static svn_wc_conflict_choice_t
-conflict_option_id_to_wc_conflict_choice(
-  svn_client_conflict_option_id_t option_id)
-{
-
-  switch (option_id)
-    {
-      case svn_client_conflict_option_undefined:
-        return svn_wc_conflict_choose_undefined;
-
-      case svn_client_conflict_option_postpone:
-        return svn_wc_conflict_choose_postpone;
-
-      case svn_client_conflict_option_base_text:
-        return svn_wc_conflict_choose_base;
-
-      case svn_client_conflict_option_incoming_new_text:
-        return svn_wc_conflict_choose_theirs_full;
-
-      case svn_client_conflict_option_working_text:
-        return svn_wc_conflict_choose_mine_full;
-
-      case svn_client_conflict_option_incoming_new_text_for_conflicted_hunks_only:
-        return svn_wc_conflict_choose_theirs_conflict;
-
-      case svn_client_conflict_option_working_text_for_conflicted_hunks_only:
-        return svn_wc_conflict_choose_mine_conflict;
-
-      case svn_client_conflict_option_merged_text:
-        return svn_wc_conflict_choose_merged;
-
-      case svn_client_conflict_option_unspecified:
-        return svn_wc_conflict_choose_unspecified;
-
-      default:
-        break;
-    }
-
-  return svn_wc_conflict_choose_undefined;
-}
-
 /* 
  * Resolve the conflict at LOCAL_ABSPATH. Currently only supports
  * an OPTION_ID which can be mapped to svn_wc_conflict_choice_t and
@@ -378,6 +465,7 @@ resolve_text_conflict(svn_client_conflic
   local_abspath = svn_client_conflict_get_local_abspath(conflict);
   SVN_ERR(resolve_conflict(id, local_abspath, TRUE, NULL, FALSE,
                            conflict->ctx, scratch_pool));
+  conflict->resolution = id;
 
   return SVN_NO_ERROR;
 }
@@ -394,6 +482,7 @@ resolve_prop_conflict(svn_client_conflic
   local_abspath = svn_client_conflict_get_local_abspath(conflict);
   SVN_ERR(resolve_conflict(id, local_abspath, FALSE, "", FALSE,
                            conflict->ctx, scratch_pool));
+  conflict->resolution = id;
 
   return SVN_NO_ERROR;
 }
@@ -410,6 +499,7 @@ resolve_tree_conflict(svn_client_conflic
   local_abspath = svn_client_conflict_get_local_abspath(conflict);
   SVN_ERR(resolve_conflict(id, local_abspath, FALSE, NULL, TRUE,
                            conflict->ctx, scratch_pool));
+  conflict->resolution = id;
 
   return SVN_NO_ERROR;
 }