You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by pr...@apache.org on 2013/07/09 10:48:47 UTC
svn commit: r1501136 [5/10] - in /subversion/branches/verify-keep-going: ./
build/ build/ac-macros/ build/generator/ subversion/bindings/javahl/native/
subversion/bindings/javahl/src/org/apache/subversion/javahl/
subversion/bindings/javahl/src/org/apac...
Modified: subversion/branches/verify-keep-going/subversion/libsvn_ra_local/ra_plugin.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_ra_local/ra_plugin.c?rev=1501136&r1=1501135&r2=1501136&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_ra_local/ra_plugin.c Tue Jul 9 08:48:43 2013
@@ -541,6 +541,9 @@ ignore_warnings(void *baton,
return;
}
+#define USER_AGENT "SVN/" SVN_VER_NUMBER " (" SVN_BUILD_TARGET ")" \
+ " ra_local"
+
static svn_error_t *
svn_ra_local__open(svn_ra_session_t *session,
const char **corrected_url,
@@ -550,6 +553,7 @@ svn_ra_local__open(svn_ra_session_t *ses
apr_hash_t *config,
apr_pool_t *pool)
{
+ const char *client_string;
svn_ra_local__session_baton_t *sess;
const char *fs_path;
static volatile svn_atomic_t cache_init_state = 0;
@@ -592,6 +596,18 @@ svn_ra_local__open(svn_ra_session_t *ses
/* Be sure username is NULL so we know to look it up / ask for it */
sess->username = NULL;
+ if (sess->callbacks->get_client_string != NULL)
+ SVN_ERR(sess->callbacks->get_client_string(sess->callback_baton,
+ &client_string, pool));
+ else
+ client_string = NULL;
+
+ if (client_string)
+ sess->useragent = apr_pstrcat(pool, USER_AGENT " ",
+ client_string, (char *)NULL);
+ else
+ sess->useragent = USER_AGENT;
+
session->priv = sess;
return SVN_NO_ERROR;
}
@@ -765,6 +781,8 @@ svn_ra_local__get_commit_editor(svn_ra_s
svn_string_create(sess->username, pool));
svn_hash_sets(revprop_table, SVN_PROP_TXN_CLIENT_COMPAT_VERSION,
svn_string_create(SVN_VER_NUMBER, pool));
+ svn_hash_sets(revprop_table, SVN_PROP_TXN_USER_AGENT,
+ svn_string_create(sess->useragent, pool));
/* Get the repos commit-editor */
return svn_repos_get_commit_editor5
Modified: subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/blame.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/blame.c?rev=1501136&r1=1501135&r2=1501136&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/blame.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/blame.c Tue Jul 9 08:48:43 2013
@@ -47,7 +47,7 @@
* This enum represents the current state of our XML parsing for a REPORT.
*/
typedef enum blame_state_e {
- INITIAL = 0,
+ INITIAL = XML_STATE_INITIAL,
FILE_REVS_REPORT,
FILE_REV,
REV_PROP,
@@ -111,7 +111,6 @@ static const svn_ra_serf__xml_transition
{ 0 }
};
-
/* Conforms to svn_ra_serf__xml_opened_t */
static svn_error_t *
blame_opened(svn_ra_serf__xml_estate_t *xes,
@@ -332,6 +331,7 @@ svn_ra_serf__get_file_revs(svn_ra_sessio
svn_ra_serf__xml_context_t *xmlctx;
const char *req_url;
svn_error_t *err;
+ svn_revnum_t peg_rev;
blame_ctx = apr_pcalloc(pool, sizeof(*blame_ctx));
blame_ctx->pool = pool;
@@ -342,18 +342,26 @@ svn_ra_serf__get_file_revs(svn_ra_sessio
blame_ctx->end = end;
blame_ctx->include_merged_revisions = include_merged_revisions;
+ /* Since Subversion 1.8 we allow retrieving blames backwards. So we can't
+ just unconditionally use end_rev as the peg revision as before */
+ if (end > start)
+ peg_rev = end;
+ else
+ peg_rev = start;
+
SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */,
session, NULL /* conn */,
- NULL /* url */, end,
+ NULL /* url */, peg_rev,
pool, pool));
xmlctx = svn_ra_serf__xml_context_create(blame_ttable,
blame_opened,
blame_closed,
blame_cdata,
+ NULL,
blame_ctx,
pool);
- handler = svn_ra_serf__create_expat_handler(xmlctx, pool);
+ handler = svn_ra_serf__create_expat_handler(xmlctx, NULL, pool);
handler->method = "REPORT";
handler->path = req_url;
Modified: subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/get_deleted_rev.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/get_deleted_rev.c?rev=1501136&r1=1501135&r2=1501136&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/get_deleted_rev.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/get_deleted_rev.c Tue Jul 9 08:48:43 2013
@@ -36,7 +36,7 @@
* This enum represents the current state of our XML parsing for a REPORT.
*/
enum drev_state_e {
- INITIAL = 0,
+ INITIAL = XML_STATE_INITIAL,
REPORT,
VERSION_NAME
};
@@ -151,10 +151,10 @@ svn_ra_serf__get_deleted_rev(svn_ra_sess
pool, pool));
xmlctx = svn_ra_serf__xml_context_create(getdrev_ttable,
- NULL, getdrev_closed, NULL,
+ NULL, getdrev_closed, NULL, NULL,
drev_ctx,
pool);
- handler = svn_ra_serf__create_expat_handler(xmlctx, pool);
+ handler = svn_ra_serf__create_expat_handler(xmlctx, NULL, pool);
handler->method = "REPORT";
handler->path = req_url;
Modified: subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/getdate.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/getdate.c?rev=1501136&r1=1501135&r2=1501136&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/getdate.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/getdate.c Tue Jul 9 08:48:43 2013
@@ -44,7 +44,7 @@
* This enum represents the current state of our XML parsing for a REPORT.
*/
enum date_state_e {
- INITIAL = 0,
+ INITIAL = XML_STATE_INITIAL,
REPORT,
VERSION_NAME
};
@@ -140,10 +140,10 @@ svn_ra_serf__get_dated_revision(svn_ra_s
SVN_ERR(svn_ra_serf__report_resource(&report_target, session, NULL, pool));
xmlctx = svn_ra_serf__xml_context_create(date_ttable,
- NULL, date_closed, NULL,
+ NULL, date_closed, NULL, NULL,
date_ctx,
pool);
- handler = svn_ra_serf__create_expat_handler(xmlctx, pool);
+ handler = svn_ra_serf__create_expat_handler(xmlctx, NULL, pool);
handler->method = "REPORT";
handler->path = report_target;
Modified: subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/getlocations.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/getlocations.c?rev=1501136&r1=1501135&r2=1501136&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/getlocations.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/getlocations.c Tue Jul 9 08:48:43 2013
@@ -43,7 +43,7 @@
* This enum represents the current state of our XML parsing for a REPORT.
*/
enum loc_state_e {
- INITIAL = 0,
+ INITIAL = XML_STATE_INITIAL,
REPORT,
LOCATION
};
@@ -176,10 +176,10 @@ svn_ra_serf__get_locations(svn_ra_sessio
pool, pool));
xmlctx = svn_ra_serf__xml_context_create(getloc_ttable,
- NULL, getloc_closed, NULL,
+ NULL, getloc_closed, NULL, NULL,
loc_ctx,
pool);
- handler = svn_ra_serf__create_expat_handler(xmlctx, pool);
+ handler = svn_ra_serf__create_expat_handler(xmlctx, NULL, pool);
handler->method = "REPORT";
handler->path = req_url;
Modified: subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/getlocationsegments.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/getlocationsegments.c?rev=1501136&r1=1501135&r2=1501136&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/getlocationsegments.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/getlocationsegments.c Tue Jul 9 08:48:43 2013
@@ -52,8 +52,8 @@ typedef struct gls_context_t {
} gls_context_t;
-enum {
- INITIAL = 0,
+enum locseg_state_e {
+ INITIAL = XML_STATE_INITIAL,
REPORT,
SEGMENT
};
@@ -178,10 +178,10 @@ svn_ra_serf__get_location_segments(svn_r
pool, pool));
xmlctx = svn_ra_serf__xml_context_create(gls_ttable,
- NULL, gls_closed, NULL,
+ NULL, gls_closed, NULL, NULL,
gls_ctx,
pool);
- handler = svn_ra_serf__create_expat_handler(xmlctx, pool);
+ handler = svn_ra_serf__create_expat_handler(xmlctx, NULL, pool);
handler->method = "REPORT";
handler->path = req_url;
Modified: subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/getlocks.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/getlocks.c?rev=1501136&r1=1501135&r2=1501136&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/getlocks.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/getlocks.c Tue Jul 9 08:48:43 2013
@@ -47,8 +47,8 @@
/*
* This enum represents the current state of our XML parsing for a REPORT.
*/
-enum {
- INITIAL = 0,
+enum getlocks_state_e {
+ INITIAL = XML_STATE_INITIAL,
REPORT,
LOCK,
PATH,
@@ -246,10 +246,10 @@ svn_ra_serf__get_locks(svn_ra_session_t
lock_ctx->hash = apr_hash_make(pool);
xmlctx = svn_ra_serf__xml_context_create(getlocks_ttable,
- NULL, getlocks_closed, NULL,
+ NULL, getlocks_closed, NULL, NULL,
lock_ctx,
pool);
- handler = svn_ra_serf__create_expat_handler(xmlctx, pool);
+ handler = svn_ra_serf__create_expat_handler(xmlctx, NULL, pool);
handler->method = "REPORT";
handler->path = req_url;
Modified: subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/inherited_props.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/inherited_props.c?rev=1501136&r1=1501135&r2=1501136&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/inherited_props.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/inherited_props.c Tue Jul 9 08:48:43 2013
@@ -41,7 +41,7 @@
/* The current state of our XML parsing. */
typedef enum iprops_state_e {
- NONE = 0,
+ INITIAL = XML_STATE_INITIAL,
IPROPS_REPORT,
IPROPS_ITEM,
IPROPS_PATH,
@@ -61,18 +61,12 @@ typedef struct iprops_context_t {
/* The repository's root URL. */
const char *repos_root_url;
- /* Current CDATA values*/
- svn_stringbuf_t *curr_path;
+ /* Current property name */
svn_stringbuf_t *curr_propname;
- svn_stringbuf_t *curr_propval;
- const char *curr_prop_val_encoding;
/* Current element in IPROPS. */
svn_prop_inherited_item_t *curr_iprop;
- /* Serf context completion flag for svn_ra_serf__context_run_wait() */
- svn_boolean_t done;
-
/* Path we are finding inherited properties for. This is relative to
the RA session passed to svn_ra_serf__get_inherited_props. */
const char *path;
@@ -80,162 +74,121 @@ typedef struct iprops_context_t {
svn_revnum_t revision;
} iprops_context_t;
+#define S_ SVN_XML_NAMESPACE
+static const svn_ra_serf__xml_transition_t iprops_table[] = {
+ { INITIAL, S_, SVN_DAV__INHERITED_PROPS_REPORT, IPROPS_REPORT,
+ FALSE, { NULL }, FALSE },
+
+ { IPROPS_REPORT, S_, SVN_DAV__IPROP_ITEM, IPROPS_ITEM,
+ FALSE, { NULL }, TRUE },
+
+ { IPROPS_ITEM, S_, SVN_DAV__IPROP_PATH, IPROPS_PATH,
+ TRUE, { NULL }, TRUE },
+
+ { IPROPS_ITEM, S_, SVN_DAV__IPROP_PROPNAME, IPROPS_PROPNAME,
+ TRUE, { NULL }, TRUE },
+
+ { IPROPS_ITEM, S_, SVN_DAV__IPROP_PROPVAL, IPROPS_PROPVAL,
+ TRUE, { "?V:encoding", NULL }, TRUE },
+
+ { 0 }
+};
+
+/* Conforms to svn_ra_serf__xml_opened_t */
static svn_error_t *
-start_element(svn_ra_serf__xml_parser_t *parser,
- svn_ra_serf__dav_props_t name,
- const char **attrs,
+iprops_opened(svn_ra_serf__xml_estate_t *xes,
+ void *baton,
+ int entered_state,
+ const svn_ra_serf__dav_props_t *tag,
apr_pool_t *scratch_pool)
{
- iprops_context_t *iprops_ctx = parser->user_data;
- iprops_state_e state;
+ iprops_context_t *iprops_ctx = baton;
- state = parser->state->current_state;
- if (state == NONE
- && strcmp(name.name, SVN_DAV__INHERITED_PROPS_REPORT) == 0)
+ if (entered_state == IPROPS_ITEM)
{
- svn_ra_serf__xml_push_state(parser, IPROPS_REPORT);
- }
- else if (state == IPROPS_REPORT &&
- strcmp(name.name, SVN_DAV__IPROP_ITEM) == 0)
- {
- svn_stringbuf_setempty(iprops_ctx->curr_path);
svn_stringbuf_setempty(iprops_ctx->curr_propname);
- svn_stringbuf_setempty(iprops_ctx->curr_propval);
- iprops_ctx->curr_prop_val_encoding = NULL;
- iprops_ctx->curr_iprop = NULL;
- svn_ra_serf__xml_push_state(parser, IPROPS_ITEM);
- }
- else if (state == IPROPS_ITEM &&
- strcmp(name.name, SVN_DAV__IPROP_PROPVAL) == 0)
- {
- const char *prop_val_encoding = svn_xml_get_attr_value("encoding",
- attrs);
- iprops_ctx->curr_prop_val_encoding = apr_pstrdup(iprops_ctx->pool,
- prop_val_encoding);
- svn_ra_serf__xml_push_state(parser, IPROPS_PROPVAL);
- }
- else if (state == IPROPS_ITEM &&
- strcmp(name.name, SVN_DAV__IPROP_PATH) == 0)
- {
- svn_ra_serf__xml_push_state(parser, IPROPS_PATH);
- }
- else if (state == IPROPS_ITEM &&
- strcmp(name.name, SVN_DAV__IPROP_PROPNAME) == 0)
- {
- svn_ra_serf__xml_push_state(parser, IPROPS_PROPNAME);
- }
- else if (state == IPROPS_ITEM &&
- strcmp(name.name, SVN_DAV__IPROP_PROPVAL) == 0)
- {
- svn_ra_serf__xml_push_state(parser, IPROPS_PROPVAL);
- }
+ iprops_ctx->curr_iprop = apr_pcalloc(iprops_ctx->pool,
+ sizeof(*iprops_ctx->curr_iprop));
+
+ iprops_ctx->curr_iprop->prop_hash = apr_hash_make(iprops_ctx->pool);
+ }
return SVN_NO_ERROR;
}
+/* Conforms to svn_ra_serf__xml_closed_t */
static svn_error_t *
-end_element(svn_ra_serf__xml_parser_t *parser,
- svn_ra_serf__dav_props_t name,
- apr_pool_t *scratch_pool)
+iprops_closed(svn_ra_serf__xml_estate_t *xes,
+ void *baton,
+ int leaving_state,
+ const svn_string_t *cdata,
+ apr_hash_t *attrs,
+ apr_pool_t *scratch_pool)
{
- iprops_context_t *iprops_ctx = parser->user_data;
- iprops_state_e state;
-
- state = parser->state->current_state;
+ iprops_context_t *iprops_ctx = baton;
- if (state == IPROPS_REPORT &&
- strcmp(name.name, SVN_DAV__INHERITED_PROPS_REPORT) == 0)
+ if (leaving_state == IPROPS_ITEM)
{
- svn_ra_serf__xml_pop_state(parser);
+ APR_ARRAY_PUSH(iprops_ctx->iprops, svn_prop_inherited_item_t *) =
+ iprops_ctx->curr_iprop;
+
+ iprops_ctx->curr_iprop = NULL;
}
- else if (state == IPROPS_PATH
- && strcmp(name.name, SVN_DAV__IPROP_PATH) == 0)
+ else if (leaving_state == IPROPS_PATH)
{
- iprops_ctx->curr_iprop = apr_palloc(
- iprops_ctx->pool, sizeof(svn_prop_inherited_item_t));
+ /* Every <iprop-item> has a single <iprop-path> */
+ if (iprops_ctx->curr_iprop->path_or_url)
+ return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL);
iprops_ctx->curr_iprop->path_or_url =
svn_path_url_add_component2(iprops_ctx->repos_root_url,
- iprops_ctx->curr_path->data,
+ cdata->data,
iprops_ctx->pool);
- iprops_ctx->curr_iprop->prop_hash = apr_hash_make(iprops_ctx->pool);
- svn_ra_serf__xml_pop_state(parser);
}
- else if (state == IPROPS_PROPVAL
- && strcmp(name.name, SVN_DAV__IPROP_PROPVAL) == 0)
+ else if (leaving_state == IPROPS_PROPNAME)
{
- const svn_string_t *prop_val;
+ if (iprops_ctx->curr_propname->len)
+ return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL);
- if (iprops_ctx->curr_prop_val_encoding)
- {
- svn_string_t encoded_prop_val;
+ /* Store propname for value */
+ svn_stringbuf_set(iprops_ctx->curr_propname, cdata->data);
+ }
+ else if (leaving_state == IPROPS_PROPVAL)
+ {
+ const char *encoding;
+ const svn_string_t *val_str;
+
+ if (! iprops_ctx->curr_propname->len)
+ return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL);
+
+ encoding = svn_hash_gets(attrs, "V:encoding");
- if (strcmp(iprops_ctx->curr_prop_val_encoding, "base64") != 0)
- return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL);
+ if (encoding)
+ {
+ if (strcmp(encoding, "base64") != 0)
+ return svn_error_createf(SVN_ERR_XML_MALFORMED,
+ NULL,
+ _("Got unrecognized encoding '%s'"),
+ encoding);
- encoded_prop_val.data = iprops_ctx->curr_propval->data;
- encoded_prop_val.len = iprops_ctx->curr_propval->len;
- prop_val = svn_base64_decode_string(&encoded_prop_val,
- iprops_ctx->pool);
+ /* Decode into the right pool. */
+ val_str = svn_base64_decode_string(cdata, iprops_ctx->pool);
}
else
{
- prop_val = svn_string_create_from_buf(iprops_ctx->curr_propval,
- iprops_ctx->pool);
+ /* Copy into the right pool. */
+ val_str = svn_string_dup(cdata, iprops_ctx->pool);
}
svn_hash_sets(iprops_ctx->curr_iprop->prop_hash,
apr_pstrdup(iprops_ctx->pool,
iprops_ctx->curr_propname->data),
- prop_val);
- /* Clear current propname and propval in the event there are
- multiple properties on the current path. */
+ val_str);
+ /* Clear current propname. */
svn_stringbuf_setempty(iprops_ctx->curr_propname);
- svn_stringbuf_setempty(iprops_ctx->curr_propval);
- svn_ra_serf__xml_pop_state(parser);
- }
- else if (state == IPROPS_PROPNAME
- && strcmp(name.name, SVN_DAV__IPROP_PROPNAME) == 0)
- {
- svn_ra_serf__xml_pop_state(parser);
- }
- else if (state == IPROPS_ITEM
- && strcmp(name.name, SVN_DAV__IPROP_ITEM) == 0)
- {
- APR_ARRAY_PUSH(iprops_ctx->iprops, svn_prop_inherited_item_t *) =
- iprops_ctx->curr_iprop;
- svn_ra_serf__xml_pop_state(parser);
- }
- return SVN_NO_ERROR;
-}
-
-
-static svn_error_t *
-cdata_handler(svn_ra_serf__xml_parser_t *parser,
- const char *data,
- apr_size_t len,
- apr_pool_t *scratch_pool)
-{
- iprops_context_t *iprops_ctx = parser->user_data;
- iprops_state_e state = parser->state->current_state;
-
- switch (state)
- {
- case IPROPS_PATH:
- svn_stringbuf_appendbytes(iprops_ctx->curr_path, data, len);
- break;
-
- case IPROPS_PROPNAME:
- svn_stringbuf_appendbytes(iprops_ctx->curr_propname, data, len);
- break;
-
- case IPROPS_PROPVAL:
- svn_stringbuf_appendbytes(iprops_ctx->curr_propval, data, len);
- break;
-
- default:
- break;
}
+ else
+ SVN_ERR_MALFUNCTION(); /* Invalid transition table */
return SVN_NO_ERROR;
}
@@ -281,7 +234,7 @@ svn_ra_serf__get_inherited_props(svn_ra_
iprops_context_t *iprops_ctx;
svn_ra_serf__session_t *session = ra_session->priv;
svn_ra_serf__handler_t *handler;
- svn_ra_serf__xml_parser_t *parser_ctx;
+ svn_ra_serf__xml_context_t *xmlctx;
const char *req_url;
SVN_ERR(svn_ra_serf__get_stable_url(&req_url,
@@ -290,24 +243,26 @@ svn_ra_serf__get_inherited_props(svn_ra_
NULL /* conn */,
NULL /* url */,
revision,
- result_pool, scratch_pool));
+ scratch_pool, scratch_pool));
SVN_ERR_ASSERT(session->repos_root_str);
iprops_ctx = apr_pcalloc(scratch_pool, sizeof(*iprops_ctx));
- iprops_ctx->done = FALSE;
iprops_ctx->repos_root_url = session->repos_root_str;
iprops_ctx->pool = result_pool;
- iprops_ctx->curr_path = svn_stringbuf_create_empty(scratch_pool);
iprops_ctx->curr_propname = svn_stringbuf_create_empty(scratch_pool);
- iprops_ctx->curr_propval = svn_stringbuf_create_empty(scratch_pool);
iprops_ctx->curr_iprop = NULL;
iprops_ctx->iprops = apr_array_make(result_pool, 1,
sizeof(svn_prop_inherited_item_t *));
iprops_ctx->path = path;
iprops_ctx->revision = revision;
- handler = apr_pcalloc(scratch_pool, sizeof(*handler));
+ xmlctx = svn_ra_serf__xml_context_create(iprops_table,
+ iprops_opened, iprops_closed,
+ NULL, NULL,
+ iprops_ctx,
+ scratch_pool);
+ handler = svn_ra_serf__create_expat_handler(xmlctx, NULL, scratch_pool);
handler->method = "REPORT";
handler->path = req_url;
@@ -318,18 +273,6 @@ svn_ra_serf__get_inherited_props(svn_ra_
handler->body_type = "text/xml";
handler->handler_pool = scratch_pool;
- parser_ctx = apr_pcalloc(scratch_pool, sizeof(*parser_ctx));
-
- parser_ctx->pool = scratch_pool;
- parser_ctx->user_data = iprops_ctx;
- parser_ctx->start = start_element;
- parser_ctx->end = end_element;
- parser_ctx->cdata = cdata_handler;
- parser_ctx->done = &iprops_ctx->done;
-
- handler->response_handler = svn_ra_serf__handle_xml_parser;
- handler->response_baton = parser_ctx;
-
err = svn_ra_serf__context_run_one(handler, scratch_pool);
SVN_ERR(svn_error_compose_create(
svn_ra_serf__error_on_status(handler->sline,
@@ -337,8 +280,7 @@ svn_ra_serf__get_inherited_props(svn_ra_
handler->location),
err));
- if (iprops_ctx->done)
- *iprops = iprops_ctx->iprops;
+ *iprops = iprops_ctx->iprops;
return SVN_NO_ERROR;
}
Modified: subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/locks.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/locks.c?rev=1501136&r1=1501135&r2=1501136&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/locks.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/locks.c Tue Jul 9 08:48:43 2013
@@ -142,6 +142,10 @@ static const svn_ra_serf__xml_transition
{ 0 }
};
+static const int locks_expected_status[] = {
+ 207,
+ 0
+};
/* Conforms to svn_ra_serf__xml_closed_t */
static svn_error_t *
@@ -378,10 +382,10 @@ svn_ra_serf__get_lock(svn_ra_session_t *
lock_ctx->lock->path = apr_pstrdup(pool, path); /* be sure */
xmlctx = svn_ra_serf__xml_context_create(locks_ttable,
- NULL, locks_closed, NULL,
+ NULL, locks_closed, NULL, NULL,
lock_ctx,
pool);
- handler = svn_ra_serf__create_expat_handler(xmlctx, pool);
+ handler = svn_ra_serf__create_expat_handler(xmlctx, locks_expected_status, pool);
handler->method = "PROPFIND";
handler->path = req_url;
@@ -469,10 +473,10 @@ svn_ra_serf__lock(svn_ra_session_t *ra_s
lock_ctx->path, iterpool);
xmlctx = svn_ra_serf__xml_context_create(locks_ttable,
- NULL, locks_closed, NULL,
+ NULL, locks_closed, NULL, NULL,
lock_ctx,
iterpool);
- handler = svn_ra_serf__create_expat_handler(xmlctx, iterpool);
+ handler = svn_ra_serf__create_expat_handler(xmlctx, NULL, iterpool);
handler->method = "LOCK";
handler->path = req_url;
Modified: subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/log.c?rev=1501136&r1=1501135&r2=1501136&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/log.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/log.c Tue Jul 9 08:48:43 2013
@@ -48,8 +48,8 @@
/*
* This enum represents the current state of our XML parsing for a REPORT.
*/
-enum {
- INITIAL = 0,
+enum log_state_e {
+ INITIAL = XML_STATE_INITIAL,
REPORT,
ITEM,
VERSION,
@@ -579,10 +579,10 @@ svn_ra_serf__get_log(svn_ra_session_t *r
pool, pool));
xmlctx = svn_ra_serf__xml_context_create(log_ttable,
- log_opened, log_closed, NULL,
+ log_opened, log_closed, NULL, NULL,
log_ctx,
pool);
- handler = svn_ra_serf__create_expat_handler(xmlctx, pool);
+ handler = svn_ra_serf__create_expat_handler(xmlctx, NULL, pool);
handler->method = "REPORT";
handler->path = req_url;
Modified: subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/merge.c?rev=1501136&r1=1501135&r2=1501136&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/merge.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/merge.c Tue Jul 9 08:48:43 2013
@@ -48,7 +48,7 @@
* This enum represents the current state of our XML parsing for a MERGE.
*/
typedef enum merge_state_e {
- INITIAL = 0,
+ INITIAL = XML_STATE_INITIAL,
MERGE_RESPONSE,
UPDATED_SET,
RESPONSE,
@@ -404,10 +404,10 @@ svn_ra_serf__run_merge(const svn_commit_
merge_ctx->merge_url = session->session_url.path;
xmlctx = svn_ra_serf__xml_context_create(merge_ttable,
- NULL, merge_closed, NULL,
+ NULL, merge_closed, NULL, NULL,
merge_ctx,
scratch_pool);
- handler = svn_ra_serf__create_expat_handler(xmlctx, scratch_pool);
+ handler = svn_ra_serf__create_expat_handler(xmlctx, NULL, scratch_pool);
handler->method = "MERGE";
handler->path = merge_ctx->merge_url;
Modified: subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/mergeinfo.c?rev=1501136&r1=1501135&r2=1501136&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/mergeinfo.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/mergeinfo.c Tue Jul 9 08:48:43 2013
@@ -41,7 +41,7 @@
/* The current state of our XML parsing. */
typedef enum mergeinfo_state_e {
- INITIAL = 0,
+ INITIAL = XML_STATE_INITIAL,
MERGEINFO_REPORT,
MERGEINFO_ITEM,
MERGEINFO_PATH,
@@ -214,10 +214,10 @@ svn_ra_serf__get_mergeinfo(svn_ra_sessio
mergeinfo_ctx->include_descendants = include_descendants;
xmlctx = svn_ra_serf__xml_context_create(mergeinfo_ttable,
- NULL, mergeinfo_closed, NULL,
+ NULL, mergeinfo_closed, NULL, NULL,
mergeinfo_ctx,
pool);
- handler = svn_ra_serf__create_expat_handler(xmlctx, pool);
+ handler = svn_ra_serf__create_expat_handler(xmlctx, NULL, pool);
handler->method = "REPORT";
handler->path = path;
Modified: subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/options.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/options.c?rev=1501136&r1=1501135&r2=1501136&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/options.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/options.c Tue Jul 9 08:48:43 2013
@@ -50,7 +50,7 @@
* This enum represents the current state of our XML parsing for an OPTIONS.
*/
enum options_state_e {
- INITIAL = 0,
+ INITIAL = XML_STATE_INITIAL,
OPTIONS,
ACTIVITY_COLLECTION,
HREF
@@ -362,6 +362,8 @@ options_response_handler(serf_request_t
capability_no);
svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS,
capability_no);
+ svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE,
+ capability_no);
/* Then see which ones we can discover. */
serf_bucket_headers_do(hdrs, capabilities_headers_iterator_callback,
@@ -399,10 +401,10 @@ create_options_req(options_context_t **o
new_ctx->youngest_rev = SVN_INVALID_REVNUM;
xmlctx = svn_ra_serf__xml_context_create(options_ttable,
- NULL, options_closed, NULL,
+ NULL, options_closed, NULL, NULL,
new_ctx,
pool);
- handler = svn_ra_serf__create_expat_handler(xmlctx, pool);
+ handler = svn_ra_serf__create_expat_handler(xmlctx, NULL, pool);
handler->method = "OPTIONS";
handler->path = session->session_url.path;
@@ -518,6 +520,65 @@ svn_ra_serf__exchange_capabilities(svn_r
}
+static svn_error_t *
+create_simple_options_body(serf_bucket_t **body_bkt,
+ void *baton,
+ serf_bucket_alloc_t *alloc,
+ apr_pool_t *pool)
+{
+ serf_bucket_t *body;
+ serf_bucket_t *s;
+
+ body = serf_bucket_aggregate_create(alloc);
+ svn_ra_serf__add_xml_header_buckets(body, alloc);
+
+ s = SERF_BUCKET_SIMPLE_STRING("<D:options xmlns:D=\"DAV:\" />", alloc);
+ serf_bucket_aggregate_append(body, s);
+
+ *body_bkt = body;
+ return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_ra_serf__probe_proxy(svn_ra_serf__session_t *serf_sess,
+ apr_pool_t *scratch_pool)
+{
+ svn_ra_serf__handler_t *handler;
+
+ handler = apr_pcalloc(scratch_pool, sizeof(*handler));
+ handler->handler_pool = scratch_pool;
+ handler->method = "OPTIONS";
+ handler->path = serf_sess->session_url.path;
+ handler->conn = serf_sess->conns[0];
+ handler->session = serf_sess;
+
+ /* We don't care about the response body, so discard it. */
+ handler->response_handler = svn_ra_serf__handle_discard_body;
+
+ /* We need a simple body, in order to send it in chunked format. */
+ handler->body_delegate = create_simple_options_body;
+
+ /* No special headers. */
+
+ SVN_ERR(svn_ra_serf__context_run_one(handler, scratch_pool));
+ /* Some versions of nginx in reverse proxy mode will return 411. They want
+ a Content-Length header, rather than chunked requests. We can keep other
+ HTTP/1.1 features, but will disable the chunking. */
+ if (handler->sline.code == 411)
+ {
+ serf_sess->using_chunked_requests = FALSE;
+
+ return SVN_NO_ERROR;
+ }
+ SVN_ERR(svn_ra_serf__error_on_status(handler->sline,
+ handler->path,
+ handler->location));
+
+ return SVN_NO_ERROR;
+}
+
+
svn_error_t *
svn_ra_serf__has_capability(svn_ra_session_t *ra_session,
svn_boolean_t *has,
Modified: subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/property.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/property.c?rev=1501136&r1=1501135&r2=1501136&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/property.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/property.c Tue Jul 9 08:48:43 2013
@@ -42,7 +42,7 @@
/* Our current parsing state we're in for the PROPFIND response. */
typedef enum prop_state_e {
- INITIAL = 0,
+ INITIAL = XML_STATE_INITIAL,
MULTISTATUS,
RESPONSE,
HREF,
@@ -136,6 +136,10 @@ static const svn_ra_serf__xml_transition
{ 0 }
};
+static const int propfind_expected_status[] = {
+ 207,
+ 0
+};
/* Return the HTTP status code contained in STATUS_LINE, or 0 if
there's a problem parsing it. */
@@ -598,10 +602,12 @@ svn_ra_serf__deliver_props(svn_ra_serf__
xmlctx = svn_ra_serf__xml_context_create(propfind_ttable,
propfind_opened,
propfind_closed,
- NULL,
+ NULL, NULL,
new_prop_ctx,
pool);
- handler = svn_ra_serf__create_expat_handler(xmlctx, pool);
+ handler = svn_ra_serf__create_expat_handler(xmlctx,
+ propfind_expected_status,
+ pool);
handler->method = "PROPFIND";
handler->path = path;
Modified: subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/ra_serf.h?rev=1501136&r1=1501135&r2=1501136&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/ra_serf.h Tue Jul 9 08:48:43 2013
@@ -144,6 +144,9 @@ struct svn_ra_serf__session_t {
HTTP/1.0. Thus, we cannot send chunked requests. */
svn_boolean_t http10;
+ /* Should we use Transfer-Encoding: chunked for HTTP/1.1 servers. */
+ svn_boolean_t using_chunked_requests;
+
/* Our Version-Controlled-Configuration; may be NULL until we know it. */
const char *vcc_url;
@@ -186,7 +189,11 @@ struct svn_ra_serf__session_t {
const char *activity_collection_url;
/* Are we using a proxy? */
- int using_proxy;
+ svn_boolean_t using_proxy;
+
+ /* Should we be careful with this proxy? (some have insufficient support that
+ we need to work around). */
+ svn_boolean_t busted_proxy;
const char *proxy_username;
const char *proxy_password;
@@ -723,6 +730,16 @@ typedef svn_error_t *
apr_size_t len,
apr_pool_t *scratch_pool);
+/* Called when releasing the XML parser to signal that the entire document was
+ read successfully */
+typedef svn_error_t *
+(*svn_ra_serf__xml_done_t)(void *baton,
+ apr_pool_t *scratch_pool);
+
+
+/* Magic state value for the initial state in a svn_ra_serf__xml_transition_t
+ table */
+#define XML_STATE_INITIAL 0
/* State transition table.
@@ -732,6 +749,8 @@ typedef svn_error_t *
In a list of transitions, use { 0 } to indicate the end. Specifically,
the code looks for NS == NULL.
+ The initial state for each transition table is XML_STATE_INITIAL.
+
### more docco
*/
typedef struct svn_ra_serf__xml_transition_t {
@@ -776,7 +795,10 @@ typedef struct svn_ra_serf__xml_transiti
COLLECT_CDATA flag). It will be called in every state, so the callback
must examine the CURRENT_STATE parameter to decide what to do.
- The same BATON value will be passed to all three callbacks.
+ If DONE_CB is not NULL, then it will be called when the parser is closed
+ after successfully parsing an entire document.
+
+ The same BATON value will be passed to all four callbacks.
The context will be created within RESULT_POOL. */
svn_ra_serf__xml_context_t *
@@ -785,21 +807,29 @@ svn_ra_serf__xml_context_create(
svn_ra_serf__xml_opened_t opened_cb,
svn_ra_serf__xml_closed_t closed_cb,
svn_ra_serf__xml_cdata_t cdata_cb,
+ svn_ra_serf__xml_done_t done_cb,
void *baton,
apr_pool_t *result_pool);
-/* Destroy all subpools for this structure. */
-void
-svn_ra_serf__xml_context_destroy(
- svn_ra_serf__xml_context_t *xmlctx);
+/* Verifies if the parsing completed successfully and destroys
+ all subpools. */
+svn_error_t *
+svn_ra_serf__xml_context_done(svn_ra_serf__xml_context_t *xmlctx);
/* Construct a handler with the response function/baton set up to parse
a response body using the given XML context. The handler and its
internal structures are allocated in RESULT_POOL.
+ As part of the handling the http status value is compared to 200, or
+ if EXPECTED_STATUS is not NULL to all the values in EXPECTED_STATUS.
+ EXPECTED_STATUS is expected to be a list of integers ending with a 0
+ that lives at least as long as RESULT_POOL. If the status doesn't
+ match the request has failed and will be parsed as en error response.
+
This also initializes HANDLER_POOL to the given RESULT_POOL. */
svn_ra_serf__handler_t *
svn_ra_serf__create_expat_handler(svn_ra_serf__xml_context_t *xmlctx,
+ const int *expected_status,
apr_pool_t *result_pool);
@@ -1334,6 +1364,14 @@ svn_ra_serf__run_merge(const svn_commit_
/** OPTIONS-related functions **/
+/* When running with a proxy, we may need to detect and correct for problems.
+ This probing function will send a simple OPTIONS request to detect problems
+ with the connection. */
+svn_error_t *
+svn_ra_serf__probe_proxy(svn_ra_serf__session_t *serf_sess,
+ apr_pool_t *scratch_pool);
+
+
/* On HTTPv2 connections, run an OPTIONS request over CONN to fetch the
current youngest revnum, returning it in *YOUNGEST.
Modified: subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/replay.c?rev=1501136&r1=1501135&r2=1501136&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/replay.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/replay.c Tue Jul 9 08:48:43 2013
@@ -29,6 +29,7 @@
#include "svn_pools.h"
#include "svn_ra.h"
#include "svn_dav.h"
+#include "svn_hash.h"
#include "svn_xml.h"
#include "../libsvn_ra/ra_loader.h"
#include "svn_config.h"
@@ -46,55 +47,92 @@
* This enum represents the current state of our XML parsing.
*/
typedef enum replay_state_e {
- NONE = 0,
- REPORT,
- OPEN_DIR,
- ADD_DIR,
- OPEN_FILE,
- ADD_FILE,
- DELETE_ENTRY,
- APPLY_TEXTDELTA,
- CHANGE_PROP
+ INITIAL = XML_STATE_INITIAL,
+
+ REPLAY_REPORT,
+ REPLAY_TARGET_REVISION,
+ REPLAY_OPEN_ROOT,
+ REPLAY_OPEN_DIRECTORY,
+ REPLAY_OPEN_FILE,
+ REPLAY_ADD_DIRECTORY,
+ REPLAY_ADD_FILE,
+ REPLAY_DELETE_ENTRY,
+ REPLAY_CLOSE_FILE,
+ REPLAY_CLOSE_DIRECTORY,
+ REPLAY_CHANGE_DIRECTORY_PROP,
+ REPLAY_CHANGE_FILE_PROP,
+ REPLAY_APPLY_TEXTDELTA,
} replay_state_e;
-typedef struct replay_info_t replay_info_t;
+#define S_ SVN_XML_NAMESPACE
+static const svn_ra_serf__xml_transition_t replay_ttable[] = {
+ { INITIAL, S_, "editor-report", REPLAY_REPORT,
+ FALSE, { NULL }, TRUE },
-struct replay_info_t {
- apr_pool_t *pool;
+ /* Replay just throws every operation as xml element directly
+ in the replay report, so we can't really use the nice exit
+ handling of the transition parser to handle clean callbacks */
- void *baton;
- svn_stream_t *stream;
+ { REPLAY_REPORT, S_, "target-revision", REPLAY_TARGET_REVISION,
+ FALSE, { "rev", NULL }, TRUE },
- replay_info_t *parent;
-};
+ { REPLAY_REPORT, S_, "open-root", REPLAY_OPEN_ROOT,
+ FALSE, { "rev", NULL }, TRUE },
-typedef svn_error_t *
-(*change_prop_t)(void *baton,
- const char *name,
- const svn_string_t *value,
- apr_pool_t *pool);
+ { REPLAY_REPORT, S_, "open-directory", REPLAY_OPEN_DIRECTORY,
+ FALSE, { "name", "rev", NULL }, TRUE },
-typedef struct prop_info_t {
- apr_pool_t *pool;
+ { REPLAY_REPORT, S_, "open-file", REPLAY_OPEN_FILE,
+ FALSE, { "name", "rev", NULL }, TRUE },
- change_prop_t change;
+ { REPLAY_REPORT, S_, "add-directory", REPLAY_ADD_DIRECTORY,
+ FALSE, { "name", "?copyfrom-path", "?copyfrom-rev", NULL}, TRUE },
- const char *name;
- svn_boolean_t del_prop;
+ { REPLAY_REPORT, S_, "add-file", REPLAY_ADD_FILE,
+ FALSE, { "name", "?copyfrom-path", "?copyfrom-rev", NULL}, TRUE },
- svn_stringbuf_t *prop_value;
+ { REPLAY_REPORT, S_, "delete-entry", REPLAY_DELETE_ENTRY,
+ FALSE, { "name", "rev", NULL }, TRUE },
- replay_info_t *parent;
-} prop_info_t;
+ { REPLAY_REPORT, S_, "close-file", REPLAY_CLOSE_FILE,
+ FALSE, { "?checksum", NULL }, TRUE },
-typedef struct replay_context_t {
- apr_pool_t *src_rev_pool;
- apr_pool_t *dst_rev_pool;
- /*file_pool is cleared after completion of each file. */
- apr_pool_t *file_pool;
+ { REPLAY_REPORT, S_, "close-directory", REPLAY_CLOSE_DIRECTORY,
+ FALSE, { NULL }, TRUE },
- /* Are we done fetching this file? */
- svn_boolean_t done;
+ { REPLAY_REPORT, S_, "change-dir-prop", REPLAY_CHANGE_DIRECTORY_PROP,
+ TRUE, { "name", "?del", NULL }, TRUE },
+
+ { REPLAY_REPORT, S_, "change-file-prop", REPLAY_CHANGE_FILE_PROP,
+ TRUE, { "name", "?del", NULL }, TRUE },
+
+ { REPLAY_REPORT, S_, "apply-textdelta", REPLAY_APPLY_TEXTDELTA,
+ FALSE, { "?checksum", NULL }, TRUE },
+
+ { 0 }
+};
+
+/* Per directory/file state */
+typedef struct replay_node_t {
+ apr_pool_t *pool; /* pool allocating this node's data */
+ svn_boolean_t file; /* file or dir */
+
+ void *baton; /* node baton */
+ svn_stream_t *stream; /* stream while handling txdata */
+
+ struct replay_node_t *parent; /* parent node or NULL */
+} replay_node_t;
+
+/* Per revision replay report state */
+typedef struct revision_report_t {
+ apr_pool_t *pool; /* per revision pool */
+
+ struct replay_node_t *current_node;
+ struct replay_node_t *root_node;
+
+ /* Are we done fetching this file?
+ Handles book-keeping in multi-report case */
+ svn_boolean_t *done;
svn_ra_serf__list_t **done_list;
svn_ra_serf__list_t done_item;
@@ -126,81 +164,33 @@ typedef struct replay_context_t {
apr_hash_t *revs_props;
apr_hash_t *props;
- /* Keep a reference to the XML parser ctx to report any errors. */
- svn_ra_serf__xml_parser_t *parser_ctx;
-
/* Handlers for the PROPFIND and REPORT for the current revision. */
svn_ra_serf__handler_t *propfind_handler;
svn_ra_serf__handler_t *report_handler;
-} replay_context_t;
-
-
-static void *
-push_state(svn_ra_serf__xml_parser_t *parser,
- replay_context_t *replay_ctx,
- replay_state_e state)
-{
- svn_ra_serf__xml_push_state(parser, state);
-
- if (state == OPEN_DIR || state == ADD_DIR ||
- state == OPEN_FILE || state == ADD_FILE)
- {
- replay_info_t *info;
-
- info = apr_palloc(replay_ctx->dst_rev_pool, sizeof(*info));
-
- info->pool = replay_ctx->dst_rev_pool;
- info->parent = parser->state->private;
- info->baton = NULL;
- info->stream = NULL;
-
- parser->state->private = info;
- }
- else if (state == CHANGE_PROP)
- {
- prop_info_t *info;
-
- info = apr_pcalloc(replay_ctx->dst_rev_pool, sizeof(*info));
-
- info->pool = replay_ctx->dst_rev_pool;
- info->parent = parser->state->private;
- info->prop_value = svn_stringbuf_create_empty(info->pool);
-
- parser->state->private = info;
- }
-
- return parser->state->private;
-}
+} revision_report_t;
+/* Conforms to svn_ra_serf__xml_opened_t */
static svn_error_t *
-start_replay(svn_ra_serf__xml_parser_t *parser,
- svn_ra_serf__dav_props_t name,
- const char **attrs,
- apr_pool_t *scratch_pool)
+replay_opened(svn_ra_serf__xml_estate_t *xes,
+ void *baton,
+ int entered_state,
+ const svn_ra_serf__dav_props_t *tag,
+ apr_pool_t *scratch_pool)
{
- replay_context_t *ctx = parser->user_data;
- replay_state_e state;
-
- state = parser->state->current_state;
+ struct revision_report_t *ctx = baton;
- if (state == NONE &&
- strcmp(name.name, "editor-report") == 0)
+ if (entered_state == REPLAY_REPORT)
{
- push_state(parser, ctx, REPORT);
-
/* Before we can continue, we need the revision properties. */
SVN_ERR_ASSERT(!ctx->propfind_handler || ctx->propfind_handler->done);
/* Create a pool for the commit editor. */
- ctx->dst_rev_pool = svn_pool_create(ctx->src_rev_pool);
- ctx->file_pool = svn_pool_create(ctx->dst_rev_pool);
-
SVN_ERR(svn_ra_serf__select_revprops(&ctx->props,
ctx->revprop_target,
ctx->revprop_rev,
ctx->revs_props,
- ctx->dst_rev_pool,
+ ctx->pool,
scratch_pool));
if (ctx->revstart_func)
@@ -208,382 +198,298 @@ start_replay(svn_ra_serf__xml_parser_t *
SVN_ERR(ctx->revstart_func(ctx->revision, ctx->replay_baton,
&ctx->editor, &ctx->editor_baton,
ctx->props,
- ctx->dst_rev_pool));
+ ctx->pool));
}
}
- else if (state == REPORT &&
- strcmp(name.name, "target-revision") == 0)
+ else if (entered_state == REPLAY_APPLY_TEXTDELTA)
{
- const char *rev;
-
- rev = svn_xml_get_attr_value("rev", attrs);
- if (!rev)
- {
- return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
- _("Missing revision attr in target-revision element"));
- }
-
- SVN_ERR(ctx->editor->set_target_revision(ctx->editor_baton,
- SVN_STR_TO_REV(rev),
- scratch_pool));
+ struct replay_node_t *node = ctx->current_node;
+ apr_hash_t *attrs;
+ const char *checksum;
+ svn_txdelta_window_handler_t handler;
+ void *handler_baton;
+
+ if (! node || ! node->file || node->stream)
+ return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL);
+
+ /* ### Is there a better way to access a specific attr here? */
+ attrs = svn_ra_serf__xml_gather_since(xes, REPLAY_APPLY_TEXTDELTA);
+ checksum = svn_hash_gets(attrs, "checksum");
+
+ SVN_ERR(ctx->editor->apply_textdelta(node->baton, checksum, node->pool,
+ &handler, &handler_baton));
+
+ if (handler != svn_delta_noop_window_handler)
+ {
+ node->stream = svn_base64_decode(
+ svn_txdelta_parse_svndiff(handler,
+ handler_baton,
+ TRUE,
+ node->pool),
+ node->pool);
+ }
}
- else if (state == REPORT &&
- strcmp(name.name, "open-root") == 0)
- {
- const char *rev;
- replay_info_t *info;
- rev = svn_xml_get_attr_value("rev", attrs);
-
- if (!rev)
- {
- return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
- _("Missing revision attr in open-root element"));
- }
+ return SVN_NO_ERROR;
+}
- info = push_state(parser, ctx, OPEN_DIR);
+/* Conforms to svn_ra_serf__xml_closed_t */
+static svn_error_t *
+replay_closed(svn_ra_serf__xml_estate_t *xes,
+ void *baton,
+ int leaving_state,
+ const svn_string_t *cdata,
+ apr_hash_t *attrs,
+ apr_pool_t *scratch_pool)
+{
+ struct revision_report_t *ctx = baton;
- SVN_ERR(ctx->editor->open_root(ctx->editor_baton,
- SVN_STR_TO_REV(rev),
- ctx->dst_rev_pool,
- &info->baton));
- }
- else if ((state == OPEN_DIR || state == ADD_DIR) &&
- strcmp(name.name, "delete-entry") == 0)
+ if (leaving_state == REPLAY_REPORT)
{
- const char *file_name, *rev;
- replay_info_t *info;
+ if (ctx->current_node)
+ return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL);
- file_name = svn_xml_get_attr_value("name", attrs);
- if (!file_name)
- {
- return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
- _("Missing name attr in delete-entry element"));
- }
- rev = svn_xml_get_attr_value("rev", attrs);
- if (!rev)
+ if (ctx->revfinish_func)
{
- return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
- _("Missing revision attr in delete-entry element"));
+ SVN_ERR(ctx->revfinish_func(ctx->revision, ctx->replay_baton,
+ ctx->editor, ctx->editor_baton,
+ ctx->props,
+ scratch_pool));
}
-
- info = push_state(parser, ctx, DELETE_ENTRY);
-
- SVN_ERR(ctx->editor->delete_entry(file_name, SVN_STR_TO_REV(rev),
- info->baton, scratch_pool));
-
- svn_ra_serf__xml_pop_state(parser);
}
- else if ((state == OPEN_DIR || state == ADD_DIR) &&
- strcmp(name.name, "open-directory") == 0)
+ else if (leaving_state == REPLAY_TARGET_REVISION)
{
- const char *rev, *dir_name;
- replay_info_t *info;
-
- dir_name = svn_xml_get_attr_value("name", attrs);
- if (!dir_name)
- {
- return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
- _("Missing name attr in open-directory element"));
- }
- rev = svn_xml_get_attr_value("rev", attrs);
- if (!rev)
- {
- return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
- _("Missing revision attr in open-directory element"));
- }
-
- info = push_state(parser, ctx, OPEN_DIR);
+ const char *revstr = svn_hash_gets(attrs, "rev");
+ apr_int64_t rev;
- SVN_ERR(ctx->editor->open_directory(dir_name, info->parent->baton,
- SVN_STR_TO_REV(rev),
- ctx->dst_rev_pool, &info->baton));
+ SVN_ERR(svn_cstring_atoi64(&rev, revstr));
+ SVN_ERR(ctx->editor->set_target_revision(ctx->editor_baton,
+ (svn_revnum_t)rev,
+ scratch_pool));
}
- else if ((state == OPEN_DIR || state == ADD_DIR) &&
- strcmp(name.name, "add-directory") == 0)
+ else if (leaving_state == REPLAY_OPEN_ROOT)
{
- const char *dir_name, *copyfrom, *copyrev;
- svn_revnum_t rev;
- replay_info_t *info;
+ const char *revstr = svn_hash_gets(attrs, "rev");
+ apr_int64_t rev;
+ apr_pool_t *root_pool = svn_pool_create(ctx->pool);
- dir_name = svn_xml_get_attr_value("name", attrs);
- if (!dir_name)
- {
- return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
- _("Missing name attr in add-directory element"));
- }
- copyfrom = svn_xml_get_attr_value("copyfrom-path", attrs);
- copyrev = svn_xml_get_attr_value("copyfrom-rev", attrs);
+ if (ctx->current_node || ctx->root_node)
+ return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL);
- if (copyrev)
- rev = SVN_STR_TO_REV(copyrev);
- else
- rev = SVN_INVALID_REVNUM;
+ ctx->root_node = apr_pcalloc(root_pool, sizeof(*ctx->root_node));
+ ctx->root_node->pool = root_pool;
- info = push_state(parser, ctx, ADD_DIR);
+ ctx->current_node = ctx->root_node;
- SVN_ERR(ctx->editor->add_directory(dir_name, info->parent->baton,
- copyfrom, rev,
- ctx->dst_rev_pool, &info->baton));
+ SVN_ERR(svn_cstring_atoi64(&rev, revstr));
+ SVN_ERR(ctx->editor->open_root(ctx->editor_baton, (svn_revnum_t)rev,
+ root_pool,
+ &ctx->current_node->baton));
}
- else if ((state == OPEN_DIR || state == ADD_DIR) &&
- strcmp(name.name, "close-directory") == 0)
+ else if (leaving_state == REPLAY_OPEN_DIRECTORY
+ || leaving_state == REPLAY_OPEN_FILE
+ || leaving_state == REPLAY_ADD_DIRECTORY
+ || leaving_state == REPLAY_ADD_FILE)
{
- replay_info_t *info = parser->state->private;
+ struct replay_node_t *node;
+ apr_pool_t *node_pool;
+ const char *name = svn_hash_gets(attrs, "name");
+ const char *rev_str;
+ apr_int64_t rev;
- SVN_ERR(ctx->editor->close_directory(info->baton, scratch_pool));
+ if (!ctx->current_node || ctx->current_node->file)
+ return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL);
- svn_ra_serf__xml_pop_state(parser);
- }
- else if ((state == OPEN_DIR || state == ADD_DIR) &&
- strcmp(name.name, "open-file") == 0)
- {
- const char *file_name, *rev;
- replay_info_t *info;
+ node_pool = svn_pool_create(ctx->current_node->pool);
+ node = apr_pcalloc(node_pool, sizeof(*node));
+ node->pool = node_pool;
+ node->parent = ctx->current_node;
- svn_pool_clear(ctx->file_pool);
- file_name = svn_xml_get_attr_value("name", attrs);
- if (!file_name)
+ if (leaving_state == REPLAY_OPEN_DIRECTORY
+ || leaving_state == REPLAY_OPEN_FILE)
{
- return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
- _("Missing name attr in open-file element"));
+ rev_str = svn_hash_gets(attrs, "rev");
}
- rev = svn_xml_get_attr_value("rev", attrs);
- if (!rev)
- {
- return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
- _("Missing revision attr in open-file element"));
- }
-
- info = push_state(parser, ctx, OPEN_FILE);
-
- SVN_ERR(ctx->editor->open_file(file_name, info->parent->baton,
- SVN_STR_TO_REV(rev),
- ctx->file_pool, &info->baton));
- }
- else if ((state == OPEN_DIR || state == ADD_DIR) &&
- strcmp(name.name, "add-file") == 0)
- {
- const char *file_name, *copyfrom, *copyrev;
- svn_revnum_t rev;
- replay_info_t *info;
-
- svn_pool_clear(ctx->file_pool);
- file_name = svn_xml_get_attr_value("name", attrs);
- if (!file_name)
- {
- return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
- _("Missing name attr in add-file element"));
- }
- copyfrom = svn_xml_get_attr_value("copyfrom-path", attrs);
- copyrev = svn_xml_get_attr_value("copyfrom-rev", attrs);
-
- info = push_state(parser, ctx, ADD_FILE);
+ else
+ rev_str = svn_hash_gets(attrs, "copyfrom-rev");
- if (copyrev)
- rev = SVN_STR_TO_REV(copyrev);
+ if (rev_str)
+ SVN_ERR(svn_cstring_atoi64(&rev, rev_str));
else
rev = SVN_INVALID_REVNUM;
- SVN_ERR(ctx->editor->add_file(file_name, info->parent->baton,
- copyfrom, rev,
- ctx->file_pool, &info->baton));
- }
- else if ((state == OPEN_FILE || state == ADD_FILE) &&
- strcmp(name.name, "apply-textdelta") == 0)
- {
- const char *checksum;
- replay_info_t *info;
- svn_txdelta_window_handler_t textdelta;
- void *textdelta_baton;
- svn_stream_t *delta_stream;
-
- info = push_state(parser, ctx, APPLY_TEXTDELTA);
-
- checksum = svn_xml_get_attr_value("checksum", attrs);
- if (checksum)
+ switch (leaving_state)
{
- checksum = apr_pstrdup(info->pool, checksum);
- }
-
- SVN_ERR(ctx->editor->apply_textdelta(info->baton, checksum,
- ctx->file_pool,
- &textdelta,
- &textdelta_baton));
-
- delta_stream = svn_txdelta_parse_svndiff(textdelta, textdelta_baton,
- TRUE, info->pool);
- info->stream = svn_base64_decode(delta_stream, info->pool);
- }
- else if ((state == OPEN_FILE || state == ADD_FILE) &&
- strcmp(name.name, "close-file") == 0)
- {
- replay_info_t *info = parser->state->private;
- const char *checksum;
+ case REPLAY_OPEN_DIRECTORY:
+ node->file = FALSE;
+ SVN_ERR(ctx->editor->open_directory(name,
+ ctx->current_node->baton,
+ (svn_revnum_t)rev,
+ node->pool,
+ &node->baton));
+ break;
+ case REPLAY_OPEN_FILE:
+ node->file = TRUE;
+ SVN_ERR(ctx->editor->open_file(name,
+ ctx->current_node->baton,
+ (svn_revnum_t)rev,
+ node->pool,
+ &node->baton));
+ break;
+ case REPLAY_ADD_DIRECTORY:
+ node->file = FALSE;
+ SVN_ERR(ctx->editor->add_directory(
+ name,
+ ctx->current_node->baton,
+ SVN_IS_VALID_REVNUM(rev)
+ ? svn_hash_gets(attrs, "copyfrom-path")
+ : NULL,
+ (svn_revnum_t)rev,
+ node->pool,
+ &node->baton));
+ break;
+ case REPLAY_ADD_FILE:
+ node->file = TRUE;
+ SVN_ERR(ctx->editor->add_file(
+ name,
+ ctx->current_node->baton,
+ SVN_IS_VALID_REVNUM(rev)
+ ? svn_hash_gets(attrs, "copyfrom-path")
+ : NULL,
+ (svn_revnum_t)rev,
+ node->pool,
+ &node->baton));
+ break;
+ /* default: unreachable */
+ }
+ ctx->current_node = node;
+ }
+ else if (leaving_state == REPLAY_CLOSE_FILE)
+ {
+ struct replay_node_t *node = ctx->current_node;
+
+ if (! node || ! node->file)
+ return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL);
+
+ SVN_ERR(ctx->editor->close_file(node->baton,
+ svn_hash_gets(attrs, "checksum"),
+ node->pool));
+ ctx->current_node = node->parent;
+ svn_pool_destroy(node->pool);
+ }
+ else if (leaving_state == REPLAY_CLOSE_DIRECTORY)
+ {
+ struct replay_node_t *node = ctx->current_node;
+
+ if (! node || node->file)
+ return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL);
+
+ SVN_ERR(ctx->editor->close_directory(node->baton, node->pool));
+ ctx->current_node = node->parent;
+ svn_pool_destroy(node->pool);
+ }
+ else if (leaving_state == REPLAY_DELETE_ENTRY)
+ {
+ struct replay_node_t *parent_node = ctx->current_node;
+ const char *name = svn_hash_gets(attrs, "name");
+ const char *revstr = svn_hash_gets(attrs, "rev");
+ apr_int64_t rev;
+
+ if (! parent_node || parent_node->file)
+ return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL);
+
+ SVN_ERR(svn_cstring_atoi64(&rev, revstr));
+ SVN_ERR(ctx->editor->delete_entry(name,
+ (svn_revnum_t)rev,
+ parent_node->baton,
+ scratch_pool));
+ }
+ else if (leaving_state == REPLAY_CHANGE_FILE_PROP
+ || leaving_state == REPLAY_CHANGE_DIRECTORY_PROP)
+ {
+ struct replay_node_t *node = ctx->current_node;
+ const char *name;
+ const svn_string_t *value;
- checksum = svn_xml_get_attr_value("checksum", attrs);
+ if (! node || node->file != (leaving_state == REPLAY_CHANGE_FILE_PROP))
+ return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL);
- SVN_ERR(ctx->editor->close_file(info->baton, checksum, scratch_pool));
+ name = svn_hash_gets(attrs, "name");
- svn_ra_serf__xml_pop_state(parser);
- }
- else if (((state == OPEN_FILE || state == ADD_FILE) &&
- strcmp(name.name, "change-file-prop") == 0) ||
- ((state == OPEN_DIR || state == ADD_DIR) &&
- strcmp(name.name, "change-dir-prop") == 0))
- {
- const char *prop_name;
- prop_info_t *info;
-
- prop_name = svn_xml_get_attr_value("name", attrs);
- if (!prop_name)
- {
- return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
- _("Missing name attr in %s element"),
- name.name);
- }
-
- info = push_state(parser, ctx, CHANGE_PROP);
-
-
- if (svn_xml_get_attr_value("del", attrs))
- info->del_prop = TRUE;
+ if (svn_hash_gets(attrs, "del"))
+ value = NULL;
else
- info->del_prop = FALSE;
+ value = svn_base64_decode_string(cdata, scratch_pool);
- if (state == OPEN_FILE || state == ADD_FILE)
+ if (node->file)
{
- info->name = apr_pstrdup(ctx->file_pool, prop_name);
- info->change = ctx->editor->change_file_prop;
+ SVN_ERR(ctx->editor->change_file_prop(node->baton, name, value,
+ scratch_pool));
}
else
{
- info->name = apr_pstrdup(ctx->dst_rev_pool, prop_name);
- info->change = ctx->editor->change_dir_prop;
+ SVN_ERR(ctx->editor->change_dir_prop(node->baton, name, value,
+ scratch_pool));
}
-
}
+ else if (leaving_state == REPLAY_APPLY_TEXTDELTA)
+ {
+ struct replay_node_t *node = ctx->current_node;
+
+ if (! node || ! node->file || ! node->stream)
+ return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL);
+
+ SVN_ERR(svn_stream_close(node->stream));
+ node->stream = NULL;
+ }
return SVN_NO_ERROR;
}
+/* Conforms to svn_ra_serf__xml_cdata_t */
static svn_error_t *
-end_replay(svn_ra_serf__xml_parser_t *parser,
- svn_ra_serf__dav_props_t name,
- apr_pool_t *scratch_pool)
+replay_cdata(svn_ra_serf__xml_estate_t *xes,
+ void *baton,
+ int current_state,
+ const char *data,
+ apr_size_t len,
+ apr_pool_t *scratch_pool)
{
- replay_context_t *ctx = parser->user_data;
- replay_state_e state;
+ struct revision_report_t *ctx = baton;
- state = parser->state->current_state;
-
- if (state == REPORT &&
- strcmp(name.name, "editor-report") == 0)
- {
- svn_ra_serf__xml_pop_state(parser);
- if (ctx->revfinish_func)
- {
- SVN_ERR(ctx->revfinish_func(ctx->revision, ctx->replay_baton,
- ctx->editor, ctx->editor_baton,
- ctx->props,
- ctx->dst_rev_pool));
- }
- svn_pool_destroy(ctx->dst_rev_pool);
- }
- else if (state == OPEN_DIR && strcmp(name.name, "open-directory") == 0)
- {
- /* Don't do anything. */
- }
- else if (state == ADD_DIR && strcmp(name.name, "add-directory") == 0)
- {
- /* Don't do anything. */
- }
- else if (state == OPEN_FILE && strcmp(name.name, "open-file") == 0)
- {
- /* Don't do anything. */
- }
- else if (state == ADD_FILE && strcmp(name.name, "add-file") == 0)
- {
- /* Don't do anything. */
- }
- else if ((state == OPEN_FILE || state == ADD_FILE) &&
- strcmp(name.name, "close-file") == 0)
- {
- /* Don't do anything. */
- }
- else if ((state == APPLY_TEXTDELTA) &&
- strcmp(name.name, "apply-textdelta") == 0)
+ if (current_state == REPLAY_APPLY_TEXTDELTA)
{
- replay_info_t *info = parser->state->private;
- SVN_ERR(svn_stream_close(info->stream));
- svn_ra_serf__xml_pop_state(parser);
- }
- else if (state == CHANGE_PROP &&
- (strcmp(name.name, "change-file-prop") == 0 ||
- strcmp(name.name, "change-dir-prop") == 0))
- {
- prop_info_t *info = parser->state->private;
- const svn_string_t *prop_val;
+ struct replay_node_t *node = ctx->current_node;
- if (info->del_prop)
- {
- prop_val = NULL;
- }
- else
- {
- const svn_string_t *morph;
+ if (! node || ! node->file)
+ return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL);
- morph = svn_stringbuf__morph_into_string(info->prop_value);
-#ifdef SVN_DEBUG
- info->prop_value = NULL; /* morph killed the stringbuf. */
-#endif
+ if (node->stream)
+ {
+ apr_size_t written = len;
- if (strcmp(name.name, "change-file-prop") == 0)
- prop_val = svn_base64_decode_string(morph, ctx->file_pool);
- else
- prop_val = svn_base64_decode_string(morph, ctx->dst_rev_pool);
+ SVN_ERR(svn_stream_write(node->stream, data, &written));
+ if (written != len)
+ return svn_error_create(SVN_ERR_STREAM_UNEXPECTED_EOF, NULL,
+ _("Error writing stream: unexpected EOF"));
}
-
- SVN_ERR(info->change(info->parent->baton, info->name, prop_val,
- info->parent->pool));
- svn_ra_serf__xml_pop_state(parser);
}
return SVN_NO_ERROR;
}
+/* Conforms to svn_ra_serf__xml_done_t */
static svn_error_t *
-cdata_replay(svn_ra_serf__xml_parser_t *parser,
- const char *data,
- apr_size_t len,
- apr_pool_t *scratch_pool)
+replay_done(void *baton,
+ apr_pool_t *scratch_pool)
{
- replay_context_t *replay_ctx = parser->user_data;
- replay_state_e state;
-
- UNUSED_CTX(replay_ctx);
+ struct revision_report_t *ctx = baton;
- state = parser->state->current_state;
+ *ctx->done = TRUE; /* Breaks out svn_ra_serf__context_run_wait */
- if (state == APPLY_TEXTDELTA)
- {
- replay_info_t *info = parser->state->private;
- apr_size_t written;
-
- written = len;
-
- SVN_ERR(svn_stream_write(info->stream, data, &written));
-
- if (written != len)
- return svn_error_create(SVN_ERR_STREAM_UNEXPECTED_EOF, NULL,
- _("Error writing stream: unexpected EOF"));
- }
- else if (state == CHANGE_PROP)
- {
- prop_info_t *info = parser->state->private;
-
- svn_stringbuf_appendbytes(info->prop_value, data, len);
- }
+ ctx->done_item.data = ctx;
+ ctx->done_item.next = *ctx->done_list;
+ *ctx->done_list = &ctx->done_item;
return SVN_NO_ERROR;
}
@@ -594,7 +500,7 @@ create_replay_body(serf_bucket_t **bkt,
serf_bucket_alloc_t *alloc,
apr_pool_t *pool)
{
- replay_context_t *ctx = baton;
+ struct revision_report_t *ctx = baton;
serf_bucket_t *body_bkt;
body_bkt = serf_bucket_aggregate_create(alloc);
@@ -617,17 +523,17 @@ create_replay_body(serf_bucket_t **bkt,
{
svn_ra_serf__add_tag_buckets(body_bkt,
"S:revision",
- apr_ltoa(ctx->src_rev_pool, ctx->revision),
+ apr_ltoa(pool, ctx->revision),
alloc);
}
svn_ra_serf__add_tag_buckets(body_bkt,
"S:low-water-mark",
- apr_ltoa(ctx->src_rev_pool, ctx->low_water_mark),
+ apr_ltoa(pool, ctx->low_water_mark),
alloc);
svn_ra_serf__add_tag_buckets(body_bkt,
"S:send-deltas",
- apr_ltoa(ctx->src_rev_pool, ctx->send_deltas),
+ apr_ltoa(pool, ctx->send_deltas),
alloc);
svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "S:replay-report");
@@ -643,57 +549,49 @@ svn_ra_serf__replay(svn_ra_session_t *ra
svn_boolean_t send_deltas,
const svn_delta_editor_t *editor,
void *edit_baton,
- apr_pool_t *pool)
+ apr_pool_t *scratch_pool)
{
- replay_context_t *replay_ctx;
+ struct revision_report_t ctx = { NULL };
svn_ra_serf__session_t *session = ra_session->priv;
svn_ra_serf__handler_t *handler;
- svn_ra_serf__xml_parser_t *parser_ctx;
+ svn_ra_serf__xml_context_t *xmlctx;
svn_error_t *err;
const char *report_target;
- SVN_ERR(svn_ra_serf__report_resource(&report_target, session, NULL, pool));
+ SVN_ERR(svn_ra_serf__report_resource(&report_target, session, NULL,
+ scratch_pool));
- replay_ctx = apr_pcalloc(pool, sizeof(*replay_ctx));
- replay_ctx->src_rev_pool = pool;
- replay_ctx->editor = editor;
- replay_ctx->editor_baton = edit_baton;
- replay_ctx->done = FALSE;
- replay_ctx->revision = revision;
- replay_ctx->low_water_mark = low_water_mark;
- replay_ctx->send_deltas = send_deltas;
- replay_ctx->revs_props = apr_hash_make(replay_ctx->src_rev_pool);
+ ctx.pool = svn_pool_create(scratch_pool);
+ ctx.editor = editor;
+ ctx.editor_baton = edit_baton;
+ ctx.done = FALSE;
+ ctx.revision = revision;
+ ctx.low_water_mark = low_water_mark;
+ ctx.send_deltas = send_deltas;
+ ctx.revs_props = apr_hash_make(scratch_pool);
+
+ xmlctx = svn_ra_serf__xml_context_create(replay_ttable,
+ replay_opened, replay_closed,
+ replay_cdata,
+ NULL,
+ &ctx,
+ scratch_pool);
- handler = apr_pcalloc(pool, sizeof(*handler));
+ handler = svn_ra_serf__create_expat_handler(xmlctx, NULL, scratch_pool);
- handler->handler_pool = pool;
handler->method = "REPORT";
handler->path = session->session_url.path;
handler->body_delegate = create_replay_body;
- handler->body_delegate_baton = replay_ctx;
+ handler->body_delegate_baton = &ctx;
handler->body_type = "text/xml";
handler->conn = session->conns[0];
handler->session = session;
- parser_ctx = apr_pcalloc(pool, sizeof(*parser_ctx));
-
- parser_ctx->pool = pool;
- parser_ctx->user_data = replay_ctx;
- parser_ctx->start = start_replay;
- parser_ctx->end = end_replay;
- parser_ctx->cdata = cdata_replay;
- parser_ctx->done = &replay_ctx->done;
-
- handler->response_handler = svn_ra_serf__handle_xml_parser;
- handler->response_baton = parser_ctx;
-
- /* This is only needed to handle errors during XML parsing. */
- replay_ctx->parser_ctx = parser_ctx;
- replay_ctx->report_handler = handler; /* unused */
+ ctx.report_handler = handler; /* unused */
svn_ra_serf__request_create(handler);
- err = svn_ra_serf__context_run_wait(&replay_ctx->done, session, pool);
+ err = svn_ra_serf__context_run_wait(&handler->done, session, scratch_pool);
SVN_ERR(svn_error_compose_create(
svn_ra_serf__error_on_status(handler->sline,
@@ -751,6 +649,8 @@ svn_ra_serf__replay_range(svn_ra_session
const char *report_target;
int active_reports = 0;
const char *include_path;
+ svn_boolean_t done;
+ svn_ra_serf__list_t *done_reports = NULL;
SVN_ERR(svn_ra_serf__report_resource(&report_target, session, NULL, pool));
@@ -785,10 +685,6 @@ svn_ra_serf__replay_range(svn_ra_session
while (active_reports || rev <= end_revision)
{
- svn_ra_serf__list_t *done_list;
- svn_ra_serf__list_t *done_reports = NULL;
- replay_context_t *replay_ctx;
-
if (session->cancel_func)
SVN_ERR(session->cancel_func(session->cancel_baton));
@@ -796,17 +692,19 @@ svn_ra_serf__replay_range(svn_ra_session
requests to MAX_OUTSTANDING_REQUESTS. */
if (rev <= end_revision && active_reports < MAX_OUTSTANDING_REQUESTS)
{
+ struct revision_report_t *replay_ctx;
svn_ra_serf__handler_t *handler;
- svn_ra_serf__xml_parser_t *parser_ctx;
apr_pool_t *ctx_pool = svn_pool_create(pool);
+ svn_ra_serf__xml_context_t *xmlctx;
const char *replay_target;
replay_ctx = apr_pcalloc(ctx_pool, sizeof(*replay_ctx));
- replay_ctx->src_rev_pool = ctx_pool;
+ replay_ctx->pool = ctx_pool;
replay_ctx->revstart_func = revstart_func;
replay_ctx->revfinish_func = revfinish_func;
replay_ctx->replay_baton = replay_baton;
- replay_ctx->done = FALSE;
+ replay_ctx->done = &done;
+ replay_ctx->done_list = &done_reports;
replay_ctx->include_path = include_path;
replay_ctx->revision = rev;
replay_ctx->low_water_mark = low_water_mark;
@@ -814,7 +712,7 @@ svn_ra_serf__replay_range(svn_ra_session
replay_ctx->done_item.data = replay_ctx;
/* Request all properties of a certain revision. */
- replay_ctx->revs_props = apr_hash_make(replay_ctx->src_rev_pool);
+ replay_ctx->revs_props = apr_hash_make(replay_ctx->pool);
if (SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(session))
{
@@ -835,7 +733,7 @@ svn_ra_serf__replay_range(svn_ra_session
replay_ctx->revprop_rev,
"0", all_props,
NULL,
- replay_ctx->src_rev_pool));
+ replay_ctx->pool));
/* Spin up the serf request for the PROPFIND. */
svn_ra_serf__request_create(replay_ctx->propfind_handler);
@@ -851,9 +749,14 @@ svn_ra_serf__replay_range(svn_ra_session
replay_target = session->session_url.path;
}
- handler = apr_pcalloc(replay_ctx->src_rev_pool, sizeof(*handler));
+ xmlctx = svn_ra_serf__xml_context_create(replay_ttable,
+ replay_opened, replay_closed,
+ replay_cdata, replay_done,
+ replay_ctx,
+ ctx_pool);
+
+ handler = svn_ra_serf__create_expat_handler(xmlctx, NULL, ctx_pool);
- handler->handler_pool = replay_ctx->src_rev_pool;
handler->method = "REPORT";
handler->path = replay_target;
handler->body_delegate = create_replay_body;
@@ -861,31 +764,7 @@ svn_ra_serf__replay_range(svn_ra_session
handler->conn = session->conns[0];
handler->session = session;
- parser_ctx = apr_pcalloc(replay_ctx->src_rev_pool,
- sizeof(*parser_ctx));
-
- /* Setup the XML parser context.
- Because we have not one but a list of requests, the 'done' property
- on the replay_ctx is not of much use. Instead, use 'done_list'.
- On each handled response (succesfully or not), the parser will add
- done_item to done_list, so by keeping track of the state of
- done_list we know how many requests have been handled completely.
- */
- parser_ctx->pool = replay_ctx->src_rev_pool;
- parser_ctx->user_data = replay_ctx;
- parser_ctx->start = start_replay;
- parser_ctx->end = end_replay;
- parser_ctx->cdata = cdata_replay;
- parser_ctx->done = &replay_ctx->done;
- parser_ctx->done_list = &done_reports;
- parser_ctx->done_item = &replay_ctx->done_item;
- handler->response_handler = svn_ra_serf__handle_xml_parser;
- handler->response_baton = parser_ctx;
replay_ctx->report_handler = handler;
-
- /* This is only needed to handle errors during XML parsing. */
- replay_ctx->parser_ctx = parser_ctx;
-
svn_ra_serf__request_create(handler);
rev++;
@@ -893,26 +772,32 @@ svn_ra_serf__replay_range(svn_ra_session
}
/* Run the serf loop. */
- SVN_ERR(svn_ra_serf__context_run_wait(&replay_ctx->done, session, pool));
+ SVN_ERR(svn_ra_serf__context_run_wait(&done, session, pool));
/* Substract the number of completely handled responses from our
total nr. of open requests', so we'll know when to stop this loop.
Since the message is completely handled, we can destroy its pool. */
- done_list = done_reports;
- while (done_list)
- {
- replay_context_t *ctx = (replay_context_t *)done_list->data;
- svn_ra_serf__handler_t *done_handler = ctx->report_handler;
+ {
+ svn_ra_serf__list_t *done_list;
- done_list = done_list->next;
- SVN_ERR(svn_ra_serf__error_on_status(done_handler->sline,
- done_handler->path,
- done_handler->location));
- svn_pool_destroy(ctx->src_rev_pool);
- active_reports--;
- }
+ done_list = done_reports;
+
+ done = FALSE;
+ done_reports = NULL;
- done_reports = NULL;
+ while (done_list)
+ {
+ revision_report_t *ctx = (revision_report_t *)done_list->data;
+ svn_ra_serf__handler_t *done_handler = ctx->report_handler;
+
+ done_list = done_list->next;
+ SVN_ERR(svn_ra_serf__error_on_status(done_handler->sline,
+ done_handler->path,
+ done_handler->location));
+ svn_pool_clear(ctx->pool);
+ active_reports--;
+ }
+ }
}
return SVN_NO_ERROR;
Modified: subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/serf.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/serf.c?rev=1501136&r1=1501135&r2=1501136&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_ra_serf/serf.c Tue Jul 9 08:48:43 2013
@@ -225,6 +225,12 @@ load_config(svn_ra_serf__session_t *sess
SVN_CONFIG_OPTION_HTTP_MAX_CONNECTIONS,
SVN_CONFIG_DEFAULT_OPTION_HTTP_MAX_CONNECTIONS));
+ /* Is this proxy potentially busted? Do we need to take special care? */
+ SVN_ERR(svn_config_get_bool(config, &session->busted_proxy,
+ SVN_CONFIG_SECTION_GLOBAL,
+ SVN_CONFIG_OPTION_BUSTED_PROXY,
+ FALSE));
+
if (config)
server_group = svn_config_find_group(config,
session->session_url.hostname,
@@ -281,6 +287,13 @@ load_config(svn_ra_serf__session_t *sess
server_group,
SVN_CONFIG_OPTION_HTTP_MAX_CONNECTIONS,
session->max_connections));
+
+ /* Do we need to take care with this proxy? */
+ SVN_ERR(svn_config_get_bool(
+ config, &session->busted_proxy,
+ server_group,
+ SVN_CONFIG_OPTION_BUSTED_PROXY,
+ session->busted_proxy));
}
/* Don't allow the http-max-connections value to be larger than our
@@ -392,6 +405,7 @@ svn_ra_serf__open(svn_ra_session_t *sess
svn_ra_serf__session_t *serf_sess;
apr_uri_t url;
const char *client_string = NULL;
+ svn_error_t *err;
if (corrected_url)
*corrected_url = NULL;
@@ -441,6 +455,10 @@ svn_ra_serf__open(svn_ra_session_t *sess
HTTP/1.1 is supported, we can upgrade. */
serf_sess->http10 = TRUE;
+ /* If we switch to HTTP/1.1, then we will use chunked requests. We may disable
+ this, if we find an intervening proxy does not support chunked requests. */
+ serf_sess->using_chunked_requests = TRUE;
+
SVN_ERR(load_config(serf_sess, config, serf_sess->pool));
serf_sess->conns[0] = apr_pcalloc(serf_sess->pool,
@@ -479,7 +497,23 @@ svn_ra_serf__open(svn_ra_session_t *sess
session->priv = serf_sess;
- return svn_ra_serf__exchange_capabilities(serf_sess, corrected_url, pool);
+ err = svn_ra_serf__exchange_capabilities(serf_sess, corrected_url, pool);
+
+ /* serf should produce a usable error code instead of APR_EGENERAL */
+ if (err && err->apr_err == APR_EGENERAL)
+ err = svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, err,
+ _("Connection to '%s' failed"), session_URL);
+ SVN_ERR(err);
+
+ /* We have set up a useful connection (that doesn't indication a redirect).
+ If we've been told there is possibly a busted proxy in our path to the
+ server AND we switched to HTTP/1.1 (chunked requests), then probe for
+ problems in any proxy. */
+ if ((corrected_url == NULL || *corrected_url == NULL)
+ && serf_sess->busted_proxy && !serf_sess->http10)
+ SVN_ERR(svn_ra_serf__probe_proxy(serf_sess, pool));
+
+ return SVN_NO_ERROR;
}
/* Implements svn_ra__vtable_t.reparent(). */