In this commit, I run svn_wc__db_read_info() in check_tree_conflicts(), when
half or more of its callers have already called svn_wc__db_read_info().

So would it be an optimization to pass STATUS, maybe more, as args to
check_tree_conflict(), rather than calling svn_wc__db_read_info() twice?
Code readability wise it wouldn't be one. Which way to bend?

Thanks
~Neels

ne...@apache.org wrote:
> 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,
> 
> 

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to