subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From julianf...@apache.org
Subject svn commit: r1696593 - in /subversion/branches/move-tracking-2/subversion: include/private/svn_branch.h libsvn_delta/branch.c libsvn_delta/compat3e.c svnmover/svnmover.c
Date Wed, 19 Aug 2015 14:13:49 GMT
Author: julianfoad
Date: Wed Aug 19 14:13:49 2015
New Revision: 1696593

URL: http://svn.apache.org/r1696593
Log:
On the 'move-tracking-2' branch: More support for top-level (that is,
non-nested) branches.

This makes it possible to create a new top-level branch by branching any
existing branch, by means of:

  svnmover -B <existing-branch-id> tbranch <path-to-existing-branch>

(The syntax is redundant, as <existing-branch-id> implies
<path-to-existing-branch>.)

TODO:
  * change svnmover syntax so that paths given are relative to the branch
    designated by the "-B" option;
  * mkbranch <top-level-branch>
  * rmbranch <top-level-branch>
  * command-line syntax for addressing things in other top-level branches,
    e.g. <path>@[<rev>].[B<branch-id>]
    or   ^B<branch-id>/path[@rev]

* subversion/include/private/svn_branch.h
  (svn_branch_add_new_branch,
   svn_branch_branch_subtree): Take the revision root as a separate parameter.

* subversion/libsvn_delta/branch.c
  (svn_branch_instantiate_subtree): Adjust calls to track the API changes.
  (svn_branch_add_new_branch,
   svn_branch_branch_subtree): Take the revision root as a separate parameter.
  (svn_branch_revision_root_delete_branch): Also update the list of
    top-level branches, in preparation for when we can delete a top-level
    branch.
  (svn_branch_delete_branch_r): Remove a dereference that was redundant for
    nested branches but would have broken when deleting a top-level branch.
  (svn_branch_repos_find_el_rev_by_path_rev): Error out nicely if asked to
    look in a nonexistent top-level branch.

* subversion/libsvn_delta/compat3e.c
  (drive_changes_branch): Create the top-level storage node for any newly
    created top-level branch.

* subversion/svnmover/svnmover.c
  (commit_callback_baton_t,
   display_diff_of_commit): Rename a baton field, for clarity.
  (wc_commit): Support creating a new top-level branch as part of the commit.
  (action_code_t,
   action_defn): Add a 'tbranch' subcommand.
  (do_topbranch): New.
  (execute): Implement the 'tbranch' subcommand.
  (find_el_rev_by_rrpath_rev): Adjust doc string now that it can return an
    error if the given top-level branch does not exist at the requested rev.
  (svn_branch_replay,
   merge_subbranch,
   mk_branch,
   do_branch): Adjust calls to track the API changes.

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/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=1696593&r1=1696592&r2=1696593&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 Aug 19
14:13:49 2015
@@ -346,14 +346,19 @@ svn_branch_get_id(svn_branch_state_t *br
 /* Create a new branch at OUTER_BRANCH:OUTER_EID, with no elements
  * (not even a root element).
  *
- * Do not require that a subbranch root element exists in OUTER_BRANCH,
- * nor create one.
+ * Create and return a new branch object. Register its existence in REV_ROOT.
+ *
+ * If OUTER_BRANCH is NULL, create a top-level branch with OUTER_EID
+ * as its top-level branch number. Otherise, create a branch that claims
+ * to be nested under OUTER_BRANCH:OUTER_EID, but do not require that
+ * a subbranch root element exists there, nor create one.
  *
  * Set the root element to ROOT_EID, or, if ROOT_EID is -1, allocate a new
  * EID for the root element.
  */
 svn_branch_state_t *
-svn_branch_add_new_branch(svn_branch_state_t *outer_branch,
+svn_branch_add_new_branch(svn_branch_revision_root_t *rev_root,
+                          svn_branch_state_t *outer_branch,
                           int outer_eid,
                           int root_eid,
                           apr_pool_t *scratch_pool);
@@ -595,17 +600,22 @@ svn_branch_instantiate_subtree(svn_branc
 
 /* Create a new branch of a given subtree.
  *
- * Instantiate a new branch of the subtree FROM_SUBTREE, at the
- * existing subbranch-root element TO_OUTER_BRANCH:TO_OUTER_EID.
- *
- * Also branch the subbranches in FROM_SUBTREE, creating corresponding new
- * subbranches in TO_BRANCH, recursively.
+ * Create a new branch object. Register its existence in REV_ROOT.
+ * Instantiate the subtree FROM_SUBTREE in this new branch. In the new
+ * branch, create new subbranches corresponding to any subbranches
+ * specified in FROM_SUBTREE, recursively.
+ *
+ * If TO_OUTER_BRANCH is NULL, create a top-level branch with TO_OUTER_EID
+ * as its top-level branch number. Otherise, create a branch that claims
+ * to be nested under TO_OUTER_BRANCH:TO_OUTER_EID, but do not require that
+ * a subbranch root element exists there, nor create one.
  *
  * Set *NEW_BRANCH_P to the new branch (the one at TO_OUTER_BRANCH:TO_OUTER_EID).
  */
 svn_error_t *
 svn_branch_branch_subtree(svn_branch_state_t **new_branch_p,
                           svn_branch_subtree_t from_subtree,
+                          svn_branch_revision_root_t *rev_root,
                           svn_branch_state_t *to_outer_branch,
                           svn_branch_eid_t to_outer_eid,
                           apr_pool_t *scratch_pool);

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=1696593&r1=1696592&r2=1696593&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_delta/branch.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_delta/branch.c Wed Aug 19 14:13:49
2015
@@ -794,6 +794,7 @@ svn_branch_instantiate_subtree(svn_branc
         /* branch this subbranch into NEW_BRANCH (recursing) */
         SVN_ERR(svn_branch_branch_subtree(NULL,
                                           *this_subtree,
+                                          to_branch->rev_root,
                                           to_branch, this_outer_eid,
                                           bi->iterpool));
       }
@@ -837,25 +838,31 @@ svn_branch_get_subbranch_at_eid(svn_bran
 }
 
 svn_branch_state_t *
-svn_branch_add_new_branch(svn_branch_state_t *outer_branch,
+svn_branch_add_new_branch(svn_branch_revision_root_t *rev_root,
+                          svn_branch_state_t *outer_branch,
                           int outer_eid,
                           int root_eid,
                           apr_pool_t *scratch_pool)
 {
   svn_branch_state_t *new_branch;
 
+  SVN_ERR_ASSERT_NO_RETURN(!outer_branch || outer_branch->rev_root == rev_root);
+
   if (root_eid == -1)
-    root_eid = svn_branch_allocate_new_eid(outer_branch->rev_root);
+    root_eid = svn_branch_allocate_new_eid(rev_root);
 
-  new_branch = svn_branch_state_create(root_eid, outer_branch->rev_root,
+  new_branch = svn_branch_state_create(root_eid, rev_root,
                                        outer_branch, outer_eid,
-                                       outer_branch->rev_root->repos->pool);
+                                       rev_root->repos->pool);
 
   /* A branch must not already exist at this outer element */
-  SVN_ERR_ASSERT_NO_RETURN(svn_branch_get_subbranch_at_eid(
+  SVN_ERR_ASSERT_NO_RETURN(!outer_branch ||
+                           svn_branch_get_subbranch_at_eid(
                              outer_branch, outer_eid, scratch_pool) == NULL);
 
-  SVN_ARRAY_PUSH(new_branch->rev_root->branches) = new_branch;
+  SVN_ARRAY_PUSH(rev_root->branches) = new_branch;
+  if (!outer_branch)
+    SVN_ARRAY_PUSH(rev_root->root_branches) = new_branch;
 
   return new_branch;
 }
@@ -883,6 +890,17 @@ svn_branch_revision_root_delete_branch(
           break;
         }
     }
+  for (SVN_ARRAY_ITER(bi, rev_root->root_branches, scratch_pool))
+    {
+      if (bi->val == branch)
+        {
+          SVN_DBG(("deleting root-branch b%s e%d",
+                   svn_branch_get_id(bi->val, bi->iterpool),
+                   bi->val->root_eid));
+          svn_sort__array_delete(rev_root->root_branches, bi->i, 1);
+          break;
+        }
+    }
 }
 
 void
@@ -897,7 +915,7 @@ svn_branch_delete_branch_r(svn_branch_st
       svn_branch_delete_branch_r(bi->val, bi->iterpool);
     }
 
-  svn_branch_revision_root_delete_branch(branch->outer_branch->rev_root,
+  svn_branch_revision_root_delete_branch(branch->rev_root,
                                          branch, scratch_pool);
 }
 
@@ -1294,6 +1312,10 @@ svn_branch_repos_find_el_rev_by_path_rev
                              _("No such revision %ld"), revnum);
 
   root_branch = svn_branch_repos_get_root_branch(repos, revnum, top_branch_num);
+  if (! root_branch)
+    return svn_error_createf(SVN_ERR_BRANCHING, NULL,
+                             _("Top-level branch B%d not found in r%ld"),
+                             top_branch_num, revnum);
   el_rev->rev = revnum;
   svn_branch_find_nested_branch_element_by_rrpath(&el_rev->branch, &el_rev->eid,
                                                   root_branch, rrpath,
@@ -1328,14 +1350,16 @@ svn_branch_get_id(svn_branch_state_t *br
 svn_error_t *
 svn_branch_branch_subtree(svn_branch_state_t **new_branch_p,
                           svn_branch_subtree_t from_subtree,
+                          svn_branch_revision_root_t *rev_root,
                           svn_branch_state_t *to_outer_branch,
                           svn_branch_eid_t to_outer_eid,
                           apr_pool_t *scratch_pool)
 {
   svn_branch_state_t *new_branch;
 
-  /* create new inner branch */
-  new_branch = svn_branch_add_new_branch(to_outer_branch, to_outer_eid,
+  /* create new branch */
+  new_branch = svn_branch_add_new_branch(rev_root,
+                                         to_outer_branch, to_outer_eid,
                                          from_subtree.root_eid,
                                          scratch_pool);
 

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=1696593&r1=1696592&r2=1696593&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_delta/compat3e.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_delta/compat3e.c Wed Aug 19 14:13:49
2015
@@ -1741,18 +1741,26 @@ drive_changes_branch(ev3_from_delta_bato
     const char *top_path = branch_get_storage_root_rrpath(root_branch,
                                                           scratch_pool);
     svn_pathrev_t current;
+    svn_branch_state_t *base_root_branch
+      = svn_branch_repos_get_root_branch(eb->edited_rev_root->repos,
+                                         eb->edited_rev_root->base_rev,
+                                         root_branch->outer_eid /*top_branch_num*/);
+    svn_boolean_t branch_is_new = !base_root_branch;
 
     current.rev = eb->edited_rev_root->base_rev;
     current.relpath = top_path;
 
-    /* Make it appear that B0 was created (as an empty dir) in r0. */
-    if (current.rev == 0)
+    /* Create the top-level storage node if the branch is new, or if this is
+       the first commit to branch B0 which was created in r0 but had no
+       storage node there. */
+    if (branch_is_new || current.rev == 0)
       {
         change_node_t *change;
 
         SVN_ERR(insert_change(&change, eb->changes, top_path, RESTRUCTURE_ADD));
         change->kind = svn_node_dir;
       }
+
     SVN_ERR(drive_changes_r(top_path, &current,
                             paths_final, root_branch->outer_eid,
                             eb, scratch_pool));

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=1696593&r1=1696592&r2=1696593&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c (original)
+++ subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c Wed Aug 19 14:13:49
2015
@@ -406,6 +406,7 @@ svn_branch_replay(svn_editor3_t *editor,
           else
             {
               edit_subbranch = svn_branch_add_new_branch(
+                                 edit_branch->rev_root,
                                  edit_branch, this_eid,
                                  this_s_right->root_eid, scratch_pool);
             }
@@ -458,7 +459,7 @@ typedef struct commit_callback_baton_t
 {
   svn_branch_revision_root_t *edit_txn;
   const char *wc_base_branch_id;
-  const char *wc_working_branch_id;
+  const char *wc_commit_branch_id;
   svn_editor3_t *editor;
 
   /* just-committed revision */
@@ -491,6 +492,7 @@ wc_commit(svn_revnum_t *new_rev_p,
   svn_editor3_t *commit_editor;
   commit_callback_baton_t ccbb;
   svn_boolean_t change_detected;
+  svn_branch_state_t *edit_root_branch;
 
   /* Choose whether to store branching info in a local dir or in revprops.
      (For now, just to exercise the options, we choose local files for
@@ -516,22 +518,44 @@ wc_commit(svn_revnum_t *new_rev_p,
                                                &change_detected,
                                                commit_editor,
                                                scratch_pool));
-  ccbb.edit_txn = commit_txn;
-  ccbb.wc_base_branch_id = svn_branch_get_id(wc->base_branch, scratch_pool);
-  ccbb.wc_working_branch_id = svn_branch_get_id(wc->working_branch, scratch_pool);
-  ccbb.editor = commit_editor;
   /*SVN_ERR(svn_editor3__get_debug_editor(&wc->editor, wc->editor, scratch_pool));*/
 
-  /* ### See do_update() for how to choose correct root-branches.
-     Should we replay a whole txn or just the edited branch (and children)? */
+  edit_root_branch = svn_branch_revision_root_get_branch_by_id(
+                       commit_txn, wc->working_branch_id, scratch_pool);
+
+  /* We might be creating a new top-level branch in this commit. That is the
+     only case in which the working branch will not be found in EDIT_TXN.
+     (Creating any other branch can only be done inside a checkout of a
+     parent branch.) So, maybe create a new top-level branch. */
+  if (! edit_root_branch)
+    {
+      /* Create a new top-level branch in the edited state. (It will have
+         an independent new top-level branch number.) */
+      int top_branch_num = commit_txn->root_branches->nelts;
+
+      SVN_ERR(svn_branch_branch_subtree(&edit_root_branch,
+                                        *svn_branch_get_subtree(
+                                          wc->base_branch,
+                                          wc->base_branch->root_eid,
+                                          scratch_pool),
+                                        commit_txn,
+                                        wc->working_branch->outer_branch,
+                                        top_branch_num /*outer_eid*/,
+                                        scratch_pool));
+    }
   SVN_ERR(replay(commit_editor,
-                 svn_branch_revision_root_get_branch_by_id(
-                   ccbb.edit_txn, ccbb.wc_working_branch_id, scratch_pool),
+                 edit_root_branch,
                  wc->base_branch,
                  wc->working_branch,
                  scratch_pool));
   if (change_detected)
     {
+      ccbb.edit_txn = commit_txn;
+      ccbb.wc_base_branch_id = wc->base_branch_id;
+      ccbb.wc_commit_branch_id = svn_branch_get_id(edit_root_branch,
+                                                   scratch_pool);
+      ccbb.editor = commit_editor;
+
       SVN_ERR(svn_editor3_complete(commit_editor));
       SVN_ERR(display_diff_of_commit(&ccbb, scratch_pool));
 
@@ -555,6 +579,7 @@ typedef enum action_code_t {
   ACTION_LIST_BRANCHES,
   ACTION_LIST_BRANCHES_R,
   ACTION_LS,
+  ACTION_TBRANCH,
   ACTION_BRANCH,
   ACTION_BRANCH_INTO,
   ACTION_MKBRANCH,
@@ -590,6 +615,9 @@ static const action_defn_t action_defn[]
     "list elements in the branch found at PATH"},
   {ACTION_LOG,              "log", 2, "FROM@REV TO@REV",
     "show per-revision diffs between FROM and TO"},
+  {ACTION_TBRANCH,          "tbranch", 1, "SRC",
+    "branch the branch-root or branch-subtree at SRC" NL
+    "to make a new top-level branch"},
   {ACTION_BRANCH,           "branch", 2, "SRC DST",
     "branch the branch-root or branch-subtree at SRC" NL
     "to make a new branch at DST"},
@@ -647,7 +675,8 @@ typedef struct action_t {
  * Return the location of the element in that branch, or with
  * EID=-1 if no element exists there.
  *
- * The result will never be NULL, as every path is within at least the root
+ * Return an error if B<TOP_BRANCH_NUM> does not exist in r<REVNUM>; otherwise,
+ * the result will never be NULL, as every path is within at least the root
  * branch.
  */
 static svn_error_t *
@@ -1273,6 +1302,7 @@ merge_subbranch(svn_editor3_t *editor,
 
       SVN_ERR(svn_branch_branch_subtree(NULL,
                 *from_subtree,
+                tgt->branch->rev_root,
                 tgt->branch, eid,
                 scratch_pool));
     }
@@ -2134,6 +2164,7 @@ mk_branch(svn_branch_state_t **new_branc
                           outer_parent_eid, outer_name,
                           NULL /*new_payload*/));
   new_branch = svn_branch_add_new_branch(
+                 outer_branch->rev_root,
                  outer_branch, new_outer_eid, -1/*new_root_eid*/,
                  iterpool);
   svn_branch_update_element(new_branch, new_branch->root_eid,
@@ -2191,12 +2222,47 @@ do_branch(svn_branch_state_t **new_branc
 
   SVN_ERR(svn_branch_branch_subtree(new_branch_p,
                                     *from_subtree,
+                                    to_outer_branch->rev_root,
                                     to_outer_branch, to_outer_eid,
                                     scratch_pool));
 
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+do_topbranch(svn_branch_state_t **new_branch_p,
+             svn_branch_revision_root_t *rev_root,
+             svn_branch_state_t *from_branch,
+             int from_eid,
+             apr_pool_t *scratch_pool)
+{
+  svn_branch_subtree_t *from_subtree;
+  int to_outer_eid; /* ### top-level branch number */
+
+  /* Source element must exist */
+  if (! svn_branch_get_path_by_eid(from_branch, from_eid, scratch_pool))
+    {
+      return svn_error_createf(SVN_ERR_BRANCHING, NULL,
+                               _("cannot branch from b%s e%d: "
+                                 "does not exist"),
+                               svn_branch_get_id(
+                                 from_branch, scratch_pool), from_eid);
+    }
+
+  from_subtree = svn_branch_get_subtree(from_branch, from_eid, scratch_pool);
+
+  /* assign new top-level branch number to new branch */
+  to_outer_eid = from_branch->rev_root->root_branches->nelts;
+
+  SVN_ERR(svn_branch_branch_subtree(new_branch_p,
+                                    *from_subtree,
+                                    rev_root,
+                                    NULL /*to_outer_branch*/, to_outer_eid,
+                                    scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
 /* Branch the subtree of FROM_BRANCH found at FROM_EID, to appear
  * in the existing branch TO_BRANCH at TO_PARENT_EID:NEW_NAME.
  *
@@ -2267,7 +2333,7 @@ display_diff_of_commit(const commit_call
                                                 scratch_pool);
   svn_branch_state_t *committed_branch
     = svn_branch_revision_root_get_branch_by_id(ccbb->edit_txn,
-                                                ccbb->wc_working_branch_id,
+                                                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,
@@ -2705,6 +2771,24 @@ execute(svnmover_wc_t *wc,
           }
           break;
 
+        case ACTION_TBRANCH:
+          VERIFY_EID_EXISTS("tbranch", 0);
+          {
+            svn_branch_state_t *new_branch;
+
+            SVN_ERR(do_topbranch(&new_branch,
+                                 wc->working_branch->rev_root,
+                                 arg[0]->el_rev->branch, arg[0]->el_rev->eid,
+                                 iterpool));
+            notify_v("A+  %s",
+                     branch_str(new_branch, iterpool));
+            /* Switch the WC working state to this new branch */
+            wc->top_branch_num = new_branch->outer_eid;
+            wc->working_branch_id = svn_branch_get_id(new_branch, wc->pool);
+            wc->working_branch = new_branch;
+          }
+          break;
+
         case ACTION_BRANCH:
           VERIFY_EID_EXISTS("branch", 0);
           VERIFY_REV_UNSPECIFIED("branch", 1);



Mime
View raw message