Author: rhuijben
Date: Thu Dec 19 16:09:26 2013
New Revision: 1552324

URL: http://svn.apache.org/r1552324
Log:
Introduce a new ra api: svn_ra_session_dup() which allows opening a new ra
session from an existing ra session. While this by itself might help
performance in a few specific scenarios where opening a repository is
expensive, it also allows moving certain kinds of ra backwards
compatibility code into the ra layer itself, that are otherwise impossible.

Update two usages to add some test coverage.

* subversion/include/svn_ra.h
  (svn_ra_dup_session): New function.

* subversion/libsvn_client/diff.c
  (diff_repos_repos,
   diff_summarize_repos_repos): Showcase for testing. Update caller.

* subversion/libsvn_ra/ra_loader.c
  (svn_ra_dup_session): New function.

* subversion/libsvn_ra/ra_loader.h
  (svn_ra__vtable_t): Add member.

* subversion/libsvn_ra_local/ra_plugin.c
  (svn_ra_local__dup_session): New function.
  (ra_local_vtable): Update vtable.

* subversion/libsvn_ra_serf/ra_serf.h
  (svn_ra_serf__session_t): Add comment. Add config.

* subversion/libsvn_ra_serf/serf.c
  (svn_ra_serf__open): Store config.
  (ra_serf_dup_session): New function.
  (serf_vtable): Update vtable.

* subversion/libsvn_ra_svn/client.c
  (open_session): Add argument. Store config.
  (ra_svn_dup_session): New function.
  (ra_svn_reparent): Update caller.
  (ra_svn_vtable): Update vtable.

* subversion/libsvn_ra_svn/ra_svn.h
  (svn_ra_svn__session_baton_t): Add variable.

Modified:
    subversion/trunk/subversion/include/svn_ra.h
    subversion/trunk/subversion/libsvn_client/diff.c
    subversion/trunk/subversion/libsvn_ra/ra_loader.c
    subversion/trunk/subversion/libsvn_ra/ra_loader.h
    subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c
    subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h
    subversion/trunk/subversion/libsvn_ra_serf/serf.c
    subversion/trunk/subversion/libsvn_ra_svn/client.c
    subversion/trunk/subversion/libsvn_ra_svn/ra_svn.h

Modified: subversion/trunk/subversion/include/svn_ra.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_ra.h?rev=1552324&r1=1552323&r2=1552324&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_ra.h (original)
+++ subversion/trunk/subversion/include/svn_ra.h Thu Dec 19 16:09:26 2013
@@ -747,6 +747,28 @@ svn_ra_open4(svn_ra_session_t **session_
              apr_hash_t *config,
              apr_pool_t *pool);
 
+/**
+ * Open a new ra session @a *new_session to the same repository as an existing
+ * ra session @a old_session, copying the callbacks, auth baton, etc. from the
+ * old session.
+ *
+ * If @a session_url is not NULL, parent the new session at session_url. Note
+ * that @a session_url MUST BE in the same repository as @a old_session.
+ * Otherwise the same root will be used.
+ *
+ * Allocate @a new_session in @a result_pool. Perform temporary allocations
+ * in @a scratch_pool
+ *
+ * @since New in 1.9.
+ */
+svn_error_t *
+svn_ra_dup_session(svn_ra_session_t **new_session,
+                   svn_ra_session_t *old_session,
+                   const char *session_url,
+                   apr_pool_t *result_pool,
+                   apr_pool_t *scratch_pool);
+
+
 /** Similar to svn_ra_open4(), but with @a corrected_url always passed
  * as @c NULL.
  *

Modified: subversion/trunk/subversion/libsvn_client/diff.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/diff.c?rev=1552324&r1=1552323&r2=1552324&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/diff.c (original)
+++ subversion/trunk/subversion/libsvn_client/diff.c Thu Dec 19 16:09:26 2013
@@ -1773,8 +1773,8 @@ diff_repos_repos(const svn_wc_diff_callb
   /* Now, we open an extra RA session to the correct anchor
      location for URL1.  This is used during the editor calls to fetch file
      contents.  */
-  SVN_ERR(svn_client_open_ra_session2(&extra_ra_session, anchor1, wri_abspath,
-                                      ctx, pool, pool));
+  SVN_ERR(svn_ra_dup_session(&extra_ra_session, ra_session, anchor1,
+                             pool, pool));
 
   SVN_ERR(svn_client__get_diff_editor2(
                 &diff_editor, &diff_edit_baton,
@@ -2329,8 +2329,8 @@ diff_summarize_repos_repos(svn_client_di
 
   /* Now, we open an extra RA session to the correct anchor
      location for URL1.  This is used to get deleted path information.  */
-  SVN_ERR(svn_client_open_ra_session2(&extra_ra_session, anchor1, NULL,
-                                      ctx, pool, pool));
+  SVN_ERR(svn_ra_dup_session(&extra_ra_session, ra_session, anchor1,
+                             pool, pool));
 
   SVN_ERR(svn_client__get_diff_editor2(&diff_editor, &diff_edit_baton,
                                        extra_ra_session,

Modified: subversion/trunk/subversion/libsvn_ra/ra_loader.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra/ra_loader.c?rev=1552324&r1=1552323&r2=1552324&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra/ra_loader.c (original)
+++ subversion/trunk/subversion/libsvn_ra/ra_loader.c Thu Dec 19 16:09:26 2013
@@ -526,6 +526,45 @@ svn_error_t *svn_ra_open4(svn_ra_session
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_ra_dup_session(svn_ra_session_t **new_session,
+                   svn_ra_session_t *old_session,
+                   const char *session_url,
+                   apr_pool_t *result_pool,
+                   apr_pool_t *scratch_pool)
+{
+  svn_ra_session_t *session;
+
+  if (session_url)
+    {
+      const char *dummy;
+
+      /* This verifies in new_session_url is in the repository */
+      SVN_ERR(svn_ra_get_path_relative_to_root(old_session,
+                                               &dummy,
+                                               session_url,
+                                               scratch_pool));
+    }
+  else
+    SVN_ERR(svn_ra_get_session_url(old_session, &session_url, scratch_pool));
+
+  /* Create the session object. */
+  session = apr_pcalloc(result_pool, sizeof(*session));
+  session->cancel_func = old_session->cancel_func;
+  session->cancel_baton = old_session->cancel_baton;
+  session->vtable = old_session->vtable;
+  session->pool = result_pool;
+
+  SVN_ERR(old_session->vtable->dup_session(session,
+                                           old_session,
+                                           session_url,
+                                           result_pool,
+                                           scratch_pool));
+
+  *new_session = session;
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *svn_ra_reparent(svn_ra_session_t *session,
                              const char *url,
                              apr_pool_t *pool)

Modified: subversion/trunk/subversion/libsvn_ra/ra_loader.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra/ra_loader.h?rev=1552324&r1=1552323&r2=1552324&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra/ra_loader.h (original)
+++ subversion/trunk/subversion/libsvn_ra/ra_loader.h Thu Dec 19 16:09:26 2013
@@ -63,6 +63,12 @@ typedef struct svn_ra__vtable_t {
                                void *callback_baton,
                                apr_hash_t *config,
                                apr_pool_t *pool);
+  /* Backs svn_ra_dup_session */
+  svn_error_t * (*dup_session)(svn_ra_session_t *new_session,
+                               svn_ra_session_t *old_session,
+                               const char *new_session_url,
+                               apr_pool_t *result_pool,
+                               apr_pool_t *scratch_pool);
   /* See svn_ra_reparent(). */
   /* URL is guaranteed to have what get_repos_root() returns as a prefix. */
   svn_error_t *(*reparent)(svn_ra_session_t *session,

Modified: subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c?rev=1552324&r1=1552323&r2=1552324&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c Thu Dec 19 16:09:26 
2013
@@ -613,6 +613,53 @@ svn_ra_local__open(svn_ra_session_t *ses
 }
 
 static svn_error_t *
+svn_ra_local__dup_session(svn_ra_session_t *new_session,
+                          svn_ra_session_t *session,
+                          const char *new_session_url,
+                          apr_pool_t *result_pool,
+                          apr_pool_t *scratch_pool)
+{
+  svn_ra_local__session_baton_t *old_sess = session->priv;
+  svn_ra_local__session_baton_t *new_sess;
+  const char *fs_path;
+
+  /* Allocate and stash the session_sess args we have already. */
+  new_sess = apr_pcalloc(result_pool, sizeof(*new_sess));
+  new_sess->callbacks = old_sess->callbacks;
+  new_sess->callback_baton = old_sess->callback_baton;
+
+  /* ### Re-use existing FS handle? */
+
+  /* Reuse existing code */
+  SVN_ERR(svn_ra_local__split_URL(&(new_sess->repos),
+                                  &(new_sess->repos_url),
+                                  &fs_path,
+                                  new_session_url,
+                                  result_pool));
+
+  new_sess->fs_path = svn_stringbuf_create(fs_path, result_pool);
+
+  /* Cache the filesystem object from the repos here for
+     convenience. */
+  new_sess->fs = svn_repos_fs(new_sess->repos);
+
+  /* Ignore FS warnings. */
+  svn_fs_set_warning_func(new_sess->fs, ignore_warnings, NULL);
+
+  /* Cache the repository UUID as well */
+  new_sess->uuid = apr_pstrdup(result_pool, old_sess->uuid);
+
+  new_sess->username = old_sess->username
+                            ? apr_pstrdup(result_pool, old_sess->username)
+                            : NULL;
+
+  new_sess->useragent = apr_pstrdup(result_pool, old_sess->useragent);
+  new_session->priv = new_sess;
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
 svn_ra_local__reparent(svn_ra_session_t *session,
                        const char *url,
                        apr_pool_t *pool)
@@ -1702,6 +1749,7 @@ static const svn_ra__vtable_t ra_local_v
   svn_ra_local__get_description,
   svn_ra_local__get_schemes,
   svn_ra_local__open,
+  svn_ra_local__dup_session,
   svn_ra_local__reparent,
   svn_ra_local__get_session_url,
   svn_ra_local__get_latest_revnum,

Modified: subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h?rev=1552324&r1=1552323&r2=1552324&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h Thu Dec 19 16:09:26 
2013
@@ -99,10 +99,13 @@ typedef struct svn_ra_serf__connection_t
  * The master serf RA session.
  *
  * This is stored in the ra session ->priv field.
+ *
+ * ### Check ra_serf_dup_session when adding fields.
  */
 struct svn_ra_serf__session_t {
   /* Pool for allocations during this session */
   apr_pool_t *pool;
+  apr_hash_t *config; /* For duplicating */
 
   /* The current context */
   serf_context_t *context;

Modified: subversion/trunk/subversion/libsvn_ra_serf/serf.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/serf.c?rev=1552324&r1=1552323&r2=1552324&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/serf.c Thu Dec 19 16:09:26 2013
@@ -494,6 +494,7 @@ svn_ra_serf__open(svn_ra_session_t *sess
 
   serf_sess = apr_pcalloc(pool, sizeof(*serf_sess));
   serf_sess->pool = svn_pool_create(pool);
+  serf_sess->config = config;
   serf_sess->wc_callbacks = callbacks;
   serf_sess->wc_callback_baton = callback_baton;
   serf_sess->progress_func = callbacks->progress_func;
@@ -598,6 +599,181 @@ svn_ra_serf__open(svn_ra_session_t *sess
   return SVN_NO_ERROR;
 }
 
+/* Implements svn_ra__vtable_t.dup_session */
+static svn_error_t *
+ra_serf_dup_session(svn_ra_session_t *new_session,
+                    svn_ra_session_t *old_session,
+                    const char *new_session_url,
+                    apr_pool_t *result_pool,
+                    apr_pool_t *scratch_pool)
+{
+  svn_ra_serf__session_t *old_sess = old_session->priv;
+  svn_ra_serf__session_t *new_sess;
+  apr_status_t status;
+
+  if (new_session_url)
+    {
+      const char *dummy;
+      SVN_ERR(svn_ra_get_path_relative_to_root(old_session, &dummy,
+                                               new_session_url,
+                                               scratch_pool));
+    }
+
+  new_sess = apr_pmemdup(result_pool, old_sess, sizeof(*new_sess));
+
+  new_sess->pool = result_pool;
+  /* config */
+  /* max_connections */
+  /* using_ssl */
+  /* using_compression */
+  /* http10 */
+  /* using_chunked_requests */
+  /* detect_chunking */
+
+  if (new_sess->useragent)
+    new_sess->useragent = apr_pstrdup(result_pool, new_sess->useragent);
+
+  if (new_sess->vcc_url)
+    new_sess->vcc_url = apr_pstrdup(result_pool, new_sess->vcc_url);
+
+  new_sess->auth_state = NULL;
+  new_sess->auth_attempts = 0;
+
+  /* Callback functions to get info from WC */
+  /* wc_callbacks */
+  /* wc_callback_baton */
+
+  /* progress_func */
+  /* progress_baton */
+
+  /* cancel_func */
+  /* cancel_baton */
+
+  /* shim_callbacks */
+
+  new_sess->pending_error = NULL;
+
+  /* authn_types */
+
+  /* Keys and values are static */
+  if (new_sess->capabilities)
+    new_sess->capabilities = apr_hash_copy(result_pool, 
new_sess->capabilities);
+
+  if (new_sess->activity_collection_url)
+    {
+      new_sess->activity_collection_url
+                = apr_pstrdup(result_pool, new_sess->activity_collection_url);
+    }
+
+   /* using_proxy */
+
+  if (new_sess->proxy_username)
+    {
+      new_sess->proxy_username
+                = apr_pstrdup(result_pool, new_sess->proxy_username);
+    }
+
+  if (new_sess->proxy_password)
+    {
+      new_sess->proxy_username
+                = apr_pstrdup(result_pool, new_sess->proxy_password);
+    }
+
+  new_sess->proxy_auth_attempts = 0;
+
+  /* trust_default_ca */
+
+  if (new_sess->ssl_authorities)
+    {
+      new_sess->ssl_authorities = apr_pstrdup(result_pool,
+                                              new_sess->ssl_authorities);
+    }
+
+  if (new_sess->uuid)
+    new_sess->uuid = apr_pstrdup(result_pool, new_sess->uuid);
+
+  /* timeout */
+  /* supports_deadprop_count */
+
+  if (new_sess->me_resource)
+    new_sess->me_resource = apr_pstrdup(result_pool, new_sess->me_resource);
+  if (new_sess->rev_stub)
+    new_sess->rev_stub = apr_pstrdup(result_pool, new_sess->rev_stub);
+  if (new_sess->txn_stub)
+    new_sess->txn_stub = apr_pstrdup(result_pool, new_sess->txn_stub);
+  if (new_sess->txn_root_stub)
+    new_sess->txn_root_stub = apr_pstrdup(result_pool,
+                                          new_sess->txn_root_stub);
+  if (new_sess->vtxn_stub)
+    new_sess->vtxn_stub = apr_pstrdup(result_pool, new_sess->vtxn_stub);
+  if (new_sess->vtxn_root_stub)
+    new_sess->vtxn_root_stub = apr_pstrdup(result_pool,
+                                           new_sess->vtxn_root_stub);
+
+  /* Keys and values are static */
+  if (new_sess->supported_posts)
+    new_sess->supported_posts = apr_hash_copy(result_pool,
+                                              new_sess->supported_posts);
+
+  /* ### Can we copy this? */
+  SVN_ERR(svn_ra_serf__blncache_create(&new_sess->blncache,
+                                       new_sess->pool));
+
+  if (new_sess->server_allows_bulk)
+    new_sess->server_allows_bulk = apr_pstrdup(result_pool,
+                                               new_sess->server_allows_bulk);
+
+  new_sess->repos_root_str = apr_pstrdup(result_pool,
+                                         new_sess->repos_root_str);
+  status = apr_uri_parse(result_pool, new_sess->repos_root_str,
+                         &new_sess->repos_root);
+  if (status)
+    return svn_ra_serf__wrap_err(status, NULL);
+
+  new_sess->session_url_str = apr_pstrdup(result_pool, new_session_url);
+
+  status = apr_uri_parse(result_pool, new_sess->session_url_str,
+                         &new_sess->session_url);
+
+  if (status)
+    return svn_ra_serf__wrap_err(status, NULL);
+
+  /* svn_boolean_t supports_inline_props */
+  /* supports_rev_rsrc_replay */
+
+  new_sess->context = serf_context_create(result_pool);
+
+  SVN_ERR(load_config(new_sess, old_sess->config, result_pool));
+
+  new_sess->conns[0] = apr_pcalloc(result_pool,
+                                   sizeof(*new_sess->conns[0]));
+  new_sess->conns[0]->bkt_alloc =
+          serf_bucket_allocator_create(result_pool, NULL, NULL);
+  new_sess->conns[0]->session = new_sess;
+  new_sess->conns[0]->last_status_code = -1;
+
+  /* go ahead and tell serf about the connection. */
+  status =
+    serf_connection_create2(&new_sess->conns[0]->conn,
+                            new_sess->context,
+                            new_sess->session_url,
+                            svn_ra_serf__conn_setup, new_sess->conns[0],
+                            svn_ra_serf__conn_closed, new_sess->conns[0],
+                            result_pool);
+  if (status)
+    return svn_ra_serf__wrap_err(status, NULL);
+
+  /* Set the progress callback. */
+  serf_context_set_progress_cb(new_sess->context, svn_ra_serf__progress,
+                               new_sess);
+
+  new_sess->num_conns = 1;
+
+  new_session->priv = new_sess;
+
+  return SVN_NO_ERROR;
+}
+
 /* Implements svn_ra__vtable_t.reparent(). */
 static svn_error_t *
 svn_ra_serf__reparent(svn_ra_session_t *ra_session,
@@ -1270,6 +1446,7 @@ static const svn_ra__vtable_t serf_vtabl
   ra_serf_get_description,
   ra_serf_get_schemes,
   svn_ra_serf__open,
+  ra_serf_dup_session,
   svn_ra_serf__reparent,
   svn_ra_serf__get_session_url,
   svn_ra_serf__get_latest_revnum,

Modified: subversion/trunk/subversion/libsvn_ra_svn/client.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_svn/client.c?rev=1552324&r1=1552323&r2=1552324&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/trunk/subversion/libsvn_ra_svn/client.c Thu Dec 19 16:09:26 2013
@@ -598,6 +598,7 @@ static svn_error_t *open_session(svn_ra_
                                  const apr_uri_t *uri,
                                  const char *tunnel_name,
                                  const char **tunnel_argv,
+                                 apr_hash_t *config,
                                  const svn_ra_callbacks2_t *callbacks,
                                  void *callbacks_baton,
                                  apr_pool_t *pool)
@@ -622,6 +623,7 @@ static svn_error_t *open_session(svn_ra_
   sess->callbacks = callbacks;
   sess->callbacks_baton = callbacks_baton;
   sess->bytes_read = sess->bytes_written = 0;
+  sess->config = config;
 
   if (tunnel_name)
     {
@@ -823,13 +825,65 @@ static svn_error_t *ra_svn_open(svn_ra_s
 
   /* We open the session in a subpool so we can get rid of it if we
      reparent with a server that doesn't support reparenting. */
-  SVN_ERR(open_session(&sess, url, &uri, tunnel, tunnel_argv,
+  SVN_ERR(open_session(&sess, url, &uri, tunnel, tunnel_argv, config,
                        callbacks, callback_baton, sess_pool));
   session->priv = sess;
 
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *ra_svn_dup_session(svn_ra_session_t *new_session,
+                                       svn_ra_session_t *old_session,
+                                       const char *new_session_url,
+                                       apr_pool_t *result_pool,
+                                       apr_pool_t *scratch_pool)
+{
+  apr_pool_t *sess_pool = svn_pool_create(result_pool);
+  svn_ra_svn__session_baton_t *old_sess = old_session->priv;
+  svn_ra_svn__session_baton_t *new_sess;
+  const char *tunnel, **tunnel_argv;
+  apr_uri_t uri;
+  svn_config_t *cfg, *cfg_client;
+  apr_hash_t *config = old_sess->config;
+  const svn_ra_callbacks2_t *callbacks = old_sess->callbacks;
+  void *callback_baton = old_sess->callbacks_baton;
+
+  SVN_ERR(parse_url(new_session_url, &uri, sess_pool));
+
+  parse_tunnel(new_session_url, &tunnel, result_pool);
+
+  /* Use the default tunnel implementation if we got a tunnel name,
+     but either do not have tunnel handler callbacks installed, or
+     the handlers don't like the tunnel name. */
+  if (tunnel
+      && (!callbacks->open_tunnel_func
+          || (callbacks->check_tunnel_func && callbacks->open_tunnel_func
+              && !callbacks->check_tunnel_func(callbacks->tunnel_baton,
+                                               tunnel))))
+    SVN_ERR(find_tunnel_agent(tunnel, uri.hostinfo, &tunnel_argv,
+                              config,
+                              result_pool));
+  else
+    tunnel_argv = NULL;
+
+  cfg_client = config
+               ? svn_hash_gets(config, SVN_CONFIG_CATEGORY_CONFIG)
+               : NULL;
+  cfg = config ? svn_hash_gets(config, SVN_CONFIG_CATEGORY_SERVERS) : NULL;
+  svn_auth_set_parameter(callbacks->auth_baton,
+                         SVN_AUTH_PARAM_CONFIG_CATEGORY_CONFIG, cfg_client);
+  svn_auth_set_parameter(callbacks->auth_baton,
+                         SVN_AUTH_PARAM_CONFIG_CATEGORY_SERVERS, cfg);
+
+  /* We open the session in a subpool so we can get rid of it if we
+     reparent with a server that doesn't support reparenting. */
+  SVN_ERR(open_session(&new_sess, new_session_url, &uri, tunnel, tunnel_argv,
+                       config, callbacks, callback_baton, sess_pool));
+  new_session->priv = new_sess;
+
+  return SVN_NO_ERROR;
+}
+
 static svn_error_t *ra_svn_reparent(svn_ra_session_t *ra_session,
                                     const char *url,
                                     apr_pool_t *pool)
@@ -860,7 +914,8 @@ static svn_error_t *ra_svn_reparent(svn_
   err = parse_url(url, &uri, sess_pool);
   if (! err)
     err = open_session(&new_sess, url, &uri, sess->tunnel_name, 
sess->tunnel_argv,
-                       sess->callbacks, sess->callbacks_baton, sess_pool);
+                       sess->config, sess->callbacks, sess->callbacks_baton,
+                       sess_pool);
   /* We destroy the new session pool on error, since it is allocated in
      the main session pool. */
   if (err)
@@ -2808,6 +2863,7 @@ static const svn_ra__vtable_t ra_svn_vta
   ra_svn_get_description,
   ra_svn_get_schemes,
   ra_svn_open,
+  ra_svn_dup_session,
   ra_svn_reparent,
   ra_svn_get_session_url,
   ra_svn_get_latest_rev,

Modified: subversion/trunk/subversion/libsvn_ra_svn/ra_svn.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_svn/ra_svn.h?rev=1552324&r1=1552323&r2=1552324&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_svn/ra_svn.h (original)
+++ subversion/trunk/subversion/libsvn_ra_svn/ra_svn.h Thu Dec 19 16:09:26 2013
@@ -131,6 +131,7 @@ struct svn_ra_svn__session_baton_t {
   const char **tunnel_argv;
   const svn_ra_callbacks2_t *callbacks;
   void *callbacks_baton;
+  apr_hash_t *config;
   apr_off_t bytes_read, bytes_written; /* apr_off_t's because that's what
                                           the callback interface uses */
   const char *useragent;


Reply via email to