Modified: subversion/branches/revprop-packing/subversion/libsvn_client/externals.c URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/libsvn_client/externals.c?rev=1231318&r1=1231317&r2=1231318&view=diff ============================================================================== --- subversion/branches/revprop-packing/subversion/libsvn_client/externals.c (original) +++ subversion/branches/revprop-packing/subversion/libsvn_client/externals.c Fri Jan 13 21:40:26 2012 @@ -126,8 +126,8 @@ relegate_dir_external(svn_wc_context_t * static svn_error_t * switch_dir_external(const char *local_abspath, const char *url, - const svn_opt_revision_t *revision, const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, const char *defining_abspath, svn_boolean_t *timestamp_sleep, svn_client_ctx_t *ctx, @@ -135,10 +135,18 @@ switch_dir_external(const char *local_ab { svn_node_kind_t kind; svn_error_t *err; + svn_revnum_t external_peg_rev = SVN_INVALID_REVNUM; + svn_revnum_t external_rev = SVN_INVALID_REVNUM; apr_pool_t *subpool = svn_pool_create(pool); SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath)); + if (peg_revision->kind == svn_opt_revision_number) + external_peg_rev = peg_revision->value.number; + + if (revision->kind == svn_opt_revision_number) + external_rev = revision->value.number; + /* If path is a directory, try to update/switch to the correct URL and revision. */ SVN_ERR(svn_io_check_path(local_abspath, &kind, pool)); @@ -230,8 +238,8 @@ switch_dir_external(const char *local_ab svn_uri_skip_ancestor( repos_root_url, url, subpool), - SVN_INVALID_REVNUM, - SVN_INVALID_REVNUM, + external_peg_rev, + external_rev, subpool)); svn_pool_destroy(subpool); @@ -288,8 +296,8 @@ switch_dir_external(const char *local_ab repos_root_url, repos_uuid, svn_uri_skip_ancestor(repos_root_url, url, pool), - SVN_INVALID_REVNUM, - SVN_INVALID_REVNUM, + external_peg_rev, + external_rev, pool)); } @@ -504,219 +512,6 @@ cleanup: return svn_error_trace(err); } -/* Return the scheme of @a uri in @a scheme allocated from @a pool. - If @a uri does not appear to be a valid URI, then @a scheme will - not be updated. */ -static svn_error_t * -uri_scheme(const char **scheme, const char *uri, apr_pool_t *pool) -{ - apr_size_t i; - - for (i = 0; uri[i] && uri[i] != ':'; ++i) - if (uri[i] == '/') - goto error; - - if (i > 0 && uri[i] == ':' && uri[i+1] == '/' && uri[i+2] == '/') - { - *scheme = apr_pstrmemdup(pool, uri, i); - return SVN_NO_ERROR; - } - -error: - return svn_error_createf(SVN_ERR_BAD_URL, 0, - _("URL '%s' does not begin with a scheme"), - uri); -} - -/* If the URL for @a item is relative, then using the repository root - URL @a repos_root_url and the parent directory URL @parent_dir_url, - resolve it into an absolute URL and save it in @a item. - - Regardless if the URL is absolute or not, if there are no errors, - the URL in @a item will be canonicalized. - - The following relative URL formats are supported: - - ../ relative to the parent directory of the external - ^/ relative to the repository root - // relative to the scheme - / relative to the server's hostname - - The ../ and ^/ relative URLs may use .. to remove path elements up - to the server root. - - The external URL should not be canonicalized before calling this function, - as otherwise the scheme relative URL '//host/some/path' would have been - canonicalized to '/host/some/path' and we would not be able to match on - the leading '//'. */ -static svn_error_t * -resolve_relative_external_url(const char **resolved_url, - const svn_wc_external_item2_t *item, - const char *repos_root_url, - const char *parent_dir_url, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) -{ - const char *url = item->url; - apr_uri_t parent_dir_uri; - apr_status_t status; - - *resolved_url = item->url; - - /* If the URL is already absolute, there is nothing to do. */ - if (svn_path_is_url(url)) - { - /* "http://server/path" */ - *resolved_url = svn_uri_canonicalize(url, result_pool); - return SVN_NO_ERROR; - } - - if (url[0] == '/') - { - /* "/path", "//path", and "///path" */ - int num_leading_slashes = 1; - if (url[1] == '/') - { - num_leading_slashes++; - if (url[2] == '/') - num_leading_slashes++; - } - - /* "//schema-relative" and in some cases "///schema-relative". - This last format is supported on file:// schema relative. */ - url = apr_pstrcat(scratch_pool, - apr_pstrndup(scratch_pool, url, num_leading_slashes), - svn_relpath_canonicalize(url + num_leading_slashes, - scratch_pool), - (char*)NULL); - } - else - { - /* "^/path" and "../path" */ - url = svn_relpath_canonicalize(url, scratch_pool); - } - - /* Parse the parent directory URL into its parts. */ - status = apr_uri_parse(scratch_pool, parent_dir_url, &parent_dir_uri); - if (status) - return svn_error_createf(SVN_ERR_BAD_URL, 0, - _("Illegal parent directory URL '%s'"), - parent_dir_url); - - /* If the parent directory URL is at the server root, then the URL - may have no / after the hostname so apr_uri_parse() will leave - the URL's path as NULL. */ - if (! parent_dir_uri.path) - parent_dir_uri.path = apr_pstrmemdup(scratch_pool, "/", 1); - parent_dir_uri.query = NULL; - parent_dir_uri.fragment = NULL; - - /* Handle URLs relative to the current directory or to the - repository root. The backpaths may only remove path elements, - not the hostname. This allows an external to refer to another - repository in the same server relative to the location of this - repository, say using SVNParentPath. */ - if ((0 == strncmp("../", url, 3)) || - (0 == strncmp("^/", url, 2))) - { - apr_array_header_t *base_components; - apr_array_header_t *relative_components; - int i; - - /* Decompose either the parent directory's URL path or the - repository root's URL path into components. */ - if (0 == strncmp("../", url, 3)) - { - base_components = svn_path_decompose(parent_dir_uri.path, - scratch_pool); - relative_components = svn_path_decompose(url, scratch_pool); - } - else - { - apr_uri_t repos_root_uri; - - status = apr_uri_parse(scratch_pool, repos_root_url, - &repos_root_uri); - if (status) - return svn_error_createf(SVN_ERR_BAD_URL, 0, - _("Illegal repository root URL '%s'"), - repos_root_url); - - /* If the repository root URL is at the server root, then - the URL may have no / after the hostname so - apr_uri_parse() will leave the URL's path as NULL. */ - if (! repos_root_uri.path) - repos_root_uri.path = apr_pstrmemdup(scratch_pool, "/", 1); - - base_components = svn_path_decompose(repos_root_uri.path, - scratch_pool); - relative_components = svn_path_decompose(url + 2, scratch_pool); - } - - for (i = 0; i < relative_components->nelts; ++i) - { - const char *component = APR_ARRAY_IDX(relative_components, - i, - const char *); - if (0 == strcmp("..", component)) - { - /* Constructing the final absolute URL together with - apr_uri_unparse() requires that the path be absolute, - so only pop a component if the component being popped - is not the component for the root directory. */ - if (base_components->nelts > 1) - apr_array_pop(base_components); - } - else - APR_ARRAY_PUSH(base_components, const char *) = component; - } - - parent_dir_uri.path = (char *)svn_path_compose(base_components, - scratch_pool); - *resolved_url = svn_uri_canonicalize(apr_uri_unparse(scratch_pool, - &parent_dir_uri, 0), - result_pool); - return SVN_NO_ERROR; - } - - /* The remaining URLs are relative to the either the scheme or - server root and can only refer to locations inside that scope, so - backpaths are not allowed. */ - if (svn_path_is_backpath_present(url + 2)) - return svn_error_createf(SVN_ERR_BAD_URL, 0, - _("The external relative URL '%s' cannot have " - "backpaths, i.e. '..'"), - item->url); - - /* Relative to the scheme: Build a new URL from the parts we know. */ - if (0 == strncmp("//", url, 2)) - { - const char *scheme; - - SVN_ERR(uri_scheme(&scheme, repos_root_url, scratch_pool)); - *resolved_url = svn_uri_canonicalize(apr_pstrcat(scratch_pool, scheme, - ":", url, (char *)NULL), - result_pool); - return SVN_NO_ERROR; - } - - /* Relative to the server root: Just replace the path portion of the - parent's URL. */ - if (url[0] == '/') - { - parent_dir_uri.path = (char *)url; - *resolved_url = svn_uri_canonicalize(apr_uri_unparse(scratch_pool, - &parent_dir_uri, 0), - result_pool); - return SVN_NO_ERROR; - } - - return svn_error_createf(SVN_ERR_BAD_URL, 0, - _("Unrecognized format for the relative external " - "URL '%s'"), - item->url); -} - static svn_error_t * handle_external_item_removal(const struct external_change_baton_t *eb, const char *defining_abspath, @@ -811,6 +606,7 @@ handle_external_item_change(const struct svn_ra_session_t *ra_session; svn_client__ra_session_from_path_results ra_cache = { 0 }; const char *new_url; + svn_node_kind_t kind; ra_cache.kind = svn_node_unknown; @@ -824,155 +620,99 @@ handle_external_item_change(const struct iterpool, since the hash table values outlive the iterpool and any pointers they have should also outlive the iterpool. */ - SVN_ERR(resolve_relative_external_url(&new_url, - new_item, eb->repos_root_url, - parent_dir_url, - scratch_pool, scratch_pool)); - - /* If the external is being checked out, exported or updated, - determine if the external is a file or directory. */ - if (new_item) - { - svn_node_kind_t kind; + SVN_ERR(svn_wc__resolve_relative_external_url(&new_url, + new_item, eb->repos_root_url, + parent_dir_url, + scratch_pool, scratch_pool)); + + /* Determine if the external is a file or directory. */ + /* Get the RA connection. */ + SVN_ERR(svn_client__ra_session_from_path(&ra_session, + &ra_cache.ra_revnum, + &ra_cache.ra_session_url, + new_url, NULL, + &(new_item->peg_revision), + &(new_item->revision), eb->ctx, + scratch_pool)); - /* Get the RA connection. */ - SVN_ERR(svn_client__ra_session_from_path(&ra_session, - &ra_cache.ra_revnum, - &ra_cache.ra_session_url, - new_url, NULL, - &(new_item->peg_revision), - &(new_item->revision), eb->ctx, - scratch_pool)); - - SVN_ERR(svn_ra_get_uuid2(ra_session, &ra_cache.repos_uuid, - scratch_pool)); - SVN_ERR(svn_ra_get_repos_root2(ra_session, &ra_cache.repos_root_url, - scratch_pool)); - SVN_ERR(svn_ra_check_path(ra_session, "", ra_cache.ra_revnum, &kind, - scratch_pool)); + SVN_ERR(svn_ra_get_uuid2(ra_session, &ra_cache.repos_uuid, + scratch_pool)); + SVN_ERR(svn_ra_get_repos_root2(ra_session, &ra_cache.repos_root_url, + scratch_pool)); + SVN_ERR(svn_ra_check_path(ra_session, "", ra_cache.ra_revnum, &kind, + scratch_pool)); + + if (svn_node_none == kind) + return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL, + _("URL '%s' at revision %ld doesn't exist"), + ra_cache.ra_session_url, + ra_cache.ra_revnum); + + if (svn_node_dir != kind && svn_node_file != kind) + return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL, + _("URL '%s' at revision %ld is not a file " + "or a directory"), + ra_cache.ra_session_url, + ra_cache.ra_revnum); - if (svn_node_none == kind) - return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL, - _("URL '%s' at revision %ld doesn't exist"), - ra_cache.ra_session_url, - ra_cache.ra_revnum); - - if (svn_node_dir != kind && svn_node_file != kind) - return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL, - _("URL '%s' at revision %ld is not a file " - "or a directory"), - ra_cache.ra_session_url, - ra_cache.ra_revnum); + ra_cache.kind = kind; - ra_cache.kind = kind; - } /* Not protecting against recursive externals. Detecting them in the global case is hard, and it should be pretty obvious to a user when it happens. Worst case: your disk fills up :-). */ - if (! old_defining_abspath) + /* First notify that we're about to handle an external. */ + if (eb->ctx->notify_func2) { - /* This branch is only used during a checkout or an export. */ - - /* First notify that we're about to handle an external. */ - if (eb->ctx->notify_func2) - (*eb->ctx->notify_func2)( - eb->ctx->notify_baton2, - svn_wc_create_notify(local_abspath, svn_wc_notify_update_external, - scratch_pool), scratch_pool); - - switch (ra_cache.kind) - { - case svn_node_dir: - /* The target dir might have multiple components. Guarantee - the path leading down to the last component. */ - SVN_ERR(svn_io_make_dir_recursively(svn_dirent_dirname(local_abspath, - scratch_pool), - scratch_pool)); - - SVN_ERR(switch_dir_external( - local_abspath, new_url, - &(new_item->peg_revision), &(new_item->revision), - parent_dir_abspath, eb->timestamp_sleep, eb->ctx, - scratch_pool)); - break; - case svn_node_file: - if (strcmp(eb->repos_root_url, ra_cache.repos_root_url)) - return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL, - _("Unsupported external: " - "url of file external '%s' is not in repository '%s'"), - new_url, eb->repos_root_url); - SVN_ERR(switch_file_external(local_abspath, - new_url, - &new_item->peg_revision, - &new_item->revision, - parent_dir_abspath, - ra_session, - ra_cache.ra_session_url, - ra_cache.ra_revnum, - ra_cache.repos_root_url, - eb->timestamp_sleep, eb->ctx, - scratch_pool)); - break; - default: - SVN_ERR_MALFUNCTION(); - break; - } + (*eb->ctx->notify_func2)( + eb->ctx->notify_baton2, + svn_wc_create_notify(local_abspath, + svn_wc_notify_update_external, + scratch_pool), + scratch_pool); } - else - { - /* This branch handles a definition change or simple update. */ - /* First notify that we're about to handle an external. */ - if (eb->ctx->notify_func2) - { - svn_wc_notify_t *nt; - - nt = svn_wc_create_notify(local_abspath, - svn_wc_notify_update_external, - scratch_pool); - - eb->ctx->notify_func2(eb->ctx->notify_baton2, nt, scratch_pool); - } - - /* Either the URL changed, or the exact same item is present in - both hashes, and caller wants to update such unchanged items. - In the latter case, the call below will try to make sure that - the external really is a WC pointing to the correct - URL/revision. */ - switch (ra_cache.kind) - { - case svn_node_dir: - SVN_ERR(switch_dir_external(local_abspath, new_url, - &(new_item->revision), - &(new_item->peg_revision), - parent_dir_abspath, - eb->timestamp_sleep, eb->ctx, - scratch_pool)); - break; - case svn_node_file: - if (strcmp(eb->repos_root_url, ra_cache.repos_root_url)) - return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL, - _("Unsupported external: " - "url of file external '%s' is not in repository '%s'"), - new_url, eb->repos_root_url); - SVN_ERR(switch_file_external(local_abspath, - new_url, - &new_item->peg_revision, - &new_item->revision, - parent_dir_abspath, - ra_session, - ra_cache.ra_session_url, - ra_cache.ra_revnum, - ra_cache.repos_root_url, - eb->timestamp_sleep, eb->ctx, - scratch_pool)); - break; - default: - SVN_ERR_MALFUNCTION(); - break; - } + if (! old_defining_abspath) + { + /* The target dir might have multiple components. Guarantee the path + leading down to the last component. */ + SVN_ERR(svn_io_make_dir_recursively(svn_dirent_dirname(local_abspath, + scratch_pool), + scratch_pool)); + } + + switch (ra_cache.kind) + { + case svn_node_dir: + SVN_ERR(switch_dir_external(local_abspath, new_url, + &(new_item->peg_revision), + &(new_item->revision), + parent_dir_abspath, + eb->timestamp_sleep, eb->ctx, + scratch_pool)); + break; + case svn_node_file: + if (strcmp(eb->repos_root_url, ra_cache.repos_root_url)) + return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL, + _("Unsupported external: " + "url of file external '%s' is not in repository '%s'"), + new_url, eb->repos_root_url); + SVN_ERR(switch_file_external(local_abspath, + new_url, + &new_item->peg_revision, + &new_item->revision, + parent_dir_abspath, + ra_session, + ra_cache.ra_session_url, + ra_cache.ra_revnum, + ra_cache.repos_root_url, + eb->timestamp_sleep, eb->ctx, + scratch_pool)); + break; + default: + SVN_ERR_MALFUNCTION(); + break; } return SVN_NO_ERROR; @@ -1156,6 +896,7 @@ svn_client__handle_externals(apr_hash_t { const char *item_abspath = svn__apr_hash_index_key(hi); const char *defining_abspath = svn__apr_hash_index_val(hi); + const char *parent_abspath; svn_pool_clear(iterpool); @@ -1164,6 +905,30 @@ svn_client__handle_externals(apr_hash_t handle_external_item_removal(&eb, defining_abspath, item_abspath, iterpool), iterpool)); + + /* Are there any unversioned directories between the removed + * external and the DEFINING_ABSPATH which we can remove? */ + parent_abspath = item_abspath; + do { + svn_wc_status3_t *parent_status; + + parent_abspath = svn_dirent_dirname(parent_abspath, iterpool); + SVN_ERR(svn_wc_status3(&parent_status, ctx->wc_ctx, parent_abspath, + iterpool, iterpool)); + if (parent_status->node_status == svn_wc_status_unversioned) + { + svn_error_t *err; + + err = svn_io_dir_remove_nonrecursive(parent_abspath, iterpool); + if (err && APR_STATUS_IS_ENOTEMPTY(err->apr_err)) + { + svn_error_clear(err); + break; + } + else + SVN_ERR(err); + } + } while (strcmp(parent_abspath, defining_abspath) != 0); } @@ -1232,9 +997,10 @@ svn_client__export_externals(apr_hash_t item_abspath = svn_dirent_join(local_abspath, item->target_dir, sub_iterpool); - SVN_ERR(resolve_relative_external_url(&new_url, item, - repos_root_url, dir_url, - sub_iterpool, sub_iterpool)); + SVN_ERR(svn_wc__resolve_relative_external_url(&new_url, item, + repos_root_url, + dir_url, sub_iterpool, + sub_iterpool)); /* The target dir might have multiple components. Guarantee the path leading down to the last component. */
Modified: subversion/branches/revprop-packing/subversion/libsvn_client/info.c URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/libsvn_client/info.c?rev=1231318&r1=1231317&r2=1231318&view=diff ============================================================================== --- subversion/branches/revprop-packing/subversion/libsvn_client/info.c (original) +++ subversion/branches/revprop-packing/subversion/libsvn_client/info.c Fri Jan 13 21:40:26 2012 @@ -145,8 +145,8 @@ push_dir_info(svn_ra_session_t *ra_sessi path = svn_relpath_join(dir, name, subpool); URL = svn_path_url_add_component2(session_URL, name, subpool); - fs_path = svn_fspath__canonicalize(svn_uri__is_child(repos_root, URL, - subpool), subpool); + fs_path = svn_fspath__canonicalize( + svn_uri_skip_ancestor(repos_root, URL, subpool), subpool); lock = apr_hash_get(locks, fs_path, APR_HASH_KEY_STRING); @@ -186,20 +186,17 @@ same_resource_in_head(svn_boolean_t *sam apr_pool_t *pool) { svn_error_t *err; - svn_opt_revision_t start_rev, end_rev, peg_rev; - svn_opt_revision_t *ignored_rev; - const char *head_url, *ignored_url; + svn_opt_revision_t start_rev, peg_rev; + const char *head_url; start_rev.kind = svn_opt_revision_head; peg_rev.kind = svn_opt_revision_number; peg_rev.value.number = rev; - end_rev.kind = svn_opt_revision_unspecified; - err = svn_client__repos_locations(&head_url, &ignored_rev, - &ignored_url, &ignored_rev, + err = svn_client__repos_locations(&head_url, NULL, NULL, NULL, ra_session, url, &peg_rev, - &start_rev, &end_rev, + &start_rev, NULL, ctx, pool); if (err && ((err->apr_err == SVN_ERR_CLIENT_UNRELATED_RESOURCES) || @@ -258,6 +255,75 @@ wc_info_receiver(void *baton, abspath_or_url, &client_info, scratch_pool); } +/* Like svn_ra_stat() but with a compatibility hack for pre-1.2 svnserve. */ +static svn_error_t * +ra_stat_compatible(svn_ra_session_t *ra_session, + svn_revnum_t rev, + svn_dirent_t **dirent_p, + apr_uint32_t dirent_fields, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + const char *repos_root_URL, *url; + svn_error_t *err; + svn_dirent_t *the_ent; + + SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root_URL, pool)); + SVN_ERR(svn_ra_get_session_url(ra_session, &url, pool)); + + err = svn_ra_stat(ra_session, "", rev, &the_ent, pool); + + /* svn_ra_stat() will work against old versions of mod_dav_svn, but + not old versions of svnserve. In the case of a pre-1.2 svnserve, + catch the specific error it throws:*/ + if (err && err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED) + { + /* Fall back to pre-1.2 strategy for fetching dirent's URL. */ + svn_node_kind_t url_kind; + svn_ra_session_t *parent_ra_session; + apr_hash_t *parent_ents; + const char *parent_url, *base_name; + + if (strcmp(url, repos_root_URL) == 0) + { + /* In this universe, there's simply no way to fetch + information about the repository's root directory! */ + return err; + } + + svn_error_clear(err); + + SVN_ERR(svn_ra_check_path(ra_session, "", rev, &url_kind, pool)); + if (url_kind == svn_node_none) + return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL, + _("URL '%s' non-existent in revision %ld"), + url, rev); + + /* Open a new RA session to the item's parent. */ + svn_uri_split(&parent_url, &base_name, url, pool); + SVN_ERR(svn_client__open_ra_session_internal(&parent_ra_session, NULL, + parent_url, NULL, + NULL, FALSE, TRUE, + ctx, pool)); + + /* Get all parent's entries, and find the item's dirent in the hash. */ + SVN_ERR(svn_ra_get_dir2(parent_ra_session, &parent_ents, NULL, NULL, + "", rev, dirent_fields, pool)); + the_ent = apr_hash_get(parent_ents, base_name, APR_HASH_KEY_STRING); + if (the_ent == NULL) + return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL, + _("URL '%s' non-existent in revision %ld"), + url, rev); + } + else if (err) + { + return svn_error_trace(err); + } + + *dirent_p = the_ent; + return SVN_NO_ERROR; +} + svn_error_t * svn_client_info3(const char *abspath_or_url, const svn_opt_revision_t *peg_revision, @@ -271,15 +337,13 @@ svn_client_info3(const char *abspath_or_ svn_client_ctx_t *ctx, apr_pool_t *pool) { - svn_ra_session_t *ra_session, *parent_ra_session; + svn_ra_session_t *ra_session; svn_revnum_t rev; const char *url; - svn_node_kind_t url_kind; const char *repos_root_URL, *repos_UUID; svn_lock_t *lock; svn_boolean_t related; - apr_hash_t *parent_ents; - const char *parent_url, *base_name; + const char *base_name; svn_dirent_t *the_ent; svn_client_info2_t *info; svn_error_t *err; @@ -314,56 +378,26 @@ svn_client_info3(const char *abspath_or_ SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root_URL, pool)); SVN_ERR(svn_ra_get_uuid2(ra_session, &repos_UUID, pool)); - svn_uri_split(&parent_url, &base_name, url, pool); + svn_uri_split(NULL, &base_name, url, pool); /* Get the dirent for the URL itself. */ - err = svn_ra_stat(ra_session, "", rev, &the_ent, pool); - - /* svn_ra_stat() will work against old versions of mod_dav_svn, but - not old versions of svnserve. In the case of a pre-1.2 svnserve, - catch the specific error it throws:*/ + err = ra_stat_compatible(ra_session, rev, &the_ent, DIRENT_FIELDS, + ctx, pool); if (err && err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED) { - /* Fall back to pre-1.2 strategy for fetching dirent's URL. */ svn_error_clear(err); - if (strcmp(url, repos_root_URL) == 0) - { - /* In this universe, there's simply no way to fetch - information about the repository's root directory! - If we're recursing, degrade gracefully: rather than - throw an error, return no information about the - repos root. */ - if (depth > svn_depth_empty) - goto pre_1_2_recurse; - - /* Otherwise, we really are stuck. Better tell the user - what's going on. */ - return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL, - _("Server does not support retrieving " - "information about the repository root")); - } - - SVN_ERR(svn_ra_check_path(ra_session, "", rev, &url_kind, pool)); - if (url_kind == svn_node_none) - return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL, - _("URL '%s' non-existent in revision %ld"), - url, rev); - - /* Open a new RA session to the item's parent. */ - SVN_ERR(svn_client__open_ra_session_internal(&parent_ra_session, NULL, - parent_url, NULL, - NULL, FALSE, TRUE, - ctx, pool)); - - /* Get all parent's entries, and find the item's dirent in the hash. */ - SVN_ERR(svn_ra_get_dir2(parent_ra_session, &parent_ents, NULL, NULL, - "", rev, DIRENT_FIELDS, pool)); - the_ent = apr_hash_get(parent_ents, base_name, APR_HASH_KEY_STRING); - if (the_ent == NULL) - return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL, - _("URL '%s' non-existent in revision %ld"), - url, rev); + /* If we're recursing, degrade gracefully: rather than + throw an error, return no information about the + repos root. */ + if (depth > svn_depth_empty) + goto pre_1_2_recurse; + + /* Otherwise, we really are stuck. Better tell the user + what's going on. */ + return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL, + _("Server does not support retrieving " + "information about the repository root")); } else if (err) { Modified: subversion/branches/revprop-packing/subversion/libsvn_client/list.c URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/libsvn_client/list.c?rev=1231318&r1=1231317&r2=1231318&view=diff ============================================================================== --- subversion/branches/revprop-packing/subversion/libsvn_client/list.c (original) +++ subversion/branches/revprop-packing/subversion/libsvn_client/list.c Fri Jan 13 21:40:26 2012 @@ -32,6 +32,7 @@ #include "client.h" #include "private/svn_fspath.h" +#include "private/svn_ra_private.h" #include "svn_private_config.h" /* Get the directory entries of DIR at REV (relative to the root of @@ -91,7 +92,7 @@ get_dir_contents(apr_uint32_t dirent_fie { svn_sort__item_t *item = &APR_ARRAY_IDX(array, i, svn_sort__item_t); const char *path; - svn_dirent_t *the_ent = apr_hash_get(tmpdirents, item->key, item->klen); + svn_dirent_t *the_ent = item->value; svn_lock_t *lock; svn_pool_clear(iterpool); @@ -121,42 +122,21 @@ get_dir_contents(apr_uint32_t dirent_fie return SVN_NO_ERROR; } -svn_error_t * -svn_client_list2(const char *path_or_url, - const svn_opt_revision_t *peg_revision, - const svn_opt_revision_t *revision, - svn_depth_t depth, - apr_uint32_t dirent_fields, - svn_boolean_t fetch_locks, - svn_client_list_func_t list_func, - void *baton, - svn_client_ctx_t *ctx, - apr_pool_t *pool) +/* Like svn_ra_stat() but with a compatibility hack for pre-1.2 svnserve. */ +static svn_error_t * +ra_stat_compatible(svn_ra_session_t *ra_session, + svn_revnum_t rev, + svn_dirent_t **dirent_p, + apr_uint32_t dirent_fields, + svn_client_ctx_t *ctx, + apr_pool_t *pool) { - svn_ra_session_t *ra_session; - svn_revnum_t rev; - svn_dirent_t *dirent; - const char *url; - const char *repos_root; - const char *fs_path; + const char *repos_root, *url; svn_error_t *err; - apr_hash_t *locks; - - /* We use the kind field to determine if we should recurse, so we - always need it. */ - dirent_fields |= SVN_DIRENT_KIND; - - /* Get an RA plugin for this filesystem object. */ - SVN_ERR(svn_client__ra_session_from_path(&ra_session, &rev, - &url, path_or_url, NULL, - peg_revision, - revision, ctx, pool)); + svn_dirent_t *dirent; SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root, pool)); - - SVN_ERR(svn_client__path_relative_to_root(&fs_path, ctx->wc_ctx, url, - repos_root, TRUE, ra_session, - pool, pool)); + SVN_ERR(svn_ra_get_session_url(ra_session, &url, pool)); err = svn_ra_stat(ra_session, "", rev, &dirent, pool); @@ -240,6 +220,45 @@ svn_client_list2(const char *path_or_url else if (err) return svn_error_trace(err); + *dirent_p = dirent; + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_list2(const char *path_or_url, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + svn_depth_t depth, + apr_uint32_t dirent_fields, + svn_boolean_t fetch_locks, + svn_client_list_func_t list_func, + void *baton, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + svn_ra_session_t *ra_session; + svn_revnum_t rev; + svn_dirent_t *dirent; + const char *url; + const char *fs_path; + svn_error_t *err; + apr_hash_t *locks; + + /* We use the kind field to determine if we should recurse, so we + always need it. */ + dirent_fields |= SVN_DIRENT_KIND; + + /* Get an RA plugin for this filesystem object. */ + SVN_ERR(svn_client__ra_session_from_path(&ra_session, &rev, + &url, path_or_url, NULL, + peg_revision, + revision, ctx, pool)); + + SVN_ERR(svn_ra__get_fspath_relative_to_root(ra_session, &fs_path, url, + pool)); + + SVN_ERR(ra_stat_compatible(ra_session, rev, &dirent, dirent_fields, + ctx, pool)); if (! dirent) return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL, _("URL '%s' non-existent in revision %ld"), Modified: subversion/branches/revprop-packing/subversion/libsvn_client/log.c URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/libsvn_client/log.c?rev=1231318&r1=1231317&r2=1231318&view=diff ============================================================================== --- subversion/branches/revprop-packing/subversion/libsvn_client/log.c (original) +++ subversion/branches/revprop-packing/subversion/libsvn_client/log.c Fri Jan 13 21:40:26 2012 @@ -211,8 +211,7 @@ pre_15_receiver(void *baton, svn_log_ent name, &value, pool)); if (log_entry->revprops == NULL) log_entry->revprops = apr_hash_make(pool); - apr_hash_set(log_entry->revprops, (const void *)name, - APR_HASH_KEY_STRING, (const void *)value); + apr_hash_set(log_entry->revprops, name, APR_HASH_KEY_STRING, value); } if (log_entry->revprops) { @@ -284,7 +283,6 @@ svn_client_log5(const apr_array_header_t svn_boolean_t has_log_revprops; const char *actual_url; apr_array_header_t *condensed_targets; - svn_revnum_t ignored_revnum; svn_opt_revision_t session_opt_rev; const char *ra_target; pre_15_receiver_baton_t rb = {0}; @@ -301,8 +299,7 @@ svn_client_log5(const apr_array_header_t /* Make a copy of PEG_REVISION, we may need to change it to a default value. */ - peg_rev.kind = peg_revision->kind; - peg_rev.value = peg_revision->value; + peg_rev = *peg_revision; /* Use the passed URL, if there is one. */ url_or_path = APR_ARRAY_IDX(targets, 0, const char *); @@ -330,7 +327,7 @@ svn_client_log5(const apr_array_header_t else if (range->start.kind == svn_opt_revision_unspecified) { /* Default to any specified peg revision. Otherwise, if the - * first target is an URL, then we default to HEAD:0. Lastly, + * first target is a URL, then we default to HEAD:0. Lastly, * the default is BASE:0 since WC@HEAD may not exist. */ if (peg_rev.kind == svn_opt_revision_unspecified) { @@ -428,7 +425,7 @@ svn_client_log5(const apr_array_header_t _("When specifying working copy paths, only " "one target may be given")); - /* An unspecified PEG_REVISION for a working copy path defautls + /* An unspecified PEG_REVISION for a working copy path defaults to svn_opt_revision_working. */ if (peg_rev.kind == svn_opt_revision_unspecified) peg_rev.kind = svn_opt_revision_working; @@ -486,8 +483,8 @@ svn_client_log5(const apr_array_header_t else ra_target = url_or_path; - SVN_ERR(svn_client__ra_session_from_path(&ra_session, &ignored_revnum, - &actual_url, ra_target, NULL, + SVN_ERR(svn_client__ra_session_from_path(&ra_session, NULL, &actual_url, + ra_target, NULL, &peg_rev, &session_opt_rev, ctx, pool));
