Author: julianfoad
Date: Mon Jun 29 13:53:42 2015
New Revision: 1688223

URL: http://svn.apache.org/r1688223
Log:
On the 'move-tracking-2' branch: Start implementing top-level branching.

Change the element data structures to support multiple top-level branches.
Everything works as before, using only top-level branch number 0.

This implementation assumes that the WC is within a single existing top
branch, and that the editor drive is within a single existing top branch.
It does not yet support creating or deleting a top-level branch.

It does not yet map top-level branches to different path-spaces in an old
repository, so it does not yet have anywhere to store the payloads.

* subversion/include/private/svn_branch.h,
  subversion/libsvn_delta/branch.c
  (svn_branch_repos_get_root_branch,
   svn_branch_repos_find_el_rev_by_path_rev): Select a particular top branch.
  (svn_branch_revision_root_t): Store an array of root branches instead of a
    single one.
  (svn_branch_revision_root_create): Remove the root branch parameter:
    instead, create the object with no branches.
  (svn_branch_revision_root_get_root_branch): New.
  (svn_branch_state_t): Update docs: for a top-level branch, the 'outer-eid'
    field now stores the top-level branch number.

* subversion/include/private/svn_editor3e.h
  (svn_editor3_in_memory): Select a particular top branch.

* subversion/libsvn_delta/compat3e.c
  (ev3_from_delta_baton_t): Remember which top branch we're editing.
  (drive_changes_branch,
   editor3_sequence_point): When accessing the root branch, access the right
    one.
  (svn_editor3_in_memory): Select a particular top branch.

* subversion/svnmover/svnmover.c
  (wc_checkout): Initialize the editor for the requested top branch; error
    out if that branch doesn't exist.
  (wc_create): Remember which top branch the WC is editing.
  (replay): Take branches instead of rev-roots as inputs.
  (commit_callback_baton_t): Remember which top branch we are editing.
  (wc_commit): Pass the appropriate top level branches to replay().
  (find_el_rev_by_rrpath_rev): Look up within the WC's designated top
    branch.
  (do_update): Operate within the designated top branch.
  (display_diff_of_commit,
   do_revert): Update calls.
  (usage,
   sub_main): Add a '-B'/'--branch-id' option to select the top branch.

* subversion/svnmover/svnmover.h
  (svnmover_wc_t): Remember which top branch the WC is editing.

Modified:
    subversion/branches/move-tracking-2/subversion/include/private/svn_branch.h
    
subversion/branches/move-tracking-2/subversion/include/private/svn_editor3e.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
    subversion/branches/move-tracking-2/subversion/svnmover/svnmover.h

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=1688223&r1=1688222&r2=1688223&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 
Mon Jun 29 13:53:42 2015
@@ -141,7 +141,8 @@ svn_branch_repos_get_revision(const svn_
  */
 struct svn_branch_state_t *
 svn_branch_repos_get_root_branch(const svn_branch_repos_t *repos,
-                                 svn_revnum_t revnum);
+                                 svn_revnum_t revnum,
+                                 int top_branch_num);
 
 /* Set *EL_REV_P to the el-rev-id of the element at branch id BRANCH_ID,
  * element id EID, in revision REVNUM in REPOS.
@@ -177,6 +178,7 @@ svn_branch_repos_find_el_rev_by_id(svn_b
 svn_error_t *
 svn_branch_repos_find_el_rev_by_path_rev(svn_branch_el_rev_id_t **el_rev_p,
                                 const char *rrpath,
+                                int top_branch_num,
                                 svn_revnum_t revnum,
                                 const svn_branch_repos_t *repos,
                                 apr_pool_t *result_pool,
@@ -200,20 +202,22 @@ typedef struct svn_branch_revision_root_
   /* The range of element ids assigned. */
   int first_eid, next_eid;
 
-  /* The root branch. */
-  struct svn_branch_state_t *root_branch;
+  /* The root branches, indexed by top-level branch id (0...N). */
+  apr_array_header_t *root_branches;
 
-  /* All branches, including ROOT_BRANCH. */
+  /* All branches, including root branches. */
   apr_array_header_t *branches;
 
 } svn_branch_revision_root_t;
 
-/* Create a new branching revision-info object */
+/* Create a new branching revision-info object.
+ *
+ * It will have no branch-roots.
+ */
 svn_branch_revision_root_t *
 svn_branch_revision_root_create(svn_branch_repos_t *repos,
                                 svn_revnum_t rev,
                                 svn_revnum_t base_rev,
-                                struct svn_branch_state_t *root_branch,
                                 apr_pool_t *result_pool);
 
 /* Return the revision root that represents the base revision (or,
@@ -222,6 +226,14 @@ svn_branch_revision_root_create(svn_bran
 svn_branch_revision_root_t *
 svn_branch_revision_root_get_base(svn_branch_revision_root_t *rev_root);
 
+/* Return the top-level branch numbered TOP_BRANCH_NUM in REV_ROOT.
+ *
+ * Return null if there is no such branch.
+ */
+svn_branch_state_t *
+svn_branch_revision_root_get_root_branch(svn_branch_revision_root_t *rev_root,
+                                         int top_branch_num);
+
 /* Return all the branches in REV_ROOT.
  *
  * Return an empty array if there are none.
@@ -288,11 +300,11 @@ struct svn_branch_state_t
   svn_branch_revision_root_t *rev_root;
 
   /* The outer branch state that contains the subbranch
-     root element of this branch. Null if this is the root branch. */
+     root element of this branch. Null if this is a root branch. */
   struct svn_branch_state_t *outer_branch;
 
   /* The subbranch-root element in OUTER_BRANCH of the root of this branch.
-   * -1 if this is the root branch. */
+   * The top branch id if this is a root branch. */
   int outer_eid;
 
   /* --- Contents of this object --- */

Modified: 
subversion/branches/move-tracking-2/subversion/include/private/svn_editor3e.h
URL: 
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/include/private/svn_editor3e.h?rev=1688223&r1=1688222&r2=1688223&view=diff
==============================================================================
--- 
subversion/branches/move-tracking-2/subversion/include/private/svn_editor3e.h 
(original)
+++ 
subversion/branches/move-tracking-2/subversion/include/private/svn_editor3e.h 
Mon Jun 29 13:53:42 2015
@@ -1260,6 +1260,7 @@ svn_editor3__delta_from_ev3_for_update(
 svn_error_t *
 svn_editor3_in_memory(svn_editor3_t **editor_p,
                       svn_branch_revision_root_t *branching_txn,
+                      int top_branch_num,
                       svn_editor3__shim_fetch_func_t fetch_func,
                       void *fetch_baton,
                       apr_pool_t *result_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=1688223&r1=1688222&r2=1688223&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_delta/branch.c 
(original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_delta/branch.c Mon 
Jun 29 13:53:42 2015
@@ -74,19 +74,19 @@ svn_branch_repos_get_revision(const svn_
 
 struct svn_branch_state_t *
 svn_branch_repos_get_root_branch(const svn_branch_repos_t *repos,
-                                 svn_revnum_t revnum)
+                                 svn_revnum_t revnum,
+                                 int top_branch_num)
 {
   svn_branch_revision_root_t *rev_root
     = svn_branch_repos_get_revision(repos, revnum);
 
-  return rev_root->root_branch;
+  return svn_branch_revision_root_get_root_branch(rev_root, top_branch_num);
 }
 
 svn_branch_revision_root_t *
 svn_branch_revision_root_create(svn_branch_repos_t *repos,
                                 svn_revnum_t rev,
                                 svn_revnum_t base_rev,
-                                struct svn_branch_state_t *root_branch,
                                 apr_pool_t *result_pool)
 {
   svn_branch_revision_root_t *rev_root
@@ -95,7 +95,7 @@ svn_branch_revision_root_create(svn_bran
   rev_root->repos = repos;
   rev_root->rev = rev;
   rev_root->base_rev = base_rev;
-  rev_root->root_branch = root_branch;
+  rev_root->root_branches = apr_array_make(result_pool, 0, sizeof(void *));
   rev_root->branches = svn_array_make(result_pool);
   return rev_root;
 }
@@ -115,6 +115,16 @@ svn_branch_allocate_new_eid(svn_branch_r
   return eid;
 }
 
+svn_branch_state_t *
+svn_branch_revision_root_get_root_branch(svn_branch_revision_root_t *rev_root,
+                                         int top_branch_num)
+{
+  if (top_branch_num < 0 || top_branch_num >= rev_root->root_branches->nelts)
+    return NULL;
+  return APR_ARRAY_IDX(rev_root->root_branches, top_branch_num, void *);
+
+}
+
 const apr_array_header_t *
 svn_branch_revision_root_get_branches(svn_branch_revision_root_t *rev_root,
                                       apr_pool_t *result_pool)
@@ -1134,7 +1144,6 @@ svn_branch_revision_root_parse(svn_branc
   SVN_ERR_ASSERT(n == 4);
 
   rev_root = svn_branch_revision_root_create(repos, rev, rev - 1,
-                                             NULL /*root_branch*/,
                                              result_pool);
   rev_root->first_eid = first_eid;
   rev_root->next_eid = next_eid;
@@ -1148,10 +1157,10 @@ svn_branch_revision_root_parse(svn_branc
                                      result_pool, scratch_pool));
       SVN_ARRAY_PUSH(rev_root->branches) = branch;
 
-      /* Note the revision-root branch */
+      /* Note the root branches */
       if (! branch->outer_branch)
         {
-          rev_root->root_branch = branch;
+          APR_ARRAY_PUSH(rev_root->root_branches, void *) = branch;
         }
     }
 
@@ -1314,6 +1323,7 @@ svn_branch_repos_find_el_rev_by_id(svn_b
 svn_error_t *
 svn_branch_repos_find_el_rev_by_path_rev(svn_branch_el_rev_id_t **el_rev_p,
                                 const char *rrpath,
+                                int top_branch_num,
                                 svn_revnum_t revnum,
                                 const svn_branch_repos_t *repos,
                                 apr_pool_t *result_pool,
@@ -1326,7 +1336,7 @@ svn_branch_repos_find_el_rev_by_path_rev
     return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
                              _("No such revision %ld"), revnum);
 
-  root_branch = svn_branch_repos_get_root_branch(repos, revnum);
+  root_branch = svn_branch_repos_get_root_branch(repos, revnum, 
top_branch_num);
   el_rev->rev = revnum;
   svn_branch_find_nested_branch_element_by_rrpath(&el_rev->branch, 
&el_rev->eid,
                                                   root_branch, rrpath,

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=1688223&r1=1688222&r2=1688223&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_delta/compat3e.c 
(original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_delta/compat3e.c Mon 
Jun 29 13:53:42 2015
@@ -561,6 +561,7 @@ typedef struct ev3_from_delta_baton_t
 
   /* The branching state on which the per-element API is working */
   svn_branch_revision_root_t *edited_rev_root;
+  int top_branch_num;
 
   apr_pool_t *edit_pool;
 } ev3_from_delta_baton_t;
@@ -1372,7 +1373,9 @@ drive_changes_r(const char *rrpath,
 
       SVN_ERR(svn_branch_repos_find_el_rev_by_path_rev(
                                             &pred_el_rev,
-                                            pred_loc->relpath, pred_loc->rev,
+                                            pred_loc->relpath,
+                                            eb->top_branch_num,
+                                            pred_loc->rev,
                                             eb->edited_rev_root->repos,
                                             scratch_pool, scratch_pool));
 
@@ -1562,7 +1565,10 @@ drive_changes_branch(ev3_from_delta_bato
         3. modify/delete/add/replace as needed at each path.
    */
   paths_final = apr_hash_make(scratch_pool);
-  convert_branch_to_paths_r(paths_final, eb->edited_rev_root->root_branch,
+  /* ### TODO: map paths of non-0 top-level branch to a hidden path space */
+  convert_branch_to_paths_r(paths_final,
+                            svn_branch_revision_root_get_root_branch(
+                              eb->edited_rev_root, eb->top_branch_num),
                             scratch_pool, scratch_pool);
 
   {
@@ -1605,8 +1611,11 @@ editor3_sequence_point(void *baton,
                        apr_pool_t *scratch_pool)
 {
   ev3_from_delta_baton_t *eb = baton;
+  svn_branch_state_t *b
+    = svn_branch_revision_root_get_root_branch(eb->edited_rev_root,
+                                               eb->top_branch_num);
 
-  svn_branch_purge_r(eb->edited_rev_root->root_branch, scratch_pool);
+  svn_branch_purge_r(b, scratch_pool);
   return SVN_NO_ERROR;
 }
 
@@ -1684,6 +1693,7 @@ editor3_mem_abort(void *baton,
 svn_error_t *
 svn_editor3_in_memory(svn_editor3_t **editor_p,
                       svn_branch_revision_root_t *branching_txn,
+                      int top_branch_num,
                       svn_editor3__shim_fetch_func_t fetch_func,
                       void *fetch_baton,
                       apr_pool_t *result_pool)
@@ -1706,6 +1716,7 @@ svn_editor3_in_memory(svn_editor3_t **ed
                                  NULL, NULL /*cancel*/, result_pool);
 
   eb->edited_rev_root = branching_txn;
+  eb->top_branch_num = top_branch_num;
   eb->fetch_func = fetch_func;
   eb->fetch_baton = fetch_baton;
 

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=1688223&r1=1688222&r2=1688223&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c 
(original)
+++ subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c Mon Jun 
29 13:53:42 2015
@@ -182,8 +182,22 @@ wc_checkout(svnmover_wc_t *wc,
                                       wc->ra_session, branch_info_dir,
                                       wc->base_revision,
                                       wc->pool, scratch_pool));
+
+  /* Check requested root branch exists */
+  {
+    svn_branch_state_t *root_branch
+      = svn_branch_revision_root_get_root_branch(wc->edit_txn,
+                                                 wc->top_branch_num);
+
+    if (! root_branch)
+      return svn_error_createf(SVN_ERR_BRANCHING, NULL,
+                               "branch B%d not present in r%ld",
+                               wc->top_branch_num, wc->base_revision);
+  }
+
   SVN_ERR(svn_editor3_in_memory(&wc->editor,
                                 wc->edit_txn,
+                                wc->top_branch_num,
                                 fetch_func, fetch_baton,
                                 wc->pool));
 
@@ -197,6 +211,7 @@ wc_checkout(svnmover_wc_t *wc,
  *   repos_root_url
  *   ra_session
  *   made_changes
+ *   top_branch_num
  *   ctx
  *   pool
  *
@@ -206,6 +221,7 @@ static svn_error_t *
 wc_create(svnmover_wc_t **wc_p,
           const char *anchor_url,
           svn_revnum_t base_revision,
+          int top_branch_num,
           svn_client_ctx_t *ctx,
           apr_pool_t *result_pool,
           apr_pool_t *scratch_pool)
@@ -213,6 +229,7 @@ wc_create(svnmover_wc_t **wc_p,
   apr_pool_t *wc_pool = svn_pool_create(result_pool);
   svnmover_wc_t *wc = apr_pcalloc(wc_pool, sizeof(*wc));
 
+  wc->top_branch_num = top_branch_num;
   wc->pool = wc_pool;
   wc->ctx = ctx;
 
@@ -375,22 +392,26 @@ svn_branch_replay(svn_editor3_t *editor,
   return SVN_NO_ERROR;
 }
 
-/* Replay differences between LEFT_TXN and RIGHT_TXN into EDIT_ROOT_BRANCH.
+/* Replay differences between LEFT_BRANCH and RIGHT_BRANCH into
+ * EDIT_ROOT_BRANCH.
  * (Recurse into subbranches.)
  */
 static svn_error_t *
 replay(svn_editor3_t *editor,
        svn_branch_state_t *edit_root_branch,
-       svn_branch_revision_root_t *left_txn,
-       svn_branch_revision_root_t *right_txn,
+       svn_branch_state_t *left_branch,
+       svn_branch_state_t *right_branch,
        apr_pool_t *scratch_pool)
 {
   svn_branch_subtree_t *s_left
-    = svn_branch_get_subtree(left_txn->root_branch,
-                             left_txn->root_branch->root_eid, scratch_pool);
+    = left_branch ? svn_branch_get_subtree(left_branch, left_branch->root_eid,
+                                           scratch_pool) : NULL;
   svn_branch_subtree_t *s_right
-    = svn_branch_get_subtree(right_txn->root_branch,
-                             right_txn->root_branch->root_eid, scratch_pool);
+    = right_branch ? svn_branch_get_subtree(right_branch, 
right_branch->root_eid,
+                                            scratch_pool) : NULL;
+
+  SVN_ERR_ASSERT(editor && edit_root_branch);
+  SVN_ERR_ASSERT(left_branch || right_branch);
 
   SVN_ERR(svn_branch_replay(editor, edit_root_branch,
                             s_left, s_right, scratch_pool));
@@ -406,6 +427,7 @@ commit_callback(const svn_commit_info_t
 typedef struct commit_callback_baton_t
 {
   svn_branch_revision_root_t *edit_txn;
+  int top_branch_num;
   svn_editor3_t *editor;
 
   /* just-committed revision */
@@ -467,12 +489,19 @@ wc_commit(svn_revnum_t *new_rev_p,
                                                commit_editor,
                                                scratch_pool));
   ccbb.edit_txn = commit_txn;
+  ccbb.top_branch_num = wc->top_branch_num;
   ccbb.editor = commit_editor;
   /*SVN_ERR(svn_editor3__get_debug_editor(&wc->editor, wc->editor, 
scratch_pool));*/
 
-  SVN_ERR(replay(commit_editor, commit_txn->root_branch,
-                 left_txn,
-                 right_txn,
+  /* ### See do_update() for how to choose correct root-branches.
+     Should we replay a whole txn or just the edited branch (and children)? */
+  SVN_ERR(replay(commit_editor,
+                 svn_branch_revision_root_get_root_branch(commit_txn,
+                                                          wc->top_branch_num),
+                 svn_branch_revision_root_get_root_branch(left_txn,
+                                                          wc->top_branch_num),
+                 svn_branch_revision_root_get_root_branch(right_txn,
+                                                          wc->top_branch_num),
                  scratch_pool));
   if (change_detected)
     {
@@ -607,7 +636,9 @@ find_el_rev_by_rrpath_rev(svn_branch_el_
       const svn_branch_repos_t *repos = wc->edit_txn->repos;
 
       SVN_ERR(svn_branch_repos_find_el_rev_by_path_rev(el_rev_p,
-                                                       rrpath, revnum, repos,
+                                                       rrpath,
+                                                       wc->top_branch_num,
+                                                       revnum, repos,
                                                        result_pool,
                                                        scratch_pool));
     }
@@ -617,7 +648,8 @@ find_el_rev_by_rrpath_rev(svn_branch_el_
 
       svn_branch_find_nested_branch_element_by_rrpath(
         &el_rev->branch, &el_rev->eid,
-        wc->edit_txn->root_branch, rrpath, scratch_pool);
+        svn_branch_revision_root_get_root_branch(wc->edit_txn, 
wc->top_branch_num),
+        rrpath, scratch_pool);
       el_rev->rev = SVN_INVALID_REVNUM;
       *el_rev_p = el_rev;
     }
@@ -1617,6 +1649,10 @@ svn_branch_merge(svn_editor3_t *editor,
 /* Update the WC to revision BASE_REVISION (SVN_INVALID_REVNUM means HEAD).
  *
  * Merge any changes in the existing txn into the new txn.
+ *
+ * ### If current WC branch doesn't exist in target rev, should
+ *     'update' follow to a different branch? By following merge graph?
+ *     Presently it would try to update to a state of nonexistence.
  */
 static svn_error_t *
 do_update(svnmover_wc_t *wc,
@@ -1626,7 +1662,13 @@ do_update(svnmover_wc_t *wc,
   /* Keep hold of the previous WC txn */
   svn_branch_revision_root_t *previous_base_state
     = svn_branch_revision_root_get_base(wc->edit_txn);
-  svn_branch_revision_root_t *previous_working_txn = wc->edit_txn;
+  svn_branch_state_t *previous_base_br
+    = svn_branch_revision_root_get_root_branch(previous_base_state,
+                                               wc->top_branch_num);
+  svn_branch_state_t *previous_working_br
+    = svn_branch_revision_root_get_root_branch(wc->edit_txn,
+                                               wc->top_branch_num);
+  svn_branch_state_t *edit_br;
   svn_branch_el_rev_id_t *yca, *src, *tgt;
 
   /* Complete the old edit drive into the 'WC' txn */
@@ -1637,14 +1679,16 @@ do_update(svnmover_wc_t *wc,
                       scratch_pool));
 
   /* Merge changes from the old into the new WC */
-  yca = svn_branch_el_rev_id_create(previous_base_state->root_branch,
-                                    previous_base_state->root_branch->root_eid,
+  yca = svn_branch_el_rev_id_create(previous_base_br,
+                                    previous_base_br->root_eid,
                                     previous_base_state->rev, scratch_pool);
-  src = svn_branch_el_rev_id_create(previous_working_txn->root_branch,
-                                    
previous_working_txn->root_branch->root_eid,
-                                    previous_working_txn->rev, scratch_pool);
-  tgt = svn_branch_el_rev_id_create(wc->edit_txn->root_branch,
-                                    wc->edit_txn->root_branch->root_eid,
+  src = svn_branch_el_rev_id_create(previous_working_br,
+                                    previous_working_br->root_eid,
+                                    SVN_INVALID_REVNUM, scratch_pool);
+  edit_br = svn_branch_revision_root_get_root_branch(wc->edit_txn,
+                                                     wc->top_branch_num);
+  tgt = svn_branch_el_rev_id_create(edit_br,
+                                    edit_br->root_eid,
                                     wc->edit_txn->rev, scratch_pool);
   SVN_ERR(svn_branch_merge(wc->editor, src, tgt, yca,
                            scratch_pool));
@@ -2221,11 +2265,13 @@ display_diff_of_commit(const commit_call
 
   SVN_ERR(svn_branch_repos_find_el_rev_by_path_rev(&el_rev_left,
                                                    rrpath,
+                                                   ccbb->top_branch_num,
                                                    ccbb->revision - 1,
                                                    repos, scratch_pool,
                                                    scratch_pool));
   SVN_ERR(svn_branch_repos_find_el_rev_by_path_rev(&el_rev_right,
                                                    rrpath,
+                                                   ccbb->top_branch_num,
                                                    ccbb->revision,
                                                    repos, scratch_pool,
                                                    scratch_pool));
@@ -2281,9 +2327,13 @@ do_revert(svnmover_wc_t *wc,
     = svn_branch_revision_root_get_base(wc->edit_txn);
 
   /* Replay the inverse of the current edit txn, into the current edit txn */
-  SVN_ERR(replay(wc->editor, wc->edit_txn->root_branch,
-                 wc->edit_txn,
-                 base_txn,
+  SVN_ERR(replay(wc->editor,
+                 svn_branch_revision_root_get_root_branch(wc->edit_txn,
+                                                          wc->top_branch_num),
+                 svn_branch_revision_root_get_root_branch(wc->edit_txn,
+                                                          wc->top_branch_num),
+                 svn_branch_revision_root_get_root_branch(base_txn,
+                                                          wc->top_branch_num),
                  scratch_pool));
 
   return SVN_NO_ERROR;
@@ -2967,6 +3017,7 @@ usage(FILE *stream, apr_pool_t *pool)
       "  -p [--password] ARG    : use ARG as the password\n"
       "  -U [--root-url] ARG    : interpret all action URLs relative to ARG\n"
       "  -r [--revision] ARG    : use revision ARG as baseline for changes\n"
+      "  -B [--branch-id] ARG   : work on the branch identified by ARG\n"
       "  --with-revprop ARG     : set revision property in the following 
format:\n"
       "                               NAME[=VALUE]\n"
       "  --non-interactive      : do no interactive prompting (default is to\n"
@@ -3289,6 +3340,7 @@ sub_main(int *exit_code, int argc, const
     {"password", 'p', 1, ""},
     {"root-url", 'U', 1, ""},
     {"revision", 'r', 1, ""},
+    {"branch-id", 'B', 1, ""},
     {"with-revprop",  with_revprop_opt, 1, ""},
     {"extra-args", 'X', 1, ""},
     {"help", 'h', 0, ""},
@@ -3321,6 +3373,8 @@ sub_main(int *exit_code, int argc, const
   svn_boolean_t trust_other_failure = FALSE;
   svn_boolean_t no_auth_cache = FALSE;
   svn_revnum_t base_revision = SVN_INVALID_REVNUM;
+  const char *branch_id = NULL;
+  int top_branch_num = 0;
   apr_array_header_t *action_args;
   apr_hash_t *revprops = apr_hash_make(pool);
   apr_hash_t *cfg_hash;
@@ -3397,6 +3451,9 @@ sub_main(int *exit_code, int argc, const
                                        saved_arg);
           }
           break;
+        case 'B':
+          branch_id = apr_pstrdup(pool, arg);
+          break;
         case with_revprop_opt:
           SVN_ERR(svn_opt_parse_revprop(&revprops, arg, pool));
           break;
@@ -3570,9 +3627,26 @@ sub_main(int *exit_code, int argc, const
       linenoiseSetCompletionCallback(linenoise_completion);
     }
 
+  /* If a branch id was specified, use it to select the top_branch_num;
+     else top_branch_num = 0.
+     ### TODO: Select a nested branch too, from the given id. */
+  if (branch_id)
+    {
+      int n;
+
+      n = sscanf(branch_id, "B%d", &top_branch_num);
+      printf("'%s' %d %d\n", branch_id, n, top_branch_num);
+      if (n != 1)
+        return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
+                                 _("invalid branch spec: '%s'"),
+                                 branch_id);
+    }
+
   SVN_ERR(wc_create(&wc,
                     anchor_url, base_revision,
+                    top_branch_num,
                     ctx, pool, pool));
+
   do
     {
       /* Parse arguments -- converting local style to internal style,

Modified: subversion/branches/move-tracking-2/subversion/svnmover/svnmover.h
URL: 
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svnmover/svnmover.h?rev=1688223&r1=1688222&r2=1688223&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnmover/svnmover.h 
(original)
+++ subversion/branches/move-tracking-2/subversion/svnmover/svnmover.h Mon Jun 
29 13:53:42 2015
@@ -49,6 +49,7 @@ typedef struct svnmover_wc_t
   svn_ra_session_t *ra_session;
   svn_editor3_t *editor;
   svn_branch_revision_root_t *edit_txn;
+  int top_branch_num;
   svn_client_ctx_t *ctx;
 
 } svnmover_wc_t;


Reply via email to