Return-Path: X-Original-To: apmail-subversion-commits-archive@minotaur.apache.org Delivered-To: apmail-subversion-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 7BA4B1896B for ; Wed, 19 Aug 2015 14:13:59 +0000 (UTC) Received: (qmail 23671 invoked by uid 500); 19 Aug 2015 14:13:50 -0000 Delivered-To: apmail-subversion-commits-archive@subversion.apache.org Received: (qmail 23540 invoked by uid 500); 19 Aug 2015 14:13:50 -0000 Mailing-List: contact commits-help@subversion.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@subversion.apache.org Delivered-To: mailing list commits@subversion.apache.org Received: (qmail 23441 invoked by uid 99); 19 Aug 2015 14:13:49 -0000 Received: from eris.apache.org (HELO hades.apache.org) (140.211.11.105) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 19 Aug 2015 14:13:49 +0000 Received: from hades.apache.org (localhost [127.0.0.1]) by hades.apache.org (ASF Mail Server at hades.apache.org) with ESMTP id C0F10AC085A for ; Wed, 19 Aug 2015 14:13:49 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit 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 -0000 To: commits@subversion.apache.org From: julianfoad@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20150819141349.C0F10AC085A@hades.apache.org> 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 tbranch (The syntax is redundant, as implies .) TODO: * change svnmover syntax so that paths given are relative to the branch designated by the "-B" option; * mkbranch * rmbranch * command-line syntax for addressing things in other top-level branches, e.g. @[].[B] or ^B/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 does not exist in r; 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);