'Daniel Shahaf' wrote on Mon, Mar 28, 2011 at 00:16:49 +0200: > Bert Huijben wrote on Sun, Mar 27, 2011 at 19:26:50 +0200: > > and there are easier (and more > > performant) ways to check if a node is part of a working copy (e.g. helpers > > to check if a path is switched/a wc root). > > Could you elaborate on these please? I looked through the header files > and amn't sure which helpers you're referring to.
New patch, including your previous feedbacks modulo the above point: [[[ Resolve issue #3469 (tree conflict under a directory external). Review by: rhuijben * subversion/libsvn_client/merge.c (merge_cmd_baton_t): Add TARGET_WCROOT_ABSPATH member. (do_merge): Initialize new member. (merge_file_added): Skip files that belong to externals or to disjoint working copies. Exploit knowledge of libsvn_wc implementations details (queries on directories are faster) to make the check cheaper. TODO: remove @XFail decorator (from tree_conflict_tests.py 22) ]]] [[[ Index: subversion/libsvn_client/merge.c =================================================================== --- subversion/libsvn_client/merge.c (revision 1086475) +++ subversion/libsvn_client/merge.c (working copy) @@ -249,6 +249,8 @@ typedef struct merge_cmd_baton_t { versioned dir (dry-run only) */ const char *target_abspath; /* Absolute working copy target of the merge. */ + const char *target_wcroot_abspath; /* Absolute path to root of wc that + TARGET_ABSPATH belongs to. */ /* The left and right URLs and revs. The value of this field changes to reflect the merge_source_t *currently* being merged by do_merge(). */ @@ -1555,6 +1557,32 @@ merge_file_added(const char *local_dir_abspath, if (tree_conflicted) *tree_conflicted = FALSE; + /* Easy out: not the same working copy. (So, a disjoint working copy or + an external.) */ + { + const char *mine_wcroot_abspath; + + /* ### White-box optimization: + + The code knows that MINE_ABSPATH is not a directory (it's an added + file), and we know that internally libsvn_wc queries are faster for + directories (this is an implementation detail). Therefore, query for + the wcroot of the containing directory of MINE_ABSPATH. + + (We rely on the implementation detail only for performance, not for + correctness; under any implementation it would be valid to query for + the parent's wcroot.) + */ + SVN_ERR(svn_wc_get_wc_root(&mine_wcroot_abspath, merge_b->ctx->wc_ctx, + svn_dirent_dirname(mine_abspath, scratch_pool), + scratch_pool, scratch_pool)); + if (strcmp(mine_wcroot_abspath, merge_b->target_wcroot_abspath)) + { + *content_state = svn_wc_notify_state_obstructed; + return SVN_NO_ERROR; + } + } + /* Apply the prop changes to a new hash table. */ file_props = apr_hash_copy(subpool, original_props); for (i = 0; i < prop_changes->nelts; ++i) @@ -8653,6 +8685,9 @@ do_merge(apr_hash_t **modified_subtrees, merge_cmd_baton.target_missing_child = FALSE; merge_cmd_baton.reintegrate_merge = reintegrate_merge; merge_cmd_baton.target_abspath = target_abspath; + SVN_ERR(svn_wc_get_wc_root(&merge_cmd_baton.target_wcroot_abspath, + ctx->wc_ctx, merge_cmd_baton.target_abspath, + pool, subpool)); merge_cmd_baton.pool = subpool; merge_cmd_baton.merge_options = merge_options; merge_cmd_baton.diff3_cmd = diff3_cmd; ]]]