On Mon, May 23, 2011 at 8:15 AM, Greg Stein <gst...@gmail.com> wrote:
> On Mon, May 23, 2011 at 11:00, <hwri...@apache.org> wrote: > >... > > +++ subversion/trunk/subversion/libsvn_client/delete.c Mon May 23 > 15:00:50 2011 > > @@ -141,36 +141,22 @@ path_driver_cb_func(void **dir_baton, > > return editor->delete_entry(path, SVN_INVALID_REVNUM, parent_baton, > pool); > > } > > > > - > > static svn_error_t * > > -delete_urls(const apr_array_header_t *paths, > > - const apr_hash_t *revprop_table, > > - svn_commit_callback2_t commit_callback, > > - void *commit_baton, > > - svn_client_ctx_t *ctx, > > - apr_pool_t *pool) > > +single_repos_delete(svn_ra_session_t *ra_session, > > + const char *repos_root, > > + const apr_array_header_t *relpaths, > > + const apr_hash_t *revprop_table, > > + svn_commit_callback2_t commit_callback, > > + void *commit_baton, > > + svn_client_ctx_t *ctx, > > + apr_pool_t *pool) > > { > > - svn_ra_session_t *ra_session = NULL; > > const svn_delta_editor_t *editor; > > + apr_hash_t *commit_revprops; > > void *edit_baton; > > const char *log_msg; > > - svn_node_kind_t kind; > > - apr_array_header_t *targets; > > - apr_hash_t *commit_revprops; > > - svn_error_t *err; > > - const char *common_url; > > int i; > > - apr_pool_t *iterpool = svn_pool_create(pool); > > - > > - /* Condense our list of deletion targets. */ > > - SVN_ERR(svn_uri_condense_targets(&common_url, &targets, paths, TRUE, > > - pool, iterpool)); > > - if (! targets->nelts) > > - { > > - const char *bname; > > - svn_uri_split(&common_url, &bname, common_url, pool); > > - APR_ARRAY_PUSH(targets, const char *) = bname; > > - } > > + svn_error_t *err; > > > > /* Create new commit items and add them to the array. */ > > if (SVN_CLIENT__HAS_LOG_MSG_FUNC(ctx)) > > @@ -178,24 +164,21 @@ delete_urls(const apr_array_header_t *pa > > svn_client_commit_item3_t *item; > > const char *tmp_file; > > apr_array_header_t *commit_items > > - = apr_array_make(pool, targets->nelts, sizeof(item)); > > + = apr_array_make(pool, relpaths->nelts, sizeof(item)); > > > > - for (i = 0; i < targets->nelts; i++) > > + for (i = 0; i < relpaths->nelts; i++) > > { > > - const char *relpath = APR_ARRAY_IDX(targets, i, const char *); > > + const char *relpath = APR_ARRAY_IDX(relpaths, i, const char > *); > > > > item = svn_client_commit_item3_create(pool); > > - item->url = svn_path_url_add_component2(common_url, relpath, > pool); > > + item->url = svn_path_url_add_component2(repos_root, relpath, > pool); > > item->state_flags = SVN_CLIENT_COMMIT_ITEM_DELETE; > > APR_ARRAY_PUSH(commit_items, svn_client_commit_item3_t *) = > item; > > } > > SVN_ERR(svn_client__get_log_msg(&log_msg, &tmp_file, commit_items, > > ctx, pool)); > > if (! log_msg) > > - { > > - svn_pool_destroy(iterpool); > > - return SVN_NO_ERROR; > > - } > > + return SVN_NO_ERROR; > > } > > else > > log_msg = ""; > > @@ -203,30 +186,8 @@ delete_urls(const apr_array_header_t *pa > > SVN_ERR(svn_client__ensure_revprop_table(&commit_revprops, > revprop_table, > > log_msg, ctx, pool)); > > > > - /* Open ra session to the common parent of our deletes */ > > - SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, > > - common_url, NULL, NULL, > > - FALSE, TRUE, ctx, pool)); > > - > > - /* Verify that each thing to be deleted actually exists (to prevent > > - the creation of a revision that has no changes, since the > > - filesystem allows for no-op deletes). */ > > - for (i = 0; i < targets->nelts; i++) > > - { > > - const char *relpath = APR_ARRAY_IDX(targets, i, const char *); > > - > > - svn_pool_clear(iterpool); > > - > > - SVN_ERR(svn_ra_check_path(ra_session, relpath, SVN_INVALID_REVNUM, > > - &kind, iterpool)); > > - if (kind == svn_node_none) > > - { > > - return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL, > > - _("URL '%s' does not exist"), > > - > svn_path_url_add_component2(common_url, > > - relpath, > pool)); > > - } > > - } > > + /* Reparent the RA_session to the repos_root. */ > > + SVN_ERR(svn_ra_reparent(ra_session, repos_root, pool)); > > You shouldn't need to do this. See below. > > > > > /* Fetch RA commit editor */ > > SVN_ERR(svn_ra_get_commit_editor3(ra_session, &editor, &edit_baton, > > @@ -238,10 +199,9 @@ delete_urls(const apr_array_header_t *pa > > > > /* Call the path-based editor driver. */ > > err = svn_delta_path_driver(editor, edit_baton, SVN_INVALID_REVNUM, > > - targets, path_driver_cb_func, > > - (void *)editor, iterpool); > > + relpaths, path_driver_cb_func, > > + (void *)editor, pool); > > > > - svn_pool_destroy(iterpool); > > if (err) > > { > > return svn_error_return( > > @@ -253,6 +213,100 @@ delete_urls(const apr_array_header_t *pa > > return svn_error_return(editor->close_edit(edit_baton, pool)); > > } > > > > +static svn_error_t * > > +delete_urls_multi_repos(const apr_array_header_t *uris, > > + const apr_hash_t *revprop_table, > > + svn_commit_callback2_t commit_callback, > > + void *commit_baton, > > + svn_client_ctx_t *ctx, > > + apr_pool_t *pool) > > +{ > > + apr_hash_t *sessions = apr_hash_make(pool); > > + apr_hash_t *relpaths = apr_hash_make(pool); > > + apr_hash_index_t *hi; > > + int i; > > + > > + /* Create a hash of repos_root -> ra_session maps and repos_root -> > relpaths > > + maps, used to group the various targets. */ > > It isn't clear that "relpaths" is an array of char* relpaths. > > > + for (i = 0; i < uris->nelts; i++) > > + { > > + const char *uri = APR_ARRAY_IDX(uris, i, const char *); > > + svn_ra_session_t *ra_session = NULL; > > + const char *repos_root = NULL; > > + const char *repos_relpath = NULL; > > + apr_array_header_t *relpaths_list; > > + svn_node_kind_t kind; > > + > > + for (hi = apr_hash_first(pool, sessions); hi; hi = > apr_hash_next(hi)) > > + { > > + repos_root = svn__apr_hash_index_key(hi); > > + repos_relpath = svn_uri_is_child(repos_root, uri, pool); > > + > > + if (repos_relpath) > > + { > > + /* Great! We've found another uri underneath this > session, > > + store it and move on. */ > > + ra_session = svn__apr_hash_index_val(hi); > > + relpaths_list = apr_hash_get(relpaths, repos_root, > > + APR_HASH_KEY_STRING); > > + > > + APR_ARRAY_PUSH(relpaths_list, const char *) = > > + svn_path_uri_decode(repos_relpath, > pool); > > svn_uri_is_child() already decodes its result. You're double-decoding. > > > + > > + break; > > + } > > + } > > + > > + if (!ra_session) > > + { > > + /* If we haven't found a session yet, we need to open one up. > > + Note that we don't have a local directory, nor a place > > + to put temp files. */ > > + SVN_ERR(svn_client__open_ra_session_internal(&ra_session, > NULL, uri, > > + NULL, NULL, > FALSE, > > + TRUE, ctx, > pool)); > > + SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root, > pool)); > > + > > + apr_hash_set(sessions, repos_root, APR_HASH_KEY_STRING, > ra_session); > > + repos_relpath = svn_uri_is_child(repos_root, uri, pool); > > + > > + relpaths_list = apr_array_make(pool, 1, sizeof(const char *)); > > + apr_hash_set(relpaths, repos_root, APR_HASH_KEY_STRING, > > + relpaths_list); > > + APR_ARRAY_PUSH(relpaths_list, const char *) = > > + svn_path_uri_decode(repos_relpath, > pool); > > Double-decode again. > > > + } > > + > > + /* Now, test to see if the thing actually exists. */ > > + SVN_ERR(svn_ra_reparent(ra_session, uri, pool)); > > + SVN_ERR(svn_ra_check_path(ra_session, "", SVN_INVALID_REVNUM, > &kind, > > + pool)); > > Rather than reparenting to the URI and checking "" ... why not > reparent the session (when created) to REPOS_ROOT and then use the > REPOS_RELPATH variable? You could then remove the reparent from the > single_repos_delete() function. > > > + if (kind == svn_node_none) > > + return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL, > > + "URL '%s' does not exist", uri); > > + } > > + > > + /* At this point, we should have two hashs: > > + SESSIONS maps repos_roots to ra_sessions. > > + RELPATHS maps repos_roots to a list of decoded relpaths for that > root. > > + > > + Now we iterate over the collection of sessions and do a commit for > each > > + one with the collected relpaths. */ > > + for (hi = apr_hash_first(pool, sessions); hi; hi = apr_hash_next(hi)) > > + { > > + const char *repos_root = svn__apr_hash_index_key(hi); > > + svn_ra_session_t *ra_session = svn__apr_hash_index_val(hi); > > + apr_array_header_t *relpaths_list = apr_hash_get(relpaths, > repos_root, > > + > APR_HASH_KEY_STRING); > > const! > > >... > Thanks for the review. The original patch had rotted a bit, so I'm glad for some extra eyes. Concerns addressed in subsequent commits. -Hyrum