Copied: subversion/branches/move-tracking-2/subversion/libsvn_delta/branch_nested.c (from r1708080, 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_nested.c?p2=subversion/branches/move-tracking-2/subversion/libsvn_delta/branch_nested.c&p1=subversion/branches/move-tracking-2/subversion/libsvn_delta/branch.c&r1=1708080&r2=1708550&rev=1708550&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/libsvn_delta/branch.c (original) +++ subversion/branches/move-tracking-2/subversion/libsvn_delta/branch_nested.c Wed Oct 14 06:38:16 2015 @@ -1,5 +1,5 @@ /* - * branch.c : Element-Based Branching and Move Tracking. + * branch_nested.c : Nested Branches * * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one @@ -29,513 +29,145 @@ #include "svn_hash.h" #include "svn_iter.h" -#include "private/svn_element.h" -#include "private/svn_branch.h" -#include "private/svn_sorts_private.h" +#include "private/svn_branch_nested.h" +#include "private/svn_branch_repos.h" #include "svn_private_config.h" -/* Is EID allocated (no matter whether an element with this id exists)? */ -#define EID_IS_ALLOCATED(branch, eid) \ - ((eid) >= (branch)->rev_root->first_eid && (eid) < (branch)->rev_root->next_eid) - -#define IS_BRANCH_ROOT_EID(branch, eid) \ - ((eid) == (branch)->root_eid) - -/* Is BRANCH1 the same branch as BRANCH2? Compare by full branch-ids; don't - require identical branch objects. */ -#define BRANCH_IS_SAME_BRANCH(branch1, branch2, scratch_pool) \ - (strcmp(svn_branch_get_id(branch1, scratch_pool), \ - svn_branch_get_id(branch2, scratch_pool)) == 0) - -/* Is BRANCH1 an immediate child of BRANCH2? Compare by full branch-ids; don't - require identical branch objects. */ -#define BRANCH_IS_CHILD_OF_BRANCH(branch1, branch2, scratch_pool) \ - ((branch1)->outer_branch && \ - BRANCH_IS_SAME_BRANCH((branch1)->outer_branch, branch2, scratch_pool)) - -svn_branch_revision_root_t * -svn_branch_revision_root_create(svn_branch_repos_t *repos, - svn_revnum_t rev, - svn_revnum_t base_rev, - apr_pool_t *result_pool) -{ - svn_branch_revision_root_t *rev_root - = apr_pcalloc(result_pool, sizeof(*rev_root)); - - rev_root->repos = repos; - rev_root->rev = rev; - rev_root->base_rev = base_rev; - rev_root->root_branches = apr_array_make(result_pool, 0, sizeof(void *)); - rev_root->branches = svn_array_make(result_pool); - return rev_root; -} - -int -svn_branch_txn_new_eid(svn_branch_revision_root_t *rev_root) -{ - int eid = (rev_root->first_eid < 0) ? rev_root->first_eid - 1 : -2; - - rev_root->first_eid = eid; - return eid; +void +svn_branch_get_outer_branch_and_eid(svn_branch_state_t **outer_branch_p, + int *outer_eid_p, + const svn_branch_state_t *branch, + apr_pool_t *scratch_pool) +{ + const char *outer_bid; + + svn_branch_id_unnest(&outer_bid, outer_eid_p, branch->bid, scratch_pool); + *outer_branch_p = NULL; + if (outer_bid) + { + *outer_branch_p + = svn_branch_revision_root_get_branch_by_id(branch->rev_root, outer_bid, + scratch_pool); + } } -/* Change txn-local EIDs (negative integers) in BRANCH to revision EIDs, by - * assigning a new revision-EID (positive integer) for each one. - */ -static svn_error_t * -branch_finalize_eids(svn_branch_state_t *branch, - int mapping_offset, - apr_pool_t *scratch_pool) +const char * +svn_branch_get_root_rrpath(const svn_branch_state_t *branch, + apr_pool_t *result_pool) { - apr_hash_index_t *hi; + svn_branch_state_t *outer_branch; + int outer_eid; + const char *root_rrpath; - if (branch->root_eid < -1) + svn_branch_get_outer_branch_and_eid(&outer_branch, &outer_eid, branch, + result_pool); + if (outer_branch) { - branch->root_eid = mapping_offset - branch->root_eid; + root_rrpath + = svn_branch_get_rrpath_by_eid(outer_branch, outer_eid, result_pool); } - - if (branch->outer_eid < -1) + else { - branch->outer_eid = mapping_offset - branch->outer_eid; + root_rrpath = ""; } - for (hi = apr_hash_first(scratch_pool, branch->e_map); - hi; hi = apr_hash_next(hi)) - { - int old_eid = svn_int_hash_this_key(hi); - svn_branch_el_rev_content_t *element = apr_hash_this_val(hi); - - if (old_eid < -1) - { - int new_eid = mapping_offset - old_eid; - - svn_int_hash_set(branch->e_map, old_eid, NULL); - svn_int_hash_set(branch->e_map, new_eid, element); - } - if (element->parent_eid < -1) - { - element->parent_eid = mapping_offset - element->parent_eid; - } - } - return SVN_NO_ERROR; + SVN_ERR_ASSERT_NO_RETURN(root_rrpath); + return root_rrpath; } -svn_error_t * -svn_branch_txn_finalize_eids(svn_branch_revision_root_t *txn, - apr_pool_t *scratch_pool) +const char * +svn_branch_get_rrpath_by_eid(const svn_branch_state_t *branch, + int eid, + apr_pool_t *result_pool) { - int n_txn_eids = (-1) - txn->first_eid; - int mapping_offset; - int i; - - if (txn->first_eid == 0) - return SVN_NO_ERROR; - - /* mapping from txn-local (negative) EID to committed (positive) EID is: - txn_local_eid == -2 => committed_eid := (txn.next_eid + 0) - txn_local_eid == -3 => committed_eid := (txn.next_eid + 1) ... */ - mapping_offset = txn->next_eid - 2; + const char *path = svn_branch_get_path_by_eid(branch, eid, result_pool); + const char *rrpath = NULL; - for (i = 0; i < txn->branches->nelts; i++) + if (path) { - svn_branch_state_t *b = APR_ARRAY_IDX(txn->branches, i, void *); - - SVN_ERR(branch_finalize_eids(b, mapping_offset, scratch_pool)); + rrpath = svn_relpath_join(svn_branch_get_root_rrpath(branch, result_pool), + path, result_pool); } - - txn->next_eid += n_txn_eids; - txn->first_eid = 0; - return SVN_NO_ERROR; -} - -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) -{ - return rev_root->branches; + return rrpath; } svn_branch_state_t * -svn_branch_revision_root_get_branch_by_id(const svn_branch_revision_root_t *rev_root, - const char *branch_id, - apr_pool_t *scratch_pool) +svn_branch_get_subbranch_at_eid(svn_branch_state_t *branch, + int eid, + apr_pool_t *scratch_pool) { - SVN_ITER_T(svn_branch_state_t) *bi; - svn_branch_state_t *branch = NULL; + svn_branch_el_rev_content_t *element = svn_branch_get_element(branch, eid); - for (SVN_ARRAY_ITER(bi, rev_root->branches, scratch_pool)) + if (element && element->payload->is_subbranch_root) { - svn_branch_state_t *b = bi->val; + const char *branch_id = svn_branch_get_id(branch, scratch_pool); + const char *subbranch_id = svn_branch_id_nest(branch_id, eid, + scratch_pool); - if (strcmp(svn_branch_get_id(b, scratch_pool), branch_id) == 0) - { - branch = b; - break; - } + return svn_branch_revision_root_get_branch_by_id(branch->rev_root, + subbranch_id, + scratch_pool); } - return branch; + return NULL; } -static void -branch_validate_element(const svn_branch_state_t *branch, - int eid, - const svn_branch_el_rev_content_t *element); - -/* Assert BRANCH satisfies all its invariants. - */ -static void -assert_branch_state_invariants(const svn_branch_state_t *branch, - apr_pool_t *scratch_pool) +apr_array_header_t * +svn_branch_get_immediate_subbranches(svn_branch_state_t *branch, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { + svn_array_t *subbranches = svn_array_make(result_pool); + const char *branch_id = svn_branch_get_id(branch, scratch_pool); apr_hash_index_t *hi; - assert(branch->rev_root); - if (branch->outer_branch) - { - assert(EID_IS_ALLOCATED(branch, branch->outer_eid)); - } - assert(branch->outer_eid != -1); - assert(branch->e_map); - - /* Validate elements in the map */ for (hi = apr_hash_first(scratch_pool, branch->e_map); hi; hi = apr_hash_next(hi)) { - branch_validate_element(branch, svn_int_hash_this_key(hi), - apr_hash_this_val(hi)); - } -} - -svn_branch_state_t * -svn_branch_state_create(svn_branch_rev_bid_t *predecessor, - int root_eid, - svn_branch_revision_root_t *rev_root, - svn_branch_state_t *outer_branch, - int outer_eid, - apr_pool_t *result_pool) -{ - svn_branch_state_t *b = apr_pcalloc(result_pool, sizeof(*b)); - - b->predecessor = svn_branch_rev_bid_dup(predecessor, result_pool); - b->root_eid = root_eid; - b->rev_root = rev_root; - b->e_map = apr_hash_make(result_pool); - b->outer_branch = outer_branch; - b->outer_eid = outer_eid; - assert_branch_state_invariants(b, result_pool); - return b; -} - -svn_branch_el_rev_id_t * -svn_branch_el_rev_id_create(svn_branch_state_t *branch, - int eid, - svn_revnum_t rev, - apr_pool_t *result_pool) -{ - svn_branch_el_rev_id_t *id = apr_palloc(result_pool, sizeof(*id)); - - id->branch = branch; - id->eid = eid; - id->rev = rev; - return id; -} - -svn_branch_rev_bid_eid_t * -svn_branch_rev_bid_eid_create(svn_revnum_t rev, - const char *branch_id, - int eid, - apr_pool_t *result_pool) -{ - svn_branch_rev_bid_eid_t *id = apr_palloc(result_pool, sizeof(*id)); - - id->bid = branch_id; - id->eid = eid; - id->rev = rev; - return id; -} - -svn_branch_rev_bid_eid_t * -svn_branch_rev_bid_eid_dup(const svn_branch_rev_bid_eid_t *old_id, - apr_pool_t *result_pool) -{ - svn_branch_rev_bid_eid_t *id; - - if (! old_id) - return NULL; - - id = apr_pmemdup(result_pool, old_id, sizeof(*id)); - id->bid = apr_pstrdup(result_pool, old_id->bid); - return id; -} - -svn_branch_rev_bid_t * -svn_branch_rev_bid_create(svn_revnum_t rev, - const char *branch_id, - apr_pool_t *result_pool) -{ - svn_branch_rev_bid_t *id = apr_palloc(result_pool, sizeof(*id)); - - id->bid = branch_id; - id->rev = rev; - return id; -} - -svn_branch_rev_bid_t * -svn_branch_rev_bid_dup(const svn_branch_rev_bid_t *old_id, - apr_pool_t *result_pool) -{ - svn_branch_rev_bid_t *id; - - if (! old_id) - return NULL; - - id = apr_pmemdup(result_pool, old_id, sizeof(*id)); - id->bid = apr_pstrdup(result_pool, old_id->bid); - return id; -} - -svn_branch_el_rev_content_t * -svn_branch_el_rev_content_create(svn_branch_eid_t parent_eid, - const char *name, - const svn_element_payload_t *payload, - apr_pool_t *result_pool) -{ - svn_branch_el_rev_content_t *content - = apr_palloc(result_pool, sizeof(*content)); - - content->parent_eid = parent_eid; - content->name = apr_pstrdup(result_pool, name); - content->payload = svn_element_payload_dup(payload, result_pool); - return content; -} - -svn_branch_el_rev_content_t * -svn_branch_el_rev_content_dup(const svn_branch_el_rev_content_t *old, - apr_pool_t *result_pool) -{ - svn_branch_el_rev_content_t *content - = apr_pmemdup(result_pool, old, sizeof(*content)); - - content->name = apr_pstrdup(result_pool, old->name); - content->payload = svn_element_payload_dup(old->payload, result_pool); - return content; -} - -svn_boolean_t -svn_branch_el_rev_content_equal(const svn_branch_el_rev_content_t *content_left, - const svn_branch_el_rev_content_t *content_right, - apr_pool_t *scratch_pool) -{ - if (!content_left && !content_right) - { - return TRUE; - } - else if (!content_left || !content_right) - { - return FALSE; - } - - if (content_left->parent_eid != content_right->parent_eid) - { - return FALSE; - } - if (strcmp(content_left->name, content_right->name) != 0) - { - return FALSE; - } - if (! svn_element_payload_equal(content_left->payload, content_right->payload, - scratch_pool)) - { - return FALSE; - } - - return TRUE; -} - - -/* - * ======================================================================== - * Branch mappings - * ======================================================================== - */ - -svn_branch_subtree_t * -svn_branch_subtree_create(apr_hash_t *e_map, - int root_eid, - apr_pool_t *result_pool) -{ - svn_branch_subtree_t *subtree = apr_pcalloc(result_pool, sizeof(*subtree)); - - subtree->e_map = e_map ? apr_hash_copy(result_pool, e_map) - : apr_hash_make(result_pool); - subtree->root_eid = root_eid; - subtree->subbranches = apr_hash_make(result_pool); - return subtree; -} - -svn_branch_subtree_t * -svn_branch_subtree_get_subbranch_at_eid(svn_branch_subtree_t *subtree, - int eid, - apr_pool_t *result_pool) -{ - subtree = svn_int_hash_get(subtree->subbranches, eid); - - return subtree; -} - -/* Validate that ELEMENT is suitable for a mapping of BRANCH:EID. - * ELEMENT->payload may be null. - */ -static void -branch_validate_element(const svn_branch_state_t *branch, - int eid, - const svn_branch_el_rev_content_t *element) -{ - SVN_ERR_ASSERT_NO_RETURN(element); + int eid = svn_int_hash_this_key(hi); + svn_branch_el_rev_content_t *element = apr_hash_this_val(hi); - /* Parent EID must be valid and different from this element's EID, or -1 - iff this is the branch root element. */ - SVN_ERR_ASSERT_NO_RETURN( - IS_BRANCH_ROOT_EID(branch, eid) - ? (element->parent_eid == -1) - : (element->parent_eid != eid - && EID_IS_ALLOCATED(branch, element->parent_eid))); - - /* Element name must be given, and empty iff EID is the branch root. */ - SVN_ERR_ASSERT_NO_RETURN( - element->name - && IS_BRANCH_ROOT_EID(branch, eid) == (*element->name == '\0')); + 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_revision_root_get_branch_by_id(branch->rev_root, + subbranch_id, + scratch_pool); - SVN_ERR_ASSERT_NO_RETURN(svn_element_payload_invariants(element->payload)); - if (element->payload->is_subbranch_root) - { - /* a subbranch root element must not be the branch root element */ - SVN_ERR_ASSERT_NO_RETURN(eid != branch->root_eid); + SVN_ARRAY_PUSH(subbranches) = subbranch; + } } + return subbranches; } -apr_hash_t * -svn_branch_get_elements(svn_branch_state_t *branch) -{ - return branch->e_map; -} - -svn_branch_el_rev_content_t * -svn_branch_get_element(const svn_branch_state_t *branch, - int eid) -{ - svn_branch_el_rev_content_t *element; - - SVN_ERR_ASSERT_NO_RETURN(EID_IS_ALLOCATED(branch, eid)); - - element = svn_int_hash_get(branch->e_map, eid); - - if (element) - branch_validate_element(branch, eid, element); - return element; -} - -/* In BRANCH, set element EID to ELEMENT. - * - * If ELEMENT is null, delete element EID. Otherwise, ELEMENT->payload may be - * null meaning it is a subbranch-root. - * - * Assume ELEMENT is already allocated with sufficient lifetime. - */ -static void -branch_map_set(svn_branch_state_t *branch, - int eid, - svn_branch_el_rev_content_t *element) -{ - apr_pool_t *map_pool = apr_hash_pool_get(branch->e_map); - - SVN_ERR_ASSERT_NO_RETURN(EID_IS_ALLOCATED(branch, eid)); - if (element) - branch_validate_element(branch, eid, element); - - svn_int_hash_set(branch->e_map, eid, element); - assert_branch_state_invariants(branch, map_pool); -} - -void -svn_branch_delete_element(svn_branch_state_t *branch, - int eid) -{ - SVN_ERR_ASSERT_NO_RETURN(EID_IS_ALLOCATED(branch, eid)); - - branch_map_set(branch, eid, NULL); -} - -void -svn_branch_update_element(svn_branch_state_t *branch, - int eid, - svn_branch_eid_t new_parent_eid, - const char *new_name, - const svn_element_payload_t *new_payload) -{ - apr_pool_t *map_pool = apr_hash_pool_get(branch->e_map); - svn_branch_el_rev_content_t *element - = svn_branch_el_rev_content_create(new_parent_eid, new_name, new_payload, - map_pool); - - /* EID must be a valid element id */ - SVN_ERR_ASSERT_NO_RETURN(EID_IS_ALLOCATED(branch, eid)); - /* NEW_PAYLOAD must be specified, either in full or by reference */ - SVN_ERR_ASSERT_NO_RETURN(new_payload); - - /* Insert the new version */ - branch_map_set(branch, eid, element); -} - -static void -map_purge_orphans(apr_hash_t *e_map, - int root_eid, - apr_pool_t *scratch_pool); - svn_branch_subtree_t * -svn_branch_get_subtree(const svn_branch_state_t *branch, +svn_branch_get_subtree(svn_branch_state_t *branch, int eid, apr_pool_t *result_pool) { svn_branch_subtree_t *new_subtree; - svn_branch_el_rev_content_t *subtree_root_element; SVN_ITER_T(svn_branch_state_t) *bi; SVN_BRANCH_SEQUENCE_POINT(branch); - new_subtree = svn_branch_subtree_create(branch->e_map, eid, - result_pool); - new_subtree->predecessor = svn_branch_rev_bid_dup(branch->predecessor, - result_pool); - - /* Purge orphans */ - map_purge_orphans(new_subtree->e_map, new_subtree->root_eid, result_pool); - - /* Remove 'parent' and 'name' attributes from subtree root element */ - subtree_root_element - = svn_int_hash_get(new_subtree->e_map, new_subtree->root_eid); - svn_int_hash_set(new_subtree->e_map, new_subtree->root_eid, - svn_branch_el_rev_content_create( - -1, "", subtree_root_element->payload, result_pool)); + new_subtree + = svn_branch_get_subtree_n(branch, eid, result_pool); /* Add subbranches */ for (SVN_ARRAY_ITER(bi, svn_branch_get_immediate_subbranches( branch, result_pool, result_pool), result_pool)) { svn_branch_state_t *subbranch = bi->val; - const char *subbranch_relpath_in_subtree - = svn_branch_subtree_get_path_by_eid(new_subtree, subbranch->outer_eid, + const char *outer_bid; + int outer_eid; + const char *subbranch_relpath_in_subtree; + + svn_branch_id_unnest(&outer_bid, &outer_eid, subbranch->bid, + bi->iterpool); + subbranch_relpath_in_subtree + = svn_branch_subtree_get_path_by_eid(new_subtree, outer_eid, bi->iterpool); /* Is it pathwise at or below EID? If so, add it into the subtree. */ @@ -544,285 +176,19 @@ svn_branch_get_subtree(const svn_branch_ svn_branch_subtree_t *this_subtree = svn_branch_get_subtree(subbranch, subbranch->root_eid, result_pool); - svn_int_hash_set(new_subtree->subbranches, subbranch->outer_eid, + svn_int_hash_set(new_subtree->subbranches, outer_eid, this_subtree); } } return new_subtree; } -/* Purge entries from E_MAP that don't connect, via parent directory hierarchy, - * to ROOT_EID. In other words, remove elements that have been implicitly - * deleted. - * - * ROOT_EID must be present in E_MAP. - * - * ### Does not detect cycles: current implementation will not purge a cycle - * that is disconnected from ROOT_EID. This could be a problem. - */ -static void -map_purge_orphans(apr_hash_t *e_map, - int root_eid, - apr_pool_t *scratch_pool) -{ - apr_hash_index_t *hi; - svn_boolean_t changed; - - SVN_ERR_ASSERT_NO_RETURN(svn_int_hash_get(e_map, root_eid)); - - do - { - changed = FALSE; - - for (hi = apr_hash_first(scratch_pool, e_map); - hi; hi = apr_hash_next(hi)) - { - int this_eid = svn_int_hash_this_key(hi); - svn_branch_el_rev_content_t *this_element = apr_hash_this_val(hi); - - if (this_eid != root_eid) - { - svn_branch_el_rev_content_t *parent_element - = svn_int_hash_get(e_map, this_element->parent_eid); - - /* Purge if parent is deleted */ - if (! parent_element) - { - SVN_DBG(("purge orphan: e%d", this_eid)); - svn_int_hash_set(e_map, this_eid, NULL); - changed = TRUE; - } - else - SVN_ERR_ASSERT_NO_RETURN( - ! parent_element->payload->is_subbranch_root); - } - } - } - while (changed); -} - -void -svn_branch_purge_r(svn_branch_state_t *branch, - apr_pool_t *scratch_pool) -{ - SVN_ITER_T(svn_branch_state_t) *bi; - - /* first, remove elements that have no parent element */ - map_purge_orphans(branch->e_map, branch->root_eid, scratch_pool); - - /* second, remove subbranches that have no subbranch-root element */ - for (SVN_ARRAY_ITER(bi, svn_branch_get_immediate_subbranches( - branch, scratch_pool, scratch_pool), scratch_pool)) - { - svn_branch_state_t *b = bi->val; - - if (svn_branch_get_element(branch, b->outer_eid)) - { - svn_branch_purge_r(b, bi->iterpool); - } - else - { - svn_branch_delete_branch_r(b, bi->iterpool); - } - } -} - -const char * -svn_branch_get_root_rrpath(const svn_branch_state_t *branch, - apr_pool_t *result_pool) -{ - const char *root_rrpath; - - if (branch->outer_branch) - { - root_rrpath - = svn_branch_get_rrpath_by_eid(branch->outer_branch, branch->outer_eid, - result_pool); - } - else - { - root_rrpath = ""; - } - - SVN_ERR_ASSERT_NO_RETURN(root_rrpath); - return root_rrpath; -} - -const char * -svn_branch_subtree_get_path_by_eid(const svn_branch_subtree_t *subtree, - int eid, - apr_pool_t *result_pool) -{ - const char *path = ""; - svn_branch_el_rev_content_t *element; - - for (; eid != subtree->root_eid; eid = element->parent_eid) - { - element = svn_int_hash_get(subtree->e_map, eid); - if (! element) - return NULL; - path = svn_relpath_join(element->name, path, result_pool); - } - SVN_ERR_ASSERT_NO_RETURN(eid == subtree->root_eid); - return path; -} - -const char * -svn_branch_get_path_by_eid(const svn_branch_state_t *branch, - int eid, - apr_pool_t *result_pool) -{ - const char *path = ""; - svn_branch_el_rev_content_t *element; - - SVN_ERR_ASSERT_NO_RETURN(EID_IS_ALLOCATED(branch, eid)); - - for (; ! IS_BRANCH_ROOT_EID(branch, eid); eid = element->parent_eid) - { - element = svn_branch_get_element(branch, eid); - if (! element) - return NULL; - path = svn_relpath_join(element->name, path, result_pool); - } - SVN_ERR_ASSERT_NO_RETURN(IS_BRANCH_ROOT_EID(branch, eid)); - return path; -} - -const char * -svn_branch_get_rrpath_by_eid(const svn_branch_state_t *branch, - int eid, - apr_pool_t *result_pool) -{ - const char *path = svn_branch_get_path_by_eid(branch, eid, result_pool); - const char *rrpath = NULL; - - if (path) - { - rrpath = svn_relpath_join(svn_branch_get_root_rrpath(branch, result_pool), - path, result_pool); - } - return rrpath; -} - -int -svn_branch_get_eid_by_path(const svn_branch_state_t *branch, - const char *path, - apr_pool_t *scratch_pool) -{ - apr_hash_index_t *hi; - - /* ### This is a crude, linear search */ - for (hi = apr_hash_first(scratch_pool, branch->e_map); - hi; hi = apr_hash_next(hi)) - { - int eid = svn_int_hash_this_key(hi); - const char *this_path = svn_branch_get_path_by_eid(branch, eid, - scratch_pool); - - if (! this_path) - { - /* Mapping is not complete; this element is in effect not present. */ - continue; - } - if (strcmp(path, this_path) == 0) - { - return eid; - } - } - - return -1; -} - -int -svn_branch_get_eid_by_rrpath(svn_branch_state_t *branch, - const char *rrpath, - apr_pool_t *scratch_pool) -{ - const char *path = svn_relpath_skip_ancestor(svn_branch_get_root_rrpath( - branch, scratch_pool), - rrpath); - int eid = -1; - - if (path) - { - eid = svn_branch_get_eid_by_path(branch, path, scratch_pool); - } - return eid; -} - svn_error_t * -svn_branch_map_add_subtree(svn_branch_state_t *to_branch, - int to_eid, - svn_branch_eid_t new_parent_eid, - const char *new_name, - svn_branch_subtree_t new_subtree, - apr_pool_t *scratch_pool) +svn_branch_instantiate_elements_r(svn_branch_state_t *to_branch, + svn_branch_subtree_t elements, + apr_pool_t *scratch_pool) { - apr_hash_index_t *hi; - svn_branch_el_rev_content_t *new_root_content; - - if (new_subtree.subbranches && apr_hash_count(new_subtree.subbranches)) - { - return svn_error_createf(SVN_ERR_BRANCHING, NULL, - _("Adding or copying a subtree containing " - "subbranches is not implemented")); - } - - /* Get a new EID for the root element, if not given. */ - if (to_eid == -1) - { - to_eid = svn_branch_txn_new_eid(to_branch->rev_root); - } - - /* Create the new subtree root element */ - new_root_content = svn_int_hash_get(new_subtree.e_map, new_subtree.root_eid); - svn_branch_update_element(to_branch, to_eid, - new_parent_eid, new_name, - new_root_content->payload); - - /* Process its immediate children */ - for (hi = apr_hash_first(scratch_pool, new_subtree.e_map); - hi; hi = apr_hash_next(hi)) - { - int this_from_eid = svn_int_hash_this_key(hi); - svn_branch_el_rev_content_t *from_element = apr_hash_this_val(hi); - - if (from_element->parent_eid == new_subtree.root_eid) - { - svn_branch_subtree_t this_subtree; - - /* Recurse. (We don't try to check whether it's a directory node, - as we might not have the node kind in the map.) */ - this_subtree.e_map = new_subtree.e_map; - this_subtree.root_eid = this_from_eid; - this_subtree.subbranches = apr_hash_make(scratch_pool); - SVN_ERR(svn_branch_map_add_subtree(to_branch, -1 /*to_eid*/, - to_eid, from_element->name, - this_subtree, scratch_pool)); - } - } - - return SVN_NO_ERROR; -} - -svn_error_t * -svn_branch_instantiate_elements(svn_branch_state_t *to_branch, - svn_branch_subtree_t elements, - apr_pool_t *scratch_pool) -{ - apr_hash_index_t *hi; - - /* Instantiate all the elements of NEW_SUBTREE */ - for (hi = apr_hash_first(scratch_pool, elements.e_map); - hi; hi = apr_hash_next(hi)) - { - int this_eid = svn_int_hash_this_key(hi); - svn_branch_el_rev_content_t *this_element = apr_hash_this_val(hi); - - branch_map_set(to_branch, this_eid, - svn_branch_el_rev_content_dup( - this_element, apr_hash_pool_get(to_branch->e_map))); - } + SVN_ERR(svn_branch_instantiate_elements(to_branch, elements, scratch_pool)); /* branch any subbranches */ { @@ -832,477 +198,26 @@ svn_branch_instantiate_elements(svn_bran { int this_outer_eid = svn_int_hash_this_key(bi->apr_hi); svn_branch_subtree_t *this_subtree = bi->val; + const char *new_branch_id; svn_branch_state_t *new_branch; /* branch this subbranch into NEW_BRANCH (recursing) */ - new_branch = svn_branch_add_new_branch(to_branch->rev_root, + new_branch_id = svn_branch_id_nest(to_branch->bid, this_outer_eid, + bi->iterpool); + new_branch = svn_branch_add_new_branch(new_branch_id, + to_branch->rev_root, this_subtree->predecessor, - to_branch, this_outer_eid, this_subtree->root_eid, bi->iterpool); - SVN_ERR(svn_branch_instantiate_elements(new_branch, *this_subtree, - bi->iterpool)); + SVN_ERR(svn_branch_instantiate_elements_r(new_branch, *this_subtree, + bi->iterpool)); } } return SVN_NO_ERROR; } -apr_array_header_t * -svn_branch_get_immediate_subbranches(const svn_branch_state_t *branch, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) -{ - svn_array_t *subbranches = svn_array_make(result_pool); - SVN_ITER_T(svn_branch_state_t) *bi; - - for (SVN_ARRAY_ITER(bi, branch->rev_root->branches, scratch_pool)) - { - /* Is it an immediate child? */ - if (bi->val->outer_branch == branch) - SVN_ARRAY_PUSH(subbranches) = bi->val; - } - return subbranches; -} - -svn_branch_state_t * -svn_branch_get_subbranch_at_eid(svn_branch_state_t *branch, - int eid, - apr_pool_t *scratch_pool) -{ - SVN_ITER_T(svn_branch_state_t) *bi; - - /* TODO: more efficient to search in branch->rev_root->branches */ - for (SVN_ARRAY_ITER(bi, svn_branch_get_immediate_subbranches( - branch, scratch_pool, scratch_pool), scratch_pool)) - { - if (bi->val->outer_eid == eid) - return bi->val; - } - return NULL; -} - -svn_branch_state_t * -svn_branch_add_new_branch(svn_branch_revision_root_t *rev_root, - svn_branch_rev_bid_t *predecessor, - 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); - SVN_ERR_ASSERT_NO_RETURN(root_eid != -1); - - if (! outer_branch) - outer_eid = rev_root->root_branches->nelts; - - new_branch = svn_branch_state_create(predecessor, root_eid, rev_root, - outer_branch, outer_eid, - rev_root->branches->pool); - - /* A branch must not already exist at this outer element */ - SVN_ERR_ASSERT_NO_RETURN(!outer_branch || - svn_branch_get_subbranch_at_eid( - outer_branch, outer_eid, scratch_pool) == NULL); - - SVN_ARRAY_PUSH(rev_root->branches) = new_branch; - if (!outer_branch) - SVN_ARRAY_PUSH(rev_root->root_branches) = new_branch; - - return new_branch; -} - -/* Remove branch BRANCH from the list of branches in REV_ROOT. - */ -static void -svn_branch_revision_root_delete_branch( - svn_branch_revision_root_t *rev_root, - svn_branch_state_t *branch, - apr_pool_t *scratch_pool) -{ - SVN_ITER_T(svn_branch_state_t) *bi; - - SVN_ERR_ASSERT_NO_RETURN(branch->rev_root == rev_root); - - for (SVN_ARRAY_ITER(bi, rev_root->branches, scratch_pool)) - { - if (bi->val == branch) - { - SVN_DBG(("deleting branch b%s e%d", - svn_branch_get_id(bi->val, bi->iterpool), - bi->val->root_eid)); - svn_sort__array_delete(rev_root->branches, bi->i, 1); - 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 -svn_branch_delete_branch_r(svn_branch_state_t *branch, - apr_pool_t *scratch_pool) -{ - SVN_ITER_T(svn_branch_state_t) *bi; - - for (SVN_ARRAY_ITER(bi, svn_branch_get_immediate_subbranches( - branch, scratch_pool, scratch_pool), scratch_pool)) - { - svn_branch_delete_branch_r(bi->val, bi->iterpool); - } - - svn_branch_revision_root_delete_branch(branch->rev_root, - branch, scratch_pool); -} - - -/* - * ======================================================================== - * Parsing and Serializing - * ======================================================================== - */ - -svn_string_t * -svn_branch_get_default_r0_metadata(apr_pool_t *result_pool) -{ - static const char *default_repos_info - = "r0: eids 0 1 branches 1\n" - "B0 root-eid 0 num-eids 1 # at /\n" - "e0: normal -1 .\n"; - - return svn_string_create(default_repos_info, result_pool); -} - -/* */ -static svn_error_t * -parse_branch_line(char *bid_p, - int *root_eid_p, - int *num_eids_p, - svn_branch_rev_bid_t **predecessor, - svn_stream_t *stream, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) -{ - svn_stringbuf_t *line; - svn_boolean_t eof; - int n; - svn_revnum_t pred_rev; - char pred_bid[1000]; - - /* Read a line */ - SVN_ERR(svn_stream_readline(stream, &line, "\n", &eof, scratch_pool)); - SVN_ERR_ASSERT(!eof); - - n = sscanf(line->data, "%s root-eid %d num-eids %d from r%ld.%s", - bid_p, root_eid_p, num_eids_p, &pred_rev, pred_bid); - SVN_ERR_ASSERT(n == 3 || n == 5); - - if (n == 5) - { - *predecessor = svn_branch_rev_bid_create(pred_rev, pred_bid, result_pool); - } - else - { - *predecessor = NULL; - } - - return SVN_NO_ERROR; -} - -/* */ -static svn_error_t * -parse_element_line(int *eid_p, - svn_boolean_t *is_subbranch_p, - int *parent_eid_p, - const char **name_p, - svn_stream_t *stream, - apr_pool_t *scratch_pool) -{ - svn_stringbuf_t *line; - svn_boolean_t eof; - char kind[10]; - int n; - int offset; - - /* Read a line */ - SVN_ERR(svn_stream_readline(stream, &line, "\n", &eof, scratch_pool)); - SVN_ERR_ASSERT(!eof); - - n = sscanf(line->data, "e%d: %9s %d%n", - eid_p, - kind, parent_eid_p, &offset); - SVN_ERR_ASSERT(n >= 3); /* C std is unclear on whether '%n' counts */ - SVN_ERR_ASSERT(line->data[offset] == ' '); - *name_p = line->data + offset + 1; - - *is_subbranch_p = (strcmp(kind, "subbranch") == 0); - - if (strcmp(*name_p, "(null)") == 0) - *name_p = NULL; - else if (strcmp(*name_p, ".") == 0) - *name_p = ""; - - return SVN_NO_ERROR; -} - -const char * -svn_branch_id_nest(const char *outer_bid, - int outer_eid, - apr_pool_t *result_pool) -{ - if (!outer_bid) - return apr_psprintf(result_pool, "B%d", outer_eid); - - return apr_psprintf(result_pool, "%s.%d", outer_bid, outer_eid); -} - -void -svn_branch_id_unnest(const char **outer_bid, - int *outer_eid, - const char *bid, - apr_pool_t *result_pool) -{ - char *last_dot = strrchr(bid, '.'); - - if (last_dot) /* BID looks like "B3.11" or "B3.11.22" etc. */ - { - *outer_bid = apr_pstrndup(result_pool, bid, last_dot - bid); - *outer_eid = atoi(last_dot + 1); - } - else /* looks like "B0" or B22" (with no dot) */ - { - *outer_bid = NULL; - *outer_eid = atoi(bid + 1); - } -} - -/* Create a new branch *NEW_BRANCH, initialized - * with info parsed from STREAM, allocated in RESULT_POOL. - */ -static svn_error_t * -svn_branch_state_parse(svn_branch_state_t **new_branch, - svn_branch_revision_root_t *rev_root, - svn_stream_t *stream, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) -{ - char bid[1000]; - int root_eid, num_eids; - svn_branch_rev_bid_t *predecessor; - svn_branch_state_t *branch_state; - svn_branch_state_t *outer_branch; - int outer_eid; - int i; - - SVN_ERR(parse_branch_line(bid, &root_eid, &num_eids, &predecessor, - stream, scratch_pool, scratch_pool)); - - /* Find the outer branch and outer EID */ - { - const char *outer_bid; - - svn_branch_id_unnest(&outer_bid, &outer_eid, bid, scratch_pool); - if (outer_bid) - { - outer_branch - = svn_branch_revision_root_get_branch_by_id(rev_root, outer_bid, - scratch_pool); - } - else - outer_branch = NULL; - } - branch_state = svn_branch_state_create(predecessor, root_eid, rev_root, - outer_branch, outer_eid, - result_pool); - - /* Read in the structure. Set the payload of each normal element to a - (branch-relative) reference. */ - for (i = 0; i < num_eids; i++) - { - int eid, this_parent_eid; - const char *this_name; - svn_boolean_t is_subbranch; - - SVN_ERR(parse_element_line(&eid, - &is_subbranch, &this_parent_eid, &this_name, - stream, scratch_pool)); - - if (this_name) - { - svn_element_payload_t *payload; - if (! is_subbranch) - { - payload = svn_element_payload_create_ref(rev_root->rev, bid, eid, - result_pool); - } - else - { - payload - = svn_element_payload_create_subbranch(result_pool); - } - svn_branch_update_element( - branch_state, eid, this_parent_eid, this_name, payload); - } - } - - *new_branch = branch_state; - return SVN_NO_ERROR; -} - -svn_error_t * -svn_branch_revision_root_parse(svn_branch_revision_root_t **rev_root_p, - svn_branch_repos_t *repos, - svn_stream_t *stream, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) -{ - svn_branch_revision_root_t *rev_root; - svn_revnum_t rev; - int first_eid, next_eid; - int num_branches; - svn_stringbuf_t *line; - svn_boolean_t eof; - int n; - int j; - - SVN_ERR(svn_stream_readline(stream, &line, "\n", &eof, scratch_pool)); - SVN_ERR_ASSERT(! eof); - n = sscanf(line->data, "r%ld: eids %d %d " - "branches %d", - &rev, - &first_eid, &next_eid, - &num_branches); - SVN_ERR_ASSERT(n == 4); - - rev_root = svn_branch_revision_root_create(repos, rev, rev - 1, - result_pool); - rev_root->first_eid = first_eid; - rev_root->next_eid = next_eid; - - /* parse the branches */ - for (j = 0; j < num_branches; j++) - { - svn_branch_state_t *branch; - - SVN_ERR(svn_branch_state_parse(&branch, rev_root, stream, - result_pool, scratch_pool)); - SVN_ARRAY_PUSH(rev_root->branches) = branch; - - /* Note the root branches */ - if (! branch->outer_branch) - { - APR_ARRAY_PUSH(rev_root->root_branches, void *) = branch; - } - } - - *rev_root_p = rev_root; - return SVN_NO_ERROR; -} - -/* ### Duplicated in svnmover.c. */ -static int -sort_compare_items_by_eid(const svn_sort__item_t *a, - const svn_sort__item_t *b) -{ - int eid_a = *(const int *)a->key; - int eid_b = *(const int *)b->key; - - return eid_a - eid_b; -} - -/* Write to STREAM a parseable representation of BRANCH. - */ -svn_error_t * -svn_branch_state_serialize(svn_stream_t *stream, - svn_branch_state_t *branch, - apr_pool_t *scratch_pool) -{ - const char *branch_root_rrpath = svn_branch_get_root_rrpath(branch, - scratch_pool); - SVN_ITER_T(svn_branch_el_rev_content_t) *hi; - const char *predecessor_str = ""; - - if (branch->predecessor) - { - assert(SVN_IS_VALID_REVNUM(branch->predecessor->rev)); - predecessor_str = apr_psprintf(scratch_pool, " from r%ld.%s", - branch->predecessor->rev, - branch->predecessor->bid); - } - - SVN_ERR(svn_stream_printf(stream, scratch_pool, - "%s root-eid %d num-eids %d%s # at /%s\n", - svn_branch_get_id(branch, scratch_pool), - branch->root_eid, - apr_hash_count(branch->e_map), - predecessor_str, - branch_root_rrpath)); - - map_purge_orphans(branch->e_map, branch->root_eid, scratch_pool); - - for (SVN_HASH_ITER_SORTED(hi, branch->e_map, sort_compare_items_by_eid, - scratch_pool)) - { - int eid = *(const int *)hi->key; - svn_branch_el_rev_content_t *element = svn_branch_get_element(branch, eid); - int parent_eid; - const char *name; - - SVN_ERR_ASSERT(element); - parent_eid = element->parent_eid; - name = element->name[0] ? element->name : "."; - SVN_ERR(svn_stream_printf(stream, scratch_pool, - "e%d: %s %d %s\n", - eid, - element ? ((! element->payload->is_subbranch_root) - ? "normal" : "subbranch") - : "none", - parent_eid, name)); - } - return SVN_NO_ERROR; -} - -svn_error_t * -svn_branch_revision_root_serialize(svn_stream_t *stream, - svn_branch_revision_root_t *rev_root, - apr_pool_t *scratch_pool) -{ - SVN_ITER_T(svn_branch_state_t) *bi; - - SVN_ERR(svn_stream_printf(stream, scratch_pool, - "r%ld: eids %d %d " - "branches %d\n", - rev_root->rev, - rev_root->first_eid, rev_root->next_eid, - rev_root->branches->nelts)); - - for (SVN_ARRAY_ITER(bi, rev_root->branches, scratch_pool)) - { - svn_branch_state_t *branch = bi->val; - - if (branch->predecessor && branch->predecessor->rev < 0) - { - branch->predecessor->rev = rev_root->rev; - } - - SVN_ERR(svn_branch_state_serialize(stream, bi->val, bi->iterpool)); - } - return SVN_NO_ERROR; -} - - /* * ======================================================================== */ @@ -1327,12 +242,16 @@ svn_branch_find_nested_branch_element_by scratch_pool)) { svn_branch_state_t *subbranch = bi->val; + svn_branch_state_t *outer_branch; + int outer_eid; const char *relpath_to_subbranch; const char *relpath_in_subbranch; + svn_branch_get_outer_branch_and_eid(&outer_branch, &outer_eid, + subbranch, scratch_pool); + relpath_to_subbranch - = svn_branch_get_path_by_eid(root_branch, subbranch->outer_eid, - scratch_pool); + = svn_branch_get_path_by_eid(root_branch, outer_eid, scratch_pool); relpath_in_subbranch = svn_relpath_skip_ancestor(relpath_to_subbranch, relpath); @@ -1355,23 +274,30 @@ svn_branch_find_nested_branch_element_by *eid_p = svn_branch_get_eid_by_path(root_branch, relpath, scratch_pool); } - -/* - * ======================================================================== - */ - -const char * -svn_branch_get_id(svn_branch_state_t *branch, - apr_pool_t *result_pool) +svn_error_t * +svn_branch_repos_find_el_rev_by_path_rev(svn_branch_el_rev_id_t **el_rev_p, + 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) { - const char *id = ""; + svn_branch_el_rev_id_t *el_rev = apr_palloc(result_pool, sizeof(*el_rev)); + svn_branch_state_t *branch; - while (branch->outer_branch) - { - id = apr_psprintf(result_pool, ".%d%s", branch->outer_eid, id); - branch = branch->outer_branch; - } - id = apr_psprintf(result_pool, "B%d%s", branch->outer_eid, id); - return id; + 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_relpath(&el_rev->branch, + &el_rev->eid, + branch, relpath, + scratch_pool); + + /* 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/branch_repos.c URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_delta/branch_repos.c?rev=1708550&r1=1708549&r2=1708550&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/libsvn_delta/branch_repos.c (original) +++ subversion/branches/move-tracking-2/subversion/libsvn_delta/branch_repos.c Wed Oct 14 06:38:16 2015 @@ -71,17 +71,6 @@ svn_branch_repos_get_revision(const svn_ return svn_array_get(repos->rev_roots, revnum); } -struct svn_branch_state_t * -svn_branch_repos_get_root_branch(const svn_branch_repos_t *repos, - svn_revnum_t revnum, - int top_branch_num) -{ - svn_branch_revision_root_t *rev_root - = svn_branch_repos_get_revision(repos, revnum); - - return svn_branch_revision_root_get_root_branch(rev_root, top_branch_num); -} - svn_branch_revision_root_t * svn_branch_repos_get_base_revision_root(svn_branch_revision_root_t *rev_root) { @@ -137,31 +126,4 @@ svn_branch_repos_find_el_rev_by_id(svn_b *el_rev_p = el_rev; return SVN_NO_ERROR; } - -svn_error_t * -svn_branch_repos_find_el_rev_by_path_rev(svn_branch_el_rev_id_t **el_rev_p, - 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 *branch; - - 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_relpath(&el_rev->branch, - &el_rev->eid, - branch, relpath, - scratch_pool); - - /* 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=1708550&r1=1708549&r2=1708550&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/libsvn_delta/compat3e.c (original) +++ subversion/branches/move-tracking-2/subversion/libsvn_delta/compat3e.c Wed Oct 14 06:38:16 2015 @@ -32,6 +32,7 @@ #include "svn_pools.h" #include "private/svn_branch_repos.h" +#include "private/svn_branch_nested.h" #include "private/svn_delta_private.h" #include "private/svn_editor3e.h" #include "../libsvn_delta/debug_editor.h" @@ -952,18 +953,6 @@ apply_change(void **dir_baton, * (A branch root is not necessarily a directory, it could be a file.) */ -/* */ -static int -branch_get_top_num(const svn_branch_state_t *branch, - apr_pool_t *scratch_pool) -{ - while (branch->outer_branch) - { - branch = branch->outer_branch; - } - return branch->outer_eid; -} - /* Get the old-repository path for the storage of the root element of BRANCH. * * Currently, this is the same as the nested-branching hierarchical path @@ -973,7 +962,7 @@ static const char * branch_get_storage_root_rrpath(const svn_branch_state_t *branch, apr_pool_t *result_pool) { - int top_branch_num = branch_get_top_num(branch, result_pool); + int top_branch_num = atoi(branch->bid + 1); const char *top_path = apr_psprintf(result_pool, "top%d", top_branch_num); const char *nested_path = svn_branch_get_root_rrpath(branch, result_pool); @@ -1187,7 +1176,6 @@ editor3_open_branch(void *baton, { ev3_from_delta_baton_t *eb = baton; svn_branch_state_t *new_branch; - svn_branch_state_t *outer_branch = NULL; /* if the subbranch already exists, just return its bid */ *new_branch_id_p @@ -1204,14 +1192,10 @@ editor3_open_branch(void *baton, return SVN_NO_ERROR; } - if (outer_branch_id) - outer_branch = svn_branch_revision_root_get_branch_by_id( - eb->edited_rev_root, outer_branch_id, scratch_pool); - new_branch = svn_branch_add_new_branch(eb->edited_rev_root, + new_branch = svn_branch_add_new_branch(*new_branch_id_p, + eb->edited_rev_root, predecessor, - outer_branch, outer_eid, root_eid, scratch_pool); - *new_branch_id_p = svn_branch_get_id(new_branch, result_pool); return SVN_NO_ERROR; } @@ -1228,7 +1212,6 @@ editor3_branch(void *baton, ev3_from_delta_baton_t *eb = baton; svn_branch_rev_bid_t *predecessor; svn_branch_state_t *new_branch; - svn_branch_state_t *outer_branch = NULL; svn_branch_state_t *from_branch; svn_branch_subtree_t *from_subtree; @@ -1244,20 +1227,18 @@ editor3_branch(void *baton, from->rev, from->bid, from->eid); } - if (outer_branch_id) - outer_branch = svn_branch_revision_root_get_branch_by_id( - eb->edited_rev_root, outer_branch_id, scratch_pool); + *new_branch_id_p + = svn_branch_id_nest(outer_branch_id, outer_eid, result_pool); predecessor = svn_branch_rev_bid_create(from->rev, from->bid, scratch_pool); - new_branch = svn_branch_add_new_branch(eb->edited_rev_root, + new_branch = svn_branch_add_new_branch(*new_branch_id_p, + eb->edited_rev_root, predecessor, - outer_branch, outer_eid, from->eid, scratch_pool); /* Populate the mapping from the 'from' source */ - SVN_ERR(svn_branch_instantiate_elements(new_branch, *from_subtree, - scratch_pool)); + SVN_ERR(svn_branch_instantiate_elements_r(new_branch, *from_subtree, + scratch_pool)); - *new_branch_id_p = svn_branch_get_id(new_branch, result_pool); return SVN_NO_ERROR; } @@ -1843,17 +1824,20 @@ drive_changes(ev3_from_delta_baton_t *eb for (i = 0; i < eb->edited_rev_root->root_branches->nelts; i++) { svn_branch_state_t *root_branch - = svn_branch_revision_root_get_root_branch(eb->edited_rev_root, i); + = APR_ARRAY_IDX(eb->edited_rev_root->root_branches, i, void *); apr_hash_t *paths_final; 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; + svn_branch_state_t *base_root_branch; + svn_boolean_t branch_is_new; + + SVN_ERR(svn_branch_repos_get_branch_by_id(&base_root_branch, + eb->edited_rev_root->repos, + eb->edited_rev_root->base_rev, + root_branch->bid, scratch_pool)); + branch_is_new = !base_root_branch; paths_final = apr_hash_make(scratch_pool); convert_branch_to_paths_r(paths_final, @@ -1913,13 +1897,35 @@ editor3_sequence_point(void *baton, ev3_from_delta_baton_t *eb = baton; int i; - for (i = 0; i < eb->edited_rev_root->root_branches->nelts; i++) + /* first, purge elements in each branch */ + for (i = 0; i < eb->edited_rev_root->branches->nelts; i++) + { + svn_branch_state_t *b + = APR_ARRAY_IDX(eb->edited_rev_root->branches, i, void *); + + svn_branch_purge(b, scratch_pool); + } + + /* second, purge branches that are no longer nested */ + for (i = 0; i < eb->edited_rev_root->branches->nelts; i++) { svn_branch_state_t *b - = svn_branch_revision_root_get_root_branch(eb->edited_rev_root, i); + = APR_ARRAY_IDX(eb->edited_rev_root->branches, i, void *); + svn_branch_state_t *outer_branch; + int outer_eid; + + svn_branch_get_outer_branch_and_eid(&outer_branch, &outer_eid, + b, scratch_pool); - svn_branch_purge_r(b, scratch_pool); + if (outer_branch + && ! svn_branch_get_element(outer_branch, outer_eid)) + { + svn_branch_revision_root_delete_branch(b->rev_root, b, scratch_pool); + /* Re-visit this position in the array */ + i--; + } } + return SVN_NO_ERROR; } 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=1708550&r1=1708549&r2=1708550&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c (original) +++ subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c Wed Oct 14 06:38:16 2015 @@ -46,6 +46,7 @@ #include "private/svn_cmdline_private.h" #include "private/svn_subr_private.h" #include "private/svn_branch_repos.h" +#include "private/svn_branch_nested.h" #include "private/svn_editor3e.h" #include "private/svn_ra_private.h" #include "private/svn_string_private.h" @@ -1010,10 +1011,14 @@ branch_id_str(svn_branch_state_t *branch else { svn_branch_el_rev_content_t *outer_el = NULL; + svn_branch_state_t *outer_branch; + int outer_eid; - if (branch->outer_branch) - outer_el = svn_branch_get_element(branch->outer_branch, - branch->outer_eid); + svn_branch_get_outer_branch_and_eid(&outer_branch, &outer_eid, + branch, scratch_pool); + + if (outer_branch) + outer_el = svn_branch_get_element(outer_branch, outer_eid); return apr_psprintf(result_pool, "%-10s %-12s root=e%d", svn_branch_get_id(branch, scratch_pool), @@ -2515,8 +2520,8 @@ do_branch_into(svn_branch_state_t *from_ new_root_content); /* Populate the new branch mapping */ - SVN_ERR(svn_branch_instantiate_elements(to_branch, *from_subtree, - scratch_pool)); + SVN_ERR(svn_branch_instantiate_elements_r(to_branch, *from_subtree, + scratch_pool)); notify_v("A+ %s (subtree)", svn_branch_get_path_by_eid(to_branch, from_eid, scratch_pool)); @@ -2998,17 +3003,24 @@ typedef struct arg_t */ static svn_error_t * point_to_outer_element_instead(svn_branch_el_rev_id_t *el_rev, - const char *op) + const char *op, + apr_pool_t *scratch_pool) { if (is_branch_root_element(el_rev->branch, el_rev->eid)) { - if (! el_rev->branch->outer_branch) + svn_branch_state_t *outer_branch; + int outer_eid; + + svn_branch_get_outer_branch_and_eid(&outer_branch, &outer_eid, + el_rev->branch, scratch_pool); + + if (! outer_branch) return svn_error_createf(SVN_ERR_BRANCHING, NULL, "%s: %s", op, _("svnmover cannot delete or move a " "top-level branch")); - el_rev->eid = el_rev->branch->outer_eid; - el_rev->branch = el_rev->branch->outer_branch; + el_rev->eid = outer_eid; + el_rev->branch = outer_branch; } return SVN_NO_ERROR; @@ -3290,7 +3302,8 @@ execute(svnmover_wc_t *wc, break; case ACTION_MV: - SVN_ERR(point_to_outer_element_instead(arg[0]->el_rev, "mv")); + SVN_ERR(point_to_outer_element_instead(arg[0]->el_rev, "mv", + iterpool)); VERIFY_REV_UNSPECIFIED("mv", 0); VERIFY_EID_EXISTS("mv", 0); @@ -3333,7 +3346,8 @@ execute(svnmover_wc_t *wc, break; case ACTION_RM: - SVN_ERR(point_to_outer_element_instead(arg[0]->el_rev, "rm")); + SVN_ERR(point_to_outer_element_instead(arg[0]->el_rev, "rm", + iterpool)); VERIFY_REV_UNSPECIFIED("rm", 0); VERIFY_EID_EXISTS("rm", 0); @@ -3344,7 +3358,7 @@ execute(svnmover_wc_t *wc, case ACTION_CP_RM: SVN_ERR(point_to_outer_element_instead(arg[0]->el_rev, - "copy-and-delete")); + "copy-and-delete", iterpool)); VERIFY_REV_UNSPECIFIED("copy-and-delete", 0); VERIFY_EID_EXISTS("copy-and-delete", 0); @@ -3363,7 +3377,8 @@ execute(svnmover_wc_t *wc, case ACTION_BR_RM: SVN_ERR(point_to_outer_element_instead(arg[0]->el_rev, - "branch-and-delete")); + "branch-and-delete", + iterpool)); VERIFY_REV_UNSPECIFIED("branch-and-delete", 0); VERIFY_EID_EXISTS("branch-and-delete", 0); @@ -3382,7 +3397,8 @@ execute(svnmover_wc_t *wc, case ACTION_BR_INTO_RM: SVN_ERR(point_to_outer_element_instead(arg[0]->el_rev, - "branch-into-and-delete")); + "branch-into-and-delete", + iterpool)); VERIFY_REV_UNSPECIFIED("branch-into-and-delete", 0); VERIFY_EID_EXISTS("branch-into-and-delete", 0); Modified: subversion/branches/move-tracking-2/subversion/tests/cmdline/svnmover_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/tests/cmdline/svnmover_tests.py?rev=1708550&r1=1708549&r2=1708550&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/tests/cmdline/svnmover_tests.py (original) +++ subversion/branches/move-tracking-2/subversion/tests/cmdline/svnmover_tests.py Wed Oct 14 06:38:16 2015 @@ -1340,13 +1340,14 @@ def merge_swap_abc(sbox): sbox_build_svnmover(sbox) expected_eids = svntest.wc.State('', { - '' : Item(eid=0), - 'X' : Item(eid=2), - 'X/A' : Item(eid=3), - 'X/A/a1' : Item(eid=4), - 'X/A/B' : Item(eid=5), - 'X/A/B/C' : Item(eid=6), - 'X/A/B/C/c1' : Item(eid=7), + 'B0' : Item(eid=0), + 'B0/X' : Item(eid=1), + 'B0.1' : Item(eid=2), + 'B0.1/A' : Item(eid=3), + 'B0.1/A/a1' : Item(eid=4), + 'B0.1/A/B' : Item(eid=5), + 'B0.1/A/B/C' : Item(eid=6), + 'B0.1/A/B/C/c1' : Item(eid=7), }) test_svnmover3(sbox, '', reported_br_diff('') + @@ -1360,20 +1361,21 @@ def merge_swap_abc(sbox): 'mkdir X/A/B/C/c1') expected_eids.add({ - 'Y' : Item(eid=2), - 'Y/A' : Item(eid=3), - 'Y/A/a1' : Item(eid=4), - 'Y/A/B' : Item(eid=5), - 'Y/A/B/C' : Item(eid=6), - 'Y/A/B/C/c1' : Item(eid=7), + 'B0/Y' : Item(eid=8), + 'B0.8' : Item(eid=2), + 'B0.8/A' : Item(eid=3), + 'B0.8/A/a1' : Item(eid=4), + 'B0.8/A/B' : Item(eid=5), + 'B0.8/A/B/C' : Item(eid=6), + 'B0.8/A/B/C/c1' : Item(eid=7), }) test_svnmover3(sbox, '', None, expected_eids, 'branch X Y') expected_eids.rename({ - 'X/A/B/C' : 'X/A', - 'X/A/B' : 'X/A/B', - 'X/A' : 'X/A/B/C', + 'B0.1/A/B/C' : 'B0.1/A', + 'B0.1/A/B' : 'B0.1/A/B', + 'B0.1/A' : 'B0.1/A/B/C', }) test_svnmover3(sbox, '', reported_br_diff('X') + @@ -1387,9 +1389,9 @@ def merge_swap_abc(sbox): 'mv X/C X/A') expected_eids.rename({ - 'Y/A' : 'Y/A/B/C', - 'Y/A/B' : 'Y/A/B', - 'Y/A/B/C' : 'Y/A', + 'B0.8/A' : 'B0.8/A/B/C', + 'B0.8/A/B' : 'B0.8/A/B', + 'B0.8/A/B/C' : 'B0.8/A', }) test_svnmover3(sbox, '', reported_br_diff('Y') + @@ -1404,10 +1406,11 @@ def move_to_related_branch_2(sbox): sbox_build_svnmover(sbox) expected_eids = svntest.wc.State('', { - '' : Item(eid=0), - 'X' : Item(eid=2), - 'X/A' : Item(eid=3), - 'X/A/B' : Item(eid=4), + 'B0' : Item(eid=0), + 'B0/X' : Item(eid=1), + 'B0.1' : Item(eid=2), + 'B0.1/A' : Item(eid=3), + 'B0.1/A/B' : Item(eid=4), }) test_svnmover3(sbox, '', reported_br_diff('') + @@ -1418,9 +1421,10 @@ def move_to_related_branch_2(sbox): 'mkdir X/A/B') expected_eids.add({ - 'Y' : Item(eid=2), - 'Y/A' : Item(eid=3), - 'Y/A/B' : Item(eid=4), + 'B0/Y' : Item(eid=5), + 'B0.5' : Item(eid=2), + 'B0.5/A' : Item(eid=3), + 'B0.5/A/B' : Item(eid=4), }) test_svnmover3(sbox, '', reported_br_diff('') + @@ -1429,10 +1433,10 @@ def move_to_related_branch_2(sbox): 'branch X Y') expected_eids.add({ - 'X/A/ax' : Item(eid=6), - 'X/A/B/bx' : Item(eid=7), - 'Y/A/ay' : Item(eid=8), - 'Y/A/B/by' : Item(eid=9), + 'B0.1/A/ax' : Item(eid=6), + 'B0.1/A/B/bx' : Item(eid=7), + 'B0.5/A/ay' : Item(eid=8), + 'B0.5/A/B/by' : Item(eid=9), }) test_svnmover3(sbox, '', reported_br_diff('X') + @@ -1450,10 +1454,10 @@ def move_to_related_branch_2(sbox): # X and Y are related, X/A/B contains X/A/B/bx, Y/A/B contains Y/A/B/by. # Moving X/A/B to Y/B, i.e. from X to Y, by branch-into-and-delete, # results in Y/B that contains both bx and by. - expected_eids.rename({'X/A/B' : 'Y/B'}) - expected_eids.remove('Y/A/B', 'Y/A/B/by') + expected_eids.rename({'B0.1/A/B' : 'B0.5/B'}) + expected_eids.remove('B0.5/A/B', 'B0.5/A/B/by') expected_eids.add({ - 'Y/B/by' : Item(eid=9), + 'B0.5/B/by' : Item(eid=9), }) test_svnmover3(sbox, '', reported_br_diff('X') + Modified: subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/wc.py URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/wc.py?rev=1708550&r1=1708549&r2=1708550&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/wc.py (original) +++ subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/wc.py Wed Oct 14 06:38:16 2015 @@ -119,13 +119,11 @@ _re_parse_commit = re.compile('^(\w+( \ #rN: eids 0 15 branches 4 _re_parse_eid_header = re.compile('^r(-1|[0-9]+): eids ([0-9]+) ([0-9]+) ' 'branches ([0-9]+)$') -# B0.2 root-eid 3 # at /X -_re_parse_eid_branch = re.compile('^B([0-9.]+) root-eid ([0-9]+) num-eids ([0-9]+)( from [^ ]*)? # at /(.*)$') +# B0.2 root-eid 3 +_re_parse_eid_branch = re.compile('^(B[0-9.]+) root-eid ([0-9]+) num-eids ([0-9]+)( from [^ ]*)?$') # e4: normal 6 C _re_parse_eid_ele = re.compile('^e([0-9]+): (none|normal|subbranch) ' '(-1|[0-9]+) (.*)$') -# 25.34.78 -_re_parse_split_branch_eid = re.compile('^([0-9.]+)\.([0-9]+)$') class State: """Describes an existing or expected state of a working copy. @@ -789,6 +787,7 @@ class State: # Need to read all elements in a branch before we can construct # the full path to an element. + # For the full path we use <branch-id>/<path-within-branch>. def eid_path(eids, eid): ele = eids[eid] @@ -799,20 +798,17 @@ class State: return ele[1] return parent_path + '/' + ele[1] - def eid_full_path(eids, eid, root_path): + def eid_full_path(eids, eid, branch_id): path = eid_path(eids, eid) - if root_path == '': - return eid_path(eids, eid) if path == '': - return root_path - return root_path + '/' + eid_path(eids, eid) + return branch_id + return branch_id + '/' + path - def add_to_desc(eids, desc, branch_root_path): + def add_to_desc(eids, desc, branch_id): for k, v in eids.items(): - desc[eid_full_path(eids, k, branch_root_path)] = StateItem(eid=k) + desc[eid_full_path(eids, k, branch_id)] = StateItem(eid=k) - branches = {} - branch = None + branch_id = None eids = {} desc = {} for line in lines: @@ -828,21 +824,13 @@ class State: match = _re_parse_eid_branch.search(line) if match: - if branch: - branches[branch[0]] = branch - add_to_desc(eids, desc, branch[3]) + if branch_id: + add_to_desc(eids, desc, branch_id) eids = {} - parent_branch_eid = None - branch_eid = match.group(1) - match2 = _re_parse_split_branch_eid.search(branch_eid) - if match2: - parent_branch_eid = branches[match2.group(1)] + branch_id = match.group(1) root_eid = match.group(2) - path = match.group(5) - branch = [branch_eid, parent_branch_eid, root_eid, path] - branches[branch[0]] = branch - add_to_desc(eids, desc, branch[3]) + add_to_desc(eids, desc, branch_id) return cls('', desc)
