#define SVN_CLIENT__MAX_REDIRECT_ATTEMPTS 3 /* ### TODO: Make configurable. */
svn_error_t *
svn_client__open_ra_session_internal(svn_ra_sessio n_t **ra_session,
const char **corrected_url,
const char *base_url,
const char *base_dir_abspath,
const apr_array_header_t *commit_items,
svn_boolean_t use_admin,
svn_boolean_t read_only_wc,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
svn_ra_callbacks2_t *cbtable;
callback_baton_t *cb = apr_pcalloc(pool, sizeof(*cb));
const char *uuid = NULL;
SVN_ERR_ASSERT(base_dir_abspath != NULL || ! use_admin);
SVN_ERR_ASSERT(base_dir_abspath == NULL
|| svn_dirent_is_absolute(base_dir_abspath));
SVN_ERR(svn_ra_create_callbacks(&cbtable, pool));
cbtable->open_tmp_file = open_tmp_file;
cbtable->get_wc_prop = use_admin ? get_wc_prop : NULL;
cbtable->set_wc_prop = read_only_wc ? NULL : set_wc_prop;
cbtable->push_wc_prop = commit_items ? push_wc_prop : NULL;
cbtable->invalidate_wc_props = read_only_wc ? NULL : invalidate_wc_props;
cbtable->auth_baton = ctx->auth_baton; /* new-style */
cbtable->progress_func = ctx->progress_func;
cbtable->progress_baton = ctx->progress_baton;
cbtable->cancel_func = ctx->cancel_func ? cancel_callback : NULL;
cbtable->get_client_string = get_client_string;
cbtable->get_wc_contents = get_wc_contents;
cb->base_dir_abspath = base_dir_abspath;
cb->commit_items = commit_items;
cb->ctx = ctx;
if (base_dir_abspath)
{
svn_error_t *err = svn_wc__node_get_repos_info(NULL, &uuid, ctx->wc_ctx,
base_dir_abspath,
pool, pool);
if (err && (err->apr_err == SVN_ERR_WC_NOT_WORKING_COPY
|| err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND
|| err->apr_err == SVN_ERR_WC_UPGRADE_REQUIRED))
{
svn_error_clear(err);
uuid = NULL;
}
else
{
SVN_ERR(err);
cb->base_dir_isversioned = TRUE;
}
}
/* If the caller allows for auto-following redirections, and the
RA->open() call above reveals a CORRECTED_URL, try the new URL.
We'll do this in a loop up to some maximum number follow-and-retry
attempts. */
if (corrected_url)
{
apr_hash_t *attempted = apr_hash_make(pool);
int attempts_left = SVN_CLIENT__MAX_REDIRECT_ATTEMPTS;
*corrected_url = NULL;
while (attempts_left--)
{
const char *corrected = NULL;
/* Try to open the RA session. If this is our last attempt,
don't accept corrected URLs from the RA provider. */
SVN_ERR(svn_ra_open4(ra_session,
attempts_left == 0 ? NULL : &corrected,
base_url, uuid, cbtable, cb, ctx->config, pool));
/* No error and no corrected URL? We're done here. */
if (! corrected)
break;
/* Notify the user that a redirect is being followed. */
if (ctx->notify_func2 != NULL)
{
svn_wc_notify_t *notify =
svn_wc_create_notify_url(corrected,
svn_wc_notify_url_redirect, pool);
(*ctx->notify_func2)(ctx->notify_baton2, notify, pool);
}
/* Our caller will want to know what our final corrected URL was. */
*corrected_url = corrected;
/* Make sure we've not attempted this URL before. */
if (apr_hash_get(attempted, corrected, APR_HASH_KEY_STRING))
return svn_error_createf(SVN_ERR_CLIENT_CYCLE_DETECTED, NULL,
_("Redirect cycle detected for URL '%s'"),
corrected);
/* Remember this CORRECTED_URL so we don't wind up in a loop. */
apr_hash_set(attempted, corrected, APR_HASH_KEY_STRING, (void *)1);
base_url = corrected;
}
}
else
{
SVN_ERR(svn_ra_open4(ra_session, NULL, base_url,
uuid, cbtable, cb, ctx->config, pool));
}
return SVN_NO_ERROR;
}
#undef SVN_CLIENT__MAX_REDIRECT_ATTEMPTS
Bookmarks