Author: stsp
Date: Tue Oct 4 20:17:29 2011
New Revision: 1178942
URL: http://svn.apache.org/viewvc?rev=1178942&view=rev
Log:
Factor out code from merge_binary_file(), which handles the trivial case where
the left side of the merge equals the merge target, into a separate function.
Prepares for future reuse of this code during text merges.
See issue #4009, "Big trivial text files merged MUCH slower than binary".
(Because I'm travelling I couldn't run the full test suite on this
patch before commit. Apologies if this breaks anything.)
* subversion/libsvn_wc/merge.c
(merge_binary_file): Factor out the trivial merge case into ...
(merge_file_trivial): ... this new function. Also cope with the target
being a dangling symlink (which is one of the issues exposed by test
failures if the trivial merge is performed in the text merge code path).
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=1178942&r1=1178941&r2=1178942&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/merge.c (original)
+++ subversion/trunk/subversion/libsvn_wc/merge.c Tue Oct 4 20:17:29 2011
@@ -924,6 +924,68 @@ maybe_resolve_conflicts(svn_skel_t **wor
return SVN_NO_ERROR;
}
+
+/* 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.
+ * On failure, set *MERGE_OUTCOME to SVN_WC_MERGE_NO_MERGE. */
+static svn_error_t *
+merge_file_trivial(svn_skel_t **work_items,
+ enum svn_wc_merge_outcome_t *merge_outcome,
+ const char *left_abspath,
+ const char *right_abspath,
+ const char *target_abspath,
+ svn_boolean_t dry_run,
+ svn_wc__db_t *db,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_skel_t *work_item;
+ svn_boolean_t same_contents = FALSE;
+ svn_error_t *err;
+
+ /* 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)
+ {
+ if (APR_STATUS_IS_ENOENT(err->apr_err))
+ {
+ /* 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;
+ }
+ 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;
+ return SVN_NO_ERROR;
+ }
+
+ *merge_outcome = svn_wc_merge_no_merge;
+ return SVN_NO_ERROR;
+}
+
+
/* XXX Insane amount of parameters... */
static svn_error_t*
merge_text_file(svn_skel_t **work_items,
@@ -1112,37 +1174,22 @@ merge_binary_file(svn_skel_t **work_item
const char *merge_dirpath, *merge_filename;
const char *conflict_wrk;
svn_skel_t *work_item;
- svn_boolean_t same_contents = FALSE;
*work_items = NULL;
svn_dirent_split(&merge_dirpath, &merge_filename, mt->local_abspath, pool);
- /* Attempt to merge the binary file. At the moment, we can only
- handle the special case: if the LEFT side of the merge is equal
- to WORKING, then we can copy RIGHT directly. */
- SVN_ERR(svn_io_files_contents_same_p(&same_contents,
- left_abspath,
- mt->local_abspath,
- scratch_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 (same_contents)
- {
- if (!dry_run)
- {
- SVN_ERR(svn_wc__wq_build_file_install(&work_item,
- mt->db, mt->local_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);
- }
+ /* 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. */
- *merge_outcome = svn_wc_merge_merged;
- return SVN_NO_ERROR;
- }
- else if (dry_run)
+ if (dry_run)
{
*merge_outcome = svn_wc_merge_conflict;
return SVN_NO_ERROR;