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