You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2015/10/14 17:49:23 UTC

svn commit: r1708631 - in /subversion/branches/move-tracking-2/subversion: include/private/ libsvn_delta/ svnmover/

Author: julianfoad
Date: Wed Oct 14 15:49:22 2015
New Revision: 1708631

URL: http://svn.apache.org/viewvc?rev=1708631&view=rev
Log:
On the 'move-tracking-2' branch: More refactoring, disentangling the concept
of nested branches from the basic concept of branches, following r1708550.

* subversion/include/private/svn_branch.h,
  subversion/libsvn_delta/branch.c
  (svn_branch_state_t): Move the element mapping into a sub-structure.
  (svn_branch_root_eid,
   svn_branch_get_element_tree,
   svn_branch_get_element_tree_at_eid): New.
  (svn_branch_el_rev_content_t,
   svn_branch_el_rev_content_create,
   svn_branch_el_rev_content_dup,
   svn_branch_el_rev_content_equal): Move to element.c/h.
  (svn_branch_subtree_t,
   svn_branch_subtree_create,
   svn_branch_subtree_get_subbranch_at_eid): Move to branch_nested.c/h.
  (svn_branch_get_element_tree_at_eid): Rename from
    'svn_branch_get_subtree_n' and change the return type.
  (svn_branch_instantiate_elements,
   svn_branch_map_add_subtree): Change an input parameter type.
  (svn_branch_subtree_get_path_by_eid): Delete; the replacement is
    'svn_element_tree_get_path_by_eid'.
  (map_purge_orphans): Delete; the replacement is
    'svn_element_tree_purge_orphans'.

* subversion/include/private/svn_branch_nested.h,
  subversion/libsvn_delta/branch_nested.c
  (svn_branch_subtree_t,
   svn_branch_subtree_create,
  (svn_branch_subtree_get_subbranch_at_eid): Moved from branch.c/h.

* subversion/include/private/svn_element.h,
  subversion/libsvn_delta/element.c
  (svn_branch_el_rev_content_t,
   svn_branch_el_rev_content_create,
   svn_branch_el_rev_content_dup,
   svn_branch_el_rev_content_equal): Move from branch.c/h.
  (svn_element_tree_t,
   svn_element_tree_create,
   svn_element_tree_get,
   svn_element_tree_set,
   svn_element_tree_purge_orphans,
   svn_element_tree_get_path_by_eid): New.

* subversion/libsvn_delta/compat3e.c
  Update all callers/users.

* subversion/svnmover/svnmover.c
  Update all callers/users.

Modified:
    subversion/branches/move-tracking-2/subversion/include/private/svn_branch.h
    subversion/branches/move-tracking-2/subversion/include/private/svn_branch_nested.h
    subversion/branches/move-tracking-2/subversion/include/private/svn_element.h
    subversion/branches/move-tracking-2/subversion/libsvn_delta/branch.c
    subversion/branches/move-tracking-2/subversion/libsvn_delta/branch_nested.c
    subversion/branches/move-tracking-2/subversion/libsvn_delta/compat3e.c
    subversion/branches/move-tracking-2/subversion/libsvn_delta/element.c
    subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c

Modified: subversion/branches/move-tracking-2/subversion/include/private/svn_branch.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/include/private/svn_branch.h?rev=1708631&r1=1708630&r2=1708631&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/include/private/svn_branch.h (original)
+++ subversion/branches/move-tracking-2/subversion/include/private/svn_branch.h Wed Oct 14 15:49:22 2015
@@ -231,17 +231,11 @@ struct svn_branch_state_t
   /* (REV = -1 means "in this txn") */
   svn_branch_rev_bid_t *predecessor;
 
-  /* The EID of its pathwise root element. */
-  int root_eid;
-
   /* The revision to which this branch state belongs */
   svn_branch_revision_root_t *rev_root;
 
   /* EID -> svn_branch_el_rev_content_t mapping. */
-  /* ### TODO: This should use an svn_branch_subtree_t instead of E_MAP and
-   *     ROOT_EID.
-   *     And a whole bunch of methods would be common to both. */
-  apr_hash_t *e_map;
+  svn_element_tree_t *element_tree;
 
 };
 
@@ -270,6 +264,11 @@ const char *
 svn_branch_get_id(svn_branch_state_t *branch,
                   apr_pool_t *result_pool);
 
+/* Return the element id of the root element of BRANCH.
+ */
+int
+svn_branch_root_eid(const svn_branch_state_t *branch);
+
 /* Return the id of the branch nested in OUTER_BID at element OUTER_EID.
  *
  * For a top-level branch, OUTER_BID is null and OUTER_EID is the
@@ -397,95 +396,13 @@ svn_branch_rev_bid_t *
 svn_branch_rev_bid_dup(const svn_branch_rev_bid_t *old_id,
                        apr_pool_t *result_pool);
 
-/* The content (parent, name and payload) of an element-revision.
- * In other words, an el-rev node in a (mixed-rev) directory-tree.
- */
-typedef struct svn_branch_el_rev_content_t
-{
-  /* eid of the parent element, or -1 if this is the root element */
-  int parent_eid;
-  /* struct svn_branch_element_t *parent_element; */
-  /* element name, or "" for root element; never null */
-  const char *name;
-  /* payload (kind, props, text, ...) */
-  svn_element_payload_t *payload;
-
-} svn_branch_el_rev_content_t;
-
-/* Return a new content object constructed with deep copies of PARENT_EID,
- * NAME and PAYLOAD, allocated in RESULT_POOL.
- */
-svn_branch_el_rev_content_t *
-svn_branch_el_rev_content_create(svn_branch_eid_t parent_eid,
-                                 const char *name,
-                                 const svn_element_payload_t *payload,
-                                 apr_pool_t *result_pool);
-
-/* Return a deep copy of OLD, allocated in RESULT_POOL.
- */
-svn_branch_el_rev_content_t *
-svn_branch_el_rev_content_dup(const svn_branch_el_rev_content_t *old,
-                              apr_pool_t *result_pool);
-
-/* Return TRUE iff CONTENT_LEFT is the same as CONTENT_RIGHT. */
-svn_boolean_t
-svn_branch_el_rev_content_equal(const svn_branch_el_rev_content_t *content_left,
-                                const svn_branch_el_rev_content_t *content_right,
-                                apr_pool_t *scratch_pool);
-
-
-/* Describe a subtree of elements.
- *
- * A subtree is described by the content of element ROOT_EID in E_MAP,
- * and its children (as determined by their parent links) and their names
- * and their content recursively. For the element ROOT_EID itself, only
- * its content is relevant; its parent and name are to be ignored.
- *
- * E_MAP may also contain entries that are not part of the subtree. Thus,
- * to select a sub-subtree, it is only necessary to change ROOT_EID.
- *
- * The EIDs used in here may be considered either as global EIDs (known to
- * the repo), or as local stand-alone EIDs (in their own local name-space),
- * according to the context.
- *
- * ### TODO: This should be used in the implementation of svn_branch_state_t.
- *     A whole bunch of methods would be common to both.
- */
-typedef struct svn_branch_subtree_t
-{
-  svn_branch_rev_bid_t *predecessor;
-
-  /* EID -> svn_branch_el_rev_content_t mapping. */
-  apr_hash_t *e_map;
-
-  /* Subtree root EID. (ROOT_EID must be an existing key in E_MAP.) */
-  int root_eid;
 
-  /* Subbranches to be included: each subbranch-root element in E_MAP
-     should be mapped here.
-
-     A mapping of (int)EID -> (svn_branch_subtree_t *). */
-  apr_hash_t *subbranches;
-} svn_branch_subtree_t;
-
-/* Create an empty subtree (no elements populated, not even ROOT_EID).
- *
- * The result contains a *shallow* copy of E_MAP, or a new empty mapping
- * if E_MAP is null.
+/* Return the element-tree of BRANCH.
  */
-svn_branch_subtree_t *
-svn_branch_subtree_create(apr_hash_t *e_map,
-                          int root_eid,
-                          apr_pool_t *result_pool);
+const svn_element_tree_t *
+svn_branch_get_element_tree(svn_branch_state_t *branch);
 
-/* Return the subbranch rooted at SUBTREE:EID, or NULL if that is
- * not a subbranch root. */
-svn_branch_subtree_t *
-svn_branch_subtree_get_subbranch_at_eid(svn_branch_subtree_t *subtree,
-                                        int eid,
-                                        apr_pool_t *result_pool);
-
-/* Return the subtree of BRANCH rooted at EID.
+/* Return the element-tree within BRANCH rooted at EID.
  *
  * The result is limited by the lifetime of BRANCH. It includes a shallow
  * copy of the element maps in BRANCH: the hash table is
@@ -493,10 +410,10 @@ svn_branch_subtree_get_subbranch_at_eid(
  * It assumes that modifications on a svn_branch_state_t treat element
  * map keys and values as immutable -- which they do.
  */
-svn_branch_subtree_t *
-svn_branch_get_subtree_n(svn_branch_state_t *branch,
-                       int eid,
-                       apr_pool_t *result_pool);
+svn_element_tree_t *
+svn_branch_get_element_tree_at_eid(svn_branch_state_t *branch,
+                                   int eid,
+                                   apr_pool_t *result_pool);
 
 /* Declare that the following function requires/implies that in BRANCH's
  * mapping, for each existing element, the parent also exists.
@@ -551,7 +468,7 @@ svn_branch_purge(svn_branch_state_t *bra
  */
 svn_error_t *
 svn_branch_instantiate_elements(svn_branch_state_t *to_branch,
-                                svn_branch_subtree_t elements,
+                                const svn_element_tree_t *elements,
                                 apr_pool_t *scratch_pool);
 
 /* Create a copy of NEW_SUBTREE in TO_BRANCH.
@@ -570,19 +487,9 @@ svn_branch_map_add_subtree(svn_branch_st
                            int to_eid,
                            svn_branch_eid_t new_parent_eid,
                            const char *new_name,
-                           svn_branch_subtree_t new_subtree,
+                           svn_element_tree_t *new_subtree,
                            apr_pool_t *scratch_pool);
 
-/* Return the subtree-relative path of element EID in SUBTREE.
- *
- * If the element EID does not currently exist in SUBTREE, return NULL.
- *
- * ### TODO: Clarify sequencing requirements.
- */
-const char *
-svn_branch_subtree_get_path_by_eid(const svn_branch_subtree_t *subtree,
-                                   int eid,
-                                   apr_pool_t *result_pool);
 /* Return the branch-relative path of element EID in BRANCH.
  *
  * If the element EID does not currently exist in BRANCH, return NULL.

Modified: subversion/branches/move-tracking-2/subversion/include/private/svn_branch_nested.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/include/private/svn_branch_nested.h?rev=1708631&r1=1708630&r2=1708631&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/include/private/svn_branch_nested.h (original)
+++ subversion/branches/move-tracking-2/subversion/include/private/svn_branch_nested.h Wed Oct 14 15:49:22 2015
@@ -138,6 +138,32 @@ svn_branch_get_subbranch_at_eid(svn_bran
                                 int eid,
                                 apr_pool_t *scratch_pool);
 
+/* A subtree of a branch, including any nested branches.
+ */
+typedef struct svn_branch_subtree_t
+{
+  svn_branch_rev_bid_t *predecessor;
+
+  /* EID -> svn_branch_el_rev_content_t mapping. */
+  svn_element_tree_t *tree;
+
+  /* Subbranches to be included: each subbranch-root element in E_MAP
+     should be mapped here.
+
+     A mapping of (int)EID -> (svn_branch_subtree_t *). */
+  apr_hash_t *subbranches;
+} svn_branch_subtree_t;
+
+/* Create an empty subtree (no elements populated, not even ROOT_EID).
+ *
+ * The result contains a *shallow* copy of E_MAP, or a new empty mapping
+ * if E_MAP is null.
+ */
+svn_branch_subtree_t *
+svn_branch_subtree_create(apr_hash_t *e_map,
+                          int root_eid,
+                          apr_pool_t *result_pool);
+
 /* Return the subtree of BRANCH rooted at EID.
  * Recursive: includes subbranches.
  *
@@ -152,6 +178,13 @@ svn_branch_get_subtree(svn_branch_state_
                        int eid,
                        apr_pool_t *result_pool);
 
+/* Return the subbranch rooted at SUBTREE:EID, or NULL if that is
+ * not a subbranch root. */
+svn_branch_subtree_t *
+svn_branch_subtree_get_subbranch_at_eid(svn_branch_subtree_t *subtree,
+                                        int eid,
+                                        apr_pool_t *result_pool);
+
 /* Instantiate elements in a branch.
  *
  * In TO_BRANCH, instantiate (or alter, if existing) each element of

Modified: subversion/branches/move-tracking-2/subversion/include/private/svn_element.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/include/private/svn_element.h?rev=1708631&r1=1708630&r2=1708631&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/include/private/svn_element.h (original)
+++ subversion/branches/move-tracking-2/subversion/include/private/svn_element.h Wed Oct 14 15:49:22 2015
@@ -206,6 +206,135 @@ svn_element_payload_create_symlink(apr_h
 /** @} */
 
 
+/*
+ * ========================================================================
+ * Element-Revision Content
+ * ========================================================================
+ *
+ * @defgroup svn_el_rev_content Element-Revision Content
+ * @{
+ */
+
+/* The content (parent, name and payload) of an element-revision.
+ * In other words, an el-rev node in a (mixed-rev) directory-tree.
+ */
+typedef struct svn_branch_el_rev_content_t
+{
+  /* eid of the parent element, or -1 if this is the root element */
+  int parent_eid;
+  /* element name, or "" for root element; never null */
+  const char *name;
+  /* payload (kind, props, text, ...) */
+  svn_element_payload_t *payload;
+
+} svn_branch_el_rev_content_t;
+
+/* Return a new content object constructed with deep copies of PARENT_EID,
+ * NAME and PAYLOAD, allocated in RESULT_POOL.
+ */
+svn_branch_el_rev_content_t *
+svn_branch_el_rev_content_create(int parent_eid,
+                                 const char *name,
+                                 const svn_element_payload_t *payload,
+                                 apr_pool_t *result_pool);
+
+/* Return a deep copy of OLD, allocated in RESULT_POOL.
+ */
+svn_branch_el_rev_content_t *
+svn_branch_el_rev_content_dup(const svn_branch_el_rev_content_t *old,
+                              apr_pool_t *result_pool);
+
+/* Return TRUE iff CONTENT_LEFT is the same as CONTENT_RIGHT. */
+svn_boolean_t
+svn_branch_el_rev_content_equal(const svn_branch_el_rev_content_t *content_left,
+                                const svn_branch_el_rev_content_t *content_right,
+                                apr_pool_t *scratch_pool);
+
+/** @} */
+
+
+/*
+ * ========================================================================
+ * Element Tree
+ * ========================================================================
+ *
+ * The elements in an Element Tree do not necessarily form a single,
+ * complete tree at all times.
+ *
+ * @defgroup svn_element_tree Element Tree
+ * @{
+ */
+
+/* A (sub)tree of elements.
+ *
+ * An element tree is described by the content of element ROOT_EID in E_MAP,
+ * and its children (as determined by their parent links) and their names
+ * and their content recursively. For the element ROOT_EID itself, only
+ * its content is relevant; its parent and name are to be ignored.
+ *
+ * E_MAP may also contain entries that are not part of the subtree. Thus,
+ * to select a sub-subtree, it is only necessary to change ROOT_EID.
+ *
+ * The EIDs used in here may be considered either as global EIDs (known to
+ * the repo), or as local stand-alone EIDs (in their own local name-space),
+ * according to the context.
+ */
+typedef struct svn_element_tree_t
+{
+  /* EID -> svn_branch_el_rev_content_t mapping. */
+  apr_hash_t *e_map;
+
+  /* Subtree root EID. (ROOT_EID must be an existing key in E_MAP.) */
+  int root_eid;
+
+} svn_element_tree_t;
+
+/* Create an element tree object.
+ *
+ * The result contains a *shallow* copy of E_MAP, or a new empty mapping
+ * if E_MAP is null.
+ */
+svn_element_tree_t *
+svn_element_tree_create(apr_hash_t *e_map,
+                        int root_eid,
+                        apr_pool_t *result_pool);
+
+svn_branch_el_rev_content_t *
+svn_element_tree_get(const svn_element_tree_t *tree,
+                     int eid);
+
+svn_error_t *
+svn_element_tree_set(svn_element_tree_t *tree,
+                     int eid,
+                     svn_branch_el_rev_content_t *element);
+
+/* Purge entries from E_MAP that don't connect, via parent directory hierarchy,
+ * to ROOT_EID. In other words, remove elements that have been implicitly
+ * deleted.
+ *
+ * ROOT_EID must be present in E_MAP.
+ *
+ * ### Does not detect cycles: current implementation will not purge a cycle
+ *     that is disconnected from ROOT_EID. This could be a problem.
+ */
+void
+svn_element_tree_purge_orphans(apr_hash_t *e_map,
+                               int root_eid,
+                               apr_pool_t *scratch_pool);
+
+/* Return the subtree-relative path of element EID in TREE.
+ *
+ * If the element EID does not currently exist in TREE, return NULL.
+ *
+ * ### TODO: Clarify sequencing requirements.
+ */
+const char *
+svn_element_tree_get_path_by_eid(const svn_element_tree_t *tree,
+                                 int eid,
+                                 apr_pool_t *result_pool);
+
+/** @} */
+
 
 #ifdef __cplusplus
 }

Modified: subversion/branches/move-tracking-2/subversion/libsvn_delta/branch.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_delta/branch.c?rev=1708631&r1=1708630&r2=1708631&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_delta/branch.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_delta/branch.c Wed Oct 14 15:49:22 2015
@@ -40,7 +40,7 @@
   ((eid) >= (branch)->rev_root->first_eid && (eid) < (branch)->rev_root->next_eid)
 
 #define IS_BRANCH_ROOT_EID(branch, eid) \
-  ((eid) == (branch)->root_eid)
+  ((eid) == (branch)->element_tree->root_eid)
 
 /* Is BRANCH1 the same branch as BRANCH2? Compare by full branch-ids; don't
    require identical branch objects. */
@@ -108,12 +108,13 @@ branch_finalize_eids(svn_branch_state_t
   apr_hash_index_t *hi;
 
   branch->bid = branch_finalize_bid(branch->bid, mapping_offset, scratch_pool);
-  if (branch->root_eid < -1)
+  if (branch->element_tree->root_eid < -1)
     {
-      branch->root_eid = mapping_offset - branch->root_eid;
+      branch->element_tree->root_eid
+        = mapping_offset - branch->element_tree->root_eid;
     }
 
-  for (hi = apr_hash_first(scratch_pool, branch->e_map);
+  for (hi = apr_hash_first(scratch_pool, branch->element_tree->e_map);
        hi; hi = apr_hash_next(hi))
     {
       int old_eid = svn_int_hash_this_key(hi);
@@ -123,8 +124,8 @@ branch_finalize_eids(svn_branch_state_t
         {
           int new_eid = mapping_offset - old_eid;
 
-          svn_int_hash_set(branch->e_map, old_eid, NULL);
-          svn_int_hash_set(branch->e_map, new_eid, element);
+          svn_element_tree_set(branch->element_tree, old_eid, NULL);
+          svn_element_tree_set(branch->element_tree, new_eid, element);
         }
       if (element->parent_eid < -1)
         {
@@ -205,10 +206,11 @@ assert_branch_state_invariants(const svn
 
   assert(branch->bid);
   assert(branch->rev_root);
-  assert(branch->e_map);
+  assert(branch->element_tree);
+  assert(branch->element_tree->e_map);
 
   /* Validate elements in the map */
-  for (hi = apr_hash_first(scratch_pool, branch->e_map);
+  for (hi = apr_hash_first(scratch_pool, branch->element_tree->e_map);
        hi; hi = apr_hash_next(hi))
     {
       branch_validate_element(branch, svn_int_hash_this_key(hi),
@@ -227,13 +229,25 @@ svn_branch_state_create(const char *bid,
 
   b->bid = apr_pstrdup(result_pool, bid);
   b->predecessor = svn_branch_rev_bid_dup(predecessor, result_pool);
-  b->root_eid = root_eid;
   b->rev_root = rev_root;
-  b->e_map = apr_hash_make(result_pool);
+  b->element_tree = svn_element_tree_create(NULL, root_eid, result_pool);
   assert_branch_state_invariants(b, result_pool);
   return b;
 }
 
+const char *
+svn_branch_get_id(svn_branch_state_t *branch,
+                  apr_pool_t *result_pool)
+{
+  return branch->bid;
+}
+
+int
+svn_branch_root_eid(const svn_branch_state_t *branch)
+{
+  return branch->element_tree->root_eid;
+}
+
 svn_branch_el_rev_id_t *
 svn_branch_el_rev_id_create(svn_branch_state_t *branch,
                             int eid,
@@ -302,64 +316,6 @@ svn_branch_rev_bid_dup(const svn_branch_
   return id;
 }
 
-svn_branch_el_rev_content_t *
-svn_branch_el_rev_content_create(svn_branch_eid_t parent_eid,
-                                 const char *name,
-                                 const svn_element_payload_t *payload,
-                                 apr_pool_t *result_pool)
-{
-  svn_branch_el_rev_content_t *content
-     = apr_palloc(result_pool, sizeof(*content));
-
-  content->parent_eid = parent_eid;
-  content->name = apr_pstrdup(result_pool, name);
-  content->payload = svn_element_payload_dup(payload, result_pool);
-  return content;
-}
-
-svn_branch_el_rev_content_t *
-svn_branch_el_rev_content_dup(const svn_branch_el_rev_content_t *old,
-                              apr_pool_t *result_pool)
-{
-  svn_branch_el_rev_content_t *content
-     = apr_pmemdup(result_pool, old, sizeof(*content));
-
-  content->name = apr_pstrdup(result_pool, old->name);
-  content->payload = svn_element_payload_dup(old->payload, result_pool);
-  return content;
-}
-
-svn_boolean_t
-svn_branch_el_rev_content_equal(const svn_branch_el_rev_content_t *content_left,
-                                const svn_branch_el_rev_content_t *content_right,
-                                apr_pool_t *scratch_pool)
-{
-  if (!content_left && !content_right)
-    {
-      return TRUE;
-    }
-  else if (!content_left || !content_right)
-    {
-      return FALSE;
-    }
-
-  if (content_left->parent_eid != content_right->parent_eid)
-    {
-      return FALSE;
-    }
-  if (strcmp(content_left->name, content_right->name) != 0)
-    {
-      return FALSE;
-    }
-  if (! svn_element_payload_equal(content_left->payload, content_right->payload,
-                                  scratch_pool))
-    {
-      return FALSE;
-    }
-
-  return TRUE;
-}
-
 
 /*
  * ========================================================================
@@ -367,28 +323,10 @@ svn_branch_el_rev_content_equal(const sv
  * ========================================================================
  */
 
-svn_branch_subtree_t *
-svn_branch_subtree_create(apr_hash_t *e_map,
-                          int root_eid,
-                          apr_pool_t *result_pool)
+const svn_element_tree_t *
+svn_branch_get_element_tree(svn_branch_state_t *branch)
 {
-  svn_branch_subtree_t *subtree = apr_pcalloc(result_pool, sizeof(*subtree));
-
-  subtree->e_map = e_map ? apr_hash_copy(result_pool, e_map)
-                         : apr_hash_make(result_pool);
-  subtree->root_eid = root_eid;
-  subtree->subbranches = apr_hash_make(result_pool);
-  return subtree;
-}
-
-svn_branch_subtree_t *
-svn_branch_subtree_get_subbranch_at_eid(svn_branch_subtree_t *subtree,
-                                        int eid,
-                                        apr_pool_t *result_pool)
-{
-  subtree = svn_int_hash_get(subtree->subbranches, eid);
-
-  return subtree;
+  return branch->element_tree;
 }
 
 /* Validate that ELEMENT is suitable for a mapping of BRANCH:EID.
@@ -418,14 +356,14 @@ branch_validate_element(const svn_branch
   if (element->payload->is_subbranch_root)
     {
       /* a subbranch root element must not be the branch root element */
-      SVN_ERR_ASSERT_NO_RETURN(eid != branch->root_eid);
+      SVN_ERR_ASSERT_NO_RETURN(! IS_BRANCH_ROOT_EID(branch, eid));
     }
 }
 
 apr_hash_t *
 svn_branch_get_elements(svn_branch_state_t *branch)
 {
-  return branch->e_map;
+  return branch->element_tree->e_map;
 }
 
 svn_branch_el_rev_content_t *
@@ -434,7 +372,7 @@ svn_branch_get_element(const svn_branch_
 {
   svn_branch_el_rev_content_t *element;
 
-  element = svn_int_hash_get(branch->e_map, eid);
+  element = svn_element_tree_get(branch->element_tree, eid);
 
   if (element)
     branch_validate_element(branch, eid, element);
@@ -452,13 +390,13 @@ branch_map_set(svn_branch_state_t *branc
                int eid,
                svn_branch_el_rev_content_t *element)
 {
-  apr_pool_t *map_pool = apr_hash_pool_get(branch->e_map);
+  apr_pool_t *map_pool = apr_hash_pool_get(branch->element_tree->e_map);
 
   SVN_ERR_ASSERT_NO_RETURN(EID_IS_ALLOCATED(branch, eid));
   if (element)
     branch_validate_element(branch, eid, element);
 
-  svn_int_hash_set(branch->e_map, eid, element);
+  svn_element_tree_set(branch->element_tree, eid, element);
   assert_branch_state_invariants(branch, map_pool);
 }
 
@@ -478,7 +416,7 @@ svn_branch_update_element(svn_branch_sta
                           const char *new_name,
                           const svn_element_payload_t *new_payload)
 {
-  apr_pool_t *map_pool = apr_hash_pool_get(branch->e_map);
+  apr_pool_t *map_pool = apr_hash_pool_get(branch->element_tree->e_map);
   svn_branch_el_rev_content_t *element
     = svn_branch_el_rev_content_create(new_parent_eid, new_name, new_payload,
                                        map_pool);
@@ -492,113 +430,39 @@ svn_branch_update_element(svn_branch_sta
   branch_map_set(branch, eid, element);
 }
 
-static void
-map_purge_orphans(apr_hash_t *e_map,
-                  int root_eid,
-                  apr_pool_t *scratch_pool);
-
-svn_branch_subtree_t *
-svn_branch_get_subtree_n(svn_branch_state_t *branch,
-                       int eid,
-                       apr_pool_t *result_pool)
+svn_element_tree_t *
+svn_branch_get_element_tree_at_eid(svn_branch_state_t *branch,
+                                   int eid,
+                                   apr_pool_t *result_pool)
 {
-  svn_branch_subtree_t *new_subtree;
+  svn_element_tree_t *new_subtree;
   svn_branch_el_rev_content_t *subtree_root_element;
 
   SVN_BRANCH_SEQUENCE_POINT(branch);
 
-  new_subtree = svn_branch_subtree_create(branch->e_map, eid,
-                                          result_pool);
-  new_subtree->predecessor = svn_branch_rev_bid_dup(branch->predecessor,
-                                                    result_pool);
+  new_subtree = svn_element_tree_create(branch->element_tree->e_map, eid,
+                                        result_pool);
 
   /* Purge orphans */
-  map_purge_orphans(new_subtree->e_map, new_subtree->root_eid, result_pool);
+  svn_element_tree_purge_orphans(new_subtree->e_map,
+                                 new_subtree->root_eid, result_pool);
 
   /* Remove 'parent' and 'name' attributes from subtree root element */
   subtree_root_element
-    = svn_int_hash_get(new_subtree->e_map, new_subtree->root_eid);
-  svn_int_hash_set(new_subtree->e_map, new_subtree->root_eid,
-                   svn_branch_el_rev_content_create(
-                     -1, "", subtree_root_element->payload, result_pool));
+    = svn_element_tree_get(new_subtree, new_subtree->root_eid);
+  svn_element_tree_set(new_subtree, new_subtree->root_eid,
+                       svn_branch_el_rev_content_create(
+                         -1, "", subtree_root_element->payload, result_pool));
 
   return new_subtree;
 }
 
-/* Purge entries from E_MAP that don't connect, via parent directory hierarchy,
- * to ROOT_EID. In other words, remove elements that have been implicitly
- * deleted.
- *
- * ROOT_EID must be present in E_MAP.
- *
- * ### Does not detect cycles: current implementation will not purge a cycle
- *     that is disconnected from ROOT_EID. This could be a problem.
- */
-static void
-map_purge_orphans(apr_hash_t *e_map,
-                  int root_eid,
-                  apr_pool_t *scratch_pool)
-{
-  apr_hash_index_t *hi;
-  svn_boolean_t changed;
-
-  SVN_ERR_ASSERT_NO_RETURN(svn_int_hash_get(e_map, root_eid));
-
-  do
-    {
-      changed = FALSE;
-
-      for (hi = apr_hash_first(scratch_pool, e_map);
-           hi; hi = apr_hash_next(hi))
-        {
-          int this_eid = svn_int_hash_this_key(hi);
-          svn_branch_el_rev_content_t *this_element = apr_hash_this_val(hi);
-
-          if (this_eid != root_eid)
-            {
-              svn_branch_el_rev_content_t *parent_element
-                = svn_int_hash_get(e_map, this_element->parent_eid);
-
-              /* Purge if parent is deleted */
-              if (! parent_element)
-                {
-                  SVN_DBG(("purge orphan: e%d", this_eid));
-                  svn_int_hash_set(e_map, this_eid, NULL);
-                  changed = TRUE;
-                }
-              else
-                SVN_ERR_ASSERT_NO_RETURN(
-                  ! parent_element->payload->is_subbranch_root);
-            }
-        }
-    }
-  while (changed);
-}
-
 void
 svn_branch_purge(svn_branch_state_t *branch,
                  apr_pool_t *scratch_pool)
 {
-  map_purge_orphans(branch->e_map, branch->root_eid, scratch_pool);
-}
-
-const char *
-svn_branch_subtree_get_path_by_eid(const svn_branch_subtree_t *subtree,
-                                   int eid,
-                                   apr_pool_t *result_pool)
-{
-  const char *path = "";
-  svn_branch_el_rev_content_t *element;
-
-  for (; eid != subtree->root_eid; eid = element->parent_eid)
-    {
-      element = svn_int_hash_get(subtree->e_map, eid);
-      if (! element)
-        return NULL;
-      path = svn_relpath_join(element->name, path, result_pool);
-    }
-  SVN_ERR_ASSERT_NO_RETURN(eid == subtree->root_eid);
-  return path;
+  svn_element_tree_purge_orphans(branch->element_tree->e_map,
+                                 branch->element_tree->root_eid, scratch_pool);
 }
 
 const char *
@@ -630,7 +494,7 @@ svn_branch_get_eid_by_path(const svn_bra
   apr_hash_index_t *hi;
 
   /* ### This is a crude, linear search */
-  for (hi = apr_hash_first(scratch_pool, branch->e_map);
+  for (hi = apr_hash_first(scratch_pool, branch->element_tree->e_map);
        hi; hi = apr_hash_next(hi))
     {
       int eid = svn_int_hash_this_key(hi);
@@ -656,19 +520,12 @@ svn_branch_map_add_subtree(svn_branch_st
                            int to_eid,
                            svn_branch_eid_t new_parent_eid,
                            const char *new_name,
-                           svn_branch_subtree_t new_subtree,
+                           svn_element_tree_t *new_subtree,
                            apr_pool_t *scratch_pool)
 {
   apr_hash_index_t *hi;
   svn_branch_el_rev_content_t *new_root_content;
 
-  if (new_subtree.subbranches && apr_hash_count(new_subtree.subbranches))
-    {
-      return svn_error_createf(SVN_ERR_BRANCHING, NULL,
-                               _("Adding or copying a subtree containing "
-                                 "subbranches is not implemented"));
-    }
-
   /* Get a new EID for the root element, if not given. */
   if (to_eid == -1)
     {
@@ -676,27 +533,27 @@ svn_branch_map_add_subtree(svn_branch_st
     }
 
   /* Create the new subtree root element */
-  new_root_content = svn_int_hash_get(new_subtree.e_map, new_subtree.root_eid);
+  new_root_content = svn_element_tree_get(new_subtree, new_subtree->root_eid);
   svn_branch_update_element(to_branch, to_eid,
-                              new_parent_eid, new_name,
-                              new_root_content->payload);
+                            new_parent_eid, new_name,
+                            new_root_content->payload);
 
   /* Process its immediate children */
-  for (hi = apr_hash_first(scratch_pool, new_subtree.e_map);
+  for (hi = apr_hash_first(scratch_pool, new_subtree->e_map);
        hi; hi = apr_hash_next(hi))
     {
       int this_from_eid = svn_int_hash_this_key(hi);
       svn_branch_el_rev_content_t *from_element = apr_hash_this_val(hi);
 
-      if (from_element->parent_eid == new_subtree.root_eid)
+      if (from_element->parent_eid == new_subtree->root_eid)
         {
-          svn_branch_subtree_t this_subtree;
+          svn_element_tree_t *this_subtree;
 
           /* Recurse. (We don't try to check whether it's a directory node,
              as we might not have the node kind in the map.) */
-          this_subtree.e_map = new_subtree.e_map;
-          this_subtree.root_eid = this_from_eid;
-          this_subtree.subbranches = apr_hash_make(scratch_pool);
+          this_subtree
+            = svn_element_tree_create(new_subtree->e_map, this_from_eid,
+                                      scratch_pool);
           SVN_ERR(svn_branch_map_add_subtree(to_branch, -1 /*to_eid*/,
                                              to_eid, from_element->name,
                                              this_subtree, scratch_pool));
@@ -708,13 +565,13 @@ svn_branch_map_add_subtree(svn_branch_st
 
 svn_error_t *
 svn_branch_instantiate_elements(svn_branch_state_t *to_branch,
-                                svn_branch_subtree_t elements,
+                                const svn_element_tree_t *elements,
                                 apr_pool_t *scratch_pool)
 {
   apr_hash_index_t *hi;
 
   /* Instantiate all the elements of NEW_SUBTREE */
-  for (hi = apr_hash_first(scratch_pool, elements.e_map);
+  for (hi = apr_hash_first(scratch_pool, elements->e_map);
        hi; hi = apr_hash_next(hi))
     {
       int this_eid = svn_int_hash_this_key(hi);
@@ -722,7 +579,8 @@ svn_branch_instantiate_elements(svn_bran
 
       branch_map_set(to_branch, this_eid,
                      svn_branch_el_rev_content_dup(
-                       this_element, apr_hash_pool_get(to_branch->e_map)));
+                       this_element,
+                       apr_hash_pool_get(to_branch->element_tree->e_map)));
     }
 
   return SVN_NO_ERROR;
@@ -763,7 +621,7 @@ svn_branch_revision_root_delete_branch(
         {
           SVN_DBG(("deleting branch b%s e%d",
                    svn_branch_get_id(bi->val, bi->iterpool),
-                   bi->val->root_eid));
+                   bi->val->element_tree->root_eid));
           svn_sort__array_delete(rev_root->branches, bi->i, 1);
           break;
         }
@@ -1022,14 +880,15 @@ svn_branch_state_serialize(svn_stream_t
   SVN_ERR(svn_stream_printf(stream, scratch_pool,
                             "%s root-eid %d num-eids %d%s\n",
                             svn_branch_get_id(branch, scratch_pool),
-                            branch->root_eid,
-                            apr_hash_count(branch->e_map),
+                            branch->element_tree->root_eid,
+                            apr_hash_count(branch->element_tree->e_map),
                             predecessor_str));
 
-  map_purge_orphans(branch->e_map, branch->root_eid, scratch_pool);
+  svn_element_tree_purge_orphans(branch->element_tree->e_map,
+                                 branch->element_tree->root_eid, scratch_pool);
 
-  for (SVN_HASH_ITER_SORTED(hi, branch->e_map, sort_compare_items_by_eid,
-                            scratch_pool))
+  for (SVN_HASH_ITER_SORTED(hi, branch->element_tree->e_map,
+                            sort_compare_items_by_eid, scratch_pool))
     {
       int eid = *(const int *)hi->key;
       svn_branch_el_rev_content_t *element = svn_branch_get_element(branch, eid);
@@ -1083,10 +942,3 @@ svn_branch_revision_root_serialize(svn_s
  * ========================================================================
  */
 
-const char *
-svn_branch_get_id(svn_branch_state_t *branch,
-                  apr_pool_t *result_pool)
-{
-  return branch->bid;
-}
-

Modified: subversion/branches/move-tracking-2/subversion/libsvn_delta/branch_nested.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_delta/branch_nested.c?rev=1708631&r1=1708630&r2=1708631&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_delta/branch_nested.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_delta/branch_nested.c Wed Oct 14 15:49:22 2015
@@ -121,7 +121,7 @@ svn_branch_get_immediate_subbranches(svn
   const char *branch_id = svn_branch_get_id(branch, scratch_pool);
   apr_hash_index_t *hi;
 
-  for (hi = apr_hash_first(scratch_pool, branch->e_map);
+  for (hi = apr_hash_first(scratch_pool, svn_branch_get_elements(branch));
        hi; hi = apr_hash_next(hi))
     {
       int eid = svn_int_hash_this_key(hi);
@@ -143,6 +143,18 @@ svn_branch_get_immediate_subbranches(svn
 }
 
 svn_branch_subtree_t *
+svn_branch_subtree_create(apr_hash_t *e_map,
+                          int root_eid,
+                          apr_pool_t *result_pool)
+{
+  svn_branch_subtree_t *subtree = apr_pcalloc(result_pool, sizeof(*subtree));
+
+  subtree->tree = svn_element_tree_create(e_map, root_eid, result_pool);
+  subtree->subbranches = apr_hash_make(result_pool);
+  return subtree;
+}
+
+svn_branch_subtree_t *
 svn_branch_get_subtree(svn_branch_state_t *branch,
                        int eid,
                        apr_pool_t *result_pool)
@@ -153,7 +165,11 @@ svn_branch_get_subtree(svn_branch_state_
   SVN_BRANCH_SEQUENCE_POINT(branch);
 
   new_subtree
-    = svn_branch_get_subtree_n(branch, eid, result_pool);
+    = svn_branch_subtree_create(
+        svn_branch_get_element_tree_at_eid(branch, eid, result_pool)->e_map,
+        eid, result_pool);
+  new_subtree->predecessor = svn_branch_rev_bid_dup(branch->predecessor,
+                                                    result_pool);
 
   /* Add subbranches */
   for (SVN_ARRAY_ITER(bi, svn_branch_get_immediate_subbranches(
@@ -167,14 +183,15 @@ svn_branch_get_subtree(svn_branch_state_
       svn_branch_id_unnest(&outer_bid, &outer_eid, subbranch->bid,
                            bi->iterpool);
       subbranch_relpath_in_subtree
-        = svn_branch_subtree_get_path_by_eid(new_subtree, outer_eid,
-                                             bi->iterpool);
+        = svn_element_tree_get_path_by_eid(new_subtree->tree, outer_eid,
+                                           bi->iterpool);
 
       /* Is it pathwise at or below EID? If so, add it into the subtree. */
       if (subbranch_relpath_in_subtree)
         {
           svn_branch_subtree_t *this_subtree
-            = svn_branch_get_subtree(subbranch, subbranch->root_eid, result_pool);
+            = svn_branch_get_subtree(subbranch, svn_branch_root_eid(subbranch),
+                                     result_pool);
 
           svn_int_hash_set(new_subtree->subbranches, outer_eid,
                            this_subtree);
@@ -183,12 +200,23 @@ svn_branch_get_subtree(svn_branch_state_
   return new_subtree;
 }
 
+svn_branch_subtree_t *
+svn_branch_subtree_get_subbranch_at_eid(svn_branch_subtree_t *subtree,
+                                        int eid,
+                                        apr_pool_t *result_pool)
+{
+  subtree = svn_int_hash_get(subtree->subbranches, eid);
+
+  return subtree;
+}
+
 svn_error_t *
 svn_branch_instantiate_elements_r(svn_branch_state_t *to_branch,
                                   svn_branch_subtree_t elements,
                                   apr_pool_t *scratch_pool)
 {
-  SVN_ERR(svn_branch_instantiate_elements(to_branch, elements, scratch_pool));
+  SVN_ERR(svn_branch_instantiate_elements(to_branch, elements.tree,
+                                          scratch_pool));
 
   /* branch any subbranches */
   {
@@ -207,7 +235,7 @@ svn_branch_instantiate_elements_r(svn_br
         new_branch = svn_branch_add_new_branch(new_branch_id,
                                                to_branch->rev_root,
                                                this_subtree->predecessor,
-                                               this_subtree->root_eid,
+                                               this_subtree->tree->root_eid,
                                                bi->iterpool);
 
         SVN_ERR(svn_branch_instantiate_elements_r(new_branch, *this_subtree,

Modified: subversion/branches/move-tracking-2/subversion/libsvn_delta/compat3e.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_delta/compat3e.c?rev=1708631&r1=1708630&r2=1708631&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_delta/compat3e.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_delta/compat3e.c Wed Oct 14 15:49:22 2015
@@ -1188,7 +1188,7 @@ editor3_open_branch(void *baton,
     {
       SVN_ERR_ASSERT(predecessor->rev == new_branch->predecessor->rev);
       SVN_ERR_ASSERT(strcmp(predecessor->bid, new_branch->predecessor->bid) == 0);
-      SVN_ERR_ASSERT(root_eid == new_branch->root_eid);
+      SVN_ERR_ASSERT(root_eid == svn_branch_root_eid(new_branch));
       return SVN_NO_ERROR;
     }
 
@@ -1326,15 +1326,24 @@ copy_subtree(const svn_branch_el_rev_id_
              const char *to_name,
              apr_pool_t *scratch_pool)
 {
+  svn_branch_subtree_t *new_subtree;
+
   SVN_DBG(("cp subtree from e%d to e%d/%s",
            from_el_rev->eid, to_parent_eid, to_name));
 
+  new_subtree = svn_branch_get_subtree(from_el_rev->branch, from_el_rev->eid,
+                                       scratch_pool);
+  if (new_subtree->subbranches && apr_hash_count(new_subtree->subbranches))
+    {
+      return svn_error_createf(SVN_ERR_BRANCHING, NULL,
+                               _("Adding or copying a subtree containing "
+                                 "subbranches is not implemented"));
+    }
+
   /* copy the subtree, assigning new EIDs */
   SVN_ERR(svn_branch_map_add_subtree(to_branch, -1 /*to_eid*/,
                                      to_parent_eid, to_name,
-                                     *svn_branch_get_subtree(
-                                       from_el_rev->branch, from_el_rev->eid,
-                                       scratch_pool),
+                                     new_subtree->tree,
                                      scratch_pool));
 
   /* handle any subbranches under FROM_BRANCH:FROM_EID */
@@ -1405,7 +1414,7 @@ convert_branch_to_paths(apr_hash_t *path
 
   /* assert(branch is at a sequence point); */
 
-  for (hi = apr_hash_first(scratch_pool, branch->e_map);
+  for (hi = apr_hash_first(scratch_pool, svn_branch_get_elements(branch));
        hi; hi = apr_hash_next(hi))
     {
       int eid = *(const int *)apr_hash_this_key(hi);
@@ -1419,7 +1428,7 @@ convert_branch_to_paths(apr_hash_t *path
          be specifying the element's payload.
        */
       if (! ba
-          || eid == branch->root_eid)
+          || eid == svn_branch_root_eid(branch))
         {
           ba = svn_branch_el_rev_id_create(branch, eid, branch->rev_root->rev,
                                            result_pool);

Modified: subversion/branches/move-tracking-2/subversion/libsvn_delta/element.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_delta/element.c?rev=1708631&r1=1708630&r2=1708631&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_delta/element.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_delta/element.c Wed Oct 14 15:49:22 2015
@@ -29,6 +29,7 @@
 #include "svn_string.h"
 #include "svn_props.h"
 #include "svn_dirent_uri.h"
+#include "svn_iter.h"
 
 #include "private/svn_element.h"
 #include "svn_private_config.h"
@@ -255,3 +256,152 @@ svn_element_payload_create_symlink(apr_h
   return new_payload;
 }
 
+svn_branch_el_rev_content_t *
+svn_branch_el_rev_content_create(int parent_eid,
+                                 const char *name,
+                                 const svn_element_payload_t *payload,
+                                 apr_pool_t *result_pool)
+{
+  svn_branch_el_rev_content_t *content
+     = apr_palloc(result_pool, sizeof(*content));
+
+  content->parent_eid = parent_eid;
+  content->name = apr_pstrdup(result_pool, name);
+  content->payload = svn_element_payload_dup(payload, result_pool);
+  return content;
+}
+
+svn_branch_el_rev_content_t *
+svn_branch_el_rev_content_dup(const svn_branch_el_rev_content_t *old,
+                              apr_pool_t *result_pool)
+{
+  svn_branch_el_rev_content_t *content
+     = apr_pmemdup(result_pool, old, sizeof(*content));
+
+  content->name = apr_pstrdup(result_pool, old->name);
+  content->payload = svn_element_payload_dup(old->payload, result_pool);
+  return content;
+}
+
+svn_boolean_t
+svn_branch_el_rev_content_equal(const svn_branch_el_rev_content_t *content_left,
+                                const svn_branch_el_rev_content_t *content_right,
+                                apr_pool_t *scratch_pool)
+{
+  if (!content_left && !content_right)
+    {
+      return TRUE;
+    }
+  else if (!content_left || !content_right)
+    {
+      return FALSE;
+    }
+
+  if (content_left->parent_eid != content_right->parent_eid)
+    {
+      return FALSE;
+    }
+  if (strcmp(content_left->name, content_right->name) != 0)
+    {
+      return FALSE;
+    }
+  if (! svn_element_payload_equal(content_left->payload, content_right->payload,
+                                  scratch_pool))
+    {
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+svn_element_tree_t *
+svn_element_tree_create(apr_hash_t *e_map,
+                        int root_eid,
+                        apr_pool_t *result_pool)
+{
+  svn_element_tree_t *element_tree
+    = apr_pcalloc(result_pool, sizeof(*element_tree));
+
+  element_tree->e_map = e_map ? apr_hash_copy(result_pool, e_map)
+                              : apr_hash_make(result_pool);
+  element_tree->root_eid = root_eid;
+  return element_tree;
+}
+
+svn_branch_el_rev_content_t *
+svn_element_tree_get(const svn_element_tree_t *tree,
+                     int eid)
+{
+  return svn_int_hash_get(tree->e_map, eid);
+}
+
+svn_error_t *
+svn_element_tree_set(svn_element_tree_t *tree,
+                     int eid,
+                     svn_branch_el_rev_content_t *element)
+{
+  svn_int_hash_set(tree->e_map, eid, element);
+
+  return SVN_NO_ERROR;
+}
+
+void
+svn_element_tree_purge_orphans(apr_hash_t *e_map,
+                               int root_eid,
+                               apr_pool_t *scratch_pool)
+{
+  apr_hash_index_t *hi;
+  svn_boolean_t changed;
+
+  SVN_ERR_ASSERT_NO_RETURN(svn_int_hash_get(e_map, root_eid));
+
+  do
+    {
+      changed = FALSE;
+
+      for (hi = apr_hash_first(scratch_pool, e_map);
+           hi; hi = apr_hash_next(hi))
+        {
+          int this_eid = svn_int_hash_this_key(hi);
+          svn_branch_el_rev_content_t *this_element = apr_hash_this_val(hi);
+
+          if (this_eid != root_eid)
+            {
+              svn_branch_el_rev_content_t *parent_element
+                = svn_int_hash_get(e_map, this_element->parent_eid);
+
+              /* Purge if parent is deleted */
+              if (! parent_element)
+                {
+                  SVN_DBG(("purge orphan: e%d", this_eid));
+                  svn_int_hash_set(e_map, this_eid, NULL);
+                  changed = TRUE;
+                }
+              else
+                SVN_ERR_ASSERT_NO_RETURN(
+                  ! parent_element->payload->is_subbranch_root);
+            }
+        }
+    }
+  while (changed);
+}
+
+const char *
+svn_element_tree_get_path_by_eid(const svn_element_tree_t *tree,
+                                 int eid,
+                                 apr_pool_t *result_pool)
+{
+  const char *path = "";
+  svn_branch_el_rev_content_t *element;
+
+  for (; eid != tree->root_eid; eid = element->parent_eid)
+    {
+      element = svn_element_tree_get(tree, eid);
+      if (! element)
+        return NULL;
+      path = svn_relpath_join(element->name, path, result_pool);
+    }
+  SVN_ERR_ASSERT_NO_RETURN(eid == tree->root_eid);
+  return path;
+}
+

Modified: subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c?rev=1708631&r1=1708630&r2=1708631&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c (original)
+++ subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c Wed Oct 14 15:49:22 2015
@@ -91,7 +91,7 @@ static const svn_token_map_t ui_mode_map
       {NULL, SVN_TOKEN_UNKNOWN} };
 
 #define is_branch_root_element(branch, eid) \
-  ((branch)->root_eid == (eid))
+  (svn_branch_root_eid(branch) == (eid))
 
 /* Is BRANCH1 the same branch as BRANCH2? Compare by full branch-ids; don't
    require identical branch objects. */
@@ -287,13 +287,14 @@ element_differences(apr_hash_t **diff_p,
            right->eid));*/
 
   for (SVN_HASH_ITER(hi, scratch_pool,
-                     apr_hash_overlay(scratch_pool, left->e_map, right->e_map)))
+                     apr_hash_overlay(scratch_pool,
+                                      left->tree->e_map, right->tree->e_map)))
     {
       int e = svn_int_hash_this_key(hi->apr_hi);
       svn_branch_el_rev_content_t *element_left
-        = svn_int_hash_get(left->e_map, e);
+        = svn_element_tree_get(left->tree, e);
       svn_branch_el_rev_content_t *element_right
-        = svn_int_hash_get(right->e_map, e);
+        = svn_element_tree_get(right->tree, e);
 
       /* If node payload is given by reference, resolve it to full payload */
       if (element_left)
@@ -401,7 +402,7 @@ svn_branch_replay(svn_editor3_t *editor,
                   svn_branch_subtree_t *s_right,
                   apr_pool_t *scratch_pool)
 {
-  assert((s_left && s_right) ? (s_left->root_eid == s_right->root_eid)
+  assert((s_left && s_right) ? (s_left->tree->root_eid == s_right->tree->root_eid)
                              : (s_left || s_right));
 
   if (s_right)
@@ -447,7 +448,7 @@ svn_branch_replay(svn_editor3_t *editor,
               SVN_ERR(svn_editor3_open_branch(editor, &edit_subbranch_id,
                                               this_s_right->predecessor,
                                               edit_branch_id, this_eid,
-                                              this_s_right->root_eid,
+                                              this_s_right->tree->root_eid,
                                               scratch_pool));
             }
 
@@ -475,10 +476,12 @@ replay(svn_editor3_t *editor,
        apr_pool_t *scratch_pool)
 {
   svn_branch_subtree_t *s_left
-    = left_branch ? svn_branch_get_subtree(left_branch, left_branch->root_eid,
+    = left_branch ? svn_branch_get_subtree(left_branch,
+                                           svn_branch_root_eid(left_branch),
                                            scratch_pool) : NULL;
   svn_branch_subtree_t *s_right
-    = right_branch ? svn_branch_get_subtree(right_branch, right_branch->root_eid,
+    = right_branch ? svn_branch_get_subtree(right_branch,
+                                            svn_branch_root_eid(right_branch),
                                             scratch_pool) : NULL;
 
   SVN_ERR_ASSERT(editor && edit_root_branch_id);
@@ -592,7 +595,7 @@ wc_commit(svn_revnum_t *new_rev_p,
          an independent new top-level branch number.) */
       svn_branch_rev_bid_eid_t *from
         = svn_branch_rev_bid_eid_create(wc->base->revision, wc->base->branch_id,
-                                        wc->base->branch->root_eid,
+                                        svn_branch_root_eid(wc->base->branch),
                                         scratch_pool);
 
       SVN_ERR(do_topbranch(&edit_root_branch_id, commit_editor,
@@ -894,7 +897,7 @@ list_branch_elements(svn_branch_state_t
   apr_hash_index_t *hi;
   SVN_ITER_T(int) *pi;
 
-  for (hi = apr_hash_first(scratch_pool, branch->e_map);
+  for (hi = apr_hash_first(scratch_pool, svn_branch_get_elements(branch));
        hi; hi = apr_hash_next(hi))
     {
       int eid = svn_int_hash_this_key(hi);
@@ -1023,7 +1026,7 @@ branch_id_str(svn_branch_state_t *branch
       return apr_psprintf(result_pool, "%-10s %-12s root=e%d",
                           svn_branch_get_id(branch, scratch_pool),
                           outer_el ? outer_el->name : "/",
-                          branch->root_eid);
+                          svn_branch_root_eid(branch));
     }
 }
 
@@ -1074,7 +1077,7 @@ list_branches(svn_branch_revision_root_t
     {
       svn_branch_state_t *branch = bi->val;
 
-      if (branch->root_eid != eid)
+      if (svn_branch_root_eid(branch) != eid)
         continue;
 
       SVN_ERR(list_branch(branch, with_elements, bi->iterpool));
@@ -1087,7 +1090,7 @@ list_branches(svn_branch_revision_root_t
       svn_branch_state_t *branch = bi->val;
 
       if (! svn_branch_get_element(branch, eid)
-          || branch->root_eid == eid)
+          || svn_branch_root_eid(branch) == eid)
         continue;
 
       if (! printed_header)
@@ -1391,15 +1394,15 @@ merge_subbranch(svn_editor3_t *editor,
 
   if (src_subbranch)
     subbr_src = svn_branch_el_rev_id_create(
-                  src_subbranch, src_subbranch->root_eid,
+                  src_subbranch, svn_branch_root_eid(src_subbranch),
                   src->rev, scratch_pool);
   if (tgt_subbranch)
     subbr_tgt = svn_branch_el_rev_id_create(
-                  tgt_subbranch, tgt_subbranch->root_eid,
+                  tgt_subbranch, svn_branch_root_eid(tgt_subbranch),
                   tgt->rev, scratch_pool);
   if (yca_subbranch)
     subbr_yca = svn_branch_el_rev_id_create(
-                  yca_subbranch, yca_subbranch->root_eid,
+                  yca_subbranch, svn_branch_root_eid(yca_subbranch),
                   yca->rev, scratch_pool);
 
   if (subbr_src && subbr_tgt && subbr_yca)  /* ?edit vs. ?edit */
@@ -1426,7 +1429,7 @@ merge_subbranch(svn_editor3_t *editor,
         = svn_branch_rev_bid_eid_create(src_subbranch->rev_root->rev,
                                         svn_branch_get_id(src_subbranch,
                                                           scratch_pool),
-                                        src_subbranch->root_eid,
+                                        svn_branch_root_eid(src_subbranch),
                                         scratch_pool);
 
       SVN_ERR(svn_editor3_branch(editor, NULL /*new_branch_id_p*/, from,
@@ -1730,15 +1733,16 @@ do_switch(svnmover_wc_t *wc,
   svn_boolean_t has_local_changes = TRUE /* ### wc_has_local_changes(wc) */;
 
   if (has_local_changes
-      && target_branch->root_eid != previous_base_br->root_eid)
+      && svn_branch_root_eid(target_branch)
+         != svn_branch_root_eid(previous_base_br))
     {
       return svn_error_createf(SVN_ERR_BRANCHING, NULL,
                                _("Cannot switch to branch '%s' and preserve "
                                  "local changes as the new root element e%d "
                                  "is not related to the old root element e%d"),
                                target_branch_id,
-                               target_branch->root_eid,
-                               previous_base_br->root_eid);
+                               svn_branch_root_eid(target_branch),
+                               svn_branch_root_eid(previous_base_br));
     }
 
   /* Complete the old edit drive into the 'WC' txn */
@@ -1753,14 +1757,14 @@ do_switch(svnmover_wc_t *wc,
 
       /* Merge changes from the old into the new WC */
       yca = svn_branch_el_rev_id_create(previous_base_br,
-                                        previous_base_br->root_eid,
+                                        svn_branch_root_eid(previous_base_br),
                                         previous_base_br->rev_root->rev,
                                         scratch_pool);
       src = svn_branch_el_rev_id_create(previous_working_br,
-                                        previous_working_br->root_eid,
+                                        svn_branch_root_eid(previous_working_br),
                                         SVN_INVALID_REVNUM, scratch_pool);
       tgt = svn_branch_el_rev_id_create(wc->working->branch,
-                                        wc->working->branch->root_eid,
+                                        svn_branch_root_eid(wc->working->branch),
                                         SVN_INVALID_REVNUM, scratch_pool);
       SVN_ERR(svn_branch_merge(wc->editor, src, tgt, yca,
                                scratch_pool));
@@ -1820,10 +1824,10 @@ subtree_diff(apr_hash_t **diff_changes,
           item->eid = eid;
           item->e0 = e0;
           item->e1 = e1;
-          item->relpath0 = e0 ? svn_branch_subtree_get_path_by_eid(
-                                  s_left, eid, result_pool) : NULL;
-          item->relpath1 = e1 ? svn_branch_subtree_get_path_by_eid(
-                                  s_right, eid, result_pool) : NULL;
+          item->relpath0 = e0 ? svn_element_tree_get_path_by_eid(
+                                  s_left->tree, eid, result_pool) : NULL;
+          item->relpath1 = e1 ? svn_element_tree_get_path_by_eid(
+                                  s_right->tree, eid, result_pool) : NULL;
           item->reparented = (e0 && e1 && e0->parent_eid != e1->parent_eid);
           item->renamed = (e0 && e1 && strcmp(e0->name, e1->name) != 0);
 
@@ -1882,8 +1886,8 @@ show_subtree_diff(svn_editor3_t *editor,
   apr_hash_t *diff_changes;
   SVN_ITER_T(diff_item_t) *ai;
 
-  SVN_ERR_ASSERT(left && left->root_eid >= 0
-                 && right && right->root_eid >= 0);
+  SVN_ERR_ASSERT(left && left->tree->root_eid >= 0
+                 && right && right->tree->root_eid >= 0);
 
   SVN_ERR(subtree_diff(&diff_changes, editor, left, right,
                        scratch_pool, scratch_pool));
@@ -1993,11 +1997,11 @@ subtree_diff_r(svn_editor3_t *editor,
 {
   const char *left_str
     = left ? apr_psprintf(scratch_pool, "r%ld:%s:e%d at /%s",
-                          left_rev, left_bid, left->root_eid, left_rrpath)
+                          left_rev, left_bid, left->tree->root_eid, left_rrpath)
            : NULL;
   const char *right_str
     = right ? apr_psprintf(scratch_pool, "r%ld:%s:e%d at /%s",
-                           right_rev, right_bid, right->root_eid, right_rrpath)
+                           right_rev, right_bid, right->tree->root_eid, right_rrpath)
             : NULL;
   const char *header;
   apr_hash_t *subbranches_l, *subbranches_r, *subbranches_all;
@@ -2062,7 +2066,7 @@ subtree_diff_r(svn_editor3_t *editor,
           if (sub_left)
             {
               const char *relpath
-                = svn_branch_subtree_get_path_by_eid(left, e, scratch_pool);
+                = svn_element_tree_get_path_by_eid(left->tree, e, scratch_pool);
 
               sub_left_bid = svn_branch_id_nest(left_bid, e, scratch_pool);
               sub_left_rrpath = svn_relpath_join(left_rrpath, relpath,
@@ -2076,7 +2080,7 @@ subtree_diff_r(svn_editor3_t *editor,
           if (sub_right)
             {
               const char *relpath
-                = svn_branch_subtree_get_path_by_eid(right, e, scratch_pool);
+                = svn_element_tree_get_path_by_eid(right->tree, e, scratch_pool);
 
               sub_right_bid = svn_branch_id_nest(right_bid, e, scratch_pool);
               sub_right_rrpath = svn_relpath_join(right_rrpath, relpath,
@@ -2512,12 +2516,12 @@ do_branch_into(svn_branch_state_t *from_
 
   /* Change this subtree's root element to TO_PARENT_EID/NEW_NAME. */
   new_root_content
-    = svn_int_hash_get(from_subtree->e_map, from_subtree->root_eid);
+    = svn_element_tree_get(from_subtree->tree, from_subtree->tree->root_eid);
   new_root_content
     = svn_branch_el_rev_content_create(to_parent_eid, new_name,
                                        new_root_content->payload, scratch_pool);
-  svn_int_hash_set(from_subtree->e_map, from_subtree->root_eid,
-                   new_root_content);
+  svn_element_tree_set(from_subtree->tree, from_subtree->tree->root_eid,
+                         new_root_content);
 
   /* Populate the new branch mapping */
   SVN_ERR(svn_branch_instantiate_elements_r(to_branch, *from_subtree,
@@ -2761,11 +2765,12 @@ display_diff_of_commit(const commit_call
                                                 ccbb->wc_commit_branch_id,
                                                 scratch_pool);
   svn_branch_el_rev_id_t *el_rev_left
-    = svn_branch_el_rev_id_create(base_branch, base_branch->root_eid,
+    = svn_branch_el_rev_id_create(base_branch, svn_branch_root_eid(base_branch),
                                   base_branch->rev_root->rev,
                                   scratch_pool);
   svn_branch_el_rev_id_t *el_rev_right
-    = svn_branch_el_rev_id_create(committed_branch, committed_branch->root_eid,
+    = svn_branch_el_rev_id_create(committed_branch,
+                                  svn_branch_root_eid(committed_branch),
                                   committed_branch->rev_root->rev,
                                   scratch_pool);
 
@@ -3132,10 +3137,10 @@ execute(svnmover_wc_t *wc,
             svn_branch_el_rev_id_t *from, *to;
 
             from = svn_branch_el_rev_id_create(wc->base->branch,
-                                               wc->base->branch->root_eid,
+                                               svn_branch_root_eid(wc->base->branch),
                                                wc->base->revision, iterpool);
             to = svn_branch_el_rev_id_create(wc->working->branch,
-                                             wc->working->branch->root_eid,
+                                             svn_branch_root_eid(wc->working->branch),
                                              SVN_INVALID_REVNUM, iterpool);
             SVN_ERR(branch_diff_r(editor,
                                       from, to,