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/12/04 13:23:33 UTC
svn commit: r1717949 -
/subversion/trunk/subversion/libsvn_delta/branch_nested.c
Author: julianfoad
Date: Fri Dec 4 12:23:33 2015
New Revision: 1717949
URL: http://svn.apache.org/viewvc?rev=1717949&view=rev
Log:
In 'svnmover', allow a couple of nested-branching functions to operate on a
non-flat branch hierarchy without raising an assertion failure.
The specific case this enables is where a branch-root element points to a
nested branch that doesn't currently exist. No test currently requires this,
but it makes the functions more widely applicable for future use.
* subversion/libsvn_delta/branch_nested.c
(svn_branch__get_immediate_subbranch_eids): New, extracted...
(svn_branch__get_immediate_subbranches): ... from here.
(svn_branch__get_subtree,
svn_branch__find_nested_branch_element_by_relpath): Use it, and ignore
any subbranch-root element that points to a nonexistent nested branch
instead of raising an assertion failure.
Modified:
subversion/trunk/subversion/libsvn_delta/branch_nested.c
Modified: subversion/trunk/subversion/libsvn_delta/branch_nested.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_delta/branch_nested.c?rev=1717949&r1=1717948&r2=1717949&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_delta/branch_nested.c (original)
+++ subversion/trunk/subversion/libsvn_delta/branch_nested.c Fri Dec 4 12:23:33 2015
@@ -120,15 +120,17 @@ svn_branch__get_subbranch_at_eid(svn_bra
return SVN_NO_ERROR;
}
-svn_error_t *
-svn_branch__get_immediate_subbranches(svn_branch__state_t *branch,
- apr_array_header_t **subbranches_p,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
+/* Set *SUBBRANCH_EIDS_P an array of EIDs of the subbranch-root elements in
+ * BRANCH.
+ */
+static svn_error_t *
+svn_branch__get_immediate_subbranch_eids(svn_branch__state_t *branch,
+ apr_array_header_t **subbranch_eids_p,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
- apr_array_header_t *subbranches
- = apr_array_make(result_pool, 0, sizeof(void *));
- const char *branch_id = svn_branch__get_id(branch, scratch_pool);
+ apr_array_header_t *subbranch_eids
+ = apr_array_make(result_pool, 0, sizeof(int));
svn_element__tree_t *elements;
apr_hash_index_t *hi;
@@ -141,16 +143,39 @@ svn_branch__get_immediate_subbranches(sv
if (element->payload->is_subbranch_root)
{
- const char *subbranch_id
- = svn_branch__id_nest(branch_id, eid, scratch_pool);
- svn_branch__state_t *subbranch
- = svn_branch__txn_get_branch_by_id(branch->txn, subbranch_id,
- scratch_pool);
-
- SVN_ERR_ASSERT_NO_RETURN(subbranch);
- APR_ARRAY_PUSH(subbranches, void *) = subbranch;
+ APR_ARRAY_PUSH(subbranch_eids, int) = eid;
}
}
+ *subbranch_eids_p = subbranch_eids;
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_branch__get_immediate_subbranches(svn_branch__state_t *branch,
+ apr_array_header_t **subbranches_p,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ apr_array_header_t *subbranch_eids;
+ apr_array_header_t *subbranches
+ = apr_array_make(result_pool, 0, sizeof(void *));
+ const char *branch_id = svn_branch__get_id(branch, scratch_pool);
+ int i;
+
+ SVN_ERR(svn_branch__get_immediate_subbranch_eids(branch, &subbranch_eids,
+ scratch_pool, scratch_pool));
+ for (i = 0; i < subbranch_eids->nelts; i++)
+ {
+ int eid = APR_ARRAY_IDX(subbranch_eids, i, int);
+ const char *subbranch_id
+ = svn_branch__id_nest(branch_id, eid, scratch_pool);
+ svn_branch__state_t *subbranch
+ = svn_branch__txn_get_branch_by_id(branch->txn, subbranch_id,
+ scratch_pool);
+
+ SVN_ERR_ASSERT_NO_RETURN(subbranch);
+ APR_ARRAY_PUSH(subbranches, void *) = subbranch;
+ }
*subbranches_p = subbranches;
return SVN_NO_ERROR;
}
@@ -175,7 +200,7 @@ svn_branch__get_subtree(svn_branch__stat
{
svn_element__tree_t *element_tree;
svn_branch__subtree_t *new_subtree;
- apr_array_header_t *subbranches;
+ apr_array_header_t *subbranch_eids;
int i;
apr_pool_t *iterpool = result_pool; /* ### not a proper iterpool */
@@ -188,17 +213,13 @@ svn_branch__get_subtree(svn_branch__stat
result_pool);
/* Add subbranches */
- SVN_ERR(svn_branch__get_immediate_subbranches(branch, &subbranches,
- result_pool, result_pool));
- for (i = 0; i < subbranches->nelts; i++)
+ SVN_ERR(svn_branch__get_immediate_subbranch_eids(branch, &subbranch_eids,
+ result_pool, result_pool));
+ for (i = 0; i < subbranch_eids->nelts; i++)
{
- svn_branch__state_t *subbranch = APR_ARRAY_IDX(subbranches, i, void *);
- const char *outer_bid;
- int outer_eid;
+ int outer_eid = APR_ARRAY_IDX(subbranch_eids, i, int);
const char *subbranch_relpath_in_subtree;
- svn_branch__id_unnest(&outer_bid, &outer_eid, subbranch->bid,
- iterpool);
subbranch_relpath_in_subtree
= svn_element__tree_get_path_by_eid(new_subtree->tree, outer_eid,
iterpool);
@@ -206,13 +227,19 @@ svn_branch__get_subtree(svn_branch__stat
/* Is it pathwise at or below EID? If so, add it into the subtree. */
if (subbranch_relpath_in_subtree)
{
+ svn_branch__state_t *subbranch;
svn_branch__subtree_t *this_subtree;
- SVN_ERR(svn_branch__get_subtree(subbranch, &this_subtree,
- svn_branch__root_eid(subbranch),
- result_pool));
- svn_eid__hash_set(new_subtree->subbranches, outer_eid,
- this_subtree);
+ SVN_ERR(svn_branch__get_subbranch_at_eid(branch, &subbranch,
+ outer_eid, iterpool));
+ if (subbranch)
+ {
+ SVN_ERR(svn_branch__get_subtree(subbranch, &this_subtree,
+ svn_branch__root_eid(subbranch),
+ result_pool));
+ svn_eid__hash_set(new_subtree->subbranches, outer_eid,
+ this_subtree);
+ }
}
}
*subtree_p = new_subtree;
@@ -302,36 +329,45 @@ svn_branch__find_nested_branch_element_b
{
/* The path we're looking for is (path-wise) in this branch. See if it
is also in a sub-branch. */
+ /* Loop invariants: RELPATH is the path we're looking for, relative to
+ ROOT_BRANCH which is the current level of nesting that we've descended
+ into. */
while (TRUE)
{
- apr_array_header_t *subbranches;
+ apr_array_header_t *subbranch_eids;
int i;
svn_boolean_t found = FALSE;
- SVN_ERR(svn_branch__get_immediate_subbranches(root_branch, &subbranches,
- scratch_pool, scratch_pool));
- for (i = 0; i < subbranches->nelts; i++)
+ SVN_ERR(svn_branch__get_immediate_subbranch_eids(
+ root_branch, &subbranch_eids, scratch_pool, scratch_pool));
+ for (i = 0; i < subbranch_eids->nelts; i++)
{
- svn_branch__state_t *subbranch = APR_ARRAY_IDX(subbranches, i, void *);
- svn_branch__state_t *outer_branch;
- int outer_eid;
+ int outer_eid = APR_ARRAY_IDX(subbranch_eids, i, int);
const char *relpath_to_subbranch;
const char *relpath_in_subbranch;
- svn_branch__get_outer_branch_and_eid(&outer_branch, &outer_eid,
- subbranch, scratch_pool);
-
+ /* Check whether the RELPATH we're looking for is within this
+ subbranch at OUTER_EID. If it is, recurse in the subbranch. */
relpath_to_subbranch
= svn_branch__get_path_by_eid(root_branch, 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;
+ svn_branch__state_t *subbranch;
+
+ SVN_ERR(svn_branch__get_subbranch_at_eid(
+ root_branch, &subbranch, outer_eid, scratch_pool));
+ /* If the branch hierarchy is not 'flat' then we might find
+ there is no actual branch where the subbranch-root element
+ says there should be one. In that case, ignore it. */
+ if (subbranch)
+ {
+ root_branch = subbranch;
+ relpath = relpath_in_subbranch;
+ found = TRUE;
+ break;
+ }
}
}
if (! found)