diff options
author | peter <peter@FreeBSD.org> | 2014-05-27 04:55:31 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 2014-05-27 04:55:31 +0000 |
commit | 9efa638bec6d135464ff9b3bab358c76671c87bf (patch) | |
tree | 6d1265a766b5c11e4c2414a994dbabb861526c73 /subversion/libsvn_client/commit_util.c | |
parent | b168ae828108b6f3a7d68ace24b6e8383a081fb5 (diff) | |
download | FreeBSD-src-9efa638bec6d135464ff9b3bab358c76671c87bf.zip FreeBSD-src-9efa638bec6d135464ff9b3bab358c76671c87bf.tar.gz |
Vendor import svn-1.8.9
Diffstat (limited to 'subversion/libsvn_client/commit_util.c')
-rw-r--r-- | subversion/libsvn_client/commit_util.c | 118 |
1 files changed, 82 insertions, 36 deletions
diff --git a/subversion/libsvn_client/commit_util.c b/subversion/libsvn_client/commit_util.c index 1e2c50c..a32ec5d 100644 --- a/subversion/libsvn_client/commit_util.c +++ b/subversion/libsvn_client/commit_util.c @@ -892,7 +892,7 @@ harvest_status_callback(void *status_baton, if (matches_changelists && (is_harvest_root || baton->changelists) && state_flags - && is_added + && (is_added || (is_deleted && is_op_root && status->copied)) && baton->danglers) { /* If a node is added, its parent must exist in the repository at the @@ -966,17 +966,19 @@ struct handle_descendants_baton void *cancel_baton; svn_client__check_url_kind_t check_url_func; void *check_url_baton; + svn_client__committables_t *committables; }; /* Helper for the commit harvesters */ static svn_error_t * handle_descendants(void *baton, - const void *key, apr_ssize_t klen, void *val, - apr_pool_t *pool) + const void *key, apr_ssize_t klen, void *val, + apr_pool_t *pool) { struct handle_descendants_baton *hdb = baton; apr_array_header_t *commit_items = val; apr_pool_t *iterpool = svn_pool_create(pool); + const char *repos_root_url = key; int i; for (i = 0; i < commit_items->nelts; i++) @@ -1002,32 +1004,64 @@ handle_descendants(void *baton, for (j = 0; j < absent_descendants->nelts; j++) { - int k; - svn_boolean_t found_item = FALSE; svn_node_kind_t kind; + svn_client_commit_item3_t *desc_item; const char *relpath = APR_ARRAY_IDX(absent_descendants, j, const char *); const char *local_abspath = svn_dirent_join(item->path, relpath, iterpool); - /* If the path has a commit operation, we do nothing. - (It will be deleted by the operation) */ - for (k = 0; k < commit_items->nelts; k++) + /* ### Need a sub-iterpool? */ + + + /* We found a 'not present' descendant during a copy (at op_depth>0), + this is most commonly caused by copying some mixed revision tree. + + In this case not present can imply that the node does not exist + in the parent revision, or that the node does. But we want to copy + the working copy state in which it does not exist, but might be + replaced. */ + + desc_item = svn_hash_gets(hdb->committables->by_path, local_abspath); + + /* If the path has a commit operation (possibly at an higher + op_depth, we might want to turn an add in a replace. */ + if (desc_item) { - svn_client_commit_item3_t *cmt_item = - APR_ARRAY_IDX(commit_items, k, svn_client_commit_item3_t *); + const char *dir; + svn_boolean_t found_intermediate = FALSE; + + if (desc_item->state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE) + continue; /* We already have a delete or replace */ + else if (!(desc_item->state_flags & SVN_CLIENT_COMMIT_ITEM_ADD)) + continue; /* Not a copy/add, just a modification */ - if (! strcmp(cmt_item->path, local_abspath)) + dir = svn_dirent_dirname(local_abspath, iterpool); + + while (strcmp(dir, item->path)) { - found_item = TRUE; - break; + svn_client_commit_item3_t *i_item; + + i_item = svn_hash_gets(hdb->committables->by_path, dir); + + if (i_item) + { + if ((i_item->state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE) + || (i_item->state_flags & SVN_CLIENT_COMMIT_ITEM_ADD)) + { + found_intermediate = TRUE; + break; + } + } + dir = svn_dirent_dirname(dir, iterpool); } - } - if (found_item) - continue; /* We have an explicit delete or replace for this path */ + if (found_intermediate) + continue; /* Some intermediate ancestor is an add or delete */ - /* ### Need a sub-iterpool? */ + /* Fall through to detect if we need to turn the add in a + replace. */ + } if (hdb->check_url_func) { @@ -1045,25 +1079,35 @@ handle_descendants(void *baton, else kind = svn_node_unknown; /* 'Ok' for a delete of something */ - { - /* Add a new commit item that describes the delete */ - apr_pool_t *result_pool = commit_items->pool; - svn_client_commit_item3_t *new_item - = svn_client_commit_item3_create(result_pool); - - new_item->path = svn_dirent_join(item->path, relpath, - result_pool); - new_item->kind = kind; - new_item->url = svn_path_url_add_component2(item->url, relpath, - result_pool); - new_item->revision = SVN_INVALID_REVNUM; - new_item->state_flags = SVN_CLIENT_COMMIT_ITEM_DELETE; - new_item->incoming_prop_changes = apr_array_make(result_pool, 1, - sizeof(svn_prop_t *)); - - APR_ARRAY_PUSH(commit_items, svn_client_commit_item3_t *) - = new_item; - } + if (desc_item) + { + /* Extend the existing add/copy item to create a replace */ + desc_item->state_flags |= SVN_CLIENT_COMMIT_ITEM_DELETE; + continue; + } + + /* Add a new commit item that describes the delete */ + + SVN_ERR(add_committable(hdb->committables, + svn_dirent_join(item->path, relpath, + iterpool), + kind, + repos_root_url, + svn_uri_skip_ancestor( + repos_root_url, + svn_path_url_add_component2(item->url, + relpath, + iterpool), + iterpool), + SVN_INVALID_REVNUM, + NULL /* copyfrom_relpath */, + SVN_INVALID_REVNUM, + NULL /* moved_from_abspath */, + SVN_CLIENT_COMMIT_ITEM_DELETE, + NULL /* lock tokens */, + NULL /* lock */, + commit_items->pool, + iterpool)); } } @@ -1181,6 +1225,7 @@ svn_client__harvest_committables(svn_client__committables_t **committables, hdb.cancel_baton = ctx->cancel_baton; hdb.check_url_func = check_url_func; hdb.check_url_baton = check_url_baton; + hdb.committables = *committables; SVN_ERR(svn_iter_apr_hash(NULL, (*committables)->by_repository, handle_descendants, &hdb, iterpool)); @@ -1274,6 +1319,7 @@ harvest_copy_committables(void *baton, void *item, apr_pool_t *pool) hdb.cancel_baton = btn->ctx->cancel_baton; hdb.check_url_func = btn->check_url_func; hdb.check_url_baton = btn->check_url_baton; + hdb.committables = btn->committables; SVN_ERR(svn_iter_apr_hash(NULL, btn->committables->by_repository, handle_descendants, &hdb, pool)); |