You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2012/07/11 12:26:26 UTC
svn commit: r1360103 [6/18] - in /subversion/branches/ev2-export: ./ build/
build/ac-macros/ build/generator/ build/generator/templates/ build/win32/
contrib/server-side/ notes/wc-ng/ subversion/bindings/javahl/native/
subversion/bindings/javahl/src/or...
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c Wed Jul 11 10:26:19 2012
@@ -143,7 +143,7 @@ typedef struct report_dir_t
apr_hash_t *removed_props;
/* The propfind request for our current directory */
- svn_ra_serf__propfind_context_t *propfind;
+ svn_ra_serf__handler_t *propfind_handler;
/* Has the server told us to fetch the dir props? */
svn_boolean_t fetch_props;
@@ -203,7 +203,7 @@ typedef struct report_info_t
svn_revnum_t copyfrom_rev;
/* The propfind request for our current file (if present) */
- svn_ra_serf__propfind_context_t *propfind;
+ svn_ra_serf__handler_t *propfind_handler;
/* Has the server told us to fetch the file props? */
svn_boolean_t fetch_props;
@@ -346,7 +346,7 @@ struct report_context_t {
/* number of pending PROPFIND requests */
unsigned int active_propfinds;
- /* completed PROPFIND requests (contains svn_ra_serf__propfind_context_t) */
+ /* completed PROPFIND requests (contains svn_ra_serf__handler_t) */
svn_ra_serf__list_t *done_propfinds;
/* list of files that only have prop changes (contains report_info_t) */
@@ -464,10 +464,6 @@ set_file_props(void *baton,
const svn_delta_editor_t *editor = info->dir->report_context->update_editor;
const char *prop_name;
- if (strcmp(name, "md5-checksum") == 0
- && strcmp(ns, SVN_DAV_PROP_NS_DAV) == 0)
- info->final_checksum = apr_pstrdup(info->pool, val->data);
-
prop_name = svn_ra_serf__svnname_from_wirename(ns, name, scratch_pool);
if (prop_name != NULL)
return svn_error_trace(editor->change_file_prop(info->file_baton,
@@ -730,7 +726,7 @@ headers_fetch(serf_bucket_t *headers,
serf_bucket_headers_setn(headers, "Accept-Encoding",
"svndiff1;q=0.9,svndiff;q=0.8");
}
- else if (fetch_ctx->conn->using_compression)
+ else if (fetch_ctx->sess->using_compression)
{
serf_bucket_headers_setn(headers, "Accept-Encoding", "gzip");
}
@@ -1079,19 +1075,15 @@ handle_stream(serf_request_t *request,
apr_pool_t *pool)
{
report_fetch_t *fetch_ctx = handler_baton;
- const char *location;
svn_error_t *err;
apr_status_t status;
/* ### new field. make sure we didn't miss some initialization. */
SVN_ERR_ASSERT(fetch_ctx->handler != NULL);
- /* Woo-hoo. Nothing here to see. */
- location = svn_ra_serf__response_get_location(response, pool);
-
err = svn_ra_serf__error_on_status(fetch_ctx->handler->sline.code,
fetch_ctx->info->name,
- location);
+ fetch_ctx->handler->location);
if (err)
{
fetch_ctx->handler->done = TRUE;
@@ -1230,15 +1222,18 @@ fetch_file(report_context_t *ctx, report
}
/* If needed, create the PROPFIND to retrieve the file's properties. */
- info->propfind = NULL;
+ info->propfind_handler = NULL;
if (info->fetch_props)
{
- SVN_ERR(svn_ra_serf__deliver_props(&info->propfind, info->props,
+ SVN_ERR(svn_ra_serf__deliver_props(&info->propfind_handler, info->props,
ctx->sess, conn, info->url,
ctx->target_rev, "0", all_props,
&ctx->done_propfinds,
info->dir->pool));
- SVN_ERR_ASSERT(info->propfind);
+ SVN_ERR_ASSERT(info->propfind_handler);
+
+ /* Create a serf request for the PROPFIND. */
+ svn_ra_serf__request_create(info->propfind_handler);
ctx->active_propfinds++;
}
@@ -1251,18 +1246,32 @@ fetch_file(report_context_t *ctx, report
svn_stream_t *contents = NULL;
if (ctx->sess->wc_callbacks->get_wc_contents
- && info->final_sha1_checksum)
+ && (info->final_sha1_checksum || info->final_checksum))
{
svn_error_t *err;
- svn_checksum_t *sha1_checksum;
+ svn_checksum_t *checksum;
+
+ /* Parse our checksum, preferring SHA1 to MD5. */
+ if (info->final_sha1_checksum)
+ {
+ err = svn_checksum_parse_hex(&checksum, svn_checksum_sha1,
+ info->final_sha1_checksum,
+ info->pool);
+ }
+ else if (info->final_checksum)
+ {
+ err = svn_checksum_parse_hex(&checksum, svn_checksum_md5,
+ info->final_checksum,
+ info->pool);
+ }
- err = svn_checksum_parse_hex(&sha1_checksum, svn_checksum_sha1,
- info->final_sha1_checksum, info->pool);
+ /* Okay so far? Let's try to get a stream on some readily
+ available matching content. */
if (!err)
{
err = ctx->sess->wc_callbacks->get_wc_contents(
ctx->sess->wc_callback_baton, &contents,
- sha1_checksum, info->pool);
+ checksum, info->pool);
}
if (err)
@@ -1282,7 +1291,7 @@ fetch_file(report_context_t *ctx, report
if (info->cached_contents)
{
/* If we'll be doing a PROPFIND for this file... */
- if (info->propfind)
+ if (info->propfind_handler)
{
/* ... then we'll just leave ourselves a little "todo"
about that fact (and we'll deal with the file content
@@ -1339,7 +1348,7 @@ fetch_file(report_context_t *ctx, report
ctx->active_fetches++;
}
}
- else if (info->propfind)
+ else if (info->propfind_handler)
{
svn_ra_serf__list_t *list_item;
@@ -1806,6 +1815,14 @@ start_report(svn_ra_serf__xml_parser_t *
info->prop_encoding = svn_xml_get_attr_value("encoding", attrs);
svn_stringbuf_setempty(info->prop_value);
}
+ else if (strcmp(name.name, "txdelta") == 0)
+ {
+ /* Pre 1.2, mod_dav_svn was using <txdelta> tags (in
+ addition to <fetch-file>s and such) when *not* in
+ "send-all" mode. As a client, we're smart enough to know
+ that's wrong, so we'll just ignore these tags. */
+ ;
+ }
else
{
return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
@@ -1884,7 +1901,7 @@ end_report(svn_ra_serf__xml_parser_t *pa
/* Unconditionally set fetch_props now. */
info->dir->fetch_props = TRUE;
- SVN_ERR(svn_ra_serf__deliver_props(&info->dir->propfind,
+ SVN_ERR(svn_ra_serf__deliver_props(&info->dir->propfind_handler,
info->dir->props, ctx->sess,
ctx->sess->conns[ctx->sess->cur_conn],
info->dir->url,
@@ -1892,7 +1909,10 @@ end_report(svn_ra_serf__xml_parser_t *pa
all_props,
&ctx->done_propfinds,
info->dir->pool));
- SVN_ERR_ASSERT(info->dir->propfind);
+ SVN_ERR_ASSERT(info->dir->propfind_handler);
+
+ /* Create a serf request for the PROPFIND. */
+ svn_ra_serf__request_create(info->dir->propfind_handler);
ctx->active_propfinds++;
@@ -1902,7 +1922,7 @@ end_report(svn_ra_serf__xml_parser_t *pa
}
else
{
- info->dir->propfind = NULL;
+ info->dir->propfind_handler = NULL;
}
svn_ra_serf__xml_pop_state(parser);
@@ -2078,6 +2098,13 @@ end_report(svn_ra_serf__xml_parser_t *pa
svn_ra_serf__set_ver_prop(props, info->base_name, info->base_rev,
ns->namespace, ns->url, set_val_str, pool);
+
+ /* Advance handling: if we spotted the md5-checksum property on
+ the wire, remember it's value. */
+ if (strcmp(ns->url, "md5-checksum") == 0
+ && strcmp(ns->namespace, SVN_DAV_PROP_NS_DAV) == 0)
+ info->final_checksum = apr_pstrdup(info->pool, set_val_str->data);
+
svn_ra_serf__xml_pop_state(parser);
}
else if (state == IGNORE_PROP_NAME || state == NEED_PROP_NAME)
@@ -2239,8 +2266,6 @@ link_path(void *report_baton,
return APR_SUCCESS;
}
-/** Max. number of connctions we'll open to the server. */
-#define MAX_NR_OF_CONNS 4
/** Minimum nr. of outstanding requests needed before a new connection is
* opened. */
#define REQS_PER_CONN 8
@@ -2261,16 +2286,10 @@ open_connection_if_needed(svn_ra_serf__s
apr_status_t status;
sess->conns[cur] = apr_pcalloc(sess->pool, sizeof(*sess->conns[cur]));
- sess->conns[cur]->http10 = TRUE; /* until we confirm HTTP/1.1 */
- sess->conns[cur]->http10 = FALSE; /* ### don't change behavior yet */
sess->conns[cur]->bkt_alloc = serf_bucket_allocator_create(sess->pool,
NULL, NULL);
- sess->conns[cur]->hostname = sess->conns[0]->hostname;
- sess->conns[cur]->using_ssl = sess->conns[0]->using_ssl;
- sess->conns[cur]->using_compression = sess->conns[0]->using_compression;
sess->conns[cur]->last_status_code = -1;
sess->conns[cur]->session = sess;
- sess->conns[cur]->useragent = sess->conns[0]->useragent;
status = serf_connection_create2(&sess->conns[cur]->conn,
sess->context,
sess->session_url,
@@ -2313,7 +2332,7 @@ headers_report(serf_bucket_t *headers,
{
report_context_t *report = baton;
- if (report->conn->using_compression)
+ if (report->sess->using_compression)
{
serf_bucket_headers_setn(headers, "Accept-Encoding", "gzip");
}
@@ -2421,6 +2440,11 @@ finish_report(void *report_baton,
err = sess->pending_error;
sess->pending_error = SVN_NO_ERROR;
+ if (!err && handler->done && handler->server_error)
+ {
+ err = handler->server_error->error;
+ }
+
if (APR_STATUS_IS_TIMEUP(status))
{
svn_error_clear(err);
@@ -2468,7 +2492,7 @@ finish_report(void *report_baton,
{
report_info_t *item = cur->data;
- if (item->propfind == done_list->data)
+ if (item->propfind_handler == done_list->data)
{
break;
}
@@ -2536,9 +2560,9 @@ finish_report(void *report_baton,
* we've already completed the propfind
* then, we know it's time for us to close this directory.
*/
- while (cur_dir && !cur_dir->ref_count && cur_dir->tag_closed &&
- (!cur_dir->fetch_props ||
- svn_ra_serf__propfind_is_done(cur_dir->propfind)))
+ while (cur_dir && !cur_dir->ref_count && cur_dir->tag_closed
+ && (!cur_dir->fetch_props
+ || cur_dir->propfind_handler->done))
{
report_dir_t *parent = cur_dir->parent_dir;
@@ -2821,6 +2845,74 @@ svn_ra_serf__do_switch(svn_ra_session_t
switch_editor, switch_baton, pool);
}
+/* Helper svn_ra_serf__get_file(). Attempts to fetch file contents
+ * using SESSION->wc_callbacks->get_wc_contents() if sha1 property is
+ * present in PROPS.
+ *
+ * Sets *FOUND_P to TRUE if file contents was successfuly fetched.
+ *
+ * Performs all temporary allocations in POOL.
+ */
+static svn_error_t *
+try_get_wc_contents(svn_boolean_t *found_p,
+ svn_ra_serf__session_t *session,
+ apr_hash_t *props,
+ svn_stream_t *dst_stream,
+ apr_pool_t *pool)
+{
+ apr_hash_t *svn_props;
+ const char *sha1_checksum_prop;
+ svn_checksum_t *checksum;
+ svn_stream_t *wc_stream;
+ svn_error_t *err;
+
+ /* No contents found by default. */
+ *found_p = FALSE;
+
+ if (!session->wc_callbacks->get_wc_contents)
+ {
+ /* No callback, nothing to do. */
+ return SVN_NO_ERROR;
+ }
+
+
+ svn_props = apr_hash_get(props, SVN_DAV_PROP_NS_DAV, APR_HASH_KEY_STRING);
+ if (!svn_props)
+ {
+ /* No properties -- therefore no checksum property -- in response. */
+ return SVN_NO_ERROR;
+ }
+
+ sha1_checksum_prop = svn_prop_get_value(svn_props, "sha1-checksum");
+ if (sha1_checksum_prop == NULL)
+ {
+ /* No checksum property in response. */
+ return SVN_NO_ERROR;
+ }
+
+ SVN_ERR(svn_checksum_parse_hex(&checksum, svn_checksum_sha1,
+ sha1_checksum_prop, pool));
+
+ err = session->wc_callbacks->get_wc_contents(
+ session->wc_callback_baton, &wc_stream, checksum, pool);
+
+ if (err)
+ {
+ svn_error_clear(err);
+
+ /* Ignore errors for now. */
+ return SVN_NO_ERROR;
+ }
+
+ if (wc_stream)
+ {
+ SVN_ERR(svn_stream_copy3(wc_stream, dst_stream, NULL, NULL, pool));
+ *found_p = TRUE;
+ }
+
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_ra_serf__get_file(svn_ra_session_t *ra_session,
const char *path,
@@ -2835,6 +2927,7 @@ svn_ra_serf__get_file(svn_ra_session_t *
const char *fetch_url;
apr_hash_t *fetch_props;
svn_kind_t res_kind;
+ const svn_ra_serf__dav_props_t *which_props;
/* What connection should we go on? */
conn = session->conns[session->cur_conn];
@@ -2859,9 +2952,22 @@ svn_ra_serf__get_file(svn_ra_session_t *
/* REVISION is always SVN_INVALID_REVNUM */
SVN_ERR_ASSERT(!SVN_IS_VALID_REVNUM(revision));
+ if (props)
+ {
+ which_props = all_props;
+ }
+ else if (stream && session->wc_callbacks->get_wc_contents)
+ {
+ which_props = type_and_checksum_props;
+ }
+ else
+ {
+ which_props = check_path_props;
+ }
+
SVN_ERR(svn_ra_serf__fetch_node_props(&fetch_props, conn, fetch_url,
SVN_INVALID_REVNUM,
- props ? all_props : check_path_props,
+ which_props,
pool, pool));
/* Verify that resource type is not collection. */
@@ -2883,39 +2989,46 @@ svn_ra_serf__get_file(svn_ra_session_t *
if (stream)
{
- report_fetch_t *stream_ctx;
- svn_ra_serf__handler_t *handler;
+ svn_boolean_t found;
+ SVN_ERR(try_get_wc_contents(&found, session, fetch_props, stream, pool));
+
+ /* No contents found in the WC, let's fetch from server. */
+ if (!found)
+ {
+ report_fetch_t *stream_ctx;
+ svn_ra_serf__handler_t *handler;
- /* Create the fetch context. */
- stream_ctx = apr_pcalloc(pool, sizeof(*stream_ctx));
- stream_ctx->target_stream = stream;
- stream_ctx->sess = session;
- stream_ctx->conn = conn;
- stream_ctx->info = apr_pcalloc(pool, sizeof(*stream_ctx->info));
- stream_ctx->info->name = fetch_url;
+ /* Create the fetch context. */
+ stream_ctx = apr_pcalloc(pool, sizeof(*stream_ctx));
+ stream_ctx->target_stream = stream;
+ stream_ctx->sess = session;
+ stream_ctx->conn = conn;
+ stream_ctx->info = apr_pcalloc(pool, sizeof(*stream_ctx->info));
+ stream_ctx->info->name = fetch_url;
- handler = apr_pcalloc(pool, sizeof(*handler));
+ handler = apr_pcalloc(pool, sizeof(*handler));
- handler->handler_pool = pool;
- handler->method = "GET";
- handler->path = fetch_url;
- handler->conn = conn;
- handler->session = session;
+ handler->handler_pool = pool;
+ handler->method = "GET";
+ handler->path = fetch_url;
+ handler->conn = conn;
+ handler->session = session;
- handler->header_delegate = headers_fetch;
- handler->header_delegate_baton = stream_ctx;
+ handler->header_delegate = headers_fetch;
+ handler->header_delegate_baton = stream_ctx;
- handler->response_handler = handle_stream;
- handler->response_baton = stream_ctx;
+ handler->response_handler = handle_stream;
+ handler->response_baton = stream_ctx;
- handler->response_error = cancel_fetch;
- handler->response_error_baton = stream_ctx;
+ handler->response_error = cancel_fetch;
+ handler->response_error_baton = stream_ctx;
- stream_ctx->handler = handler;
+ stream_ctx->handler = handler;
- svn_ra_serf__request_create(handler);
+ svn_ra_serf__request_create(handler);
- SVN_ERR(svn_ra_serf__context_run_wait(&stream_ctx->done, session, pool));
+ SVN_ERR(svn_ra_serf__context_run_wait(&stream_ctx->done, session, pool));
+ }
}
return SVN_NO_ERROR;
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c Wed Jul 11 10:26:19 2012
@@ -257,7 +257,7 @@ ssl_server_cert(void *baton, int failure
int i;
for (i = 0; i < san->nelts; i++) {
char *s = APR_ARRAY_IDX(san, i, char*);
- if (apr_fnmatch(s, conn->hostname,
+ if (apr_fnmatch(s, conn->session->session_url.hostname,
APR_FNM_PERIOD) == APR_SUCCESS) {
found_matching_hostname = 1;
cert_info.hostname = s;
@@ -269,7 +269,7 @@ ssl_server_cert(void *baton, int failure
/* Match server certificate CN with the hostname of the server */
if (!found_matching_hostname && cert_info.hostname)
{
- if (apr_fnmatch(cert_info.hostname, conn->hostname,
+ if (apr_fnmatch(cert_info.hostname, conn->session->session_url.hostname,
APR_FNM_PERIOD) == APR_FNM_NOMATCH)
{
svn_failures |= SVN_AUTH_SSL_CNMISMATCH;
@@ -364,7 +364,7 @@ conn_setup(apr_socket_t *sock,
*read_bkt = serf_context_bucket_socket_create(conn->session->context,
sock, conn->bkt_alloc);
- if (conn->using_ssl)
+ if (conn->session->using_ssl)
{
/* input stream */
*read_bkt = serf_bucket_ssl_decrypt_create(*read_bkt, conn->ssl_context,
@@ -374,7 +374,8 @@ conn_setup(apr_socket_t *sock,
conn->ssl_context = serf_bucket_ssl_encrypt_context_get(*read_bkt);
#if SERF_VERSION_AT_LEAST(1,0,0)
- serf_ssl_set_hostname(conn->ssl_context, conn->hostname);
+ serf_ssl_set_hostname(conn->ssl_context,
+ conn->session->session_url.hostname);
#endif
serf_ssl_client_cert_provider_set(conn->ssl_context,
@@ -479,7 +480,7 @@ connection_closed(svn_ra_serf__connectio
SVN_ERR_MALFUNCTION();
}
- if (conn->using_ssl)
+ if (conn->session->using_ssl)
conn->ssl_context = NULL;
return SVN_NO_ERROR;
@@ -632,7 +633,7 @@ static svn_error_t *
setup_serf_req(serf_request_t *request,
serf_bucket_t **req_bkt,
serf_bucket_t **hdrs_bkt,
- svn_ra_serf__connection_t *conn,
+ svn_ra_serf__session_t *session,
const char *method, const char *url,
serf_bucket_t *body_bkt, const char *content_type,
apr_pool_t *request_pool,
@@ -643,7 +644,7 @@ setup_serf_req(serf_request_t *request,
#if SERF_VERSION_AT_LEAST(1, 1, 0)
svn_spillbuf_t *buf;
- if (conn->http10 && body_bkt != NULL)
+ if (session->http10 && body_bkt != NULL)
{
/* Ugh. Use HTTP/1.0 to talk to the server because we don't know if
it speaks HTTP/1.1 (and thus, chunked requests), or because the
@@ -669,7 +670,7 @@ setup_serf_req(serf_request_t *request,
/* Set the Content-Length value. This will also trigger an HTTP/1.0
request (rather than the default chunked request). */
#if SERF_VERSION_AT_LEAST(1, 1, 0)
- if (conn->http10)
+ if (session->http10)
{
if (body_bkt == NULL)
serf_bucket_request_set_CL(*req_bkt, 0);
@@ -680,10 +681,10 @@ setup_serf_req(serf_request_t *request,
*hdrs_bkt = serf_bucket_request_get_headers(*req_bkt);
- /* We use serf_bucket_headers_setn() because the string below have a
+ /* We use serf_bucket_headers_setn() because the USERAGENT has a
lifetime longer than this bucket. Thus, there is no need to copy
the header values. */
- serf_bucket_headers_setn(*hdrs_bkt, "User-Agent", conn->useragent);
+ serf_bucket_headers_setn(*hdrs_bkt, "User-Agent", session->useragent);
if (content_type)
{
@@ -941,16 +942,29 @@ svn_ra_serf__response_discard_handler(se
return drain_bucket(response);
}
-const char *
-svn_ra_serf__response_get_location(serf_bucket_t *response,
- apr_pool_t *pool)
+
+/* Return the value of the RESPONSE's Location header if any, or NULL
+ otherwise. All allocations will be made in POOL. */
+static const char *
+response_get_location(serf_bucket_t *response,
+ apr_pool_t *pool)
{
serf_bucket_t *headers;
- const char *val;
+ const char *location;
+ apr_status_t status;
+ apr_uri_t uri;
headers = serf_bucket_response_get_headers(response);
- val = serf_bucket_headers_get(headers, "Location");
- return val ? svn_urlpath__canonicalize(val, pool) : NULL;
+ location = serf_bucket_headers_get(headers, "Location");
+ if (location == NULL)
+ return NULL;
+
+ /* Ignore the scheme/host/port. Or just return as-is if we can't parse. */
+ status = apr_uri_parse(pool, location, &uri);
+ if (!status)
+ location = uri.path;
+
+ return svn_urlpath__canonicalize(location, pool);
}
@@ -990,11 +1004,6 @@ svn_ra_serf__expect_empty_body(serf_requ
}
else
{
- /* ### hmm. this is a bit early. we have not seen EOF. if the
- ### caller thinks we are "done", then it may never call into
- ### serf_context_run() again to flush the response. */
- handler->done = TRUE;
-
/* The body was not text/xml, so we don't know what to do with it.
Toss anything that arrives. */
handler->discard_body = TRUE;
@@ -1175,11 +1184,6 @@ svn_ra_serf__handle_multistatus_only(ser
}
else
{
- /* ### hmm. this is a bit early. we have not seen EOF. if the
- ### caller thinks we are "done", then it may never call into
- ### serf_context_run() again to flush the response. */
- handler->done = TRUE;
-
/* The body was not text/xml, so we don't know what to do with it.
Toss anything that arrives. */
handler->discard_body = TRUE;
@@ -1419,6 +1423,7 @@ handle_server_error(serf_request_t *requ
svn_ra_serf__server_error_t server_err = { 0 };
serf_bucket_t *hdrs;
const char *val;
+ apr_status_t err;
hdrs = serf_bucket_response_get_headers(response);
val = serf_bucket_headers_get(hdrs, "Content-Type");
@@ -1458,8 +1463,11 @@ handle_server_error(serf_request_t *requ
}
/* The only error that we will return is from the XML response body.
- Otherwise, ignore the entire body and return success. */
- (void) drain_bucket(response);
+ Otherwise, ignore the entire body but allow SUCCESS/EOF/EAGAIN to
+ surface. */
+ err = drain_bucket(response);
+ if (err && !SERF_BUCKET_READ_ERROR(err))
+ return svn_error_wrap_apr(err, NULL);
return SVN_NO_ERROR;
}
@@ -1487,17 +1495,11 @@ svn_ra_serf__handle_xml_parser(serf_requ
/* Woo-hoo. Nothing here to see. */
if (sl.code == 404 && ctx->ignore_errors == FALSE)
{
- add_done_item(ctx);
-
err = handle_server_error(request, response, pool);
- /* ### the above call should have drained the entire response. this
- ### call is historical, and probably not required. but during
- ### the rework of this core handling... let's keep it for now. */
- status = drain_bucket(response);
- if (status)
- err = svn_error_compose_create(svn_error_wrap_apr(status, NULL),
- err);
+ if (err && APR_STATUS_IS_EOF(err->apr_err))
+ add_done_item(ctx);
+
return svn_error_trace(err);
}
@@ -1773,6 +1775,10 @@ handle_response(serf_request_t *request,
handler->sline = sl;
handler->sline.reason = apr_pstrdup(handler->handler_pool, sl.reason);
+
+ /* HTTP/1.1? (or later) */
+ if (sl.version != SERF_HTTP_10)
+ handler->session->http10 = FALSE;
}
/* Keep reading from the network until we've read all the headers. */
@@ -1824,8 +1830,7 @@ handle_response(serf_request_t *request,
}
/* ... and set up the header fields in HANDLER. */
- handler->location = svn_ra_serf__response_get_location(
- response, handler->handler_pool);
+ handler->location = response_get_location(response, handler->handler_pool);
/* On the last request, we failed authentication. We succeeded this time,
so let's save away these credentials. */
@@ -1845,28 +1850,43 @@ handle_response(serf_request_t *request,
/* 405 Method Not allowed.
409 Conflict: can indicate a hook error.
5xx (Internal) Server error. */
- /* ### this is completely wrong. it only catches the current network
- ### packet. we need ongoing parsing. see SERVER_ERROR down below
- ### in the process_body: area. we'll eventually move to that. */
- SVN_ERR(handle_server_error(request, response, scratch_pool));
-
- if (!handler->session->pending_error)
- {
- apr_status_t apr_err = SVN_ERR_RA_DAV_REQUEST_FAILED;
-
- /* 405 == Method Not Allowed (Occurs when trying to lock a working
- copy path which no longer exists at HEAD in the repository. */
- if (handler->sline.code == 405
- && strcmp(handler->method, "LOCK") == 0)
- apr_err = SVN_ERR_FS_OUT_OF_DATE;
+ serf_bucket_t *hdrs;
+ const char *val;
- return svn_error_createf(apr_err, NULL,
- _("%s request on '%s' failed: %d %s"),
+ hdrs = serf_bucket_response_get_headers(response);
+ val = serf_bucket_headers_get(hdrs, "Content-Type");
+ if (val && strncasecmp(val, "text/xml", sizeof("text/xml") - 1) == 0)
+ {
+ svn_ra_serf__server_error_t *server_err;
+
+ server_err = begin_error_parsing(start_error, end_error, cdata_error,
+ handler->handler_pool);
+ /* Get the parser to set our DONE flag. */
+ server_err->parser.done = &handler->done;
+
+ handler->server_error = server_err;
+ }
+ else
+ {
+ handler->discard_body = TRUE;
+
+ if (!handler->session->pending_error)
+ {
+ apr_status_t apr_err = SVN_ERR_RA_DAV_REQUEST_FAILED;
+
+ /* 405 == Method Not Allowed (Occurs when trying to lock a working
+ copy path which no longer exists at HEAD in the repository. */
+ if (handler->sline.code == 405
+ && strcmp(handler->method, "LOCK") == 0)
+ apr_err = SVN_ERR_FS_OUT_OF_DATE;
+
+ handler->session->pending_error =
+ svn_error_createf(apr_err, NULL,
+ _("%s request on '%s' failed: %d %s"),
handler->method, handler->path,
handler->sline.code, handler->sline.reason);
+ }
}
-
- return SVN_NO_ERROR; /* Error is set in caller */
}
/* Stop processing the above, on every packet arrival. */
@@ -1878,6 +1898,14 @@ handle_response(serf_request_t *request,
if (handler->discard_body)
{
*serf_status = drain_bucket(response);
+
+ /* If the handler hasn't set done (which it shouldn't have) and
+ we now have the EOF, go ahead and set it so that we can stop
+ our context loops.
+ */
+ if (!handler->done && APR_STATUS_IS_EOF(*serf_status))
+ handler->done = TRUE;
+
return SVN_NO_ERROR;
}
@@ -1889,17 +1917,25 @@ handle_response(serf_request_t *request,
&handler->server_error->parser,
scratch_pool);
- /* APR_EOF will be returned when parsing is complete. If we see
- any other error, return it immediately.
+ /* If we do not receive an error or it is a non-transient error, return
+ immediately.
- In practice the only other error we expect to see is APR_EAGAIN,
- which indicates the network has no more data right now. This
- svn_error_t will get unwrapped, and that APR_EAGAIN will be
- returned to serf. We'll get called later, when more network data
- is available. */
- if (!err || !APR_STATUS_IS_EOF(err->apr_err))
+ APR_EOF will be returned when parsing is complete.
+
+ APR_EAGAIN & WAIT_CONN may be intermittently returned as we proceed through
+ parsing and the network has no more data right now. If we receive that,
+ clear the error and return - allowing serf to wait for more data.
+ */
+ if (!err || SERF_BUCKET_READ_ERROR(err->apr_err))
return svn_error_trace(err);
+ if (!APR_STATUS_IS_EOF(err->apr_err))
+ {
+ *serf_status = err->apr_err;
+ svn_error_clear(err);
+ return SVN_NO_ERROR;
+ }
+
/* Clear the EOF. We don't need it. */
svn_error_clear(err);
@@ -1999,7 +2035,7 @@ setup_request(serf_request_t *request,
}
SVN_ERR(setup_serf_req(request, req_bkt, &headers_bkt,
- handler->conn, handler->method, handler->path,
+ handler->session, handler->method, handler->path,
body_bkt, handler->body_type,
request_pool, scratch_pool));
@@ -2351,7 +2387,15 @@ expat_response_handler(serf_request_t *r
{
struct expat_ctx_t *ectx = baton;
- SVN_ERR_ASSERT(ectx->parser != NULL);
+ if (!ectx->parser)
+ {
+ ectx->parser = XML_ParserCreate(NULL);
+ apr_pool_cleanup_register(ectx->cleanup_pool, &ectx->parser,
+ xml_parser_cleanup, apr_pool_cleanup_null);
+ XML_SetUserData(ectx->parser, ectx);
+ XML_SetElementHandler(ectx->parser, expat_start, expat_end);
+ XML_SetCharacterDataHandler(ectx->parser, expat_cdata);
+ }
/* ### should we bail on anything < 200 or >= 300 ??
### actually: < 200 should really be handled by the core. */
@@ -2387,6 +2431,20 @@ expat_response_handler(serf_request_t *r
/* ### should we have an IGNORE_ERRORS flag like the v1 parser? */
expat_status = XML_Parse(ectx->parser, data, (int)len, 0 /* isFinal */);
+
+ /* We need to check INNER_ERROR first. This is an error from the
+ callbacks that has been "dropped off" for us to retrieve. On
+ current Expat parsers, we stop the parser when an error occurs,
+ so we want to ignore EXPAT_STATUS (which reports the stoppage).
+
+ If an error is not present, THEN we go ahead and look for parsing
+ errors. */
+ if (ectx->inner_error)
+ {
+ apr_pool_cleanup_run(ectx->cleanup_pool, &ectx->parser,
+ xml_parser_cleanup);
+ return svn_error_trace(ectx->inner_error);
+ }
if (expat_status == XML_STATUS_ERROR)
return svn_error_createf(SVN_ERR_XML_MALFORMED,
ectx->inner_error,
@@ -2396,31 +2454,24 @@ expat_response_handler(serf_request_t *r
ectx->handler->sline.code,
ectx->handler->sline.reason);
- /* Was an error dropped off for us? */
- if (ectx->inner_error)
- {
- apr_pool_cleanup_run(ectx->cleanup_pool, &ectx->parser,
- xml_parser_cleanup);
- return svn_error_trace(ectx->inner_error);
- }
-
/* The parsing went fine. What has the bucket told us? */
- if (APR_STATUS_IS_EAGAIN(status))
- return svn_error_wrap_apr(status, NULL);
-
if (APR_STATUS_IS_EOF(status))
{
/* Tell expat we've reached the end of the content. Ignore the
return status. We just don't care. */
(void) XML_Parse(ectx->parser, NULL, 0, 1 /* isFinal */);
+ svn_ra_serf__xml_context_destroy(ectx->xmlctx);
apr_pool_cleanup_run(ectx->cleanup_pool, &ectx->parser,
xml_parser_cleanup);
/* ### should check XMLCTX to see if it has returned to the
### INITIAL state. we may have ended early... */
+ }
+ if (status && !SERF_BUCKET_READ_ERROR(status))
+ {
return svn_error_wrap_apr(status, NULL);
}
}
@@ -2438,12 +2489,8 @@ svn_ra_serf__create_expat_handler(svn_ra
ectx = apr_pcalloc(result_pool, sizeof(*ectx));
ectx->xmlctx = xmlctx;
- ectx->parser = XML_ParserCreate(NULL);
- apr_pool_cleanup_register(result_pool, &ectx->parser,
- xml_parser_cleanup, apr_pool_cleanup_null);
- XML_SetUserData(ectx->parser, ectx);
- XML_SetElementHandler(ectx->parser, expat_start, expat_end);
- XML_SetCharacterDataHandler(ectx->parser, expat_cdata);
+ ectx->parser = NULL;
+ ectx->cleanup_pool = result_pool;
handler = apr_pcalloc(result_pool, sizeof(*handler));
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/xml.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/xml.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/xml.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/xml.c Wed Jul 11 10:26:19 2012
@@ -443,6 +443,12 @@ lazy_create_pool(void *baton)
return xes->state_pool;
}
+void
+svn_ra_serf__xml_context_destroy(
+ svn_ra_serf__xml_context_t *xmlctx)
+{
+ svn_pool_destroy(xmlctx->scratch_pool);
+}
svn_ra_serf__xml_context_t *
svn_ra_serf__xml_context_create(
@@ -483,12 +489,35 @@ svn_ra_serf__xml_gather_since(svn_ra_ser
int stop_state)
{
apr_hash_t *data;
+ apr_pool_t *pool;
ensure_pool(xes);
+ pool = xes->state_pool;
- data = apr_hash_make(xes->state_pool);
+ data = apr_hash_make(pool);
+
+ for (; xes != NULL; xes = xes->prev)
+ {
+ if (xes->attrs != NULL)
+ {
+ apr_hash_index_t *hi;
- /* ### gather data */
+ for (hi = apr_hash_first(pool, xes->attrs); hi;
+ hi = apr_hash_next(hi))
+ {
+ const void *key;
+ apr_ssize_t klen;
+ void *val;
+
+ /* Parent name/value lifetimes are at least as long as POOL. */
+ apr_hash_this(hi, &key, &klen, &val);
+ apr_hash_set(data, key, klen, val);
+ }
+ }
+
+ if (xes->state == stop_state)
+ break;
+ }
return data;
}
@@ -632,7 +661,8 @@ svn_ra_serf__xml_cb_start(svn_ra_serf__x
}
if (value)
- apr_hash_set(new_xes->attrs, name, APR_HASH_KEY_STRING, value);
+ apr_hash_set(new_xes->attrs, name, APR_HASH_KEY_STRING,
+ apr_pstrdup(new_pool, value));
}
}
}
@@ -751,11 +781,29 @@ svn_ra_serf__xml_cb_cdata(svn_ra_serf__x
const char *data,
apr_size_t len)
{
- /* If we're collecting cdata, but NOT waiting for a closing tag
- (ie. not within an unknown tag), then copy the cdata. */
- if (xmlctx->current->cdata != NULL
- && xmlctx->waiting.namespace == NULL)
- svn_stringbuf_appendbytes(xmlctx->current->cdata, data, len);
+ /* If we are waiting for a closing tag, then we are uninterested in
+ the cdata. Just return. */
+ if (xmlctx->waiting.namespace != NULL)
+ return SVN_NO_ERROR;
+
+ /* If the current state is collecting cdata, then copy the cdata. */
+ if (xmlctx->current->cdata != NULL)
+ {
+ svn_stringbuf_appendbytes(xmlctx->current->cdata, data, len);
+ }
+ /* ... else if a CDATA_CB has been supplied, then invoke it for
+ all states. */
+ else if (xmlctx->cdata_cb != NULL)
+ {
+ START_CALLBACK(xmlctx);
+ SVN_ERR(xmlctx->cdata_cb(xmlctx->current,
+ xmlctx->baton,
+ xmlctx->current->state,
+ data, len,
+ xmlctx->scratch_pool));
+ END_CALLBACK(xmlctx);
+ svn_pool_clear(xmlctx->scratch_pool);
+ }
return SVN_NO_ERROR;
}
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_svn/marshal.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_svn/marshal.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_svn/marshal.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_svn/marshal.c Wed Jul 11 10:26:19 2012
@@ -462,7 +462,7 @@ svn_error_t *svn_ra_svn_write_string(svn
{
if (str->len < 10)
{
- SVN_ERR(writebuf_writechar(conn, pool, (char)str->len + '0'));
+ SVN_ERR(writebuf_writechar(conn, pool, (char)(str->len + '0')));
SVN_ERR(writebuf_writechar(conn, pool, ':'));
}
else
@@ -480,7 +480,7 @@ svn_error_t *svn_ra_svn_write_cstring(sv
if (len < 10)
{
- SVN_ERR(writebuf_writechar(conn, pool, (char)len + '0'));
+ SVN_ERR(writebuf_writechar(conn, pool, (char)(len + '0')));
SVN_ERR(writebuf_writechar(conn, pool, ':'));
}
else
Modified: subversion/branches/ev2-export/subversion/libsvn_repos/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/deprecated.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/deprecated.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/deprecated.c Wed Jul 11 10:26:19 2012
@@ -775,6 +775,27 @@ fns_from_fns2(const svn_repos_parse_fns2
return fns;
}
+static svn_repos_parser_fns2_t *
+fns2_from_fns3(const svn_repos_parse_fns3_t *fns3,
+ apr_pool_t *pool)
+{
+ svn_repos_parser_fns2_t *fns2;
+
+ fns2 = apr_palloc(pool, sizeof(*fns2));
+ fns2->new_revision_record = fns3->new_revision_record;
+ fns2->uuid_record = fns3->uuid_record;
+ fns2->new_node_record = fns3->new_node_record;
+ fns2->set_revision_property = fns3->set_revision_property;
+ fns2->set_node_property = fns3->set_node_property;
+ fns2->remove_node_props = fns3->remove_node_props;
+ fns2->set_fulltext = fns3->set_fulltext;
+ fns2->close_node = fns3->close_node;
+ fns2->close_revision = fns3->close_revision;
+ fns2->delete_node_property = fns3->delete_node_property;
+ fns2->apply_textdelta = fns3->apply_textdelta;
+ return fns2;
+}
+
static svn_repos_parse_fns2_t *
fns2_from_fns(const svn_repos_parser_fns_t *fns,
apr_pool_t *pool)
@@ -796,6 +817,42 @@ fns2_from_fns(const svn_repos_parser_fns
return fns2;
}
+static svn_repos_parse_fns3_t *
+fns3_from_fns2(const svn_repos_parser_fns2_t *fns2,
+ apr_pool_t *pool)
+{
+ svn_repos_parse_fns3_t *fns3;
+
+ fns3 = apr_palloc(pool, sizeof(*fns3));
+ fns3->magic_header_record = NULL;
+ fns3->uuid_record = fns2->uuid_record;
+ fns3->new_revision_record = fns2->new_revision_record;
+ fns3->new_node_record = fns2->new_node_record;
+ fns3->set_revision_property = fns2->set_revision_property;
+ fns3->set_node_property = fns2->set_node_property;
+ fns3->remove_node_props = fns2->remove_node_props;
+ fns3->set_fulltext = fns2->set_fulltext;
+ fns3->close_node = fns2->close_node;
+ fns3->close_revision = fns2->close_revision;
+ fns3->delete_node_property = fns2->delete_node_property;
+ fns3->apply_textdelta = fns2->apply_textdelta;
+ return fns3;
+}
+
+svn_error_t *
+svn_repos_parse_dumpstream2(svn_stream_t *stream,
+ const svn_repos_parser_fns2_t *parse_fns,
+ void *parse_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *pool)
+{
+ svn_repos_parse_fns3_t *fns3 = fns3_from_fns2(parse_fns, pool);
+
+ return svn_repos_parse_dumpstream3(stream, fns3, parse_baton, FALSE,
+ cancel_func, cancel_baton, pool);
+}
+
svn_error_t *
svn_repos_parse_dumpstream(svn_stream_t *stream,
const svn_repos_parser_fns_t *parse_fns,
@@ -837,11 +894,17 @@ svn_repos_get_fs_build_parser3(const svn
void *notify_baton,
apr_pool_t *pool)
{
- return svn_repos_get_fs_build_parser4(callbacks, parse_baton, repos,
- SVN_INVALID_REVNUM, SVN_INVALID_REVNUM,
- use_history, validate_props,
- uuid_action, parent_dir,
- notify_func, notify_baton, pool);
+ const svn_repos_parse_fns3_t *fns3;
+
+ SVN_ERR(svn_repos_get_fs_build_parser4(&fns3, parse_baton, repos,
+ SVN_INVALID_REVNUM,
+ SVN_INVALID_REVNUM,
+ use_history, validate_props,
+ uuid_action, parent_dir,
+ notify_func, notify_baton, pool));
+
+ *callbacks = fns2_from_fns3(fns3, pool);
+ return SVN_NO_ERROR;
}
svn_error_t *
Modified: subversion/branches/ev2-export/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/dump.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/dump.c Wed Jul 11 10:26:19 2012
@@ -736,7 +736,7 @@ close_directory(void *dir_baton,
struct dir_baton *db = dir_baton;
struct edit_baton *eb = db->edit_baton;
apr_pool_t *subpool = svn_pool_create(pool);
- unsigned int i;
+ int i;
apr_array_header_t *sorted_entries;
/* Sort entries lexically instead of as paths. Even though the entries
Modified: subversion/branches/ev2-export/subversion/libsvn_repos/load-fs-vtable.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/load-fs-vtable.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/load-fs-vtable.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/load-fs-vtable.c Wed Jul 11 10:26:19 2012
@@ -589,6 +589,13 @@ maybe_add_with_history(struct node_baton
return SVN_NO_ERROR;
}
+static svn_error_t *
+magic_header_record(int version,
+ void *parse_baton,
+ apr_pool_t *pool)
+{
+ return SVN_NO_ERROR;
+}
static svn_error_t *
uuid_record(const char *uuid,
@@ -1016,7 +1023,7 @@ close_revision(void *baton)
svn_error_t *
-svn_repos_get_fs_build_parser4(const svn_repos_parse_fns2_t **callbacks,
+svn_repos_get_fs_build_parser4(const svn_repos_parse_fns3_t **callbacks,
void **parse_baton,
svn_repos_t *repos,
svn_revnum_t start_rev,
@@ -1029,7 +1036,7 @@ svn_repos_get_fs_build_parser4(const svn
void *notify_baton,
apr_pool_t *pool)
{
- svn_repos_parse_fns2_t *parser = apr_pcalloc(pool, sizeof(*parser));
+ svn_repos_parse_fns3_t *parser = apr_pcalloc(pool, sizeof(*parser));
struct parse_baton *pb = apr_pcalloc(pool, sizeof(*pb));
if (parent_dir)
@@ -1042,9 +1049,10 @@ svn_repos_get_fs_build_parser4(const svn
if (SVN_IS_VALID_REVNUM(start_rev))
SVN_ERR_ASSERT(start_rev <= end_rev);
+ parser->magic_header_record = magic_header_record;
+ parser->uuid_record = uuid_record;
parser->new_revision_record = new_revision_record;
parser->new_node_record = new_node_record;
- parser->uuid_record = uuid_record;
parser->set_revision_property = set_revision_property;
parser->set_node_property = set_node_property;
parser->remove_node_props = remove_node_props;
@@ -1093,7 +1101,7 @@ svn_repos_load_fs4(svn_repos_t *repos,
void *cancel_baton,
apr_pool_t *pool)
{
- const svn_repos_parse_fns2_t *parser;
+ const svn_repos_parse_fns3_t *parser;
void *parse_baton;
struct parse_baton *pb;
@@ -1116,6 +1124,6 @@ svn_repos_load_fs4(svn_repos_t *repos,
pb->use_pre_commit_hook = use_pre_commit_hook;
pb->use_post_commit_hook = use_post_commit_hook;
- return svn_repos_parse_dumpstream2(dumpstream, parser, parse_baton,
+ return svn_repos_parse_dumpstream3(dumpstream, parser, parse_baton, FALSE,
cancel_func, cancel_baton, pool);
}
Modified: subversion/branches/ev2-export/subversion/libsvn_repos/load.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/load.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/load.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/load.c Wed Jul 11 10:26:19 2012
@@ -181,7 +181,7 @@ read_key_or_val(char **pbuf,
static svn_error_t *
parse_property_block(svn_stream_t *stream,
svn_filesize_t content_length,
- const svn_repos_parse_fns2_t *parse_fns,
+ const svn_repos_parse_fns3_t *parse_fns,
void *record_baton,
void *parse_baton,
svn_boolean_t is_node,
@@ -299,7 +299,7 @@ static svn_error_t *
parse_text_block(svn_stream_t *stream,
svn_filesize_t content_length,
svn_boolean_t is_delta,
- const svn_repos_parse_fns2_t *parse_fns,
+ const svn_repos_parse_fns3_t *parse_fns,
void *record_baton,
char *buffer,
apr_size_t buflen,
@@ -373,7 +373,8 @@ parse_text_block(svn_stream_t *stream,
/* Parse VERSIONSTRING and verify that we support the dumpfile format
version number, setting *VERSION appropriately. */
static svn_error_t *
-parse_format_version(const char *versionstring, int *version)
+parse_format_version(int *version,
+ const char *versionstring)
{
static const int magic_len = sizeof(SVN_REPOS_DUMPFILE_MAGIC_HEADER) - 1;
const char *p = strchr(versionstring, ':');
@@ -406,9 +407,10 @@ parse_format_version(const char *version
/** The public routines **/
svn_error_t *
-svn_repos_parse_dumpstream2(svn_stream_t *stream,
- const svn_repos_parse_fns2_t *parse_fns,
+svn_repos_parse_dumpstream3(svn_stream_t *stream,
+ const svn_repos_parse_fns3_t *parse_fns,
void *parse_baton,
+ svn_boolean_t deltas_are_text,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *pool)
@@ -428,16 +430,11 @@ svn_repos_parse_dumpstream2(svn_stream_t
return stream_ran_dry();
/* The first two lines of the stream are the dumpfile-format version
- number, and a blank line. */
- SVN_ERR(parse_format_version(linebuf->data, &version));
-
- /* If we were called from svn_repos_parse_dumpstream(), the
- callbacks to handle delta contents will be NULL, so we have to
- reject dumpfiles with the current version. */
- if (version == SVN_REPOS_DUMPFILE_FORMAT_VERSION
- && (!parse_fns->delete_node_property || !parse_fns->apply_textdelta))
- return svn_error_createf(SVN_ERR_STREAM_MALFORMED_DATA, NULL,
- _("Unsupported dumpfile version: %d"), version);
+ number, and a blank line. To preserve backward compatibility,
+ don't assume the existence of newer parser-vtable functions. */
+ SVN_ERR(parse_format_version(&version, linebuf->data));
+ if (parse_fns->magic_header_record != NULL)
+ SVN_ERR(parse_fns->magic_header_record(version, parse_baton, pool));
/* A dumpfile "record" is defined to be a header-block of
rfc822-style headers, possibly followed by a content-block.
@@ -528,6 +525,7 @@ svn_repos_parse_dumpstream2(svn_stream_t
SVN_ERR(parse_fns->uuid_record(value, parse_baton, pool));
}
/* Or perhaps a dumpfile format? */
+ /* ### TODO: use parse_format_version */
else if ((value = apr_hash_get(headers,
SVN_REPOS_DUMPFILE_MAGIC_HEADER,
APR_HASH_KEY_STRING)))
@@ -591,7 +589,9 @@ svn_repos_parse_dumpstream2(svn_stream_t
const char *delta = apr_hash_get(headers,
SVN_REPOS_DUMPFILE_TEXT_DELTA,
APR_HASH_KEY_STRING);
- svn_boolean_t is_delta = (delta && strcmp(delta, "true") == 0);
+ svn_boolean_t is_delta = FALSE;
+ if (! deltas_are_text)
+ is_delta = (delta && strcmp(delta, "true") == 0);
SVN_ERR(parse_text_block(stream,
svn__atoui64(text_cl),
Modified: subversion/branches/ev2-export/subversion/libsvn_repos/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/replay.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/replay.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/replay.c Wed Jul 11 10:26:19 2012
@@ -27,9 +27,11 @@
#include "svn_types.h"
#include "svn_delta.h"
+#include "svn_hash.h"
#include "svn_fs.h"
#include "svn_checksum.h"
#include "svn_repos.h"
+#include "svn_sorts.h"
#include "svn_props.h"
#include "svn_pools.h"
#include "svn_path.h"
@@ -101,6 +103,7 @@
(though not necessarily in the same order in which they
occurred). */
+/* #define USE_EV2_IMPL */
/*** Helper functions. ***/
@@ -147,6 +150,7 @@ struct path_driver_cb_baton
apr_pool_t *pool;
};
+#ifndef USE_EV2_IMPL
/* Recursively traverse EDIT_PATH (as it exists under SOURCE_ROOT) emitting
the appropriate editor calls to add it and its children without any
history. This is meant to be used when either a subset of the tree
@@ -338,6 +342,7 @@ add_subdir(svn_fs_root_t *source_root,
return SVN_NO_ERROR;
}
+#endif
/* Given PATH deleted under ROOT, return in READABLE whether the path was
readable prior to the deletion. Consult COPIES (a stack of 'struct
@@ -454,6 +459,7 @@ fill_copyfrom(svn_fs_root_t **copyfrom_r
return SVN_NO_ERROR;
}
+#ifndef USE_EV2_IMPL
static svn_error_t *
path_driver_cb_func(void **dir_baton,
void *parent_baton,
@@ -778,6 +784,47 @@ path_driver_cb_func(void **dir_baton,
return SVN_NO_ERROR;
}
+#else
+
+static svn_error_t *
+fetch_kind_func(svn_kind_t *kind,
+ void *baton,
+ const char *path,
+ svn_revnum_t base_revision,
+ apr_pool_t *scratch_pool)
+{
+ svn_fs_root_t *root = baton;
+ svn_node_kind_t node_kind;
+
+ SVN_ERR(svn_fs_check_path(&node_kind, root, path, scratch_pool));
+
+ *kind = svn__kind_from_node_kind(node_kind, FALSE);
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+fetch_props_func(apr_hash_t **props,
+ void *baton,
+ const char *path,
+ svn_revnum_t base_revision,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_fs_root_t *root = baton;
+ svn_fs_root_t *prev_root;
+ svn_fs_t *fs = svn_fs_root_fs(root);
+
+ SVN_ERR(svn_fs_revision_root(&prev_root, fs,
+ svn_fs_revision_root_revision(root) - 1,
+ scratch_pool));
+
+ SVN_ERR(svn_fs_node_proplist(props, prev_root, path, result_pool));
+
+ return SVN_NO_ERROR;
+}
+
+#endif
+
@@ -792,7 +839,7 @@ svn_repos_replay2(svn_fs_root_t *root,
void *authz_read_baton,
apr_pool_t *pool)
{
-#if 1
+#ifndef USE_EV2_IMPL
apr_hash_t *fs_changes;
apr_hash_t *changed_paths;
apr_hash_index_t *hi;
@@ -941,11 +988,15 @@ svn_repos_replay2(svn_fs_root_t *root,
&send_abs_paths,
repos_root, "",
NULL, NULL,
- NULL, NULL,
- NULL, NULL,
+ fetch_kind_func, root,
+ fetch_props_func, root,
pool, pool));
- SVN_ERR(svn_repos__replay_ev2(root, base_path, low_water_mark, send_deltas,
+ /* Tell the shim that we're starting the process. */
+ SVN_ERR(exb->start_edit(exb->baton, svn_fs_revision_root_revision(root)));
+
+ /* ### We're ignoring SEND_DELTAS here. */
+ SVN_ERR(svn_repos__replay_ev2(root, base_path, low_water_mark,
editorv2, authz_read_func, authz_read_baton,
pool));
@@ -958,19 +1009,468 @@ svn_repos_replay2(svn_fs_root_t *root,
* Ev2 Implementation *
*****************************************************************/
+#ifdef USE_EV2_IMPL
+/* Recursively traverse EDIT_PATH (as it exists under SOURCE_ROOT) emitting
+ the appropriate editor calls to add it and its children without any
+ history. This is meant to be used when either a subset of the tree
+ has been ignored and we need to copy something from that subset to
+ the part of the tree we do care about, or if a subset of the tree is
+ unavailable because of authz and we need to use it as the source of
+ a copy. */
static svn_error_t *
-replay_node(const char *repos_relpath,
+add_subdir(svn_fs_root_t *source_root,
+ svn_fs_root_t *target_root,
+ svn_editor_t *editor,
+ const char *repos_relpath,
+ const char *source_fspath,
+ svn_repos_authz_func_t authz_read_func,
+ void *authz_read_baton,
+ apr_hash_t *changed_paths,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ apr_hash_index_t *hi;
+ apr_hash_t *dirents;
+ apr_hash_t *props = NULL;
+ apr_array_header_t *children = NULL;
+
+ SVN_ERR(svn_fs_node_proplist(&props, target_root, repos_relpath,
+ scratch_pool));
+
+ SVN_ERR(svn_editor_add_directory(editor, repos_relpath, children,
+ props, SVN_INVALID_REVNUM));
+
+ /* We have to get the dirents from the source path, not the target,
+ because we want nested copies from *readable* paths to be handled by
+ path_driver_cb_func, not add_subdir (in order to preserve history). */
+ SVN_ERR(svn_fs_dir_entries(&dirents, source_root, source_fspath,
+ scratch_pool));
+
+ for (hi = apr_hash_first(scratch_pool, dirents); hi; hi = apr_hash_next(hi))
+ {
+ svn_fs_path_change2_t *change;
+ svn_boolean_t readable = TRUE;
+ svn_fs_dirent_t *dent = svn__apr_hash_index_val(hi);
+ const char *copyfrom_path = NULL;
+ svn_revnum_t copyfrom_rev = SVN_INVALID_REVNUM;
+ const char *child_relpath;
+
+ svn_pool_clear(iterpool);
+
+ child_relpath = svn_relpath_join(repos_relpath, dent->name, iterpool);
+
+ /* If a file or subdirectory of the copied directory is listed as a
+ changed path (because it was modified after the copy but before the
+ commit), we remove it from the changed_paths hash so that future
+ calls to path_driver_cb_func will ignore it. */
+ change = apr_hash_get(changed_paths, child_relpath, APR_HASH_KEY_STRING);
+ if (change)
+ {
+ apr_hash_set(changed_paths, child_relpath, APR_HASH_KEY_STRING,
+ NULL);
+
+ /* If it's a delete, skip this entry. */
+ if (change->change_kind == svn_fs_path_change_delete)
+ continue;
+
+ /* If it's a replacement, check for copyfrom info (if we
+ don't have it already. */
+ if (change->change_kind == svn_fs_path_change_replace)
+ {
+ if (! change->copyfrom_known)
+ {
+ SVN_ERR(svn_fs_copied_from(&change->copyfrom_rev,
+ &change->copyfrom_path,
+ target_root, child_relpath,
+ result_pool));
+ change->copyfrom_known = TRUE;
+ }
+ copyfrom_path = change->copyfrom_path;
+ copyfrom_rev = change->copyfrom_rev;
+ }
+ }
+
+ if (authz_read_func)
+ SVN_ERR(authz_read_func(&readable, target_root, child_relpath,
+ authz_read_baton, iterpool));
+
+ if (! readable)
+ continue;
+
+ if (dent->kind == svn_node_dir)
+ {
+ svn_fs_root_t *new_source_root;
+ const char *new_source_fspath;
+
+ if (copyfrom_path)
+ {
+ svn_fs_t *fs = svn_fs_root_fs(source_root);
+ SVN_ERR(svn_fs_revision_root(&new_source_root, fs,
+ copyfrom_rev, result_pool));
+ new_source_fspath = copyfrom_path;
+ }
+ else
+ {
+ new_source_root = source_root;
+ new_source_fspath = svn_fspath__join(source_fspath, dent->name,
+ iterpool);
+ }
+
+ /* ### authz considerations?
+ *
+ * I think not; when path_driver_cb_func() calls add_subdir(), it
+ * passes SOURCE_ROOT and SOURCE_FSPATH that are unreadable.
+ */
+ if (change && change->change_kind == svn_fs_path_change_replace
+ && copyfrom_path == NULL)
+ {
+ SVN_ERR(svn_editor_add_directory(editor, child_relpath,
+ children, props,
+ SVN_INVALID_REVNUM));
+ }
+ else
+ {
+ SVN_ERR(add_subdir(new_source_root, target_root,
+ editor, child_relpath,
+ new_source_fspath,
+ authz_read_func, authz_read_baton,
+ changed_paths, result_pool, iterpool));
+ }
+ }
+ else if (dent->kind == svn_node_file)
+ {
+ svn_checksum_t *checksum;
+ svn_stream_t *contents;
+
+ SVN_ERR(svn_fs_node_proplist(&props, target_root,
+ child_relpath, iterpool));
+
+ SVN_ERR(svn_fs_file_contents(&contents, target_root,
+ child_relpath, iterpool));
+
+ SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1,
+ target_root,
+ child_relpath, TRUE, iterpool));
+
+ SVN_ERR(svn_editor_add_file(editor, child_relpath, checksum,
+ contents, props, SVN_INVALID_REVNUM));
+ }
+ else
+ SVN_ERR_MALFUNCTION();
+ }
+
+ svn_pool_destroy(iterpool);
+
+ return SVN_NO_ERROR;
+}
+#endif
+
+static svn_error_t *
+replay_node(svn_fs_root_t *root,
+ const char *repos_relpath,
svn_editor_t *editor,
+ svn_revnum_t low_water_mark,
+ const char *base_repos_relpath,
+ apr_array_header_t *copies,
+ apr_hash_t *changed_paths,
+ svn_repos_authz_func_t authz_read_func,
+ void *authz_read_baton,
+ apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
+#ifndef USE_EV2_IMPL
{
SVN__NOT_IMPLEMENTED();
}
+#else
+{
+ svn_fs_path_change2_t *change;
+ svn_boolean_t do_add = FALSE;
+ svn_boolean_t do_delete = FALSE;
+ svn_revnum_t copyfrom_rev;
+ const char *copyfrom_path;
+ svn_revnum_t replaces_rev;
+
+ /* First, flush the copies stack so it only contains ancestors of path. */
+ while (copies->nelts > 0
+ && (svn_relpath_skip_ancestor(APR_ARRAY_IDX(copies,
+ copies->nelts - 1,
+ struct copy_info *)->path,
+ repos_relpath) == NULL) )
+ apr_array_pop(copies);
+
+ change = apr_hash_get(changed_paths, repos_relpath, APR_HASH_KEY_STRING);
+ if (! change)
+ {
+ /* This can only happen if the path was removed from changed_paths
+ by an earlier call to add_subdir, which means the path was already
+ handled and we should simply ignore it. */
+ return SVN_NO_ERROR;
+ }
+ switch (change->change_kind)
+ {
+ case svn_fs_path_change_add:
+ do_add = TRUE;
+ break;
+
+ case svn_fs_path_change_delete:
+ do_delete = TRUE;
+ break;
+
+ case svn_fs_path_change_replace:
+ do_add = TRUE;
+ do_delete = TRUE;
+ break;
+
+ case svn_fs_path_change_modify:
+ default:
+ /* do nothing */
+ break;
+ }
+
+ /* Handle any deletions. */
+ if (do_delete && ! do_add)
+ {
+ svn_boolean_t readable;
+
+ /* Issue #4121: delete under under a copy, of a path that was unreadable
+ at its pre-copy location. */
+ SVN_ERR(was_readable(&readable, root, repos_relpath, copies,
+ authz_read_func, authz_read_baton,
+ scratch_pool, scratch_pool));
+ if (readable)
+ SVN_ERR(svn_editor_delete(editor, repos_relpath, SVN_INVALID_REVNUM));
+
+ return SVN_NO_ERROR;
+ }
+
+ /* Handle replacements. */
+ if (do_delete && do_add)
+ replaces_rev = svn_fs_revision_root_revision(root);
+ else
+ replaces_rev = SVN_INVALID_REVNUM;
+
+ /* Fetch the node kind if it makes sense to do so. */
+ if (! do_delete || do_add)
+ {
+ if (change->node_kind == svn_node_unknown)
+ SVN_ERR(svn_fs_check_path(&(change->node_kind), root, repos_relpath,
+ scratch_pool));
+ if ((change->node_kind != svn_node_dir) &&
+ (change->node_kind != svn_node_file))
+ return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL,
+ _("Filesystem path '%s' is neither a file "
+ "nor a directory"), repos_relpath);
+ }
+
+ /* Handle any adds/opens. */
+ if (do_add)
+ {
+ svn_boolean_t src_readable;
+ svn_fs_root_t *copyfrom_root;
+
+ /* Was this node copied? */
+ SVN_ERR(fill_copyfrom(©from_root, ©from_path, ©from_rev,
+ &src_readable, root, change,
+ authz_read_func, authz_read_baton,
+ repos_relpath, scratch_pool, scratch_pool));
+
+ /* If we have a copyfrom path, and we can't read it or we're just
+ ignoring it, or the copyfrom rev is prior to the low water mark
+ then we just null them out and do a raw add with no history at
+ all. */
+ if (copyfrom_path
+ && ((! src_readable)
+ || (svn_relpath_skip_ancestor(base_repos_relpath,
+ copyfrom_path + 1) == NULL)
+ || (low_water_mark > copyfrom_rev)))
+ {
+ copyfrom_path = NULL;
+ copyfrom_rev = SVN_INVALID_REVNUM;
+ }
+
+ /* Do the right thing based on the path KIND. */
+ if (change->node_kind == svn_node_dir)
+ {
+ /* If this is a copy, but we can't represent it as such,
+ then we just do a recursive add of the source path
+ contents. */
+ if (change->copyfrom_path && ! copyfrom_path)
+ {
+ SVN_ERR(add_subdir(copyfrom_root, root, editor,
+ repos_relpath, change->copyfrom_path,
+ authz_read_func, authz_read_baton,
+ changed_paths, result_pool, scratch_pool));
+ }
+ else
+ {
+ if (copyfrom_path)
+ {
+ if (copyfrom_path[0] == '/')
+ ++copyfrom_path;
+ SVN_ERR(svn_editor_copy(editor, copyfrom_path, copyfrom_rev,
+ repos_relpath, replaces_rev));
+ }
+ else
+ {
+ apr_array_header_t *children;
+ apr_hash_t *props;
+ apr_hash_t *dirents;
+
+ SVN_ERR(svn_fs_dir_entries(&dirents, root, repos_relpath,
+ scratch_pool));
+ SVN_ERR(svn_hash_keys(&children, dirents, scratch_pool));
+
+ SVN_ERR(svn_fs_node_proplist(&props, root, repos_relpath,
+ scratch_pool));
+
+ SVN_ERR(svn_editor_add_directory(editor, repos_relpath,
+ children, props,
+ replaces_rev));
+ }
+ }
+ }
+ else
+ {
+ if (copyfrom_path)
+ {
+ if (copyfrom_path[0] == '/')
+ ++copyfrom_path;
+ SVN_ERR(svn_editor_copy(editor, copyfrom_path, copyfrom_rev,
+ repos_relpath, replaces_rev));
+ }
+ else
+ {
+ apr_hash_t *props;
+ svn_checksum_t *checksum;
+ svn_stream_t *contents;
+
+ SVN_ERR(svn_fs_node_proplist(&props, root, repos_relpath,
+ scratch_pool));
+
+ SVN_ERR(svn_fs_file_contents(&contents, root, repos_relpath,
+ scratch_pool));
+
+ SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1, root,
+ repos_relpath, TRUE, scratch_pool));
+
+ SVN_ERR(svn_editor_add_file(editor, repos_relpath, checksum,
+ contents, props, replaces_rev));
+ }
+ }
+
+ /* If we represent this as a copy... */
+ if (copyfrom_path)
+ {
+ /* If it is a directory, make sure descendants get the correct
+ delta source by remembering that we are operating inside a
+ (possibly nested) copy operation. */
+ if (change->node_kind == svn_node_dir)
+ {
+ struct copy_info *info = apr_pcalloc(result_pool, sizeof(*info));
+
+ info->path = apr_pstrdup(result_pool, repos_relpath);
+ info->copyfrom_path = apr_pstrdup(result_pool, copyfrom_path);
+ info->copyfrom_rev = copyfrom_rev;
+
+ APR_ARRAY_PUSH(copies, struct copy_info *) = info;
+ }
+ }
+ else
+ /* Else, we are an add without history... */
+ {
+ /* If an ancestor is added with history, we need to forget about
+ that here, go on with life and repeat all the mistakes of our
+ past... */
+ if (change->node_kind == svn_node_dir && copies->nelts > 0)
+ {
+ struct copy_info *info = apr_pcalloc(result_pool, sizeof(*info));
+
+ info->path = apr_pstrdup(result_pool, repos_relpath);
+ info->copyfrom_path = NULL;
+ info->copyfrom_rev = SVN_INVALID_REVNUM;
+
+ APR_ARRAY_PUSH(copies, struct copy_info *) = info;
+ }
+ }
+ }
+ else if (! do_delete)
+ {
+ /* If we are inside an add with history, we need to adjust the
+ delta source. */
+ if (copies->nelts > 0)
+ {
+ struct copy_info *info = APR_ARRAY_IDX(copies,
+ copies->nelts - 1,
+ struct copy_info *);
+ if (info->copyfrom_path)
+ {
+ const char *relpath = svn_relpath_skip_ancestor(info->path,
+ repos_relpath);
+ SVN_ERR_ASSERT(relpath && *relpath);
+ repos_relpath = svn_relpath_join(info->copyfrom_path,
+ relpath, scratch_pool);
+ }
+ }
+ }
+
+ if (! do_delete && !do_add)
+ {
+ apr_hash_t *props = NULL;
+
+ /* Is this a copy that was downgraded to a raw add? (If so,
+ we'll need to transmit properties and file contents and such
+ for it regardless of what the CHANGE structure's text_mod
+ and prop_mod flags say.) */
+ svn_boolean_t downgraded_copy = (change->copyfrom_known
+ && change->copyfrom_path
+ && (! copyfrom_path));
+
+ /* Handle property modifications. */
+ if (change->prop_mod || downgraded_copy)
+ {
+ SVN_ERR(svn_fs_node_proplist(&props, root, repos_relpath,
+ scratch_pool));
+ }
+
+ /* Handle textual modifications. */
+ if (change->node_kind == svn_node_file
+ && (change->text_mod || change->prop_mod || downgraded_copy))
+ {
+ svn_checksum_t *checksum;
+ svn_stream_t *contents;
+
+ SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1,
+ root, repos_relpath, TRUE,
+ scratch_pool));
+
+ SVN_ERR(svn_fs_file_contents(&contents, root, repos_relpath,
+ scratch_pool));
+
+ SVN_ERR(svn_editor_alter_file(editor, repos_relpath,
+ SVN_INVALID_REVNUM, props, checksum,
+ contents));
+ }
+
+ if (change->node_kind == svn_node_dir
+ && (change->prop_mod || downgraded_copy))
+ {
+ apr_array_header_t *children = NULL;
+
+ SVN_ERR(svn_editor_alter_directory(editor, repos_relpath,
+ SVN_INVALID_REVNUM, children,
+ props));
+ }
+ }
+
+ return SVN_NO_ERROR;
+}
+#endif
svn_error_t *
svn_repos__replay_ev2(svn_fs_root_t *root,
const char *base_repos_relpath,
svn_revnum_t low_water_mark,
- svn_boolean_t send_deltas,
svn_editor_t *editor,
svn_repos_authz_func_t authz_read_func,
void *authz_read_baton,
@@ -980,9 +1480,9 @@ svn_repos__replay_ev2(svn_fs_root_t *roo
apr_hash_t *changed_paths;
apr_hash_index_t *hi;
apr_array_header_t *paths;
- svn_fs_root_t *compare_root;
apr_array_header_t *copies;
apr_pool_t *iterpool;
+ svn_error_t *err = SVN_NO_ERROR;
int i;
SVN_ERR_ASSERT(!svn_dirent_is_absolute(base_repos_relpath));
@@ -1051,28 +1551,33 @@ svn_repos__replay_ev2(svn_fs_root_t *roo
if (! SVN_IS_VALID_REVNUM(low_water_mark))
low_water_mark = 0;
- if (send_deltas)
- {
- SVN_ERR(svn_fs_revision_root(&compare_root,
- svn_fs_root_fs(root),
- svn_fs_is_revision_root(root)
- ? svn_fs_revision_root_revision(root) - 1
- : svn_fs_txn_root_base_revision(root),
- scratch_pool));
- }
- else
- compare_root = NULL;
-
copies = apr_array_make(scratch_pool, 4, sizeof(struct copy_info *));
+ /* Sort the paths. Although not strictly required by the API, this has
+ the pleasant side effect of maintaining a consistent ordering of
+ dumpfile contents. */
+ qsort(paths->elts, paths->nelts, paths->elt_size, svn_sort_compare_paths);
+
/* Now actually handle the various paths. */
iterpool = svn_pool_create(scratch_pool);
for (i = 0; i < paths->nelts; i++)
{
const char *repos_relpath = APR_ARRAY_IDX(paths, i, const char *);
- SVN_ERR(replay_node(repos_relpath, editor, iterpool));
+
+ svn_pool_clear(iterpool);
+ err = replay_node(root, repos_relpath, editor, low_water_mark,
+ base_repos_relpath, copies, changed_paths,
+ authz_read_func, authz_read_baton,
+ scratch_pool, iterpool);
+ if (err)
+ break;
}
+ if (err)
+ return svn_error_compose_create(err, svn_editor_abort(editor));
+ else
+ SVN_ERR(svn_editor_complete(editor));
+
svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
Modified: subversion/branches/ev2-export/subversion/libsvn_subr/adler32.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/adler32.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/adler32.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/adler32.c Wed Jul 11 10:26:19 2012
@@ -61,7 +61,9 @@ svn__adler32(apr_uint32_t checksum, cons
* optimized code. Also, new zlib versions will come with
* SIMD code for x86 and x64.
*/
- return adler32(checksum, (const Bytef *)data, len);
+ return (apr_uint32_t)adler32(checksum,
+ (const Bytef *)data,
+ (uInt)len);
}
else
{
Modified: subversion/branches/ev2-export/subversion/libsvn_subr/auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/auth.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/auth.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/auth.c Wed Jul 11 10:26:19 2012
@@ -441,11 +441,12 @@ svn_auth_get_platform_specific_provider(
{
svn_version_func_t version_function
= version_function_symbol;
- const svn_version_checklist_t check_list[] =
- {
- { library_label, version_function },
- { NULL, NULL }
- };
+ svn_version_checklist_t check_list[2];
+
+ check_list[0].label = library_label;
+ check_list[0].version_query = version_function;
+ check_list[1].label = NULL;
+ check_list[1].version_query = NULL;
SVN_ERR(svn_ver_check_list(svn_subr_version(), check_list));
}
if (apr_dso_sym(&provider_function_symbol,
Modified: subversion/branches/ev2-export/subversion/libsvn_subr/base64.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/base64.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/base64.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/base64.c Wed Jul 11 10:26:19 2012
@@ -306,9 +306,9 @@ struct decode_baton {
static APR_INLINE void
decode_group(const unsigned char *in, char *out)
{
- out[0] = (in[0] << 2) | (in[1] >> 4);
- out[1] = ((in[1] & 0xf) << 4) | (in[2] >> 2);
- out[2] = ((in[2] & 0x3) << 6) | in[3];
+ out[0] = (char)((in[0] << 2) | (in[1] >> 4));
+ out[1] = (char)(((in[1] & 0xf) << 4) | (in[2] >> 2));
+ out[2] = (char)(((in[2] & 0x3) << 6) | in[3]);
}
/* Lookup table for base64 characters; reverse_base64[ch] gives a
Modified: subversion/branches/ev2-export/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/cache-membuffer.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/cache-membuffer.c Wed Jul 11 10:26:19 2012
@@ -700,9 +700,11 @@ let_entry_age(svn_membuffer_t *cache, en
static APR_INLINE unsigned char
is_group_initialized(svn_membuffer_t *cache, apr_uint32_t group_index)
{
- unsigned char flags = cache->group_initialized
- [group_index / (8 * GROUP_INIT_GRANULARITY)];
- unsigned char bit_mask = 1 << ((group_index / GROUP_INIT_GRANULARITY) % 8);
+ unsigned char flags
+ = cache->group_initialized[group_index / (8 * GROUP_INIT_GRANULARITY)];
+ unsigned char bit_mask
+ = (unsigned char)(1 << ((group_index / GROUP_INIT_GRANULARITY) % 8));
+
return flags & bit_mask;
}
@@ -726,7 +728,8 @@ initialize_group(svn_membuffer_t *cache,
cache->directory[i][j].offset = NO_OFFSET;
/* set the "initialized" bit for these groups */
- bit_mask = 1 << ((group_index / GROUP_INIT_GRANULARITY) % 8);
+ bit_mask
+ = (unsigned char)(1 << ((group_index / GROUP_INIT_GRANULARITY) % 8));
cache->group_initialized[group_index / (8 * GROUP_INIT_GRANULARITY)]
|= bit_mask;
}
@@ -1075,11 +1078,10 @@ svn_cache__membuffer_cache_create(svn_me
* Note, that this limit could only be exceeded in a very
* theoretical setup with about 1EB of cache.
*/
- group_count = directory_size / sizeof(entry_group_t);
- if (group_count >= (APR_UINT32_MAX / GROUP_SIZE))
- {
- group_count = (APR_UINT32_MAX / GROUP_SIZE) - 1;
- }
+ group_count = directory_size / sizeof(entry_group_t)
+ >= (APR_UINT32_MAX / GROUP_SIZE)
+ ? (APR_UINT32_MAX / GROUP_SIZE) - 1
+ : (apr_uint32_t)(directory_size / sizeof(entry_group_t));
group_init_size = 1 + group_count / (8 * GROUP_INIT_GRANULARITY);
for (seg = 0; seg < segment_count; ++seg)
Modified: subversion/branches/ev2-export/subversion/libsvn_subr/cache-memcache.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/cache-memcache.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/cache-memcache.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/cache-memcache.c Wed Jul 11 10:26:19 2012
@@ -29,6 +29,7 @@
#include "svn_private_config.h"
#include "private/svn_cache.h"
+#include "private/svn_dep_compat.h"
#include "cache.h"
@@ -527,7 +528,7 @@ svn_cache__make_memcache_from_config(svn
svn_config_t *config,
apr_pool_t *pool)
{
- apr_uint16_t server_count;
+ int server_count;
apr_pool_t *subpool = svn_pool_create(pool);
server_count =
@@ -542,12 +543,15 @@ svn_cache__make_memcache_from_config(svn
return SVN_NO_ERROR;
}
+ if (server_count > APR_INT16_MAX)
+ return svn_error_create(SVN_ERR_TOO_MANY_MEMCACHED_SERVERS, NULL, NULL);
+
#ifdef SVN_HAVE_MEMCACHE
{
struct ams_baton b;
svn_memcache_t *memcache = apr_pcalloc(pool, sizeof(*memcache));
apr_status_t apr_err = apr_memcache_create(pool,
- server_count,
+ (apr_uint16_t)server_count,
0, /* flags */
&(memcache->c));
if (apr_err != APR_SUCCESS)
Modified: subversion/branches/ev2-export/subversion/libsvn_subr/cache.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/cache.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/cache.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/cache.c Wed Jul 11 10:26:19 2012
@@ -212,14 +212,14 @@ svn_cache__format_info(const svn_cache__
enum { _1MB = 1024 * 1024 };
apr_uint64_t misses = info->gets - info->hits;
- double hit_rate = (100.0 * info->hits)
- / (info->gets ? info->gets : 1);
- double write_rate = (100.0 * info->sets)
- / (misses ? misses : 1);
- double data_usage_rate = (100.0 * info->used_size)
- / (info->data_size ? info->data_size : 1);
- double data_entry_rate = (100.0 * info->used_entries)
- / (info->total_entries ? info->total_entries : 1);
+ double hit_rate = (100.0 * (double)info->hits)
+ / (double)(info->gets ? info->gets : 1);
+ double write_rate = (100.0 * (double)info->sets)
+ / (double)(misses ? misses : 1);
+ double data_usage_rate = (100.0 * (double)info->used_size)
+ / (double)(info->data_size ? info->data_size : 1);
+ double data_entry_rate = (100.0 * (double)info->used_entries)
+ / (double)(info->total_entries ? info->total_entries : 1);
return svn_string_createf(result_pool,
Modified: subversion/branches/ev2-export/subversion/libsvn_subr/checksum.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/checksum.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/checksum.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/checksum.c Wed Jul 11 10:26:19 2012
@@ -276,8 +276,8 @@ svn_checksum_parse_hex(svn_checksum_t **
if (x1 == (char)-1 || x2 == (char)-1)
return svn_error_create(SVN_ERR_BAD_CHECKSUM_PARSE, NULL, NULL);
- digest[i] = (x1 << 4) | x2;
- is_nonzero |= (x1 << 4) | x2;
+ digest[i] = (char)((x1 << 4) | x2);
+ is_nonzero |= (char)((x1 << 4) | x2);
}
if (!is_nonzero)
Modified: subversion/branches/ev2-export/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/config_file.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/config_file.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/config_file.c Wed Jul 11 10:26:19 2012
@@ -797,9 +797,6 @@ svn_config_ensure(const char *config_dir
NL
"### http-compression Whether to compress HTTP requests" NL
"### neon-debug-mask Debug mask for Neon HTTP library" NL
-#ifdef SVN_NEON_0_26
- "### http-auth-types Auth types to use for HTTP library"NL
-#endif
"### ssl-authority-files List of files, each of a trusted CA"
NL
"### ssl-trust-default-ca Trust the system 'default' CAs" NL
@@ -809,7 +806,7 @@ svn_config_ensure(const char *config_dir
"### ssl-pkcs11-provider Name of PKCS#11 provider to use." NL
"### http-library Which library to use for http/https"
NL
- "### connections (neon or serf)" NL
+ "### connections." NL
"### store-passwords Specifies whether passwords used" NL
"### to authenticate against a" NL
"### Subversion server may be cached" NL
@@ -887,6 +884,13 @@ svn_config_ensure(const char *config_dir
"### HTTP timeouts, if given, are specified in seconds. A timeout" NL
"### of 0, i.e. zero, causes a builtin default to be used." NL
"###" NL
+ "### Most users will not need to explicitly set the http-library" NL
+ "### option, but valid values for the option include:" NL
+ "### 'serf': Serf-based module (Subversion 1.5 - present)" NL
+ "### 'neon': Neon-based module (Subversion 1.0 - 1.7)" NL
+ "### Availability of these modules may depend on your specific" NL
+ "### Subversion distribution." NL
+ "###" NL
"### The commented-out examples below are intended only to" NL
"### demonstrate how to use this file; any resemblance to actual" NL
"### servers, living or dead, is entirely coincidental." NL
@@ -908,9 +912,6 @@ svn_config_ensure(const char *config_dir
"# http-proxy-username = blah" NL
"# http-proxy-password = doubleblah" NL
"# http-timeout = 60" NL
-#ifdef SVN_NEON_0_26
- "# http-auth-types = basic;digest;negotiate" NL
-#endif
"# neon-debug-mask = 130" NL
#ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
"# store-plaintext-passwords = no" NL
@@ -951,9 +952,6 @@ svn_config_ensure(const char *config_dir
"# http-proxy-username = defaultusername" NL
"# http-proxy-password = defaultpassword" NL
"# http-compression = no" NL
-#ifdef SVN_NEON_0_26
- "# http-auth-types = basic;digest;negotiate" NL
-#endif
"# No http-timeout, so just use the builtin default." NL
"# No neon-debug-mask, so neon debugging is disabled." NL
"# ssl-authority-files = /path/to/CAcert.pem;/path/to/CAcert2.pem" NL