You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2014/01/15 18:47:24 UTC
svn commit: r1558485 [4/4] - in /subversion/branches/fsfs-ucsnorm: ./
subversion/bindings/javahl/native/
subversion/bindings/javahl/native/jniwrapper/
subversion/bindings/javahl/src/org/apache/subversion/javahl/
subversion/bindings/javahl/tests/org/apa...
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/util.c?rev=1558485&r1=1558484&r2=1558485&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/util.c Wed Jan 15 17:47:23 2014
@@ -33,64 +33,21 @@
#include <serf.h>
#include <serf_bucket_types.h>
-#include <expat.h>
-
#include "svn_private_config.h"
#include "svn_hash.h"
#include "svn_dirent_uri.h"
#include "svn_path.h"
#include "svn_string.h"
-#include "svn_xml.h"
#include "svn_props.h"
#include "svn_dirent_uri.h"
#include "../libsvn_ra/ra_loader.h"
#include "private/svn_dep_compat.h"
#include "private/svn_fspath.h"
-#include "private/svn_subr_private.h"
#include "private/svn_auth_private.h"
#include "ra_serf.h"
-
-/* Fix for older expat 1.95.x's that do not define
- * XML_STATUS_OK/XML_STATUS_ERROR
- */
-#ifndef XML_STATUS_OK
-#define XML_STATUS_OK 1
-#define XML_STATUS_ERROR 0
-#endif
-
-#ifndef XML_VERSION_AT_LEAST
-#define XML_VERSION_AT_LEAST(major,minor,patch) \
-(((major) < XML_MAJOR_VERSION) \
- || ((major) == XML_MAJOR_VERSION && (minor) < XML_MINOR_VERSION) \
- || ((major) == XML_MAJOR_VERSION && (minor) == XML_MINOR_VERSION && \
- (patch) <= XML_MICRO_VERSION))
-#endif /* APR_VERSION_AT_LEAST */
-
-#if XML_VERSION_AT_LEAST(1, 95, 8)
-#define EXPAT_HAS_STOPPARSER
-#endif
-
-/* Read/write chunks of this size into the spillbuf. */
-#define PARSE_CHUNK_SIZE 8000
-
-
-struct expat_ctx_t {
- svn_ra_serf__xml_context_t *xmlctx;
- XML_Parser parser;
- svn_ra_serf__handler_t *handler;
- const int *expected_status;
-
- svn_error_t *inner_error;
-
- /* Do not use this pool for allocation. It is merely recorded for running
- the cleanup handler. */
- apr_pool_t *cleanup_pool;
-};
-
-
static const apr_uint32_t serf_failure_map[][2] =
{
{ SERF_SSL_CERT_NOTYETVALID, SVN_AUTH_SSL_NOTYETVALID },
@@ -973,23 +930,6 @@ svn_ra_serf__context_run_one(svn_ra_serf
/* Wait until the response logic marks its DONE status. */
err = svn_ra_serf__context_run_wait(&handler->done, handler->session,
scratch_pool);
-
- /* A callback invocation has been canceled. In this simple case of
- context_run_one, we can keep the ra-session operational by resetting
- the connection.
-
- If we don't do this, the next context run will notice that the connection
- is still in the error state and will just return SVN_ERR_CEASE_INVOCATION
- (=the last error for the connection) again */
- if (err && err->apr_err == SVN_ERR_CEASE_INVOCATION)
- {
- apr_status_t status = serf_connection_reset(handler->conn->conn);
-
- if (status)
- err = svn_error_compose_create(err,
- svn_ra_serf__wrap_err(status, NULL));
- }
-
return svn_error_trace(err);
}
@@ -1136,215 +1076,6 @@ svn_ra_serf__expect_empty_body(serf_requ
return SVN_NO_ERROR;
}
-/* Conforms to Expat's XML_StartElementHandler */
-static void
-start_xml(void *userData, const char *raw_name, const char **attrs)
-{
- svn_ra_serf__xml_parser_t *parser = userData;
- svn_ra_serf__dav_props_t name;
- apr_pool_t *scratch_pool;
- svn_error_t *err;
-
- if (parser->error)
- return;
-
- if (!parser->state)
- svn_ra_serf__xml_push_state(parser, 0);
-
- /* ### get a real scratch_pool */
- scratch_pool = parser->state->pool;
-
- svn_ra_serf__define_ns(&parser->state->ns_list, attrs, parser->state->pool);
-
- svn_ra_serf__expand_ns(&name, parser->state->ns_list, raw_name);
-
- err = parser->start(parser, name, attrs, scratch_pool);
- if (err && !SERF_BUCKET_READ_ERROR(err->apr_err))
- err = svn_error_create(SVN_ERR_RA_SERF_WRAPPED_ERROR, err, NULL);
-
- parser->error = err;
-}
-
-
-/* Conforms to Expat's XML_EndElementHandler */
-static void
-end_xml(void *userData, const char *raw_name)
-{
- svn_ra_serf__xml_parser_t *parser = userData;
- svn_ra_serf__dav_props_t name;
- svn_error_t *err;
- apr_pool_t *scratch_pool;
-
- if (parser->error)
- return;
-
- /* ### get a real scratch_pool */
- scratch_pool = parser->state->pool;
-
- svn_ra_serf__expand_ns(&name, parser->state->ns_list, raw_name);
-
- err = parser->end(parser, name, scratch_pool);
- if (err && !SERF_BUCKET_READ_ERROR(err->apr_err))
- err = svn_error_create(SVN_ERR_RA_SERF_WRAPPED_ERROR, err, NULL);
-
- parser->error = err;
-}
-
-
-/* Conforms to Expat's XML_CharacterDataHandler */
-static void
-cdata_xml(void *userData, const char *data, int len)
-{
- svn_ra_serf__xml_parser_t *parser = userData;
- svn_error_t *err;
- apr_pool_t *scratch_pool;
-
- if (parser->error)
- return;
-
- if (!parser->state)
- svn_ra_serf__xml_push_state(parser, 0);
-
- /* ### get a real scratch_pool */
- scratch_pool = parser->state->pool;
-
- err = parser->cdata(parser, data, len, scratch_pool);
- if (err && !SERF_BUCKET_READ_ERROR(err->apr_err))
- err = svn_error_create(SVN_ERR_RA_SERF_WRAPPED_ERROR, err, NULL);
-
- parser->error = err;
-}
-
-/* Flip the requisite bits in CTX to indicate that processing of the
- response is complete, adding the current "done item" to the list of
- completed items. */
-static void
-add_done_item(svn_ra_serf__xml_parser_t *ctx)
-{
- /* Make sure we don't add to DONE_LIST twice. */
- if (!*ctx->done)
- {
- *ctx->done = TRUE;
- if (ctx->done_list)
- {
- ctx->done_item->data = ctx->user_data;
- ctx->done_item->next = *ctx->done_list;
- *ctx->done_list = ctx->done_item;
- }
- }
-}
-
-
-/* svn_error_t * wrapper around XML_Parse */
-static APR_INLINE svn_error_t *
-parse_xml(XML_Parser parser, const char *data, apr_size_t len, svn_boolean_t is_final)
-{
- int xml_status = XML_Parse(parser, data, (int)len, is_final);
- const char *msg;
-
- if (xml_status == XML_STATUS_OK)
- return SVN_NO_ERROR;
-
- msg = XML_ErrorString(XML_GetErrorCode(parser));
-
- return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA,
- svn_error_createf(SVN_ERR_XML_MALFORMED, NULL,
- _("Malformed XML: %s"),
- msg),
- _("The XML response contains invalid XML"));
-}
-
-/* Apr pool cleanup handler to release an XML_Parser in success and error
- conditions */
-static apr_status_t
-xml_parser_cleanup(void *baton)
-{
- XML_Parser *xmlp = baton;
-
- if (*xmlp)
- {
- (void) XML_ParserFree(*xmlp);
- *xmlp = NULL;
- }
-
- return APR_SUCCESS;
-}
-
-/* Implements svn_ra_serf__response_handler_t */
-svn_error_t *
-svn_ra_serf__handle_xml_parser(serf_request_t *request,
- serf_bucket_t *response,
- void *baton,
- apr_pool_t *pool)
-{
- apr_status_t status;
- svn_ra_serf__xml_parser_t *ctx = baton;
- svn_error_t *err;
-
- if (!ctx->xmlp)
- {
- ctx->xmlp = XML_ParserCreate(NULL);
- apr_pool_cleanup_register(ctx->pool, &ctx->xmlp, xml_parser_cleanup,
- apr_pool_cleanup_null);
- XML_SetUserData(ctx->xmlp, ctx);
- XML_SetElementHandler(ctx->xmlp, start_xml, end_xml);
- if (ctx->cdata)
- {
- XML_SetCharacterDataHandler(ctx->xmlp, cdata_xml);
- }
- }
-
- while (1)
- {
- const char *data;
- apr_size_t len;
-
- status = serf_bucket_read(response, PARSE_CHUNK_SIZE, &data, &len);
- if (SERF_BUCKET_READ_ERROR(status))
- {
- return svn_ra_serf__wrap_err(status, NULL);
- }
-
- err = parse_xml(ctx->xmlp, data, len, FALSE);
-
- err = svn_error_compose_create(ctx->error, err);
-
- if (err)
- {
- SVN_ERR_ASSERT(ctx->xmlp != NULL);
-
- apr_pool_cleanup_run(ctx->pool, &ctx->xmlp, xml_parser_cleanup);
- add_done_item(ctx);
- return svn_error_trace(err);
- }
-
- if (APR_STATUS_IS_EAGAIN(status))
- {
- return svn_ra_serf__wrap_err(status, NULL);
- }
-
- if (APR_STATUS_IS_EOF(status))
- {
- SVN_ERR_ASSERT(ctx->xmlp != NULL);
-
- err = parse_xml(ctx->xmlp, NULL, 0, TRUE);
-
- err = svn_error_compose_create(ctx->error, err);
-
- apr_pool_cleanup_run(ctx->pool, &ctx->xmlp, xml_parser_cleanup);
-
- SVN_ERR(err);
-
- add_done_item(ctx);
-
- return svn_ra_serf__wrap_err(status, NULL);
- }
-
- /* feed me! */
- }
- /* not reached */
-}
-
apr_status_t
svn_ra_serf__credentials_callback(char **username, char **password,
@@ -1452,6 +1183,8 @@ handle_response(serf_request_t *request,
if (!response)
{
/* Uh-oh. Our connection died. */
+ handler->scheduled = FALSE;
+
if (handler->response_error)
{
/* Give a handler chance to prevent request requeue. */
@@ -1673,10 +1406,14 @@ handle_response_cb(serf_request_t *reque
/* Make sure the DONE flag is set properly and requests are cleaned up. */
if (APR_STATUS_IS_EOF(outer_status) || APR_STATUS_IS_EOF(inner_status))
{
+ svn_ra_serf__session_t *sess = handler->session;
handler->done = TRUE;
+ handler->scheduled = FALSE;
outer_status = APR_EOF;
- save_error(handler->session,
+ /* We use a cached handler->session here to allow handler to free the
+ memory containing the handler */
+ save_error(sess,
handler->done_delegate(request, handler->done_delegate_baton,
scratch_pool));
}
@@ -1685,7 +1422,8 @@ handle_response_cb(serf_request_t *reque
{
handler->discard_body = TRUE; /* Discard further data */
handler->done = TRUE; /* Mark as done */
- return APR_EAGAIN; /* Exit context loop */
+ handler->scheduled = FALSE;
+ outer_status = APR_EAGAIN; /* Exit context loop */
}
return outer_status;
@@ -1787,24 +1525,29 @@ setup_request_cb(serf_request_t *request
void
svn_ra_serf__request_create(svn_ra_serf__handler_t *handler)
{
- SVN_ERR_ASSERT_NO_RETURN(handler->handler_pool != NULL);
-
- /* In case HANDLER is re-queued, reset the various transient fields.
+ SVN_ERR_ASSERT_NO_RETURN(handler->handler_pool != NULL
+ && !handler->scheduled);
- ### prior to recent changes, HANDLER was constant. maybe we should
- ### break out these processing fields, apart from the request
- ### definition. */
+ /* In case HANDLER is re-queued, reset the various transient fields. */
handler->done = FALSE;
handler->server_error = NULL;
handler->sline.version = 0;
handler->location = NULL;
handler->reading_body = FALSE;
handler->discard_body = FALSE;
+ handler->scheduled = TRUE;
+
+ /* Keeping track of the returned request object would be nice, but doesn't
+ work the way we would expect in ra_serf..
+
+ Serf sometimes creates a new request for us (and destroys the old one)
+ without telling, like when authentication failed (401/407 response.
- /* ### do we ever alter the >response_handler? */
+ We 'just' trust serf to do the right thing and expect it to tell us
+ when the state of the request changes.
- /* ### do we need to hold onto the returned request object, or just
- ### not worry about it (the serf ctx will manage it). */
+ ### I fixed a request leak in serf in r2258 on auth failures.
+ */
(void) serf_connection_request_create(handler->conn->conn,
setup_request_cb, handler);
}
@@ -2072,181 +1815,6 @@ svn_ra_serf__register_editor_shim_callba
return SVN_NO_ERROR;
}
-
-/* Conforms to Expat's XML_StartElementHandler */
-static void
-expat_start(void *userData, const char *raw_name, const char **attrs)
-{
- struct expat_ctx_t *ectx = userData;
-
- if (ectx->inner_error != NULL)
- return;
-
- ectx->inner_error = svn_error_trace(
- svn_ra_serf__xml_cb_start(ectx->xmlctx,
- raw_name, attrs));
-
-#ifdef EXPAT_HAS_STOPPARSER
- if (ectx->inner_error)
- (void) XML_StopParser(ectx->parser, 0 /* resumable */);
-#endif
-}
-
-
-/* Conforms to Expat's XML_EndElementHandler */
-static void
-expat_end(void *userData, const char *raw_name)
-{
- struct expat_ctx_t *ectx = userData;
-
- if (ectx->inner_error != NULL)
- return;
-
- ectx->inner_error = svn_error_trace(
- svn_ra_serf__xml_cb_end(ectx->xmlctx, raw_name));
-
-#ifdef EXPAT_HAS_STOPPARSER
- if (ectx->inner_error)
- (void) XML_StopParser(ectx->parser, 0 /* resumable */);
-#endif
-}
-
-
-/* Conforms to Expat's XML_CharacterDataHandler */
-static void
-expat_cdata(void *userData, const char *data, int len)
-{
- struct expat_ctx_t *ectx = userData;
-
- if (ectx->inner_error != NULL)
- return;
-
- ectx->inner_error = svn_error_trace(
- svn_ra_serf__xml_cb_cdata(ectx->xmlctx, data, len));
-
-#ifdef EXPAT_HAS_STOPPARSER
- if (ectx->inner_error)
- (void) XML_StopParser(ectx->parser, 0 /* resumable */);
-#endif
-}
-
-
-/* Implements svn_ra_serf__response_handler_t */
-static svn_error_t *
-expat_response_handler(serf_request_t *request,
- serf_bucket_t *response,
- void *baton,
- apr_pool_t *scratch_pool)
-{
- struct expat_ctx_t *ectx = baton;
- svn_boolean_t got_expected_status;
-
- if (ectx->expected_status)
- {
- const int *status = ectx->expected_status;
- got_expected_status = FALSE;
-
- while (*status && ectx->handler->sline.code != *status)
- status++;
-
- got_expected_status = (*status) != 0;
- }
- else
- got_expected_status = (ectx->handler->sline.code == 200);
-
- if (!ectx->handler->server_error
- && ((ectx->handler->sline.code < 200) || (ectx->handler->sline.code >= 300)
- || ! got_expected_status))
- {
- /* By deferring to expect_empty_body(), it will make a choice on
- how to handle the body. Whatever the decision, the core handler
- will take over, and we will not be called again. */
-
- /* ### This handles xml bodies as svn-errors (returned via serf context
- ### loop), but ignores non-xml errors.
-
- Current code depends on this behavior and checks itself while other
- continues, and then verifies if work has been performed.
-
- ### TODO: Make error checking consistent */
-
- /* ### If !GOT_EXPECTED_STATUS, this should always produce an error */
- return svn_error_trace(svn_ra_serf__expect_empty_body(
- request, response, ectx->handler,
- scratch_pool));
- }
-
- 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);
- }
-
- while (1)
- {
- apr_status_t status;
- const char *data;
- apr_size_t len;
- svn_error_t *err;
- svn_boolean_t at_eof = FALSE;
-
- status = serf_bucket_read(response, PARSE_CHUNK_SIZE, &data, &len);
- if (SERF_BUCKET_READ_ERROR(status))
- return svn_ra_serf__wrap_err(status, NULL);
- else if (APR_STATUS_IS_EOF(status))
- at_eof = TRUE;
-
-#if 0
- /* ### move restart/skip into the core handler */
- ectx->handler->read_size += len;
-#endif
-
- /* ### move PAUSED behavior to a new response handler that can feed
- ### an inner handler, or can pause for a while. */
-
- /* ### should we have an IGNORE_ERRORS flag like the v1 parser? */
-
- err = parse_xml(ectx->parser, data, len, at_eof /* isFinal */);
-
- err = svn_error_compose_create(ectx->inner_error, err);
-
- if (at_eof || err)
- {
- /* Release xml parser state/tables. */
- apr_pool_cleanup_run(ectx->cleanup_pool, &ectx->parser,
- xml_parser_cleanup);
- }
-
- /* 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. */
- SVN_ERR(err);
-
- /* The parsing went fine. What has the bucket told us? */
-
- if (at_eof)
- {
- /* Make sure we actually got xml and clean up after parsing */
- SVN_ERR(svn_ra_serf__xml_context_done(ectx->xmlctx));
- }
-
- if (status && !SERF_BUCKET_READ_ERROR(status))
- {
- return svn_ra_serf__wrap_err(status, NULL);
- }
- }
-
- /* NOTREACHED */
-}
-
/* Shandard done_delegate handler */
static svn_error_t *
response_done(serf_request_t *request,
@@ -2273,6 +1841,27 @@ response_done(serf_request_t *request,
return SVN_NO_ERROR;
}
+/* Pool cleanup handler for request handlers.
+
+ If a serf context run stops for some outside error, like when the user
+ cancels a request via ^C in the context loop, the handler is still
+ registered in the serf context. With the pool cleanup there would be
+ handlers registered in no freed memory.
+
+ This fallback kills the connection for this case, which will make serf
+ unregister any*/
+static apr_status_t
+handler_cleanup(void *baton)
+{
+ svn_ra_serf__handler_t *handler = baton;
+ if (handler->scheduled && handler->conn)
+ {
+ serf_connection_reset(handler->conn->conn);
+ }
+
+ return APR_SUCCESS;
+}
+
svn_ra_serf__handler_t *
svn_ra_serf__create_handler(apr_pool_t *result_pool)
{
@@ -2281,6 +1870,9 @@ svn_ra_serf__create_handler(apr_pool_t *
handler = apr_pcalloc(result_pool, sizeof(*handler));
handler->handler_pool = result_pool;
+ apr_pool_cleanup_register(result_pool, handler, handler_cleanup,
+ apr_pool_cleanup_null);
+
/* Setup the default done handler, to handle server errors */
handler->done_delegate_baton = handler;
handler->done_delegate = response_done;
@@ -2288,27 +1880,3 @@ svn_ra_serf__create_handler(apr_pool_t *
return handler;
}
-
-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)
-{
- svn_ra_serf__handler_t *handler;
- struct expat_ctx_t *ectx;
-
- ectx = apr_pcalloc(result_pool, sizeof(*ectx));
- ectx->xmlctx = xmlctx;
- ectx->parser = NULL;
- ectx->expected_status = expected_status;
- ectx->cleanup_pool = result_pool;
-
-
- handler = svn_ra_serf__create_handler(result_pool);
- handler->response_handler = expat_response_handler;
- handler->response_baton = ectx;
-
- ectx->handler = handler;
-
- return handler;
-}
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/xml.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/xml.c?rev=1558485&r1=1558484&r2=1558485&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/xml.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/xml.c Wed Jan 15 17:47:23 2014
@@ -24,6 +24,7 @@
#include <apr_uri.h>
+#include <expat.h>
#include <serf.h>
#include "svn_private_config.h"
@@ -42,6 +43,30 @@
#include "ra_serf.h"
+/* Fix for older expat 1.95.x's that do not define
+ * XML_STATUS_OK/XML_STATUS_ERROR
+ */
+#ifndef XML_STATUS_OK
+#define XML_STATUS_OK 1
+#define XML_STATUS_ERROR 0
+#endif
+
+#ifndef XML_VERSION_AT_LEAST
+#define XML_VERSION_AT_LEAST(major,minor,patch) \
+(((major) < XML_MAJOR_VERSION) \
+ || ((major) == XML_MAJOR_VERSION && (minor) < XML_MINOR_VERSION) \
+ || ((major) == XML_MAJOR_VERSION && (minor) == XML_MINOR_VERSION && \
+ (patch) <= XML_MICRO_VERSION))
+#endif /* APR_VERSION_AT_LEAST */
+
+#if XML_VERSION_AT_LEAST(1, 95, 8)
+#define EXPAT_HAS_STOPPARSER
+#endif
+
+/* Read/write chunks of this size into the spillbuf. */
+#define PARSE_CHUNK_SIZE 8000
+
+
struct svn_ra_serf__xml_context_t {
/* Current state information. */
svn_ra_serf__xml_estate_t *current;
@@ -85,6 +110,16 @@ struct svn_ra_serf__xml_context_t {
};
+/* Structure which represents an XML namespace. */
+typedef struct svn_ra_serf__ns_t {
+ /* The assigned name. */
+ const char *xmlns;
+ /* The full URL for this namespace. */
+ const char *url;
+ /* The next namespace in our list. */
+ struct svn_ra_serf__ns_t *next;
+} svn_ra_serf__ns_t;
+
struct svn_ra_serf__xml_estate_t {
/* The current state value. */
int state;
@@ -116,6 +151,19 @@ struct svn_ra_serf__xml_estate_t {
};
+struct expat_ctx_t {
+ svn_ra_serf__xml_context_t *xmlctx;
+ XML_Parser parser;
+ svn_ra_serf__handler_t *handler;
+ const int *expected_status;
+
+ svn_error_t *inner_error;
+
+ /* Do not use this pool for allocation. It is merely recorded for running
+ the cleanup handler. */
+ apr_pool_t *cleanup_pool;
+};
+
static void
define_namespaces(svn_ra_serf__ns_t **ns_list,
@@ -172,22 +220,15 @@ define_namespaces(svn_ra_serf__ns_t **ns
}
}
-
-void
-svn_ra_serf__define_ns(svn_ra_serf__ns_t **ns_list,
- const char *const *attrs,
- apr_pool_t *result_pool)
-{
- define_namespaces(ns_list, attrs, NULL /* get_pool */, result_pool);
-}
-
-
/*
- * Look up NAME in the NS_LIST list for previously declared namespace
- * definitions and return a DAV_PROPS_T-tuple that has values.
+ * Look up @a name in the @a ns_list list for previously declared namespace
+ * definitions.
+ *
+ * Return (in @a *returned_prop_name) a #svn_ra_serf__dav_props_t tuple
+ * representing the expanded name.
*/
-void
-svn_ra_serf__expand_ns(svn_ra_serf__dav_props_t *returned_prop_name,
+static void
+expand_ns(svn_ra_serf__dav_props_t *returned_prop_name,
const svn_ra_serf__ns_t *ns_list,
const char *name)
{
@@ -381,54 +422,6 @@ void svn_ra_serf__add_tag_buckets(serf_b
svn_ra_serf__add_close_tag_buckets(agg_bucket, bkt_alloc, tag);
}
-void
-svn_ra_serf__xml_push_state(svn_ra_serf__xml_parser_t *parser,
- int state)
-{
- svn_ra_serf__xml_state_t *new_state;
-
- if (!parser->free_state)
- {
- new_state = apr_palloc(parser->pool, sizeof(*new_state));
- new_state->pool = svn_pool_create(parser->pool);
- }
- else
- {
- new_state = parser->free_state;
- parser->free_state = parser->free_state->prev;
-
- svn_pool_clear(new_state->pool);
- }
-
- if (parser->state)
- {
- new_state->private = parser->state->private;
- new_state->ns_list = parser->state->ns_list;
- }
- else
- {
- new_state->private = NULL;
- new_state->ns_list = NULL;
- }
-
- new_state->current_state = state;
-
- /* Add it to the state chain. */
- new_state->prev = parser->state;
- parser->state = new_state;
-}
-
-void svn_ra_serf__xml_pop_state(svn_ra_serf__xml_parser_t *parser)
-{
- svn_ra_serf__xml_state_t *cur_state;
-
- cur_state = parser->state;
- parser->state = cur_state->prev;
- cur_state->prev = parser->free_state;
- parser->free_state = cur_state;
-}
-
-
/* Return a pool for XES to use for self-alloc (and other specifics). */
static apr_pool_t *
xes_pool(const svn_ra_serf__xml_estate_t *xes)
@@ -618,10 +611,10 @@ svn_ra_serf__xml_state_pool(svn_ra_serf_
}
-svn_error_t *
-svn_ra_serf__xml_cb_start(svn_ra_serf__xml_context_t *xmlctx,
- const char *raw_name,
- const char *const *attrs)
+static svn_error_t *
+xml_cb_start(svn_ra_serf__xml_context_t *xmlctx,
+ const char *raw_name,
+ const char *const *attrs)
{
svn_ra_serf__xml_estate_t *current = xmlctx->current;
svn_ra_serf__dav_props_t elemname;
@@ -641,7 +634,7 @@ svn_ra_serf__xml_cb_start(svn_ra_serf__x
were found. */
define_namespaces(¤t->ns_list, attrs, lazy_create_pool, current);
- svn_ra_serf__expand_ns(&elemname, current->ns_list, raw_name);
+ expand_ns(&elemname, current->ns_list, raw_name);
for (scan = xmlctx->ttable; scan->ns != NULL; ++scan)
{
@@ -767,14 +760,11 @@ svn_ra_serf__xml_cb_start(svn_ra_serf__x
}
-svn_error_t *
-svn_ra_serf__xml_cb_end(svn_ra_serf__xml_context_t *xmlctx,
- const char *raw_name)
+static svn_error_t *
+xml_cb_end(svn_ra_serf__xml_context_t *xmlctx,
+ const char *raw_name)
{
svn_ra_serf__xml_estate_t *xes = xmlctx->current;
- svn_ra_serf__dav_props_t elemname;
-
- svn_ra_serf__expand_ns(&elemname, xes->ns_list, raw_name);
if (xmlctx->waiting > 0)
{
@@ -825,10 +815,10 @@ svn_ra_serf__xml_cb_end(svn_ra_serf__xml
}
-svn_error_t *
-svn_ra_serf__xml_cb_cdata(svn_ra_serf__xml_context_t *xmlctx,
- const char *data,
- apr_size_t len)
+static svn_error_t *
+xml_cb_cdata(svn_ra_serf__xml_context_t *xmlctx,
+ const char *data,
+ apr_size_t len)
{
/* If we are waiting for a closing tag, then we are uninterested in
the cdata. Just return. */
@@ -857,3 +847,216 @@ svn_ra_serf__xml_cb_cdata(svn_ra_serf__x
return SVN_NO_ERROR;
}
+/* svn_error_t * wrapper around XML_Parse */
+static APR_INLINE svn_error_t *
+parse_xml(XML_Parser parser, const char *data, apr_size_t len, svn_boolean_t is_final)
+{
+ int xml_status = XML_Parse(parser, data, (int)len, is_final);
+ const char *msg;
+
+ /* ### Perhaps we should filter some specific error codes on systems
+ that use STOPPARSER to hide addtional errors */
+ if (xml_status == XML_STATUS_OK)
+ return SVN_NO_ERROR;
+
+ msg = XML_ErrorString(XML_GetErrorCode(parser));
+
+ return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA,
+ svn_error_createf(SVN_ERR_XML_MALFORMED, NULL,
+ _("Malformed XML: %s"),
+ msg),
+ _("The XML response contains invalid XML"));
+}
+
+/* Apr pool cleanup handler to release an XML_Parser in success and error
+ conditions */
+static apr_status_t
+xml_parser_cleanup(void *baton)
+{
+ XML_Parser *xmlp = baton;
+
+ if (*xmlp)
+ {
+ (void) XML_ParserFree(*xmlp);
+ *xmlp = NULL;
+ }
+
+ return APR_SUCCESS;
+}
+
+/* Conforms to Expat's XML_StartElementHandler */
+static void
+expat_start(void *userData, const char *raw_name, const char **attrs)
+{
+ struct expat_ctx_t *ectx = userData;
+
+ if (ectx->inner_error != NULL)
+ return;
+
+ ectx->inner_error = svn_error_trace(xml_cb_start(ectx->xmlctx,
+ raw_name, attrs));
+
+#ifdef EXPAT_HAS_STOPPARSER
+ if (ectx->inner_error)
+ (void) XML_StopParser(ectx->parser, 0 /* resumable */);
+#endif
+}
+
+
+/* Conforms to Expat's XML_EndElementHandler */
+static void
+expat_end(void *userData, const char *raw_name)
+{
+ struct expat_ctx_t *ectx = userData;
+
+ if (ectx->inner_error != NULL)
+ return;
+
+ ectx->inner_error = svn_error_trace(xml_cb_end(ectx->xmlctx, raw_name));
+
+#ifdef EXPAT_HAS_STOPPARSER
+ if (ectx->inner_error)
+ (void) XML_StopParser(ectx->parser, 0 /* resumable */);
+#endif
+}
+
+
+/* Conforms to Expat's XML_CharacterDataHandler */
+static void
+expat_cdata(void *userData, const char *data, int len)
+{
+ struct expat_ctx_t *ectx = userData;
+
+ if (ectx->inner_error != NULL)
+ return;
+
+ ectx->inner_error = svn_error_trace(xml_cb_cdata(ectx->xmlctx, data, len));
+
+#ifdef EXPAT_HAS_STOPPARSER
+ if (ectx->inner_error)
+ (void) XML_StopParser(ectx->parser, 0 /* resumable */);
+#endif
+}
+
+
+/* Implements svn_ra_serf__response_handler_t */
+static svn_error_t *
+expat_response_handler(serf_request_t *request,
+ serf_bucket_t *response,
+ void *baton,
+ apr_pool_t *scratch_pool)
+{
+ struct expat_ctx_t *ectx = baton;
+ svn_boolean_t got_expected_status;
+
+ if (ectx->expected_status)
+ {
+ const int *status = ectx->expected_status;
+ got_expected_status = FALSE;
+
+ while (*status && ectx->handler->sline.code != *status)
+ status++;
+
+ got_expected_status = (*status) != 0;
+ }
+ else
+ got_expected_status = (ectx->handler->sline.code == 200);
+
+ if (!ectx->handler->server_error
+ && ((ectx->handler->sline.code < 200) || (ectx->handler->sline.code >= 300)
+ || ! got_expected_status))
+ {
+ /* By deferring to expect_empty_body(), it will make a choice on
+ how to handle the body. Whatever the decision, the core handler
+ will take over, and we will not be called again. */
+
+ /* ### This handles xml bodies as svn-errors (returned via serf context
+ ### loop), but ignores non-xml errors.
+
+ Current code depends on this behavior and checks itself while other
+ continues, and then verifies if work has been performed.
+
+ ### TODO: Make error checking consistent */
+
+ /* ### If !GOT_EXPECTED_STATUS, this should always produce an error */
+ return svn_error_trace(svn_ra_serf__expect_empty_body(
+ request, response, ectx->handler,
+ scratch_pool));
+ }
+
+ 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);
+ }
+
+ while (1)
+ {
+ apr_status_t status;
+ const char *data;
+ apr_size_t len;
+ svn_error_t *err;
+ svn_boolean_t at_eof = FALSE;
+
+ status = serf_bucket_read(response, PARSE_CHUNK_SIZE, &data, &len);
+ if (SERF_BUCKET_READ_ERROR(status))
+ return svn_ra_serf__wrap_err(status, NULL);
+ else if (APR_STATUS_IS_EOF(status))
+ at_eof = TRUE;
+
+ err = parse_xml(ectx->parser, data, len, at_eof /* isFinal */);
+
+ err = svn_error_compose_create(ectx->inner_error, err);
+
+ if (at_eof || err)
+ {
+ /* Release xml parser state/tables. */
+ apr_pool_cleanup_run(ectx->cleanup_pool, &ectx->parser,
+ xml_parser_cleanup);
+ }
+
+ SVN_ERR(err);
+
+ /* The parsing went fine. What has the bucket told us? */
+ if (at_eof)
+ {
+ /* Make sure we actually got xml and clean up after parsing */
+ SVN_ERR(svn_ra_serf__xml_context_done(ectx->xmlctx));
+ }
+
+ if (status && !SERF_BUCKET_READ_ERROR(status))
+ {
+ return svn_ra_serf__wrap_err(status, NULL);
+ }
+ }
+
+ /* NOTREACHED */
+}
+
+
+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)
+{
+ svn_ra_serf__handler_t *handler;
+ struct expat_ctx_t *ectx;
+
+ ectx = apr_pcalloc(result_pool, sizeof(*ectx));
+ ectx->xmlctx = xmlctx;
+ ectx->parser = NULL;
+ ectx->expected_status = expected_status;
+ ectx->cleanup_pool = result_pool;
+
+ handler = svn_ra_serf__create_handler(result_pool);
+ handler->response_handler = expat_response_handler;
+ handler->response_baton = ectx;
+
+ ectx->handler = handler;
+
+ return handler;
+}
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/log.c?rev=1558485&r1=1558484&r2=1558485&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/log.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/log.c Wed Jan 15 17:47:23 2014
@@ -242,8 +242,7 @@ turn_unique_copies_into_moves(apr_hash_t
if ( (i == 0 || strcmp(sources[i-1], sources[i]))
&& (i == copy_sources->nelts-1 || strcmp(sources[i+1], sources[i])))
{
- apr_hash_set(unique_copy_sources, sources[i],
- APR_HASH_KEY_STRING, sources[i]);
+ svn_hash_sets(unique_copy_sources, sources[i], sources[i]);
}
/* no unique copy-from paths -> no moves */
@@ -264,12 +263,10 @@ turn_unique_copies_into_moves(apr_hash_t
apr_hash_this(hi, (const void **)&key, &klen, (void**)&change);
if ( change->copyfrom_rev != revision-1
|| !change->copyfrom_path
- || !apr_hash_get(unique_copy_sources, change->copyfrom_path,
- APR_HASH_KEY_STRING))
+ || !svn_hash_gets(unique_copy_sources, change->copyfrom_path))
continue;
- copy_from_change = apr_hash_get(changes, change->copyfrom_path,
- APR_HASH_KEY_STRING);
+ copy_from_change = svn_hash_gets(changes, change->copyfrom_path);
if (!copy_from_change || !is_deletion(copy_from_change))
continue;
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_subr/sqlite.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_subr/sqlite.c?rev=1558485&r1=1558484&r2=1558485&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_subr/sqlite.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_subr/sqlite.c Wed Jan 15 17:47:23 2014
@@ -109,6 +109,23 @@ sqlite_profiler(void *data, const char *
}
#endif
+#if defined(SVN_DEBUG) && defined(SQLITE_CONFIG_LOG)
+static void
+sqlite_error_log(void* baton, int err, const char* msg)
+{
+ fprintf(stderr, "DBG: sqlite[S%d]: %s\n", err, msg);
+}
+#endif
+
+void
+svn_sqlite__dbg_enable_errorlog(void)
+{
+#if defined(SVN_DEBUG) && defined(SQLITE_CONFIG_LOG)
+ sqlite3_config(SQLITE_CONFIG_LOG, sqlite_error_log, (void*)NULL /* baton */);
+#endif
+}
+
+
struct svn_sqlite__db_t
{
sqlite3 *db3;
Modified: subversion/branches/fsfs-ucsnorm/subversion/mod_dav_svn/reports/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/mod_dav_svn/reports/update.c?rev=1558485&r1=1558484&r2=1558485&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/mod_dav_svn/reports/update.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/mod_dav_svn/reports/update.c Wed Jan 15 17:47:23 2014
@@ -127,10 +127,6 @@ typedef struct item_baton_t {
/* File/dir copied? */
svn_boolean_t copyfrom;
- /* Does the client need to fetch additional properties for this
- item? */
- svn_boolean_t fetch_props;
-
/* Array of const char * names of removed properties. (Used only
for copied files/dirs in skelta mode.) */
apr_array_header_t *removed_props;
@@ -466,12 +462,6 @@ close_helper(svn_boolean_t is_dir, item_
}
}
- /* If our client need to fetch properties, let it know. */
- if (baton->fetch_props)
- SVN_ERR(dav_svn__brigade_printf(baton->uc->bb, baton->uc->output,
- "<S:fetch-props/>" DEBUG_CR));
-
-
/* Let's tie it off, nurse. */
if (baton->added)
SVN_ERR(dav_svn__brigade_printf(baton->uc->bb, baton->uc->output,
@@ -694,8 +684,8 @@ upd_change_xxx_prop(void *baton,
/* That said, beginning in Subversion 1.8, clients might
request even in skelta mode that we transmit properties
- on newly added files explicitly. */
- if ((! b->copyfrom) && value && b->uc->include_props)
+ on added files and directories explicitly. */
+ if (value && b->uc->include_props)
{
SVN_ERR(send_propchange(b, name, value, pool));
}
@@ -1147,6 +1137,11 @@ dav_svn__update_report(const dav_resourc
}
if (child->ns == ns && strcmp(child->name, "resource-walk") == 0)
{
+ /* This flag is not used since Subversion 1.1.x
+ There are some remains in libsvn_ra_neon, where it can
+ be enabled via a static function flag.
+ Disabled since r852220 (aka r12146)
+ "Prefer correctness over efficiency." */
cdata = dav_xml_get_cdata(child, resource->pool, 1);
if (! *cdata)
return malformed_element_error(child->name, resource->pool);
Modified: subversion/branches/fsfs-ucsnorm/subversion/mod_dav_svn/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/mod_dav_svn/repos.c?rev=1558485&r1=1558484&r2=1558485&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/mod_dav_svn/repos.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/mod_dav_svn/repos.c Wed Jan 15 17:47:23 2014
@@ -1795,7 +1795,11 @@ do_out_of_date_check(dav_resource_combin
if (comb->priv.version_name < created_rev)
{
serr = svn_error_createf(SVN_ERR_RA_OUT_OF_DATE, NULL,
- "Item '%s' is out of date",
+ comb->res.collection
+ ? "Directory '%s' is out of date"
+ : (comb->res.exists
+ ? "File '%s' is out of date"
+ : "'%s' is out of date"),
comb->priv.repos_path);
return dav_svn__convert_err(serr, HTTP_CONFLICT,
"Attempting to modify out-of-date resource.",
@@ -1973,6 +1977,25 @@ get_resource(request_rec *r,
of private resource, iff the SVNListParentPath directive is 'on'. */
if (dav_svn__is_parentpath_list(r))
{
+ /* Only allow GET and HEAD on the parentpath resource
+ * httpd uses the same method_number for HEAD as GET */
+ if (r->method_number != M_GET)
+ {
+ int status;
+
+ /* Marshall the error back to the client by generating by
+ * way of the dav_svn__error_response_tag trick. */
+ err = dav_svn__new_error(r->pool, HTTP_METHOD_NOT_ALLOWED,
+ SVN_ERR_APMOD_MALFORMED_URI,
+ "The URI does not contain the name "
+ "of a repository.");
+ /* can't use r->allowed since the default handler isn't called */
+ apr_table_setn(r->headers_out, "Allow", "GET,HEAD");
+ status = dav_svn__error_response_tag(r, err);
+
+ return dav_push_error(r->pool, status, err->error_id, NULL, err);
+ }
+
err = get_parentpath_resource(r, resource);
if (err)
return err;
@@ -3927,7 +3950,11 @@ remove_resource(dav_resource *resource,
if (resource->info->version_name < created_rev)
{
serr = svn_error_createf(SVN_ERR_RA_OUT_OF_DATE, NULL,
- "Item '%s' is out of date",
+ resource->collection
+ ? "Directory '%s' is out of date"
+ : (resource->exists
+ ? "File '%s' is out of date"
+ : "'%s' is out of date"),
resource->info->repos_path);
return dav_svn__convert_err(serr, HTTP_CONFLICT,
"Can't DELETE out-of-date resource",
Modified: subversion/branches/fsfs-ucsnorm/subversion/mod_dav_svn/version.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/mod_dav_svn/version.c?rev=1558485&r1=1558484&r2=1558485&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/mod_dav_svn/version.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/mod_dav_svn/version.c Wed Jan 15 17:47:23 2014
@@ -182,23 +182,29 @@ get_option(const dav_resource *resource,
SVN_IGNORED_REVNUM, "", 0, resource->pool);
/* ### DAV:version-history-collection-set */
- if (elem->ns == APR_XML_NS_DAV_ID)
+ if (elem->ns != APR_XML_NS_DAV_ID
+ || strcmp(elem->name, "activity-collection-set") != 0)
{
- if (strcmp(elem->name, "activity-collection-set") == 0)
- {
- apr_text_append(resource->pool, option,
- "<D:activity-collection-set>");
- apr_text_append(resource->pool, option,
- dav_svn__build_uri(resource->info->repos,
- DAV_SVN__BUILD_URI_ACT_COLLECTION,
- SVN_INVALID_REVNUM, NULL,
- 1 /* add_href */,
- resource->pool));
- apr_text_append(resource->pool, option,
- "</D:activity-collection-set>");
- }
+ /* We don't know about other options (yet).
+
+ If we ever add multiple option request keys we should
+ just write the requested option value and make sure
+ we set the headers *once*. */
+ return NULL;
}
+ apr_text_append(resource->pool, option,
+ "<D:activity-collection-set>");
+
+ apr_text_append(resource->pool, option,
+ dav_svn__build_uri(resource->info->repos,
+ DAV_SVN__BUILD_URI_ACT_COLLECTION,
+ SVN_INVALID_REVNUM, NULL,
+ 1 /* add_href */,
+ resource->pool));
+ apr_text_append(resource->pool, option,
+ "</D:activity-collection-set>");
+
/* If we're allowed (by configuration) to do so, advertise support
for ephemeral transaction properties. */
if (dav_svn__check_ephemeral_txnprops_support(r))
Modified: subversion/branches/fsfs-ucsnorm/subversion/svnrdump/dump_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/svnrdump/dump_editor.c?rev=1558485&r1=1558484&r2=1558485&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/svnrdump/dump_editor.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/svnrdump/dump_editor.c Wed Jan 15 17:47:23 2014
@@ -121,13 +121,6 @@ struct file_baton
svn_boolean_t dump_props;
};
-/* A handler baton to be used in window_handler(). */
-struct handler_baton
-{
- svn_txdelta_window_handler_t apply_handler;
- void *apply_baton;
-};
-
/* The baton used by the dump editor. */
struct dump_edit_baton {
/* The output stream we write the dumpfile to */
@@ -187,31 +180,38 @@ make_dir_baton(const char *path,
struct dump_edit_baton *eb = edit_baton;
struct dir_baton *new_db = apr_pcalloc(pool, sizeof(*new_db));
const char *repos_relpath;
+ apr_pool_t *dir_pool;
/* Construct the full path of this node. */
if (pb)
- repos_relpath = svn_relpath_canonicalize(path, pool);
+ {
+ dir_pool = svn_pool_create(pb->pool);
+ repos_relpath = svn_relpath_canonicalize(path, dir_pool);
+ }
else
- repos_relpath = "";
+ {
+ dir_pool = svn_pool_create(eb->pool);
+ repos_relpath = "";
+ }
/* Strip leading slash from copyfrom_path so that the path is
canonical and svn_relpath_join can be used */
if (copyfrom_path)
- copyfrom_path = svn_relpath_canonicalize(copyfrom_path, pool);
+ copyfrom_path = svn_relpath_canonicalize(copyfrom_path, dir_pool);
new_db->eb = eb;
new_db->parent_dir_baton = pb;
- new_db->pool = pool;
+ new_db->pool = dir_pool;
new_db->repos_relpath = repos_relpath;
new_db->copyfrom_path = copyfrom_path
- ? svn_relpath_canonicalize(copyfrom_path, pool)
+ ? svn_relpath_canonicalize(copyfrom_path, dir_pool)
: NULL;
new_db->copyfrom_rev = copyfrom_rev;
new_db->added = added;
new_db->written_out = FALSE;
- new_db->props = apr_hash_make(pool);
- new_db->deleted_props = apr_hash_make(pool);
- new_db->deleted_entries = apr_hash_make(pool);
+ new_db->props = apr_hash_make(dir_pool);
+ new_db->deleted_props = apr_hash_make(dir_pool);
+ new_db->deleted_entries = apr_hash_make(dir_pool);
return new_db;
}
@@ -225,14 +225,15 @@ make_file_baton(const char *path,
struct dir_baton *pb,
apr_pool_t *pool)
{
- struct file_baton *new_fb = apr_pcalloc(pool, sizeof(*new_fb));
+ apr_pool_t *file_pool = svn_pool_create(pb->pool);
+ struct file_baton *new_fb = apr_pcalloc(file_pool, sizeof(*new_fb));
new_fb->eb = pb->eb;
new_fb->parent_dir_baton = pb;
- new_fb->pool = pool;
- new_fb->repos_relpath = svn_relpath_canonicalize(path, pool);
- new_fb->props = apr_hash_make(pool);
- new_fb->deleted_props = apr_hash_make(pool);
+ new_fb->pool = file_pool;
+ new_fb->repos_relpath = svn_relpath_canonicalize(path, file_pool);
+ new_fb->props = apr_hash_make(file_pool);
+ new_fb->deleted_props = apr_hash_make(file_pool);
new_fb->is_copy = FALSE;
new_fb->copyfrom_path = NULL;
new_fb->copyfrom_rev = SVN_INVALID_REVNUM;
@@ -670,7 +671,7 @@ delete_entry(const char *path,
to the deleted_entries of the parent directory baton. That way,
we can tell (later) an addition from a replacement. All the real
deletions get handled in close_directory(). */
- svn_hash_sets(pb->deleted_entries, apr_pstrdup(pb->eb->pool, path), pb);
+ svn_hash_sets(pb->deleted_entries, apr_pstrdup(pb->pool, path), pb);
return SVN_NO_ERROR;
}
@@ -693,7 +694,7 @@ add_directory(const char *path,
SVN_ERR(dump_pending(pb->eb, pool));
new_db = make_dir_baton(path, copyfrom_path, copyfrom_rev, pb->eb,
- pb, TRUE, pb->eb->pool);
+ pb, TRUE, pb->pool);
/* This might be a replacement -- is the path already deleted? */
val = svn_hash_gets(pb->deleted_entries, path);
@@ -745,12 +746,12 @@ open_directory(const char *path,
{
copyfrom_path = svn_relpath_join(pb->copyfrom_path,
svn_relpath_basename(path, NULL),
- pb->eb->pool);
+ pb->pool);
copyfrom_rev = pb->copyfrom_rev;
}
new_db = make_dir_baton(path, copyfrom_path, copyfrom_rev, pb->eb, pb,
- FALSE, pb->eb->pool);
+ FALSE, pb->pool);
*child_baton = new_db;
return SVN_NO_ERROR;
@@ -801,7 +802,7 @@ close_directory(void *dir_baton,
}
/* ### should be unnecessary */
- apr_hash_clear(db->deleted_entries);
+ svn_pool_destroy(db->pool);
return SVN_NO_ERROR;
}
@@ -868,7 +869,7 @@ open_file(const char *path,
{
fb->copyfrom_path = svn_relpath_join(pb->copyfrom_path,
svn_relpath_basename(path, NULL),
- pb->eb->pool);
+ pb->pool);
fb->copyfrom_rev = pb->copyfrom_rev;
}
@@ -940,22 +941,6 @@ change_file_prop(void *file_baton,
}
static svn_error_t *
-window_handler(svn_txdelta_window_t *window, void *baton)
-{
- struct handler_baton *hb = baton;
- static svn_error_t *err;
-
- err = hb->apply_handler(window, hb->apply_baton);
- if (window != NULL && !err)
- return SVN_NO_ERROR;
-
- if (err)
- SVN_ERR(err);
-
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
apply_textdelta(void *file_baton, const char *base_checksum,
apr_pool_t *pool,
svn_txdelta_window_handler_t *handler,
@@ -963,31 +948,21 @@ apply_textdelta(void *file_baton, const
{
struct file_baton *fb = file_baton;
struct dump_edit_baton *eb = fb->eb;
- struct handler_baton *hb;
svn_stream_t *delta_filestream;
LDR_DBG(("apply_textdelta %p\n", file_baton));
- /* This is custom handler_baton, allocated from a separate pool. */
- hb = apr_pcalloc(eb->pool, sizeof(*hb));
-
/* Use a temporary file to measure the Text-content-length */
delta_filestream = svn_stream_from_aprfile2(eb->delta_file, TRUE, pool);
/* Prepare to write the delta to the delta_filestream */
- svn_txdelta_to_svndiff3(&(hb->apply_handler), &(hb->apply_baton),
+ svn_txdelta_to_svndiff3(handler, handler_baton,
delta_filestream, 0,
SVN_DELTA_COMPRESSION_LEVEL_DEFAULT, pool);
/* Record that there's text to be dumped, and its base checksum. */
fb->dump_text = TRUE;
- fb->base_checksum = apr_pstrdup(eb->pool, base_checksum);
-
- /* The actual writing takes place when this function has
- finished. Set handler and handler_baton now so for
- window_handler() */
- *handler = window_handler;
- *handler_baton = hb;
+ fb->base_checksum = apr_pstrdup(fb->pool, base_checksum);
return SVN_NO_ERROR;
}
@@ -1100,6 +1075,8 @@ close_file(void *file_baton,
dump` */
SVN_ERR(svn_stream_puts(eb->stream, "\n\n"));
+ svn_pool_clear(fb->pool);
+
return SVN_NO_ERROR;
}
Modified: subversion/branches/fsfs-ucsnorm/subversion/svnserve/logger.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/svnserve/logger.c?rev=1558485&r1=1558484&r2=1558485&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/svnserve/logger.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/svnserve/logger.c Wed Jan 15 17:47:23 2014
@@ -52,28 +52,16 @@ struct logger_t
apr_pool_t *pool;
};
-/* Pool cleanup handler. Make sure we destroy our private pool as well. */
-static apr_status_t cleanup_logger(void *data)
-{
- logger_t *logger = data;
- svn_pool_destroy(logger->pool);
-
- return APR_SUCCESS;
-}
-
svn_error_t *
logger__create_for_stderr(logger_t **logger,
apr_pool_t *pool)
{
logger_t *result = apr_pcalloc(pool, sizeof(*result));
- result->pool = svn_pool_create(NULL);
+ result->pool = svn_pool_create(pool);
SVN_ERR(svn_stream_for_stderr(&result->stream, pool));
SVN_ERR(svn_mutex__init(&result->mutex, TRUE, pool));
- apr_pool_cleanup_register(pool, result, cleanup_logger,
- apr_pool_cleanup_null);
-
*logger = result;
return SVN_NO_ERROR;
@@ -93,11 +81,8 @@ logger__create(logger_t **logger,
SVN_ERR(svn_mutex__init(&result->mutex, TRUE, pool));
result->stream = svn_stream_from_aprfile2(file, FALSE, pool);
- result->pool = svn_pool_create(NULL);
-
- apr_pool_cleanup_register(pool, result, cleanup_logger,
- apr_pool_cleanup_null);
-
+ result->pool = svn_pool_create(pool);
+
*logger = result;
return SVN_NO_ERROR;
Modified: subversion/branches/fsfs-ucsnorm/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/svnserve/serve.c?rev=1558485&r1=1558484&r2=1558485&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/svnserve/serve.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/svnserve/serve.c Wed Jan 15 17:47:23 2014
@@ -97,7 +97,6 @@ typedef struct file_revs_baton_t {
typedef struct fs_warning_baton_t {
server_baton_t *server;
svn_ra_svn_conn_t *conn;
- apr_pool_t *pool;
} fs_warning_baton_t;
typedef struct authz_baton_t {
@@ -3438,8 +3437,6 @@ fs_warning_func(void *baton, svn_error_t
{
fs_warning_baton_t *b = baton;
log_error(err, b->server);
- /* TODO: Keep log_pool in the server baton, cleared after every log? */
- svn_pool_clear(b->pool);
}
/* Return the normalized repository-relative path for the given PATH
@@ -3779,7 +3776,6 @@ construct_server_baton(server_baton_t **
warn_baton = apr_pcalloc(scratch_pool, sizeof(*warn_baton));
warn_baton->server = b;
warn_baton->conn = conn;
- warn_baton->pool = svn_pool_create(scratch_pool);
svn_fs_set_warning_func(b->repository->fs, fs_warning_func, warn_baton);
/* Set up editor shims. */
@@ -3833,7 +3829,6 @@ reopen_repos(connection_t *connection,
warn_baton->server = connection->baton;
warn_baton->conn = connection->conn;
- warn_baton->pool = svn_pool_create(pool);
svn_fs_set_warning_func(connection->baton->repository->fs,
fs_warning_func, &warn_baton);
Modified: subversion/branches/fsfs-ucsnorm/subversion/tests/cmdline/prop_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/tests/cmdline/prop_tests.py?rev=1558485&r1=1558484&r2=1558485&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/tests/cmdline/prop_tests.py (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/tests/cmdline/prop_tests.py Wed Jan 15 17:47:23 2014
@@ -2654,6 +2654,55 @@ def xml_unsafe_author(sbox):
'proplist', '--revprop', '-r', '1',
wc_dir)
+def dir_prop_conflict_details(sbox):
+ "verify dir property conflict details"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ # Apply some changes
+ sbox.simple_propset('svn:mergeinfo', '/B:1', 'A')
+ sbox.simple_propset('my-prop', 'my-val', 'A')
+ sbox.simple_commit()
+
+ # Revert to r1
+ sbox.simple_update('', revision=1)
+
+ # Apply some incompatible changes
+ sbox.simple_propset('svn:mergeinfo', '/C:1', 'A')
+ sbox.simple_propset('my-prop', 'other-val', 'A')
+
+ # This should report out of date because there are incompatible property
+ # changes that can't be merged on the server
+ svntest.actions.run_and_verify_commit(wc_dir,
+ None,
+ None,
+ '.*[Oo]ut of date.*',
+ wc_dir)
+
+ expected_output = svntest.wc.State(wc_dir, {
+ 'A' : Item(status=' C'),
+ })
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
+ expected_status.tweak('A', status=' C')
+
+ svntest.actions.run_and_verify_update(wc_dir,
+ expected_output,
+ None,
+ expected_status,
+ None, None, None, None, None, 1,
+ wc_dir)
+
+ # The conflict properties file line was shown for previous versions, but the
+ # conflict source urls are new since 1.8.
+ expected_info = {
+ 'Conflict Properties File' : re.escape(os.path.abspath(
+ sbox.ospath('A/dir_conflicts.prej'))
+ + ' Source left: (dir) ^/A@1'
+ + ' Source right: (dir) ^/A@2')
+ }
+ svntest.actions.run_and_verify_info([expected_info], sbox.path('A'))
+
########################################################################
# Run the tests
@@ -2701,6 +2750,7 @@ test_list = [ None,
almost_known_prop_names,
peg_rev_base_working,
xml_unsafe_author,
+ dir_prop_conflict_details,
]
if __name__ == '__main__':
Modified: subversion/branches/fsfs-ucsnorm/subversion/tests/libsvn_fs/fs-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/tests/libsvn_fs/fs-test.c?rev=1558485&r1=1558484&r2=1558485&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/tests/libsvn_fs/fs-test.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/tests/libsvn_fs/fs-test.c Wed Jan 15 17:47:23 2014
@@ -4582,6 +4582,7 @@ unordered_txn_dirprops(const svn_test_op
svn_fs_root_t *txn_root, *txn_root2;
svn_string_t pval;
svn_revnum_t new_rev, not_rev;
+ svn_boolean_t is_bdb = strcmp(opts->fs_type, "bdb") == 0;
/* This is a regression test for issue #2751. */
@@ -4638,10 +4639,21 @@ unordered_txn_dirprops(const svn_test_op
/* Commit the first one first. */
SVN_ERR(test_commit_txn(&new_rev, txn, NULL, pool));
- /* Then commit the second -- but expect an conflict because the
- directory wasn't up-to-date, which is required for propchanges. */
- SVN_ERR(test_commit_txn(¬_rev, txn2, "/A/B", pool));
- SVN_ERR(svn_fs_abort_txn(txn2, pool));
+ /* Some backends are clever then others. */
+ if (is_bdb)
+ {
+ /* Then commit the second -- but expect an conflict because the
+ directory wasn't up-to-date, which is required for propchanges. */
+ SVN_ERR(test_commit_txn(¬_rev, txn2, "/A/B", pool));
+ SVN_ERR(svn_fs_abort_txn(txn2, pool));
+ }
+ else
+ {
+ /* Then commit the second -- there will be no conflict despite the
+ directory being out-of-data because the properties as well as the
+ directory structure (list of nodes) was up-to-date. */
+ SVN_ERR(test_commit_txn(¬_rev, txn2, NULL, pool));
+ }
return SVN_NO_ERROR;
}
@@ -5222,6 +5234,80 @@ test_compat_version(const svn_test_opts_
return SVN_NO_ERROR;
}
+static svn_error_t *
+dir_prop_merge(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ svn_fs_t *fs;
+ svn_revnum_t head_rev;
+ svn_fs_root_t *root;
+ svn_fs_txn_t *txn, *mid_txn, *top_txn, *sub_txn, *c_txn;
+ svn_boolean_t is_bdb = strcmp(opts->fs_type, "bdb") == 0;
+
+ /* Create test repository. */
+ SVN_ERR(svn_test__create_fs(&fs, "test-dir_prop-merge", opts, pool));
+
+ SVN_ERR(svn_fs_begin_txn(&txn, fs, 0, pool));
+ SVN_ERR(svn_fs_txn_root(&root, txn, pool));
+
+ /* Create and verify the greek tree. */
+ SVN_ERR(svn_test__create_greek_tree(root, pool));
+ SVN_ERR(test_commit_txn(&head_rev, txn, NULL, pool));
+
+ /* Start concurrent transactions */
+
+ /* 1st: modify a mid-level directory */
+ SVN_ERR(svn_fs_begin_txn2(&mid_txn, fs, head_rev, 0, pool));
+ SVN_ERR(svn_fs_txn_root(&root, mid_txn, pool));
+ SVN_ERR(svn_fs_change_node_prop(root, "A/D", "test-prop",
+ svn_string_create("val1", pool), pool));
+ svn_fs_close_root(root);
+
+ /* 2st: modify a top-level directory */
+ SVN_ERR(svn_fs_begin_txn2(&top_txn, fs, head_rev, 0, pool));
+ SVN_ERR(svn_fs_txn_root(&root, top_txn, pool));
+ SVN_ERR(svn_fs_change_node_prop(root, "A", "test-prop",
+ svn_string_create("val2", pool), pool));
+ svn_fs_close_root(root);
+
+ SVN_ERR(svn_fs_begin_txn2(&sub_txn, fs, head_rev, 0, pool));
+ SVN_ERR(svn_fs_txn_root(&root, sub_txn, pool));
+ SVN_ERR(svn_fs_change_node_prop(root, "A/D/G", "test-prop",
+ svn_string_create("val3", pool), pool));
+ svn_fs_close_root(root);
+
+ /* 3rd: modify a conflicting change to the mid-level directory */
+ SVN_ERR(svn_fs_begin_txn2(&c_txn, fs, head_rev, 0, pool));
+ SVN_ERR(svn_fs_txn_root(&root, c_txn, pool));
+ SVN_ERR(svn_fs_change_node_prop(root, "A/D", "test-prop",
+ svn_string_create("valX", pool), pool));
+ svn_fs_close_root(root);
+
+ /* Prop changes to the same node should conflict */
+ SVN_ERR(test_commit_txn(&head_rev, mid_txn, NULL, pool));
+ SVN_ERR(test_commit_txn(&head_rev, c_txn, "/A/D", pool));
+ SVN_ERR(svn_fs_abort_txn(c_txn, pool));
+
+ /* Changes in a sub-tree should not conflict with prop changes to some
+ parent directory but some backends are clever then others. */
+ if (is_bdb)
+ {
+ SVN_ERR(test_commit_txn(&head_rev, top_txn, "/A", pool));
+ SVN_ERR(svn_fs_abort_txn(top_txn, pool));
+ }
+ else
+ {
+ SVN_ERR(test_commit_txn(&head_rev, top_txn, NULL, pool));
+ }
+
+ /* The inverted case is not that trivial to handle. Hence, conflict.
+ Depending on the checking order, the reported conflict path differs. */
+ SVN_ERR(test_commit_txn(&head_rev, sub_txn, is_bdb ? "/A/D" : "/A", pool));
+ SVN_ERR(svn_fs_abort_txn(sub_txn, pool));
+
+ return SVN_NO_ERROR;
+}
+
/* ------------------------------------------------------------------------ */
@@ -5315,5 +5401,7 @@ struct svn_test_descriptor_t test_funcs[
"commit timestamp"),
SVN_TEST_OPTS_PASS(test_compat_version,
"test svn_fs__compatible_version"),
+ SVN_TEST_OPTS_PASS(dir_prop_merge,
+ "test merge directory properties"),
SVN_TEST_NULL
};
Modified: subversion/branches/fsfs-ucsnorm/subversion/tests/svn_test_main.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/tests/svn_test_main.c?rev=1558485&r1=1558484&r2=1558485&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/tests/svn_test_main.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/tests/svn_test_main.c Wed Jan 15 17:47:23 2014
@@ -49,6 +49,7 @@
#include "private/svn_cmdline_private.h"
#include "private/svn_atomic.h"
#include "private/svn_mutex.h"
+#include "private/svn_sqlite.h"
#include "svn_private_config.h"
@@ -715,6 +716,11 @@ main(int argc, const char *argv[])
#endif /* _MSC_VER >= 1400 */
#endif
+ /* Temporary code: Enable Sqlite error log to diagnose buildbot issue.
+ ### Perhaps we should later attach this to an environment variable? */
+ svn_sqlite__dbg_enable_errorlog();
+ /* /Temporary code */
+
if (err)
return svn_cmdline_handle_exit_error(err, pool, prog_name);
while (1)