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 2016/04/19 14:22:41 UTC

svn commit: r1739918 - /subversion/trunk/subversion/libsvn_client/conflicts.c

Author: stsp
Date: Tue Apr 19 12:22:41 2016
New Revision: 1739918

URL: http://svn.apache.org/viewvc?rev=1739918&view=rev
Log:
Reduce recently introduced code duplication in the conflict resolver.

* subversion/libsvn_client/conflicts.c
  (merge_incoming_added_file_replace): New. Shared implementation for ...
  (resolve_merge_incoming_added_file_replace,
   configure_option_merge_incoming_added_file_replace): ... these functions.

Modified:
    subversion/trunk/subversion/libsvn_client/conflicts.c

Modified: subversion/trunk/subversion/libsvn_client/conflicts.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/conflicts.c?rev=1739918&r1=1739917&r2=1739918&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/conflicts.c (original)
+++ subversion/trunk/subversion/libsvn_client/conflicts.c Tue Apr 19 12:22:41 2016
@@ -3727,12 +3727,14 @@ resolve_merge_incoming_added_file_text_m
   return SVN_NO_ERROR;
 }
 
-/* Implements conflict_option_resolve_func_t. */
+/* Resolve a file/file "incoming add vs local obstruction" tree conflict by
+ * replacing the local file with the incoming file. If MERGE_FILES is set,
+ * also merge the files after replacing. */
 static svn_error_t *
-resolve_merge_incoming_added_file_replace(
-  svn_client_conflict_option_t *option,
-  svn_client_conflict_t *conflict,
-  apr_pool_t *scratch_pool)
+merge_incoming_added_file_replace(svn_client_conflict_option_t *option,
+                                  svn_client_conflict_t *conflict,
+                                  svn_boolean_t merge_files,
+                                  apr_pool_t *scratch_pool)
 {
   svn_ra_session_t *ra_session;
   const char *url;
@@ -3753,9 +3755,6 @@ resolve_merge_incoming_added_file_replac
   const char *working_file_tmp_abspath;
   svn_stream_t *working_file_stream;
   apr_hash_t *working_props;
-  apr_file_t *empty_file;
-  const char *empty_file_abspath;
-  apr_array_header_t *propdiffs;
   svn_error_t *err;
 
   local_abspath = svn_client_conflict_get_local_abspath(conflict);
@@ -3782,10 +3781,6 @@ resolve_merge_incoming_added_file_replac
   SVN_ERR(svn_wc_prop_list2(&working_props, ctx->wc_ctx, local_abspath,
                             scratch_pool, scratch_pool));
 
-  /* Create a property diff against an empty base. */
-  SVN_ERR(svn_prop_diffs(&propdiffs, apr_hash_make(scratch_pool),
-                         working_props, scratch_pool));
-
   /* Fetch the incoming added file from the repository. */
   SVN_ERR(svn_client_conflict_get_incoming_new_repos_location(
             &incoming_new_repos_relpath, &incoming_new_pegrev,
@@ -3816,12 +3811,6 @@ resolve_merge_incoming_added_file_replac
   /* Reset the stream in preparation for adding its content to WC. */
   SVN_ERR(svn_stream_reset(incoming_new_stream));
 
-  /* Create an empty file as fake "merge-base" for the two added files.
-   * The files are not ancestrally related so this is the best we can do. */
-  SVN_ERR(svn_io_open_unique_file3(&empty_file, &empty_file_abspath, NULL,
-                                   svn_io_file_del_on_pool_cleanup,
-                                   scratch_pool, scratch_pool));
-
   SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx,
                                                  local_abspath,
                                                  scratch_pool, scratch_pool));
@@ -3856,11 +3845,65 @@ resolve_merge_incoming_added_file_replac
       ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool);
     }
 
-  /* Resolve to current working copy state. */
+  /* Resolve to current working copy state. svn_wc_merge5() requires this. */
   err = svn_wc__del_tree_conflict(ctx->wc_ctx, local_abspath, scratch_pool);
   if (err)
     goto unlock_wc;
 
+  if (merge_files)
+    {
+      svn_wc_merge_outcome_t merge_content_outcome;
+      svn_wc_notify_state_t merge_props_outcome;
+      apr_file_t *empty_file;
+      const char *empty_file_abspath;
+      apr_array_header_t *propdiffs;
+
+      /* Create an empty file as fake "merge-base" for the two added files.
+       * The files are not ancestrally related so this is the best we can do. */
+      err = svn_io_open_unique_file3(&empty_file, &empty_file_abspath, NULL,
+                                     svn_io_file_del_on_pool_cleanup,
+                                     scratch_pool, scratch_pool);
+      if (err)
+        goto unlock_wc;
+
+      /* Create a property diff against an empty base. */
+      err = svn_prop_diffs(&propdiffs, apr_hash_make(scratch_pool),
+                           working_props, scratch_pool);
+      if (err)
+        goto unlock_wc;
+
+      /* Perform the file merge. */
+      err = svn_wc_merge5(&merge_content_outcome, &merge_props_outcome,
+                          ctx->wc_ctx, empty_file_abspath,
+                          working_file_tmp_abspath, local_abspath,
+                          NULL, NULL, NULL, /* labels */
+                          NULL, NULL, /* conflict versions */
+                          FALSE, /* dry run */
+                          NULL, NULL, /* diff3_cmd, merge_options */
+                          NULL, propdiffs,
+                          NULL, NULL, /* conflict func/baton */
+                          ctx->cancel_func, ctx->cancel_baton,
+                          scratch_pool);
+      if (err)
+        goto unlock_wc;
+
+      if (ctx->notify_func2)
+        {
+          svn_wc_notify_t *notify = svn_wc_create_notify(
+                                       local_abspath,
+                                       svn_wc_notify_update_update,
+                                       scratch_pool);
+
+          if (merge_content_outcome == svn_wc_merge_conflict)
+            notify->content_state = svn_wc_notify_state_conflicted;
+          else
+            notify->content_state = svn_wc_notify_state_merged;
+          notify->prop_state = merge_props_outcome;
+          notify->kind = svn_node_file;
+          ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool);
+        }
+    }
+
 unlock_wc:
   err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx,
                                                                  lock_abspath,
@@ -3886,191 +3929,28 @@ unlock_wc:
 
 /* Implements conflict_option_resolve_func_t. */
 static svn_error_t *
-resolve_merge_incoming_added_file_replace_and_merge(
+resolve_merge_incoming_added_file_replace(
   svn_client_conflict_option_t *option,
   svn_client_conflict_t *conflict,
   apr_pool_t *scratch_pool)
 {
-  svn_ra_session_t *ra_session;
-  const char *url;
-  const char *corrected_url;
-  const char *repos_root_url;
-  const char *repos_uuid;
-  const char *incoming_new_repos_relpath;
-  svn_revnum_t incoming_new_pegrev;
-  apr_file_t *incoming_new_file;
-  svn_stream_t *incoming_new_stream;
-  apr_hash_t *incoming_new_props;
-  const char *local_abspath;
-  const char *lock_abspath;
-  svn_client_ctx_t *ctx = conflict->ctx;
-  svn_wc_merge_outcome_t merge_content_outcome;
-  svn_wc_notify_state_t merge_props_outcome;
-  const char *wc_tmpdir;
-  apr_file_t *working_file_tmp;
-  svn_stream_t *working_file_tmp_stream;
-  const char *working_file_tmp_abspath;
-  svn_stream_t *working_file_stream;
-  apr_hash_t *working_props;
-  apr_file_t *empty_file;
-  const char *empty_file_abspath;
-  apr_array_header_t *propdiffs;
-  svn_error_t *err;
-
-  local_abspath = svn_client_conflict_get_local_abspath(conflict);
-
-  /* Set up tempory storage for the working version of file. */
-  SVN_ERR(svn_wc__get_tmpdir(&wc_tmpdir, ctx->wc_ctx, local_abspath,
-                             scratch_pool, scratch_pool));
-  SVN_ERR(svn_io_open_unique_file3(&working_file_tmp,
-                                   &working_file_tmp_abspath, wc_tmpdir,
-                                   svn_io_file_del_on_pool_cleanup,
-                                   scratch_pool, scratch_pool));
-  working_file_tmp_stream = svn_stream_from_aprfile2(working_file_tmp,
-                                                     FALSE, scratch_pool);
-
-  /* Copy the working file to temporary storage. */
-  SVN_ERR(svn_stream_open_readonly(&working_file_stream, local_abspath,
-                                   scratch_pool, scratch_pool));
-  SVN_ERR(svn_stream_copy3(working_file_stream, working_file_tmp_stream,
-                           ctx->cancel_baton, ctx->cancel_baton,
-                           scratch_pool));
-  SVN_ERR(svn_io_file_flush(working_file_tmp, scratch_pool));
-
-  /* Get a copy of the working file's properties. */
-  SVN_ERR(svn_wc_prop_list2(&working_props, ctx->wc_ctx, local_abspath,
-                            scratch_pool, scratch_pool));
-
-  /* Create a property diff against an empty base. */
-  SVN_ERR(svn_prop_diffs(&propdiffs, apr_hash_make(scratch_pool),
-                         working_props, scratch_pool));
-
-  /* Fetch the incoming added file from the repository. */
-  SVN_ERR(svn_client_conflict_get_incoming_new_repos_location(
-            &incoming_new_repos_relpath, &incoming_new_pegrev,
-            NULL, conflict, scratch_pool,
-            scratch_pool));
-  SVN_ERR(svn_client_conflict_get_repos_info(&repos_root_url, &repos_uuid,
-                                             conflict, scratch_pool,
-                                             scratch_pool));
-  url = svn_path_url_add_component2(repos_root_url, incoming_new_repos_relpath,
-                                    scratch_pool);
-  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, &corrected_url,
-                                               url, NULL, NULL, FALSE, FALSE,
-                                               conflict->ctx, scratch_pool,
-                                               scratch_pool));
-  if (corrected_url)
-    url = corrected_url;
-  SVN_ERR(svn_io_open_unique_file3(&incoming_new_file, NULL, wc_tmpdir,
-                                   svn_io_file_del_on_pool_cleanup,
-                                   scratch_pool, scratch_pool));
-  incoming_new_stream = svn_stream_from_aprfile2(incoming_new_file, TRUE,
-                                                 scratch_pool);
-  SVN_ERR(svn_ra_get_file(ra_session, "", incoming_new_pegrev,
-                          incoming_new_stream, NULL, /* fetched_rev */
-                          &incoming_new_props, scratch_pool));
-  /* Flush file to disk. */
-  SVN_ERR(svn_io_file_flush(incoming_new_file, scratch_pool));
-
-  /* Reset the stream in preparation for adding its content to WC. */
-  SVN_ERR(svn_stream_reset(incoming_new_stream));
-
-  /* Create an empty file as fake "merge-base" for the two added files.
-   * The files are not ancestrally related so this is the best we can do. */
-  SVN_ERR(svn_io_open_unique_file3(&empty_file, &empty_file_abspath, NULL,
-                                   svn_io_file_del_on_pool_cleanup,
-                                   scratch_pool, scratch_pool));
-
-  SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx,
-                                                 local_abspath,
-                                                 scratch_pool, scratch_pool));
-
-  /* ### The following WC modifications should be atomic. */
-
-  /* Replace the working file with the file from the repository. */
-  err = svn_wc_delete4(ctx->wc_ctx, local_abspath, FALSE, FALSE,
-                       ctx->cancel_func, ctx->cancel_baton,
-                       ctx->notify_func2, ctx->notify_baton2,
-                       scratch_pool);
-  if (err)
-    goto unlock_wc;
-  err = svn_wc_add_repos_file4(ctx->wc_ctx, local_abspath,
-                               incoming_new_stream,
-                               NULL, /* ### could we merge first, then set
-                                        ### the merged content here? */
-                               incoming_new_props,
-                               NULL, /* ### merge props first, set here? */
-                               url, incoming_new_pegrev,
-                               ctx->cancel_func, ctx->cancel_baton,
-                               scratch_pool);
-  if (err)
-    goto unlock_wc;
-
-  if (ctx->notify_func2)
-    {
-      svn_wc_notify_t *notify = svn_wc_create_notify(local_abspath,
-                                                     svn_wc_notify_add,
-                                                     scratch_pool);
-      notify->kind = svn_node_file;
-      ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool);
-    }
-
-  /* Resolve to current working copy state. svn_wc_merge5() requires this. */
-  err = svn_wc__del_tree_conflict(ctx->wc_ctx, local_abspath, scratch_pool);
-  if (err)
-    goto unlock_wc;
-
-  /* Perform the file merge. */
-  err = svn_wc_merge5(&merge_content_outcome, &merge_props_outcome,
-                      ctx->wc_ctx, empty_file_abspath,
-                      working_file_tmp_abspath, local_abspath,
-                      NULL, NULL, NULL, /* labels */
-                      NULL, NULL, /* conflict versions */
-                      FALSE, /* dry run */
-                      NULL, NULL, /* diff3_cmd, merge_options */
-                      NULL, propdiffs,
-                      NULL, NULL, /* conflict func/baton */
-                      ctx->cancel_func, ctx->cancel_baton,
-                      scratch_pool);
-
-  if (ctx->notify_func2)
-    {
-      svn_wc_notify_t *notify = svn_wc_create_notify(
-                                   local_abspath,
-                                   svn_wc_notify_update_update,
-                                   scratch_pool);
-
-      if (merge_content_outcome == svn_wc_merge_conflict)
-        notify->content_state = svn_wc_notify_state_conflicted;
-      else
-        notify->content_state = svn_wc_notify_state_merged;
-      notify->prop_state = merge_props_outcome;
-      notify->kind = svn_node_file;
-      ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool);
-    }
-
-
-unlock_wc:
-  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);
-  SVN_ERR(err);
-
-  SVN_ERR(svn_stream_close(incoming_new_stream));
-
-  if (ctx->notify_func2)
-    {
-      svn_wc_notify_t *notify = svn_wc_create_notify(local_abspath,
-                                                     svn_wc_notify_resolved,
-                                                     scratch_pool);
-
-      ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool);
-    }
-
-  conflict->resolution_tree = svn_client_conflict_option_get_id(option);
+  return svn_error_trace(merge_incoming_added_file_replace(option,
+                                                           conflict,
+                                                           FALSE,
+                                                           scratch_pool));
+}
 
-  return SVN_NO_ERROR;
+/* Implements conflict_option_resolve_func_t. */
+static svn_error_t *
+resolve_merge_incoming_added_file_replace_and_merge(
+  svn_client_conflict_option_t *option,
+  svn_client_conflict_t *conflict,
+  apr_pool_t *scratch_pool)
+{
+  return svn_error_trace(merge_incoming_added_file_replace(option,
+                                                           conflict,
+                                                           TRUE,
+                                                           scratch_pool));
 }
 
 /* Resolver options for a text conflict */