Author: cmpilato
Date: Wed Nov 28 19:48:40 2012
New Revision: 1414880

URL: http://svn.apache.org/viewvc?rev=1414880&view=rev
Log:
After consultation with pburba, restore the 'added_path' merge context
baton member and related functionality removed in r1414810, using it
as a preferred sourch of information about added parent directories,
and only falling back to the more expensive consultation of the
'dry_run_added' hash when we have to.  Though, rather than a *precise*
reintroduction of that baton member, call its restored form
'dry_run_last_added_dir' and position it alongside the 'dry_run_added'
baton member.

* subversion/libsvn_client/merge.c
  (merge_cmd_baton_t): Add new 'dry_run_last_added_dir' member.
  (dry_run_added_parent_p): Add 'local_abspath' parameter, and rename
    'edit_relpath' to 'local_relpath'.  Now check the incoming paths
    against the merge baton's 'dry_run_last_added_dir' as an
    optimization before consulting the 'dry_run_added' hash.
  (merge_file_added): Update call to dry_run_added_parent_p().
  (merge_dir_added): Manage the state of the new 'dry_run_last_added_dir'
    baton member.  Update call to dry_run_added_parent_p().
  (do_merge): Reset the new 'dry_run_last_added_dir' context baton member, too.

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

Modified: subversion/trunk/subversion/libsvn_client/merge.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/merge.c?rev=1414880&r1=1414879&r2=1414880&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/merge.c (original)
+++ subversion/trunk/subversion/libsvn_client/merge.c Wed Nov 28 19:48:40 2012
@@ -286,9 +286,10 @@ typedef struct merge_cmd_baton_t {
      dry_run mode. */
   apr_hash_t *dry_run_deletions;
 
-  /* The list of paths for entries we've added, used only when in
-     dry_run mode. */
+  /* The list of paths for entries we've added and the most
+     recently added directory.  (Used only when in dry_run mode.) */
   apr_hash_t *dry_run_added;
+  const char *dry_run_last_added_dir;
 
   /* The list of any paths which remained in conflict after a
      resolution attempt was made.  We track this in-memory, rather
@@ -487,32 +488,45 @@ dry_run_added_p(const merge_cmd_baton_t 
                        APR_HASH_KEY_STRING) != NULL);
 }
 
-/* Return true iff we're in dry-run mode and a parent of EDIT_RELPATH
-   would have been added by now if we weren't in dry-run mode.
-   Used to avoid spurious notifications (e.g. conflicts) from a merge
-   attempt into an existing target which would have been deleted if we
-   weren't in dry_run mode (issue #2584).  Assumes that WCPATH is
-   still versioned (e.g. has an associated entry). */
+/* Return true iff we're in dry-run mode and a parent of
+   LOCAL_RELPATH/LOCAL_ABSPATH would have been added by now if we
+   weren't in dry-run mode.  Used to avoid spurious notifications
+   (e.g. conflicts) from a merge attempt into an existing target which
+   would have been deleted if we weren't in dry_run mode (issue
+   #2584).  Assumes that WCPATH is still versioned (e.g. has an
+   associated entry). */
 static svn_boolean_t
 dry_run_added_parent_p(const merge_cmd_baton_t *merge_b,
-                       const char *edit_relpath,
+                       const char *local_relpath,
+                       const char *local_abspath,
                        apr_pool_t *scratch_pool)
 {
+  const char *abspath = local_abspath;
   int i;
-  const char *abspath;
 
   if (!merge_b->dry_run)
     return FALSE;
 
-  abspath = svn_dirent_join(merge_b->target->abspath, edit_relpath,
-                            scratch_pool);
-  for (i = 0; i < (svn_path_component_count(edit_relpath) - 1); i++)
+  /* See if LOCAL_ABSPATH is a child of the most recently added
+     directory.  This is an optimization over searching through
+     dry_run_added that plays to the strengths of the editor's drive
+     ordering constraints.  In fact, we need the fallback approach
+     below only because of ra_serf's insufficiencies in this area.  */
+  if (merge_b->dry_run_last_added_dir
+      && svn_dirent_is_child(merge_b->dry_run_last_added_dir,
+                             local_abspath, NULL))
+    return TRUE;
+
+  /* The fallback:  see if any of LOCAL_ABSPATH's parents have been
+     added in this merge so far. */
+  for (i = 0; i < (svn_path_component_count(local_relpath) - 1); i++)
     {
       abspath = svn_dirent_dirname(abspath, scratch_pool);
       if (apr_hash_get(merge_b->dry_run_added, abspath,
                        APR_HASH_KEY_STRING))
         return TRUE;
     }
+
   return FALSE;
 }
 
@@ -1884,7 +1898,8 @@ merge_file_added(svn_wc_notify_state_t *
     if (obstr_state != svn_wc_notify_state_inapplicable)
       {
         if (merge_b->dry_run 
-            && dry_run_added_parent_p(merge_b, mine_relpath, scratch_pool))
+            && dry_run_added_parent_p(merge_b, mine_relpath,
+                                      mine_abspath, scratch_pool))
           {
             if (content_state)
               *content_state = svn_wc_notify_state_changed;
@@ -2364,7 +2379,8 @@ merge_dir_added(svn_wc_notify_state_t *s
     if (obstr_state != svn_wc_notify_state_inapplicable)
       {
         if (state && merge_b->dry_run
-            && dry_run_added_parent_p(merge_b, local_relpath, scratch_pool))
+            && dry_run_added_parent_p(merge_b, local_relpath,
+                                      local_abspath, scratch_pool))
           {
             *state = svn_wc_notify_state_changed;
           }
@@ -2386,10 +2402,10 @@ merge_dir_added(svn_wc_notify_state_t *s
       /* Unversioned or schedule-delete */
       if (merge_b->dry_run)
         {
-          const char *added_path = apr_pstrdup(merge_b->pool,
-                                               local_abspath);
-          apr_hash_set(merge_b->dry_run_added, added_path,
-                       APR_HASH_KEY_STRING, added_path);
+          merge_b->dry_run_last_added_dir =
+            apr_pstrdup(merge_b->pool, local_abspath);
+          apr_hash_set(merge_b->dry_run_added, merge_b->dry_run_last_added_dir,
+                       APR_HASH_KEY_STRING, merge_b->dry_run_last_added_dir);
         }
       else
         {
@@ -2425,10 +2441,8 @@ merge_dir_added(svn_wc_notify_state_t *s
             }
           else
             {
-              const char *added_path = apr_pstrdup(merge_b->pool,
-                                                   local_abspath);
-              apr_hash_set(merge_b->dry_run_added, added_path,
-                           APR_HASH_KEY_STRING, added_path);
+              merge_b->dry_run_last_added_dir =
+                apr_pstrdup(merge_b->pool, local_abspath);
             }
           if (state)
             *state = svn_wc_notify_state_changed;
@@ -2467,6 +2481,9 @@ merge_dir_added(svn_wc_notify_state_t *s
         }
       break;
     case svn_node_file:
+      if (merge_b->dry_run)
+        merge_b->dry_run_last_added_dir = NULL;
+
       if (is_versioned && dry_run_deleted_p(merge_b, local_abspath))
         {
           /* ### TODO: Retain record of this dir being added to
@@ -2488,6 +2505,8 @@ merge_dir_added(svn_wc_notify_state_t *s
         }
       break;
     default:
+      if (merge_b->dry_run)
+        merge_b->dry_run_last_added_dir = NULL;
       if (state)
         *state = svn_wc_notify_state_unknown;
       break;
@@ -9199,6 +9218,7 @@ do_merge(apr_hash_t **modified_subtrees,
         dry_run ? apr_hash_make(iterpool) : NULL;
       merge_cmd_baton.dry_run_added =
         dry_run ? apr_hash_make(iterpool) : NULL;
+      merge_cmd_baton.dry_run_last_added_dir = NULL;
       merge_cmd_baton.conflicted_paths = NULL;
       merge_cmd_baton.paths_with_new_mergeinfo = NULL;
       merge_cmd_baton.paths_with_deleted_mergeinfo = NULL;


Reply via email to