'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;
]]]

Reply via email to