Author: julianfoad
Date: Wed Apr 15 13:14:56 2015
New Revision: 1673753

URL: http://svn.apache.org/r1673753
Log:
On the 'move-tracking-2' branch: In the metadata, note whether each element
is a subbranch root element, so that on reading it we can correctly set the
element's 'content' field to null.

Previously, everything was working well enough even though such elements had
their content set to non-null, but that is not sustainable.

* subversion/include/private/svn_branch.h
  (svn_branch_el_rev_content_t): Update the comment.
  (svn_branch_subtree_create): New.

* subversion/libsvn_delta/branch.c
  (svn_branch_subtree_create,
   svn_branch_subtree_get_path_by_eid): New.
  (parse_element_line,
   svn_branch_instance_parse,
   svn_branch_instance_serialize): Add a 'kind' field to the metadata.

* subversion/libsvn_delta/compat3e.c
  (editor3_alter): Allow altering an element whose previous content is null.

* subversion/libsvn_delta/element.c
  (svn_element_content_equal): Allow comparing null element content.

* subversion/libsvn_ra/ra_loader.c
  (default_repos_info): Add a 'kind' field to the initial metadata.

* subversion/svnmover/svnmover.c
  (element_merge): Don't allow a 'double add' to apply to subbranches, as we
    don't know whether they are identical (and don't want to check).

Modified:
    subversion/branches/move-tracking-2/subversion/include/private/svn_branch.h
    subversion/branches/move-tracking-2/subversion/libsvn_delta/branch.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/libsvn_ra/ra_loader.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=1673753&r1=1673752&r2=1673753&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 Apr 15 13:14:56 2015
@@ -356,7 +356,8 @@ typedef struct svn_branch_el_rev_content
   /* struct svn_branch_element_t *parent_element; */
   /* element name, or "" for root element; never null */
   const char *name;
-  /* content (kind, props, text, ...) */
+  /* content (kind, props, text, ...);
+   * null if this is a subbranch root element */
   svn_element_content_t *content;
 
 } svn_branch_el_rev_content_t;
@@ -406,6 +407,12 @@ typedef struct svn_branch_subtree_t
   int root_eid;
 } svn_branch_subtree_t;
 
+/* Create an empty subtree (no elements populated, not even ROOT_EID).
+ */
+svn_branch_subtree_t *
+svn_branch_subtree_create(int root_eid,
+                          apr_pool_t *result_pool);
+
 /* Return the subtree of BRANCH rooted at EID.
  */
 svn_branch_subtree_t

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=1673753&r1=1673752&r2=1673753&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_delta/branch.c 
(original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_delta/branch.c Wed 
Apr 15 13:14:56 2015
@@ -358,6 +358,17 @@ svn_branch_el_rev_content_equal(const sv
  * ========================================================================
  */
 
+svn_branch_subtree_t *
+svn_branch_subtree_create(int root_eid,
+                          apr_pool_t *result_pool)
+{
+  svn_branch_subtree_t *subtree = apr_pcalloc(result_pool, sizeof(*subtree));
+
+  subtree->e_map = apr_hash_make(result_pool);
+  subtree->root_eid = root_eid;
+  return subtree;
+}
+
 /* Validate that NODE is suitable for a mapping of BRANCH:EID.
  * NODE->content may be null.
  */
@@ -588,6 +599,25 @@ svn_branch_get_root_rrpath(const svn_bra
   return root_rrpath;
 }
 
+static 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 *node;
+
+  for (; eid != subtree->root_eid; eid = node->parent_eid)
+    {
+      node = svn_int_hash_get(subtree->e_map, eid);
+      if (! node)
+        return NULL;
+      path = svn_relpath_join(node->name, path, result_pool);
+    }
+  SVN_ERR_ASSERT_NO_RETURN(eid == subtree->root_eid);
+  return path;
+}
+
 const char *
 svn_branch_get_path_by_eid(const svn_branch_instance_t *branch,
                            int eid,
@@ -916,6 +946,7 @@ parse_branch_line(int *bsid_p,
 static svn_error_t *
 parse_element_line(int *bsid_p,
                    int *eid_p,
+                   svn_boolean_t *is_subbranch_p,
                    int *parent_eid_p,
                    const char **name_p,
                    svn_stream_t *stream,
@@ -923,6 +954,7 @@ parse_element_line(int *bsid_p,
 {
   svn_stringbuf_t *line;
   svn_boolean_t eof;
+  char kind[10];
   int n;
   int offset;
 
@@ -930,13 +962,15 @@ parse_element_line(int *bsid_p,
   SVN_ERR(svn_stream_readline(stream, &line, "\n", &eof, scratch_pool));
   SVN_ERR_ASSERT(!eof);
 
-  n = sscanf(line->data, "b%de%d: %d%n",
+  n = sscanf(line->data, "b%de%d: %9s %d%n",
              bsid_p, eid_p,
-             parent_eid_p, &offset);
-  SVN_ERR_ASSERT(n >= 3);  /* C std is unclear on whether '%n' counts */
+             kind, parent_eid_p, &offset);
+  SVN_ERR_ASSERT(n >= 4);  /* C std is unclear on whether '%n' counts */
   SVN_ERR_ASSERT(line->data[offset] == ' ');
   *name_p = line->data + offset + 1;
 
+  *is_subbranch_p = (strcmp(kind, "subbranch") == 0);
+
   if (strcmp(*name_p, "(null)") == 0)
     *name_p = NULL;
   else if (strcmp(*name_p, ".") == 0)
@@ -963,6 +997,7 @@ svn_branch_instance_parse(svn_branch_ins
   svn_branch_instance_t *outer_branch;
   int outer_eid;
   int eid;
+  svn_branch_subtree_t *tree;
 
   SVN_ERR(parse_branch_line(&bsid, &root_eid, &branch_root_rrpath,
                             stream, scratch_pool));
@@ -985,46 +1020,63 @@ svn_branch_instance_parse(svn_branch_ins
                                                result_pool);
 
   /* Read in the structure, leaving the content of each element as null */
+  tree = svn_branch_subtree_create(root_eid, scratch_pool);
   for (eid = family->first_eid; eid < family->next_eid; eid++)
     {
       int this_bsid, this_eid, this_parent_eid;
       const char *this_name;
+      svn_boolean_t is_subbranch;
 
       SVN_ERR(parse_element_line(&this_bsid, &this_eid,
-                                 &this_parent_eid, &this_name,
+                                 &is_subbranch, &this_parent_eid, &this_name,
                                  stream, scratch_pool));
 
       if (this_name)
         {
           svn_branch_el_rev_content_t *node
             = svn_branch_el_rev_content_create(this_parent_eid, this_name,
-                                               NULL /*content*/, result_pool);
+                                               NULL /*content*/, scratch_pool);
+          if (! is_subbranch)
+            node->content = (void *)1;
 
-          branch_map_set(branch_instance, this_eid, node);
+          svn_int_hash_set(tree->e_map, this_eid, node);
         }
     }
 
   /* Populate the content reference for each element, now that we have
      enough info to calculate full paths */
+  /* Subbranch root elements should have content=null */
   for (eid = family->first_eid; eid < family->next_eid; eid++)
     {
-      svn_branch_el_rev_content_t *node
-        = svn_branch_map_get(branch_instance, eid);
+      svn_branch_el_rev_content_t *node = svn_int_hash_get(tree->e_map, eid);
 
       if (node)
         {
-          const char *rrpath = svn_branch_get_rrpath_by_eid(branch_instance,
-                                                            eid, scratch_pool);
-          svn_pathrev_t peg;
-          svn_element_content_t *content;
-
-          /* Specify the content by reference */
-          peg.rev = rev_root->rev;
-          peg.relpath = rrpath;
-          content = svn_element_content_create_ref(peg, scratch_pool);
+          if (node->content == (void *)1)
+            {
+              /* ### need to get path within temp hash tree */
+              const char *relpath
+                = svn_branch_subtree_get_path_by_eid(tree, eid, scratch_pool);
+              const char *rrpath
+                = svn_relpath_join(svn_branch_get_root_rrpath(branch_instance,
+                                                              result_pool),
+                                   relpath, scratch_pool);
+              svn_pathrev_t peg;
+              svn_element_content_t *content;
+
+              /* Specify the content by reference */
+              peg.rev = rev_root->rev;
+              peg.relpath = rrpath;
+              content = svn_element_content_create_ref(peg, scratch_pool);
 
-          svn_branch_map_update(branch_instance, eid,
-                                node->parent_eid, node->name, content);
+              svn_branch_map_update(
+                branch_instance, eid, node->parent_eid, node->name, content);
+            }
+          else
+            {
+              svn_branch_map_update_as_subbranch_root(
+                branch_instance, eid, node->parent_eid, node->name);
+            }
         }
     }
 
@@ -1177,8 +1229,10 @@ svn_branch_instance_serialize(svn_stream
           name = "(null)";
         }
       SVN_ERR(svn_stream_printf(stream, scratch_pool,
-                                "b%de%d: %d %s\n",
+                                "b%de%d: %s %d %s\n",
                                 branch->sibling_defn->bsid, eid,
+                                node ? (node->content ? "normal" : "subbranch")
+                                     : "none",
                                 parent_eid, name));
     }
   return SVN_NO_ERROR;

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=1673753&r1=1673752&r2=1673753&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_delta/compat3e.c 
(original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_delta/compat3e.c Wed 
Apr 15 13:14:56 2015
@@ -998,7 +998,12 @@ editor3_alter(void *baton,
       new_content = svn_branch_map_get(branch, eid)->content;
     }
 
-  svn_branch_map_update(branch, eid, new_parent_eid, new_name, new_content);
+  if (new_content)
+    svn_branch_map_update(
+      branch, eid, new_parent_eid, new_name, new_content);
+  else
+    svn_branch_map_update_as_subbranch_root(
+      branch, eid, new_parent_eid, new_name);
 
   return SVN_NO_ERROR;
 }

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=1673753&r1=1673752&r2=1673753&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_delta/element.c 
(original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_delta/element.c Wed 
Apr 15 13:14:56 2015
@@ -94,6 +94,15 @@ svn_element_content_equal(const svn_elem
 {
   apr_array_header_t *prop_diffs;
 
+  if (!left && !right)
+    {
+      return TRUE;
+    }
+  else if (!left || !right)
+    {
+      return FALSE;
+    }
+
   /* references are not supported */
   SVN_ERR_ASSERT_NO_RETURN(! left->ref.relpath && ! right->ref.relpath);
   SVN_ERR_ASSERT_NO_RETURN(left->kind != svn_node_unknown

Modified: subversion/branches/move-tracking-2/subversion/libsvn_ra/ra_loader.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_ra/ra_loader.c?rev=1673753&r1=1673752&r2=1673753&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_ra/ra_loader.c 
(original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_ra/ra_loader.c Wed 
Apr 15 13:14:56 2015
@@ -604,7 +604,7 @@ static const char *default_repos_info
   = "r0:\n"
     "family: bsids 0 1 eids 0 1 b-instances 1\n"
     "b0: root-eid 0 at .\n"
-    "b0e0: -1 .\n";
+    "b0e0: normal -1 .\n";
 
 /* Read the branching info string VALUE belonging to revision REVISION.
  */

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=1673753&r1=1673752&r2=1673753&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c 
(original)
+++ subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c Wed Apr 
15 13:14:56 2015
@@ -628,7 +628,9 @@ element_merge(svn_branch_el_rev_content_
   else if (side1 && side2)
     {
       /* Double add (as we already handled the case where YCA also exists) */
+      /* May be allowed for equal content of a normal element (not subbranch) 
*/
       if (policy->merge_double_add
+          && side1->content && side2->content /* they are not subbranches */
           && svn_branch_el_rev_content_equal(side1, side2, scratch_pool))
         {
           SVN_DBG(("e%d double add",


Reply via email to