subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ne...@apache.org
Subject svn commit: r906110 - /subversion/trunk/subversion/libsvn_wc/update_editor.c
Date Wed, 03 Feb 2010 16:25:16 GMT
Author: neels
Date: Wed Feb  3 16:25:15 2010
New Revision: 906110

URL: http://svn.apache.org/viewvc?rev=906110&view=rev
Log:
wc-ng: Change tree-conflict checking during 'update' to use the new WC API.
In effect, 'svn info' now always reports the right node kind in the "Tree
conflict:" section, even for deleted nodes.
Also change another static function's KIND arg's type to avoid translating
node kinds once and then back again.

* subversion/libsvn_wc/update_editor.c
  (entry_has_local_mods):
    Change the type of KIND argument to svn_wc__db_kind_t.
  (modcheck_found_node):
    Call entry_has_local_mods() with new KIND type.
  (SVN_WC_CONFLICT_REASON_NONE):
    New local #define.
  (check_tree_conflict):
    Don't use svn_wc_entry_t, use wc-ng (almost a complete rewrite).
    Lose the IN_DELETED_AND_TREE_CONFLICTED_SUBTREE argument, since, if TRUE,
    this skips the entire function anyway; move this check out to each caller.
  (do_entry_deletion,  
   add_directory,  
   open_directory,  
   add_file,  
   open_file):
    Evaluate IN_DELETED_AND_TREE_CONFLICTED_SUBTREE inline instead of passing
    it to check_tree_conflict() first.


Modified:
    subversion/trunk/subversion/libsvn_wc/update_editor.c

Modified: subversion/trunk/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/update_editor.c?rev=906110&r1=906109&r2=906110&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/update_editor.c Wed Feb  3 16:25:15 2010
@@ -1434,14 +1434,15 @@
 entry_has_local_mods(svn_boolean_t *modified,
                      svn_wc__db_t *db,
                      const char *local_abspath,
-                     svn_node_kind_t kind,
+                     svn_wc__db_kind_t kind,
                      apr_pool_t *scratch_pool)
 {
   svn_boolean_t text_modified;
   svn_boolean_t props_modified;
 
   /* Check for text modifications */
-  if (kind == svn_node_file)
+  if (kind == svn_wc__db_kind_file
+      || kind == svn_wc__db_kind_symlink)
     SVN_ERR(svn_wc__internal_text_modified_p(&text_modified, db, local_abspath,
                                              FALSE, TRUE, scratch_pool));
   else
@@ -1486,10 +1487,7 @@
     modified = TRUE;
   else
     SVN_ERR(entry_has_local_mods(&modified, baton->db, local_abspath,
-                                 (kind == svn_wc__db_kind_file
-                                  || kind == svn_wc__db_kind_symlink)
-                                   ? svn_node_file : svn_node_dir,
-                                 scratch_pool));
+                                 kind, scratch_pool));
 
   if (modified)
     {
@@ -1536,6 +1534,9 @@
 }
 
 
+/* Indicates an unset svn_wc_conflict_reason_t. */
+#define SVN_WC_CONFLICT_REASON_NONE (svn_wc_conflict_reason_t)(-1)
+
 /* Check whether the incoming change ACTION on FULL_PATH would conflict with
  * LOCAL_ABSPATH's scheduled change. If so, then raise a tree conflict with
  * LOCAL_ABSPATH as the victim.
@@ -1568,189 +1569,315 @@
                     svn_wc_conflict_action_t action,
                     svn_node_kind_t their_node_kind,
                     const char *their_url,
-                    svn_boolean_t in_deleted_and_tree_conflicted_subtree,
                     apr_pool_t *pool)
 {
-  svn_wc_conflict_reason_t reason = (svn_wc_conflict_reason_t)(-1);
+  svn_wc__db_status_t status;
+  svn_wc__db_kind_t db_node_kind;
+  svn_boolean_t base_shadowed;
+  svn_wc_conflict_reason_t reason = SVN_WC_CONFLICT_REASON_NONE;
+  svn_boolean_t locally_replaced = FALSE;
+  svn_boolean_t modified = FALSE;
   svn_boolean_t all_mods_are_deletes = FALSE;
-  const svn_wc_entry_t *entry;
-  svn_error_t *err;
 
-  err = svn_wc__get_entry(&entry, eb->db, local_abspath, TRUE,
-                          svn_node_unknown, FALSE, pool, pool);
+  *pconflict = NULL;
 
-  if (err && err->apr_err == SVN_ERR_NODE_UNEXPECTED_KIND)
-    svn_error_clear(err);
-  else
-    SVN_ERR(err);
+  SVN_ERR(svn_wc__db_read_info(&status,
+                               &db_node_kind,
+                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL,
+                               &base_shadowed,
+                               NULL, NULL,
+                               eb->db,
+                               local_abspath,
+                               pool,
+                               pool));
 
-  if (entry)
-    {
-      svn_boolean_t hidden;
-      SVN_ERR(svn_wc__db_node_hidden(&hidden, eb->db, local_abspath, pool));
+  /* Find out if there are any local changes to this node that may
+   * be the "reason" of a tree-conflict with the incoming "action". */
+  switch (status)
+    {
+      case svn_wc__db_status_added:
+      case svn_wc__db_status_obstructed_add:
+      case svn_wc__db_status_moved_here:
+      case svn_wc__db_status_copied:
+        /* Is it a replace? */
+        if (base_shadowed)
+          {
+            svn_wc__db_status_t base_status;
+            SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL, NULL,
+                                             NULL, NULL, NULL, NULL, NULL,
+                                             NULL, NULL, NULL, NULL, NULL,
+                                             NULL, NULL,
+                                             eb->db, local_abspath,
+                                             pool,
+                                             pool));
+            if (base_status != svn_wc__db_status_not_present)
+              locally_replaced = TRUE;
+          }
 
-      if (hidden)
-        entry = NULL;
-    }
+        if (!locally_replaced)
+          {
+            /* The node is locally added, and it did not exist before.  This
+             * is an 'update', so the local add can only conflict with an
+             * incoming 'add'.  In fact, if we receive anything else than an
+             * svn_wc_conflict_action_add (which includes 'added',
+             * 'copied-here' and 'moved-here') during update on a node that
+             * did not exist before, then something is very wrong.
+             * Note that if there was no action on the node, this code
+             * would not have been called in the first place. */
+            SVN_ERR_ASSERT(action == svn_wc_conflict_action_add);
 
-  switch (action)
-    {
-    case svn_wc_conflict_action_edit:
-      /* Use case 1: Modifying a locally-deleted item.
-         If LOCAL_ABSPATH is an incoming leaf edit within a local
-         tree deletion then we will already have recorded a tree
-         conflict on the locally deleted parent tree.  No need
-         to record a conflict within the conflict. */
-      if ((entry->schedule == svn_wc_schedule_delete
-           || entry->schedule == svn_wc_schedule_replace)
-          && !in_deleted_and_tree_conflicted_subtree)
-        reason = entry->schedule == svn_wc_schedule_delete
-                                    ? svn_wc_conflict_reason_deleted
-                                    : svn_wc_conflict_reason_replaced;
-      break;
+            reason = svn_wc_conflict_reason_added;
+          }
+        else
+          {
+            /* The node is locally replaced. */
+            reason = svn_wc_conflict_reason_replaced;
+          }
+        break;
 
-    case svn_wc_conflict_action_add:
-      /* Use case "3.5": Adding a locally-added item.
-       *
-       * When checking out a file-external, add_file() is called twice:
-       * 1.) In the main update, a minimal entry is created.
-       * 2.) In the external update, the file is added properly.
-       * Don't raise a tree conflict the second time! */
-      if (entry && !entry->file_external_path)
-        reason = svn_wc_conflict_reason_added;
-      break;
-
-    case svn_wc_conflict_action_delete:
-    case svn_wc_conflict_action_replace:
-      /* Use case 3: Deleting a locally-deleted item. */
-      if (entry->schedule == svn_wc_schedule_delete
-          || entry->schedule == svn_wc_schedule_replace)
-        {
-          /* If LOCAL_ABSPATH is an incoming leaf deletion within a local
-             tree deletion then we will already have recorded a tree
-             conflict on the locally deleted parent tree.  No need
-             to record a conflict within the conflict. */
-          if (!in_deleted_and_tree_conflicted_subtree)
-            reason = entry->schedule == svn_wc_schedule_delete
-                                        ? svn_wc_conflict_reason_deleted
-                                        : svn_wc_conflict_reason_replaced;
-        }
-      else
-        {
-          svn_boolean_t modified = FALSE;
 
-          /* Use case 2: Deleting a locally-modified item. */
-          if (entry->kind == svn_node_file)
-            {
-              if (entry->schedule != svn_wc_schedule_normal)
-                modified = TRUE;
-              else
-                SVN_ERR(entry_has_local_mods(&modified, eb->db, local_abspath,
-                                             entry->kind, pool));
-              if (entry->schedule == svn_wc_schedule_delete)
-                all_mods_are_deletes = TRUE;
-            }
-          else if (entry->kind == svn_node_dir)
-            {
+      case svn_wc__db_status_deleted:
+      case svn_wc__db_status_obstructed_delete:
+        /* The node is locally deleted. */
+        reason = svn_wc_conflict_reason_deleted;
+        break;
+
+      case svn_wc__db_status_incomplete:
+        /* We used svn_wc__db_read_info(), so 'incomplete' means
+         * - there is no node in the WORKING tree
+         * - a BASE node is known to exist
+         * So the node exists and is essentially 'normal'. We still need to
+         * check prop and text mods, and those checks will retrieve the
+         * missing information (hopefully). */
+      case svn_wc__db_status_obstructed:
+        /* Tree-conflicts during update are only concerned with local
+         * modifications. We can safely update BASE, disregarding the
+         * obstruction. So let's treat this as normal. */
+      case svn_wc__db_status_normal:
+        if (action == svn_wc_conflict_action_edit)
+          /* An edit onto a local edit or onto *no* local changes is no
+           * tree-conflict. (It's possibly a text- or prop-conflict,
+           * but we don't handle those here.) */
+          return SVN_NO_ERROR;
+
+        /* Check if the update wants to delete or replace a locally
+         * modified node. */
+        switch (db_node_kind)
+          {
+            case svn_wc__db_kind_file:
+            case svn_wc__db_kind_symlink:
+              all_mods_are_deletes = FALSE;
+              SVN_ERR(entry_has_local_mods(&modified, eb->db, local_abspath,
+                                           db_node_kind, pool));
+              break;
+
+            case svn_wc__db_kind_dir:
               /* We must detect deep modifications in a directory tree,
                * but the update editor will not visit the subdirectories
                * of a directory that it wants to delete.  Therefore, we
                * need to start a separate crawl here. */
-
               if (!svn_wc__adm_missing(eb->db, local_abspath, pool))
                 SVN_ERR(tree_has_local_mods(&modified, &all_mods_are_deletes,
                                             eb->db, local_abspath,
                                             eb->cancel_func, eb->cancel_baton,
                                             pool));
-            }
+              break;
 
-          if (modified)
-            {
-              if (all_mods_are_deletes)
-                reason = svn_wc_conflict_reason_deleted;
-              else
-                reason = svn_wc_conflict_reason_edited;
-            }
+            default:
+              /* It's supposed to be in 'normal' status. So how can it be
+               * neither file nor folder? */
+              SVN_ERR_MALFUNCTION();
+              break;
+          }
+
+        if (modified)
+          {
+            if (all_mods_are_deletes)
+              reason = svn_wc_conflict_reason_deleted;
+            else
+              reason = svn_wc_conflict_reason_edited;
+          }
+        break;
+
+      case svn_wc__db_status_absent:
+        /* Not allowed to view the node. Not allowed to report tree
+         * conflicts. */
+      case svn_wc__db_status_excluded:
+        /* Locally marked as excluded. No conflicts wanted. */
+      case svn_wc__db_status_not_present:
+        /* A committed delete (but parent not updated). The delete is
+           committed, so no conflict possible during update. */
+        return SVN_NO_ERROR;
+
+      case svn_wc__db_status_base_deleted:
+        /* An internal status. Should never show up here. */
+        SVN_ERR_MALFUNCTION();
+        break;
 
-        }
-      break;
     }
 
-  *pconflict = NULL;
+  if (reason == SVN_WC_CONFLICT_REASON_NONE)
+    /* No conflict with the current action. */
+    return SVN_NO_ERROR;
+
+
+  /* Sanity checks.
+   * When the node existed before (it was locally deleted, replaced or
+   * edited), then, to be sane, 'update' can only send
+   * svn_wc_conflict_action_edit, svn_wc_conflict_action_delete or
+   * svn_wc_conflict_action_replace.  Note that if there was no action on
+   * the node, this code would not have been called in the first place. */
+  if (reason == svn_wc_conflict_reason_edited
+      || reason == svn_wc_conflict_reason_deleted
+      || reason == svn_wc_conflict_reason_replaced)
+    SVN_ERR_ASSERT(action == svn_wc_conflict_action_edit
+                   || action == svn_wc_conflict_action_delete
+                   || action == svn_wc_conflict_action_replace);
+  else
+  if (reason == svn_wc_conflict_reason_added)
+    /* When the node did not exist before (it was locally added), then, to
+     * be sane, 'update' can only send svn_wc_conflict_action_add. */
+    SVN_ERR_ASSERT(action == svn_wc_conflict_action_add);
+
 
-  /* If a conflict was detected, append log commands to the log accumulator
+  /* A conflict was detected. Append log commands to the log accumulator
    * to record it. */
-  if (reason != (svn_wc_conflict_reason_t)(-1))
-    {
-      svn_wc_conflict_description2_t *conflict;
-      const svn_wc_conflict_version_t *src_left_version;
-      const svn_wc_conflict_version_t *src_right_version;
-      const char *repos_url = NULL;
-      const char *path_in_repos = NULL;
-      svn_node_kind_t left_kind = (entry->schedule == svn_wc_schedule_add)
-                                  ? svn_node_none
-                                  : (entry->schedule == svn_wc_schedule_delete)
-                                    ? svn_node_unknown
-                                    : entry->kind;
-
-      /* Source-left repository root URL and path in repository.
-       * The Source-right ones will be the same for update.
-       * For switch, only the path in repository will differ, because
-       * a cross-repository switch is not possible. */
-      repos_url = entry->repos;
-      path_in_repos = svn_uri_is_child(repos_url, entry->url, pool);
-      if (path_in_repos == NULL)
-        path_in_repos = "";
-
-      src_left_version = svn_wc_conflict_version_create(repos_url,
-                                                        path_in_repos,
-                                                        entry->revision,
-                                                        left_kind,
-                                                        pool);
-
-      /* entry->kind is both base kind and working kind, because schedule
-       * replace-by-different-kind is not supported. */
-      /* ### TODO: but in case the entry is locally removed, entry->kind
-       * is svn_node_none and doesn't reflect the older kind. Then we
-       * need to find out the older kind in a different way! */
-
-      /* For switch, find out the proper PATH_IN_REPOS for source-right. */
-      if (eb->switch_url != NULL)
-        {
-          if (their_url != NULL)
-            path_in_repos = svn_uri_is_child(repos_url, their_url, pool);
-          else
-            {
-              /* The complete source-right URL is not available, but it
-               * is somewhere below the SWITCH_URL. For now, just go
-               * without it.
-               * ### TODO: Construct a proper THEIR_URL in some of the
-               * delete cases that still pass NULL for THEIR_URL when
-               * calling this function. Do that on the caller's side. */
-              path_in_repos = svn_uri_is_child(repos_url, eb->switch_url,
-                                               pool);
-              path_in_repos = apr_pstrcat(
-                                pool, path_in_repos,
-                                "_THIS_IS_INCOMPLETE",
-                                NULL);
-            }
-        }
+  {
+    const char *repos_root_url;
+    const char *left_repos_relpath;
+    svn_revnum_t left_revision;
+    svn_node_kind_t left_kind;
+    const char *right_repos_relpath;
+    svn_node_kind_t conflict_node_kind;
+    svn_wc_conflict_version_t *src_left_version;
+    svn_wc_conflict_version_t *src_right_version;
+    
+    /* Get the source-left information, i.e. the local state of the node 
+     * before any changes were made to the working copy, i.e. the state the
+     * node would have if it was reverted. */
+    if (reason == svn_wc_conflict_reason_added)
+      {
+        /* Source-left does not exist.
+         * We will still report the URL and revision onto which this node
+         * is locally added. We don't report the locally added node kind,
+         * since that would be 'target', not 'source-left'. */
+        svn_wc__db_status_t added_status;
+
+        left_kind = svn_node_none;
+
+        SVN_ERR(svn_wc__db_scan_addition(&added_status, NULL,
+                                         &left_repos_relpath,
+                                         &repos_root_url,
+                                         NULL, NULL, NULL, NULL,
+                                         &left_revision,
+                                         eb->db,
+                                         local_abspath,
+                                         pool,
+                                         pool));
+
+        /* Sanity. */
+        SVN_ERR_ASSERT(added_status == svn_wc__db_status_added
+                       || added_status == svn_wc__db_status_obstructed_add
+                       || added_status == svn_wc__db_status_copied
+                       || added_status == svn_wc__db_status_moved_here);
+      }
+    else
+      {
+        /* A BASE node should exist. */
+        svn_wc__db_kind_t base_kind;
 
-      src_right_version = svn_wc_conflict_version_create(repos_url,
-                                                         path_in_repos,
-                                                         *eb->target_revision,
-                                                         their_node_kind,
-                                                         pool);
-
-      conflict = svn_wc_conflict_description_create_tree2(
-        local_abspath, entry->kind,
-        eb->switch_url ? svn_wc_operation_switch : svn_wc_operation_update,
-        src_left_version, src_right_version, pool);
-      conflict->action = action;
-      conflict->reason = reason;
+        /* If anything else shows up, then this assertion is probably naive
+         * and that other case should also be handled. */
+        SVN_ERR_ASSERT(reason == svn_wc_conflict_reason_edited
+                       || reason == svn_wc_conflict_reason_deleted
+                       || reason == svn_wc_conflict_reason_replaced
+                       || reason == svn_wc_conflict_reason_obstructed);
+
+        SVN_ERR(svn_wc__db_base_get_info(NULL, &base_kind,
+                                         &left_revision,
+                                         &left_repos_relpath,
+                                         &repos_root_url,
+                                         NULL, NULL, NULL, NULL, NULL, NULL,
+                                         NULL, NULL, NULL, NULL,
+                                         eb->db,
+                                         local_abspath,
+                                         pool,
+                                         pool));
+        /* Translate the node kind. */
+        if (base_kind == svn_wc__db_kind_file
+            || base_kind == svn_wc__db_kind_symlink)
+          left_kind = svn_node_file;
+        else
+        if (base_kind == svn_wc__db_kind_dir)
+          left_kind = svn_node_dir;
+        else
+          SVN_ERR_MALFUNCTION();
+      }
 
-      *pconflict = conflict;
-    }
+
+    /* Find the source-right information, i.e. the state in the repository
+     * to which we would like to update. */
+    if (eb->switch_url != NULL)
+      {
+        /* If this is a 'switch' operation, try to construct the switch
+         * target's REPOS_RELPATH. */
+        if (their_url != NULL)
+          right_repos_relpath = svn_uri_is_child(repos_root_url, their_url, pool);
+        else
+          {
+            /* The complete source-right URL is not available, but it
+             * is somewhere below the SWITCH_URL. For now, just go
+             * without it.
+             * ### TODO: Construct a proper THEIR_URL in some of the
+             * delete cases that still pass NULL for THEIR_URL when
+             * calling this function. Do that on the caller's side. */
+            right_repos_relpath = svn_uri_is_child(repos_root_url,
+                                                   eb->switch_url, pool);
+            right_repos_relpath = apr_pstrcat(pool, right_repos_relpath,
+                                              "_THIS_IS_INCOMPLETE", NULL);
+          }
+      }
+    else
+      {
+        /* This is an 'update', so REPOS_RELPATH is the same as for
+         * source-left. */
+        right_repos_relpath = left_repos_relpath;
+      }
+
+    /* Determine PCONFLICT's overall node kind. We give it the source-right
+     * revision (THEIR_NODE_KIND) -- unless source-right is deleted and hence
+     * == svn_node_none, in which case we take it from source-left, which has
+     * to be the node kind that was deleted in source-right. */
+    conflict_node_kind = (action == svn_wc_conflict_action_delete ?
+                          left_kind : their_node_kind);
+    SVN_ERR_ASSERT(conflict_node_kind == svn_node_file
+                   || conflict_node_kind == svn_node_dir);
+
+
+    /* Construct the tree conflict info structs. */
+
+    src_left_version = svn_wc_conflict_version_create(repos_root_url,
+                                                      left_repos_relpath,
+                                                      left_revision,
+                                                      left_kind,
+                                                      pool);
+    
+    src_right_version = svn_wc_conflict_version_create(repos_root_url,
+                                                       right_repos_relpath,
+                                                       *eb->target_revision,
+                                                       their_node_kind,
+                                                       pool);
+
+    *pconflict = svn_wc_conflict_description_create_tree2(
+                     local_abspath, conflict_node_kind,
+                     eb->switch_url ?
+                       svn_wc_operation_switch : svn_wc_operation_update,
+                     src_left_version, src_right_version, pool);
+    (*pconflict)->action = action;
+    (*pconflict)->reason = reason;
+  }
 
   return SVN_NO_ERROR;
 }
@@ -2092,7 +2219,7 @@
   const svn_wc_entry_t *entry;
   svn_boolean_t already_conflicted;
   svn_stringbuf_t *log_item = svn_stringbuf_create("", pool);
-  svn_wc_conflict_description2_t *tree_conflict;
+  svn_wc_conflict_description2_t *tree_conflict = NULL;
   const char *dir_abspath = svn_dirent_dirname(local_abspath, pool);
   svn_boolean_t hidden;
 
@@ -2146,13 +2273,15 @@
   /* Is this path the victim of a newly-discovered tree conflict?  If so,
    * remember it and notify the client. Then (if it was existing and
    * modified), re-schedule the node to be added back again, as a (modified)
-   * copy of the previous base version.
-   */
-  SVN_ERR(check_tree_conflict(&tree_conflict, eb, local_abspath,
-                              svn_wc_conflict_action_delete, svn_node_none,
-                              their_url,
-                              in_deleted_and_tree_conflicted_subtree,
-                              pool));
+   * copy of the previous base version.  */
+
+  /* Check for conflicts only when we haven't already recorded
+   * a tree-conflict on a parent node. */
+  if (!in_deleted_and_tree_conflicted_subtree)
+    SVN_ERR(check_tree_conflict(&tree_conflict, eb, local_abspath,
+                                svn_wc_conflict_action_delete, svn_node_none,
+                                their_url, pool));
+
   if (tree_conflict != NULL)
     {
       /* When we raise a tree conflict on a directory, we want to avoid
@@ -2604,15 +2733,15 @@
             break;
           default:
             {
-              svn_wc_conflict_description2_t *tree_conflict;
+              svn_wc_conflict_description2_t *tree_conflict = NULL;
 
-              /* Raise a tree conflict. */
-              SVN_ERR(check_tree_conflict(
-                          &tree_conflict, eb, db->local_abspath,
-                          svn_wc_conflict_action_add, svn_node_dir,
-                          db->new_URL,
-                          db->in_deleted_and_tree_conflicted_subtree,
-                          pool));
+              /* Check for conflicts only when we haven't already recorded
+               * a tree-conflict on a parent node. */
+              if (!db->in_deleted_and_tree_conflicted_subtree)
+                SVN_ERR(check_tree_conflict(&tree_conflict, eb,
+                                            db->local_abspath,
+                                            svn_wc_conflict_action_add,
+                                            svn_node_dir, db->new_URL, pool));
 
               if (tree_conflict != NULL)
                 {
@@ -2800,7 +2929,7 @@
     SVN_WC__ENTRY_MODIFY_URL | SVN_WC__ENTRY_MODIFY_INCOMPLETE;
 
   svn_boolean_t already_conflicted;
-  svn_wc_conflict_description2_t *tree_conflict;
+  svn_wc_conflict_description2_t *tree_conflict = NULL;
   svn_wc__db_status_t status;
 
   SVN_ERR(make_dir_baton(&db, path, eb, pb, FALSE, pool));
@@ -2857,11 +2986,13 @@
 
   /* Is this path a fresh tree conflict victim?  If so, skip the tree
      with one notification. */
-  SVN_ERR(check_tree_conflict(&tree_conflict, eb, db->local_abspath,
-                              svn_wc_conflict_action_edit,
-                              svn_node_dir, db->new_URL,
-                              db->in_deleted_and_tree_conflicted_subtree,
-                              pool));
+
+  /* Check for conflicts only when we haven't already recorded
+   * a tree-conflict on a parent node. */
+  if (!db->in_deleted_and_tree_conflicted_subtree)
+    SVN_ERR(check_tree_conflict(&tree_conflict, eb, db->local_abspath,
+                                svn_wc_conflict_action_edit, svn_node_dir,
+                                db->new_URL, pool));
 
   /* Remember the roots of any locally deleted trees. */
   if (tree_conflict != NULL)
@@ -3908,14 +4039,16 @@
             break;
           default:
             {
-              svn_wc_conflict_description2_t *tree_conflict;
+              svn_wc_conflict_description2_t *tree_conflict = NULL;
 
-              SVN_ERR(check_tree_conflict(
-                          &tree_conflict, eb, fb->local_abspath,
-                          svn_wc_conflict_action_add, svn_node_file,
-                          fb->new_URL,
-                          pb->in_deleted_and_tree_conflicted_subtree,
-                          subpool));
+              /* Check for conflicts only when we haven't already recorded
+               * a tree-conflict on a parent node. */
+              if (!pb->in_deleted_and_tree_conflicted_subtree)
+                SVN_ERR(check_tree_conflict(&tree_conflict, eb,
+                                            fb->local_abspath,
+                                            svn_wc_conflict_action_add,
+                                            svn_node_file, fb->new_URL,
+                                            subpool));
 
               if (tree_conflict != NULL)
                 {
@@ -3969,7 +4102,7 @@
   struct file_baton *fb;
   svn_node_kind_t kind;
   svn_boolean_t already_conflicted;
-  svn_wc_conflict_description2_t *tree_conflict;
+  svn_wc_conflict_description2_t *tree_conflict = NULL;
 
   /* the file_pool can stick around for a *long* time, so we want to use
      a subpool for any temporary allocations. */
@@ -4026,13 +4159,14 @@
 
   fb->deleted = pb->in_deleted_and_tree_conflicted_subtree;
 
-  /* Is this path the victim of a newly-discovered tree conflict? */
-  SVN_ERR(check_tree_conflict(&tree_conflict, eb, fb->local_abspath,
-                              svn_wc_conflict_action_edit, svn_node_file,
-                              fb->new_URL,
-                              pb->in_deleted_and_tree_conflicted_subtree,
-                              pool));
+  /* Check for conflicts only when we haven't already recorded
+   * a tree-conflict on a parent node. */
+  if (!pb->in_deleted_and_tree_conflicted_subtree)
+    SVN_ERR(check_tree_conflict(&tree_conflict, eb, fb->local_abspath,
+                                svn_wc_conflict_action_edit, svn_node_file,
+                                fb->new_URL, pool));
 
+  /* Is this path the victim of a newly-discovered tree conflict? */
   if (tree_conflict)
     {
       SVN_ERR(svn_wc__loggy_add_tree_conflict(&fb->log_accum, tree_conflict,



Mime
View raw message