You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by pb...@apache.org on 2012/07/12 22:24:57 UTC

svn commit: r1360909 [8/14] - in /subversion/branches/inheritable-props: ./ build/generator/ build/generator/templates/ notes/wc-ng/ subversion/bindings/javahl/native/ subversion/bindings/javahl/tests/org/apache/subversion/javahl/ subversion/bindings/j...

Modified: subversion/branches/inheritable-props/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_wc/update_editor.c?rev=1360909&r1=1360908&r2=1360909&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_wc/update_editor.c Thu Jul 12 20:24:53 2012
@@ -46,6 +46,7 @@
 
 #include "wc.h"
 #include "adm_files.h"
+#include "conflicts.h"
 #include "entries.h"
 #include "translate.h"
 #include "workqueue.h"
@@ -298,6 +299,9 @@ struct dir_baton
   /* 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;
 
@@ -325,7 +329,7 @@ struct dir_baton
   const char *changed_author;
 
   /* If not NULL, contains a mapping of const char* basenames of children that
-     have been deleted to their svn_wc_conflict_description2_t* tree conflicts.
+     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.
 
@@ -355,7 +359,7 @@ struct dir_baton
   svn_boolean_t edited;
 
   /* The tree conflict to install once the node is really edited */
-  svn_wc_conflict_description2_t *edit_conflict;
+  svn_skel_t *edit_conflict;
 
   /* The bump information for this directory. */
   struct bump_dir_info *bump_info;
@@ -720,6 +724,9 @@ struct file_baton
   /* 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;
 
@@ -774,7 +781,7 @@ struct file_baton
   svn_boolean_t edited;
 
   /* The tree conflict to install once the node is really edited */
-  svn_wc_conflict_description2_t *edit_conflict;
+  svn_skel_t *edit_conflict;
 };
 
 
@@ -866,10 +873,10 @@ mark_directory_edited(struct dir_baton *
   if (db->edit_conflict)
     {
       /* We have a (delayed) tree conflict to install */
-      SVN_ERR(svn_wc__db_op_set_tree_conflict(db->edit_baton->db,
-                                              db->local_abspath,
-                                              db->edit_conflict,
-                                              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);
@@ -894,10 +901,10 @@ mark_file_edited(struct file_baton *fb, 
   if (fb->edit_conflict)
     {
       /* We have a (delayed) tree conflict to install */
-      SVN_ERR(svn_wc__db_op_set_tree_conflict(fb->edit_baton->db,
-                                              fb->local_abspath,
-                                              fb->edit_conflict,
-                                              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);
@@ -1131,7 +1138,8 @@ open_root(void *edit_baton,
       /* 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, NULL, NULL, NULL, NULL,
+      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,
@@ -1285,36 +1293,28 @@ node_has_local_mods(svn_boolean_t *modif
  *
  * The REASON is stored directly in the tree conflict info.
  *
- * All temporary allocactions are be made in SCRATCH_POOL, while allocations
+ * All temporary allocations are be made in SCRATCH_POOL, while allocations
  * needed for the returned conflict struct are made in RESULT_POOL.
  *
  * All other parameters are identical to and described by
  * check_tree_conflict(), with the slight modification that this function
  * relies on the reason passed in REASON instead of actively looking for one. */
 static svn_error_t *
-create_tree_conflict(svn_wc_conflict_description2_t **pconflict,
+create_tree_conflict(svn_skel_t **pconflict,
                      struct edit_baton *eb,
                      const char *local_abspath,
                      svn_wc_conflict_reason_t reason,
                      svn_wc_conflict_action_t action,
-                     svn_node_kind_t their_node_kind,
-                     const char *their_relpath,
                      apr_pool_t *result_pool, apr_pool_t *scratch_pool)
 {
-  const char *repos_root_url = NULL;
   const char *left_repos_relpath;
   svn_revnum_t left_revision;
   svn_node_kind_t left_kind;
-  const char *right_repos_relpath;
-  const char *added_repos_relpath = NULL;
-  svn_node_kind_t conflict_node_kind;
   svn_wc_conflict_version_t *src_left_version;
-  svn_wc_conflict_version_t *src_right_version;
 
   *pconflict = NULL;
 
   SVN_ERR_ASSERT(reason != SVN_WC_CONFLICT_REASON_NONE);
-  SVN_ERR_ASSERT(their_relpath != NULL);
 
   /* Get the source-left information, i.e. the local state of the node
    * before any changes were made to the working copy, i.e. the state the
@@ -1322,8 +1322,6 @@ create_tree_conflict(svn_wc_conflict_des
   if (reason == svn_wc_conflict_reason_added ||
       reason == svn_wc_conflict_reason_moved_here)
     {
-      svn_wc__db_status_t added_status;
-
       /* ###TODO: It would be nice to tell the user at which URL and
        * ### revision source-left was empty, which could be quite difficult
        * ### to code, and is a slight theoretical leap of the svn mind.
@@ -1341,21 +1339,6 @@ create_tree_conflict(svn_wc_conflict_des
       left_kind = svn_node_none;
       left_revision = SVN_INVALID_REVNUM;
       left_repos_relpath = NULL;
-
-      /* Still get the repository root needed by both 'update' and 'switch',
-       * and the would-be repos_relpath needed to construct the source-right
-       * in case of an 'update'. Check sanity while we're at it. */
-      SVN_ERR(svn_wc__db_scan_addition(&added_status, NULL,
-                                       &added_repos_relpath,
-                                       &repos_root_url,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       NULL, eb->db, local_abspath,
-                                       result_pool, scratch_pool));
-
-      /* This better really be an added status. */
-      SVN_ERR_ASSERT(added_status == svn_wc__db_status_added
-                     || added_status == svn_wc__db_status_copied
-                     || added_status == svn_wc__db_status_moved_here);
     }
   else if (reason == svn_wc_conflict_reason_unversioned)
     {
@@ -1364,7 +1347,6 @@ create_tree_conflict(svn_wc_conflict_des
       left_kind = svn_node_none;
       left_revision = SVN_INVALID_REVNUM;
       left_repos_relpath = NULL;
-      repos_root_url = eb->repos_root;
     }
   else
     {
@@ -1383,13 +1365,11 @@ create_tree_conflict(svn_wc_conflict_des
       SVN_ERR(svn_wc__db_base_get_info(NULL, &base_kind,
                                        &left_revision,
                                        &left_repos_relpath,
-                                       &repos_root_url,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
+                                       NULL, NULL,
+                                       NULL, NULL, NULL, NULL, NULL,
                                        NULL, NULL, NULL, NULL,
-                                       eb->db,
-                                       local_abspath,
-                                       result_pool,
-                                       scratch_pool));
+                                       eb->db, local_abspath,
+                                       result_pool, scratch_pool));
       /* Translate the node kind. */
       if (base_kind == svn_kind_file
           || base_kind == svn_kind_symlink)
@@ -1400,40 +1380,6 @@ create_tree_conflict(svn_wc_conflict_des
         SVN_ERR_MALFUNCTION();
     }
 
-  SVN_ERR_ASSERT(strcmp(repos_root_url, eb->repos_root) == 0);
-
-  /* Find the source-right information, i.e. the state in the repository
-   * to which we would like to update. */
-  if (eb->switch_relpath)
-    {
-      /* This is a 'switch' operation. */
-      right_repos_relpath = their_relpath;
-    }
-  else
-    {
-      /* This is an 'update', so REPOS_RELPATH would be the same as for
-       * source-left. However, we don't have a source-left for locally
-       * added files. */
-      right_repos_relpath = ((reason == svn_wc_conflict_reason_added ||
-                              reason == svn_wc_conflict_reason_moved_here) ?
-                             added_repos_relpath : left_repos_relpath);
-      if (! right_repos_relpath)
-        right_repos_relpath = their_relpath;
-    }
-
-  SVN_ERR_ASSERT(right_repos_relpath != NULL);
-
-  /* Determine PCONFLICT's overall node kind, which is not allowed to be
-   * svn_node_none. We give it the source-right revision (THEIR_NODE_KIND)
-   * -- unless source-right is deleted and hence == svn_node_none, in which
-   * case we take it from source-left, which has to be the node kind that
-   * was deleted. */
-  conflict_node_kind = (action == svn_wc_conflict_action_delete ?
-                        left_kind : their_node_kind);
-  SVN_ERR_ASSERT(conflict_node_kind == svn_node_file
-                 || conflict_node_kind == svn_node_dir);
-
-
   /* Construct the tree conflict info structs. */
 
   if (left_repos_relpath == NULL)
@@ -1441,25 +1387,29 @@ create_tree_conflict(svn_wc_conflict_des
      * Send an 'empty' left revision. */
     src_left_version = NULL;
   else
-    src_left_version = svn_wc_conflict_version_create(repos_root_url,
-                                                      left_repos_relpath,
-                                                      left_revision,
-                                                      left_kind,
-                                                      result_pool);
-
-  src_right_version = svn_wc_conflict_version_create(repos_root_url,
-                                                     right_repos_relpath,
-                                                     *eb->target_revision,
-                                                     their_node_kind,
-                                                     result_pool);
-
-  *pconflict = svn_wc_conflict_description_create_tree2(
-                   local_abspath, conflict_node_kind,
-                   eb->switch_relpath ?
-                     svn_wc_operation_switch : svn_wc_operation_update,
-                   src_left_version, src_right_version, result_pool);
-  (*pconflict)->action = action;
-  (*pconflict)->reason = reason;
+    src_left_version = svn_wc_conflict_version_create2(eb->repos_root,
+                                                       eb->repos_uuid,
+                                                       left_repos_relpath,
+                                                       left_revision,
+                                                       left_kind,
+                                                       result_pool);
+
+  *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));
+
+  if (eb->switch_relpath)
+    SVN_ERR(svn_wc__conflict_skel_set_op_switch(*pconflict,
+                                                src_left_version,
+                                                result_pool, scratch_pool));
+  else
+    SVN_ERR(svn_wc__conflict_skel_set_op_update(*pconflict,
+                                                src_left_version,
+                                                result_pool, scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -1480,28 +1430,17 @@ create_tree_conflict(svn_wc_conflict_des
  * tree conflict info is returned in *PCONFLICT. PCONFLICT must be non-NULL,
  * while *PCONFLICT is always overwritten.
  *
- * THEIR_NODE_KIND should be the node kind reflected by the incoming edit
- * function. E.g. dir_opened() should pass svn_node_dir, etc.
- * In some cases of delete, svn_node_none may be used here.
- *
- * THEIR_RELPATH should be the involved node's repository-relative path on the
- * source-right side, the side that the target should become after the update.
- * Simply put, that's the URL obtained from the node's dir_baton->new_relpath
- * or file_baton->new_relpath (but it's more complex for a delete).
- *
  * The tree conflict is allocated in RESULT_POOL. Temporary allocations use
  * SCRACTH_POOl.
  */
 static svn_error_t *
-check_tree_conflict(svn_wc_conflict_description2_t **pconflict,
+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,
-                    svn_node_kind_t their_node_kind,
-                    const char *their_relpath,
                     const char *moved_to_abspath,
                     apr_pool_t *result_pool,
                     apr_pool_t *scratch_pool)
@@ -1511,8 +1450,6 @@ check_tree_conflict(svn_wc_conflict_desc
   svn_boolean_t modified = FALSE;
   svn_boolean_t all_mods_are_deletes = FALSE;
 
-  SVN_ERR_ASSERT(their_relpath != NULL);
-
   *pconflict = NULL;
 
   /* Find out if there are any local changes to this node that may
@@ -1675,8 +1612,7 @@ check_tree_conflict(svn_wc_conflict_desc
   /* A conflict was detected. Append log commands to the log accumulator
    * to record it. */
   return svn_error_trace(create_tree_conflict(pconflict, eb, local_abspath,
-                                              reason, action, their_node_kind,
-                                              their_relpath,
+                                              reason, action,
                                               result_pool, scratch_pool));
 }
 
@@ -1700,30 +1636,17 @@ already_in_a_tree_conflict(svn_boolean_t
 
   while (TRUE)
     {
-      svn_boolean_t is_wc_root, has_conflict;
+      svn_boolean_t is_wc_root, tree_conflicted;
 
       svn_pool_clear(iterpool);
 
-      SVN_ERR(svn_wc__db_read_info(NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                                   NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                                   NULL, NULL, NULL, NULL, NULL, NULL,
-                                   &has_conflict, NULL, NULL, NULL,
-                                   NULL, NULL, NULL,
-                                   db, ancestor_abspath, iterpool, iterpool));
+      SVN_ERR(svn_wc__internal_conflicted_p(NULL, NULL, &tree_conflicted,
+                                            db, ancestor_abspath, iterpool));
 
-      if (has_conflict)
+      if (tree_conflicted)
         {
-          const svn_wc_conflict_description2_t *conflict;
-
-          SVN_ERR(svn_wc__db_op_read_tree_conflict(&conflict, db,
-                                                   ancestor_abspath,
-                                                   iterpool, iterpool));
-
-          if (conflict != NULL)
-            {
-              *conflicted = TRUE;
-              break;
-            }
+          *conflicted = TRUE;
+          break;
         }
 
       SVN_ERR(svn_wc__db_is_wcroot(&is_wc_root, db, ancestor_abspath,
@@ -1777,12 +1700,12 @@ delete_entry(const char *path,
   svn_boolean_t conflicted;
   svn_boolean_t have_base;
   svn_boolean_t have_work;
-  svn_wc_conflict_description2_t *tree_conflict = NULL;
-  svn_skel_t *work_item = NULL;
+  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;
@@ -1862,7 +1785,10 @@ delete_entry(const char *path,
       || 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, scratch_pool));
+      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;
@@ -1890,13 +1816,13 @@ delete_entry(const char *path,
     {
       SVN_ERR(check_tree_conflict(&tree_conflict, eb, local_abspath,
                                   status, kind, TRUE,
-                                  svn_wc_conflict_action_delete, svn_node_none,
-                                  repos_relpath, moved_to_abspath,
-                                  pb->pool, scratch_pool));
+                                  svn_wc_conflict_action_delete,
+                                  moved_to_abspath, 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
@@ -1907,15 +1833,12 @@ delete_entry(const char *path,
       apr_hash_set(pb->deletion_conflicts, apr_pstrdup(pb->pool, base),
                    APR_HASH_KEY_STRING, tree_conflict);
 
-      SVN_ERR(svn_wc__db_op_set_tree_conflict(eb->db,
-                                              local_abspath,
-                                              tree_conflict,
-                                              scratch_pool));
-
-      do_notification(eb, local_abspath, svn_node_unknown,
-                      svn_wc_notify_tree_conflict, scratch_pool);
+      SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL,
+                                                  eb->db, local_abspath,
+                                                  tree_conflict,
+                                                  scratch_pool, scratch_pool));
 
-      if (tree_conflict->reason == svn_wc_conflict_reason_edited)
+      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.
@@ -1923,17 +1846,15 @@ delete_entry(const char *path,
            * 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. */
-          SVN_ERR(svn_wc__db_temp_op_make_copy(eb->db, local_abspath,
-                                               scratch_pool));
+          keep_as_working = TRUE;
 
           /* Fall through to remove the BASE_NODEs properly, with potentially
              keeping a not-present marker */
         }
-      else if (tree_conflict->reason == svn_wc_conflict_reason_deleted
-               || tree_conflict->reason == svn_wc_conflict_reason_moved_away
-               || tree_conflict->reason ==
-                     svn_wc_conflict_reason_moved_away_and_edited
-               || tree_conflict->reason == svn_wc_conflict_reason_replaced)
+      else if (reason == svn_wc_conflict_reason_deleted
+               || reason == svn_wc_conflict_reason_moved_away
+               || reason == svn_wc_conflict_reason_moved_away_and_edited
+               || 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
@@ -1951,8 +1872,9 @@ delete_entry(const char *path,
        * by deleting the node from the moved-away subtree. */
       /* ### This should probably use a work queue. */
       SVN_ERR(svn_wc__db_op_delete(eb->db, moved_to_abspath, NULL,
-                                   NULL, NULL, /* notify below */
+                                   NULL, NULL,
                                    eb->cancel_func, eb->cancel_baton,
+                                   NULL, NULL, /* notify below */
                                    scratch_pool));
       if (kind == svn_kind_dir)
         SVN_ERR(svn_io_remove_dir2(moved_to_abspath, TRUE,
@@ -1973,32 +1895,30 @@ delete_entry(const char *path,
   if (! deleting_target)
     {
       /* Delete, and do not leave a not-present node.  */
-      SVN_ERR(svn_wc__wq_build_base_remove(&work_item,
-                                           eb->db, local_abspath,
-                                           SVN_INVALID_REVNUM,
-                                           svn_kind_unknown,
-                                           scratch_pool, scratch_pool));
+      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__wq_build_base_remove(&work_item,
-                                           eb->db, local_abspath,
-                                           *eb->target_revision,
-                                           base_kind,
-                                           scratch_pool, scratch_pool));
+      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__db_wq_add(eb->db, pb->local_abspath, work_item,
-                                scratch_pool));
-
   SVN_ERR(svn_wc__wq_run(eb->db, pb->local_abspath,
                          eb->cancel_func, eb->cancel_baton,
                          scratch_pool));
 
-  /* Notify. (If tree_conflict, we've already notified.) */
-  if (tree_conflict == NULL)
+  /* 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;
@@ -2037,7 +1957,7 @@ add_directory(const char *path,
   svn_kind_t wc_kind;
   svn_boolean_t conflicted;
   svn_boolean_t versioned_locally_and_present;
-  svn_wc_conflict_description2_t *tree_conflict = NULL;
+  svn_skel_t *tree_conflict = NULL;
   svn_error_t *err;
 
   SVN_ERR_ASSERT(! (copyfrom_path || SVN_IS_VALID_REVNUM(copyfrom_rev)));
@@ -2165,21 +2085,34 @@ add_directory(const char *path,
 
       if (tree_conflict)
         {
+          svn_wc_conflict_reason_t reason;
           /* So this deletion wasn't just a deletion, it is actually a
-             replacement. Luckily we still have the conflict so we can
-             just update it. */
+             replacement. Let's install a better tree conflict. */
+
+          /* ### Should store the conflict in DB to allow reinstalling
+             ### with theoretically more data in close_directory() */
 
-          /* ### What else should we update? */
-          tree_conflict->action = svn_wc_conflict_action_replace;
+          SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL,
+                                                      eb->db,
+                                                      db->local_abspath,
+                                                      tree_conflict,
+                                                      db->pool, db->pool));
 
-          SVN_ERR(svn_wc__db_op_set_tree_conflict(eb->db, db->local_abspath,
-                                                  tree_conflict, 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 */
           tree_conflict = NULL; /* No direct notification */
           db->shadowed = TRUE; /* Just continue */
           conflicted = FALSE; /* No skip */
+
+          db->edit_conflict = tree_conflict; /* Cache for close_directory */
         }
       else
         SVN_ERR(node_already_conflicted(&conflicted, eb->db,
@@ -2269,7 +2202,6 @@ add_directory(const char *path,
                                       db->local_abspath,
                                       status, wc_kind, FALSE,
                                       svn_wc_conflict_action_add,
-                                      svn_node_dir, db->new_relpath,
                                       NULL, pool, pool));
         }
 
@@ -2295,48 +2227,32 @@ add_directory(const char *path,
                                        db->local_abspath,
                                        svn_wc_conflict_reason_unversioned,
                                        svn_wc_conflict_action_add,
-                                       svn_node_dir,
-                                       db->new_relpath, pool, pool));
+                                       pool, pool));
           SVN_ERR_ASSERT(tree_conflict != NULL);
         }
     }
 
-  SVN_ERR(svn_wc__db_temp_op_set_new_dir_to_incomplete(eb->db,
-                                                       db->local_abspath,
-                                                       db->new_relpath,
-                                                       eb->repos_root,
-                                                       eb->repos_uuid,
-                                                       *eb->target_revision,
-                                                       db->ambient_depth,
-                                                       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 or the parent was moved away. */
   if (!db->shadowed && !pb->moved_to_abspath)
     SVN_ERR(svn_wc__ensure_directory(db->local_abspath, pool));
 
-  if (!db->shadowed && status == svn_wc__db_status_added)
-    /* If there is no conflict we take over any added directory */
-    SVN_ERR(svn_wc__db_temp_op_remove_working(eb->db, db->local_abspath, pool));
-
-  /* ### We can't record an unversioned obstruction yet, so
-     ### we record a delete instead, which will allow resolving the conflict
-     ### to theirs with 'svn revert'. */
-  if (db->shadowed && db->obstruction_found)
-    {
-      SVN_ERR(svn_wc__db_op_delete(eb->db, db->local_abspath, NULL,
-                                   NULL, NULL /* notification */,
-                                   eb->cancel_func, eb->cancel_baton,
-                                   pool));
-    }
-
   if (tree_conflict != NULL)
     {
-      SVN_ERR(svn_wc__db_op_set_tree_conflict(eb->db, db->local_abspath,
-                                              tree_conflict, pool));
-
       db->already_notified = TRUE;
-
       do_notification(eb, db->local_abspath, svn_node_dir,
                       svn_wc_notify_tree_conflict, pool);
     }
@@ -2391,7 +2307,7 @@ open_directory(const char *path,
   struct edit_baton *eb = pb->edit_baton;
   svn_boolean_t have_work;
   svn_boolean_t conflicted;
-  svn_wc_conflict_description2_t *tree_conflict = NULL;
+  svn_skel_t *tree_conflict = NULL;
   svn_wc__db_status_t status, base_status;
   svn_kind_t wc_kind;
   svn_error_t *err;
@@ -2426,8 +2342,9 @@ open_directory(const char *path,
   /* 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, NULL,
-                               NULL, NULL, &db->changed_rev, &db->changed_date,
+  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,
@@ -2440,10 +2357,10 @@ open_directory(const char *path,
     base_status = status;
   else
     SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL, &db->old_revision,
-                                     NULL, NULL, NULL, &db->changed_rev,
-                                     &db->changed_date, &db->changed_author,
-                                     &db->ambient_depth, NULL, NULL, NULL,
-                                     NULL, NULL,
+                                     &db->old_repos_relpath, NULL, NULL,
+                                     &db->changed_rev, &db->changed_date,
+                                     &db->changed_author, &db->ambient_depth,
+                                     NULL, NULL, NULL, NULL, NULL,
                                      eb->db, db->local_abspath,
                                      db->pool, pool));
 
@@ -2494,21 +2411,24 @@ open_directory(const char *path,
   if (!db->shadowed)
     SVN_ERR(check_tree_conflict(&tree_conflict, eb, db->local_abspath,
                                 status, wc_kind, TRUE,
-                                svn_wc_conflict_action_edit, svn_node_dir,
-                                db->new_relpath, db->moved_to_abspath,
-                                db->pool, pool));
+                                svn_wc_conflict_action_edit,
+                                db->moved_to_abspath, 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_ASSERT(
-                tree_conflict->reason == svn_wc_conflict_reason_deleted ||
-                tree_conflict->reason == svn_wc_conflict_reason_moved_away ||
-                tree_conflict->reason ==
-                  svn_wc_conflict_reason_moved_away_and_edited ||
-                tree_conflict->reason == svn_wc_conflict_reason_replaced);
+
+      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_moved_away_and_edited
+                     || reason == svn_wc_conflict_reason_replaced);
 
       /* Continue updating BASE */
       db->shadowed = TRUE;
@@ -2588,6 +2508,7 @@ close_directory(void *dir_baton,
   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)
@@ -2598,6 +2519,9 @@ close_directory(void *dir_baton,
       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));
 
@@ -2670,8 +2594,6 @@ close_directory(void *dir_baton,
      to deal with them. */
   if (regular_prop_changes->nelts)
     {
-      svn_skel_t *work_item;
-
       /* If recording traversal info, then see if the
          SVN_PROP_EXTERNALS property on this directory changed,
          and record before and after for the change. */
@@ -2719,23 +2641,19 @@ close_directory(void *dir_baton,
 
       /* Merge pending properties into temporary files (ignoring
          conflicts). */
-      SVN_ERR_W(svn_wc__merge_props(&work_item,
+      SVN_ERR_W(svn_wc__merge_props(&conflict_skel,
                                     &prop_state,
                                     &new_base_props,
                                     &new_actual_props,
                                     eb->db,
                                     db->local_abspath,
                                     svn_kind_dir,
-                                    NULL, /* left_version */
-                                    NULL, /* right_version */
                                     NULL /* use baseprops */,
                                     base_props,
                                     actual_props,
                                     regular_prop_changes,
                                     TRUE /* base_merge */,
                                     FALSE /* dry_run */,
-                                    eb->conflict_func,
-                                    eb->conflict_baton,
                                     eb->cancel_func,
                                     eb->cancel_baton,
                                     db->pool,
@@ -2743,8 +2661,6 @@ close_directory(void *dir_baton,
                 _("Couldn't do property merge"));
       /* After a (not-dry-run) merge, we ALWAYS have props to save.  */
       SVN_ERR_ASSERT(new_base_props != NULL && new_actual_props != NULL);
-      all_work_items = svn_wc__wq_merge(all_work_items, work_item,
-                                        scratch_pool);
     }
 
   SVN_ERR(accumulate_last_change(&new_changed_rev, &new_changed_date,
@@ -2915,6 +2831,54 @@ close_directory(void *dir_baton,
       if (props == NULL)
         props = base_props;
 
+      if (conflict_skel)
+        {
+          svn_skel_t *work_item;
+          svn_boolean_t completed;
+
+          SVN_ERR(svn_wc__conflict_skel_is_complete(&completed,
+                                                    conflict_skel));
+
+          if (completed)
+            {
+              /* Avoid assertion */
+            }
+          else if (eb->switch_relpath)
+            SVN_ERR(svn_wc__conflict_skel_set_op_switch(
+                        conflict_skel,
+                        db->adding_dir
+                            ? NULL
+                            : svn_wc_conflict_version_create2(
+                                            eb->repos_root,
+                                            eb->repos_uuid,
+                                            db->old_repos_relpath,
+                                            db->old_revision,
+                                            svn_node_dir,
+                                            scratch_pool),
+                        db->pool, db->pool));
+          else
+            SVN_ERR(svn_wc__conflict_skel_set_op_update(
+                        conflict_skel,
+                        db->adding_dir
+                            ? NULL
+                            : svn_wc_conflict_version_create2(
+                                            eb->repos_root,
+                                            eb->repos_uuid,
+                                            db->old_repos_relpath,
+                                            db->old_revision,
+                                            svn_node_dir,
+                                            scratch_pool),
+                        db->pool, db->pool));
+
+          SVN_ERR(svn_wc__conflict_create_markers(&work_item,
+                                                  eb->db, db->local_abspath,
+                                                  conflict_skel,
+                                                  scratch_pool, scratch_pool));
+
+          all_work_items = svn_wc__wq_merge(all_work_items, work_item,
+                                            scratch_pool);
+        }
+
       /* Update the BASE data for the directory and mark the directory
          complete */
       SVN_ERR(svn_wc__db_base_add_directory(
@@ -2930,7 +2894,7 @@ close_directory(void *dir_baton,
                 (dav_prop_changes->nelts > 0)
                     ? svn_prop_array_to_hash(dav_prop_changes, pool)
                     : NULL,
-                NULL /* conflict */,
+                conflict_skel,
                 (! db->shadowed) && new_base_props != NULL,
                 new_actual_props,
                 all_work_items,
@@ -2977,6 +2941,14 @@ close_directory(void *dir_baton,
                          eb->cancel_func, eb->cancel_baton,
                          scratch_pool));
 
+  if (conflict_skel && eb->conflict_func)
+    SVN_ERR(svn_wc__conflict_invoke_resolver(eb->db, db->local_abspath,
+                                             conflict_skel,
+                                             NULL /* merge_options */,
+                                             eb->conflict_func,
+                                             eb->conflict_baton,
+                                             scratch_pool));
+
   /* Notify of any prop changes on this directory -- but do nothing if
      it's an added or skipped directory, because notification has already
      happened in that case - unless the add was obstructed by a dir
@@ -3152,7 +3124,7 @@ add_file(const char *path,
   apr_pool_t *scratch_pool;
   svn_boolean_t conflicted = FALSE;
   svn_boolean_t versioned_locally_and_present = FALSE;
-  svn_wc_conflict_description2_t *tree_conflict = NULL;
+  svn_skel_t *tree_conflict = NULL;
   svn_error_t *err = SVN_NO_ERROR;
 
   SVN_ERR_ASSERT(! (copyfrom_path || SVN_IS_VALID_REVNUM(copyfrom_rev)));
@@ -3266,21 +3238,34 @@ add_file(const char *path,
 
       if (tree_conflict)
         {
+          svn_wc_conflict_reason_t reason;
           /* So this deletion wasn't just a deletion, it is actually a
-             replacement. Luckily we still have the conflict so we can
-             just update it. */
+             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,
+                                                      fb->local_abspath,
+                                                      tree_conflict,
+                                                      fb->pool, fb->pool));
 
-          /* ### What else should we update? */
-          tree_conflict->action = svn_wc_conflict_action_replace;
+          tree_conflict = svn_wc__conflict_skel_create(fb->pool);
 
-          SVN_ERR(svn_wc__db_op_set_tree_conflict(eb->db, fb->local_abspath,
-                                                  tree_conflict, pool));
+          SVN_ERR(svn_wc__conflict_skel_add_tree_conflict(
+                                        tree_conflict,
+                                        eb->db, fb->local_abspath,
+                                        reason, svn_wc_conflict_action_replace,
+                                        fb->pool, fb->pool));
 
           /* And now stop checking for conflicts here and just perform
              a shadowed update */
           tree_conflict = NULL; /* No direct notification */
           fb->shadowed = TRUE; /* Just continue */
           conflicted = FALSE; /* No skip */
+
+          fb->edit_conflict = tree_conflict; /* Cache for close_file */
         }
       else
         SVN_ERR(node_already_conflicted(&conflicted, eb->db,
@@ -3365,8 +3350,7 @@ add_file(const char *path,
           SVN_ERR(check_tree_conflict(&tree_conflict, eb,
                                       fb->local_abspath,
                                       status, wc_kind, FALSE,
-                                      svn_wc_conflict_action_add,
-                                      svn_node_file, fb->new_relpath, NULL,
+                                      svn_wc_conflict_action_add, NULL,
                                       scratch_pool, scratch_pool));
         }
 
@@ -3393,8 +3377,6 @@ add_file(const char *path,
                                        fb->local_abspath,
                                        svn_wc_conflict_reason_unversioned,
                                        svn_wc_conflict_action_add,
-                                       svn_node_file,
-                                       fb->new_relpath,
                                        scratch_pool, scratch_pool));
           SVN_ERR_ASSERT(tree_conflict != NULL);
         }
@@ -3413,10 +3395,10 @@ add_file(const char *path,
 
   if (tree_conflict != NULL)
     {
-      SVN_ERR(svn_wc__db_op_set_tree_conflict(eb->db,
-                                              fb->local_abspath,
-                                              tree_conflict,
-                                              scratch_pool));
+      SVN_ERR(svn_wc__db_op_mark_conflict(eb->db,
+                                          fb->local_abspath,
+                                          tree_conflict, NULL,
+                                          scratch_pool));
 
       fb->already_notified = TRUE;
       do_notification(eb, fb->local_abspath, svn_node_file,
@@ -3453,7 +3435,7 @@ open_file(const char *path,
   svn_boolean_t have_work;
   svn_wc__db_status_t status;
   svn_kind_t wc_kind;
-  svn_wc_conflict_description2_t *tree_conflict = NULL;
+  svn_skel_t *tree_conflict = NULL;
 
   /* the file_pool can stick around for a *long* time, so we want to use
      a subpool for any temporary allocations. */
@@ -3489,8 +3471,9 @@ open_file(const char *path,
   /* Sanity check. */
 
   /* If replacing, make sure the .svn entry already exists. */
-  SVN_ERR(svn_wc__db_read_info(&status, &wc_kind, &fb->old_revision, NULL,
-                               NULL, NULL, &fb->changed_rev, &fb->changed_date,
+  SVN_ERR(svn_wc__db_read_info(&status, &wc_kind, &fb->old_revision,
+                               &fb->old_repos_relpath, NULL, NULL,
+                               &fb->changed_rev, &fb->changed_date,
                                &fb->changed_author, NULL,
                                &fb->original_checksum, NULL, NULL, NULL,
                                NULL, NULL, NULL, NULL, NULL, NULL,
@@ -3501,9 +3484,10 @@ open_file(const char *path,
 
   if (have_work)
     SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, &fb->old_revision,
-                                     NULL, NULL, NULL, &fb->changed_rev,
-                                     &fb->changed_date, &fb->changed_author,
-                                     NULL, &fb->original_checksum, NULL, NULL,
+                                     &fb->old_repos_relpath, NULL, NULL,
+                                     &fb->changed_rev, &fb->changed_date,
+                                     &fb->changed_author, NULL,
+                                     &fb->original_checksum, NULL, NULL,
                                      NULL, NULL,
                                      eb->db, fb->local_abspath,
                                      fb->pool, scratch_pool));
@@ -3540,22 +3524,24 @@ open_file(const char *path,
   if (!fb->shadowed)
     SVN_ERR(check_tree_conflict(&tree_conflict, eb, fb->local_abspath,
                                 status, wc_kind, TRUE,
-                                svn_wc_conflict_action_edit, svn_node_file,
-                                fb->new_relpath, fb->moved_to_abspath,
-                                fb->pool, scratch_pool));
+                                svn_wc_conflict_action_edit,
+                                fb->moved_to_abspath, fb->pool, scratch_pool));
 
   /* Is this path the victim of a newly-discovered tree conflict? */
   if (tree_conflict != NULL)
     {
+      svn_wc_conflict_reason_t reason;
       fb->edit_conflict = tree_conflict;
-
       /* Other modifications wouldn't be a tree conflict */
-      SVN_ERR_ASSERT(
-                tree_conflict->reason == svn_wc_conflict_reason_deleted ||
-                tree_conflict->reason == svn_wc_conflict_reason_moved_away ||
-                tree_conflict->reason ==
-                  svn_wc_conflict_reason_moved_away_and_edited ||
-                tree_conflict->reason == svn_wc_conflict_reason_replaced);
+
+      SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL,
+                                                  eb->db, fb->local_abspath,
+                                                  tree_conflict,
+                                                  fb->pool, fb->pool));
+      SVN_ERR_ASSERT(reason == svn_wc_conflict_reason_deleted
+                     || reason == svn_wc_conflict_reason_moved_away
+                     || reason == svn_wc_conflict_reason_moved_away_and_edited
+                     || reason == svn_wc_conflict_reason_replaced);
 
       /* Continue updating BASE */
       fb->shadowed = TRUE;
@@ -3742,6 +3728,7 @@ change_file_prop(void *file_baton,
  */
 svn_error_t *
 svn_wc__perform_file_merge(svn_skel_t **work_items,
+                           svn_skel_t **conflict_skel,
                            enum svn_wc_merge_outcome_t *merge_outcome,
                            svn_wc__db_t *db,
                            const char *local_abspath,
@@ -3754,8 +3741,6 @@ svn_wc__perform_file_merge(svn_skel_t **
                            svn_revnum_t target_revision,
                            const apr_array_header_t *propchanges,
                            const char *diff3_cmd,
-                           svn_wc_conflict_resolver_func2_t conflict_func,
-                           void *conflict_baton,
                            svn_cancel_func_t cancel_func,
                            void *cancel_baton,
                            apr_pool_t *result_pool,
@@ -3823,17 +3808,17 @@ svn_wc__perform_file_merge(svn_skel_t **
      Remember that this function wants full paths! */
   /* ### TODO: Pass version info here. */
   SVN_ERR(svn_wc__internal_merge(&work_item,
+                                 conflict_skel,
                                  merge_outcome,
                                  db,
-                                 merge_left, NULL,
-                                 new_text_base_tmp_abspath, NULL,
+                                 merge_left,
+                                 new_text_base_tmp_abspath,
                                  local_abspath,
                                  wri_abspath,
                                  oldrev_str, newrev_str, mine_str,
                                  actual_props,
                                  FALSE /* dry_run */,
                                  diff3_cmd, NULL, propchanges,
-                                 conflict_func, conflict_baton,
                                  cancel_func, cancel_baton,
                                  result_pool, scratch_pool));
 
@@ -3875,6 +3860,7 @@ svn_wc__perform_file_merge(svn_skel_t **
  */
 static svn_error_t *
 merge_file(svn_skel_t **work_items,
+           svn_skel_t **conflict_skel,
            svn_boolean_t *install_pristine,
            const char **install_from,
            svn_wc_notify_state_t *content_state,
@@ -3976,6 +3962,7 @@ merge_file(svn_skel_t **work_items,
          Now we need to let loose svn_wc__merge_internal() to merge
          the textual changes into the working file. */
       SVN_ERR(svn_wc__perform_file_merge(work_items,
+                                         conflict_skel,
                                          &merge_outcome,
                                          eb->db,
                                          working_abspath,
@@ -3990,7 +3977,6 @@ merge_file(svn_skel_t **work_items,
                                          *eb->target_revision,
                                          fb->propchanges,
                                          eb->diff3_cmd,
-                                         eb->conflict_func, eb->conflict_baton,
                                          eb->cancel_func, eb->cancel_baton,
                                          result_pool, scratch_pool));
     } /* end: working file exists and has mods */
@@ -4104,6 +4090,7 @@ close_file(void *file_baton,
   apr_hash_t *current_actual_props = NULL;
   apr_hash_t *local_actual_props = NULL;
   svn_skel_t *all_work_items = NULL;
+  svn_skel_t *conflict_skel = NULL;
   svn_skel_t *work_item;
   apr_pool_t *scratch_pool = fb->pool; /* Destroyed at function exit */
   svn_boolean_t keep_recorded_info = FALSE;
@@ -4118,6 +4105,9 @@ close_file(void *file_baton,
       return SVN_NO_ERROR;
     }
 
+  if (fb->edited)
+    conflict_skel = fb->edit_conflict;
+
   if (expected_md5_digest)
     SVN_ERR(svn_checksum_parse_hex(&expected_md5_checksum, svn_checksum_md5,
                                    expected_md5_digest, scratch_pool));
@@ -4266,26 +4256,26 @@ close_file(void *file_baton,
 
       if (local_is_link != incoming_is_link)
         {
-          svn_wc_conflict_description2_t *tree_conflict = NULL;
-
           fb->shadowed = TRUE;
           fb->obstruction_found = TRUE;
           fb->add_existed = FALSE;
 
-          SVN_ERR(create_tree_conflict(&tree_conflict, eb,
-                                       fb->local_abspath,
+          if (!conflict_skel)
+            conflict_skel = svn_wc__conflict_skel_create(fb->pool);
+
+          SVN_ERR(svn_wc__conflict_skel_add_tree_conflict(
+                                       conflict_skel,
+                                       eb->db, fb->local_abspath,
                                        svn_wc_conflict_reason_added,
                                        svn_wc_conflict_action_add,
-                                       svn_node_file, fb->new_relpath,
                                        scratch_pool, scratch_pool));
-          SVN_ERR(svn_wc__db_op_set_tree_conflict(eb->db,
-                                                  fb->local_abspath,
-                                                  tree_conflict,
-                                                  scratch_pool));
 
           fb->already_notified = TRUE;
           do_notification(eb, fb->local_abspath, svn_node_unknown,
                           svn_wc_notify_tree_conflict, scratch_pool);
+
+          /* The update will be applied to PRISTINE, but not to
+             the in-working copy node */
         }
     }
 
@@ -4300,35 +4290,31 @@ close_file(void *file_baton,
       /* This will merge the old and new props into a new prop db, and
          write <cp> commands to the logfile to install the merged
          props.  */
-      SVN_ERR(svn_wc__merge_props(&work_item,
+      SVN_ERR(svn_wc__merge_props(&conflict_skel,
                                   &prop_state,
                                   &new_base_props,
                                   &new_actual_props,
                                   eb->db,
                                   working_abspath,
                                   svn_kind_file,
-                                  NULL /* left_version */,
-                                  NULL /* right_version */,
                                   NULL /* server_baseprops (update, not merge)  */,
                                   current_base_props,
                                   current_actual_props,
                                   regular_prop_changes, /* propchanges */
                                   TRUE /* base_merge */,
                                   FALSE /* dry_run */,
-                                  eb->conflict_func, eb->conflict_baton,
                                   eb->cancel_func, eb->cancel_baton,
                                   scratch_pool,
                                   scratch_pool));
       /* We will ALWAYS have properties to save (after a not-dry-run merge). */
       SVN_ERR_ASSERT(new_base_props != NULL && new_actual_props != NULL);
-      all_work_items = svn_wc__wq_merge(all_work_items, work_item,
-                                        scratch_pool);
 
       /* Merge the text. This will queue some additional work.  */
       if (!fb->obstruction_found)
         {
           svn_error_t *err;
-          err = merge_file(&work_item, &install_pristine, &install_from,
+          err = merge_file(&work_item, &conflict_skel,
+                           &install_pristine, &install_from,
                            &content_state, fb, current_actual_props,
                            fb->changed_date, scratch_pool, scratch_pool);
 
@@ -4439,29 +4425,23 @@ close_file(void *file_baton,
 
       /* Store the incoming props (sent as propchanges) in new_base_props
          and create a set of new actual props to use for notifications */
-      SVN_ERR(svn_wc__merge_props(&work_item,
+      SVN_ERR(svn_wc__merge_props(&conflict_skel,
                                   &prop_state,
                                   &new_base_props,
                                   &new_actual_props,
                                   eb->db,
                                   fb->local_abspath,
                                   svn_kind_file,
-                                  NULL /* left_version */,
-                                  NULL /* right_version */,
                                   NULL /* server_baseprops (not merging) */,
                                   current_base_props /* pristine_props */,
                                   fake_actual_props /* actual_props */,
                                   regular_prop_changes, /* propchanges */
                                   TRUE /* base_merge */,
                                   FALSE /* dry_run */,
-                                  NULL, NULL, /* No conflict handling */
                                   eb->cancel_func, eb->cancel_baton,
                                   scratch_pool,
                                   scratch_pool));
 
-      all_work_items = svn_wc__wq_merge(all_work_items, work_item,
-                                        scratch_pool);
-
       if (fb->new_text_base_sha1_checksum)
         content_state = svn_wc_notify_state_changed;
       else
@@ -4480,6 +4460,51 @@ close_file(void *file_baton,
   if (new_checksum == NULL)
     new_checksum = fb->original_checksum;
 
+  if (conflict_skel)
+    {
+      svn_boolean_t completed;
+
+      SVN_ERR(svn_wc__conflict_skel_is_complete(&completed,
+                                                    conflict_skel));
+
+      if (completed)
+        {
+          /* Avoid assertion */
+        }
+      else if (eb->switch_relpath)
+        SVN_ERR(svn_wc__conflict_skel_set_op_switch(
+                    conflict_skel,
+                    fb->adding_file
+                      ? NULL
+                      : svn_wc_conflict_version_create2(eb->repos_root,
+                                                        eb->repos_uuid,
+                                                        fb->old_repos_relpath,
+                                                        fb->old_revision,
+                                                        svn_node_file,
+                                                        fb->pool),
+                    fb->pool, fb->pool));
+      else
+        SVN_ERR(svn_wc__conflict_skel_set_op_update(
+                    conflict_skel,
+                    fb->adding_file
+                      ? NULL
+                      : svn_wc_conflict_version_create2(eb->repos_root,
+                                                        eb->repos_uuid,
+                                                        fb->old_repos_relpath,
+                                                        fb->old_revision,
+                                                        svn_node_file,
+                                                        fb->pool),
+                    fb->pool, fb->pool));
+
+      SVN_ERR(svn_wc__conflict_create_markers(&work_item,
+                                              eb->db, fb->local_abspath,
+                                              conflict_skel,
+                                              scratch_pool, scratch_pool));
+
+      all_work_items = svn_wc__wq_merge(all_work_items, work_item,
+                                        scratch_pool);
+    }
+
   SVN_ERR(svn_wc__db_base_add_file(eb->db, fb->local_abspath,
                                    eb->wcroot_abspath,
                                    fb->new_relpath,
@@ -4495,14 +4520,23 @@ close_file(void *file_baton,
                                                       dav_prop_changes,
                                                       scratch_pool)
                                      : NULL,
-                                   NULL /* conflict */,
+                                   (fb->add_existed && fb->adding_file),
                                    (! fb->shadowed) && new_base_props,
                                    new_actual_props,
                                    keep_recorded_info,
                                    (fb->shadowed && fb->obstruction_found),
+                                   conflict_skel,
                                    all_work_items,
                                    scratch_pool));
 
+  if (conflict_skel && eb->conflict_func)
+    SVN_ERR(svn_wc__conflict_invoke_resolver(eb->db, fb->local_abspath,
+                                             conflict_skel,
+                                             NULL /* merge_options */,
+                                             eb->conflict_func,
+                                             eb->conflict_baton,
+                                             scratch_pool));
+
   /* Deal with the WORKING tree, based on updates to the BASE tree.  */
 
   if (fb->moved_to_abspath)
@@ -4519,21 +4553,14 @@ close_file(void *file_baton,
                                       eb->repos_uuid,
                                       *eb->target_revision,
                                       new_checksum,
+                                      FALSE /* update_actual_props */,
+                                      NULL /* new_actual_props */,
                                       TRUE /* is_move */,
                                       NULL /* conflict */,
                                       NULL, /* no work, just modify DB */
                                       scratch_pool));
     }
 
-  /* If this file was locally-added and is now being added by the update, we
-     can toss the local-add, turning this into a local-edit.
-     If the local file is replaced, we don't want to touch ACTUAL. */
-  if (fb->add_existed && fb->adding_file)
-    {
-      SVN_ERR(svn_wc__db_temp_op_remove_working(eb->db, fb->local_abspath,
-                                                scratch_pool));
-    }
-
   apr_hash_set(fb->dir_baton->not_present_files, fb->name,
                APR_HASH_KEY_STRING, NULL);
 
@@ -4677,7 +4704,8 @@ close_edit(void *edit_baton,
                  If so, we should get rid of this excluded node now. */
 
               SVN_ERR(svn_wc__db_base_remove(eb->db, eb->target_abspath,
-                                             scratch_pool));
+                                             FALSE, SVN_INVALID_REVNUM,
+                                             NULL, NULL, scratch_pool));
             }
         }
     }
@@ -5664,16 +5692,10 @@ svn_wc_add_repos_file4(svn_wc_context_t 
                                   original_uuid,
                                   copyfrom_rev,
                                   new_text_base_sha1_checksum,
+                                  TRUE,
+                                  new_props,
                                   FALSE /* is_move */,
                                   NULL /* conflict */,
-                                  NULL /* work_items */,
-                                  pool));
-
-  /* ### if below fails, then the above db change would remain :-(  */
-
-  SVN_ERR(svn_wc__db_op_set_props(db, local_abspath,
-                                  new_props, FALSE,
-                                  NULL /* conflict */,
                                   all_work_items,
                                   pool));
 

Modified: subversion/branches/inheritable-props/subversion/libsvn_wc/upgrade.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_wc/upgrade.c?rev=1360909&r1=1360908&r2=1360909&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_wc/upgrade.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_wc/upgrade.c Thu Jul 12 20:24:53 2012
@@ -31,6 +31,7 @@
 
 #include "wc.h"
 #include "adm_files.h"
+#include "conflicts.h"
 #include "entries.h"
 #include "wc_db.h"
 #include "tree_conflicts.h"
@@ -1364,6 +1365,202 @@ bump_to_29(void *baton, svn_sqlite__db_t
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_wc__upgrade_conflict_skel_from_raw(svn_skel_t **conflicts,
+                                       svn_wc__db_t *db,
+                                       const char *wri_abspath,
+                                       const char *local_relpath,
+                                       const char *conflict_old,
+                                       const char *conflict_wrk,
+                                       const char *conflict_new,
+                                       const char *prej_file,
+                                       const char *tree_conflict_data,
+                                       apr_size_t tree_conflict_len,
+                                       apr_pool_t *result_pool,
+                                       apr_pool_t *scratch_pool)
+{
+  svn_skel_t *conflict_data = NULL;
+  
+  if (conflict_old || conflict_new || conflict_wrk)
+    {
+      const char *old_abspath = NULL;
+      const char *new_abspath = NULL;
+      const char *wrk_abspath = NULL;
+
+      conflict_data = svn_wc__conflict_skel_create(result_pool);
+
+      if (conflict_old)
+        SVN_ERR(svn_wc__db_from_relpath(&old_abspath, db, wri_abspath,
+                                        conflict_old,
+                                        scratch_pool, scratch_pool));
+
+      if (conflict_new)
+        SVN_ERR(svn_wc__db_from_relpath(&new_abspath, db, wri_abspath,
+                                        conflict_new,
+                                        scratch_pool, scratch_pool));
+
+      if (conflict_wrk)
+        SVN_ERR(svn_wc__db_from_relpath(&wrk_abspath, db, wri_abspath,
+                                        conflict_wrk,
+                                        scratch_pool, scratch_pool));
+
+      SVN_ERR(svn_wc__conflict_skel_add_text_conflict(conflict_data,
+                                                      db, wri_abspath,
+                                                      wrk_abspath,
+                                                      old_abspath,
+                                                      new_abspath,
+                                                      scratch_pool,
+                                                      scratch_pool));
+    }
+
+  if (prej_file)
+    {
+      const char *prej_abspath;
+
+      if (!conflict_data)
+        conflict_data = svn_wc__conflict_skel_create(result_pool);
+
+      SVN_ERR(svn_wc__db_from_relpath(&prej_abspath, db, wri_abspath,
+                                      prej_file,
+                                      scratch_pool, scratch_pool));
+
+      SVN_ERR(svn_wc__conflict_skel_add_prop_conflict(conflict_data,
+                                                      db, wri_abspath,
+                                                      prej_abspath,
+                                                      NULL, NULL, NULL,
+                                                apr_hash_make(scratch_pool),
+                                                      scratch_pool,
+                                                      scratch_pool));
+    }
+
+  if (tree_conflict_data)
+    {
+      svn_skel_t *tc_skel;
+      const svn_wc_conflict_description2_t *tc;
+      const char *local_abspath;
+
+      if (!conflict_data)
+        conflict_data = svn_wc__conflict_skel_create(scratch_pool);
+
+      tc_skel = svn_skel__parse(tree_conflict_data, tree_conflict_len,
+                                scratch_pool);
+
+      SVN_ERR(svn_wc__db_from_relpath(&local_abspath, db, wri_abspath,
+                                      local_relpath,
+                                      scratch_pool, scratch_pool));
+
+      SVN_ERR(svn_wc__deserialize_conflict(&tc, tc_skel,
+                                           svn_dirent_dirname(local_abspath,
+                                                              scratch_pool),
+                                           scratch_pool, scratch_pool));
+
+      SVN_ERR(svn_wc__conflict_skel_add_tree_conflict(conflict_data,
+                                                      db, wri_abspath,
+                                                      tc->reason,
+                                                      tc->action,
+                                                      scratch_pool,
+                                                      scratch_pool));
+
+      switch (tc->operation)
+        {
+          case svn_wc_operation_update:
+          default:
+            SVN_ERR(svn_wc__conflict_skel_set_op_update(conflict_data,
+                                                       tc->src_left_version,
+                                                       scratch_pool,
+                                                       scratch_pool));
+            break;
+          case svn_wc_operation_switch:
+            SVN_ERR(svn_wc__conflict_skel_set_op_switch(conflict_data,
+                                                        tc->src_left_version,
+                                                        scratch_pool,
+                                                        scratch_pool));
+            break;
+          case svn_wc_operation_merge:
+            SVN_ERR(svn_wc__conflict_skel_set_op_merge(conflict_data,
+                                                       tc->src_left_version,
+                                                       tc->src_right_version,
+                                                       scratch_pool,
+                                                       scratch_pool));
+            break;
+        }
+    }
+  else if (conflict_data)
+    {
+      SVN_ERR(svn_wc__conflict_skel_set_op_update(conflict_data, NULL,
+                                                  scratch_pool,
+                                                  scratch_pool));
+    }
+
+  *conflicts = conflict_data;
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+bump_to_30(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
+{
+  struct bump_baton *bb = baton;
+  svn_boolean_t have_row;
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  svn_sqlite__stmt_t *stmt;
+  svn_sqlite__stmt_t *stmt_store;
+  svn_wc__db_t *db; /* Read only temp db */
+  const char *wri_abspath = bb->wcroot_abspath;
+
+  SVN_ERR(svn_wc__db_open(&db, NULL, FALSE, FALSE,
+                          scratch_pool, scratch_pool));
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt_store, sdb,
+                                    STMT_UPGRADE_30_SET_CONFLICT));
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+                                    STMT_UPGRADE_30_SELECT_CONFLICT_SEPARATE));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+  while (have_row)
+    {
+      svn_stringbuf_t *skel_data;
+      svn_skel_t *conflict_data;
+      apr_int64_t wc_id = svn_sqlite__column_int64(stmt, 0);
+      const char *local_relpath = svn_sqlite__column_text(stmt, 1, NULL);
+      const char *conflict_old = svn_sqlite__column_text(stmt, 2, NULL);
+      const char *conflict_wrk = svn_sqlite__column_text(stmt, 3, NULL);
+      const char *conflict_new = svn_sqlite__column_text(stmt, 4, NULL);
+      const char *prop_reject = svn_sqlite__column_text(stmt, 5, NULL);
+      apr_size_t tree_conflict_size;
+      const char *tree_conflict_data = svn_sqlite__column_blob(stmt, 6,
+                                               &tree_conflict_size, NULL);
+
+      svn_pool_clear(iterpool);
+
+      SVN_ERR(svn_wc__upgrade_conflict_skel_from_raw(&conflict_data,
+                                                     db, wri_abspath,
+                                                     local_relpath,
+                                                     conflict_old,
+                                                     conflict_wrk,
+                                                     conflict_new,
+                                                     prop_reject,
+                                                     tree_conflict_data,
+                                                     tree_conflict_size,
+                                                     iterpool, iterpool));
+
+      SVN_ERR_ASSERT(conflict_data != NULL);
+
+      skel_data = svn_skel__unparse(conflict_data, iterpool);
+
+      SVN_ERR(svn_sqlite__bindf(stmt_store, "isb", wc_id, local_relpath,
+                                skel_data->data, skel_data->len));
+      SVN_ERR(svn_sqlite__step_done(stmt_store));
+
+      SVN_ERR(svn_sqlite__step(&have_row, stmt));
+    }
+  SVN_ERR(svn_sqlite__reset(stmt));
+
+  SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_30));
+  SVN_ERR(svn_wc__db_close(db));
+  return SVN_NO_ERROR;
+}
+
 
 struct upgrade_data_t {
   svn_sqlite__db_t *sdb;
@@ -1637,6 +1834,13 @@ svn_wc__upgrade_sdb(int *result_format,
         *result_format = 29;
         /* FALLTHROUGH  */
 
+#if SVN_WC__VERSION >= 30
+      case 29:
+        SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_30, &bb,
+                                             scratch_pool));
+        *result_format = 30;
+        /* FALLTHROUGH  */
+#endif
       /* ### future bumps go here.  */
 #if 0
       case XXX-1:

Modified: subversion/branches/inheritable-props/subversion/libsvn_wc/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_wc/util.c?rev=1360909&r1=1360908&r2=1360909&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_wc/util.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_wc/util.c Thu Jul 12 20:24:53 2012
@@ -285,24 +285,27 @@ svn_wc__conflict_description2_dup(const 
 }
 
 svn_wc_conflict_version_t *
-svn_wc_conflict_version_create(const char *repos_url,
-                               const char *path_in_repos,
-                               svn_revnum_t peg_rev,
-                               svn_node_kind_t node_kind,
-                               apr_pool_t *pool)
+svn_wc_conflict_version_create2(const char *repos_url,
+                                const char *repos_uuid,
+                                const char *repos_relpath,
+                                svn_revnum_t revision,
+                                svn_node_kind_t kind,
+                                apr_pool_t *result_pool)
 {
   svn_wc_conflict_version_t *version;
 
-  version = apr_pcalloc(pool, sizeof(*version));
+  version = apr_pcalloc(result_pool, sizeof(*version));
 
-  SVN_ERR_ASSERT_NO_RETURN(svn_uri_is_canonical(repos_url, pool) &&
-                           svn_relpath_is_canonical(path_in_repos) &&
-                           SVN_IS_VALID_REVNUM(peg_rev));
+    SVN_ERR_ASSERT_NO_RETURN(svn_uri_is_canonical(repos_url, result_pool)
+                             && svn_relpath_is_canonical(repos_relpath)
+                             && SVN_IS_VALID_REVNUM(revision)
+                             /* ### repos_uuid can be NULL :( */);
 
   version->repos_url = repos_url;
-  version->peg_rev = peg_rev;
-  version->path_in_repos = path_in_repos;
-  version->node_kind = node_kind;
+  version->peg_rev = revision;
+  version->path_in_repos = repos_relpath;
+  version->node_kind = kind;
+  version->repos_uuid = repos_uuid;
 
   return version;
 }
@@ -310,7 +313,7 @@ svn_wc_conflict_version_create(const cha
 
 svn_wc_conflict_version_t *
 svn_wc_conflict_version_dup(const svn_wc_conflict_version_t *version,
-                            apr_pool_t *pool)
+                            apr_pool_t *result_pool)
 {
 
   svn_wc_conflict_version_t *new_version;
@@ -318,16 +321,20 @@ svn_wc_conflict_version_dup(const svn_wc
   if (version == NULL)
     return NULL;
 
-  new_version = apr_pcalloc(pool, sizeof(*new_version));
+  new_version = apr_pcalloc(result_pool, sizeof(*new_version));
 
   /* Shallow copy all members. */
   *new_version = *version;
 
   if (version->repos_url)
-    new_version->repos_url = apr_pstrdup(pool, version->repos_url);
+    new_version->repos_url = apr_pstrdup(result_pool, version->repos_url);
 
   if (version->path_in_repos)
-    new_version->path_in_repos = apr_pstrdup(pool, version->path_in_repos);
+    new_version->path_in_repos = apr_pstrdup(result_pool,
+                                             version->path_in_repos);
+
+  if (version->repos_uuid)
+    new_version->repos_uuid = apr_pstrdup(result_pool, version->repos_uuid);
 
   return new_version;
 }
@@ -441,9 +448,8 @@ svn_wc__status2_from_3(svn_wc_status2_t 
   if (old_status->conflicted)
     {
       const svn_wc_conflict_description2_t *tree_conflict;
-      SVN_ERR(svn_wc__db_op_read_tree_conflict(&tree_conflict, wc_ctx->db,
-                                               local_abspath, scratch_pool,
-                                               scratch_pool));
+      SVN_ERR(svn_wc__get_tree_conflict(&tree_conflict, wc_ctx, local_abspath,
+                                        scratch_pool, scratch_pool));
       (*status)->tree_conflict = svn_wc__cd2_to_cd(tree_conflict, result_pool);
     }
 

Modified: subversion/branches/inheritable-props/subversion/libsvn_wc/wc-metadata.sql
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_wc/wc-metadata.sql?rev=1360909&r1=1360908&r2=1360909&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_wc/wc-metadata.sql (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_wc/wc-metadata.sql Thu Jul 12 20:24:53 2012
@@ -107,7 +107,8 @@ CREATE TABLE PRISTINE (
   md5_checksum  TEXT NOT NULL
   );
 
-
+CREATE INDEX I_PRISTINE_MD5 ON PRISTINE (md5_checksum);
+  
 /* ------------------------------------------------------------------------- */
 
 /* The ACTUAL_NODE table describes text changes and property changes
@@ -784,10 +785,31 @@ PRAGMA user_version = 29;
 CREATE UNIQUE INDEX IF NOT EXISTS I_NODES_MOVED
 ON NODES (wc_id, moved_to, op_depth);
 
+CREATE INDEX IF NOT EXISTS I_PRISTINE_MD5 ON PRISTINE (md5_checksum);
+
 /* Just to be sure clear out file external skels from pre 1.7.0 development
    working copies that were never updated by 1.7.0+ style clients */
 UPDATE nodes SET file_external=1 WHERE file_external IS NOT NULL;
 
+PRAGMA user_version = 30;
+
+-- STMT_UPGRADE_30_SELECT_CONFLICT_SEPARATE
+SELECT wc_id, local_relpath,
+  conflict_old, conflict_working, conflict_new, prop_reject, tree_conflict_data
+FROM actual_node
+WHERE conflict_old IS NOT NULL
+   OR conflict_working IS NOT NULL
+   OR conflict_new IS NOT NULL
+   OR prop_reject IS NOT NULL
+   OR tree_conflict_data IS NOT NULL
+ORDER by wc_id, local_relpath
+
+-- STMT_UPGRADE_30_SET_CONFLICT
+UPDATE actual_node SET conflict_data = ?3, conflict_old = NULL,
+  conflict_working = NULL, conflict_new = NULL, prop_reject = NULL,
+  tree_conflict_data = NULL
+WHERE wc_id = ?1 and local_relpath = ?2
+
 /* ------------------------------------------------------------------------- */
 
 /* Format YYY introduces new handling for conflict information.  */