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/08/19 16:13:49 UTC
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
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, ¤t,
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);