You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2018/11/07 12:30:11 UTC
svn commit: r1846002 [13/44] - in /subversion/branches/ra-git: ./ build/
build/ac-macros/ build/generator/ build/generator/swig/
build/generator/templates/ build/generator/util/ build/win32/
contrib/client-side/ contrib/client-side/svn_load_dirs/ contr...
Modified: subversion/branches/ra-git/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_ra_serf/ra_serf.h?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/ra-git/subversion/libsvn_ra_serf/ra_serf.h Wed Nov 7 12:30:06 2018
@@ -113,8 +113,12 @@ struct svn_ra_serf__session_t {
/* Are we using ssl */
svn_boolean_t using_ssl;
- /* Should we use compression for network transmissions? */
- svn_boolean_t using_compression;
+ /* Tristate flag that indicates if we should use compression for
+ network transmissions. If svn_tristate_true or svn_tristate_false,
+ the compression should be enabled and disabled, respectively.
+ If svn_tristate_unknown, determine this automatically based
+ on network parameters. */
+ svn_tristate_t using_compression;
/* The user agent string */
const char *useragent;
@@ -261,6 +265,15 @@ struct svn_ra_serf__session_t {
/* Indicates whether the server can understand svndiff version 1. */
svn_boolean_t supports_svndiff1;
+
+ /* Indicates whether the server can understand svndiff version 2. */
+ svn_boolean_t supports_svndiff2;
+
+ /* Indicates whether the server sends the result checksum in the response
+ * to a successful PUT request. */
+ svn_boolean_t supports_put_result_checksum;
+
+ apr_interval_time_t conn_latency;
};
#define SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(sess) ((sess)->me_resource != NULL)
@@ -1418,6 +1431,18 @@ svn_ra_serf__get_locks(svn_ra_session_t
svn_depth_t depth,
apr_pool_t *pool);
+/* Implements svn_ra__vtable_t.list(). */
+svn_error_t *
+svn_ra_serf__list(svn_ra_session_t *ra_session,
+ const char *path,
+ svn_revnum_t revision,
+ const apr_array_header_t *patterns,
+ svn_depth_t depth,
+ apr_uint32_t dirent_fields,
+ svn_ra_dirent_receiver_t receiver,
+ void *receiver_baton,
+ apr_pool_t *scratch_pool);
+
/* Request a mergeinfo-report from the URL attached to SESSION,
and fill in the MERGEINFO hash with the results.
@@ -1568,6 +1593,24 @@ svn_ra_serf__uri_parse(apr_uri_t *uri,
const char *url_str,
apr_pool_t *result_pool);
+/* Setup the "Accept-Encoding" header value for requests that expect
+ svndiff-encoded deltas, depending on the SESSION state. */
+void
+svn_ra_serf__setup_svndiff_accept_encoding(serf_bucket_t *headers,
+ svn_ra_serf__session_t *session);
+
+svn_boolean_t
+svn_ra_serf__is_low_latency_connection(svn_ra_serf__session_t *session);
+
+/* Return an APR array of svn_ra_serf__dav_props_t containing the
+ * properties (names and namespaces) corresponding to the flegs set
+ * in DIRENT_FIELDS. If SESSION does not support deadprops, only
+ * the generic "DAV:allprop" will be returned. Allocate the result
+ * in RESULT_POOL. */
+apr_array_header_t *
+svn_ra_serf__get_dirent_props(apr_uint32_t dirent_fields,
+ svn_ra_serf__session_t *session,
+ apr_pool_t *result_pool);
/* Default limit for in-memory size of a request body. */
#define SVN_RA_SERF__REQUEST_BODY_IN_MEM_SIZE 256 * 1024
@@ -1601,6 +1644,19 @@ svn_error_t *
svn_ra_serf__request_body_cleanup(svn_ra_serf__request_body_t *body,
apr_pool_t *scratch_pool);
+/* Callback used in svn_ra_serf__create_stream_bucket(). ERR will be
+ will be cleared and becomes invalid after the callback returns,
+ use svn_error_dup() to preserve it. */
+typedef void
+(*svn_ra_serf__stream_bucket_errfunc_t)(void *baton, svn_error_t *err);
+
+/* Create a bucket that wraps a generic readable STREAM. This function
+ takes ownership of the passed-in stream, and will close it. */
+serf_bucket_t *
+svn_ra_serf__create_stream_bucket(svn_stream_t *stream,
+ serf_bucket_alloc_t *allocator,
+ svn_ra_serf__stream_bucket_errfunc_t errfunc,
+ void *errfunc_baton);
#if defined(SVN_DEBUG)
/* Wrapper macros to collect file and line information */
Modified: subversion/branches/ra-git/subversion/libsvn_ra_serf/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_ra_serf/replay.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_ra_serf/replay.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_ra_serf/replay.c Wed Nov 7 12:30:06 2018
@@ -166,6 +166,8 @@ typedef struct revision_report_t {
svn_ra_serf__handler_t *propfind_handler;
svn_ra_serf__handler_t *report_handler; /* For done handler */
+ svn_ra_serf__session_t *session;
+
} revision_report_t;
/* Conforms to svn_ra_serf__xml_opened_t */
@@ -630,6 +632,20 @@ replay_done(serf_request_t *request,
return SVN_NO_ERROR;
}
+/* Implements svn_ra_serf__request_header_delegate_t */
+static svn_error_t *
+setup_headers(serf_bucket_t *headers,
+ void *baton,
+ apr_pool_t *request_pool,
+ apr_pool_t *scratch_pool)
+{
+ struct revision_report_t *ctx = baton;
+
+ svn_ra_serf__setup_svndiff_accept_encoding(headers, ctx->session);
+
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_ra_serf__replay_range(svn_ra_session_t *ra_session,
svn_revnum_t start_revision,
@@ -685,7 +701,7 @@ svn_ra_serf__replay_range(svn_ra_session
wish for the best.
See issue #4287:
- http://subversion.tigris.org/issues/show_bug.cgi?id=4287
+ https://issues.apache.org/jira/browse/SVN-4287
*/
if (session->supports_rev_rsrc_replay)
{
@@ -724,6 +740,7 @@ svn_ra_serf__replay_range(svn_ra_session
rev_ctx->revision = rev;
rev_ctx->low_water_mark = low_water_mark;
rev_ctx->send_deltas = send_deltas;
+ rev_ctx->session = session;
/* Request all properties of a certain revision. */
rev_ctx->rev_props = apr_hash_make(rev_ctx->pool);
@@ -781,6 +798,10 @@ svn_ra_serf__replay_range(svn_ra_session
handler->done_delegate = replay_done;
handler->done_delegate_baton = rev_ctx;
+ handler->custom_accept_encoding = TRUE;
+ handler->header_delegate = setup_headers;
+ handler->header_delegate_baton = rev_ctx;
+
rev_ctx->report_handler = handler;
svn_ra_serf__request_create(handler);
Modified: subversion/branches/ra-git/subversion/libsvn_ra_serf/serf.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_ra_serf/serf.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_ra_serf/serf.c Wed Nov 7 12:30:06 2018
@@ -180,9 +180,10 @@ load_config(svn_ra_serf__session_t *sess
config_client = NULL;
}
- SVN_ERR(svn_config_get_bool(config, &session->using_compression,
- SVN_CONFIG_SECTION_GLOBAL,
- SVN_CONFIG_OPTION_HTTP_COMPRESSION, TRUE));
+ SVN_ERR(svn_config_get_tristate(config, &session->using_compression,
+ SVN_CONFIG_SECTION_GLOBAL,
+ SVN_CONFIG_OPTION_HTTP_COMPRESSION,
+ "auto", svn_tristate_unknown));
svn_config_get(config, &timeout_str, SVN_CONFIG_SECTION_GLOBAL,
SVN_CONFIG_OPTION_HTTP_TIMEOUT, NULL);
@@ -266,10 +267,10 @@ load_config(svn_ra_serf__session_t *sess
if (server_group)
{
- SVN_ERR(svn_config_get_bool(config, &session->using_compression,
- server_group,
- SVN_CONFIG_OPTION_HTTP_COMPRESSION,
- session->using_compression));
+ SVN_ERR(svn_config_get_tristate(config, &session->using_compression,
+ server_group,
+ SVN_CONFIG_OPTION_HTTP_COMPRESSION,
+ "auto", session->using_compression));
svn_config_get(config, &timeout_str, server_group,
SVN_CONFIG_OPTION_HTTP_TIMEOUT, timeout_str);
@@ -593,6 +594,10 @@ svn_ra_serf__open(svn_ra_session_t *sess
&& apr_pool_is_ancestor(serf_sess->pool, scratch_pool));
#endif
+ /* The actual latency will be determined as a part of the initial
+ OPTIONS request. */
+ serf_sess->conn_latency = -1;
+
err = svn_ra_serf__exchange_capabilities(serf_sess, corrected_url,
result_pool, scratch_pool);
@@ -686,7 +691,7 @@ ra_serf_dup_session(svn_ra_session_t *ne
if (new_sess->proxy_password)
{
- new_sess->proxy_username
+ new_sess->proxy_password
= apr_pstrdup(result_pool, new_sess->proxy_password);
}
@@ -752,6 +757,9 @@ ra_serf_dup_session(svn_ra_session_t *ne
/* svn_boolean_t supports_inline_props */
/* supports_rev_rsrc_replay */
/* supports_svndiff1 */
+ /* supports_svndiff2 */
+ /* supports_put_result_checksum */
+ /* conn_latency */
new_sess->context = serf_context_create(result_pool);
@@ -1055,7 +1063,7 @@ static const svn_ra__vtable_t serf_vtabl
svn_ra_serf__get_deleted_rev,
svn_ra_serf__get_inherited_props,
NULL /* set_svn_ra_open */,
- NULL /* svn_ra_list */,
+ svn_ra_serf__list,
svn_ra_serf__register_editor_shim_callbacks,
NULL /* commit_ev2 */,
NULL /* replay_range_ev2 */
Modified: subversion/branches/ra-git/subversion/libsvn_ra_serf/stat.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_ra_serf/stat.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_ra_serf/stat.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_ra_serf/stat.c Wed Nov 7 12:30:06 2018
@@ -216,64 +216,8 @@ get_dirent_props(apr_uint32_t dirent_fie
apr_pool_t *pool)
{
svn_ra_serf__dav_props_t *prop;
- apr_array_header_t *props = apr_array_make
- (pool, 7, sizeof(svn_ra_serf__dav_props_t));
-
- if (session->supports_deadprop_count != svn_tristate_false
- || ! (dirent_fields & SVN_DIRENT_HAS_PROPS))
- {
- if (dirent_fields & SVN_DIRENT_KIND)
- {
- prop = apr_array_push(props);
- prop->xmlns = "DAV:";
- prop->name = "resourcetype";
- }
-
- if (dirent_fields & SVN_DIRENT_SIZE)
- {
- prop = apr_array_push(props);
- prop->xmlns = "DAV:";
- prop->name = "getcontentlength";
- }
-
- if (dirent_fields & SVN_DIRENT_HAS_PROPS)
- {
- prop = apr_array_push(props);
- prop->xmlns = SVN_DAV_PROP_NS_DAV;
- prop->name = "deadprop-count";
- }
-
- if (dirent_fields & SVN_DIRENT_CREATED_REV)
- {
- svn_ra_serf__dav_props_t *p = apr_array_push(props);
- p->xmlns = "DAV:";
- p->name = SVN_DAV__VERSION_NAME;
- }
-
- if (dirent_fields & SVN_DIRENT_TIME)
- {
- prop = apr_array_push(props);
- prop->xmlns = "DAV:";
- prop->name = SVN_DAV__CREATIONDATE;
- }
-
- if (dirent_fields & SVN_DIRENT_LAST_AUTHOR)
- {
- prop = apr_array_push(props);
- prop->xmlns = "DAV:";
- prop->name = "creator-displayname";
- }
- }
- else
- {
- /* We found an old subversion server that can't handle
- the deadprop-count property in the way we expect.
-
- The neon behavior is to retrieve all properties in this case */
- prop = apr_array_push(props);
- prop->xmlns = "DAV:";
- prop->name = "allprop";
- }
+ apr_array_header_t *props = svn_ra_serf__get_dirent_props(dirent_fields,
+ session, pool);
prop = apr_array_push(props);
prop->xmlns = NULL;
Modified: subversion/branches/ra-git/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_ra_serf/update.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_ra_serf/update.c Wed Nov 7 12:30:06 2018
@@ -365,7 +365,7 @@ typedef struct fetch_ctx_t {
/* The handler representing this particular fetch. */
svn_ra_serf__handler_t *handler;
- svn_boolean_t using_compression;
+ svn_ra_serf__session_t *session;
/* Stores the information for the file we want to fetch. */
file_baton_t *file;
@@ -603,7 +603,7 @@ get_best_connection(report_context_t *ct
### simply can't handle the way ra_serf violates the editor v1
### drive ordering requirements.
###
- ### See http://subversion.tigris.org/issues/show_bug.cgi?id=4116.
+ ### See https://issues.apache.org/jira/browse/SVN-4116.
*/
if (ctx->report_received && (ctx->sess->max_connections > 2))
first_conn = 0;
@@ -797,19 +797,9 @@ headers_fetch(serf_bucket_t *headers,
{
serf_bucket_headers_setn(headers, SVN_DAV_DELTA_BASE_HEADER,
fetch_ctx->delta_base);
- if (fetch_ctx->using_compression)
- {
- serf_bucket_headers_setn(headers, "Accept-Encoding",
- "svndiff1;q=0.9,svndiff;q=0.8");
- }
- else
- {
- /* Do not advertise svndiff1 support if we're not interested in
- compression. */
- serf_bucket_headers_setn(headers, "Accept-Encoding", "svndiff");
- }
+ svn_ra_serf__setup_svndiff_accept_encoding(headers, fetch_ctx->session);
}
- else if (fetch_ctx->using_compression)
+ else if (fetch_ctx->session->using_compression != svn_tristate_false)
{
serf_bucket_headers_setn(headers, "Accept-Encoding", "gzip");
}
@@ -1287,7 +1277,7 @@ fetch_for_file(file_baton_t *file,
fetch_ctx = apr_pcalloc(file->pool, sizeof(*fetch_ctx));
fetch_ctx->file = file;
- fetch_ctx->using_compression = ctx->sess->using_compression;
+ fetch_ctx->session = ctx->sess;
/* Can we somehow get away with just obtaining a DIFF? */
if (SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(ctx->sess))
@@ -2178,17 +2168,7 @@ setup_update_report_headers(serf_bucket_
{
report_context_t *report = baton;
- if (report->sess->using_compression)
- {
- serf_bucket_headers_setn(headers, "Accept-Encoding",
- "gzip,svndiff1;q=0.9,svndiff;q=0.8");
- }
- else
- {
- /* Do not advertise svndiff1 support if we're not interested in
- compression. */
- serf_bucket_headers_setn(headers, "Accept-Encoding", "svndiff");
- }
+ svn_ra_serf__setup_svndiff_accept_encoding(headers, report->sess);
return SVN_NO_ERROR;
}
Modified: subversion/branches/ra-git/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_ra_serf/util.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_ra_serf/util.c Wed Nov 7 12:30:06 2018
@@ -756,6 +756,9 @@ handle_client_cert_pw(void *data,
if (creds)
{
+ /* At this stage we are unable to check whether the password
+ is correct; if it is incorrect serf will fail to establish
+ an SSL connection and will return a generic SSL error. */
svn_auth_cred_ssl_client_cert_pw_t *pw_creds;
pw_creds = creds;
*password = pw_creds->password;
@@ -1445,6 +1448,23 @@ handle_response(serf_request_t *request,
process_body:
+ /* A client cert file password was obtained and worked (any HTTP
+ response means that the SSL connection was established.) */
+ if (handler->conn->ssl_client_pw_auth_state)
+ {
+ SVN_ERR(svn_auth_save_credentials(handler->conn->ssl_client_pw_auth_state,
+ handler->session->pool));
+ handler->conn->ssl_client_pw_auth_state = NULL;
+ }
+ if (handler->conn->ssl_client_auth_state)
+ {
+ /* The cert file provider doesn't have any code to save creds so
+ this is currently a no-op. */
+ SVN_ERR(svn_auth_save_credentials(handler->conn->ssl_client_auth_state,
+ handler->session->pool));
+ handler->conn->ssl_client_auth_state = NULL;
+ }
+
/* We've been instructed to ignore the body. Drain whatever is present. */
if (handler->discard_body)
{
@@ -1571,7 +1591,7 @@ setup_request(serf_request_t *request,
{
accept_encoding = NULL;
}
- else if (handler->session->using_compression)
+ else if (handler->session->using_compression != svn_tristate_false)
{
/* Accept gzip compression if enabled. */
accept_encoding = "gzip";
@@ -2023,3 +2043,114 @@ svn_ra_serf__uri_parse(apr_uri_t *uri,
return SVN_NO_ERROR;
}
+
+void
+svn_ra_serf__setup_svndiff_accept_encoding(serf_bucket_t *headers,
+ svn_ra_serf__session_t *session)
+{
+ if (session->using_compression == svn_tristate_false)
+ {
+ /* Don't advertise support for compressed svndiff formats if
+ compression is disabled. */
+ serf_bucket_headers_setn(
+ headers, "Accept-Encoding", "svndiff");
+ }
+ else if (session->using_compression == svn_tristate_unknown &&
+ svn_ra_serf__is_low_latency_connection(session))
+ {
+ /* With http-compression=auto, advertise that we prefer svndiff2
+ to svndiff1 with a low latency connection (assuming the underlying
+ network has high bandwidth), as it is faster and in this case, we
+ don't care about worse compression ratio. */
+ serf_bucket_headers_setn(
+ headers, "Accept-Encoding",
+ "gzip,svndiff2;q=0.9,svndiff1;q=0.8,svndiff;q=0.7");
+ }
+ else
+ {
+ /* Otherwise, advertise that we prefer svndiff1 over svndiff2.
+ svndiff2 is not a reasonable substitute for svndiff1 with default
+ compression level, because, while it is faster, it also gives worse
+ compression ratio. While we can use svndiff2 in some cases (see
+ above), we can't do this generally. */
+ serf_bucket_headers_setn(
+ headers, "Accept-Encoding",
+ "gzip,svndiff1;q=0.9,svndiff2;q=0.8,svndiff;q=0.7");
+ }
+}
+
+svn_boolean_t
+svn_ra_serf__is_low_latency_connection(svn_ra_serf__session_t *session)
+{
+ return session->conn_latency >= 0 &&
+ session->conn_latency < apr_time_from_msec(5);
+}
+
+apr_array_header_t *
+svn_ra_serf__get_dirent_props(apr_uint32_t dirent_fields,
+ svn_ra_serf__session_t *session,
+ apr_pool_t *result_pool)
+{
+ svn_ra_serf__dav_props_t *prop;
+ apr_array_header_t *props = apr_array_make
+ (result_pool, 7, sizeof(svn_ra_serf__dav_props_t));
+
+ if (session->supports_deadprop_count != svn_tristate_false
+ || ! (dirent_fields & SVN_DIRENT_HAS_PROPS))
+ {
+ if (dirent_fields & SVN_DIRENT_KIND)
+ {
+ prop = apr_array_push(props);
+ prop->xmlns = "DAV:";
+ prop->name = "resourcetype";
+ }
+
+ if (dirent_fields & SVN_DIRENT_SIZE)
+ {
+ prop = apr_array_push(props);
+ prop->xmlns = "DAV:";
+ prop->name = "getcontentlength";
+ }
+
+ if (dirent_fields & SVN_DIRENT_HAS_PROPS)
+ {
+ prop = apr_array_push(props);
+ prop->xmlns = SVN_DAV_PROP_NS_DAV;
+ prop->name = "deadprop-count";
+ }
+
+ if (dirent_fields & SVN_DIRENT_CREATED_REV)
+ {
+ svn_ra_serf__dav_props_t *p = apr_array_push(props);
+ p->xmlns = "DAV:";
+ p->name = SVN_DAV__VERSION_NAME;
+ }
+
+ if (dirent_fields & SVN_DIRENT_TIME)
+ {
+ prop = apr_array_push(props);
+ prop->xmlns = "DAV:";
+ prop->name = SVN_DAV__CREATIONDATE;
+ }
+
+ if (dirent_fields & SVN_DIRENT_LAST_AUTHOR)
+ {
+ prop = apr_array_push(props);
+ prop->xmlns = "DAV:";
+ prop->name = "creator-displayname";
+ }
+ }
+ else
+ {
+ /* We found an old subversion server that can't handle
+ the deadprop-count property in the way we expect.
+
+ The neon behavior is to retrieve all properties in this case */
+ prop = apr_array_push(props);
+ prop->xmlns = "DAV:";
+ prop->name = "allprop";
+ }
+
+ return props;
+}
+
Modified: subversion/branches/ra-git/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_ra_svn/client.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_ra_svn/client.c Wed Nov 7 12:30:06 2018
@@ -46,6 +46,7 @@
#include "svn_props.h"
#include "svn_mergeinfo.h"
#include "svn_version.h"
+#include "svn_ctype.h"
#include "svn_private_config.h"
@@ -398,7 +399,7 @@ static svn_error_t *find_tunnel_agent(co
* versions have it too. If the user is using some other ssh
* implementation that doesn't accept it, they can override it
* in the [tunnels] section of the config. */
- val = "$SVN_SSH ssh -q";
+ val = "$SVN_SSH ssh -q --";
}
if (!val || !*val)
@@ -443,7 +444,7 @@ static svn_error_t *find_tunnel_agent(co
for (n = 0; cmd_argv[n] != NULL; n++)
argv[n] = cmd_argv[n];
- argv[n++] = svn_path_uri_decode(hostinfo, pool);
+ argv[n++] = hostinfo;
argv[n++] = "svnserve";
argv[n++] = "-t";
argv[n] = NULL;
@@ -629,11 +630,17 @@ static svn_error_t *open_session(svn_ra_
svn_ra_svn__list_t *mechlist, *server_caplist, *repos_caplist;
const char *client_string = NULL;
apr_pool_t *pool = result_pool;
+ svn_ra_svn__parent_t *parent;
+
+ parent = apr_pcalloc(pool, sizeof(*parent));
+ parent->client_url = svn_stringbuf_create(url, pool);
+ parent->server_url = svn_stringbuf_create(url, pool);
+ parent->path = svn_stringbuf_create_empty(pool);
sess = apr_palloc(pool, sizeof(*sess));
sess->pool = pool;
sess->is_tunneled = (tunnel_name != NULL);
- sess->url = apr_pstrdup(pool, url);
+ sess->parent = parent;
sess->user = uri->user;
sess->hostname = uri->hostname;
sess->tunnel_name = tunnel_name;
@@ -740,10 +747,11 @@ static svn_error_t *open_session(svn_ra_
* capability list, and the URL, and subsequently there is an auth
* request. */
/* Client-side capabilities list: */
- SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "n(wwwwww)cc(?c)",
+ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "n(wwwwwww)cc(?c)",
(apr_uint64_t) 2,
SVN_RA_SVN_CAP_EDIT_PIPELINE,
SVN_RA_SVN_CAP_SVNDIFF1,
+ SVN_RA_SVN_CAP_SVNDIFF2_ACCEPTED,
SVN_RA_SVN_CAP_ABSENT_ENTRIES,
SVN_RA_SVN_CAP_DEPTH,
SVN_RA_SVN_CAP_MERGEINFO,
@@ -804,6 +812,32 @@ ra_svn_get_schemes(apr_pool_t *pool)
}
+/* A simple whitelist to ensure the following are valid:
+ * user@server
+ * [::1]:22
+ * server-name
+ * server_name
+ * 127.0.0.1
+ * with an extra restriction that a leading '-' is invalid.
+ */
+static svn_boolean_t
+is_valid_hostinfo(const char *hostinfo)
+{
+ const char *p = hostinfo;
+
+ if (p[0] == '-')
+ return FALSE;
+
+ while (*p)
+ {
+ if (!svn_ctype_isalnum(*p) && !strchr(":.-_[]@", *p))
+ return FALSE;
+
+ ++p;
+ }
+
+ return TRUE;
+}
static svn_error_t *ra_svn_open(svn_ra_session_t *session,
const char **corrected_url,
@@ -837,8 +871,18 @@ static svn_error_t *ra_svn_open(svn_ra_s
|| (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));
+ {
+ const char *decoded_hostinfo;
+
+ decoded_hostinfo = svn_path_uri_decode(uri.hostinfo, result_pool);
+
+ if (!is_valid_hostinfo(decoded_hostinfo))
+ return svn_error_createf(SVN_ERR_BAD_URL, NULL, _("Invalid host '%s'"),
+ uri.hostinfo);
+
+ SVN_ERR(find_tunnel_agent(tunnel, decoded_hostinfo, &tunnel_argv,
+ config, result_pool));
+ }
else
tunnel_argv = NULL;
@@ -877,23 +921,29 @@ static svn_error_t *ra_svn_dup_session(s
return SVN_NO_ERROR;
}
-static svn_error_t *ra_svn_reparent(svn_ra_session_t *ra_session,
- const char *url,
- apr_pool_t *pool)
+/* Send the "reparent to URL" command to the server for RA_SESSION and
+ update the session state. Use SCRATCH_POOL for tempoaries.
+ */
+static svn_error_t *
+reparent_server(svn_ra_session_t *ra_session,
+ const char *url,
+ apr_pool_t *scratch_pool)
{
svn_ra_svn__session_baton_t *sess = ra_session->priv;
+ svn_ra_svn__parent_t *parent = sess->parent;
svn_ra_svn_conn_t *conn = sess->conn;
svn_error_t *err;
apr_pool_t *sess_pool;
svn_ra_svn__session_baton_t *new_sess;
apr_uri_t uri;
- SVN_ERR(svn_ra_svn__write_cmd_reparent(conn, pool, url));
- err = handle_auth_request(sess, pool);
+ /* Send the request to the server. */
+ SVN_ERR(svn_ra_svn__write_cmd_reparent(conn, scratch_pool, url));
+ err = handle_auth_request(sess, scratch_pool);
if (! err)
{
- SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, ""));
- sess->url = apr_pstrdup(sess->pool, url);
+ SVN_ERR(svn_ra_svn__read_cmd_response(conn, scratch_pool, ""));
+ svn_stringbuf_set(parent->server_url, url);
return SVN_NO_ERROR;
}
else if (err->apr_err != SVN_ERR_RA_SVN_UNKNOWN_CMD)
@@ -924,11 +974,143 @@ static svn_error_t *ra_svn_reparent(svn_
return SVN_NO_ERROR;
}
+/* Make sure that RA_SESSION's client and server-side parent infp are in
+ sync. Use SCRATCH_POOL for temporary allocations. */
+static svn_error_t *
+ensure_exact_server_parent(svn_ra_session_t *ra_session,
+ apr_pool_t *scratch_pool)
+{
+ svn_ra_svn__session_baton_t *sess = ra_session->priv;
+ svn_ra_svn__parent_t *parent = sess->parent;
+
+ /* During e.g. a checkout operation, many requests will be sent for the
+ same URL that was used to create the session. So, both sides are
+ often already in sync. */
+ if (svn_stringbuf_compare(parent->client_url, parent->server_url))
+ return SVN_NO_ERROR;
+
+ /* Actually reparent the server to the session URL. */
+ SVN_ERR(reparent_server(ra_session, parent->client_url->data,
+ scratch_pool));
+ svn_stringbuf_setempty(parent->path);
+
+ return SVN_NO_ERROR;
+}
+
+/* Return a copy of PATH, adjusted to the RA_SESSION's server parent URL.
+ Allocate the result in RESULT_POOL. */
+static const char *
+reparent_path(svn_ra_session_t *ra_session,
+ const char *path,
+ apr_pool_t *result_pool)
+{
+ svn_ra_svn__session_baton_t *sess = ra_session->priv;
+ svn_ra_svn__parent_t *parent = sess->parent;
+
+ return svn_relpath_join(parent->path->data, path, result_pool);
+}
+
+/* Return a copy of PATHS, containing the same const char * paths but
+ adjusted to the RA_SESSION's server parent URL. Returns NULL if
+ PATHS is NULL. Allocate the result in RESULT_POOL. */
+static apr_array_header_t *
+reparent_path_array(svn_ra_session_t *ra_session,
+ const apr_array_header_t *paths,
+ apr_pool_t *result_pool)
+{
+ int i;
+ apr_array_header_t *result;
+
+ if (!paths)
+ return NULL;
+
+ result = apr_array_copy(result_pool, paths);
+ for (i = 0; i < result->nelts; ++i)
+ {
+ const char **path = &APR_ARRAY_IDX(result, i, const char *);
+ *path = reparent_path(ra_session, *path, result_pool);
+ }
+
+ return result;
+}
+
+/* Return a copy of PATHS, containing the same paths for keys but adjusted
+ to the RA_SESSION's server parent URL. Keeps the values as-are and
+ returns NULL if PATHS is NULL. Allocate the result in RESULT_POOL. */
+static apr_hash_t *
+reparent_path_hash(svn_ra_session_t *ra_session,
+ apr_hash_t *paths,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ apr_hash_t *result;
+ apr_hash_index_t *hi;
+
+ if (!paths)
+ return NULL;
+
+ result = svn_hash__make(result_pool);
+ for (hi = apr_hash_first(scratch_pool, paths); hi; hi = apr_hash_next(hi))
+ {
+ const char *path = apr_hash_this_key(hi);
+ svn_hash_sets(result,
+ reparent_path(ra_session, path, result_pool),
+ apr_hash_this_val(hi));
+ }
+
+ return result;
+}
+
+static svn_error_t *ra_svn_reparent(svn_ra_session_t *ra_session,
+ const char *url,
+ apr_pool_t *pool)
+{
+ svn_ra_svn__session_baton_t *sess = ra_session->priv;
+ svn_ra_svn__parent_t *parent = sess->parent;
+ svn_ra_svn_conn_t *conn = sess->conn;
+ const char *path;
+
+ /* Eliminate reparent requests if they are to a sub-path of the
+ server's current parent path. */
+ path = svn_uri_skip_ancestor(parent->server_url->data, url, pool);
+ if (!path)
+ {
+ /* Send the request to the server.
+
+ If within the same repository, reparent to the repo root
+ because this will maximize the chance to turn future reparent
+ requests into a client-side update of the rel path. */
+ path = conn->repos_root
+ ? svn_uri_skip_ancestor(conn->repos_root, url, pool)
+ : NULL;
+
+ if (path)
+ SVN_ERR(reparent_server(ra_session, conn->repos_root, pool));
+ else
+ SVN_ERR(reparent_server(ra_session, url, pool));
+ }
+
+ /* Update the local PARENT information.
+ PARENT.SERVER_BASE_URL is already up-to-date. */
+ svn_stringbuf_set(parent->client_url, url);
+ if (path)
+ svn_stringbuf_set(parent->path, path);
+ else
+ svn_stringbuf_setempty(parent->path);
+
+ return SVN_NO_ERROR;
+}
+
static svn_error_t *ra_svn_get_session_url(svn_ra_session_t *session,
- const char **url, apr_pool_t *pool)
+ const char **url,
+ apr_pool_t *pool)
{
svn_ra_svn__session_baton_t *sess = session->priv;
- *url = apr_pstrdup(pool, sess->url);
+ svn_ra_svn__parent_t *parent = sess->parent;
+
+ *url = apr_pstrmemdup(pool, parent->client_url->data,
+ parent->client_url->len);
+
return SVN_NO_ERROR;
}
@@ -1137,6 +1319,9 @@ static svn_error_t *ra_svn_commit(svn_ra
svn_string_create(sess_baton->useragent, pool));
}
+ /* Callbacks may assume that all data is relative the sessions's URL. */
+ SVN_ERR(ensure_exact_server_parent(session, pool));
+
/* Tell the server we're starting the commit.
Send log message here for backwards compatibility with servers
before 1.5. */
@@ -1262,6 +1447,7 @@ static svn_error_t *ra_svn_get_file(svn_
svn_checksum_ctx_t *checksum_ctx;
apr_pool_t *iterpool;
+ path = reparent_path(session, path, pool);
SVN_ERR(svn_ra_svn__write_cmd_get_file(conn, pool, path, rev,
(props != NULL), (stream != NULL)));
SVN_ERR(handle_auth_request(sess_baton, pool));
@@ -1367,6 +1553,7 @@ static svn_error_t *ra_svn_get_dir(svn_r
svn_ra_svn__list_t *proplist, *dirlist;
int i;
+ path = reparent_path(session, path, pool);
SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w(c(?r)bb(!", "get-dir", path,
rev, (props != NULL), (dirents != NULL)));
SVN_ERR(send_dirent_fields(conn, dirent_fields, pool));
@@ -1463,12 +1650,14 @@ static svn_error_t *ra_svn_get_mergeinfo
apr_pool_t *pool)
{
svn_ra_svn__session_baton_t *sess_baton = session->priv;
+ svn_ra_svn__parent_t *parent = sess_baton->parent;
svn_ra_svn_conn_t *conn = sess_baton->conn;
int i;
svn_ra_svn__list_t *mergeinfo_tuple;
svn_ra_svn__item_t *elt;
const char *path;
+ paths = reparent_path_array(session, paths, pool);
SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w((!", "get-mergeinfo"));
for (i = 0; i < paths->nelts; i++)
{
@@ -1498,9 +1687,16 @@ static svn_error_t *ra_svn_get_mergeinfo
SVN_ERR(svn_ra_svn__parse_tuple(&elt->u.list, "cc",
&path, &to_parse));
SVN_ERR(svn_mergeinfo_parse(&for_path, to_parse, pool));
+
/* Correct for naughty servers that send "relative" paths
with leading slashes! */
- svn_hash_sets(*catalog, path[0] == '/' ? path + 1 :path, for_path);
+ if (path[0] == '/')
+ ++path;
+
+ /* Correct for the (potential) difference between client and
+ server-side session parent paths. */
+ path = svn_relpath_skip_ancestor(parent->path->data, path);
+ svn_hash_sets(*catalog, path, for_path);
}
}
@@ -1522,6 +1718,9 @@ static svn_error_t *ra_svn_update(svn_ra
svn_ra_svn_conn_t *conn = sess_baton->conn;
svn_boolean_t recurse = DEPTH_TO_RECURSE(depth);
+ /* Callbacks may assume that all data is relative the sessions's URL. */
+ SVN_ERR(ensure_exact_server_parent(session, scratch_pool));
+
/* Tell the server we want to start an update. */
SVN_ERR(svn_ra_svn__write_cmd_update(conn, pool, rev, target, recurse,
depth, send_copyfrom_args,
@@ -1553,6 +1752,9 @@ ra_svn_switch(svn_ra_session_t *session,
svn_ra_svn_conn_t *conn = sess_baton->conn;
svn_boolean_t recurse = DEPTH_TO_RECURSE(depth);
+ /* Callbacks may assume that all data is relative the sessions's URL. */
+ SVN_ERR(ensure_exact_server_parent(session, scratch_pool));
+
/* Tell the server we want to start a switch. */
SVN_ERR(svn_ra_svn__write_cmd_switch(conn, pool, rev, target, recurse,
switch_url, depth,
@@ -1578,6 +1780,9 @@ static svn_error_t *ra_svn_status(svn_ra
svn_ra_svn_conn_t *conn = sess_baton->conn;
svn_boolean_t recurse = DEPTH_TO_RECURSE(depth);
+ /* Callbacks may assume that all data is relative the sessions's URL. */
+ SVN_ERR(ensure_exact_server_parent(session, pool));
+
/* Tell the server we want to start a status operation. */
SVN_ERR(svn_ra_svn__write_cmd_status(conn, pool, target, recurse, rev,
depth));
@@ -1605,6 +1810,9 @@ static svn_error_t *ra_svn_diff(svn_ra_s
svn_ra_svn_conn_t *conn = sess_baton->conn;
svn_boolean_t recurse = DEPTH_TO_RECURSE(depth);
+ /* Callbacks may assume that all data is relative the sessions's URL. */
+ SVN_ERR(ensure_exact_server_parent(session, pool));
+
/* Tell the server we want to start a diff. */
SVN_ERR(svn_ra_svn__write_cmd_diff(conn, pool, rev, target, recurse,
ignore_ancestry, versus_url,
@@ -1869,6 +2077,16 @@ ra_svn_log(svn_ra_session_t *session,
svn_error_t *outer_error = NULL;
svn_error_t *err;
+ /* If we don't specify paths, the session's URL is implied.
+
+ Because the paths passed to callbacks are always relative the repos
+ root, there is no need *always* sync the parent URLs despite invoking
+ user-provided callbacks. */
+ if (paths)
+ paths = reparent_path_array(session, paths, pool);
+ else
+ SVN_ERR(ensure_exact_server_parent(session, pool));
+
err = svn_error_trace(perform_ra_svn_log(&outer_error,
session, paths,
start, end,
@@ -1894,6 +2112,7 @@ static svn_error_t *ra_svn_check_path(sv
svn_ra_svn_conn_t *conn = sess_baton->conn;
const char *kind_word;
+ path = reparent_path(session, path, pool);
SVN_ERR(svn_ra_svn__write_cmd_check_path(conn, pool, path, rev));
SVN_ERR(handle_auth_request(sess_baton, pool));
SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, "w", &kind_word));
@@ -1923,6 +2142,7 @@ static svn_error_t *ra_svn_stat(svn_ra_s
svn_ra_svn__list_t *list = NULL;
svn_dirent_t *the_dirent;
+ path = reparent_path(session, path, pool);
SVN_ERR(svn_ra_svn__write_cmd_stat(conn, pool, path, rev));
SVN_ERR(handle_unsupported_cmd(handle_auth_request(sess_baton, pool),
N_("'stat' not implemented")));
@@ -1972,6 +2192,8 @@ static svn_error_t *ra_svn_get_locations
apr_pool_t *iterpool;
int i;
+ path = reparent_path(session, path, pool);
+
/* Transmit the parameters. */
SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w(cr(!",
"get-locations", path, peg_revision));
@@ -2114,6 +2336,7 @@ ra_svn_get_location_segments(svn_ra_sess
svn_error_t *outer_err = SVN_NO_ERROR;
svn_error_t *err;
+ path = reparent_path(session, path, pool);
err = svn_error_trace(
perform_get_location_segments(&outer_err, session, path,
peg_revision, start_rev, end_rev,
@@ -2138,6 +2361,7 @@ static svn_error_t *ra_svn_get_file_revs
rev_pool = svn_pool_create(pool);
chunk_pool = svn_pool_create(pool);
+ path = reparent_path(session, path, pool);
SVN_ERR(svn_ra_svn__write_cmd_get_file_revs(sess_baton->conn, pool,
path, start, end,
include_merged_revisions));
@@ -2376,6 +2600,7 @@ static svn_error_t *ra_svn_lock(svn_ra_s
svn_error_t *err;
apr_pool_t *iterpool = svn_pool_create(pool);
+ path_revs = reparent_path_hash(session, path_revs, pool, pool);
SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w((?c)b(!", "lock-many",
comment, steal_lock));
@@ -2500,6 +2725,7 @@ static svn_error_t *ra_svn_unlock(svn_ra
svn_error_t *err;
const char *path;
+ path_tokens = reparent_path_hash(session, path_tokens, pool, pool);
SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w(b(!", "unlock-many",
break_lock));
@@ -2619,6 +2845,7 @@ static svn_error_t *ra_svn_get_lock(svn_
svn_ra_svn_conn_t* conn = sess->conn;
svn_ra_svn__list_t *list;
+ path = reparent_path(session, path, pool);
SVN_ERR(svn_ra_svn__write_cmd_get_lock(conn, pool, path));
/* Servers before 1.2 doesn't support locking. Check this here. */
@@ -2667,7 +2894,8 @@ static svn_error_t *ra_svn_get_locks(svn
int i;
/* Figure out the repository abspath from PATH. */
- full_url = svn_path_url_add_component2(sess->url, path, pool);
+ full_url = svn_path_url_add_component2(sess->parent->client_url->data,
+ path, pool);
SVN_ERR(path_relative_to_root(session, &abs_path, full_url, pool));
abs_path = svn_fspath__canonicalize(abs_path, pool);
@@ -2728,6 +2956,9 @@ static svn_error_t *ra_svn_replay(svn_ra
{
svn_ra_svn__session_baton_t *sess = session->priv;
+ /* Complex EDITOR callbacks may rely on client and server parent path
+ being in sync. */
+ SVN_ERR(ensure_exact_server_parent(session, pool));
SVN_ERR(svn_ra_svn__write_cmd_replay(sess->conn, pool, revision,
low_water_mark, send_deltas));
@@ -2758,6 +2989,9 @@ ra_svn_replay_range(svn_ra_session_t *se
svn_revnum_t rev;
svn_boolean_t drive_aborted = FALSE;
+ /* Complex EDITOR callbacks may rely on client and server parent path
+ being in sync. */
+ SVN_ERR(ensure_exact_server_parent(session, pool));
SVN_ERR(svn_ra_svn__write_cmd_replay_range(sess->conn, pool,
start_revision, end_revision,
low_water_mark, send_deltas));
@@ -2872,6 +3106,8 @@ ra_svn_get_deleted_rev(svn_ra_session_t
svn_ra_svn__session_baton_t *sess_baton = session->priv;
svn_ra_svn_conn_t *conn = sess_baton->conn;
+ path = reparent_path(session, path, pool);
+
/* Transmit the parameters. */
SVN_ERR(svn_ra_svn__write_cmd_get_deleted_rev(conn, pool, path,
peg_revision, end_revision));
@@ -2909,6 +3145,7 @@ ra_svn_get_inherited_props(svn_ra_sessio
svn_ra_svn__list_t *iproplist;
svn_boolean_t iprop_capable;
+ path = reparent_path(session, path, scratch_pool);
SVN_ERR(ra_svn_has_capability(session, &iprop_capable,
SVN_RA_CAPABILITY_INHERITED_PROPS,
scratch_pool));
@@ -2932,7 +3169,7 @@ static svn_error_t *
ra_svn_list(svn_ra_session_t *session,
const char *path,
svn_revnum_t revision,
- apr_array_header_t *patterns,
+ const apr_array_header_t *patterns,
svn_depth_t depth,
apr_uint32_t dirent_fields,
svn_ra_dirent_receiver_t receiver,
@@ -2944,6 +3181,8 @@ ra_svn_list(svn_ra_session_t *session,
int i;
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ path = reparent_path(session, path, scratch_pool);
+
/* Send the list request. */
SVN_ERR(svn_ra_svn__write_tuple(conn, scratch_pool, "w(c(?r)w(!", "list",
path, revision, svn_depth_to_word(depth)));
Modified: subversion/branches/ra-git/subversion/libsvn_ra_svn/editorp.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_ra_svn/editorp.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_ra_svn/editorp.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_ra_svn/editorp.c Wed Nov 7 12:30:06 2018
@@ -351,15 +351,9 @@ static svn_error_t *ra_svn_apply_textdel
svn_stream_set_write(diff_stream, ra_svn_svndiff_handler);
svn_stream_set_close(diff_stream, ra_svn_svndiff_close_handler);
- /* If the connection does not support SVNDIFF1 or if we don't want to use
- * compression, use the non-compressing "version 0" implementation */
- if ( svn_ra_svn_compression_level(b->conn) > 0
- && svn_ra_svn_has_capability(b->conn, SVN_RA_SVN_CAP_SVNDIFF1))
- svn_txdelta_to_svndiff3(wh, wh_baton, diff_stream, 1,
- b->conn->compression_level, pool);
- else
- svn_txdelta_to_svndiff3(wh, wh_baton, diff_stream, 0,
- b->conn->compression_level, pool);
+ svn_txdelta_to_svndiff3(wh, wh_baton, diff_stream,
+ svn_ra_svn__svndiff_version(b->conn),
+ b->conn->compression_level, pool);
return SVN_NO_ERROR;
}
Modified: subversion/branches/ra-git/subversion/libsvn_ra_svn/marshal.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_ra_svn/marshal.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_ra_svn/marshal.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_ra_svn/marshal.c Wed Nov 7 12:30:06 2018
@@ -265,6 +265,24 @@ svn_ra_svn__set_capabilities(svn_ra_svn_
return SVN_NO_ERROR;
}
+int
+svn_ra_svn__svndiff_version(svn_ra_svn_conn_t *conn)
+{
+ /* If we don't want to use compression, use the non-compressing
+ * "version 0" implementation. */
+ if (svn_ra_svn_compression_level(conn) <= 0)
+ return 0;
+
+ /* Prefer SVNDIFF2 over SVNDIFF1. */
+ if (svn_ra_svn_has_capability(conn, SVN_RA_SVN_CAP_SVNDIFF2_ACCEPTED))
+ return 2;
+ if (svn_ra_svn_has_capability(conn, SVN_RA_SVN_CAP_SVNDIFF1))
+ return 1;
+
+ /* The connection does not support SVNDIFF1/2; default to "version 0". */
+ return 0;
+}
+
apr_pool_t *
svn_ra_svn__get_pool(svn_ra_svn_conn_t *conn)
{
@@ -1142,10 +1160,17 @@ static svn_error_t *vwrite_tuple(svn_ra_
SVN_ERR(opt ? vwrite_tuple_string_opt(conn, pool, ap)
: vwrite_tuple_string(conn, pool, ap));
else if (*fmt == '(' && !opt)
- SVN_ERR(write_tuple_start_list(conn, pool));
+ {
+ /* Optional sub-tuples are not supported.
+ * If OPT was set, we would fall through to the malfunction call. */
+ SVN_ERR(write_tuple_start_list(conn, pool));
+ }
else if (*fmt == ')')
{
SVN_ERR(write_tuple_end_list(conn, pool));
+
+ /* OPT could not have been set when opening the list (see above),
+ * hence this is correct and handles nested tuples just fine. */
opt = FALSE;
}
else if (*fmt == '?')
@@ -2921,7 +2946,7 @@ svn_ra_svn__write_dirent(svn_ra_svn_conn
apr_pool_t *pool,
const char *path,
svn_dirent_t *dirent,
- apr_uint64_t dirent_fields)
+ apr_uint32_t dirent_fields)
{
const char *kind = (dirent_fields & SVN_DIRENT_KIND)
? svn_node_kind_to_word(dirent->kind)
Modified: subversion/branches/ra-git/subversion/libsvn_ra_svn/protocol
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_ra_svn/protocol?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_ra_svn/protocol (original)
+++ subversion/branches/ra-git/subversion/libsvn_ra_svn/protocol Wed Nov 7 12:30:06 2018
@@ -188,6 +188,10 @@ capability and C indicates a client capa
[CS] svndiff1 If both the client and server support svndiff version
1, this will be used as the on-the-wire format for
svndiff instead of svndiff version 0.
+[CS] accepts-svndiff2 This capability advertises support for accepting
+ svndiff2 deltas. The sender of a delta (= the editor
+ driver) may send it in any svndiff version the receiver
+ has announced it can accept.
[CS] absent-entries If the remote end announces support for this capability,
it will accept the absent-dir and absent-file editor
commands.
@@ -338,7 +342,7 @@ second place for auth-request point as n
stat
params: ( path:string [ rev:number ] )
response: ( ? entry:dirent )
- dirent: ( name:string kind:node-kind size:number has-props:bool
+ dirent: ( kind:node-kind size:number has-props:bool
created-rev:number [ created-date:string ]
[ last-author:string ] )
New in svn 1.2. If path is non-existent, an empty response is returned.
Modified: subversion/branches/ra-git/subversion/libsvn_ra_svn/ra_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_ra_svn/ra_svn.h?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_ra_svn/ra_svn.h (original)
+++ subversion/branches/ra-git/subversion/libsvn_ra_svn/ra_svn.h Wed Nov 7 12:30:06 2018
@@ -125,12 +125,30 @@ struct svn_ra_svn_conn_st {
apr_pool_t *pool;
};
+/* The session's URL state for client and server side.
+ *
+ * This keeps track of the respective client-side and server-side "parent"
+ * URLs. It tells us whether we may have to send reparent commands to the
+ * server and how to tweak path parameters when we decided to handle
+ * reparent requests on the client side only. */
+typedef struct svn_ra_svn__parent_t {
+ /* Client-side session base URL, i.e. client's parent path. */
+ svn_stringbuf_t *client_url;
+
+ /* Server-side base URL, i.e. server's parent path. */
+ svn_stringbuf_t *server_url;
+
+ /* Relative path to add to a client-side parameter to translate it for the
+ * server-side. I.e. the relative path from SERVER_URL to CLIENT_URL. */
+ svn_stringbuf_t *path;
+} svn_ra_svn__parent_t;
+
struct svn_ra_svn__session_baton_t {
apr_pool_t *pool;
svn_ra_svn_conn_t *conn;
svn_boolean_t is_tunneled;
svn_auth_baton_t *auth_baton;
- const char *url;
+ svn_ra_svn__parent_t *parent;
const char *user;
const char *hostname; /* The remote hostname. */
const char *realm_prefix;