You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by vm...@apache.org on 2012/12/27 05:03:55 UTC

svn commit: r1426116 [10/16] - in /subversion/branches/javahl-ra: ./ build/ build/ac-macros/ build/generator/ build/win32/ contrib/server-side/svncutter/ notes/ subversion/bindings/cxxhl/ subversion/bindings/swig/ subversion/bindings/swig/perl/native/ ...

Modified: subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db.h?rev=1426116&r1=1426115&r2=1426116&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db.h Thu Dec 27 04:03:49 2012
@@ -74,7 +74,7 @@ extern "C" {
    The pool that DB is allocated within (the "state" pool) is only used
    for a few, limited allocations to track each of the working copy roots
    that the DB is asked to operate upon. The memory usage on this pool
-   os O(# wcroots), which should normally be one or a few. Custom clients
+   is O(# wcroots), which should normally be one or a few. Custom clients
    which hold open structures over a significant period of time should
    pay particular attention to the number of roots touched, and the
    resulting impact on memory consumption (which should still be minimal).
@@ -134,7 +134,8 @@ typedef enum svn_wc__db_status_t {
     svn_wc__db_status_normal,
 
     /* The node has been added (potentially obscuring a delete or move of
-       the BASE node; see HAVE_BASE param). The text will be marked as
+       the BASE node; see HAVE_BASE param [### What param? This is an enum
+       not a function.] ). The text will be marked as
        modified, and if properties exist, they will be marked as modified.
 
        In many cases svn_wc__db_status_added means any of added, moved-here
@@ -212,7 +213,7 @@ typedef struct svn_wc__db_lock_t {
 
 
 /*
-  @defgroup svn_wc__db_admin  General administractive functions
+  @defgroup svn_wc__db_admin  General administrative functions
   @{
 */
 
@@ -511,6 +512,7 @@ svn_wc__db_base_add_file(svn_wc__db_t *d
                          svn_boolean_t delete_working,
                          svn_boolean_t update_actual_props,
                          apr_hash_t *new_actual_props,
+                         apr_array_header_t *new_iprops,
                          svn_boolean_t keep_recorded_info,
                          svn_boolean_t insert_base_deleted,
                          const svn_skel_t *conflict,
@@ -593,6 +595,7 @@ svn_wc__db_base_add_symlink(svn_wc__db_t
                             svn_boolean_t delete_working,
                             svn_boolean_t update_actual_props,
                             apr_hash_t *new_actual_props,
+                            apr_array_header_t *new_iprops,
                             svn_boolean_t keep_recorded_info,
                             svn_boolean_t insert_base_deleted,
                             const svn_skel_t *conflict,
@@ -726,6 +729,7 @@ svn_wc__db_base_remove(svn_wc__db_t *db,
      LOCK               NULL
 
      HAD_PROPS          FALSE
+     PROPS              NULL
 
      UPDATE_ROOT        FALSE
 
@@ -741,6 +745,11 @@ svn_wc__db_base_remove(svn_wc__db_t *db,
    If TARGET is requested, and the node is NOT a symlink, then it will
    be set to NULL.
 
+   *PROPS maps "const char *" names to "const svn_string_t *" values.  If
+   the base node is capable of having properties but has none, set
+   *PROPS to an empty hash.  If its status is such that it cannot have
+   properties, set *PROPS to NULL.
+
    If UPDATE_ROOT is requested, set it to TRUE if the node should only
    be updated when it is the root of an update (e.g. file externals).
 
@@ -762,6 +771,7 @@ svn_wc__db_base_get_info(svn_wc__db_stat
                          const char **target,
                          svn_wc__db_lock_t **lock,
                          svn_boolean_t *had_props,
+                         apr_hash_t **props,
                          svn_boolean_t *update_root,
                          svn_wc__db_t *db,
                          const char *local_abspath,
@@ -797,7 +807,8 @@ svn_wc__db_base_get_children_info(apr_ha
    *PROPS maps "const char *" names to "const svn_string_t *" values.
    If the node has no properties, set *PROPS to an empty hash.
    *PROPS will never be set to NULL.
-   If the node is not present in the BASE tree, return an error.
+   If the node is not present in the BASE tree (with presence 'normal'
+   or 'incomplete'), return an error.
    Allocate *PROPS and its keys and values in RESULT_POOL.
 */
 svn_error_t *
@@ -1147,7 +1158,7 @@ svn_wc__db_external_remove(svn_wc__db_t 
 
    When KIND is requested then the value will be set to the kind of external.
 
-   If DEFININING_ABSPATH is requested, then the value will be set to the
+   If DEFINING_ABSPATH is requested, then the value will be set to the
    absolute path of the directory which originally defined the external.
    (The path with the svn:externals property)
 
@@ -1281,7 +1292,7 @@ svn_wc__db_op_copy(svn_wc__db_t *db,
  * of SRC_ABSPATH (so SRC_ABSPATH must be an op_root) to dst_abspaths
  * parents layer.
  *
- * This operation is recursive. It copies all the descandants at the lower
+ * This operation is recursive. It copies all the descendants at the lower
  * layer and adds base-deleted nodes on dst_abspath layer to mark these nodes
  * properly deleted.
  *
@@ -1406,8 +1417,8 @@ svn_wc__db_op_add_symlink(svn_wc__db_t *
    If PROPS is NULL, set the properties to be the same as the pristine
    properties.
 
-   CONFLICT is used to register a conflict on this node at the same time
-   the properties are changed.
+   If CONFLICT is not NULL, it is used to register a conflict on this
+   node at the same time the properties are changed.
 
    WORK_ITEMS are inserted into the work queue, as additional things that
    need to be completed before the working copy is stable.
@@ -1434,42 +1445,6 @@ svn_wc__db_op_set_props(svn_wc__db_t *db
                         const svn_skel_t *work_items,
                         apr_pool_t *scratch_pool);
 
-/* See props.h  */
-#ifdef SVN__SUPPORT_BASE_MERGE
-/* ### Set the properties of the node LOCAL_ABSPATH in the BASE tree to PROPS.
-   ###
-   ### This function should not exist because properties should be stored
-   ### onto the BASE node at construction time, in a single atomic operation.
-   ###
-   ### PROPS maps "const char *" names to "const svn_string_t *" values.
-   ### To specify no properties, PROPS must be an empty hash, not NULL.
-   ### If the node is not present, SVN_ERR_WC_PATH_NOT_FOUND is returned.
-*/
-svn_error_t *
-svn_wc__db_temp_base_set_props(svn_wc__db_t *db,
-                               const char *local_abspath,
-                               const apr_hash_t *props,
-                               apr_pool_t *scratch_pool);
-
-
-/* ### Set the properties of the node LOCAL_ABSPATH in the WORKING tree
-   ### to PROPS.
-   ###
-   ### This function should not exist because properties should be stored
-   ### onto the WORKING node at construction time, in a single atomic
-   ### operation.
-   ###
-   ### PROPS maps "const char *" names to "const svn_string_t *" values.
-   ### To specify no properties, PROPS must be an empty hash, not NULL.
-   ### If the node is not present, SVN_ERR_WC_PATH_NOT_FOUND is returned.
-*/
-svn_error_t *
-svn_wc__db_temp_working_set_props(svn_wc__db_t *db,
-                                  const char *local_abspath,
-                                  const apr_hash_t *props,
-                                  apr_pool_t *scratch_pool);
-#endif
-
 /* Mark LOCAL_ABSPATH, and all children, for deletion.
  *
  * This function removes the file externals (and if DELETE_DIR_EXTERNALS is
@@ -1720,7 +1695,7 @@ svn_wc__db_revert_list_done(svn_wc__db_t
      LOCK                    NULL
 
      RECORDED_SIZE           SVN_INVALID_FILESIZE
-     RECORDED_MOD_TIME       0
+     RECORDED_TIME       0
 
      CHANGELIST              NULL
      CONFLICTED              FALSE
@@ -1804,7 +1779,7 @@ svn_wc__db_revert_list_done(svn_wc__db_t
    If HAD_PROPS is requested and the node has pristine props, the value will
    be set to TRUE.
 
-   If PROP_MODS is requested and the node has property modification the value
+   If PROPS_MOD is requested and the node has property modification the value
    will be set to TRUE.
 
    ### add information about the need to scan upwards to get a complete
@@ -1815,7 +1790,7 @@ svn_wc__db_revert_list_done(svn_wc__db_t
    ### the TEXT_MOD may become an enumerated value at some point to
    ### indicate different states of knowledge about text modifications.
    ### for example, an "svn edit" command in the future might set a
-   ### flag indicating adminstratively-defined modification. and/or we
+   ### flag indicating administratively-defined modification. and/or we
    ### might have a status indicating that we saw it was modified while
    ### performing a filesystem traversal.
 
@@ -1872,7 +1847,7 @@ svn_wc__db_read_info(svn_wc__db_status_t
 
                      /* Recorded for files present in the working copy */
                      svn_filesize_t *recorded_size,
-                     apr_time_t *recorded_mod_time,
+                     apr_time_t *recorded_time,
 
                      /* From ACTUAL */
                      const char **changelist,
@@ -1908,7 +1883,7 @@ struct svn_wc__db_info_t {
   svn_depth_t depth;
 
   svn_filesize_t recorded_size;
-  apr_time_t recorded_mod_time;
+  apr_time_t recorded_time;
 
   const char *changelist;
   svn_boolean_t conflicted;
@@ -1972,6 +1947,11 @@ struct svn_wc__db_walker_info_t {
    calling svn_wc__db_read_info().
 
    (All other information (like original_*) can be obtained via other apis).
+
+   *PROPS maps "const char *" names to "const svn_string_t *" values.  If
+   the pristine node is capable of having properties but has none, set
+   *PROPS to an empty hash.  If its status is such that it cannot have
+   properties, set *PROPS to NULL.
  */
 svn_error_t *
 svn_wc__db_read_pristine_info(svn_wc__db_status_t *status,
@@ -1983,6 +1963,7 @@ svn_wc__db_read_pristine_info(svn_wc__db
                               const svn_checksum_t **checksum, /* files only */
                               const char **target, /* symlinks only */
                               svn_boolean_t *had_props,
+                              apr_hash_t **props,
                               svn_wc__db_t *db,
                               const char *local_abspath,
                               apr_pool_t *result_pool,
@@ -2010,7 +1991,7 @@ svn_wc__db_read_node_install_info(const 
                                   apr_pool_t *scratch_pool);
 
 /* Return in *NODES a hash mapping name->struct svn_wc__db_walker_info_t for
-   the children of DIR_ABSPATH. "name" is the child's name relatve to
+   the children of DIR_ABSPATH. "name" is the child's name relative to
    DIR_ABSPATH, not an absolute path. */
 svn_error_t *
 svn_wc__db_read_children_walker_info(apr_hash_t **nodes,
@@ -2054,11 +2035,8 @@ svn_wc__db_read_props(apr_hash_t **props
  * a hash table mapping <tt>char *</tt> names onto svn_string_t *
  * values for any properties of child nodes of LOCAL_ABSPATH (up to DEPTH).
  *
- * If BASE_PROPS is FALSE, read the properties from the WORKING layer (highest
- * op_depth).
- *
- * If BASE_PROPS is FALSE and, PRISTINE is TRUE, the local modifications will
- * be suppressed. If PRISTINE is FALSE, local modifications will be visible.
+ * If PRISTINE is FALSE, read the properties from the WORKING layer (highest
+ * op_depth); if PRISTINE is FALSE, local modifications will be visible.
  */
 svn_error_t *
 svn_wc__db_read_props_streamily(svn_wc__db_t *db,
@@ -2091,6 +2069,26 @@ svn_wc__db_read_pristine_props(apr_hash_
                                apr_pool_t *result_pool,
                                apr_pool_t *scratch_pool);
 
+
+/**
+ * Set @a *inherited_props to a depth-first ordered array of
+ * #svn_prop_inherited_item_t * structures representing the properties
+ * inherited by @a local_abspath from the ACTUAL tree above
+ * @a local_abspath (looking through to the WORKING or BASE tree as
+ * required), up to and including the root of the working copy and
+ * any cached inherited properties inherited by the root.
+ *
+ * Allocate @a *inherited_props in @a result_pool.  Use @a scratch_pool
+ * for temporary allocations.
+ */
+svn_error_t *
+svn_wc__db_read_inherited_props(apr_array_header_t **iprops,
+                                svn_wc__db_t *db,
+                                const char *local_abspath,
+                                const char *propname,
+                                apr_pool_t *result_pool,
+                                apr_pool_t *scratch_pool);
+
 /* Read a BASE node's inherited property information.
 
    Set *IPROPS to to a depth-first ordered array of
@@ -2113,9 +2111,11 @@ svn_wc__db_read_cached_iprops(apr_array_
 /* Find BASE nodes with cached inherited properties.
 
    Set *IPROPS_PATHS to a hash mapping const char * absolute working copy
-   paths to the same for each path in the working copy at or below
-   LOCAL_ABSPATH, limited by DEPTH, that has cached inherited properties
-   for the BASE node of the path.  Allocate *IPROP_PATHS in RESULT_POOL.
+   paths to the repos_relpath of the path for each path in the working copy
+   at or below LOCAL_ABSPATH, limited by DEPTH, that has cached inherited
+   properties for the BASE node of the path.
+
+   Allocate *IPROP_PATHS in RESULT_POOL.
    Use SCRATCH_POOL for temporary allocations. */
 svn_error_t *
 svn_wc__db_get_children_with_cached_iprops(apr_hash_t **iprop_paths,
@@ -2146,7 +2146,7 @@ svn_wc__db_prop_retrieve_recursive(apr_h
    Return every path that refers to a child of the working node at
    LOCAL_ABSPATH.  Do not include a path just because it was a child of a
    deleted directory that existed at LOCAL_ABSPATH if that directory is now
-   sheduled to be replaced by the working node at LOCAL_ABSPATH.
+   scheduled to be replaced by the working node at LOCAL_ABSPATH.
 
    Allocate *CHILDREN in RESULT_POOL and do temporary allocations in
    SCRATCH_POOL.
@@ -2277,16 +2277,36 @@ svn_wc__db_node_check_replace(svn_boolea
    ### changelist usage -- we may already assume the list fits in memory.
 */
 
-/* Checks if LOCAL_ABSPATH has a parent directory that knows about its
- * existance. Set *IS_ROOT to FALSE if a parent is found, and to TRUE
- * if there is no such parent.
+/* The DB-private version of svn_wc__is_wcroot(), which see.
  */
 svn_error_t *
-svn_wc__db_is_wcroot(svn_boolean_t *is_root,
+svn_wc__db_is_wcroot(svn_boolean_t *is_wcroot,
                      svn_wc__db_t *db,
                      const char *local_abspath,
                      apr_pool_t *scratch_pool);
 
+/* Check whether a node is a working copy root and/or switched.
+
+   If LOCAL_ABSPATH is the root of a working copy, set *IS_WC_ROOT to TRUE,
+   otherwise to FALSE.
+
+   If LOCAL_ABSPATH is switched against its parent in the same working copy
+   set *IS_SWITCHED to TRUE, otherwise to FALSE.
+
+   If KIND is not null, set *KIND to the node type of LOCAL_ABSPATH.
+
+   Any of the output arguments can be null to specify that the result is not
+   interesting to the caller.
+
+   Use SCRATCH_POOL for temporary allocations.
+ */
+svn_error_t *
+svn_wc__db_is_switched(svn_boolean_t *is_wcroot,
+                       svn_boolean_t *is_switched,
+                       svn_kind_t *kind,
+                       svn_wc__db_t *db,
+                       const char *local_abspath,
+                       apr_pool_t *scratch_pool);
 
 
 /* @} */
@@ -2333,7 +2353,7 @@ svn_wc__db_global_relocate(svn_wc__db_t 
 
    CHANGED_REVISION is the new 'last changed' revision. If the node is
    modified its value is equivalent to NEW_REVISION, but in case of a
-   decendant of a copy/move it can be an older revision.
+   descendant of a copy/move it can be an older revision.
 
    CHANGED_DATE is the (server-side) date of CHANGED_REVISION. It may be 0 if
    the revprop is missing on the revision.
@@ -2456,23 +2476,23 @@ svn_wc__db_op_bump_revisions_post_update
                                          apr_pool_t *scratch_pool);
 
 
-/* Record the TRANSLATED_SIZE and LAST_MOD_TIME for a versioned node.
+/* Record the RECORDED_SIZE and RECORDED_TIME for a versioned node.
 
    This function will record the information within the WORKING node,
    if present, or within the BASE tree. If neither node is present, then
    SVN_ERR_WC_PATH_NOT_FOUND will be returned.
 
-   TRANSLATED_SIZE may be SVN_INVALID_FILESIZE, which will be recorded
+   RECORDED_SIZE may be SVN_INVALID_FILESIZE, which will be recorded
    as such, implying "unknown size".
 
-   LAST_MOD_TIME may be 0, which will be recorded as such, implying
+   RECORDED_TIME may be 0, which will be recorded as such, implying
    "unknown last mod time".
 */
 svn_error_t *
 svn_wc__db_global_record_fileinfo(svn_wc__db_t *db,
                                   const char *local_abspath,
-                                  svn_filesize_t translated_size,
-                                  apr_time_t last_mod_time,
+                                  svn_filesize_t recorded_size,
+                                  apr_time_t recorded_time,
                                   apr_pool_t *scratch_pool);
 
 
@@ -3076,7 +3096,7 @@ svn_wc__db_get_not_present_descendants(c
  * Only nodes with op_depth zero and presence 'normal' or 'incomplete'
  * are considered, so that added, deleted or excluded nodes do not affect
  * the result.  If COMMITTED is TRUE, set *MIN_REVISION and *MAX_REVISION
- * to the lowest and highest comitted (i.e. "last changed") revision numbers,
+ * to the lowest and highest committed (i.e. "last changed") revision numbers,
  * respectively.
  *
  * Indicate in *IS_SPARSE_CHECKOUT whether any of the nodes within
@@ -3111,7 +3131,7 @@ svn_wc__db_revision_status(svn_revnum_t 
  * Only nodes with op_depth zero and presence 'normal' or 'incomplete'
  * are considered, so that added, deleted or excluded nodes do not affect
  * the result.  If COMMITTED is TRUE, set *MIN_REVISION and *MAX_REVISION
- * to the lowest and highest comitted (i.e. "last changed") revision numbers,
+ * to the lowest and highest committed (i.e. "last changed") revision numbers,
  * respectively. Use SCRATCH_POOL for temporary allocations.
  *
  * Either of MIN_REVISION and MAX_REVISION may be passed as NULL if
@@ -3207,8 +3227,8 @@ svn_wc__db_follow_moved_to(apr_array_hea
  * need to run as part of marking the conflict resolved. */
 svn_error_t *
 svn_wc__db_update_moved_away_conflict_victim(svn_skel_t **work_items,
-                                             const char *victim_abspath,
                                              svn_wc__db_t *db,
+                                             const char *victim_abspath,
                                              svn_wc_notify_func2_t notify_func,
                                              void *notify_baton,
                                              svn_cancel_func_t cancel_func,
@@ -3216,6 +3236,13 @@ svn_wc__db_update_moved_away_conflict_vi
                                              apr_pool_t *result_pool,
                                              apr_pool_t *scratch_pool);
 
+/* Recover space from the database file for LOCAL_ABSPATH by running
+ * the "vacuum" command. */
+svn_error_t *
+svn_wc__db_vacuum(svn_wc__db_t *db,
+                  const char *local_abspath,
+                  apr_pool_t *scratch_pool);
+
 /* @} */
 
 

Modified: subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db_private.h?rev=1426116&r1=1426115&r2=1426116&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db_private.h (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db_private.h Thu Dec 27 04:03:49 2012
@@ -96,7 +96,7 @@ typedef struct svn_wc__db_wcroot_t {
      Typically just one or two locks maximum. */
   apr_array_header_t *owned_locks;
 
-  /* Map a working copy diretory to a cached adm_access baton.
+  /* Map a working copy directory to a cached adm_access baton.
      const char *local_abspath -> svn_wc_adm_access_t *adm_access */
   apr_hash_t *access_cache;
 
@@ -254,6 +254,7 @@ svn_wc__db_base_get_info_internal(svn_wc
                                   const char **target,
                                   svn_wc__db_lock_t **lock,
                                   svn_boolean_t *had_props,
+                                  apr_hash_t **props,
                                   svn_boolean_t *update_root,
                                   svn_wc__db_wcroot_t *wcroot,
                                   const char *local_relpath,
@@ -262,7 +263,18 @@ svn_wc__db_base_get_info_internal(svn_wc
 
 /* Similar to svn_wc__db_base_get_info(), but taking WCROOT+LOCAL_RELPATH 
  * instead of DB+LOCAL_ABSPATH, an explicit op-depth of the node to get
- * information about, and outputting REPOS_ID instead of URL+UUID. */
+ * information about, and outputting REPOS_ID instead of URL+UUID, and
+ * without the LOCK or UPDATE_ROOT outputs.
+ *
+ * OR
+ *
+ * Similar to svn_wc__db_base_get_info_internal(), but taking an explicit
+ * op-depth OP_DEPTH of the node to get information about, and without the
+ * LOCK or UPDATE_ROOT outputs.
+ *
+ * ### [JAF] TODO: Harmonize svn_wc__db_base_get_info[_internal] with
+ * svn_wc__db_depth_get_info -- common API, common implementation.
+ */
 svn_error_t *
 svn_wc__db_depth_get_info(svn_wc__db_status_t *status,
                           svn_kind_t *kind,
@@ -276,6 +288,7 @@ svn_wc__db_depth_get_info(svn_wc__db_sta
                           const svn_checksum_t **checksum,
                           const char **target,
                           svn_boolean_t *had_props,
+                          apr_hash_t **props,
                           svn_wc__db_wcroot_t *wcroot,
                           const char *local_relpath,
                           int op_depth,
@@ -291,6 +304,14 @@ svn_wc__db_read_conflict_internal(svn_sk
                                   apr_pool_t *result_pool,
                                   apr_pool_t *scratch_pool);
 
+/* Like svn_wc__db_op_mark_conflict(), but with WCROOT+LOCAL_RELPATH instead of
+   DB+LOCAL_ABSPATH. */
+svn_error_t *
+svn_wc__db_mark_conflict_internal(svn_wc__db_wcroot_t *wcroot,
+                                  const char *local_relpath,
+                                  const svn_skel_t *conflict_skel,
+                                  apr_pool_t *scratch_pool);
+
 
 /* Transaction handling */
 
@@ -312,4 +333,28 @@ svn_wc__db_with_txn(svn_wc__db_wcroot_t 
                     apr_pool_t *scratch_pool);
 
 
+/* Return CHILDREN mapping const char * names to svn_kind_t * for the
+   children of LOCAL_RELPATH at OP_DEPTH. */
+svn_error_t *
+svn_wc__db_get_children_op_depth(apr_hash_t **children,
+                                 svn_wc__db_wcroot_t *wcroot,
+                                 const char *local_relpath,
+                                 int op_depth,
+                                 apr_pool_t *result_pool,
+                                 apr_pool_t *scratch_pool);
+
+
+svn_error_t *
+svn_wc__db_extend_parent_delete(svn_wc__db_wcroot_t *wcroot,
+                                const char *local_relpath,
+                                svn_kind_t kind,
+                                int op_depth,
+                                apr_pool_t *scratch_pool);
+
+svn_error_t *
+svn_wc__db_retract_parent_delete(svn_wc__db_wcroot_t *wcroot,
+                                 const char *local_relpath,
+                                 int op_depth,
+                                 apr_pool_t *scratch_pool);
+
 #endif /* WC_DB_PRIVATE_H */

Modified: subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db_update_move.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db_update_move.c?rev=1426116&r1=1426115&r2=1426116&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db_update_move.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db_update_move.c Thu Dec 27 04:03:49 2012
@@ -38,7 +38,9 @@
 #include "svn_dirent_uri.h"
 #include "svn_editor.h"
 #include "svn_error.h"
+#include "svn_hash.h"
 #include "svn_wc.h"
+#include "svn_props.h"
 #include "svn_pools.h"
 
 #include "private/svn_skel.h"
@@ -46,6 +48,7 @@
 #include "private/svn_wc_private.h"
 
 #include "wc.h"
+#include "props.h"
 #include "wc_db_private.h"
 #include "wc-queries.h"
 #include "conflicts.h"
@@ -53,14 +56,18 @@
 
 /*
  * Receiver code.
+ *
+ * The receiver is an editor that, when driven with a certain change, will
+ * merge the edits into the 'actual' layer of a moved subtree.
  */
 
 struct tc_editor_baton {
-  const char *move_root_src_relpath;
-  const char *move_root_dst_relpath;
+  svn_skel_t **work_items;
   svn_wc__db_t *db;
   svn_wc__db_wcroot_t *wcroot;
-  svn_skel_t **work_items;
+  const char *move_root_src_relpath;
+  const char *move_root_dst_relpath;
+  int src_op_depth;
   svn_wc_conflict_version_t *old_version;
   svn_wc_conflict_version_t *new_version;
   svn_wc_notify_func2_t notify_func;
@@ -76,7 +83,15 @@ tc_editor_add_directory(void *baton,
                         svn_revnum_t replaces_rev,
                         apr_pool_t *scratch_pool)
 {
-  return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, NULL);
+  struct tc_editor_baton *b = baton;
+  int op_depth = relpath_depth(b->move_root_dst_relpath);
+
+  SVN_ERR(svn_wc__db_extend_parent_delete(b->wcroot, relpath, svn_kind_dir,
+                                          op_depth, scratch_pool));
+
+  /* ### TODO check for, and flag, tree conflict */
+
+  return SVN_NO_ERROR;
 }
 
 static svn_error_t *
@@ -88,7 +103,15 @@ tc_editor_add_file(void *baton,
                    svn_revnum_t replaces_rev,
                    apr_pool_t *scratch_pool)
 {
-  return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, NULL);
+  struct tc_editor_baton *b = baton;
+  int op_depth = relpath_depth(b->move_root_dst_relpath);
+
+  SVN_ERR(svn_wc__db_extend_parent_delete(b->wcroot, relpath, svn_kind_file,
+                                          op_depth, scratch_pool));
+
+  /* ### TODO check for, and flag, tree conflict */
+
+  return SVN_NO_ERROR;
 }
 
 static svn_error_t *
@@ -112,72 +135,261 @@ tc_editor_add_absent(void *baton,
   return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, NULL);
 }
 
+/* All the info we need about one version of a working node. */
+typedef struct working_node_version_t
+{
+  svn_wc_conflict_version_t *location_and_kind;
+  apr_hash_t *props;
+  const svn_checksum_t *checksum; /* for files only */
+} working_node_version_t;
+
+static svn_error_t *
+create_conflict_markers(svn_skel_t **work_items,
+                        const char *local_abspath,
+                        svn_wc__db_t *db,
+                        const char *repos_relpath,
+                        svn_skel_t *conflict_skel,
+                        const working_node_version_t *old_version,
+                        const working_node_version_t *new_version,
+                        apr_pool_t *result_pool,
+                        apr_pool_t *scratch_pool)
+{
+  svn_skel_t *work_item;
+  svn_wc_conflict_version_t *original_version;
+
+  original_version = svn_wc_conflict_version_dup(
+                       old_version->location_and_kind, scratch_pool);
+  original_version->path_in_repos = repos_relpath;
+  original_version->node_kind = svn_node_file;
+  SVN_ERR(svn_wc__conflict_skel_set_op_update(conflict_skel,
+                                              original_version,
+                                              scratch_pool,
+                                              scratch_pool));
+  /* According to this func's doc string, it is "Currently only used for
+   * property conflicts as text conflict markers are just in-wc files." */
+  SVN_ERR(svn_wc__conflict_create_markers(&work_item, db,
+                                          local_abspath,
+                                          conflict_skel,
+                                          scratch_pool,
+                                          scratch_pool));
+  *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
+
+  return SVN_NO_ERROR;
+}
+
 static svn_error_t *
-tc_editor_alter_directory(void *baton,
-                          const char *relpath,
-                          svn_revnum_t revision,
-                          const apr_array_header_t *children,
-                          apr_hash_t *props,
-                          apr_pool_t *scratch_pool)
+update_working_props(svn_wc_notify_state_t *prop_state,
+                     svn_skel_t **conflict_skel,
+                     apr_array_header_t **propchanges,
+                     apr_hash_t **actual_props,
+                     svn_wc__db_t *db,
+                     const char *local_abspath,
+                     const struct working_node_version_t *old_version,
+                     const struct working_node_version_t *new_version,
+                     apr_pool_t *result_pool,
+                     apr_pool_t *scratch_pool)
 {
-  return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, NULL);
+  apr_hash_t *new_actual_props;
+
+  /*
+   * Run a 3-way prop merge to update the props, using the pre-update
+   * props as the merge base, the post-update props as the
+   * merge-left version, and the current props of the
+   * moved-here working file as the merge-right version.
+   */
+  SVN_ERR(svn_wc__db_read_props(actual_props,
+                                db, local_abspath,
+                                result_pool, scratch_pool));
+  SVN_ERR(svn_prop_diffs(propchanges, new_version->props, old_version->props,
+                         result_pool));
+  SVN_ERR(svn_wc__merge_props(conflict_skel, prop_state,
+                              NULL, &new_actual_props,
+                              db, local_abspath,
+                              old_version->props, old_version->props,
+                              *actual_props, *propchanges,
+                              result_pool, scratch_pool));
+  /* Install the new actual props. Don't set the conflict_skel yet, because
+     we might need to add a text conflict to it as well. */
+  SVN_ERR(svn_wc__db_op_set_props(db, local_abspath,
+                                  new_actual_props,
+                                  svn_wc__has_magic_property(*propchanges),
+                                  NULL/*conflict_skel*/, NULL/*work_items*/,
+                                  scratch_pool));
+
+  return SVN_NO_ERROR;
 }
 
 
-/* Check whether the node at LOCAL_RELPATH in the working copy at WCROOT
- * is shadowed by some node at a higher op depth than EXPECTED_OP_DEPTH. */
+/* If LOCAL_ABSPATH is shadowed then raise a tree-conflict on the root
+   of the obstruction if such a tree-conflict does not already exist. */
 static svn_error_t *
-check_shadowed_node(svn_boolean_t *is_shadowed,
-                    int expected_op_depth,
+check_tree_conflict(svn_boolean_t *is_conflicted,
+                    struct tc_editor_baton *b,
                     const char *local_relpath,
-                    svn_wc__db_wcroot_t *wcroot)
+                    apr_pool_t *scratch_pool)
 {
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
-
-  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                    STMT_SELECT_WORKING_NODE));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+  int dst_op_depth = relpath_depth(b->move_root_dst_relpath);
+  int op_depth;
+  const char *conflict_root_relpath = local_relpath;
+  svn_skel_t *conflict;
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
+                                    STMT_SELECT_LOWEST_WORKING_NODE));
+  SVN_ERR(svn_sqlite__bindf(stmt, "isd", b->wcroot->wc_id, local_relpath,
+                            dst_op_depth));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
+  if (have_row)
+    op_depth = svn_sqlite__column_int(stmt, 0);
+  SVN_ERR(svn_sqlite__reset(stmt));
 
-  while (have_row)
+  if (!have_row)
     {
-      int op_depth = svn_sqlite__column_int(stmt, 0);
+      *is_conflicted = FALSE;
+      return SVN_NO_ERROR;
+    }
+
+  *is_conflicted = TRUE;
+
+  while (relpath_depth(conflict_root_relpath) > op_depth)
+    conflict_root_relpath = svn_relpath_dirname(conflict_root_relpath,
+                                                scratch_pool);
+
+  SVN_ERR(svn_wc__db_read_conflict_internal(&conflict, b->wcroot,
+                                            conflict_root_relpath,
+                                            scratch_pool, scratch_pool));
+
+  if (conflict)
+    /* ### TODO: check this is the right sort of tree-conflict? */
+    return SVN_NO_ERROR;
+
+  conflict = svn_wc__conflict_skel_create(scratch_pool);
+  SVN_ERR(svn_wc__conflict_skel_add_tree_conflict(
+                     conflict, NULL,
+                     svn_dirent_join(b->wcroot->abspath, conflict_root_relpath,
+                                     scratch_pool),
+                     svn_wc_conflict_reason_moved_away,
+                     svn_wc_conflict_action_edit,
+                     scratch_pool,
+                     scratch_pool));
+
+  SVN_ERR(svn_wc__conflict_skel_set_op_update(conflict, b->old_version,
+                                              scratch_pool, scratch_pool));
+  SVN_ERR(svn_wc__db_mark_conflict_internal(b->wcroot, conflict_root_relpath,
+                                            conflict, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
 
-      if (op_depth > expected_op_depth)
-        {
-          *is_shadowed = TRUE;
-          SVN_ERR(svn_sqlite__reset(stmt));
 
-          return SVN_NO_ERROR;
+static svn_error_t *
+tc_editor_alter_directory(void *baton,
+                          const char *dst_relpath,
+                          svn_revnum_t expected_move_dst_revision,
+                          const apr_array_header_t *children,
+                          apr_hash_t *new_props,
+                          apr_pool_t *scratch_pool)
+{
+  struct tc_editor_baton *b = baton;
+  const char *move_dst_repos_relpath;
+  svn_revnum_t move_dst_revision;
+  svn_kind_t move_dst_kind;
+  working_node_version_t old_version, new_version;
+  svn_wc__db_status_t status;
+  svn_boolean_t is_conflicted;
+
+  SVN_ERR_ASSERT(expected_move_dst_revision == b->old_version->peg_rev);
+
+  SVN_ERR(check_tree_conflict(&is_conflicted, b, dst_relpath, scratch_pool));
+  if (is_conflicted)
+    return SVN_NO_ERROR;
+
+  /* Get kind, revision, and checksum of the moved-here node. */
+  SVN_ERR(svn_wc__db_depth_get_info(&status, &move_dst_kind, &move_dst_revision,
+                                    &move_dst_repos_relpath, NULL, NULL, NULL,
+                                    NULL, NULL, &old_version.checksum, NULL,
+                                    NULL, &old_version.props,
+                                    b->wcroot, dst_relpath,
+                                    relpath_depth(b->move_root_dst_relpath),
+                                    scratch_pool, scratch_pool));
+  SVN_ERR_ASSERT(move_dst_revision == expected_move_dst_revision);
+  SVN_ERR_ASSERT(move_dst_kind == svn_kind_dir);
+
+  old_version.location_and_kind = b->old_version;
+  new_version.location_and_kind = b->new_version;
+
+  new_version.checksum = NULL; /* not a file */
+  new_version.props = new_props ? new_props : old_version.props;
+
+  if (new_props)
+    {
+      const char *dst_abspath = svn_dirent_join(b->wcroot->abspath,
+                                                dst_relpath,
+                                                scratch_pool);
+      svn_wc_notify_state_t prop_state;
+      svn_skel_t *conflict_skel = NULL;
+      apr_hash_t *actual_props;
+      apr_array_header_t *propchanges;
+
+      SVN_ERR(update_working_props(&prop_state, &conflict_skel,
+                                   &propchanges, &actual_props,
+                                   b->db, dst_abspath,
+                                   &old_version, &new_version,
+                                   b->result_pool, scratch_pool));
+
+      if (conflict_skel)
+        {
+          SVN_ERR(create_conflict_markers(b->work_items, dst_abspath,
+                                          b->db, move_dst_repos_relpath,
+                                          conflict_skel,
+                                          &old_version, &new_version,
+                                          b->result_pool, scratch_pool));
+          SVN_ERR(svn_wc__db_mark_conflict_internal(b->wcroot, dst_relpath,
+                                                    conflict_skel,
+                                                    scratch_pool));
         }
 
-      SVN_ERR(svn_sqlite__step(&have_row, stmt));
-    }
+      if (b->notify_func)
+        {
+          svn_wc_notify_t *notify;
 
-  *is_shadowed = FALSE;
-  SVN_ERR(svn_sqlite__reset(stmt));
+          notify = svn_wc_create_notify(dst_abspath,
+                                        svn_wc_notify_update_update,
+                                        scratch_pool);
+          notify->kind = svn_node_dir;
+          notify->content_state = svn_wc_notify_state_inapplicable;
+          notify->prop_state = prop_state;
+          notify->old_revision = b->old_version->peg_rev;
+          notify->revision = b->new_version->peg_rev;
+          b->notify_func(b->notify_baton, notify, scratch_pool);
+        }
+    }
 
   return SVN_NO_ERROR;
 }
 
-/* Update text and prop contents of the working file at DST_RELPATH
- * in the working copy at WCROOT, from OLD_VERSION to NEW_VERSION,
- * based on pristine contents identified by MOVE_SRC_CHECKSUM and
- * MOVE_DST_CHECKSUM. MOVE_DST_REPOS_RELPATH is the repository path 
- * the node at DST_RELPATH would be committed to.
- * Use working copy database DB.
+
+/* Merge the difference between OLD_VERSION and NEW_VERSION into
+ * the working file at LOCAL_RELPATH.
+ *
+ * The term 'old' refers to the pre-update state, which is the state of
+ * (some layer of) LOCAL_RELPATH while this function runs; and 'new'
+ * refers to the post-update state, as found at the (base layer of) the
+ * move source path while this function runs.
+ *
+ * LOCAL_RELPATH is a file in the working copy at WCROOT in DB, and
+ * REPOS_RELPATH is the repository path it would be committed to.
+ *
  * Use NOTIFY_FUNC and NOTIFY_BATON for notifications.
- * Add any required work items to *WORK_ITEMS, allocated in RESULT_POOL.
+ * Set *WORK_ITEMS to any required work items, allocated in RESULT_POOL.
  * Use SCRATCH_POOL for temporary allocations. */
 static svn_error_t *
 update_working_file(svn_skel_t **work_items,
-                    const char *dst_relpath,
-                    const char *move_dst_repos_relpath,
-                    const svn_checksum_t *move_src_checksum,
-                    const svn_checksum_t *move_dst_checksum,
-                    svn_wc_conflict_version_t *old_version,
-                    svn_wc_conflict_version_t *new_version,
+                    const char *local_relpath,
+                    const char *repos_relpath,
+                    const working_node_version_t *old_version,
+                    const working_node_version_t *new_version,
                     svn_wc__db_wcroot_t *wcroot,
                     svn_wc__db_t *db,
                     svn_wc_notify_func2_t notify_func,
@@ -185,15 +397,31 @@ update_working_file(svn_skel_t **work_it
                     apr_pool_t *result_pool,
                     apr_pool_t *scratch_pool)
 {
-  const char *moved_to_abspath = svn_dirent_join(wcroot->abspath,
-                                                 dst_relpath,
-                                                 scratch_pool);
-  const char *pre_update_pristine_abspath;
-  const char *post_update_pristine_abspath;
-  svn_skel_t *conflict_skel;
+  const char *local_abspath = svn_dirent_join(wcroot->abspath,
+                                              local_relpath,
+                                              scratch_pool);
+  const char *old_pristine_abspath;
+  const char *new_pristine_abspath;
+  svn_skel_t *conflict_skel = NULL;
+  apr_hash_t *actual_props;
+  apr_array_header_t *propchanges;
   enum svn_wc_merge_outcome_t merge_outcome;
-  svn_wc_notify_state_t content_state;
-  svn_wc_notify_t *notify;
+  svn_wc_notify_state_t prop_state, content_state;
+
+  SVN_ERR(update_working_props(&prop_state, &conflict_skel, &propchanges,
+                               &actual_props, db, local_abspath,
+                               old_version, new_version,
+                               result_pool, scratch_pool));
+
+  /* If there are any conflicts to be stored, convert them into work items
+   * too. */
+  if (conflict_skel)
+    {
+      SVN_ERR(create_conflict_markers(work_items, local_abspath, db,
+                                      repos_relpath, conflict_skel,
+                                      old_version, new_version,
+                                      result_pool, scratch_pool));
+    }
 
   /*
    * Run a 3-way merge to update the file, using the pre-update
@@ -201,51 +429,44 @@ update_working_file(svn_skel_t **work_it
    * text as the merge-left version, and the current content of the
    * moved-here working file as the merge-right version.
    */
-  SVN_ERR(svn_wc__db_pristine_get_path(&pre_update_pristine_abspath,
+  SVN_ERR(svn_wc__db_pristine_get_path(&old_pristine_abspath,
                                        db, wcroot->abspath,
-                                       move_dst_checksum,
+                                       old_version->checksum,
                                        scratch_pool, scratch_pool));
-  SVN_ERR(svn_wc__db_pristine_get_path(&post_update_pristine_abspath,
+  SVN_ERR(svn_wc__db_pristine_get_path(&new_pristine_abspath,
                                        db, wcroot->abspath,
-                                       move_src_checksum,
+                                       new_version->checksum,
                                        scratch_pool, scratch_pool));
   SVN_ERR(svn_wc__internal_merge(work_items, &conflict_skel,
                                  &merge_outcome, db,
-                                 pre_update_pristine_abspath,
-                                 post_update_pristine_abspath,
-                                 moved_to_abspath,
-                                 moved_to_abspath,
+                                 old_pristine_abspath,
+                                 new_pristine_abspath,
+                                 local_abspath,
+                                 local_abspath,
                                  NULL, NULL, NULL, /* diff labels */
-                                 NULL, /* actual props */
+                                 actual_props,
                                  FALSE, /* dry-run */
                                  NULL, /* diff3-cmd */
                                  NULL, /* merge options */
-                                 NULL, /* prop_diff */
+                                 propchanges,
                                  NULL, NULL, /* cancel_func + baton */
                                  result_pool, scratch_pool));
 
-  if (merge_outcome == svn_wc_merge_conflict)
+  /* If there are any conflicts to be stored, convert them into work items
+   * too. */
+  if (conflict_skel)
     {
-      svn_skel_t *work_item;
-      svn_wc_conflict_version_t *original_version;
+      SVN_ERR(create_conflict_markers(work_items, local_abspath, db,
+                                      repos_relpath, conflict_skel,
+                                      old_version, new_version,
+                                      result_pool, scratch_pool));
+      SVN_ERR(svn_wc__db_mark_conflict_internal(wcroot, local_relpath,
+                                                conflict_skel,
+                                                scratch_pool));
+    }
 
-      if (conflict_skel)
-        {
-          original_version = svn_wc_conflict_version_dup(old_version,
-                                                         scratch_pool);
-          original_version->path_in_repos = move_dst_repos_relpath;
-          original_version->node_kind = svn_node_file;
-          SVN_ERR(svn_wc__conflict_skel_set_op_update(conflict_skel,
-                                                      original_version,
-                                                      scratch_pool,
-                                                      scratch_pool));
-          SVN_ERR(svn_wc__conflict_create_markers(&work_item, db,
-                                                  moved_to_abspath,
-                                                  conflict_skel,
-                                                  scratch_pool,
-                                                  scratch_pool));
-          *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
-        }
+  if (merge_outcome == svn_wc_merge_conflict)
+    {
       content_state = svn_wc_notify_state_conflicted;
     }
   else
@@ -253,7 +474,7 @@ update_working_file(svn_skel_t **work_it
       svn_boolean_t is_locally_modified;
 
       SVN_ERR(svn_wc__internal_file_modified_p(&is_locally_modified,
-                                               db, moved_to_abspath,
+                                               db, local_abspath,
                                                FALSE /* exact_comparison */,
                                                scratch_pool));
       if (is_locally_modified)
@@ -262,70 +483,82 @@ update_working_file(svn_skel_t **work_it
         content_state = svn_wc_notify_state_changed;
     }
 
-  notify = svn_wc_create_notify(moved_to_abspath,
-                                svn_wc_notify_update_update,
-                                scratch_pool);
-  notify->kind = svn_node_file;
-  notify->content_state = content_state;
-  notify->prop_state = svn_wc_notify_state_unknown; /* ### TODO */
-  notify->old_revision = old_version->peg_rev;
-  notify->revision = new_version->peg_rev;
-  notify_func(notify_baton, notify, scratch_pool);
+  if (notify_func)
+    {
+      svn_wc_notify_t *notify;
+
+      notify = svn_wc_create_notify(local_abspath,
+                                    svn_wc_notify_update_update,
+                                    scratch_pool);
+      notify->kind = svn_node_file;
+      notify->content_state = content_state;
+      notify->prop_state = prop_state;
+      notify->old_revision = old_version->location_and_kind->peg_rev;
+      notify->revision = new_version->location_and_kind->peg_rev;
+      notify_func(notify_baton, notify, scratch_pool);
+    }
 
   return SVN_NO_ERROR;
 }
 
 
+/* Edit the file found at the move destination, which is initially at
+ * the old state.  Merge the changes into the "working"/"actual" file.
+ */
 static svn_error_t *
 tc_editor_alter_file(void *baton,
                      const char *dst_relpath,
                      svn_revnum_t expected_move_dst_revision,
-                     apr_hash_t *props,
-                     const svn_checksum_t *move_src_checksum,
-                     svn_stream_t *post_update_contents,
+                     apr_hash_t *new_props,
+                     const svn_checksum_t *new_checksum,
+                     svn_stream_t *new_contents,
                      apr_pool_t *scratch_pool)
 {
   struct tc_editor_baton *b = baton;
-  const svn_checksum_t *move_dst_checksum;
   const char *move_dst_repos_relpath;
   svn_revnum_t move_dst_revision;
   svn_kind_t move_dst_kind;
+  working_node_version_t old_version, new_version;
+  svn_boolean_t is_conflicted;
+
+  SVN_ERR(check_tree_conflict(&is_conflicted, b, dst_relpath, scratch_pool));
+  if (is_conflicted)
+    return SVN_NO_ERROR;
 
   /* Get kind, revision, and checksum of the moved-here node. */
   SVN_ERR(svn_wc__db_depth_get_info(NULL, &move_dst_kind, &move_dst_revision,
                                     &move_dst_repos_relpath, NULL, NULL, NULL,
-                                    NULL, NULL, &move_dst_checksum, NULL,
-                                    NULL, b->wcroot, dst_relpath,
+                                    NULL, NULL, &old_version.checksum, NULL,
+                                    NULL, &old_version.props,
+                                    b->wcroot, dst_relpath,
                                     relpath_depth(b->move_root_dst_relpath),
                                     scratch_pool, scratch_pool));
   SVN_ERR_ASSERT(move_dst_revision == expected_move_dst_revision);
   SVN_ERR_ASSERT(move_dst_kind == svn_kind_file);
 
+  old_version.location_and_kind = b->old_version;
+  new_version.location_and_kind = b->new_version;
+
+  /* If new checksum is null that means no change; similarly props. */
+  new_version.checksum = new_checksum ? new_checksum : old_version.checksum;
+  new_version.props = new_props ? new_props : old_version.props;
+
   /* ### TODO update revision etc. in NODES table */
 
   /* Update file and prop contents if the update has changed them. */
-  if (!svn_checksum_match(move_src_checksum, move_dst_checksum)
+  if (!svn_checksum_match(new_checksum, old_version.checksum)
       /* ### || props have changed */)
     {
-      svn_boolean_t is_shadowed;
+      svn_skel_t *work_item;
 
-      /* If the node is shadowed by a higher layer, we need to flag a 
-       * tree conflict and must not touch the working file. */
-      SVN_ERR(check_shadowed_node(&is_shadowed,
-                                  relpath_depth(b->move_root_dst_relpath),
-                                  dst_relpath, b->wcroot));
-      if (is_shadowed)
-        {
-          /* ### TODO flag tree conflict */
-        }
-      else
-        SVN_ERR(update_working_file(b->work_items, dst_relpath,
-                                    move_dst_repos_relpath,
-                                    move_src_checksum, move_dst_checksum,
-                                    b->old_version, b->new_version,
-                                    b->wcroot, b->db,
-                                    b->notify_func, b->notify_baton,
-                                    b->result_pool, scratch_pool));
+      SVN_ERR(update_working_file(&work_item, dst_relpath,
+                                  move_dst_repos_relpath,
+                                  &old_version, &new_version,
+                                  b->wcroot, b->db,
+                                  b->notify_func, b->notify_baton,
+                                  b->result_pool, scratch_pool));
+      *b->work_items = svn_wc__wq_merge(*b->work_items, work_item,
+                                        b->result_pool);
     }
 
   return SVN_NO_ERROR;
@@ -348,7 +581,23 @@ tc_editor_delete(void *baton,
                  svn_revnum_t revision,
                  apr_pool_t *scratch_pool)
 {
-  return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, NULL);
+  struct tc_editor_baton *b = baton;
+  svn_sqlite__stmt_t *stmt;
+  int op_depth = relpath_depth(b->move_root_dst_relpath);
+
+  /* Deleting the ROWS is valid so long as we update the parent before
+     committing the transaction. */
+  SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
+                                    STMT_DELETE_WORKING_OP_DEPTH));
+  SVN_ERR(svn_sqlite__bindf(stmt, "isd", b->wcroot->wc_id, relpath, op_depth));
+  SVN_ERR(svn_sqlite__step_done(stmt));
+
+  /* Retract any base-delete. */
+  SVN_ERR(svn_wc__db_retract_parent_delete(b->wcroot, relpath, op_depth,
+                                           scratch_pool));
+
+  /* ### TODO check for, and flag, tree conflict */
+  return SVN_NO_ERROR;
 }
 
 static svn_error_t *
@@ -387,18 +636,22 @@ tc_editor_complete(void *baton,
                    apr_pool_t *scratch_pool)
 {
   struct tc_editor_baton *b = baton;
-  svn_wc_notify_t *notify;
 
-  notify = svn_wc_create_notify(svn_dirent_join(b->wcroot->abspath,
-                                                b->move_root_dst_relpath,
-                                                scratch_pool),
-                                svn_wc_notify_update_completed,
-                                scratch_pool);
-  notify->kind = svn_node_none;
-  notify->content_state = svn_wc_notify_state_inapplicable;
-  notify->prop_state = svn_wc_notify_state_inapplicable;
-  notify->revision = b->new_version->peg_rev;
-  b->notify_func(b->notify_baton, notify, scratch_pool);
+  if (b->notify_func)
+    {
+      svn_wc_notify_t *notify;
+
+      notify = svn_wc_create_notify(svn_dirent_join(b->wcroot->abspath,
+                                                    b->move_root_dst_relpath,
+                                                    scratch_pool),
+                                    svn_wc_notify_update_completed,
+                                    scratch_pool);
+      notify->kind = svn_node_none;
+      notify->content_state = svn_wc_notify_state_inapplicable;
+      notify->prop_state = svn_wc_notify_state_inapplicable;
+      notify->revision = b->new_version->peg_rev;
+      b->notify_func(b->notify_baton, notify, scratch_pool);
+    }
 
   return SVN_NO_ERROR;
 }
@@ -410,6 +663,13 @@ tc_editor_abort(void *baton,
   return SVN_NO_ERROR;
 }
 
+/* An editor.
+ *
+ * This editor will merge the edits into the 'actual' tree at
+ * MOVE_ROOT_DST_RELPATH (in struct tc_editor_baton),
+ * perhaps raising conflicts if necessary.
+ *
+ */
 static const svn_editor_cb_many_t editor_ops = {
   tc_editor_add_directory,
   tc_editor_add_file,
@@ -429,6 +689,18 @@ static const svn_editor_cb_many_t editor
 
 /*
  * Driver code.
+ *
+ * The scenario is that a subtree has been locally moved, and then the base
+ * layer on the source side of the move has received an update to a new
+ * state.  The destination subtree has not yet been updated, and still
+ * matches the pre-update state of the source subtree.
+ *
+ * The edit driver drives the receiver with the difference between the
+ * pre-update state (as found now at the move-destination) and the
+ * post-update state (found now at the move-source).
+ *
+ * We currently assume that both the pre-update and post-update states are
+ * single-revision.
  */
 
 /* Set *OPERATION, *LOCAL_CHANGE, *INCOMING_CHANGE, *OLD_VERSION, *NEW_VERSION
@@ -442,8 +714,8 @@ get_tc_info(svn_wc_operation_t *operatio
             svn_wc_conflict_action_t *incoming_change,
             svn_wc_conflict_version_t **old_version,
             svn_wc_conflict_version_t **new_version,
-            const char *src_abspath,
             svn_wc__db_t *db,
+            const char *src_abspath,
             apr_pool_t *result_pool,
             apr_pool_t *scratch_pool)
 {
@@ -488,14 +760,55 @@ get_tc_info(svn_wc_operation_t *operatio
           const char *repos_relpath;
           svn_revnum_t revision;
           svn_node_kind_t node_kind;
+          svn_wc__db_status_t status;
+
+          /* The scan dance: read_info then scan_delete then base_get
+             or scan_addition.  Use the internal/relpath functions
+             here? */
+          SVN_ERR(svn_wc__db_read_info(&status, &kind, &revision,
+                                       &repos_relpath, &repos_root_url,
+                                       &repos_uuid, NULL, NULL, NULL, NULL,
+                                       NULL, NULL, NULL, NULL, NULL, NULL,
+                                       NULL, NULL, NULL, NULL, NULL, NULL,
+                                       NULL, NULL, NULL, NULL, NULL,
+                                       db, src_abspath, result_pool,
+                                       scratch_pool));
+          if (status == svn_wc__db_status_deleted)
+            {
+              const char *base_del_abspath, *work_del_abspath;
+              SVN_ERR(svn_wc__db_scan_deletion(&base_del_abspath, NULL,
+                                               &work_del_abspath,
+                                               NULL, db, src_abspath,
+                                               scratch_pool, scratch_pool));
+              SVN_ERR_ASSERT(base_del_abspath || work_del_abspath);
+              if (base_del_abspath)
+                {
+                  SVN_ERR(svn_wc__db_base_get_info(NULL, &kind, &revision,
+                                                   &repos_relpath,
+                                                   &repos_root_url,
+                                                   &repos_uuid,
+                                                   NULL, NULL, NULL, NULL, NULL,
+                                                   NULL, NULL, NULL, NULL, NULL,
+                                                   db, src_abspath, result_pool,
+                                                   scratch_pool));
+                }
+              else if (work_del_abspath)
+                {
+                  work_del_abspath = svn_dirent_dirname(work_del_abspath,
+                                                        scratch_pool);
+                  SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, &repos_relpath,
+                                                   &repos_root_url, &repos_uuid,
+                                                   NULL, NULL, NULL,
+                                                   &revision, NULL, NULL,
+                                                   db, work_del_abspath,
+                                                   scratch_pool, scratch_pool));
+                  repos_relpath = svn_relpath_join(repos_relpath,
+                                     svn_dirent_skip_ancestor(work_del_abspath,
+                                                              src_abspath),
+                                                   scratch_pool);
+                }
+            }
 
-          /* Construct new_version from BASE info. */
-          SVN_ERR(svn_wc__db_base_get_info(NULL, &kind, &revision,
-                                           &repos_relpath, &repos_root_url,
-                                           &repos_uuid, NULL, NULL, NULL,
-                                           NULL, NULL, NULL, NULL, NULL, NULL,
-                                           db, src_abspath, result_pool,
-                                           scratch_pool));
           node_kind = svn__node_kind_from_kind(kind);
           *new_version = svn_wc_conflict_version_create2(repos_root_url,
                                                          repos_uuid,
@@ -519,6 +832,7 @@ get_tc_info(svn_wc_operation_t *operatio
  */
 static svn_error_t *
 update_moved_away_file(svn_editor_t *tc_editor,
+                       svn_boolean_t add,
                        const char *src_relpath,
                        const char *dst_relpath,
                        const char *move_root_dst_relpath,
@@ -528,26 +842,35 @@ update_moved_away_file(svn_editor_t *tc_
                        apr_pool_t *scratch_pool)
 {
   svn_kind_t kind;
-  svn_stream_t *post_update_contents;
-  const svn_checksum_t *move_src_checksum;
-                    
+  svn_stream_t *new_contents;
+  const svn_checksum_t *new_checksum;
+  apr_hash_t *new_props;
+
   /* Read post-update contents from the updated moved-away file and tell
    * the editor to merge them into the moved-here file. */
   SVN_ERR(svn_wc__db_read_pristine_info(NULL, &kind, NULL, NULL, NULL, NULL,
-                                        &move_src_checksum, NULL, NULL, db,
-                                        svn_dirent_join(wcroot->abspath,
-                                                        src_relpath,
-                                                        scratch_pool),
+                                        &new_checksum, NULL, NULL, &new_props,
+                                        db, svn_dirent_join(wcroot->abspath,
+                                                            src_relpath,
+                                                            scratch_pool),
                                         scratch_pool, scratch_pool));
-  SVN_ERR(svn_wc__db_pristine_read(&post_update_contents, NULL, db,
-                                   wcroot->abspath, move_src_checksum,
+  SVN_ERR(svn_wc__db_pristine_read(&new_contents, NULL, db,
+                                   wcroot->abspath, new_checksum,
                                    scratch_pool, scratch_pool));
-  SVN_ERR(svn_editor_alter_file(tc_editor, dst_relpath,
-                                move_root_dst_revision,
-                                NULL, /* ### TODO props */
-                                move_src_checksum,
-                                post_update_contents));
-  SVN_ERR(svn_stream_close(post_update_contents));
+
+  if (add)
+    /* FIXME: editor API violation: missing svn_editor_alter_directory. */
+    SVN_ERR(svn_editor_add_file(tc_editor, dst_relpath,
+                                new_checksum, new_contents,
+                                apr_hash_make(scratch_pool), /* ### TODO props */
+                                move_root_dst_revision));
+  else
+    SVN_ERR(svn_editor_alter_file(tc_editor, dst_relpath,
+                                  move_root_dst_revision,
+                                  new_props, new_checksum,
+                                  new_contents));
+
+  SVN_ERR(svn_stream_close(new_contents));
 
   return SVN_NO_ERROR;
 }
@@ -556,19 +879,45 @@ update_moved_away_file(svn_editor_t *tc_
  */
 static svn_error_t *
 update_moved_away_dir(svn_editor_t *tc_editor,
+                      svn_boolean_t add,
                       const char *src_relpath,
                       const char *dst_relpath,
+                      int src_op_depth,
                       const char *move_root_dst_relpath,
                       svn_revnum_t move_root_dst_revision,
                       svn_wc__db_t *db,
                       svn_wc__db_wcroot_t *wcroot,
                       apr_pool_t *scratch_pool)
 {
-  /* ### notify */
+  apr_hash_t *children_hash;
+  apr_array_header_t *new_children;
+  apr_hash_t *new_props;
+  const char *src_abspath = svn_dirent_join(wcroot->abspath,
+                                            src_relpath,
+                                            scratch_pool);
 
-  /* ### update prop content if changed */
+  if (add)
+    {
+      /* ### TODO children and props */
+      SVN_ERR(svn_editor_add_directory(tc_editor, dst_relpath,
+                                       apr_array_make(scratch_pool, 0,
+                                                      sizeof (const char *)),
+                                       apr_hash_make(scratch_pool),
+                                       move_root_dst_revision));
+      return SVN_NO_ERROR;
+    }
 
-  /* ### update list of children if changed */
+  SVN_ERR(svn_wc__db_get_children_op_depth(&children_hash, wcroot,
+                                           src_relpath, src_op_depth,
+                                           scratch_pool, scratch_pool));
+  SVN_ERR(svn_hash_keys(&new_children, children_hash, scratch_pool));
+
+  SVN_ERR(svn_wc__db_read_pristine_props(&new_props, db, src_abspath,
+                                         scratch_pool, scratch_pool));
+
+  SVN_ERR(svn_editor_alter_directory(tc_editor, dst_relpath,
+                                     move_root_dst_revision,
+                                     new_children, new_props));
 
   return SVN_NO_ERROR;
 }
@@ -577,85 +926,169 @@ update_moved_away_dir(svn_editor_t *tc_e
  */
 static svn_error_t *
 update_moved_away_subtree(svn_editor_t *tc_editor,
+                          svn_boolean_t add,
                           const char *src_relpath,
                           const char *dst_relpath,
+                          int src_op_depth,
                           const char *move_root_dst_relpath,
                           svn_revnum_t move_root_dst_revision,
                           svn_wc__db_t *db,
                           svn_wc__db_wcroot_t *wcroot,
                           apr_pool_t *scratch_pool)
 {
-  const apr_array_header_t *children;
+  apr_hash_t *src_children, *dst_children;
   apr_pool_t *iterpool;
-  int i;
+  apr_hash_index_t *hi;
 
-  SVN_ERR(update_moved_away_dir(tc_editor, src_relpath, dst_relpath,
-                                move_root_dst_relpath,
+  SVN_ERR(update_moved_away_dir(tc_editor, add, src_relpath, dst_relpath,
+                                src_op_depth, move_root_dst_relpath,
                                 move_root_dst_revision,
                                 db, wcroot, scratch_pool));
 
-  SVN_ERR(svn_wc__db_base_get_children(&children, db,
-                                       svn_dirent_join(wcroot->abspath,
-                                                       src_relpath,
-                                                       scratch_pool),
-                                       scratch_pool, scratch_pool));
+  SVN_ERR(svn_wc__db_get_children_op_depth(&src_children, wcroot,
+                                           src_relpath, src_op_depth,
+                                           scratch_pool, scratch_pool));
+  SVN_ERR(svn_wc__db_get_children_op_depth(&dst_children, wcroot,
+                                           dst_relpath,
+                                           relpath_depth(move_root_dst_relpath),
+                                           scratch_pool, scratch_pool));
   iterpool = svn_pool_create(scratch_pool);
-  for (i = 0; i < children->nelts; i++)
+  for (hi = apr_hash_first(scratch_pool, src_children);
+       hi;
+       hi = apr_hash_next(hi))
+    {
+      const char *src_name = svn__apr_hash_index_key(hi);
+      svn_kind_t *src_kind = svn__apr_hash_index_val(hi);
+      svn_kind_t *dst_kind = apr_hash_get(dst_children, src_name,
+                                          APR_HASH_KEY_STRING);
+      svn_boolean_t is_add = FALSE;
+      const char *child_src_relpath, *child_dst_relpath;
+
+      svn_pool_clear(iterpool);
+
+      child_src_relpath = svn_relpath_join(src_relpath, src_name, iterpool);
+      child_dst_relpath = svn_relpath_join(dst_relpath, src_name, iterpool);
+
+      if (!dst_kind || (*src_kind != *dst_kind))
+        {
+          is_add = TRUE;
+          if (dst_kind)
+            /* FIXME:editor API violation:missing svn_editor_alter_directory. */
+            SVN_ERR(svn_editor_delete(tc_editor, child_dst_relpath,
+                                      move_root_dst_revision));
+        }
+
+      if (*src_kind == svn_kind_file || *src_kind == svn_kind_symlink)
+        {
+          SVN_ERR(update_moved_away_file(tc_editor, is_add,
+                                         child_src_relpath,
+                                         child_dst_relpath,
+                                         move_root_dst_relpath,
+                                         move_root_dst_revision,
+                                         db, wcroot, iterpool));
+        }
+      else if (*src_kind == svn_kind_dir)
+        {
+          SVN_ERR(update_moved_away_subtree(tc_editor, is_add,
+                                            child_src_relpath,
+                                            child_dst_relpath,
+                                            src_op_depth,
+                                            move_root_dst_relpath,
+                                            move_root_dst_revision,
+                                            db, wcroot, iterpool));
+        }
+      else
+        ; /* ### TODO */
+
+      apr_hash_set(dst_children, src_name, APR_HASH_KEY_STRING, NULL);
+    }
+  for (hi = apr_hash_first(scratch_pool, dst_children);
+       hi;
+       hi = apr_hash_next(hi))
     {
-      const char *child_src_relpath;
-      svn_kind_t child_kind;
-      const char *child_dst_op_root_relpath;
+      const char *dst_name = svn__apr_hash_index_key(hi);
       const char *child_dst_relpath;
 
       svn_pool_clear(iterpool);
+      child_dst_relpath = svn_relpath_join(dst_relpath, dst_name, iterpool);
 
-      child_src_relpath = svn_relpath_join(src_relpath,
-                                           APR_ARRAY_IDX(children, i,
-                                                         const char *),
-                                           iterpool);
-
-      /* Is this child part of our move operation? */
-      /* ### need to handle children which were newly added or removed
-       * ### during the update */
-      SVN_ERR(svn_wc__db_scan_deletion_internal(NULL, &child_dst_relpath, NULL,
-                                                &child_dst_op_root_relpath,
-                                                wcroot, child_src_relpath,
-                                                iterpool, iterpool));
-      if (child_dst_op_root_relpath == NULL ||
-          strcmp(child_dst_op_root_relpath, move_root_dst_relpath) != 0)
-        continue;
-
-      SVN_ERR(svn_wc__db_base_get_info_internal(NULL, &child_kind,
-                                                NULL, NULL, NULL, NULL,
-                                                NULL, NULL, NULL, NULL,
-                                                NULL, NULL, NULL, NULL,
-                                                wcroot, child_src_relpath,
-                                                iterpool, iterpool));
-
-      if (child_kind == svn_kind_file || child_kind == svn_kind_symlink)
-        SVN_ERR(update_moved_away_file(tc_editor, child_src_relpath,
-                                       child_dst_relpath,
-                                       move_root_dst_relpath,
-                                       move_root_dst_revision,
-                                       db, wcroot, iterpool));
-      else if (child_kind == svn_kind_dir)
-        SVN_ERR(update_moved_away_subtree(tc_editor, child_src_relpath,
-                                          child_dst_relpath,
-                                          move_root_dst_relpath,
-                                          move_root_dst_revision,
-                                          db, wcroot, iterpool));
+      /* FIXME: editor API violation: missing svn_editor_alter_directory. */
+      SVN_ERR(svn_editor_delete(tc_editor, child_dst_relpath,
+                                move_root_dst_revision));
     }
   svn_pool_destroy(iterpool);
 
   return SVN_NO_ERROR;
 }
 
-/* ### Drive TC_EDITOR so as to ...
+/* Update the single op-depth layer in the move destination subtree
+   rooted at DST_RELPATH to make it match the move source subtree
+   rooted at SRC_RELPATH. */
+static svn_error_t *
+replace_moved_layer(const char *src_relpath,
+                    const char *dst_relpath,
+                    int src_op_depth,
+                    svn_wc__db_t *db,
+                    svn_wc__db_wcroot_t *wcroot,
+                    apr_pool_t *scratch_pool)
+{
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
+  int dst_op_depth = relpath_depth(dst_relpath);
+
+  /* Replace entire subtree at one op-depth. */
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_SELECT_LOCAL_RELPATH_OP_DEPTH));
+  SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id,
+                            src_relpath, src_op_depth));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+  while (have_row)
+    {
+      svn_error_t *err;
+      svn_sqlite__stmt_t *stmt2;
+      const char *src_cp_relpath = svn_sqlite__column_text(stmt, 0, NULL);
+      const char *dst_cp_relpath
+        = svn_relpath_join(dst_relpath,
+                           svn_relpath_skip_ancestor(src_relpath,
+                                                     src_cp_relpath),
+                           scratch_pool);
+
+      err = svn_sqlite__get_statement(&stmt2, wcroot->sdb,
+                                      STMT_COPY_NODE_MOVE);
+      if (!err)
+        err = svn_sqlite__bindf(stmt2, "isdsds", wcroot->wc_id,
+                                src_cp_relpath, src_op_depth,
+                                dst_cp_relpath, dst_op_depth,
+                                svn_relpath_dirname(dst_cp_relpath,
+                                                    scratch_pool));
+      if (!err)
+        err = svn_sqlite__step_done(stmt2);
+      if (err)
+        return svn_error_compose_create(err, svn_sqlite__reset(stmt));
+ 
+      SVN_ERR(svn_sqlite__step(&have_row, stmt));
+    }
+  SVN_ERR(svn_sqlite__reset(stmt));
+
+  return SVN_NO_ERROR;
+}
+
+/* Transfer changes from the move source to the move destination.
+ *
+ * Drive the editor TC_EDITOR with the difference between DST_RELPATH
+ * (at its own op-depth) and SRC_RELPATH (at op-depth zero).
+ *
+ * Then update the single op-depth layer in the move destination subtree
+ * rooted at DST_RELPATH to make it match the move source subtree
+ * rooted at SRC_RELPATH.
+ *
+ * ### And the other params?
  */
 static svn_error_t *
 drive_tree_conflict_editor(svn_editor_t *tc_editor,
                            const char *src_relpath,
                            const char *dst_relpath,
+                           int src_op_depth,
                            svn_wc_operation_t operation,
                            svn_wc_conflict_reason_t local_change,
                            svn_wc_conflict_action_t incoming_change,
@@ -680,40 +1113,36 @@ drive_tree_conflict_editor(svn_editor_t 
                                               src_relpath, scratch_pool),
                               scratch_pool));
 
-  /*
-   * Drive the TC editor to transfer incoming changes from the move source
-   * to the move destination.
-   *
-   * The pre-update tree is within dst at the op-depth of the move's op-root.
-   * The post-update base tree is within src at op-depth zero.
-   *
-   * We walk the move source (i.e. the post-update tree), comparing each node
+  /* We walk the move source (i.e. the post-update tree), comparing each node
    * with the equivalent node at the move destination and applying the update
-   * to nodes at the move destination.
-   */
+   * to nodes at the move destination. */
   if (old_version->node_kind == svn_node_file)
-    SVN_ERR(update_moved_away_file(tc_editor, src_relpath, dst_relpath,
+    SVN_ERR(update_moved_away_file(tc_editor, FALSE, src_relpath, dst_relpath,
                                    dst_relpath, old_version->peg_rev,
                                    db, wcroot, scratch_pool));
   else if (old_version->node_kind == svn_node_dir)
-    SVN_ERR(update_moved_away_subtree(tc_editor, src_relpath, dst_relpath,
+    SVN_ERR(update_moved_away_subtree(tc_editor, FALSE,
+                                      src_relpath, dst_relpath,
+                                      src_op_depth,
                                       dst_relpath, old_version->peg_rev,
                                       db, wcroot, scratch_pool));
 
   SVN_ERR(svn_editor_complete(tc_editor));
 
+  SVN_ERR(replace_moved_layer(src_relpath, dst_relpath, src_op_depth,
+                              db, wcroot, scratch_pool));
+
   return SVN_NO_ERROR;
 }
 
 struct update_moved_away_conflict_victim_baton {
   svn_skel_t **work_items;
-  const char *victim_relpath;
+  svn_wc__db_t *db;
   svn_wc_operation_t operation;
   svn_wc_conflict_reason_t local_change;
   svn_wc_conflict_action_t incoming_change;
   svn_wc_conflict_version_t *old_version;
   svn_wc_conflict_version_t *new_version;
-  svn_wc__db_t *db;
   svn_wc_notify_func2_t notify_func;
   void *notify_baton;
   svn_cancel_func_t cancel_func;
@@ -732,21 +1161,22 @@ update_moved_away_conflict_victim(void *
   struct update_moved_away_conflict_victim_baton *b = baton;
   svn_editor_t *tc_editor;
   struct tc_editor_baton *tc_editor_baton;
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
 
   /* ### assumes wc write lock already held */
 
   /* Construct editor baton. */
   tc_editor_baton = apr_pcalloc(scratch_pool, sizeof(*tc_editor_baton));
-  tc_editor_baton->move_root_src_relpath = b->victim_relpath;
+  tc_editor_baton->move_root_src_relpath = victim_relpath;
   SVN_ERR(svn_wc__db_scan_deletion_internal(
             NULL, &tc_editor_baton->move_root_dst_relpath, NULL, NULL,
-            wcroot, b->victim_relpath, scratch_pool, scratch_pool));
+            wcroot, victim_relpath, scratch_pool, scratch_pool));
   if (tc_editor_baton->move_root_dst_relpath == NULL)
     return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
                              _("The node '%s' has not been moved away"),
                              svn_dirent_local_style(
-                               svn_dirent_join(wcroot->abspath,
-                                               b->victim_relpath,
+                               svn_dirent_join(wcroot->abspath, victim_relpath,
                                                scratch_pool),
                                scratch_pool));
   tc_editor_baton->old_version= b->old_version;
@@ -758,6 +1188,23 @@ update_moved_away_conflict_victim(void *
   tc_editor_baton->notify_baton = b->notify_baton;
   tc_editor_baton->result_pool = b->result_pool;
 
+  /* ### TODO get from svn_wc__db_scan_deletion_internal? */
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_SELECT_NODE_INFO));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, victim_relpath));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+  if (have_row)
+    SVN_ERR(svn_sqlite__step(&have_row, stmt));
+  if (have_row)
+    tc_editor_baton->src_op_depth = svn_sqlite__column_int(stmt, 0);
+  SVN_ERR(svn_sqlite__reset(stmt));
+  if (!have_row)
+    return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
+                             _("'%s' is not deleted"),
+                             svn_dirent_local_style(
+                               svn_dirent_join(wcroot->abspath, victim_relpath,
+                                               scratch_pool),
+                               scratch_pool));
   /* Create the editor... */
   SVN_ERR(svn_editor_create(&tc_editor, tc_editor_baton,
                             b->cancel_func, b->cancel_baton,
@@ -768,6 +1215,7 @@ update_moved_away_conflict_victim(void *
   SVN_ERR(drive_tree_conflict_editor(tc_editor,
                                      tc_editor_baton->move_root_src_relpath,
                                      tc_editor_baton->move_root_dst_relpath,
+                                     tc_editor_baton->src_op_depth,
                                      b->operation,
                                      b->local_change, b->incoming_change,
                                      tc_editor_baton->old_version,
@@ -782,8 +1230,8 @@ update_moved_away_conflict_victim(void *
 
 svn_error_t *
 svn_wc__db_update_moved_away_conflict_victim(svn_skel_t **work_items,
-                                             const char *victim_abspath,
                                              svn_wc__db_t *db,
+                                             const char *victim_abspath,
                                              svn_wc_notify_func2_t notify_func,
                                              void *notify_baton,
                                              svn_cancel_func_t cancel_func,
@@ -794,15 +1242,11 @@ svn_wc__db_update_moved_away_conflict_vi
   struct update_moved_away_conflict_victim_baton b;
   svn_wc__db_wcroot_t *wcroot;
   const char *local_relpath;
-  svn_wc_operation_t operation;
-  svn_wc_conflict_reason_t local_change;
-  svn_wc_conflict_action_t incoming_change;
-  svn_wc_conflict_version_t *old_version;
-  svn_wc_conflict_version_t *new_version;
 
-  SVN_ERR(get_tc_info(&operation, &local_change, &incoming_change,
-                      &old_version, &new_version,
-                      victim_abspath, db, scratch_pool, scratch_pool));
+  SVN_ERR(get_tc_info(&b.operation, &b.local_change, &b.incoming_change,
+                      &b.old_version, &b.new_version,
+                      db, victim_abspath,
+                      scratch_pool, scratch_pool));
 
   SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath,
                                                 db, victim_abspath,
@@ -810,12 +1254,6 @@ svn_wc__db_update_moved_away_conflict_vi
   VERIFY_USABLE_WCROOT(wcroot);
 
   b.work_items = work_items;
-  b.victim_relpath = local_relpath;
-  b.operation = operation;
-  b.local_change = local_change;
-  b.incoming_change = incoming_change;
-  b.old_version = old_version;
-  b.new_version = new_version;
   b.db = db;
   b.notify_func = notify_func;
   b.notify_baton = notify_baton;

Modified: subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db_util.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db_util.c?rev=1426116&r1=1426115&r2=1426116&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db_util.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_wc/wc_db_util.c Thu Dec 27 04:03:49 2012
@@ -153,8 +153,8 @@ svn_wc__db_util_open_db(svn_sqlite__db_t
 
 /* Some helpful transaction helpers.
 
-   Instead of directly using SQLite transactions, these wrappers take care of
-   simple cases by allowing consumers to worry about wrapping the wcroot and
+   Instead of directly using SQLite transactions, these wrappers
+   relieve the consumer from the need to wrap the wcroot and
    local_relpath, which are almost always used within the transaction.
 
    This also means if we later want to implement some wc_db-specific txn

Modified: subversion/branches/javahl-ra/subversion/libsvn_wc/workqueue.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_wc/workqueue.c?rev=1426116&r1=1426115&r2=1426116&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_wc/workqueue.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_wc/workqueue.c Thu Dec 27 04:03:49 2012
@@ -148,7 +148,7 @@ run_base_remove(svn_wc__db_t *db,
                                            &not_present_rev, NULL,
                                            NULL, NULL, NULL,
                                            NULL, NULL, NULL, NULL, NULL, NULL,
-                                           NULL, NULL,
+                                           NULL, NULL, NULL,
                                            db, local_abspath,
                                            scratch_pool, scratch_pool));
         }

Modified: subversion/branches/javahl-ra/subversion/libsvn_wc/workqueue.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_wc/workqueue.h?rev=1426116&r1=1426115&r2=1426116&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_wc/workqueue.h (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_wc/workqueue.h Thu Dec 27 04:03:49 2012
@@ -93,8 +93,8 @@ svn_wc__wq_run(svn_wc__db_t *db,
 /* Set *WORK_ITEM to a new work item that will install the working
    copy file at LOCAL_ABSPATH. If USE_COMMIT_TIMES is TRUE, then the newly
    installed file will use the nodes CHANGE_DATE for the file timestamp.
-   If RECORD_FILEINFO is TRUE, then the resulting LAST_MOD_TIME and
-   TRANSLATED_SIZE will be recorded in the database.
+   If RECORD_FILEINFO is TRUE, then the resulting RECORDED_TIME and
+   RECORDED_SIZE will be recorded in the database.
 
    If SOURCE_ABSPATH is NULL, then the pristine contents will be installed
    (with appropriate translation). If SOURCE_ABSPATH is not NULL, then it

Modified: subversion/branches/javahl-ra/subversion/mod_dav_svn/dav_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/mod_dav_svn/dav_svn.h?rev=1426116&r1=1426115&r2=1426116&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/mod_dav_svn/dav_svn.h (original)
+++ subversion/branches/javahl-ra/subversion/mod_dav_svn/dav_svn.h Thu Dec 27 04:03:49 2012
@@ -52,6 +52,12 @@ extern "C" {
 /* a pool-key for the shared dav_svn_root used by autoversioning  */
 #define DAV_SVN__AUTOVERSIONING_ACTIVITY "svn-autoversioning-activity"
 
+/* Option values for SVNAllowBulkUpdates */
+typedef enum dav_svn__bulk_upd_conf {
+    CONF_BULKUPD_ON,
+    CONF_BULKUPD_OFF,
+    CONF_BULKUPD_PREFER
+} dav_svn__bulk_upd_conf;
 
 /* dav_svn_repos
  *
@@ -110,7 +116,7 @@ typedef struct dav_svn_repos {
   svn_boolean_t autoversioning;
 
   /* Whether bulk updates are allowed for this repository. */
-  svn_boolean_t bulk_updates;
+  dav_svn__bulk_upd_conf bulk_updates;
 
   /* Whether HTTP protocol version 2 is allowed to be used. */
   svn_boolean_t v2_protocol;
@@ -302,7 +308,7 @@ const char *dav_svn__get_fs_parent_path(
 svn_boolean_t dav_svn__get_autoversioning_flag(request_rec *r);
 
 /* for the repository referred to by this request, are bulk updates allowed? */
-svn_boolean_t dav_svn__get_bulk_updates_flag(request_rec *r);
+dav_svn__bulk_upd_conf dav_svn__get_bulk_updates_flag(request_rec *r);
 
 /* for the repository referred to by this request, are subrequests active? */
 svn_boolean_t dav_svn__get_pathauthz_flag(request_rec *r);

Modified: subversion/branches/javahl-ra/subversion/mod_dav_svn/mirror.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/mod_dav_svn/mirror.c?rev=1426116&r1=1426115&r2=1426116&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/mod_dav_svn/mirror.c (original)
+++ subversion/branches/javahl-ra/subversion/mod_dav_svn/mirror.c Thu Dec 27 04:03:49 2012
@@ -39,12 +39,17 @@
    URI_SEGMENT is the URI bits relative to the repository root (but if
    non-empty, *does* have a leading slash delimiter).
    MASTER_URI and URI_SEGMENT are not URI-encoded. */
-static void proxy_request_fixup(request_rec *r,
-                                const char *master_uri,
-                                const char *uri_segment)
+static int proxy_request_fixup(request_rec *r,
+                               const char *master_uri,
+                               const char *uri_segment)
 {
-    assert((uri_segment[0] == '\0')
-           || (uri_segment[0] == '/'));
+    if (uri_segment[0] != '\0' && uri_segment[0] != '/')
+      {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, SVN_ERR_BAD_CONFIG_VALUE, r,
+                     "Invalid URI segment '%s' in slave fixup",
+                      uri_segment);
+        return HTTP_INTERNAL_SERVER_ERROR;
+      }
 
     r->proxyreq = PROXYREQ_REVERSE;
     r->uri = r->unparsed_uri;
@@ -67,6 +72,7 @@ static void proxy_request_fixup(request_
     ap_add_output_filter("LocationRewrite", NULL, r, r->connection);
     ap_add_output_filter("ReposRewrite", NULL, r, r->connection);
     ap_add_input_filter("IncomingRewrite", NULL, r, r->connection);
+    return OK;
 }
 
 
@@ -101,8 +107,10 @@ int dav_svn__proxy_request_fixup(request
                                                     "/txn/", (char *)NULL))
                     || ap_strstr_c(seg, apr_pstrcat(r->pool, special_uri,
                                                     "/txr/", (char *)NULL))) {
+                    int rv;
                     seg += strlen(root_dir);
-                    proxy_request_fixup(r, master_uri, seg);
+                    rv = proxy_request_fixup(r, master_uri, seg);
+                    if (rv) return rv;
                 }
             }
             return OK;
@@ -116,8 +124,10 @@ int dav_svn__proxy_request_fixup(request
                     r->method_number == M_LOCK ||
                     r->method_number == M_UNLOCK ||
                     ap_strstr_c(seg, special_uri))) {
+            int rv;
             seg += strlen(root_dir);
-            proxy_request_fixup(r, master_uri, seg);
+            rv = proxy_request_fixup(r, master_uri, seg);
+            if (rv) return rv;
             return OK;
         }
     }