A patch in progress, for demonstration and your feedback. Since long ago we've thought about letting the client, through the libsvn_client API, share a single RA connection across a series of operations -- e.g.
"svn update a b c" currently opens 3 RA sesssions. Similarly, inside libsvn_client we often open up an extra RA session when we could have re-used an old one -- e.g. Update with externals -- opens a new session per external [1] "svn mergeinfo" -- opens two or three sessions The attached patch implements "caching" of connections that have been used and may be used again. The cache is initialized (to empty) by the caller (the client executable) and connections in it are established or re-used by libsvn_client as required. This patch demonstrates the usage inside "svn status" and "svn info" subcommands, and also (partially) inside svn_client_mergeinfo_log() which is the guts of the "svn mergeinfo" command. In this patch, my idea is that the client passes the cache explicitly to each API (or passes NULL to not use a cache), so that the client retains control of the lifetime of these connections. The "svn" client, for example, may not worry about ever clearing the cache whereas a long-running GUI may clear it after a certain period of time, and/or limit the number of entries in it. Thoughts? In the email threads referenced below, we discussed some related issues such as whether it would be better to use root-relative paths all the time instead of "parenting" a session at a specific URL, and how this ties in with authenticating for access to a specific path. But I don't think those issues need to be addressed before adding the basic ability to re-use a session at all. Prior discussions: [1] Email thread "Re-use connection for svn:externals", from Phillip Hellewell on 2010-02-08, <http://svn.haxx.se/dev/archive-2010-02/0168.shtml>. [2] Email thread "[RFC] Concept of RA session relative paths", from Ivan Zhakov on 2009-10-13, <http://svn.haxx.se/dev/archive-2009-10/0334.shtml>. - Julian
Enable libsvn_client APIs to re-use a previous RA session instead of always opening a new connection. Basically: - Declare an opaque "RA session cache" object in the public API. It holds one open RA session per repository, for any number of repositories. - Implement a private API for libsvn_client functions to use instead of simply opening a new session. It re-uses a session from the cache, if present, or opens a new connection if necessary. - Modify some libsvn_client APIs to use the cache: + svn_client_info4() to take a cache from its caller; + svn_client_status6() to take two caches from its caller (because it needs to use two connections in parallel); ### Are we sure it needs two? + svn_client_mergeinfo_log() to use a cache internally. This is just a start; in principle, more or less every libsvn_client API should accept a cache from its caller. In detail: * subversion/include/svn_client.h (svn_client_ra_sessions_cache_t): New structure type. (svn_client_ra_sessions_cache_init): New function. (svn_client_status6): New rev of svn_client_status5(), accepting an RA session cache. (svn_client_info4): New rev of svn_client_info3(), accepting two RA session caches. * subversion/libsvn_client/client.h (svn_client__cached_ra_session, svn_client__get_cached_ra_session): New functions. ### The names of the last two of those are not sufficiently distinct. * subversion/libsvn_client/deprecated.c (svn_client_status5, svn_client_info3): Re-implement as wrappers. * subversion/libsvn_client/info.c (svn_client_info4): New rev of svn_client_info3(), adding an RA session cache parameter. * subversion/libsvn_client/mergeinfo.c (svn_client_mergeinfo_log): Create and use an RA session cache internally, to eliminate one RA session (in the --show-revs=merged case only). There is more to be done here, as it still opens another session later on. * subversion/libsvn_client/ra.c (resolve_rev_and_url): New function, factored out of ... (svn_client__ra_session_from_path): ... here. (svn_client_ra_sessions_cache_t): New structure type. (svn_client_ra_sessions_cache_init, svn_client__cached_ra_session, svn_client__get_cached_ra_session): New functions. * subversion/libsvn_client/status.c (report_baton_t): Add a cache of RA sessions in here ... (reporter_finish_report): ... and use it here for fetching locks. (svn_client_status5): New rev of svn_client_status5(), adding RA session cache parameters. * subversion/libsvn_ra/ra_loader.c (svn_ra_open4): ### Debugging. * subversion/svn/info-cmd.c (svn_cl__info): Create an RA sessions cache and pass it to the API. * subversion/svn/status-cmd.c (svn_cl__status): Create an RA sessions cache and pass it to the API. --This line, and those below, will be ignored-- Index: subversion/include/svn_client.h =================================================================== --- subversion/include/svn_client.h (revision 1170548) +++ subversion/include/svn_client.h (working copy) @@ -69,6 +69,14 @@ svn_client_version(void); */ +/* */ +typedef struct svn_client_ra_sessions_cache_t svn_client_ra_sessions_cache_t; + +/* */ +svn_client_ra_sessions_cache_t * +svn_client_ra_sessions_cache_init(apr_pool_t *pool); + + /*** Authentication stuff ***/ /** The new authentication system allows the RA layer to "pull" @@ -2320,7 +2328,39 @@ typedef svn_error_t *(*svn_client_status * * All temporary allocations are performed in @a scratch_pool. * + * When connecting to the repository (if @a update is true): Re-use an + * existing connection in @a ra_sessions_cache_1 if it is not NULL and + * holds a connection to the correct repository, otherwise open a new + * connection and (if non-null) add it to this cache. Same for @a + * ra_sessions_cache_2; two parallel connections are used. See + * #svn_client_ra_session_cache_t for details. + * + * @since New in 1.8. + */ +svn_error_t * +svn_client_status6(svn_revnum_t *result_rev, + svn_client_ctx_t *ctx, + const char *path, + const svn_opt_revision_t *revision, + svn_depth_t depth, + svn_boolean_t get_all, + svn_boolean_t update, + svn_boolean_t no_ignore, + svn_boolean_t ignore_externals, + svn_boolean_t depth_as_sticky, + const apr_array_header_t *changelists, + svn_client_status_func_t status_func, + void *status_baton, + svn_client_ra_sessions_cache_t *ra_sessions_cache_1, + svn_client_ra_sessions_cache_t *ra_sessions_cache_2, + apr_pool_t *scratch_pool); + +/** + * Same as svn_client_status6(), but without the ability to use cached + * RA sessions. + * * @since New in 1.7. + * @deprecated Provided for backward compatibility with the 1.7 API. */ svn_error_t * svn_client_status5(svn_revnum_t *result_rev, @@ -5502,7 +5542,33 @@ typedef svn_error_t *(*svn_client_info_r * it's a member of one of those changelists. If @a changelists is * empty (or altogether @c NULL), no changelist filtering occurs. * + * When connecting to the repository: Re-use an existing connection in + * @a ra_sessions_cache if @a ra_sessions is not NULL and holds a + * connection to the correct repository, otherwise open a new connection + * and (if non-null) add it to this cache. See + * #svn_client_ra_session_cache_t for details. + * + * @since New in 1.8. + */ +svn_error_t * +svn_client_info4(const char *abspath_or_url, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + svn_depth_t depth, + svn_boolean_t fetch_excluded, + svn_boolean_t fetch_actual_only, + const apr_array_header_t *changelists, + svn_client_info_receiver2_t receiver, + void *receiver_baton, + svn_client_ra_sessions_cache_t *ra_sessions_cache, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool); + +/** Similar to svn_client_info4(), but without the ability to use cached + * RA sessions. + * * @since New in 1.7. + * @deprecated Provided for backward compatibility with the 1.7 API. */ svn_error_t * svn_client_info3(const char *abspath_or_url, Index: subversion/libsvn_client/client.h =================================================================== --- subversion/libsvn_client/client.h (revision 1170548) +++ subversion/libsvn_client/client.h (working copy) @@ -215,6 +218,29 @@ svn_client__ra_session_from_path(svn_ra_ svn_client_ctx_t *ctx, apr_pool_t *pool); +/* Retrieve an existing RA session from RA_SESSIONS_CACHE and reparent it + * to URL, or open a new session and add it to the cache. */ +svn_error_t * +svn_client__cached_ra_session(svn_ra_session_t **ra_session_p, + svn_client_ra_sessions_cache_t *ra_sessions_cache, + const char *url, + svn_client_ctx_t *ctx, + apr_pool_t *pool); + +/* A drop-in replacement for svn_client__ra_session_from_path() with + * base_dir_abspath=NULL, but using RA_SESSIONS_CACHE in the same way that + * svn_client__cached_ra_session() does. */ +svn_error_t * +svn_client__get_cached_ra_session(svn_ra_session_t **ra_session_p, + svn_revnum_t *rev_p, + const char **url_p, + svn_client_ra_sessions_cache_t *ra_sessions_cache, + const char *path_or_url, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + svn_client_ctx_t *ctx, + apr_pool_t *pool); + /* Ensure that RA_SESSION's session URL matches SESSION_URL, reparenting that session if necessary. If reparenting occurs, store the previous session URL in *OLD_SESSION_URL (so that if the Index: subversion/libsvn_client/deprecated.c =================================================================== --- subversion/libsvn_client/deprecated.c (revision 1170548) +++ subversion/libsvn_client/deprecated.c (working copy) @@ -1822,6 +1822,29 @@ svn_client_proplist(apr_array_header_t * /*** From status.c ***/ +svn_error_t * +svn_client_status5(svn_revnum_t *result_rev, + svn_client_ctx_t *ctx, + const char *path, + const svn_opt_revision_t *revision, + svn_depth_t depth, + svn_boolean_t get_all, + svn_boolean_t update, + svn_boolean_t no_ignore, + svn_boolean_t ignore_externals, + svn_boolean_t depth_as_sticky, + const apr_array_header_t *changelists, + svn_client_status_func_t status_func, + void *status_baton, + apr_pool_t *pool) +{ + return svn_client_status6(result_rev, ctx, path, revision, depth, + get_all, update, no_ignore, ignore_externals, + depth_as_sticky, changelists, + status_func, status_baton, + NULL, NULL, pool); +} + struct status4_wrapper_baton { svn_wc_context_t *wc_ctx; @@ -2119,6 +2142,26 @@ svn_client_checkout(svn_revnum_t *result /*** From info.c ***/ +svn_error_t * +svn_client_info3(const char *abspath_or_url, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + svn_depth_t depth, + svn_boolean_t fetch_excluded, + svn_boolean_t fetch_actual_only, + const apr_array_header_t *changelists, + svn_client_info_receiver2_t receiver, + void *receiver_baton, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_client_info4(abspath_or_url, peg_revision, revision, + depth, fetch_excluded, fetch_actual_only, + changelists, + receiver, receiver_baton, + NULL, ctx, pool); +} + svn_info_t * svn_info_dup(const svn_info_t *info, apr_pool_t *pool) { Index: subversion/libsvn_client/info.c =================================================================== --- subversion/libsvn_client/info.c (revision 1170548) +++ subversion/libsvn_client/info.c (working copy) @@ -257,7 +257,7 @@ wc_info_receiver(void *baton, } svn_error_t * -svn_client_info3(const char *abspath_or_url, +svn_client_info4(const char *abspath_or_url, const svn_opt_revision_t *peg_revision, const svn_opt_revision_t *revision, svn_depth_t depth, @@ -266,6 +266,7 @@ svn_client_info3(const char *abspath_or_ const apr_array_header_t *changelists, svn_client_info_receiver2_t receiver, void *receiver_baton, + svn_client_ra_sessions_cache_t *ra_sessions_cache, svn_client_ctx_t *ctx, apr_pool_t *pool) { @@ -304,10 +305,10 @@ svn_client_info3(const char *abspath_or_ /* Trace rename history (starting at path_or_url@peg_revision) and return RA session to the possibly-renamed URL as it exists in REVISION. The ra_session returned will be anchored on this "final" URL. */ - SVN_ERR(svn_client__ra_session_from_path(&ra_session, &rev, - &url, abspath_or_url, NULL, - peg_revision, - revision, ctx, pool)); + SVN_ERR(svn_client__get_cached_ra_session(&ra_session, &rev, &url, + ra_sessions_cache, abspath_or_url, + peg_revision, revision, + ctx, pool)); SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root_URL, pool)); SVN_ERR(svn_ra_get_uuid2(ra_session, &repos_UUID, pool)); Index: subversion/libsvn_client/mergeinfo.c =================================================================== --- subversion/libsvn_client/mergeinfo.c (revision 1170548) +++ subversion/libsvn_client/mergeinfo.c (working copy) @@ -1735,6 +1735,8 @@ svn_client_mergeinfo_log(svn_boolean_t f const char *repos_root; const char *target_repos_rel; svn_mergeinfo_catalog_t target_mergeinfo_cat; + svn_client_ra_sessions_cache_t *ra_sessions_cache + = svn_client_ra_sessions_cache_init(scratch_pool); /* A hash of paths, at or under TARGET_PATH_OR_URL, mapped to rangelists. Not technically mergeinfo, so not using the svn_mergeinfo_t type. */ @@ -1810,12 +1812,13 @@ svn_client_mergeinfo_log(svn_boolean_t f svn_revnum_t target_peg_revnum; const char *url; - SVN_ERR(svn_client__ra_session_from_path(&target_session, - &target_peg_revnum, &url, - target_path_or_url, NULL, - target_peg_revision, - target_peg_revision, - ctx, scratch_pool)); + SVN_ERR(svn_client__get_cached_ra_session(&target_session, + &target_peg_revnum, &url, + ra_sessions_cache, + target_path_or_url, + target_peg_revision, + target_peg_revision, + ctx, scratch_pool)); SVN_ERR(svn_client__get_history_as_mergeinfo(&target_history, NULL, target_peg_revnum, @@ -1829,12 +1832,13 @@ svn_client_mergeinfo_log(svn_boolean_t f svn_revnum_t source_peg_revnum; const char *url; - SVN_ERR(svn_client__ra_session_from_path(&source_session, - &source_peg_revnum, &url, - source_path_or_url, NULL, - source_peg_revision, - source_peg_revision, - ctx, scratch_pool)); + SVN_ERR(svn_client__get_cached_ra_session(&source_session, + &source_peg_revnum, &url, + ra_sessions_cache, + source_path_or_url, + source_peg_revision, + source_peg_revision, + ctx, scratch_pool)); SVN_ERR(svn_client__get_history_as_mergeinfo(&source_history, NULL, source_peg_revnum, Index: subversion/libsvn_client/ra.c =================================================================== --- subversion/libsvn_client/ra.c (revision 1170548) +++ subversion/libsvn_client/ra.c (working copy) @@ -435,22 +435,59 @@ path_or_url_local_style(const char *path return svn_dirent_local_style(path_or_url, pool); } +/* Like the resolving part of svn_client__ra_session_from_path(). */ +static svn_error_t * +resolve_rev_and_url(svn_revnum_t *rev_p, + const char **url_p, + svn_ra_session_t *ra_session, + const char *path_or_url, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + svn_opt_revision_t peg_rev = *peg_revision; + svn_opt_revision_t start_rev = *revision; + const char *url; + svn_opt_revision_t *good_rev; + + SVN_ERR(svn_opt_resolve_revisions(&peg_rev, &start_rev, + svn_path_is_url(path_or_url), + TRUE, + pool)); + + /* Run the history function to get the object's (possibly + different) url in REVISION. */ + SVN_ERR(svn_client__repos_locations(&url, &good_rev, NULL, NULL, + ra_session, + path_or_url, &peg_rev, + /* search range: */ + &start_rev, NULL, + ctx, pool)); + + /* Resolve good_rev into a real revnum. */ + if (good_rev->kind == svn_opt_revision_unspecified) + good_rev->kind = svn_opt_revision_head; + SVN_ERR(svn_client__get_revision_number(rev_p, NULL, ctx->wc_ctx, url, + ra_session, good_rev, pool)); + *url_p = url; + + return SVN_NO_ERROR; +} + svn_error_t * svn_client__ra_session_from_path(svn_ra_session_t **ra_session_p, svn_revnum_t *rev_p, const char **url_p, const char *path_or_url, const char *base_dir_abspath, - const svn_opt_revision_t *peg_revision_p, + const svn_opt_revision_t *peg_revision, const svn_opt_revision_t *revision, svn_client_ctx_t *ctx, apr_pool_t *pool) { svn_ra_session_t *ra_session; - const char *initial_url, *url; - svn_opt_revision_t *good_rev; - svn_opt_revision_t peg_revision, start_rev; - svn_revnum_t rev; + const char *initial_url; const char *corrected_url; SVN_ERR(svn_client_url_from_path2(&initial_url, path_or_url, ctx, pool, @@ -459,13 +496,6 @@ svn_client__ra_session_from_path(svn_ra_ return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL, _("'%s' has no URL"), path_or_url); - start_rev = *revision; - peg_revision = *peg_revision_p; - SVN_ERR(svn_opt_resolve_revisions(&peg_revision, &start_rev, - svn_path_is_url(path_or_url), - TRUE, - pool)); - SVN_ERR(svn_client__open_ra_session_internal(&ra_session, &corrected_url, initial_url, base_dir_abspath, NULL, @@ -476,28 +506,117 @@ svn_client__ra_session_from_path(svn_ra_ URL-ized form of PATH_OR_URL from now on. */ if (corrected_url && svn_path_is_url(path_or_url)) path_or_url = corrected_url; - - /* Run the history function to get the object's (possibly - different) url in REVISION. */ - SVN_ERR(svn_client__repos_locations(&url, &good_rev, NULL, NULL, - ra_session, - path_or_url, &peg_revision, - /* search range: */ - &start_rev, NULL, - ctx, pool)); + + SVN_ERR(resolve_rev_and_url(rev_p, url_p, ra_session, + path_or_url, peg_revision, revision, + ctx, pool)); /* Make the session point to the real URL. */ - SVN_ERR(svn_ra_reparent(ra_session, url, pool)); + SVN_ERR(svn_ra_reparent(ra_session, *url_p, pool)); + *ra_session_p = ra_session; - /* Resolve good_rev into a real revnum. */ - if (good_rev->kind == svn_opt_revision_unspecified) - good_rev->kind = svn_opt_revision_head; - SVN_ERR(svn_client__get_revision_number(&rev, NULL, ctx->wc_ctx, url, - ra_session, good_rev, pool)); + return SVN_NO_ERROR; +} + +struct svn_client_ra_sessions_cache_t +{ + /* Mapping (const char *) repo root URL -> (svn_ra_session_t). */ + apr_hash_t *sessions; +}; + +svn_client_ra_sessions_cache_t * +svn_client_ra_sessions_cache_init(apr_pool_t *pool) +{ + svn_client_ra_sessions_cache_t *cache = apr_palloc(pool, sizeof(*cache)); + cache->sessions = apr_hash_make(pool); + return cache; +} + +svn_error_t * +svn_client__cached_ra_session(svn_ra_session_t **ra_session_p, + svn_client_ra_sessions_cache_t *sessions_cache, + const char *url, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + svn_ra_session_t *ra_session = NULL; + apr_hash_index_t *hi; + apr_pool_t *session_pool = pool; + + /* If we're using a cache, find a suitable session in it (if any) and if + * there isn't one, then ensure the new session will be allocated in the + * cache's pool. */ + if (sessions_cache) + { + for (hi = apr_hash_first(pool, sessions_cache->sessions); + hi; + hi = apr_hash_next(hi)) + { + const char *root_url = svn__apr_hash_index_key(hi); + + if (svn_uri_skip_ancestor(root_url, url, pool)) + { + ra_session = svn__apr_hash_index_val(hi); + break; + } + } + + /* Allocate any new session in the cache's pool */ + session_pool = apr_hash_pool_get(sessions_cache->sessions); + } + + if (ra_session) + { + SVN_ERR(svn_ra_reparent(ra_session, url, pool)); + } + else + { + SVN_ERR(svn_client_open_ra_session(&ra_session, url, ctx, session_pool)); + + /* Cache the new session */ + if (sessions_cache) + { + const char *root_url; + + SVN_ERR(svn_ra_get_repos_root2(ra_session, &root_url, session_pool)); + apr_hash_set(sessions_cache->sessions, root_url, APR_HASH_KEY_STRING, + ra_session); + } + } *ra_session_p = ra_session; - *rev_p = rev; - *url_p = url; + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client__get_cached_ra_session(svn_ra_session_t **ra_session_p, + svn_revnum_t *rev_p, + const char **url_p, + svn_client_ra_sessions_cache_t *ra_sessions_cache, + const char *path_or_url, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + svn_ra_session_t *ra_session = NULL; + const char *initial_url; + + SVN_ERR(svn_client_url_from_path2(&initial_url, path_or_url, ctx, pool, + pool)); + if (! initial_url) + return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL, + _("'%s' has no URL"), path_or_url); + + SVN_ERR(svn_client__cached_ra_session(&ra_session, ra_sessions_cache, + initial_url, ctx, pool)); + + /* Resolve and reparent. */ + SVN_ERR(resolve_rev_and_url(rev_p, url_p, ra_session, + path_or_url, peg_revision, revision, + ctx, pool)); + SVN_ERR(svn_ra_reparent(ra_session, *url_p, pool)); + *ra_session_p = ra_session; return SVN_NO_ERROR; } Index: subversion/libsvn_client/status.c =================================================================== --- subversion/libsvn_client/status.c (revision 1170548) +++ subversion/libsvn_client/status.c (working copy) @@ -131,6 +131,7 @@ typedef struct report_baton_t { void *set_locks_baton; svn_depth_t depth; svn_client_ctx_t *ctx; + svn_client_ra_sessions_cache_t *ra_sessions_for_locks; /* Pool to store locks in. */ apr_pool_t *pool; } report_baton_t; @@ -200,9 +201,8 @@ reporter_finish_report(void *report_bato /* Open an RA session to our common ancestor and grab the locks under it. */ - SVN_ERR(svn_client__open_ra_session_internal(&ras, NULL, rb->ancestor, NULL, - NULL, FALSE, TRUE, - rb->ctx, subpool)); + SVN_ERR(svn_client__cached_ra_session(&ras, rb->ra_sessions_for_locks, + rb->ancestor, rb->ctx, subpool)); /* The locks need to live throughout the edit. Note that if the server doesn't support lock discovery, we'll just not do locky @@ -252,7 +252,7 @@ static svn_ra_reporter3_t lock_fetch_rep svn_error_t * -svn_client_status5(svn_revnum_t *result_rev, +svn_client_status6(svn_revnum_t *result_rev, svn_client_ctx_t *ctx, const char *path, const svn_opt_revision_t *revision, @@ -265,6 +265,8 @@ svn_client_status5(svn_revnum_t *result_ const apr_array_header_t *changelists, svn_client_status_func_t status_func, void *status_baton, + svn_client_ra_sessions_cache_t *ra_sessions_cache_1, + svn_client_ra_sessions_cache_t *ra_sessions_cache_2, apr_pool_t *pool) /* ### aka scratch_pool */ { struct status_baton sb; @@ -366,10 +368,8 @@ svn_client_status5(svn_revnum_t *result_ svn_dirent_local_style(dir, pool)); /* Open a repository session to the URL. */ - SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, URL, - dir_abspath, - NULL, FALSE, TRUE, - ctx, pool)); + SVN_ERR(svn_client__cached_ra_session(&ra_session, ra_sessions_cache_1, + URL, ctx, pool)); SVN_ERR(svn_ra_has_capability(ra_session, &server_supports_depth, SVN_RA_CAPABILITY_DEPTH, pool)); @@ -445,6 +445,7 @@ svn_client_status5(svn_revnum_t *result_ rb.ancestor = apr_pstrdup(pool, URL); /* Edited later */ rb.set_locks_baton = set_locks_baton; rb.ctx = ctx; + rb.ra_sessions_for_locks = ra_sessions_cache_2; rb.pool = pool; if (depth == svn_depth_unknown) Index: subversion/libsvn_ra/ra_loader.c =================================================================== --- subversion/libsvn_ra/ra_loader.c (revision 1170548) +++ subversion/libsvn_ra/ra_loader.c (working copy) @@ -297,6 +297,7 @@ svn_error_t *svn_ra_open4(svn_ra_session = SVN_CONFIG_DEFAULT_OPTION_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT; const char *corrected_url; + SVN_DBG(("RA_open (%s)\n", repos_URL)); /* Initialize the return variable. */ *session_p = NULL; Index: subversion/svn/info-cmd.c =================================================================== --- subversion/svn/info-cmd.c (revision 1170548) +++ subversion/svn/info-cmd.c (working copy) @@ -592,6 +592,8 @@ svn_cl__info(apr_getopt_t *os, svn_opt_revision_t peg_revision; svn_client_info_receiver2_t receiver; const char *path_prefix; + svn_client_ra_sessions_cache_t *ra_sessions_cache + = svn_client_ra_sessions_cache_init(pool); SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os, opt_state->targets, @@ -647,12 +649,12 @@ svn_cl__info(apr_getopt_t *os, SVN_ERR(svn_dirent_get_absolute(&truepath, truepath, subpool)); } - err = svn_client_info3(truepath, + err = svn_client_info4(truepath, &peg_revision, &(opt_state->start_revision), opt_state->depth, TRUE, TRUE, opt_state->changelists, receiver, (void *) path_prefix, - ctx, subpool); + ra_sessions_cache, ctx, subpool); if (err) { Index: subversion/svn/status-cmd.c =================================================================== --- subversion/svn/status-cmd.c (revision 1170548) +++ subversion/svn/status-cmd.c (working copy) @@ -266,6 +266,10 @@ svn_cl__status(apr_getopt_t *os, int i; svn_opt_revision_t rev; struct status_baton sb; + svn_client_ra_sessions_cache_t *ra_sessions_cache + = svn_client_ra_sessions_cache_init(scratch_pool); + svn_client_ra_sessions_cache_t *ra_sessions_for_locks + = svn_client_ra_sessions_cache_init(scratch_pool); SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os, opt_state->targets, @@ -328,7 +332,7 @@ svn_cl__status(apr_getopt_t *os, /* Retrieve a hash of status structures with the information requested by the user. */ - SVN_ERR(svn_cl__try(svn_client_status5(&repos_rev, ctx, target, &rev, + SVN_ERR(svn_cl__try(svn_client_status6(&repos_rev, ctx, target, &rev, opt_state->depth, opt_state->verbose, opt_state->update, @@ -337,6 +341,8 @@ svn_cl__status(apr_getopt_t *os, FALSE /* depth_as_sticky */, opt_state->changelists, print_status, &sb, + ra_sessions_cache, + ra_sessions_for_locks, iterpool), NULL, opt_state->quiet, /* not versioned: */