Author: julianfoad
Date: Thu Aug 20 16:56:11 2015
New Revision: 1696816

URL: http://svn.apache.org/r1696816
Log:
On the 'move-tracking-2' branch: Implement '^B<branch-id>/path' syntax for
svnmover path inputs.

The full syntax is

  [^B<branch-id>/]relpath[@rev]

When BRANCH-ID is given, this means the relative path RELPATH within the
branch. When branches are nested, this may identify an element in a branch
that is nested inside branch <branch-id>; in case of multiple nesting, the
most deeply nested branch is found.

When the '^B<branch-id>/' prefix is not given, look inside the same branch
id as the WC base branch when a revision number is given, and look inside
the WC working branch when a revision number is not given.

* subversion/include/private/svn_branch.h,
  subversion/libsvn_delta/branch.c
  (svn_branch_repos_find_el_rev_by_path_rev): Take an arbitrary branch id
    and a branch-relative path instead of a top-level branch number and a
    repository-relative path.
  (svn_branch_find_nested_branch_element_by_relpath): Rename from
    svn_branch_find_nested_branch_element_by_rrpath. Take a branch-relative
    path instead of a repository-relative path.
  (svn_branch_repos_get_branch_by_id): New.
  (svn_branch_repos_find_el_rev_by_id): Simplify by using
    svn_branch_repos_get_branch_by_id; this also means it will throw an
    error instead of crashing if the branch is not found.

* subversion/libsvn_delta/compat3e.c
  (drive_changes_r,
   drive_changes_branch): Track the change to
    svn_branch_repos_find_el_rev_by_path_rev(), by identifying the top-level
    branch by its branch-id rather than its top-level branch number.

* subversion/svnmover/svnmover.h
  (svnmover_wc_t): Remove the 'top_branch_num' field.

* subversion/svnmover/svnmover.c
  (wc_create): Remove initialization of the obsolete 'top_branch_num' field.
  (action_t): Add a 'branch_id' field.
  (find_el_rev_by_rrpath_rev): Look up the path in a given branch, defaulting
    to the base branch when looking in a given revision or the working branch
    otherwise.
  (execute): Pass on the branch id when looking up a path. Remove a
    re-initialization of the obsolete 'top_branch_num' field.
  (parse_actions): Parse "^B<branch-id>/path" syntax.
  (sub_main): No longer pass the obsolete 'top_branch_num' parameter to
    wc_create().

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
    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=1696816&r1=1696815&r2=1696816&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 
Thu Aug 20 16:56:11 2015
@@ -144,6 +144,16 @@ svn_branch_repos_get_root_branch(const s
                                  svn_revnum_t revnum,
                                  int top_branch_num);
 
+/* Set *BRANCH_P to the branch found in REPOS : REVNUM : BRANCH_ID.
+ *
+ * Return an error if REVNUM or BRANCH_ID is not found.
+ */
+svn_error_t *
+svn_branch_repos_get_branch_by_id(svn_branch_state_t **branch_p,
+                                  const svn_branch_repos_t *repos,
+                                  svn_revnum_t revnum,
+                                  const char *branch_id,
+                                  apr_pool_t *scratch_pool);
 /* 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.
  *
@@ -163,8 +173,8 @@ svn_branch_repos_find_el_rev_by_id(svn_b
                                    apr_pool_t *result_pool,
                                    apr_pool_t *scratch_pool);
 
-/* Set *EL_REV_P to the el-rev-id of the element at repos-relpath RRPATH
- * in revision REVNUM in REPOS.
+/* Set *EL_REV_P to the el-rev-id of the element at relative path RELPATH
+ * anywhere in or under branch BRANCH_ID in revision REVNUM in REPOS.
  *
  * If there is no element there, set *EL_REV_P to point to an id in which
  * the BRANCH field is the nearest enclosing branch of RRPATH and the EID
@@ -177,10 +187,10 @@ 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,
+                                svn_revnum_t revnum,
+                                const char *branch_id,
+                                const char *relpath,
                                 apr_pool_t *result_pool,
                                 apr_pool_t *scratch_pool);
 
@@ -701,27 +711,27 @@ svn_branch_get_eid_by_rrpath(svn_branch_
                              const char *rrpath,
                              apr_pool_t *scratch_pool);
 
-/* Find the (deepest) branch of which the path RRPATH is either the root
+/* Find the (deepest) branch of which the path RELPATH is either the root
  * path or a normal, non-sub-branch path. An element need not exist at
- * RRPATH.
+ * RELPATH.
  *
  * Set *BRANCH_P to the deepest branch within ROOT_BRANCH (recursively,
- * including itself) that contains the path RRPATH.
+ * including itself) that contains the path RELPATH.
  *
- * If EID_P is not null then set *EID_P to the element id of RRPATH in
- * *BRANCH_P, or to -1 if no element exists at RRPATH in that branch.
+ * If EID_P is not null then set *EID_P to the element id of RELPATH in
+ * *BRANCH_P, or to -1 if no element exists at RELPATH in that branch.
  *
- * If RRPATH is not within any branch in ROOT_BRANCH, set *BRANCH_P to
+ * If RELPATH is not within any branch in ROOT_BRANCH, set *BRANCH_P to
  * NULL and (if EID_P is not null) *EID_P to -1.
  *
  * ### TODO: Clarify sequencing requirements.
  */
 void
-svn_branch_find_nested_branch_element_by_rrpath(
+svn_branch_find_nested_branch_element_by_relpath(
                                 svn_branch_state_t **branch_p,
                                 int *eid_p,
                                 svn_branch_state_t *root_branch,
-                                const char *rrpath,
+                                const char *relpath,
                                 apr_pool_t *scratch_pool);
 
 /* Get the default branching metadata for r0 of a new repository.

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=1696816&r1=1696815&r2=1696816&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_delta/branch.c 
(original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_delta/branch.c Thu 
Aug 20 16:56:11 2015
@@ -1217,51 +1217,74 @@ svn_branch_revision_root_serialize(svn_s
  */
 
 void
-svn_branch_find_nested_branch_element_by_rrpath(
+svn_branch_find_nested_branch_element_by_relpath(
                                 svn_branch_state_t **branch_p,
                                 int *eid_p,
                                 svn_branch_state_t *root_branch,
-                                const char *rrpath,
+                                const char *relpath,
                                 apr_pool_t *scratch_pool)
 {
-  const char *branch_root_path = svn_branch_get_root_rrpath(root_branch,
-                                                            scratch_pool);
-  SVN_ITER_T(svn_branch_state_t) *bi;
-
-  if (! svn_relpath_skip_ancestor(branch_root_path, rrpath))
-    {
-      /* The path we're looking for is not (path-wise) in this branch. */
-      *branch_p = NULL;
-      if (eid_p)
-        *eid_p = -1;
-      return;
-    }
-
   /* The path we're looking for is (path-wise) in this branch. See if it
-     is also in a sub-branch (recursively). */
-  for (SVN_ARRAY_ITER(bi, svn_branch_get_immediate_subbranches(
-                            root_branch, scratch_pool, scratch_pool),
-                      scratch_pool))
+     is also in a sub-branch. */
+  while (TRUE)
     {
-      svn_branch_state_t *subbranch;
-      int subbranch_eid;
+      SVN_ITER_T(svn_branch_state_t) *bi;
+      svn_boolean_t found = FALSE;
 
-      svn_branch_find_nested_branch_element_by_rrpath(&subbranch,
-                                                      &subbranch_eid,
-                                                      bi->val, rrpath,
-                                                      bi->iterpool);
-      if (subbranch)
+      for (SVN_ARRAY_ITER(bi, svn_branch_get_immediate_subbranches(
+                                root_branch, scratch_pool, scratch_pool),
+                          scratch_pool))
         {
-           *branch_p = subbranch;
-           if (eid_p)
-             *eid_p = subbranch_eid;
-           return;
-         }
+          svn_branch_state_t *subbranch = bi->val;
+          const char *relpath_to_subbranch;
+          const char *relpath_in_subbranch;
+
+          relpath_to_subbranch
+            = svn_branch_get_path_by_eid(root_branch, subbranch->outer_eid,
+                                         scratch_pool);
+
+          relpath_in_subbranch
+            = svn_relpath_skip_ancestor(relpath_to_subbranch, relpath);
+          if (relpath_in_subbranch)
+            {
+              root_branch = subbranch;
+              relpath = relpath_in_subbranch;
+              found = TRUE;
+              break;
+            }
+        }
+      if (! found)
+        {
+          break;
+        }
     }
 
   *branch_p = root_branch;
   if (eid_p)
-    *eid_p = svn_branch_get_eid_by_rrpath(root_branch, rrpath, scratch_pool);
+    *eid_p = svn_branch_get_eid_by_path(root_branch, relpath, scratch_pool);
+}
+
+svn_error_t *
+svn_branch_repos_get_branch_by_id(svn_branch_state_t **branch_p,
+                                  const svn_branch_repos_t *repos,
+                                  svn_revnum_t revnum,
+                                  const char *branch_id,
+                                  apr_pool_t *scratch_pool)
+{
+  svn_branch_revision_root_t *rev_root;
+
+  if (revnum < 0 || revnum >= repos->rev_roots->nelts)
+    return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
+                             _("No such revision %ld"), revnum);
+
+  rev_root = svn_branch_repos_get_revision(repos, revnum);
+  *branch_p = svn_branch_revision_root_get_branch_by_id(rev_root, branch_id,
+                                                        scratch_pool);
+  if (! *branch_p)
+    return svn_error_createf(SVN_ERR_BRANCHING, NULL,
+                             _("Branch %s not found in r%ld"),
+                             branch_id, revnum);
+  return SVN_NO_ERROR;
 }
 
 svn_error_t *
@@ -1274,17 +1297,11 @@ svn_branch_repos_find_el_rev_by_id(svn_b
                                    apr_pool_t *scratch_pool)
 {
   svn_branch_el_rev_id_t *el_rev = apr_palloc(result_pool, sizeof(*el_rev));
-  const svn_branch_revision_root_t *rev_root;
 
-  if (revnum < 0 || revnum >= repos->rev_roots->nelts)
-    return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
-                             _("No such revision %ld"), revnum);
-
-  rev_root = svn_branch_repos_get_revision(repos, revnum);
   el_rev->rev = revnum;
-  el_rev->branch
-    = svn_branch_revision_root_get_branch_by_id(rev_root, branch_id,
-                                                scratch_pool);
+  SVN_ERR(svn_branch_repos_get_branch_by_id(&el_rev->branch,
+                                            repos, revnum, branch_id,
+                                            scratch_pool));
   if (svn_branch_get_element(el_rev->branch, eid))
     {
       el_rev->eid = eid;
@@ -1299,31 +1316,26 @@ 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,
+                                svn_revnum_t revnum,
+                                const char *branch_id,
+                                const char *relpath,
                                 apr_pool_t *result_pool,
                                 apr_pool_t *scratch_pool)
 {
   svn_branch_el_rev_id_t *el_rev = apr_palloc(result_pool, sizeof(*el_rev));
-  svn_branch_state_t *root_branch;
+  svn_branch_state_t *branch;
 
-  if (revnum < 0 || revnum >= repos->rev_roots->nelts)
-    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, 
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);
+  SVN_ERR(svn_branch_repos_get_branch_by_id(&branch,
+                                            repos, revnum, branch_id,
+                                            scratch_pool));
   el_rev->rev = revnum;
-  svn_branch_find_nested_branch_element_by_rrpath(&el_rev->branch, 
&el_rev->eid,
-                                                  root_branch, rrpath,
-                                                  scratch_pool);
+  svn_branch_find_nested_branch_element_by_relpath(&el_rev->branch,
+                                                   &el_rev->eid,
+                                                   branch, relpath,
+                                                   scratch_pool);
 
-  /* Any path must at least be within the repository root branch */
+  /* Any relpath must at least be within the originally given branch */
   SVN_ERR_ASSERT_NO_RETURN(el_rev->branch);
   *el_rev_p = el_rev;
   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=1696816&r1=1696815&r2=1696816&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_delta/compat3e.c 
(original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_delta/compat3e.c Thu 
Aug 20 16:56:11 2015
@@ -1489,7 +1489,7 @@ static svn_error_t *
 drive_changes_r(const char *rrpath,
                 svn_pathrev_t *pred_loc,
                 apr_hash_t *paths_final,
-                int top_branch_num,
+                const char *top_branch_id,
                 ev3_from_delta_baton_t *eb,
                 apr_pool_t *scratch_pool)
 {
@@ -1540,12 +1540,11 @@ drive_changes_r(const char *rrpath,
     {
       svn_branch_el_rev_id_t *pred_el_rev;
 
-      SVN_ERR(svn_branch_repos_find_el_rev_by_path_rev(
-                                            &pred_el_rev,
-                                            pred_loc->relpath,
-                                            top_branch_num,
-                                            pred_loc->rev,
+      SVN_ERR(svn_branch_repos_find_el_rev_by_path_rev(&pred_el_rev,
                                             eb->edited_rev_root->repos,
+                                            pred_loc->rev,
+                                            top_branch_id,
+                                            pred_loc->relpath,
                                             scratch_pool, scratch_pool));
 
       succession = (pred_el_rev->eid == final_el_rev->eid);
@@ -1702,7 +1701,7 @@ drive_changes_r(const char *rrpath,
 
               SVN_ERR(drive_changes_r(this_rrpath,
                                       child_pred,
-                                      paths_final, top_branch_num,
+                                      paths_final, top_branch_id,
                                       eb, scratch_pool));
             }
         }
@@ -1762,7 +1761,8 @@ drive_changes_branch(ev3_from_delta_bato
       }
 
     SVN_ERR(drive_changes_r(top_path, &current,
-                            paths_final, root_branch->outer_eid,
+                            paths_final, svn_branch_get_id(root_branch,
+                                                           scratch_pool),
                             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=1696816&r1=1696815&r2=1696816&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c 
(original)
+++ subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c Thu Aug 
20 16:56:11 2015
@@ -234,7 +234,6 @@ static svn_error_t *
 wc_create(svnmover_wc_t **wc_p,
           const char *anchor_url,
           svn_revnum_t base_revision,
-          int top_branch_num,
           const char *base_branch_id,
           svn_client_ctx_t *ctx,
           apr_pool_t *result_pool,
@@ -243,7 +242,6 @@ 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;
 
@@ -659,22 +657,27 @@ typedef struct action_t {
   /* argument revisions */
   svn_opt_revision_t rev_spec[3];
 
+  const char *branch_id[3];
+
   /* argument paths */
   const char *relpath[3];
 } action_t;
 
 /* ====================================================================== */
 
-/* Find the deepest branch in the repository of which REVNUM:RRPATH is
- * either the root element or a normal, non-sub-branch element.
+/* Find the deepest branch in the repository of which REVNUM:BRANCH_ID:RELPATH
+ * is either the root element or a normal, non-sub-branch element.
  *
- * RRPATH is a repository-relative path. REVNUM is a revision number, or
+ * RELPATH is a repository-relative path. REVNUM is a revision number, or
  * SVN_INVALID_REVNUM meaning the current txn.
  *
  * Return the location of the element in that branch, or with
  * EID=-1 if no element exists there.
  *
- * Return an error if B<TOP_BRANCH_NUM> does not exist in r<REVNUM>; otherwise,
+ * If BRANCH_ID is null, the default is the WC base branch when REVNUM is
+ * specified, and the WC working branch when REVNUM is SVN_INVALID_REVNUM.
+ *
+ * Return an error if branch BRANCH_ID does not exist in r<REVNUM>; otherwise,
  * the result will never be NULL, as every path is within at least the root
  * branch.
  */
@@ -682,7 +685,8 @@ static svn_error_t *
 find_el_rev_by_rrpath_rev(svn_branch_el_rev_id_t **el_rev_p,
                           svnmover_wc_t *wc,
                           svn_revnum_t revnum,
-                          const char *rrpath,
+                          const char *branch_id,
+                          const char *relpath,
                           apr_pool_t *result_pool,
                           apr_pool_t *scratch_pool)
 {
@@ -690,21 +694,30 @@ find_el_rev_by_rrpath_rev(svn_branch_el_
     {
       const svn_branch_repos_t *repos = wc->working->branch->rev_root->repos;
 
-      SVN_ERR(svn_branch_repos_find_el_rev_by_path_rev(el_rev_p,
-                                                       rrpath,
-                                                       wc->top_branch_num,
-                                                       revnum, repos,
+      if (! branch_id)
+        branch_id = wc->base->branch_id;
+      SVN_ERR(svn_branch_repos_find_el_rev_by_path_rev(el_rev_p, repos,
+                                                       revnum,
+                                                       branch_id,
+                                                       relpath,
                                                        result_pool,
                                                        scratch_pool));
     }
   else
     {
+      svn_branch_state_t *branch
+        = branch_id ? svn_branch_revision_root_get_branch_by_id(
+                        wc->working->branch->rev_root, branch_id, scratch_pool)
+                    : wc->working->branch;
       svn_branch_el_rev_id_t *el_rev = apr_palloc(result_pool, 
sizeof(*el_rev));
 
-      svn_branch_find_nested_branch_element_by_rrpath(
+      if (! branch)
+        return svn_error_createf(SVN_ERR_BRANCHING, NULL,
+                                 _("Branch %s not found in working state"),
+                                 branch_id);
+      svn_branch_find_nested_branch_element_by_relpath(
         &el_rev->branch, &el_rev->eid,
-        wc->working->branch,
-        rrpath, scratch_pool);
+        branch, relpath, scratch_pool);
       el_rev->rev = SVN_INVALID_REVNUM;
       *el_rev_p = el_rev;
     }
@@ -2654,10 +2667,14 @@ execute(svnmover_wc_t *wc,
 
               arg[j]->path_name = svn_relpath_basename(rrpath, NULL);
               SVN_ERR(find_el_rev_by_rrpath_rev(&arg[j]->el_rev, wc,
-                                                arg[j]->revnum, rrpath,
+                                                arg[j]->revnum,
+                                                action->branch_id[j],
+                                                rrpath,
                                                 iterpool, iterpool));
               SVN_ERR(find_el_rev_by_rrpath_rev(&arg[j]->parent_el_rev, wc,
-                                                arg[j]->revnum, parent_rrpath,
+                                                arg[j]->revnum,
+                                                action->branch_id[j],
+                                                parent_rrpath,
                                                 iterpool, iterpool));
             }
         }
@@ -2778,7 +2795,6 @@ execute(svnmover_wc_t *wc,
             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;
           }
@@ -3322,6 +3338,16 @@ parse_actions(apr_array_header_t **actio
                                        "Argument '%s' is a URL; use "
                                        "--root-url (-U) instead", path);
             }
+          /* Parse "^B<branch-id>/path" syntax. */
+          if (strncmp("^B", path, 2) == 0)
+            {
+              const char *slash = strchr(path, '/');
+
+              action->branch_id[k]
+                = slash ? apr_pstrndup(pool, path + 1, slash - (path + 1))
+                        : path + 1;
+              path = slash ? slash + 1 : "";
+            }
           /* These args must be relpaths, except for the 'local file' arg
              of a 'put' command. */
           if (! svn_relpath_is_canonical(path)
@@ -3731,7 +3757,7 @@ sub_main(int *exit_code, int argc, const
 
   SVN_ERR(wc_create(&wc,
                     anchor_url, base_revision,
-                    atoi(branch_id + 1) /*top_branch_num*/, branch_id,
+                    branch_id,
                     ctx, pool, pool));
 
   do

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=1696816&r1=1696815&r2=1696816&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnmover/svnmover.h 
(original)
+++ subversion/branches/move-tracking-2/subversion/svnmover/svnmover.h Thu Aug 
20 16:56:11 2015
@@ -54,7 +54,6 @@ typedef struct svnmover_wc_t
 
   svn_ra_session_t *ra_session;
   svn_editor3_t *editor;
-  int top_branch_num;
 
   /* Base and working versions. */
   svnmover_wc_version_t *base, *working;


Reply via email to