You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2013/01/02 15:38:26 UTC

svn commit: r1427801 [2/2] - in /subversion/trunk/subversion/libsvn_wc: update_editor.c wcroot_anchor.c

Copied: subversion/trunk/subversion/libsvn_wc/wcroot_anchor.c (from r1426819, subversion/trunk/subversion/libsvn_wc/update_editor.c)
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wcroot_anchor.c?p2=subversion/trunk/subversion/libsvn_wc/wcroot_anchor.c&p1=subversion/trunk/subversion/libsvn_wc/update_editor.c&r1=1426819&r2=1427801&rev=1427801&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wcroot_anchor.c Wed Jan  2 14:38:26 2013
@@ -1,5 +1,5 @@
 /*
- * update_editor.c :  main editor for checkouts and updates
+ * wcroot_anchor.c :  wcroot and anchor functions
  *
  * ====================================================================
  *    Licensed to the Apache Software Foundation (ASF) under one
@@ -26,4857 +26,17 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <apr_pools.h>
-#include <apr_hash.h>
-#include <apr_md5.h>
-#include <apr_tables.h>
-#include <apr_strings.h>
-
-#include "svn_types.h"
-#include "svn_pools.h"
-#include "svn_delta.h"
-#include "svn_hash.h"
-#include "svn_string.h"
-#include "svn_dirent_uri.h"
-#include "svn_path.h"
-#include "svn_error.h"
-#include "svn_io.h"
-#include "svn_private_config.h"
-#include "svn_time.h"
-
-#include "wc.h"
-#include "adm_files.h"
-#include "conflicts.h"
-#include "entries.h"
-#include "translate.h"
-#include "workqueue.h"
-
-#include "private/svn_subr_private.h"
-#include "private/svn_wc_private.h"
-/* Checks whether a svn_wc__db_status_t indicates whether a node is
-   present in a working copy. Used by the editor implementation */
-#define IS_NODE_PRESENT(status)                             \
-           ((status) != svn_wc__db_status_server_excluded &&\
-            (status) != svn_wc__db_status_excluded &&       \
-            (status) != svn_wc__db_status_not_present)
-
-static svn_error_t *
-path_join_under_root(const char **result_path,
-                     const char *base_path,
-                     const char *add_path,
-                     apr_pool_t *result_pool);
-
-
-/*
- * This code handles "checkout" and "update" and "switch".
- * A checkout is similar to an update that is only adding new items.
- *
- * The intended behaviour of "update" and "switch", focusing on the checks
- * to be made before applying a change, is:
- *
- *   For each incoming change:
- *     if target is already in conflict or obstructed:
- *       skip this change
- *     else
- *     if this action will cause a tree conflict:
- *       record the tree conflict
- *       skip this change
- *     else:
- *       make this change
- *
- * In more detail:
- *
- *   For each incoming change:
- *
- *   1.   if  # Incoming change is inside an item already in conflict:
- *    a.    tree/text/prop change to node beneath tree-conflicted dir
- *        then  # Skip all changes in this conflicted subtree [*1]:
- *          do not update the Base nor the Working
- *          notify "skipped because already in conflict" just once
- *            for the whole conflicted subtree
- *
- *        if  # Incoming change affects an item already in conflict:
- *    b.    tree/text/prop change to tree-conflicted dir/file, or
- *    c.    tree change to a text/prop-conflicted file/dir, or
- *    d.    text/prop change to a text/prop-conflicted file/dir [*2], or
- *    e.    tree change to a dir tree containing any conflicts,
- *        then  # Skip this change [*1]:
- *          do not update the Base nor the Working
- *          notify "skipped because already in conflict"
- *
- *   2.   if  # Incoming change affects an item that's "obstructed":
- *    a.    on-disk node kind doesn't match recorded Working node kind
- *            (including an absence/presence mis-match),
- *        then  # Skip this change [*1]:
- *          do not update the Base nor the Working
- *          notify "skipped because obstructed"
- *
- *   3.   if  # Incoming change raises a tree conflict:
- *    a.    tree/text/prop change to node beneath sched-delete dir, or
- *    b.    tree/text/prop change to sched-delete dir/file, or
- *    c.    text/prop change to tree-scheduled dir/file,
- *        then  # Skip this change:
- *          do not update the Base nor the Working [*3]
- *          notify "tree conflict"
- *
- *   4.   Apply the change:
- *          update the Base
- *          update the Working, possibly raising text/prop conflicts
- *          notify
- *
- * Notes:
- *
- *      "Tree change" here refers to an add or delete of the target node,
- *      including the add or delete part of a copy or move or rename.
- *
- * [*1] We should skip changes to an entire node, as the base revision number
- *      applies to the entire node. Not sure how this affects attempts to
- *      handle text and prop changes separately.
- *
- * [*2] Details of which combinations of property and text changes conflict
- *      are not specified here.
- *
- * [*3] For now, we skip the update, and require the user to:
- *        - Modify the WC to be compatible with the incoming change;
- *        - Mark the conflict as resolved;
- *        - Repeat the update.
- *      Ideally, it would be possible to resolve any conflict without
- *      repeating the update. To achieve this, we would have to store the
- *      necessary data at conflict detection time, and delay the update of
- *      the Base until the time of resolving.
- */
-
-
-/*** batons ***/
-
-struct edit_baton
-{
-  /* For updates, the "destination" of the edit is ANCHOR_ABSPATH, the
-     directory containing TARGET_ABSPATH. If ANCHOR_ABSPATH itself is the
-     target, the values are identical.
-
-     TARGET_BASENAME is the name of TARGET_ABSPATH in ANCHOR_ABSPATH, or "" if
-     ANCHOR_ABSPATH is the target */
-  const char *target_basename;
-
-  /* Absolute variants of ANCHOR and TARGET */
-  const char *anchor_abspath;
-  const char *target_abspath;
-
-  /* The DB handle for managing the working copy state.  */
-  svn_wc__db_t *db;
-
-  /* Array of file extension patterns to preserve as extensions in
-     generated conflict files. */
-  const apr_array_header_t *ext_patterns;
-
-  /* Hash mapping const char * absolute working copy paths to depth-first
-     ordered arrays of svn_prop_inherited_item_t * structures representing
-     the properties inherited by the base node at that working copy path.
-     May be NULL. */
-  apr_hash_t *wcroot_iprops;
-
-  /* The revision we're targeting...or something like that.  This
-     starts off as a pointer to the revision to which we are updating,
-     or SVN_INVALID_REVNUM, but by the end of the edit, should be
-     pointing to the final revision. */
-  svn_revnum_t *target_revision;
-
-  /* The requested depth of this edit. */
-  svn_depth_t requested_depth;
-
-  /* Is the requested depth merely an operational limitation, or is
-     also the new sticky ambient depth of the update target? */
-  svn_boolean_t depth_is_sticky;
-
-  /* Need to know if the user wants us to overwrite the 'now' times on
-     edited/added files with the last-commit-time. */
-  svn_boolean_t use_commit_times;
-
-  /* Was the root actually opened (was this a non-empty edit)? */
-  svn_boolean_t root_opened;
-
-  /* Was the update-target deleted?  This is a special situation. */
-  svn_boolean_t target_deleted;
-
-  /* Allow unversioned obstructions when adding a path. */
-  svn_boolean_t allow_unver_obstructions;
-
-  /* Handle local additions as modifications of new nodes */
-  svn_boolean_t adds_as_modification;
-
-  /* If set, we check out into an empty directory. This allows for a number
-     of conflict checks to be omitted. */
-  svn_boolean_t clean_checkout;
-
-  /* If this is a 'switch' operation, the new relpath of target_abspath,
-     else NULL. */
-  const char *switch_relpath;
-
-  /* The URL to the root of the repository. */
-  const char *repos_root;
-
-  /* The UUID of the repos, or NULL. */
-  const char *repos_uuid;
-
-  /* External diff3 to use for merges (can be null, in which case
-     internal merge code is used). */
-  const char *diff3_cmd;
-
-  /* Externals handler */
-  svn_wc_external_update_t external_func;
-  void *external_baton;
-
-  /* This editor sends back notifications as it edits. */
-  svn_wc_notify_func2_t notify_func;
-  void *notify_baton;
-
-  /* This editor is normally wrapped in a cancellation editor anyway,
-     so it doesn't bother to check for cancellation itself.  However,
-     it needs a cancel_func and cancel_baton available to pass to
-     long-running functions. */
-  svn_cancel_func_t cancel_func;
-  void *cancel_baton;
-
-  /* This editor will invoke a interactive conflict-resolution
-     callback, if available. */
-  svn_wc_conflict_resolver_func2_t conflict_func;
-  void *conflict_baton;
-
-  /* Subtrees that were skipped during the edit, and therefore shouldn't
-     have their revision/url info updated at the end.  If a path is a
-     directory, its descendants will also be skipped.  The keys are paths
-     relative to the working copy root and the values unspecified. */
-  apr_hash_t *skipped_trees;
-
-  /* A mapping from const char * repos_relpaths to the apr_hash_t * instances
-     returned from fetch_dirents_func for that repos_relpath. These
-     are used to avoid issue #3569 in specific update scenarios where a
-     restricted depth is used. */
-  apr_hash_t *dir_dirents;
-
-  /* Absolute path of the working copy root or NULL if not initialized yet */
-  const char *wcroot_abspath;
-
-  apr_pool_t *pool;
-};
-
-
-/* Record in the edit baton EB that LOCAL_ABSPATH's base version is not being
- * updated.
- *
- * Add to EB->skipped_trees a copy (allocated in EB->pool) of the string
- * LOCAL_ABSPATH.
- */
-static svn_error_t *
-remember_skipped_tree(struct edit_baton *eb,
-                      const char *local_abspath,
-                      apr_pool_t *scratch_pool)
-{
-  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
-
-  apr_hash_set(eb->skipped_trees,
-               apr_pstrdup(eb->pool,
-                           svn_dirent_skip_ancestor(eb->wcroot_abspath,
-                                                    local_abspath)),
-               APR_HASH_KEY_STRING, (void*)1);
-
-  return SVN_NO_ERROR;
-}
-
-struct dir_baton
-{
-  /* Basename of this directory. */
-  const char *name;
-
-  /* Absolute path of this directory */
-  const char *local_abspath;
-
-  /* The repository relative path this directory will correspond to. */
-  const char *new_relpath;
-
-  /* The revision of the directory before updating */
-  svn_revnum_t old_revision;
-
-  /* The repos_relpath before updating/switching */
-  const char *old_repos_relpath;
-
-  /* The global edit baton. */
-  struct edit_baton *edit_baton;
-
-  /* Baton for this directory's parent, or NULL if this is the root
-     directory. */
-  struct dir_baton *parent_baton;
-
-  /* Set if updates to this directory are skipped */
-  svn_boolean_t skip_this;
-
-  /* Set if there was a previous notification for this directory */
-  svn_boolean_t already_notified;
-
-  /* Set if this directory is being added during this editor drive. */
-  svn_boolean_t adding_dir;
-
-  /* Set on a node and its descendants are not present in the working copy
-     but should still be updated (not skipped). These nodes should all be
-     marked as deleted. */
-  svn_boolean_t shadowed;
-
-  /* The (new) changed_* information, cached to avoid retrieving it later */
-  svn_revnum_t changed_rev;
-  apr_time_t changed_date;
-  const char *changed_author;
-
-  /* If not NULL, contains a mapping of const char* basenames of children that
-     have been deleted to their svn_skel_t* tree conflicts.
-     We store this hash to allow replacements to continue under a just
-     installed tree conflict.
-
-     The add after the delete will then update the tree conflicts information
-     and reinstall it. */
-  apr_hash_t *deletion_conflicts;
-
-  /* A hash of file names (only the hash key matters) seen by add_file
-     and not yet added to the database by close_file. */
-  apr_hash_t *not_present_files;
-
-  /* Set if an unversioned dir of the same name already existed in
-     this directory. */
-  svn_boolean_t obstruction_found;
-
-  /* Set if a dir of the same name already exists and is
-     scheduled for addition without history. */
-  svn_boolean_t add_existed;
-
-  /* An array of svn_prop_t structures, representing all the property
-     changes to be applied to this directory. */
-  apr_array_header_t *propchanges;
-
-  /* A boolean indicating whether this node or one of its children has
-     received any 'real' changes. Used to avoid tree conflicts for simple
-     entryprop changes, like lock management */
-  svn_boolean_t edited;
-
-  /* The tree conflict to install once the node is really edited */
-  svn_skel_t *edit_conflict;
-
-  /* The bump information for this directory. */
-  struct bump_dir_info *bump_info;
-
-  /* The depth of the directory in the wc (or inferred if added).  Not
-     used for filtering; we have a separate wrapping editor for that. */
-  svn_depth_t ambient_depth;
-
-  /* Was the directory marked as incomplete before the update?
-     (In other words, are we resuming an interrupted update?)
-
-     If WAS_INCOMPLETE is set to TRUE we expect to receive all child nodes
-     and properties for/of the directory. If WAS_INCOMPLETE is FALSE then
-     we only receive the changes in/for children and properties.*/
-  svn_boolean_t was_incomplete;
-
-  /* The pool in which this baton itself is allocated. */
-  apr_pool_t *pool;
-};
-
-
-/* The bump information is tracked separately from the directory batons.
-   This is a small structure kept in the edit pool, while the heavier
-   directory baton is managed by the editor driver.
-
-   In a postfix delta case, the directory batons are going to disappear.
-   The files will refer to these structures, rather than the full
-   directory baton.  */
-struct bump_dir_info
-{
-  /* ptr to the bump information for the parent directory */
-  struct bump_dir_info *parent;
-
-  /* how many entries are referring to this bump information? */
-  int ref_count;
-
-  /* Pool that should be cleared after the dir is bumped */
-  apr_pool_t *pool;
-};
-
-
-struct handler_baton
-{
-  svn_txdelta_window_handler_t apply_handler;
-  void *apply_baton;
-  apr_pool_t *pool;
-  struct file_baton *fb;
-
-  /* Where we are assembling the new file. */
-  const char *new_text_base_tmp_abspath;
-
-    /* The expected source checksum of the text source or NULL if no base
-     checksum is available (MD5 if the server provides a checksum, SHA1 if
-     the server doesn't) */
-  svn_checksum_t *expected_source_checksum;
-
-  /* Why two checksums?
-     The editor currently provides an md5 which we use to detect corruption
-     during transmission.  We use the sha1 inside libsvn_wc both for pristine
-     handling and corruption detection.  In the future, the editor will also
-     provide a sha1, so we may not have to calculate both, but for the time
-     being, that's the way it is. */
-
-  /* The calculated checksum of the text source or NULL if the acual
-     checksum is not being calculated. The checksum kind is identical to the
-     kind of expected_source_checksum. */
-  svn_checksum_t *actual_source_checksum;
-
-  /* The stream used to calculate the source checksums */
-  svn_stream_t *source_checksum_stream;
-
-  /* A calculated MD5 digest of NEW_TEXT_BASE_TMP_ABSPATH.
-     This is initialized to all zeroes when the baton is created, then
-     populated with the MD5 digest of the resultant fulltext after the
-     last window is handled by the handler returned from
-     apply_textdelta(). */
-  unsigned char new_text_base_md5_digest[APR_MD5_DIGESTSIZE];
-
-  /* A calculated SHA-1 of NEW_TEXT_BASE_TMP_ABSPATH, which we'll use for
-     eventually writing the pristine. */
-  svn_checksum_t * new_text_base_sha1_checksum;
-};
-
-
-/* Get an empty file in the temporary area for WRI_ABSPATH.  The file will
-   not be set for automatic deletion, and the name will be returned in
-   TMP_FILENAME.
-
-   This implementation creates a new empty file with a unique name.
-
-   ### This is inefficient for callers that just want an empty file to read
-   ### from.  There could be (and there used to be) a permanent, shared
-   ### empty file for this purpose.
-
-   ### This is inefficient for callers that just want to reserve a unique
-   ### file name to create later.  A better way may not be readily available.
- */
-static svn_error_t *
-get_empty_tmp_file(const char **tmp_filename,
-                   svn_wc__db_t *db,
-                   const char *wri_abspath,
-                   apr_pool_t *result_pool,
-                   apr_pool_t *scratch_pool)
-{
-  const char *temp_dir_abspath;
-
-  SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&temp_dir_abspath, db, wri_abspath,
-                                         scratch_pool, scratch_pool));
-  SVN_ERR(svn_io_open_unique_file3(NULL, tmp_filename, temp_dir_abspath,
-                                   svn_io_file_del_none,
-                                   scratch_pool, scratch_pool));
-
-  return SVN_NO_ERROR;
-}
-
-/* An APR pool cleanup handler.  This runs the working queue for an
-   editor baton. */
-static apr_status_t
-cleanup_edit_baton(void *edit_baton)
-{
-  struct edit_baton *eb = edit_baton;
-  svn_error_t *err;
-  apr_pool_t *pool = apr_pool_parent_get(eb->pool);
-
-  err = svn_wc__wq_run(eb->db, eb->wcroot_abspath,
-                       NULL /* cancel_func */, NULL /* cancel_baton */,
-                       pool);
-
-  if (err)
-    {
-      apr_status_t apr_err = err->apr_err;
-      svn_error_clear(err);
-      return apr_err;
-    }
-  return APR_SUCCESS;
-}
-
-/* Make a new dir baton in a subpool of PB->pool. PB is the parent baton.
-   If PATH and PB are NULL, this is the root directory of the edit; in this
-   case, make the new dir baton in a subpool of EB->pool.
-   ADDING should be TRUE if we are adding this directory.  */
-static svn_error_t *
-make_dir_baton(struct dir_baton **d_p,
-               const char *path,
-               struct edit_baton *eb,
-               struct dir_baton *pb,
-               svn_boolean_t adding,
-               apr_pool_t *scratch_pool)
-{
-  apr_pool_t *dir_pool;
-  struct dir_baton *d;
-  struct bump_dir_info *bdi;
-
-  if (pb != NULL)
-    dir_pool = svn_pool_create(pb->pool);
-  else
-    dir_pool = svn_pool_create(eb->pool);
-
-  SVN_ERR_ASSERT(path || (! pb));
-
-  /* Okay, no easy out, so allocate and initialize a dir baton. */
-  d = apr_pcalloc(dir_pool, sizeof(*d));
-
-  /* Construct the PATH and baseNAME of this directory. */
-  if (path)
-    {
-      d->name = svn_dirent_basename(path, dir_pool);
-      SVN_ERR(path_join_under_root(&d->local_abspath,
-                                   pb->local_abspath, d->name, dir_pool));
-    }
-  else
-    {
-      /* This is the root baton. */
-      d->name = NULL;
-      d->local_abspath = eb->anchor_abspath;
-    }
-
-  /* Figure out the new_relpath for this directory. */
-  if (eb->switch_relpath)
-    {
-      /* Handle switches... */
-
-      if (pb == NULL)
-        {
-          if (*eb->target_basename == '\0')
-            {
-              /* No parent baton and target_basename=="" means that we are
-                 the target of the switch. Thus, our NEW_RELPATH will be
-                 the SWITCH_RELPATH.  */
-              d->new_relpath = eb->switch_relpath;
-            }
-          else
-            {
-              /* This node is NOT the target of the switch (one of our
-                 children is the target); therefore, it must already exist.
-                 Get its old REPOS_RELPATH, as it won't be changing.  */
-              SVN_ERR(svn_wc__db_scan_base_repos(&d->new_relpath, NULL, NULL,
-                                                 eb->db, d->local_abspath,
-                                                 dir_pool, scratch_pool));
-            }
-        }
-      else
-        {
-          /* This directory is *not* the root (has a parent). If there is
-             no grandparent, then we may have anchored at the parent,
-             and self is the target. If we match the target, then set
-             NEW_RELPATH to the SWITCH_RELPATH.
-
-             Otherwise, we simply extend NEW_RELPATH from the parent.  */
-          if (pb->parent_baton == NULL
-              && strcmp(eb->target_basename, d->name) == 0)
-            d->new_relpath = eb->switch_relpath;
-          else
-            d->new_relpath = svn_relpath_join(pb->new_relpath, d->name,
-                                              dir_pool);
-        }
-    }
-  else  /* must be an update */
-    {
-      /* If we are adding the node, then simply extend the parent's
-         relpath for our own.  */
-      if (adding)
-        {
-          SVN_ERR_ASSERT(pb != NULL);
-          d->new_relpath = svn_relpath_join(pb->new_relpath, d->name,
-                                            dir_pool);
-        }
-      else
-        {
-          SVN_ERR(svn_wc__db_scan_base_repos(&d->new_relpath, NULL, NULL,
-                                             eb->db, d->local_abspath,
-                                             dir_pool, scratch_pool));
-          SVN_ERR_ASSERT(d->new_relpath);
-        }
-    }
-
-  /* the bump information lives in the edit pool */
-  bdi = apr_pcalloc(dir_pool, sizeof(*bdi));
-  bdi->parent = pb ? pb->bump_info : NULL;
-  bdi->ref_count = 1;
-  bdi->pool = dir_pool;
-
-  /* the parent's bump info has one more referer */
-  if (pb)
-    ++bdi->parent->ref_count;
-
-  d->edit_baton   = eb;
-  d->parent_baton = pb;
-  d->pool         = dir_pool;
-  d->propchanges  = apr_array_make(dir_pool, 1, sizeof(svn_prop_t));
-  d->obstruction_found = FALSE;
-  d->add_existed  = FALSE;
-  d->bump_info    = bdi;
-  d->old_revision = SVN_INVALID_REVNUM;
-  d->adding_dir   = adding;
-  d->changed_rev  = SVN_INVALID_REVNUM;
-  d->not_present_files = apr_hash_make(dir_pool);
-
-  /* Copy some flags from the parent baton */
-  if (pb)
-    {
-      d->skip_this = pb->skip_this;
-      d->shadowed = pb->shadowed;
-    }
-
-  /* The caller of this function needs to fill these in. */
-  d->ambient_depth = svn_depth_unknown;
-  d->was_incomplete = FALSE;
-
-  *d_p = d;
-  return SVN_NO_ERROR;
-}
-
-
-/* Forward declarations. */
-static svn_error_t *
-already_in_a_tree_conflict(svn_boolean_t *conflicted,
-                           svn_wc__db_t *db,
-                           const char *local_abspath,
-                           apr_pool_t *scratch_pool);
-
-
-static void
-do_notification(const struct edit_baton *eb,
-                const char *local_abspath,
-                svn_node_kind_t kind,
-                svn_wc_notify_action_t action,
-                apr_pool_t *scratch_pool)
-{
-  svn_wc_notify_t *notify;
-
-  if (eb->notify_func == NULL)
-    return;
-
-  notify = svn_wc_create_notify(local_abspath, action, scratch_pool);
-  notify->kind = kind;
-
-  (*eb->notify_func)(eb->notify_baton, notify, scratch_pool);
-}
-
-/* Decrement the bump_dir_info's reference count. If it hits zero,
-   then this directory is "done". This means it is safe to clear its pool.
-
-   In addition, when the directory is "done", we loop onto the parent's
-   bump information to possibly mark it as done, too.
-*/
-static svn_error_t *
-maybe_release_dir_info(struct bump_dir_info *bdi)
-{
-  /* Keep moving up the tree of directories until we run out of parents,
-     or a directory is not yet "done".  */
-  while (bdi != NULL)
-    {
-      apr_pool_t *destroy_pool;
-
-      if (--bdi->ref_count > 0)
-        break;  /* directory isn't done yet */
-
-      destroy_pool = bdi->pool;
-      bdi = bdi->parent;
-
-      svn_pool_destroy(destroy_pool);
-    }
-  /* we exited the for loop because there are no more parents */
-
-  return SVN_NO_ERROR;
-}
-
-struct file_baton
-{
-  /* Pool specific to this file_baton. */
-  apr_pool_t *pool;
-
-  /* Name of this file (its entry in the directory). */
-  const char *name;
-
-  /* Absolute path to this file */
-  const char *local_abspath;
-
-  /* The repository relative path this file will correspond to. */
-  const char *new_relpath;
-
-  /* The revision of the file before updating */
-  svn_revnum_t old_revision;
-
-  /* The repos_relpath before updating/switching */
-  const char *old_repos_relpath;
-
-  /* The global edit baton. */
-  struct edit_baton *edit_baton;
-
-  /* The parent directory of this file. */
-  struct dir_baton *dir_baton;
-
-  /* Set if updates to this directory are skipped */
-  svn_boolean_t skip_this;
-
-  /* Set if there was a previous notification  */
-  svn_boolean_t already_notified;
-
-  /* Set if this file is new. */
-  svn_boolean_t adding_file;
-
-  /* Set if an unversioned file of the same name already existed in
-     this directory. */
-  svn_boolean_t obstruction_found;
-
-  /* Set if a file of the same name already exists and is
-     scheduled for addition without history. */
-  svn_boolean_t add_existed;
-
-  /* Set if this file is being added in the BASE layer, but is not-present
-     in the working copy (replaced, deleted, etc.). */
-  svn_boolean_t shadowed;
-
-  /* The (new) changed_* information, cached to avoid retrieving it later */
-  svn_revnum_t changed_rev;
-  apr_time_t changed_date;
-  const char *changed_author;
-
-  /* If there are file content changes, these are the checksums of the
-     resulting new text base, which is in the pristine store, else NULL. */
-  const svn_checksum_t *new_text_base_md5_checksum;
-  const svn_checksum_t *new_text_base_sha1_checksum;
-
-  /* The checksum of the file before the update */
-  const svn_checksum_t *original_checksum;
-
-  /* An array of svn_prop_t structures, representing all the property
-     changes to be applied to this file.  Once a file baton is
-     initialized, this is never NULL, but it may have zero elements.  */
-  apr_array_header_t *propchanges;
-
-  /* For existing files, whether there are local modifications. FALSE for added
-     files */
-  svn_boolean_t local_prop_mods;
-
-  /* Bump information for the directory this file lives in */
-  struct bump_dir_info *bump_info;
-
-  /* A boolean indicating whether this node or one of its children has
-     received any 'real' changes. Used to avoid tree conflicts for simple
-     entryprop changes, like lock management */
-  svn_boolean_t edited;
-
-  /* The tree conflict to install once the node is really edited */
-  svn_skel_t *edit_conflict;
-};
-
-
-/* Make a new file baton in a subpool of PB->pool. PB is the parent baton.
- * PATH is relative to the root of the edit. ADDING tells whether this file
- * is being added. */
-static svn_error_t *
-make_file_baton(struct file_baton **f_p,
-                struct dir_baton *pb,
-                const char *path,
-                svn_boolean_t adding,
-                apr_pool_t *scratch_pool)
-{
-  struct edit_baton *eb = pb->edit_baton;
-  apr_pool_t *file_pool = svn_pool_create(pb->pool);
-  struct file_baton *f = apr_pcalloc(file_pool, sizeof(*f));
-
-  SVN_ERR_ASSERT(path);
-
-  /* Make the file's on-disk name. */
-  f->name = svn_dirent_basename(path, file_pool);
-  f->old_revision = SVN_INVALID_REVNUM;
-  SVN_ERR(path_join_under_root(&f->local_abspath,
-                               pb->local_abspath, f->name, file_pool));
-
-  /* Figure out the new URL for this file. */
-  if (eb->switch_relpath)
-    {
-      /* Handle switches... */
-
-      /* This file has a parent directory. If there is
-         no grandparent, then we may have anchored at the parent,
-         and self is the target. If we match the target, then set
-         NEW_RELPATH to the SWITCH_RELPATH.
-
-         Otherwise, we simply extend NEW_RELPATH from the parent.  */
-      if (pb->parent_baton == NULL
-          && strcmp(eb->target_basename, f->name) == 0)
-        f->new_relpath = eb->switch_relpath;
-      else
-        f->new_relpath = svn_relpath_join(pb->new_relpath, f->name,
-                                          file_pool);
-    }
-  else  /* must be an update */
-    {
-      if (adding)
-        f->new_relpath = svn_relpath_join(pb->new_relpath, f->name, file_pool);
-      else
-        {
-          SVN_ERR(svn_wc__db_scan_base_repos(&f->new_relpath, NULL, NULL,
-                                             eb->db, f->local_abspath,
-                                             file_pool, scratch_pool));
-          SVN_ERR_ASSERT(f->new_relpath);
-        }
-    }
-
-  f->pool              = file_pool;
-  f->edit_baton        = pb->edit_baton;
-  f->propchanges       = apr_array_make(file_pool, 1, sizeof(svn_prop_t));
-  f->bump_info         = pb->bump_info;
-  f->adding_file       = adding;
-  f->obstruction_found = FALSE;
-  f->add_existed       = FALSE;
-  f->skip_this         = pb->skip_this;
-  f->shadowed          = pb->shadowed;
-  f->dir_baton         = pb;
-  f->changed_rev       = SVN_INVALID_REVNUM;
-
-  /* the directory's bump info has one more referer now */
-  ++f->bump_info->ref_count;
-
-  *f_p = f;
-  return SVN_NO_ERROR;
-}
-
-/* Complete a conflict skel by describing the update.
- *
- * All temporary allocations are be made in SCRATCH_POOL, while allocations
- * needed for the returned conflict struct are made in RESULT_POOL.
- */
-static svn_error_t *
-complete_conflict(svn_skel_t *conflict,
-                  const struct dir_baton *pb,
-                  const char *local_abspath,
-                  const char *old_repos_relpath,
-                  svn_revnum_t old_revision,
-                  svn_node_kind_t kind,
-                  apr_pool_t *result_pool, apr_pool_t *scratch_pool)
-{
-  const struct edit_baton *eb = pb->edit_baton;
-  svn_wc_conflict_version_t *src_left_version;
-  svn_boolean_t is_complete;
-
-  if (!conflict)
-    return SVN_NO_ERROR; /* Not conflicted */
-
-  SVN_ERR(svn_wc__conflict_skel_is_complete(&is_complete, conflict));
-
-  if (is_complete)
-    return SVN_NO_ERROR; /* Already completed */
-
-  if (old_repos_relpath)
-    src_left_version = svn_wc_conflict_version_create2(eb->repos_root,
-                                                       eb->repos_uuid,
-                                                       old_repos_relpath,
-                                                       old_revision,
-                                                       kind,
-                                                       result_pool);
-  else
-    src_left_version = NULL;
-
-
-  if (eb->switch_relpath)
-    SVN_ERR(svn_wc__conflict_skel_set_op_switch(conflict,
-                                                src_left_version,
-                                                result_pool, scratch_pool));
-  else
-    SVN_ERR(svn_wc__conflict_skel_set_op_update(conflict,
-                                                src_left_version,
-                                                result_pool, scratch_pool));
-
-  return SVN_NO_ERROR;
-}
-
-
-/* Called when a directory is really edited, to avoid marking a
-   tree conflict on a node for a no-change edit */
-static svn_error_t *
-mark_directory_edited(struct dir_baton *db, apr_pool_t *scratch_pool)
-{
-  if (db->edited)
-    return SVN_NO_ERROR;
-
-  if (db->parent_baton)
-    SVN_ERR(mark_directory_edited(db->parent_baton, scratch_pool));
-
-  db->edited = TRUE;
-
-  if (db->edit_conflict)
-    {
-      /* We have a (delayed) tree conflict to install */
-
-      SVN_ERR(complete_conflict(db->edit_conflict, db->parent_baton,
-                                db->local_abspath, db->old_repos_relpath,
-                                db->old_revision, svn_node_dir,
-                                db->pool, scratch_pool));
-      SVN_ERR(svn_wc__db_op_mark_conflict(db->edit_baton->db,
-                                          db->local_abspath,
-                                          db->edit_conflict, NULL,
-                                          scratch_pool));
-
-      do_notification(db->edit_baton, db->local_abspath, svn_node_dir,
-                      svn_wc_notify_tree_conflict, scratch_pool);
-      db->already_notified = TRUE;
-    }
-
-  return SVN_NO_ERROR;
-}
-
-/* Called when a file is really edited, to avoid marking a
-   tree conflict on a node for a no-change edit */
-static svn_error_t *
-mark_file_edited(struct file_baton *fb, apr_pool_t *scratch_pool)
-{
-  if (fb->edited)
-    return SVN_NO_ERROR;
-
-  SVN_ERR(mark_directory_edited(fb->dir_baton, scratch_pool));
-
-  fb->edited = TRUE;
-
-  if (fb->edit_conflict)
-    {
-      /* We have a (delayed) tree conflict to install */
-
-      SVN_ERR(complete_conflict(fb->edit_conflict, fb->dir_baton,
-                                fb->local_abspath, fb->old_repos_relpath,
-                                fb->old_revision, svn_node_file,
-                                fb->pool, scratch_pool));
-
-      SVN_ERR(svn_wc__db_op_mark_conflict(fb->edit_baton->db,
-                                          fb->local_abspath,
-                                          fb->edit_conflict, NULL,
-                                          scratch_pool));
-
-      do_notification(fb->edit_baton, fb->local_abspath, svn_node_file,
-                      svn_wc_notify_tree_conflict, scratch_pool);
-      fb->already_notified = TRUE;
-    }
-
-  return SVN_NO_ERROR;
-}
-
-
-/* Handle the next delta window of the file described by BATON.  If it is
- * the end (WINDOW == NULL), then check the checksum, store the text in the
- * pristine store and write its details into BATON->fb->new_text_base_*. */
-static svn_error_t *
-window_handler(svn_txdelta_window_t *window, void *baton)
-{
-  struct handler_baton *hb = baton;
-  struct file_baton *fb = hb->fb;
-  svn_wc__db_t *db = fb->edit_baton->db;
-  svn_error_t *err;
-
-  /* Apply this window.  We may be done at that point.  */
-  err = hb->apply_handler(window, hb->apply_baton);
-  if (window != NULL && !err)
-    return SVN_NO_ERROR;
-
-  if (hb->expected_source_checksum)
-    {
-      /* Close the stream to calculate HB->actual_source_md5_checksum. */
-      svn_error_t *err2 = svn_stream_close(hb->source_checksum_stream);
-
-      if (!err2)
-        {
-          SVN_ERR_ASSERT(hb->expected_source_checksum->kind ==
-                        hb->actual_source_checksum->kind);
-
-          if (!svn_checksum_match(hb->expected_source_checksum,
-                                  hb->actual_source_checksum))
-            {
-              err = svn_error_createf(SVN_ERR_WC_CORRUPT_TEXT_BASE, err,
-                        _("Checksum mismatch while updating '%s':\n"
-                          "   expected:  %s\n"
-                          "     actual:  %s\n"),
-                        svn_dirent_local_style(fb->local_abspath, hb->pool),
-                        svn_checksum_to_cstring(hb->expected_source_checksum,
-                                                hb->pool),
-                        svn_checksum_to_cstring(hb->actual_source_checksum,
-                                                hb->pool));
-            }
-        }
-
-      err = svn_error_compose_create(err, err2);
-    }
-
-  if (err)
-    {
-      /* We failed to apply the delta; clean up the temporary file.  */
-      svn_error_clear(svn_io_remove_file2(hb->new_text_base_tmp_abspath, TRUE,
-                                          hb->pool));
-    }
-  else
-    {
-      /* Tell the file baton about the new text base's checksums. */
-      fb->new_text_base_md5_checksum =
-        svn_checksum__from_digest_md5(hb->new_text_base_md5_digest, fb->pool);
-      fb->new_text_base_sha1_checksum =
-        svn_checksum_dup(hb->new_text_base_sha1_checksum, fb->pool);
-
-      /* Store the new pristine text in the pristine store now.  Later, in a
-         single transaction we will update the BASE_NODE to include a
-         reference to this pristine text's checksum. */
-      SVN_ERR(svn_wc__db_pristine_install(db, hb->new_text_base_tmp_abspath,
-                                          fb->new_text_base_sha1_checksum,
-                                          fb->new_text_base_md5_checksum,
-                                          hb->pool));
-    }
-
-  svn_pool_destroy(hb->pool);
-
-  return err;
-}
-
-
-/* Find the last-change info within ENTRY_PROPS, and return then in the
-   CHANGED_* parameters. Each parameter will be initialized to its "none"
-   value, and will contain the relavent info if found.
-
-   CHANGED_AUTHOR will be allocated in RESULT_POOL. SCRATCH_POOL will be
-   used for some temporary allocations.
-*/
-static svn_error_t *
-accumulate_last_change(svn_revnum_t *changed_rev,
-                       apr_time_t *changed_date,
-                       const char **changed_author,
-                       const apr_array_header_t *entry_props,
-                       apr_pool_t *result_pool,
-                       apr_pool_t *scratch_pool)
-{
-  int i;
-
-  *changed_rev = SVN_INVALID_REVNUM;
-  *changed_date = 0;
-  *changed_author = NULL;
-
-  for (i = 0; i < entry_props->nelts; ++i)
-    {
-      const svn_prop_t *prop = &APR_ARRAY_IDX(entry_props, i, svn_prop_t);
-
-      /* A prop value of NULL means the information was not
-         available.  We don't remove this field from the entries
-         file; we have convention just leave it empty.  So let's
-         just skip those entry props that have no values. */
-      if (! prop->value)
-        continue;
-
-      if (! strcmp(prop->name, SVN_PROP_ENTRY_LAST_AUTHOR))
-        *changed_author = apr_pstrdup(result_pool, prop->value->data);
-      else if (! strcmp(prop->name, SVN_PROP_ENTRY_COMMITTED_REV))
-        {
-          apr_int64_t rev;
-          SVN_ERR(svn_cstring_atoi64(&rev, prop->value->data));
-          *changed_rev = (svn_revnum_t)rev;
-        }
-      else if (! strcmp(prop->name, SVN_PROP_ENTRY_COMMITTED_DATE))
-        SVN_ERR(svn_time_from_cstring(changed_date, prop->value->data,
-                                      scratch_pool));
-
-      /* Starting with Subversion 1.7 we ignore the SVN_PROP_ENTRY_UUID
-         property here. */
-    }
-
-  return SVN_NO_ERROR;
-}
-
-
-/* Join ADD_PATH to BASE_PATH.  If ADD_PATH is absolute, or if any ".."
- * component of it resolves to a path above BASE_PATH, then return
- * SVN_ERR_WC_OBSTRUCTED_UPDATE.
- *
- * This is to prevent the situation where the repository contains,
- * say, "..\nastyfile".  Although that's perfectly legal on some
- * systems, when checked out onto Win32 it would cause "nastyfile" to
- * be created in the parent of the current edit directory.
- *
- * (http://cve.mitre.org/cgi-bin/cvename.cgi?name=2007-3846)
- */
-static svn_error_t *
-path_join_under_root(const char **result_path,
-                     const char *base_path,
-                     const char *add_path,
-                     apr_pool_t *pool)
-{
-  svn_boolean_t under_root;
-
-  SVN_ERR(svn_dirent_is_under_root(&under_root,
-                                   result_path, base_path, add_path, pool));
-
-  if (! under_root)
-    {
-      return svn_error_createf(
-          SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
-          _("Path '%s' is not in the working copy"),
-          svn_dirent_local_style(svn_dirent_join(base_path, add_path, pool),
-                                 pool));
-    }
-
-  return SVN_NO_ERROR;
-}
-
-
-/*** The callbacks we'll plug into an svn_delta_editor_t structure. ***/
-
-/* An svn_delta_editor_t function. */
-static svn_error_t *
-set_target_revision(void *edit_baton,
-                    svn_revnum_t target_revision,
-                    apr_pool_t *pool)
-{
-  struct edit_baton *eb = edit_baton;
-
-  *(eb->target_revision) = target_revision;
-  return SVN_NO_ERROR;
-}
-
-/* An svn_delta_editor_t function. */
-static svn_error_t *
-open_root(void *edit_baton,
-          svn_revnum_t base_revision, /* This is ignored in co */
-          apr_pool_t *pool,
-          void **dir_baton)
-{
-  struct edit_baton *eb = edit_baton;
-  struct dir_baton *db;
-  svn_boolean_t already_conflicted;
-  svn_error_t *err;
-  svn_wc__db_status_t status;
-
-  /* Note that something interesting is actually happening in this
-     edit run. */
-  eb->root_opened = TRUE;
-
-  SVN_ERR(make_dir_baton(&db, NULL, eb, NULL, FALSE, pool));
-  *dir_baton = db;
-
-  err = already_in_a_tree_conflict(&already_conflicted, eb->db,
-                                   db->local_abspath, pool);
-
-  if (err)
-    {
-      if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
-        return svn_error_trace(err);
-
-      svn_error_clear(err);
-      already_conflicted = FALSE;
-    }
-  else if (already_conflicted)
-    {
-      db->skip_this = TRUE;
-      db->already_notified = TRUE;
-
-      /* Notify that we skipped the target, while we actually skipped
-         the anchor */
-      do_notification(eb, eb->target_abspath, svn_node_unknown,
-                      svn_wc_notify_skip_conflicted, pool);
-
-      return SVN_NO_ERROR;
-    }
-
-  if (*eb->target_basename == '\0')
-    {
-      /* For an update with a NULL target, this is equivalent to open_dir(): */
-
-      /* Read the depth from the entry. */
-      SVN_ERR(svn_wc__db_base_get_info(&status, NULL, &db->old_revision,
-                                       &db->old_repos_relpath, NULL, NULL,
-                                       &db->changed_rev, &db->changed_date,
-                                       &db->changed_author, &db->ambient_depth,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       eb->db, db->local_abspath,
-                                       db->pool, pool));
-      db->was_incomplete = (status == svn_wc__db_status_incomplete);
-
-      SVN_ERR(svn_wc__db_temp_op_start_directory_update(eb->db,
-                                                        db->local_abspath,
-                                                        db->new_relpath,
-                                                        *eb->target_revision,
-                                                        pool));
-    }
-
-  return SVN_NO_ERROR;
-}
-
-
-/* ===================================================================== */
-/* Checking for local modifications. */
-
-/* A baton for use with modcheck_found_entry(). */
-typedef struct modcheck_baton_t {
-  svn_wc__db_t *db;         /* wc_db to access nodes */
-  svn_boolean_t found_mod;  /* whether a modification has been found */
-  svn_boolean_t found_not_delete;  /* Found a not-delete modification */
-  svn_boolean_t is_copy; /* check for post-copy modifications only */
-  const char *modcheck_root_abspath;
-} modcheck_baton_t;
-
-/* An implementation of svn_wc_status_func4_t. */
-static svn_error_t *
-modcheck_callback(void *baton,
-                  const char *local_abspath,
-                  const svn_wc_status3_t *status,
-                  apr_pool_t *scratch_pool)
-{
-  modcheck_baton_t *mb = baton;
-
-  switch (status->node_status)
-    {
-      case svn_wc_status_normal:
-      case svn_wc_status_incomplete:
-      case svn_wc_status_ignored:
-      case svn_wc_status_none:
-      case svn_wc_status_unversioned:
-      case svn_wc_status_external:
-        break;
-
-      case svn_wc_status_deleted:
-        mb->found_mod = TRUE;
-        break;
-
-      case svn_wc_status_missing:
-      case svn_wc_status_obstructed:
-        if (status->prop_status != svn_wc_status_modified)
-          break;
-
-        mb->found_mod = TRUE;
-        mb->found_not_delete = TRUE;
-        /* Exit from the status walker: We know what we want to know */
-        return svn_error_create(SVN_ERR_CEASE_INVOCATION, NULL, NULL);
-
-      case svn_wc_status_added:
-        /* Ignore the copy status if we expect a copy, but don't ignore
-           other changes */
-        if (!mb->is_copy
-            || status->text_status == svn_wc_status_modified
-            || status->prop_status == svn_wc_status_modified
-            || strcmp(mb->modcheck_root_abspath, local_abspath) != 0)
-          {
-            mb->found_mod = TRUE;
-            mb->found_not_delete = TRUE;
-            /* Exit from the status walker: We know what we want to know */
-            return svn_error_create(SVN_ERR_CEASE_INVOCATION, NULL, NULL);
-          }
-        break;
-
-      default:
-      case svn_wc_status_replaced:
-      case svn_wc_status_modified:
-        mb->found_mod = TRUE;
-        mb->found_not_delete = TRUE;
-        /* Exit from the status walker: We know what we want to know */
-        return svn_error_create(SVN_ERR_CEASE_INVOCATION, NULL, NULL);
-    }
-
-  return SVN_NO_ERROR;
-}
-
-
-/* Set *MODIFIED to true iff there are any local modifications within the
- * tree rooted at LOCAL_ABSPATH, using DB. If *MODIFIED
- * is set to true and all the local modifications were deletes then set
- * *ALL_EDITS_ARE_DELETES to true, set it to false otherwise.  LOCAL_ABSPATH
- * may be a file or a directory. If IS_COPY is TRUE, LOCAL_ABSPATH is a
- * copied (or moved) node, and nodes at or within LOCAL_ABSPATH are only
- * considered modified if they were modified post-copy. */
-static svn_error_t *
-node_has_local_mods(svn_boolean_t *modified,
-                    svn_boolean_t *all_edits_are_deletes,
-                    svn_boolean_t is_copy,
-                    svn_wc__db_t *db,
-                    const char *local_abspath,
-                    svn_cancel_func_t cancel_func,
-                    void *cancel_baton,
-                    apr_pool_t *scratch_pool)
-{
-  modcheck_baton_t modcheck_baton = { NULL, FALSE, FALSE, FALSE };
-  svn_error_t *err;
-
-  modcheck_baton.db = db;
-  modcheck_baton.is_copy = is_copy;
-  modcheck_baton.modcheck_root_abspath = local_abspath;
-
-  /* Walk the WC tree for status with depth infinity, looking for any local
-   * modifications. If it's a "sparse" directory, that's OK: there can be
-   * no local mods in the pieces that aren't present in the WC. */
-
-  err = svn_wc__internal_walk_status(db, local_abspath,
-                                     svn_depth_infinity,
-                                     FALSE, FALSE, FALSE, NULL,
-                                     modcheck_callback, &modcheck_baton,
-                                     cancel_func, cancel_baton,
-                                     scratch_pool);
-
-  if (err && err->apr_err == SVN_ERR_CEASE_INVOCATION)
-    svn_error_clear(err);
-  else
-    SVN_ERR(err);
-
-  *modified = modcheck_baton.found_mod;
-  *all_edits_are_deletes = !modcheck_baton.found_not_delete;
-
-  return SVN_NO_ERROR;
-}
-
-/* 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.
- *
- * The edit baton EB gives information including whether the operation is
- * an update or a switch.
- *
- * WORKING_STATUS and WORKING_KIND are the current node status of LOCAL_ABSPATH
- * and EXISTS_IN_REPOS specifies whether a BASE_NODE representation for exists
- * for this node.
- *
- * If a tree conflict reason was found for the incoming action, the resulting
- * tree conflict info is returned in *PCONFLICT. PCONFLICT must be non-NULL,
- * while *PCONFLICT is always overwritten.
- *
- * The tree conflict is allocated in RESULT_POOL. Temporary allocations use
- * SCRATCH_POOL.
- */
-static svn_error_t *
-check_tree_conflict(svn_skel_t **pconflict,
-                    struct edit_baton *eb,
-                    const char *local_abspath,
-                    svn_wc__db_status_t working_status,
-                    svn_kind_t working_kind,
-                    svn_boolean_t exists_in_repos,
-                    svn_wc_conflict_action_t action,
-                    apr_pool_t *result_pool,
-                    apr_pool_t *scratch_pool)
-{
-  svn_wc_conflict_reason_t reason = SVN_WC_CONFLICT_REASON_NONE;
-  svn_boolean_t modified = FALSE;
-  svn_boolean_t all_mods_are_deletes = FALSE;
-
-  *pconflict = NULL;
-
-  /* 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 (working_status)
-    {
-      case svn_wc__db_status_added:
-      case svn_wc__db_status_moved_here:
-      case svn_wc__db_status_copied:
-        if (!exists_in_repos)
-          {
-            /* 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);
-
-            /* Scan the addition in case our caller didn't. */
-            if (working_status == svn_wc__db_status_added)
-              SVN_ERR(svn_wc__db_scan_addition(&working_status, NULL, NULL,
-                                               NULL, NULL, NULL, NULL,
-                                               NULL, NULL, NULL, NULL,
-                                               eb->db, local_abspath,
-                                               scratch_pool, scratch_pool));
-
-            if (working_status == svn_wc__db_status_moved_here)
-              reason = svn_wc_conflict_reason_moved_here;
-            else
-              reason = svn_wc_conflict_reason_added;
-          }
-        else
-          {
-            /* The node is locally replaced. */
-            reason = svn_wc_conflict_reason_replaced;
-          }
-        break;
-
-
-      case svn_wc__db_status_deleted:
-        {
-          const char *moved_to_abspath;
-
-          SVN_ERR(svn_wc__db_scan_deletion(NULL, &moved_to_abspath,
-                                           NULL, NULL, eb->db,
-                                           local_abspath,
-                                           scratch_pool, scratch_pool));
-          if (moved_to_abspath)
-            reason = svn_wc_conflict_reason_moved_away;
-          else
-            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_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;
-
-        /* Replace is handled as delete and then specifically in
-           add_directory() and add_file(), so we only expect deletes here */
-        SVN_ERR_ASSERT(action == svn_wc_conflict_action_delete);
-
-        /* Check if the update wants to delete or replace a locally
-         * modified node. */
-
-
-        /* Do a deep tree detection of local changes. 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. */
-
-        SVN_ERR(node_has_local_mods(&modified, &all_mods_are_deletes, FALSE,
-                                    eb->db, local_abspath,
-                                    eb->cancel_func, eb->cancel_baton,
-                                    scratch_pool));
-
-        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_server_excluded:
-        /* 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;
-
-    }
-
-  if (reason == SVN_WC_CONFLICT_REASON_NONE)
-    /* No conflict with the current action. */
-    return SVN_NO_ERROR;
-
-
-  /* Sanity checks. Note that if there was no action on the node, this function
-   * 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_moved_away
-      || reason == svn_wc_conflict_reason_replaced)
-    /* When the node existed before (it was locally deleted, replaced or
-     * edited), then 'update' cannot add it "again". So it can only send
-     * _action_edit, _delete or _replace. */
-    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 ||
-           reason == svn_wc_conflict_reason_moved_here)
-    /* When the node did not exist before (it was locally added), then 'update'
-     * cannot want to modify it in any way. It can only send _action_add. */
-    SVN_ERR_ASSERT(action == svn_wc_conflict_action_add);
-
-
-  /* A conflict was detected. Create a conflict skel to record it. */
-  *pconflict = svn_wc__conflict_skel_create(result_pool);
-
-  SVN_ERR(svn_wc__conflict_skel_add_tree_conflict(*pconflict,
-                                                  eb->db, local_abspath,
-                                                  reason,
-                                                  action,
-                                                  result_pool, scratch_pool));
-
-  return SVN_NO_ERROR;
-}
-
-
-/* If LOCAL_ABSPATH is inside a conflicted tree, set *CONFLICTED to TRUE,
- * Otherwise set *CONFLICTED to FALSE.  Use SCRATCH_POOL for temporary
- * allocations.
- */
-static svn_error_t *
-already_in_a_tree_conflict(svn_boolean_t *conflicted,
-                           svn_wc__db_t *db,
-                           const char *local_abspath,
-                           apr_pool_t *scratch_pool)
-{
-  const char *ancestor_abspath = local_abspath;
-  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
-
-  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
-
-  *conflicted = FALSE;
-
-  while (TRUE)
-    {
-      svn_boolean_t is_wc_root, tree_conflicted;
-
-      svn_pool_clear(iterpool);
-
-      SVN_ERR(svn_wc__internal_conflicted_p(NULL, NULL, &tree_conflicted,
-                                            db, ancestor_abspath, iterpool));
-
-      if (tree_conflicted)
-        {
-          *conflicted = TRUE;
-          break;
-        }
-
-      SVN_ERR(svn_wc__db_is_wcroot(&is_wc_root, db, ancestor_abspath,
-                                   iterpool));
-
-      if (is_wc_root)
-        break;
-
-      ancestor_abspath = svn_dirent_dirname(ancestor_abspath, scratch_pool);
-    }
-
-  svn_pool_destroy(iterpool);
-
-  return SVN_NO_ERROR;
-}
-
-/* Temporary helper until the new conflict handling is in place */
-static svn_error_t *
-node_already_conflicted(svn_boolean_t *conflicted,
-                        svn_wc__db_t *db,
-                        const char *local_abspath,
-                        apr_pool_t *scratch_pool)
-{
-  svn_boolean_t text_conflicted, prop_conflicted, tree_conflicted;
-
-  SVN_ERR(svn_wc__internal_conflicted_p(&text_conflicted,
-                                        &prop_conflicted,
-                                        &tree_conflicted,
-                                        db, local_abspath,
-                                        scratch_pool));
-
-  *conflicted = (text_conflicted || prop_conflicted || tree_conflicted);
-  return SVN_NO_ERROR;
-}
-
-
-/* An svn_delta_editor_t function. */
-static svn_error_t *
-delete_entry(const char *path,
-             svn_revnum_t revision,
-             void *parent_baton,
-             apr_pool_t *pool)
-{
-  struct dir_baton *pb = parent_baton;
-  struct edit_baton *eb = pb->edit_baton;
-  const char *base = svn_relpath_basename(path, NULL);
-  const char *local_abspath;
-  const char *repos_relpath;
-  svn_kind_t kind, base_kind;
-  svn_revnum_t old_revision;
-  svn_boolean_t conflicted;
-  svn_boolean_t have_work;
-  svn_skel_t *tree_conflict = NULL;
-  svn_wc__db_status_t status;
-  svn_wc__db_status_t base_status;
-  apr_pool_t *scratch_pool;
-  svn_boolean_t deleting_target;
-  svn_boolean_t keep_as_working = FALSE;
-
-  if (pb->skip_this)
-    return SVN_NO_ERROR;
-
-  scratch_pool = svn_pool_create(pb->pool);
-
-  SVN_ERR(mark_directory_edited(pb, scratch_pool));
-
-  SVN_ERR(path_join_under_root(&local_abspath, pb->local_abspath, base,
-                               scratch_pool));
-
-  deleting_target =  (strcmp(local_abspath, eb->target_abspath) == 0);
-
-  /* Detect obstructing working copies */
-  {
-    svn_boolean_t is_root;
-
-    SVN_ERR(svn_wc__db_is_wcroot(&is_root, eb->db, local_abspath,
-                                 scratch_pool));
-
-    if (is_root)
-      {
-        /* Just skip this node; a future update will handle it */
-        SVN_ERR(remember_skipped_tree(eb, local_abspath, pool));
-        do_notification(eb, local_abspath, svn_node_unknown,
-                        svn_wc_notify_update_skip_obstruction, scratch_pool);
-
-        svn_pool_destroy(scratch_pool);
-
-        return SVN_NO_ERROR;
-      }
-  }
-
-  SVN_ERR(svn_wc__db_read_info(&status, &kind, &old_revision, &repos_relpath,
-                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               &conflicted, NULL, NULL, NULL,
-                               NULL, NULL, &have_work,
-                               eb->db, local_abspath,
-                               scratch_pool, scratch_pool));
-
-  if (!have_work)
-    {
-      base_status = status;
-      base_kind = kind;
-    }
-  else
-    SVN_ERR(svn_wc__db_base_get_info(&base_status, &base_kind, &old_revision,
-                                     &repos_relpath,
-                                     NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                                     NULL, NULL, NULL, NULL, NULL,
-                                     eb->db, local_abspath,
-                                     scratch_pool, scratch_pool));
-
-  /* Is this path a conflict victim? */
-  if (conflicted)
-    SVN_ERR(node_already_conflicted(&conflicted, eb->db, local_abspath,
-                                    scratch_pool));
-  if (conflicted)
-    {
-      SVN_ERR(remember_skipped_tree(eb, local_abspath, scratch_pool));
-
-      do_notification(eb, local_abspath, svn_node_unknown,
-                      svn_wc_notify_skip_conflicted,
-                      scratch_pool);
-
-      svn_pool_destroy(scratch_pool);
-
-      return SVN_NO_ERROR;
-    }
-
-
-
-    /* Receive the remote removal of excluded/server-excluded/not present node.
-       Do not notify, but perform the change even when the node is shadowed */
-  if (base_status == svn_wc__db_status_not_present
-      || base_status == svn_wc__db_status_excluded
-      || base_status == svn_wc__db_status_server_excluded)
-    {
-      SVN_ERR(svn_wc__db_base_remove(eb->db, local_abspath,
-                                     FALSE, SVN_INVALID_REVNUM,
-                                     NULL, NULL,
-                                     scratch_pool));
-
-      if (deleting_target)
-        eb->target_deleted = TRUE;
-
-      svn_pool_destroy(scratch_pool);
-
-      return SVN_NO_ERROR;
-    }
-
-  /* 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.  */
-
-  /* Check for conflicts only when we haven't already recorded
-   * a tree-conflict on a parent node. */
-  if (!pb->shadowed)
-    {
-      SVN_ERR(check_tree_conflict(&tree_conflict, eb, local_abspath,
-                                  status, kind, TRUE,
-                                  svn_wc_conflict_action_delete,
-                                  pb->pool, scratch_pool));
-    }
-
-  if (tree_conflict != NULL)
-    {
-      svn_wc_conflict_reason_t reason;
-      /* When we raise a tree conflict on a node, we don't want to mark the
-       * node as skipped, to allow a replacement to continue doing at least
-       * a bit of its work (possibly adding a not present node, for the
-       * next update) */
-      if (!pb->deletion_conflicts)
-        pb->deletion_conflicts = apr_hash_make(pb->pool);
-
-      apr_hash_set(pb->deletion_conflicts, apr_pstrdup(pb->pool, base),
-                   APR_HASH_KEY_STRING, tree_conflict);
-
-      SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL,
-                                                  eb->db, local_abspath,
-                                                  tree_conflict,
-                                                  scratch_pool, scratch_pool));
-
-      if (reason == svn_wc_conflict_reason_edited)
-        {
-          /* The item exists locally and has some sort of local mod.
-           * It no longer exists in the repository at its target URL@REV.
-           *
-           * To prepare the "accept mine" resolution for the tree conflict,
-           * we must schedule the existing content for re-addition as a copy
-           * of what it was, but with its local modifications preserved. */
-          keep_as_working = TRUE;
-
-          /* Fall through to remove the BASE_NODEs properly, with potentially
-             keeping a not-present marker */
-        }
-      else if (reason == svn_wc_conflict_reason_deleted
-               || reason == svn_wc_conflict_reason_moved_away
-               || reason == svn_wc_conflict_reason_replaced)
-        {
-          /* The item does not exist locally because it was already shadowed.
-           * We must complete the deletion, leaving the tree conflict info
-           * as the only difference from a normal deletion. */
-
-          /* Fall through to the normal "delete" code path. */
-        }
-      else
-        SVN_ERR_MALFUNCTION();  /* other reasons are not expected here */
-    }
-
-  SVN_ERR(complete_conflict(tree_conflict, pb, local_abspath, repos_relpath,
-                            old_revision,
-                            (kind == svn_kind_dir)
-                                ? svn_node_dir
-                                : svn_node_file,
-                            pb->pool, scratch_pool));
-
-  /* Issue a wq operation to delete the BASE_NODE data and to delete actual
-     nodes based on that from disk, but leave any WORKING_NODEs on disk.
-
-     Local modifications are already turned into copies at this point.
-
-     If the thing being deleted is the *target* of this update, then
-     we need to recreate a 'deleted' entry, so that the parent can give
-     accurate reports about itself in the future. */
-  if (! deleting_target)
-    {
-      /* Delete, and do not leave a not-present node.  */
-      SVN_ERR(svn_wc__db_base_remove(eb->db, local_abspath,
-                                     keep_as_working, SVN_INVALID_REVNUM,
-                                     tree_conflict, NULL,
-                                     scratch_pool));
-    }
-  else
-    {
-      /* Delete, leaving a not-present node.  */
-      SVN_ERR(svn_wc__db_base_remove(eb->db, local_abspath,
-                                     keep_as_working, *eb->target_revision,
-                                     tree_conflict, NULL,
-                                     scratch_pool));
-      eb->target_deleted = TRUE;
-    }
-
-  SVN_ERR(svn_wc__wq_run(eb->db, pb->local_abspath,
-                         eb->cancel_func, eb->cancel_baton,
-                         scratch_pool));
-
-  /* Notify. */
-  if (tree_conflict)
-    do_notification(eb, local_abspath, svn_node_unknown,
-                    svn_wc_notify_tree_conflict, scratch_pool);
-  else
-    {
-      svn_wc_notify_action_t action = svn_wc_notify_update_delete;
-      svn_node_kind_t node_kind;
-
-      if (pb->shadowed)
-        action = svn_wc_notify_update_shadowed_delete;
-
-      if (kind == svn_kind_dir)
-        node_kind = svn_node_dir;
-      else
-        node_kind = svn_node_file;
-
-      do_notification(eb, local_abspath, node_kind, action, scratch_pool);
-    }
-
-  svn_pool_destroy(scratch_pool);
-
-  return SVN_NO_ERROR;
-}
-
-/* An svn_delta_editor_t function. */
-static svn_error_t *
-add_directory(const char *path,
-              void *parent_baton,
-              const char *copyfrom_path,
-              svn_revnum_t copyfrom_rev,
-              apr_pool_t *pool,
-              void **child_baton)
-{
-  struct dir_baton *pb = parent_baton;
-  struct edit_baton *eb = pb->edit_baton;
-  struct dir_baton *db;
-  svn_node_kind_t kind;
-  svn_wc__db_status_t status;
-  svn_kind_t wc_kind;
-  svn_boolean_t conflicted;
-  svn_boolean_t versioned_locally_and_present;
-  svn_skel_t *tree_conflict = NULL;
-  svn_error_t *err;
-
-  SVN_ERR_ASSERT(! (copyfrom_path || SVN_IS_VALID_REVNUM(copyfrom_rev)));
-
-  SVN_ERR(make_dir_baton(&db, path, eb, pb, TRUE, pool));
-  *child_baton = db;
-
-  if (db->skip_this)
-    return SVN_NO_ERROR;
-
-  SVN_ERR(mark_directory_edited(db, pool));
-
-  if (strcmp(eb->target_abspath, db->local_abspath) == 0)
-    {
-      /* The target of the edit is being added, give it the requested
-         depth of the edit (but convert svn_depth_unknown to
-         svn_depth_infinity). */
-      db->ambient_depth = (eb->requested_depth == svn_depth_unknown)
-        ? svn_depth_infinity : eb->requested_depth;
-    }
-  else if (eb->requested_depth == svn_depth_immediates
-           || (eb->requested_depth == svn_depth_unknown
-               && pb->ambient_depth == svn_depth_immediates))
-    {
-      db->ambient_depth = svn_depth_empty;
-    }
-  else
-    {
-      db->ambient_depth = svn_depth_infinity;
-    }
-
-  /* It may not be named the same as the administrative directory. */
-  if (svn_wc_is_adm_dir(db->name, pool))
-    return svn_error_createf(
-       SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
-       _("Failed to add directory '%s': object of the same name as the "
-         "administrative directory"),
-       svn_dirent_local_style(db->local_abspath, pool));
-
-  SVN_ERR(svn_io_check_path(db->local_abspath, &kind, db->pool));
-
-  err = svn_wc__db_read_info(&status, &wc_kind, NULL, NULL, NULL, NULL, NULL,
-                             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                             NULL, NULL, NULL, NULL, NULL,
-                             &conflicted, NULL, NULL, NULL, NULL, NULL, NULL,
-                             eb->db, db->local_abspath, db->pool, db->pool);
-  if (err)
-    {
-      if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
-        return svn_error_trace(err);
-
-      svn_error_clear(err);
-      wc_kind = svn_kind_unknown;
-      status = svn_wc__db_status_normal;
-      conflicted = FALSE;
-
-      versioned_locally_and_present = FALSE;
-    }
-  else if (wc_kind == svn_kind_dir
-           && status == svn_wc__db_status_normal)
-    {
-      /* !! We found the root of a separate working copy obstructing the wc !!
-
-         If the directory would be part of our own working copy then
-         we wouldn't have been called as an add_directory().
-
-         The only thing we can do is add a not-present node, to allow
-         a future update to bring in the new files when the problem is
-         resolved.  Note that svn_wc__db_base_add_not_present_node()
-         explicitly adds the node into the parent's node database. */
-
-      SVN_ERR(svn_wc__db_base_add_not_present_node(eb->db, db->local_abspath,
-                                                   db->new_relpath,
-                                                   eb->repos_root,
-                                                   eb->repos_uuid,
-                                                   *eb->target_revision,
-                                                   svn_kind_file,
-                                                   NULL, NULL,
-                                                   pool));
-
-      SVN_ERR(remember_skipped_tree(eb, db->local_abspath, pool));
-      db->skip_this = TRUE;
-      db->already_notified = TRUE;
-
-      do_notification(eb, db->local_abspath, svn_node_dir,
-                      svn_wc_notify_update_skip_obstruction, pool);
-
-      return SVN_NO_ERROR;
-    }
-  else if (status == svn_wc__db_status_normal
-           && (wc_kind == svn_kind_file
-               || wc_kind == svn_kind_symlink))
-    {
-      /* We found a file external occupating the place we need in BASE.
-
-         We can't add a not-present node in this case as that would overwrite
-         the file external. Luckily the file external itself stops us from
-         forgetting a child of this parent directory like an obstructing
-         working copy would.
-
-         The reason we get here is that the adm crawler doesn't report
-         file externals.
-      */
-
-      SVN_ERR(remember_skipped_tree(eb, db->local_abspath, pool));
-      db->skip_this = TRUE;
-      db->already_notified = TRUE;
-
-      do_notification(eb, db->local_abspath, svn_node_file,
-                      svn_wc_notify_update_skip_obstruction, pool);
-
-      return SVN_NO_ERROR;
-    }
-  else if (wc_kind == svn_kind_unknown)
-    versioned_locally_and_present = FALSE; /* Tree conflict ACTUAL-only node */
-  else
-    versioned_locally_and_present = IS_NODE_PRESENT(status);
-
-  /* Is this path a conflict victim? */
-  if (conflicted)
-    {
-      if (pb->deletion_conflicts)
-        tree_conflict = apr_hash_get(pb->deletion_conflicts, db->name,
-                                     APR_HASH_KEY_STRING);
-
-      if (tree_conflict)
-        {
-          svn_wc_conflict_reason_t reason;
-          /* So this deletion wasn't just a deletion, it is actually a
-             replacement. Let's install a better tree conflict. */
-
-          /* ### Should store the conflict in DB to allow reinstalling
-             ### with theoretically more data in close_directory() */
-
-          SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL,
-                                                      eb->db,
-                                                      db->local_abspath,
-                                                      tree_conflict,
-                                                      db->pool, db->pool));
-
-          tree_conflict = svn_wc__conflict_skel_create(db->pool);
-
-          SVN_ERR(svn_wc__conflict_skel_add_tree_conflict(
-                                        tree_conflict,
-                                        eb->db, db->local_abspath,
-                                        reason, svn_wc_conflict_action_replace,
-                                        db->pool, db->pool));
-
-          /* And now stop checking for conflicts here and just perform
-             a shadowed update */
-          db->edit_conflict = tree_conflict; /* Cache for close_directory */
-          tree_conflict = NULL; /* No direct notification */
-          db->shadowed = TRUE; /* Just continue */
-          conflicted = FALSE; /* No skip */
-        }
-      else
-        SVN_ERR(node_already_conflicted(&conflicted, eb->db,
-                                        db->local_abspath, pool));
-    }
-
-  /* Now the "usual" behaviour if already conflicted. Skip it. */
-  if (conflicted)
-    {
-      /* Record this conflict so that its descendants are skipped silently. */
-      SVN_ERR(remember_skipped_tree(eb, db->local_abspath, pool));
-
-      db->skip_this = TRUE;
-      db->already_notified = TRUE;
-
-      /* We skip this node, but once the update completes the parent node will
-         be updated to the new revision. So a future recursive update of the
-         parent will not bring in this new node as the revision of the parent
-         describes to the repository that all children are available.
-
-         To resolve this problem, we add a not-present node to allow bringing
-         the node in once this conflict is resolved.
-
-         Note that we can safely assume that no present base node exists,
-         because then we would not have received an add_directory.
-       */
-      SVN_ERR(svn_wc__db_base_add_not_present_node(eb->db, db->local_abspath,
-                                                   db->new_relpath,
-                                                   eb->repos_root,
-                                                   eb->repos_uuid,
-                                                   *eb->target_revision,
-                                                   svn_kind_dir,
-                                                   NULL, NULL,
-                                                   pool));
-
-      /* ### TODO: Also print victim_path in the skip msg. */
-      do_notification(eb, db->local_abspath, svn_node_dir,
-                      svn_wc_notify_skip_conflicted, pool);
-      return SVN_NO_ERROR;
-    }
-
-  if (db->shadowed)
-    {
-      /* Nothing to check; does not and will not exist in working copy */
-    }
-  else if (versioned_locally_and_present)
-    {
-      /* What to do with a versioned or schedule-add dir:
-
-         A dir already added without history is OK.  Set add_existed
-         so that user notification is delayed until after any prop
-         conflicts have been found.
-
-         An existing versioned dir is an error.  In the future we may
-         relax this restriction and simply update such dirs.
-
-         A dir added with history is a tree conflict. */
-
-      svn_boolean_t local_is_non_dir;
-      svn_wc__db_status_t add_status = svn_wc__db_status_normal;
-
-      /* Is the local add a copy? */
-      if (status == svn_wc__db_status_added)
-        SVN_ERR(svn_wc__db_scan_addition(&add_status, NULL, NULL, NULL, NULL,
-                                         NULL, NULL, NULL, NULL, NULL, NULL,
-                                         eb->db, db->local_abspath,
-                                         pool, pool));
-
-
-      /* Is there *something* that is not a dir? */
-      local_is_non_dir = (wc_kind != svn_kind_dir
-                          && status != svn_wc__db_status_deleted);
-
-      /* Do tree conflict checking if
-       *  - if there is a local copy.
-       *  - if this is a switch operation
-       *  - the node kinds mismatch
-       *
-       * During switch, local adds at the same path as incoming adds get
-       * "lost" in that switching back to the original will no longer have the
-       * local add. So switch always alerts the user with a tree conflict. */
-      if (!eb->adds_as_modification
-          || local_is_non_dir
-          || add_status != svn_wc__db_status_added)
-        {
-          SVN_ERR(check_tree_conflict(&tree_conflict, eb,
-                                      db->local_abspath,
-                                      status, wc_kind, FALSE,
-                                      svn_wc_conflict_action_add,
-                                      pool, pool));
-        }
-
-      if (tree_conflict == NULL)
-        db->add_existed = TRUE; /* Take over WORKING */
-      else
-        db->shadowed = TRUE; /* Only update BASE */
-    }
-  else if (kind != svn_node_none)
-    {
-      /* There's an unversioned node at this path. */
-      db->obstruction_found = TRUE;
-
-      /* Unversioned, obstructing dirs are handled by prop merge/conflict,
-       * if unversioned obstructions are allowed. */
-      if (! (kind == svn_node_dir && eb->allow_unver_obstructions))
-        {
-          /* Bring in the node as deleted */ /* ### Obstructed Conflict */
-          db->shadowed = TRUE;
-
-          /* Mark a conflict */
-          tree_conflict = svn_wc__conflict_skel_create(db->pool);
-
-          SVN_ERR(svn_wc__conflict_skel_add_tree_conflict(
-                                        tree_conflict,
-                                        eb->db, db->local_abspath,
-                                        svn_wc_conflict_reason_unversioned,
-                                        svn_wc_conflict_action_add,
-                                        db->pool, pool));
-          db->edit_conflict = tree_conflict;
-        }
-    }
-
-  SVN_ERR(complete_conflict(tree_conflict, pb, db->local_abspath,
-                            db->old_repos_relpath, db->old_revision,
-                            svn_node_dir, db->pool, pool));
-
-  SVN_ERR(svn_wc__db_base_add_incomplete_directory(
-                                     eb->db, db->local_abspath,
-                                     db->new_relpath,
-                                     eb->repos_root,
-                                     eb->repos_uuid,
-                                     *eb->target_revision,
-                                     db->ambient_depth,
-                                     (db->shadowed && db->obstruction_found),
-                                     (! db->shadowed
-                                      && status == svn_wc__db_status_added),
-                                     tree_conflict, NULL,
-                                     pool));
-
-  /* Make sure there is a real directory at LOCAL_ABSPATH, unless we are just
-     updating the DB */
-  if (!db->shadowed)
-    SVN_ERR(svn_wc__ensure_directory(db->local_abspath, pool));
-
-  if (tree_conflict != NULL)
-    {
-      db->already_notified = TRUE;
-      do_notification(eb, db->local_abspath, svn_node_dir,
-                      svn_wc_notify_tree_conflict, pool);
-    }
-
-
-  /* If this add was obstructed by dir scheduled for addition without
-     history let close_file() handle the notification because there
-     might be properties to deal with.  If PATH was added inside a locally
-     deleted tree, then suppress notification, a tree conflict was already
-     issued. */
-  if (eb->notify_func && !db->already_notified && !db->add_existed)
-    {
-      svn_wc_notify_action_t action;
-
-      if (db->shadowed)
-        action = svn_wc_notify_update_shadowed_add;
-      else if (db->obstruction_found)
-        action = svn_wc_notify_exists;
-      else
-        action = svn_wc_notify_update_add;
-
-      db->already_notified = TRUE;
-
-      do_notification(eb, db->local_abspath, svn_node_dir, action, pool);
-    }
-
-  return SVN_NO_ERROR;
-}
-
-/* An svn_delta_editor_t function. */
-static svn_error_t *
-open_directory(const char *path,
-               void *parent_baton,
-               svn_revnum_t base_revision,
-               apr_pool_t *pool,
-               void **child_baton)
-{
-  struct dir_baton *db, *pb = parent_baton;
-  struct edit_baton *eb = pb->edit_baton;
-  svn_boolean_t have_work;
-  svn_boolean_t conflicted;
-  svn_skel_t *tree_conflict = NULL;
-  svn_wc__db_status_t status, base_status;
-  svn_kind_t wc_kind;
-
-  SVN_ERR(make_dir_baton(&db, path, eb, pb, FALSE, pool));
-  *child_baton = db;
-
-  if (db->skip_this)
-    return SVN_NO_ERROR;
-
-  /* Detect obstructing working copies */
-  {
-    svn_boolean_t is_root;
-
-    SVN_ERR(svn_wc__db_is_wcroot(&is_root, eb->db, db->local_abspath,
-                                 pool));
-
-    if (is_root)
-      {
-        /* Just skip this node; a future update will handle it */
-        SVN_ERR(remember_skipped_tree(eb, db->local_abspath, pool));
-        db->skip_this = TRUE;
-        db->already_notified = TRUE;
-
-        do_notification(eb, db->local_abspath, svn_node_dir,
-                        svn_wc_notify_update_skip_obstruction, pool);
-
-        return SVN_NO_ERROR;
-      }
-  }
-
-  /* We should have a write lock on every directory touched.  */
-  SVN_ERR(svn_wc__write_check(eb->db, db->local_abspath, pool));
-
-  SVN_ERR(svn_wc__db_read_info(&status, &wc_kind, &db->old_revision,
-                               &db->old_repos_relpath, NULL, NULL,
-                               &db->changed_rev, &db->changed_date,
-                               &db->changed_author, &db->ambient_depth,
-                               NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, NULL, NULL,
-                               &conflicted, NULL, NULL, NULL,
-                               NULL, NULL, &have_work,
-                               eb->db, db->local_abspath,
-                               db->pool, pool));
-
-  if (!have_work)
-    base_status = status;
-  else
-    SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL, &db->old_revision,
-                                     &db->old_repos_relpath, NULL, NULL,
-                                     &db->changed_rev, &db->changed_date,
-                                     &db->changed_author, &db->ambient_depth,
-                                     NULL, NULL, NULL, NULL, NULL, NULL,
-                                     eb->db, db->local_abspath,
-                                     db->pool, pool));
-
-  db->was_incomplete = (base_status == svn_wc__db_status_incomplete);
-
-  /* Is this path a conflict victim? */
-  if (conflicted)
-    SVN_ERR(node_already_conflicted(&conflicted, eb->db,
-                                    db->local_abspath, pool));
-  if (conflicted)
-    {
-      SVN_ERR(remember_skipped_tree(eb, db->local_abspath, pool));
-
-      db->skip_this = TRUE;
-      db->already_notified = TRUE;
-
-      do_notification(eb, db->local_abspath, svn_node_unknown,
-                      svn_wc_notify_skip_conflicted, pool);
-
-      return SVN_NO_ERROR;
-    }
-
-  /* Is this path a fresh tree conflict victim?  If so, skip the tree
-     with one notification. */
-
-  /* Check for conflicts only when we haven't already recorded
-   * a tree-conflict on a parent node. */
-  if (!db->shadowed)
-    SVN_ERR(check_tree_conflict(&tree_conflict, eb, db->local_abspath,
-                                status, wc_kind, TRUE,
-                                svn_wc_conflict_action_edit,
-                                db->pool, pool));
-
-  /* Remember the roots of any locally deleted trees. */
-  if (tree_conflict != NULL)
-    {
-      svn_wc_conflict_reason_t reason;
-      db->edit_conflict = tree_conflict;
-      /* Other modifications wouldn't be a tree conflict */
-
-      SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL,
-                                                  eb->db, db->local_abspath,
-                                                  tree_conflict,
-                                                  db->pool, db->pool));
-      SVN_ERR_ASSERT(reason == svn_wc_conflict_reason_deleted
-                     || reason == svn_wc_conflict_reason_moved_away
-                     || reason == svn_wc_conflict_reason_replaced);
-
-      /* Continue updating BASE */
-      db->shadowed = TRUE;
-    }
-
-  /* Mark directory as being at target_revision and URL, but incomplete. */
-  SVN_ERR(svn_wc__db_temp_op_start_directory_update(eb->db, db->local_abspath,
-                                                    db->new_relpath,
-                                                    *eb->target_revision,
-                                                    pool));
-
-  return SVN_NO_ERROR;
-}
-
-
-/* An svn_delta_editor_t function. */
-static svn_error_t *
-change_dir_prop(void *dir_baton,
-                const char *name,
-                const svn_string_t *value,
-                apr_pool_t *pool)
-{
-  svn_prop_t *propchange;
-  struct dir_baton *db = dir_baton;
-
-  if (db->skip_this)
-    return SVN_NO_ERROR;
-
-  propchange = apr_array_push(db->propchanges);
-  propchange->name = apr_pstrdup(db->pool, name);
-  propchange->value = value ? svn_string_dup(value, db->pool) : NULL;
-
-  if (!db->edited && svn_property_kind2(name) == svn_prop_regular_kind)
-    SVN_ERR(mark_directory_edited(db, pool));
-
-  return SVN_NO_ERROR;
-}
-
-/* If any of the svn_prop_t objects in PROPCHANGES represents a change
-   to the SVN_PROP_EXTERNALS property, return that change, else return
-   null.  If PROPCHANGES contains more than one such change, return
-   the first. */
-static const svn_prop_t *
-externals_prop_changed(const apr_array_header_t *propchanges)
-{
-  int i;
-
-  for (i = 0; i < propchanges->nelts; i++)
-    {
-      const svn_prop_t *p = &(APR_ARRAY_IDX(propchanges, i, svn_prop_t));
-      if (strcmp(p->name, SVN_PROP_EXTERNALS) == 0)
-        return p;
-    }
-
-  return NULL;
-}
-
-
-
-/* An svn_delta_editor_t function. */
-static svn_error_t *
-close_directory(void *dir_baton,
-                apr_pool_t *pool)
-{
-  struct dir_baton *db = dir_baton;
-  struct edit_baton *eb = db->edit_baton;
-  svn_wc_notify_state_t prop_state = svn_wc_notify_state_unknown;
-  apr_array_header_t *entry_prop_changes;
-  apr_array_header_t *dav_prop_changes;
-  apr_array_header_t *regular_prop_changes;
-  apr_hash_t *base_props;
-  apr_hash_t *actual_props;
-  apr_hash_t *new_base_props = NULL;
-  apr_hash_t *new_actual_props = NULL;
-  svn_revnum_t new_changed_rev = SVN_INVALID_REVNUM;
-  apr_time_t new_changed_date = 0;
-  const char *new_changed_author = NULL;
-  apr_pool_t *scratch_pool = db->pool;
-  svn_skel_t *all_work_items = NULL;
-  svn_skel_t *conflict_skel = NULL;
-
-  /* Skip if we're in a conflicted tree. */
-  if (db->skip_this)
-    {
-      /* Allow the parent to complete its update. */
-      SVN_ERR(maybe_release_dir_info(db->bump_info));
-
-      return SVN_NO_ERROR;
-    }
-
-  if (db->edited)
-    conflict_skel = db->edit_conflict;
-
-  SVN_ERR(svn_categorize_props(db->propchanges, &entry_prop_changes,
-                               &dav_prop_changes, &regular_prop_changes, pool));
-
-  /* Fetch the existing properties.  */
-  if ((!db->adding_dir || db->add_existed)
-      && !db->shadowed)
-    {
-      SVN_ERR(svn_wc__get_actual_props(&actual_props,
-                                       eb->db, db->local_abspath,
-                                       scratch_pool, scratch_pool));
-    }
-  else
-    actual_props = apr_hash_make(pool);
-
-  if (db->add_existed)
-    {
-      /* This node already exists. Grab the current pristine properties. */
-      SVN_ERR(svn_wc__db_read_pristine_props(&base_props,
-                                             eb->db, db->local_abspath,
-                                             scratch_pool, scratch_pool));
-    }
-  else if (!db->adding_dir)
-    {
-      /* Get the BASE properties for proper merging. */
-      SVN_ERR(svn_wc__db_base_get_props(&base_props,
-                                        eb->db, db->local_abspath,
-                                        scratch_pool, scratch_pool));
-    }
-  else
-    base_props = apr_hash_make(pool);
-
-  /* An incomplete directory might have props which were supposed to be
-     deleted but weren't.  Because the server sent us all the props we're
-     supposed to have, any previous base props not in this list must be
-     deleted (issue #1672). */
-  if (db->was_incomplete)
-    {
-      int i;
-      apr_hash_t *props_to_delete;
-      apr_hash_index_t *hi;
-
-      /* In a copy of the BASE props, remove every property that we see an
-         incoming change for. The remaining unmentioned properties are those
-         which need to be deleted.  */
-      props_to_delete = apr_hash_copy(pool, base_props);
-      for (i = 0; i < regular_prop_changes->nelts; i++)
-        {
-          const svn_prop_t *prop;
-          prop = &APR_ARRAY_IDX(regular_prop_changes, i, svn_prop_t);
-          apr_hash_set(props_to_delete, prop->name,
-                       APR_HASH_KEY_STRING, NULL);
-        }
-
-      /* Add these props to the incoming propchanges (in
-       * regular_prop_changes).  */
-      for (hi = apr_hash_first(pool, props_to_delete);
-           hi != NULL;
-           hi = apr_hash_next(hi))
-        {
-          const char *propname = svn__apr_hash_index_key(hi);
-          svn_prop_t *prop = apr_array_push(regular_prop_changes);
-
-          /* Record a deletion for PROPNAME.  */
-          prop->name = propname;
-          prop->value = NULL;
-        }
-    }
-
-  /* If this directory has property changes stored up, now is the time
-     to deal with them. */
-  if (regular_prop_changes->nelts)
-    {
-      /* If recording traversal info, then see if the
-         SVN_PROP_EXTERNALS property on this directory changed,
-         and record before and after for the change. */
-      if (eb->external_func)
-        {
-          const svn_prop_t *change
-            = externals_prop_changed(regular_prop_changes);
-

[... 2736 lines stripped ...]