Author: stsp
Date: Wed Oct 12 19:05:25 2011
New Revision: 1182527

URL: http://svn.apache.org/viewvc?rev=1182527&view=rev
Log:
Fix issue #4009, "Big trivial text files merged MUCH slower than binary".

* subversion/libsvn_wc/merge.c
  (merge_file_trivial): Account for targets which are symlinks. Do not
   report a file as changed if the delta between left and right is empty.
  (merge_binary_file): Move call to merge_file_trivial() out of here ...
  (svn_wc__internal_merge): ... to here, to make it applicable to both
   text and binary files.

Modified:
    subversion/trunk/subversion/libsvn_wc/merge.c

Modified: subversion/trunk/subversion/libsvn_wc/merge.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/merge.c?rev=1182527&r1=1182526&r2=1182527&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/merge.c (original)
+++ subversion/trunk/subversion/libsvn_wc/merge.c Wed Oct 12 19:05:25 2011
@@ -928,8 +928,9 @@ maybe_resolve_conflicts(svn_skel_t **wor
 /* Attempt a trivial merge of LEFT_ABSPATH and RIGHT_ABSPATH to TARGET_ABSPATH.
  * The merge is trivial if the file at LEFT_ABSPATH equals TARGET_ABSPATH,
  * because in this case the content of RIGHT_ABSPATH can be copied to the
- * target. On success, set *MERGE_OUTCOME to SVN_WC_MERGE_MERGED,
- * and install work queue items allocated in RESULT_POOL in *WORK_ITEMS.
+ * target. On success, set *MERGE_OUTCOME to SVN_WC_MERGE_MERGED in case the
+ * target was changed, or to SVN_WC_MERGE_UNCHANGED if the target was not
+ * changed. Install work queue items allocated in RESULT_POOL in *WORK_ITEMS.
  * On failure, set *MERGE_OUTCOME to SVN_WC_MERGE_NO_MERGE. */
 static svn_error_t *
 merge_file_trivial(svn_skel_t **work_items,
@@ -944,40 +945,48 @@ merge_file_trivial(svn_skel_t **work_ite
 {
   svn_skel_t *work_item;
   svn_boolean_t same_contents = FALSE;
-  svn_error_t *err;
+  svn_node_kind_t kind;
+  svn_boolean_t is_special;
+
+  /* If the target is not a normal file, do not attempt a trivial merge. */
+  SVN_ERR(svn_io_check_special_path(target_abspath, &kind, &is_special,
+                                    scratch_pool));
+  if (kind != svn_node_file || is_special)
+    {
+      *merge_outcome = svn_wc_merge_no_merge;
+      return SVN_NO_ERROR;
+    }
 
   /* If the LEFT side of the merge is equal to WORKING, then we can
    * copy RIGHT directly. */
-  err = svn_io_files_contents_same_p(&same_contents, left_abspath,
-                                     target_abspath, scratch_pool);
-  if (err)
+  SVN_ERR(svn_io_files_contents_same_p(&same_contents, left_abspath,
+                                       target_abspath, scratch_pool));
+  if (same_contents)
     {
-      if (APR_STATUS_IS_ENOENT(err->apr_err))
+      /* Check whether the left side equals the right side.
+       * If it does, there is no change to merge so we leave the target
+       * unchanged. */
+      SVN_ERR(svn_io_files_contents_same_p(&same_contents, left_abspath,
+                                           right_abspath, scratch_pool));
+      if (same_contents)
         {
-          /* This can happen if TARGET_ABSPATH is a broken symlink.
-           * Let the smart merge code handle this. */
-          svn_error_clear(err);
-          *merge_outcome = svn_wc_merge_no_merge;
-          return SVN_NO_ERROR;
+          *merge_outcome = svn_wc_merge_unchanged;
         }
       else
-        return svn_error_trace(err);
-    }
-
-  if (same_contents)
-    {
-      if (!dry_run)
         {
-          SVN_ERR(svn_wc__wq_build_file_install(&work_item,
-                                                db, target_abspath,
-                                                right_abspath,
-                                                FALSE /* use_commit_times */,
-                                                FALSE /* record_fileinfo */,
-                                                result_pool, scratch_pool));
-          *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
+          *merge_outcome = svn_wc_merge_merged;
+          if (!dry_run)
+            {
+              SVN_ERR(svn_wc__wq_build_file_install(
+                        &work_item, db, target_abspath, right_abspath,
+                        FALSE /* use_commit_times */,
+                        FALSE /* record_fileinfo */,
+                        result_pool, scratch_pool));
+              *work_items = svn_wc__wq_merge(*work_items, work_item,
+                                             result_pool);
+            }
         }
 
-      *merge_outcome = svn_wc_merge_merged;
       return SVN_NO_ERROR;
     }
 
@@ -1179,13 +1188,6 @@ merge_binary_file(svn_skel_t **work_item
 
   svn_dirent_split(&merge_dirpath, &merge_filename, mt->local_abspath, pool);
 
-  SVN_ERR(merge_file_trivial(work_items, merge_outcome,
-                             left_abspath, right_abspath,
-                             mt->local_abspath, dry_run, mt->db,
-                             result_pool, scratch_pool));
-  if (*merge_outcome == svn_wc_merge_merged)
-    return SVN_NO_ERROR;
-
   /* If we get here the binary files differ. Because we don't know how
    * to merge binary files in a non-trivial way we always flag a conflict. */
 
@@ -1414,41 +1416,48 @@ svn_wc__internal_merge(svn_skel_t **work
                                    cancel_func, cancel_baton,
                                    scratch_pool, scratch_pool));
 
-  if (is_binary)
-    {
-      SVN_ERR(merge_binary_file(work_items,
-                                merge_outcome,
-                                &mt,
-                                left_abspath,
-                                right_abspath,
-                                left_label,
-                                right_label,
-                                target_label,
-                                dry_run,
-                                left_version,
-                                right_version,
-                                detranslated_target_abspath,
-                                conflict_func,
-                                conflict_baton,
-                                result_pool, scratch_pool));
-    }
-  else
+  SVN_ERR(merge_file_trivial(work_items, merge_outcome,
+                             left_abspath, right_abspath,
+                             target_abspath, dry_run, db,
+                             result_pool, scratch_pool));
+  if (*merge_outcome == svn_wc_merge_no_merge)
     {
-      SVN_ERR(merge_text_file(work_items,
-                              merge_outcome,
-                              &mt,
-                              left_abspath,
-                              right_abspath,
-                              left_label,
-                              right_label,
-                              target_label,
-                              dry_run,
-                              left_version,
-                              right_version,
-                              detranslated_target_abspath,
-                              conflict_func, conflict_baton,
-                              cancel_func, cancel_baton,
-                              result_pool, scratch_pool));
+      if (is_binary)
+        {
+          SVN_ERR(merge_binary_file(work_items,
+                                    merge_outcome,
+                                    &mt,
+                                    left_abspath,
+                                    right_abspath,
+                                    left_label,
+                                    right_label,
+                                    target_label,
+                                    dry_run,
+                                    left_version,
+                                    right_version,
+                                    detranslated_target_abspath,
+                                    conflict_func,
+                                    conflict_baton,
+                                    result_pool, scratch_pool));
+        }
+      else
+        {
+          SVN_ERR(merge_text_file(work_items,
+                                  merge_outcome,
+                                  &mt,
+                                  left_abspath,
+                                  right_abspath,
+                                  left_label,
+                                  right_label,
+                                  target_label,
+                                  dry_run,
+                                  left_version,
+                                  right_version,
+                                  detranslated_target_abspath,
+                                  conflict_func, conflict_baton,
+                                  cancel_func, cancel_baton,
+                                  result_pool, scratch_pool));
+        }
     }
 
   /* Merging is complete.  Regardless of text or binariness, we might


Reply via email to