Modified: subversion/branches/pin-externals/subversion/libsvn_ra_serf/ra_serf.h URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_ra_serf/ra_serf.h?rev=1655005&r1=1655004&r2=1655005&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_ra_serf/ra_serf.h (original) +++ subversion/branches/pin-externals/subversion/libsvn_ra_serf/ra_serf.h Tue Jan 27 10:51:52 2015 @@ -378,7 +378,7 @@ typedef svn_error_t * /* Callback when the request is done */ typedef svn_error_t * (*svn_ra_serf__response_done_delegate_t)(serf_request_t *request, - void *handler_baton, + void *done_baton, apr_pool_t *scratch_pool); /* Callback for when a request body is needed. */ @@ -639,9 +639,11 @@ typedef struct svn_ra_serf__xml_transiti } svn_ra_serf__xml_transition_t; -/* Constructor for */ +/* Constructor for svn_ra_serf__handler_t. Initializes a new handler + with default settings for SESSION. */ svn_ra_serf__handler_t * -svn_ra_serf__create_handler(apr_pool_t *result_pool); +svn_ra_serf__create_handler(svn_ra_serf__session_t *session, + apr_pool_t *result_pool); /* Construct an XML parsing context, based on the TTABLE transition table. As content is parsed, the CLOSED_CB callback will be invoked according @@ -685,7 +687,8 @@ svn_ra_serf__xml_context_done(svn_ra_ser 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, +svn_ra_serf__create_expat_handler(svn_ra_serf__session_t *session, + svn_ra_serf__xml_context_t *xmlctx, const int *expected_status, apr_pool_t *result_pool); @@ -924,15 +927,15 @@ svn_ra_serf__keep_only_regular_props(apr /* Callback used via svn_ra_serf__deliver_props2 */ typedef svn_error_t * -(*svn_ra_serf__prop_func)(void *baton, - const char *path, - const char *ns, - const char *name, - const svn_string_t *value, - apr_pool_t *scratch_pool); +(*svn_ra_serf__prop_func_t)(void *baton, + const char *path, + const char *ns, + const char *name, + const svn_string_t *value, + apr_pool_t *scratch_pool); /* - * Implementation of svn_ra_serf__prop_func that just delivers svn compatible + * Implementation of svn_ra_serf__prop_func_t that just delivers svn compatible * properties in the apr_hash_t * that is used as baton. */ svn_error_t * @@ -944,48 +947,23 @@ svn_ra_serf__deliver_svn_props(void *bat apr_pool_t *scratch_pool); /* - * Implementation of svn_ra_serf__prop_func that delivers all DAV properties - * in (const char * -> apr_hash_t *) on Namespace pointing to a second hash - * (const char * -> svn_string_t *) to the values. - */ -svn_error_t * -svn_ra_serf__deliver_node_props(void *baton, - const char *path, - const char *ns, - const char *name, - const svn_string_t *value, - apr_pool_t *scratch_pool); + * This function will create a handler for a PROPFIND request, which will deliver + * properties to PROP_FUNC() with PROP_BATON for the properties listed in LOOKUP_PROPS + * at URL for DEPTH ("0","1","infinity"). + */ +svn_error_t * +svn_ra_serf__create_propfind_handler(svn_ra_serf__handler_t **handler, + svn_ra_serf__session_t *session, + const char *path, + svn_revnum_t rev, + const char *depth, + const svn_ra_serf__dav_props_t *find_props, + svn_ra_serf__prop_func_t prop_func, + void *prop_func_baton, + apr_pool_t *result_pool); -/* - * This function will deliver a PROP_CTX PROPFIND request in the SESS - * serf context for the properties listed in LOOKUP_PROPS at URL for - * DEPTH ("0","1","infinity"). - * - * This function will not block waiting for the response. Callers are - * expected to call svn_ra_serf__wait_for_props(). - */ -svn_error_t * -svn_ra_serf__deliver_props2(svn_ra_serf__handler_t **propfind_handler, - svn_ra_serf__session_t *sess, - svn_ra_serf__connection_t *conn, - const char *path, - svn_revnum_t rev, - const char *depth, - const svn_ra_serf__dav_props_t *find_props, - svn_ra_serf__prop_func prop_func, - void *prop_func_baton, - apr_pool_t *pool); -/* - * This helper function will block until PROPFIND_HANDLER indicates that is - * done or another error is returned. - */ -svn_error_t * -svn_ra_serf__wait_for_props(svn_ra_serf__handler_t *handler, - apr_pool_t *scratch_pool); - - -/* Using CONN, fetch the properties specified by WHICH_PROPS using CONN +/* Using SESSION, fetch the properties specified by WHICH_PROPS using CONN for URL at REVISION. The resulting properties are placed into a 2-level hash in RESULTS, mapping NAMESPACE -> hash<PROPNAME, PROPVALUE>, which is allocated in RESULT_POOL. @@ -998,7 +976,7 @@ svn_ra_serf__wait_for_props(svn_ra_serf_ Temporary allocations are made in SCRATCH_POOL. */ svn_error_t * svn_ra_serf__fetch_node_props(apr_hash_t **results, - svn_ra_serf__connection_t *conn, + svn_ra_serf__session_t *session, const char *url, svn_revnum_t revision, const svn_ra_serf__dav_props_t *which_props, @@ -1006,7 +984,7 @@ svn_ra_serf__fetch_node_props(apr_hash_t apr_pool_t *scratch_pool); -/* Using CONN, fetch a DAV: property from the resource identified by URL +/* Using SESSION, fetch a DAV: property from the resource identified by URL within REVISION. The PROPNAME may be one of: "checked-in" @@ -1020,31 +998,13 @@ svn_ra_serf__fetch_node_props(apr_hash_t Temporary allocations are made in SCRATCH_POOL. */ svn_error_t * svn_ra_serf__fetch_dav_prop(const char **value, - svn_ra_serf__connection_t *conn, + svn_ra_serf__session_t *session, const char *url, svn_revnum_t revision, const char *propname, apr_pool_t *result_pool, apr_pool_t *scratch_pool); - -/** Property walker functions **/ - -typedef svn_error_t * -(*svn_ra_serf__walker_visitor_t)(void *baton, - const char *ns, - const char *name, - const svn_string_t *val, - apr_pool_t *pool); - -/* Like walk_all_props(), but a 2-level hash. */ -svn_error_t * -svn_ra_serf__walk_node_props(apr_hash_t *props, - svn_ra_serf__walker_visitor_t walker, - void *baton, - apr_pool_t *scratch_pool); - - /* Map a property name, as passed over the wire, into its corresponding Subversion-internal name. The returned name will be a static value, or allocated within RESULT_POOL. @@ -1056,30 +1016,6 @@ svn_ra_serf__svnname_from_wirename(const const char *name, apr_pool_t *result_pool); - -/* PROPS is nested hash tables mapping NS -> NAME -> VALUE. - This function takes the NS:NAME:VALUE hashes and flattens them into a set of - names to VALUE. The names are composed of NS:NAME, with specific - rewrite from wire names (DAV) to SVN names. This mapping is managed - by the svn_ra_serf__set_baton_props() function. - - FLAT_PROPS is allocated in RESULT_POOL. - ### right now, we do a shallow copy from PROPS to FLAT_PROPS. therefore, - ### the names and values in PROPS must be in the proper pool. - - Temporary allocations are made in SCRATCH_POOL. */ -svn_error_t * -svn_ra_serf__flatten_props(apr_hash_t **flat_props, - apr_hash_t *props, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool); - - -svn_error_t * -svn_ra_serf__get_resource_type(svn_node_kind_t *kind, - apr_hash_t *props); - - /** MERGE-related functions **/ /* Create an MERGE request aimed at the SESSION url, requesting the @@ -1090,7 +1026,6 @@ svn_ra_serf__get_resource_type(svn_node_ svn_error_t * svn_ra_serf__run_merge(const svn_commit_info_t **commit_info, svn_ra_serf__session_t *session, - svn_ra_serf__connection_t *conn, const char *merge_resource_url, apr_hash_t *lock_tokens, svn_boolean_t keep_locks, @@ -1118,7 +1053,7 @@ svn_ra_serf__probe_proxy(svn_ra_serf__se All temporary allocations will be made in SCRATCH_POOL. */ svn_error_t * svn_ra_serf__v2_get_youngest_revnum(svn_revnum_t *youngest, - svn_ra_serf__connection_t *conn, + svn_ra_serf__session_t *session, apr_pool_t *scratch_pool); @@ -1133,35 +1068,29 @@ svn_ra_serf__v2_get_youngest_revnum(svn_ All temporary allocations will be made in SCRATCH_POOL. */ svn_error_t * svn_ra_serf__v1_get_activity_collection(const char **activity_url, - svn_ra_serf__connection_t *conn, + svn_ra_serf__session_t *session, apr_pool_t *result_pool, apr_pool_t *scratch_pool); /* Set @a VCC_URL to the default VCC for our repository based on @a * ORIG_PATH for the session @a SESSION, ensuring that the VCC URL and - * repository root URLs are cached in @a SESSION. Use @a CONN for any - * required network communications if it is non-NULL; otherwise use the - * default connection. + * repository root URLs are cached in @a SESSION. * - * All temporary allocations will be made in @a POOL. */ + * All temporary allocations will be made in @a SCRATCH_POOL. */ svn_error_t * svn_ra_serf__discover_vcc(const char **vcc_url, svn_ra_serf__session_t *session, - svn_ra_serf__connection_t *conn, - apr_pool_t *pool); + apr_pool_t *scratch_pool); /* Set @a REPORT_TARGET to the URI of the resource at which generic - * (path-agnostic) REPORTs should be aimed for @a SESSION. Use @a - * CONN for any required network communications if it is non-NULL; - * otherwise use the default connection. + * (path-agnostic) REPORTs should be aimed for @a SESSION. * * All temporary allocations will be made in @a POOL. */ svn_error_t * svn_ra_serf__report_resource(const char **report_target, svn_ra_serf__session_t *session, - svn_ra_serf__connection_t *conn, apr_pool_t *pool); /* Set @a REL_PATH to a path (not URI-encoded) relative to the root of @@ -1173,7 +1102,6 @@ svn_error_t * svn_ra_serf__get_relative_path(const char **rel_path, const char *orig_path, svn_ra_serf__session_t *session, - svn_ra_serf__connection_t *conn, apr_pool_t *pool); @@ -1200,11 +1128,9 @@ svn_ra_serf__get_youngest_revnum(svn_rev The DAV RA provider(s) solve this by generating a URL that is specific to a revision by using a URL into a "baseline collection". - For a specified SESSION, with an optional CONN (if NULL, then the - session's default connection will be used; specifically SESSION->conns[0]), - generate a revision-stable URL for URL at REVISION. If REVISION is - SVN_INVALID_REVNUM, then the stable URL will refer to the youngest - revision at the time this function was called. + For a specified SESSION, generate a revision-stable URL for URL at + REVISION. If REVISION is SVN_INVALID_REVNUM, then the stable URL will + refer to the youngest revision at the time this function was called. If URL is NULL, then the session root will be used. @@ -1223,7 +1149,6 @@ svn_error_t * svn_ra_serf__get_stable_url(const char **stable_url, svn_revnum_t *latest_revnum, svn_ra_serf__session_t *session, - svn_ra_serf__connection_t *conn, const char *url, svn_revnum_t revision, apr_pool_t *result_pool,
Modified: subversion/branches/pin-externals/subversion/libsvn_ra_serf/replay.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_ra_serf/replay.c?rev=1655005&r1=1655004&r2=1655005&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_ra_serf/replay.c (original) +++ subversion/branches/pin-externals/subversion/libsvn_ra_serf/replay.c Tue Jan 27 10:51:52 2015 @@ -112,14 +112,6 @@ static const svn_ra_serf__xml_transition { 0 } }; -/* - * An incredibly simple list. - */ -typedef struct ra_serf_list_t { - void *data; - struct ra_serf_list_t *next; -} svn_ra_serf__list_t; - /* Per directory/file state */ typedef struct replay_node_t { apr_pool_t *pool; /* pool allocating this node's data */ @@ -141,8 +133,7 @@ typedef struct revision_report_t { /* 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; + int *replay_reports; /* NULL or number of outstanding reports */ /* callback to get an editor */ svn_ra_replay_revstart_callback_t revstart_func; @@ -173,7 +164,7 @@ typedef struct revision_report_t { /* Handlers for the PROPFIND and REPORT for the current revision. */ svn_ra_serf__handler_t *propfind_handler; - svn_ra_serf__handler_t *report_handler; + svn_ra_serf__handler_t *report_handler; /* For done handler */ } revision_report_t; @@ -478,29 +469,6 @@ replay_cdata(svn_ra_serf__xml_estate_t * return SVN_NO_ERROR; } -/* Conforms to svn_ra_serf__response_done_delegate_t */ -static svn_error_t * -replay_done(serf_request_t *request, - void *baton, - apr_pool_t *scratch_pool) -{ - struct revision_report_t *ctx = baton; - svn_ra_serf__handler_t *handler = ctx->report_handler; - - if (handler->server_error) - return svn_ra_serf__server_error_create(handler, scratch_pool); - else if (handler->sline.code != 200) - return svn_error_trace(svn_ra_serf__unexpected_status(handler)); - - *ctx->done = TRUE; /* Breaks out svn_ra_serf__context_run_wait */ - - ctx->done_item.data = ctx; - ctx->done_item.next = *ctx->done_list; - *ctx->done_list = &ctx->done_item; - - return SVN_NO_ERROR; -} - /* Implements svn_ra_serf__request_body_delegate_t */ static svn_error_t * create_replay_body(serf_bucket_t **bkt, @@ -566,7 +534,7 @@ svn_ra_serf__replay(svn_ra_session_t *ra svn_ra_serf__xml_context_t *xmlctx; const char *report_target; - SVN_ERR(svn_ra_serf__report_resource(&report_target, session, NULL, + SVN_ERR(svn_ra_serf__report_resource(&report_target, session, scratch_pool)); ctx.pool = svn_pool_create(scratch_pool); @@ -584,20 +552,17 @@ svn_ra_serf__replay(svn_ra_session_t *ra &ctx, scratch_pool); - handler = svn_ra_serf__create_expat_handler(xmlctx, NULL, scratch_pool); + handler = svn_ra_serf__create_expat_handler(session, xmlctx, NULL, + scratch_pool); handler->method = "REPORT"; handler->path = session->session_url.path; handler->body_delegate = create_replay_body; handler->body_delegate_baton = &ctx; handler->body_type = "text/xml"; - handler->conn = session->conns[0]; - handler->session = session; /* Not setting up done handler as we don't use a global context */ - ctx.report_handler = handler; /* unused */ - SVN_ERR(svn_ra_serf__context_run_one(handler, scratch_pool)); return svn_error_trace( @@ -637,6 +602,33 @@ svn_ra_serf__replay(svn_ra_session_t *ra */ #define MAX_OUTSTANDING_REQUESTS 50 +/* Implements svn_ra_serf__response_done_delegate_t for svn_ra_serf__replay_range */ +static svn_error_t * +replay_done(serf_request_t *request, + void *baton, + apr_pool_t *scratch_pool) +{ + struct revision_report_t *ctx = baton; + svn_ra_serf__handler_t *handler = ctx->report_handler; + + if (handler->server_error) + return svn_ra_serf__server_error_create(handler, scratch_pool); + else if (handler->sline.code != 200) + return svn_error_trace(svn_ra_serf__unexpected_status(handler)); + + *ctx->done = TRUE; /* Breaks out svn_ra_serf__context_run_wait */ + + /* Are re replaying multiple revisions? */ + if (ctx->replay_reports) + { + (*ctx->replay_reports)--; + } + + svn_pool_destroy(ctx->pool); /* Destroys handler and request! */ + + return SVN_NO_ERROR; +} + svn_error_t * svn_ra_serf__replay_range(svn_ra_session_t *ra_session, svn_revnum_t start_revision, @@ -646,7 +638,7 @@ svn_ra_serf__replay_range(svn_ra_session svn_ra_replay_revstart_callback_t revstart_func, svn_ra_replay_revfinish_callback_t revfinish_func, void *replay_baton, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { svn_ra_serf__session_t *session = ra_session->priv; svn_revnum_t rev = start_revision; @@ -654,9 +646,9 @@ svn_ra_serf__replay_range(svn_ra_session 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)); + SVN_ERR(svn_ra_serf__report_resource(&report_target, session, + scratch_pool)); /* Prior to 1.8, mod_dav_svn expect to get replay REPORT requests aimed at the session URL. But that's incorrect -- these reports @@ -679,8 +671,7 @@ svn_ra_serf__replay_range(svn_ra_session { SVN_ERR(svn_ra_serf__get_relative_path(&include_path, session->session_url.path, - session, session->conns[0], - pool)); + session, scratch_pool)); } else { @@ -698,30 +689,29 @@ svn_ra_serf__replay_range(svn_ra_session { struct revision_report_t *rev_ctx; svn_ra_serf__handler_t *handler; - apr_pool_t *ctx_pool = svn_pool_create(pool); + apr_pool_t *rev_pool = svn_pool_create(scratch_pool); svn_ra_serf__xml_context_t *xmlctx; const char *replay_target; - rev_ctx = apr_pcalloc(ctx_pool, sizeof(*rev_ctx)); - rev_ctx->pool = ctx_pool; + rev_ctx = apr_pcalloc(rev_pool, sizeof(*rev_ctx)); + rev_ctx->pool = rev_pool; rev_ctx->revstart_func = revstart_func; rev_ctx->revfinish_func = revfinish_func; rev_ctx->replay_baton = replay_baton; rev_ctx->done = &done; - rev_ctx->done_list = &done_reports; + rev_ctx->replay_reports = &active_reports; rev_ctx->include_path = include_path; rev_ctx->revision = rev; rev_ctx->low_water_mark = low_water_mark; rev_ctx->send_deltas = send_deltas; - rev_ctx->done_item.data = rev_ctx; /* Request all properties of a certain revision. */ rev_ctx->rev_props = apr_hash_make(rev_ctx->pool); if (SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(session)) { - rev_ctx->revprop_target = apr_psprintf(pool, "%s/%ld", - session->rev_stub, rev); + rev_ctx->revprop_target = apr_psprintf(rev_pool, "%s/%ld", + session->rev_stub, rev); rev_ctx->revprop_rev = SVN_INVALID_REVNUM; } else @@ -730,14 +720,15 @@ svn_ra_serf__replay_range(svn_ra_session rev_ctx->revprop_rev = rev; } - SVN_ERR(svn_ra_serf__deliver_props2(&rev_ctx->propfind_handler, - session, session->conns[0], + SVN_ERR(svn_ra_serf__create_propfind_handler( + &rev_ctx->propfind_handler, + session, rev_ctx->revprop_target, rev_ctx->revprop_rev, "0", all_props, svn_ra_serf__deliver_svn_props, rev_ctx->rev_props, - rev_ctx->pool)); + rev_pool)); /* Spin up the serf request for the PROPFIND. */ svn_ra_serf__request_create(rev_ctx->propfind_handler); @@ -745,7 +736,7 @@ svn_ra_serf__replay_range(svn_ra_session /* Send the replay REPORT request. */ if (session->supports_rev_rsrc_replay) { - replay_target = apr_psprintf(pool, "%s/%ld", + replay_target = apr_psprintf(rev_pool, "%s/%ld", session->rev_stub, rev); } else @@ -756,16 +747,15 @@ svn_ra_serf__replay_range(svn_ra_session xmlctx = svn_ra_serf__xml_context_create(replay_ttable, replay_opened, replay_closed, replay_cdata, rev_ctx, - ctx_pool); + rev_pool); - handler = svn_ra_serf__create_expat_handler(xmlctx, NULL, ctx_pool); + handler = svn_ra_serf__create_expat_handler(session, xmlctx, NULL, + rev_pool); handler->method = "REPORT"; handler->path = replay_target; handler->body_delegate = create_replay_body; handler->body_delegate_baton = rev_ctx; - handler->conn = session->conns[0]; - handler->session = session; handler->done_delegate = replay_done; handler->done_delegate_baton = rev_ctx; @@ -779,31 +769,11 @@ svn_ra_serf__replay_range(svn_ra_session /* Run the serf loop. */ done = FALSE; - SVN_ERR(svn_ra_serf__context_run_wait(&done, session, pool)); + SVN_ERR(svn_ra_serf__context_run_wait(&done, session, scratch_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. */ - { - svn_ra_serf__list_t *done_list; - - done_list = done_reports; - - 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--; - } - } + /* The done handler of reports decrements active_reports when a report + is done. This same handler reports (fatal) report errors, so we can + just loop here. */ } return SVN_NO_ERROR; Modified: subversion/branches/pin-externals/subversion/libsvn_ra_serf/serf.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_ra_serf/serf.c?rev=1655005&r1=1655004&r2=1655005&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_ra_serf/serf.c (original) +++ subversion/branches/pin-externals/subversion/libsvn_ra_serf/serf.c Tue Jan 27 10:51:52 2015 @@ -801,7 +801,7 @@ svn_ra_serf__reparent(svn_ra_session_t * if (!session->repos_root_str) { const char *vcc_url; - SVN_ERR(svn_ra_serf__discover_vcc(&vcc_url, session, NULL, pool)); + SVN_ERR(svn_ra_serf__discover_vcc(&vcc_url, session, pool)); } if (!svn_uri__is_ancestor(session->repos_root_str, url)) @@ -887,16 +887,19 @@ serf__rev_proplist(svn_ra_session_t *ra_ else { /* Use the VCC as the propfind target path. */ - SVN_ERR(svn_ra_serf__discover_vcc(&propfind_path, session, NULL, + SVN_ERR(svn_ra_serf__discover_vcc(&propfind_path, session, scratch_pool)); } props = apr_hash_make(result_pool); - SVN_ERR(svn_ra_serf__deliver_props2(&handler, session, session->conns[0], - propfind_path, rev, "0", fetch_props, - svn_ra_serf__deliver_svn_props, props, - scratch_pool)); - SVN_ERR(svn_ra_serf__wait_for_props(handler, scratch_pool)); + SVN_ERR(svn_ra_serf__create_propfind_handler(&handler, session, + propfind_path, rev, "0", + fetch_props, + svn_ra_serf__deliver_svn_props, + props, + scratch_pool)); + + SVN_ERR(svn_ra_serf__context_run_one(handler, scratch_pool)); svn_ra_serf__keep_only_regular_props(props, scratch_pool); @@ -971,7 +974,7 @@ svn_ra_serf__get_repos_root(svn_ra_sessi if (!session->repos_root_str) { const char *vcc_url; - SVN_ERR(svn_ra_serf__discover_vcc(&vcc_url, session, NULL, pool)); + SVN_ERR(svn_ra_serf__discover_vcc(&vcc_url, session, pool)); } *url = session->repos_root_str; @@ -1007,7 +1010,7 @@ svn_ra_serf__get_uuid(svn_ra_session_t * /* We're not interested in vcc_url and relative_url, but this call also stores the repository's uuid in the session. */ - SVN_ERR(svn_ra_serf__discover_vcc(&vcc_url, session, NULL, pool)); + SVN_ERR(svn_ra_serf__discover_vcc(&vcc_url, session, pool)); if (!session->uuid) { return svn_error_create(SVN_ERR_RA_DAV_RESPONSE_HEADER_BADNESS, NULL, Modified: subversion/branches/pin-externals/subversion/libsvn_ra_serf/stat.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_ra_serf/stat.c?rev=1655005&r1=1655004&r2=1655005&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_ra_serf/stat.c (original) +++ subversion/branches/pin-externals/subversion/libsvn_ra_serf/stat.c Tue Jan 27 10:51:52 2015 @@ -48,57 +48,41 @@ -static svn_error_t * -fetch_path_props(apr_hash_t **props, - svn_ra_serf__session_t *session, - const char *session_relpath, - svn_revnum_t revision, - const svn_ra_serf__dav_props_t *desired_props, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) +/* Implements svn_ra__vtable_t.check_path(). */ +svn_error_t * +svn_ra_serf__check_path(svn_ra_session_t *ra_session, + const char *relpath, + svn_revnum_t revision, + svn_node_kind_t *kind, + apr_pool_t *scratch_pool) { + svn_ra_serf__session_t *session = ra_session->priv; + apr_hash_t *props; + svn_error_t *err; const char *url; url = session->session_url.path; /* If we have a relative path, append it. */ - if (session_relpath) - url = svn_path_url_add_component2(url, session_relpath, scratch_pool); + if (relpath) + url = svn_path_url_add_component2(url, relpath, scratch_pool); /* If we were given a specific revision, get a URL that refers to that specific revision (rather than floating with HEAD). */ if (SVN_IS_VALID_REVNUM(revision)) { SVN_ERR(svn_ra_serf__get_stable_url(&url, NULL /* latest_revnum */, - session, NULL /* conn */, + session, url, revision, scratch_pool, scratch_pool)); } /* URL is stable, so we use SVN_INVALID_REVNUM since it is now irrelevant. Or we started with SVN_INVALID_REVNUM and URL may be floating. */ - SVN_ERR(svn_ra_serf__fetch_node_props(props, session->conns[0], - url, SVN_INVALID_REVNUM, - desired_props, - result_pool, scratch_pool)); - - return SVN_NO_ERROR; -} - -/* Implements svn_ra__vtable_t.check_path(). */ -svn_error_t * -svn_ra_serf__check_path(svn_ra_session_t *ra_session, - const char *rel_path, - svn_revnum_t revision, - svn_node_kind_t *kind, - apr_pool_t *pool) -{ - svn_ra_serf__session_t *session = ra_session->priv; - apr_hash_t *props; - - svn_error_t *err = fetch_path_props(&props, session, rel_path, - revision, check_path_props, - pool, pool); + err = svn_ra_serf__fetch_node_props(&props, session, + url, SVN_INVALID_REVNUM, + check_path_props, + scratch_pool, scratch_pool); if (err && err->apr_err == SVN_ERR_FS_NOT_FOUND) { @@ -107,18 +91,35 @@ svn_ra_serf__check_path(svn_ra_session_t } else { + apr_hash_t *dav_props; + const char *res_type; + /* Any other error, raise to caller. */ - if (err) - return svn_error_trace(err); + SVN_ERR(err); - SVN_ERR(svn_ra_serf__get_resource_type(kind, props)); + dav_props = apr_hash_get(props, "DAV:", 4); + res_type = svn_prop_get_value(dav_props, "resourcetype"); + if (!res_type) + { + /* How did this happen? */ + return svn_error_create(SVN_ERR_RA_DAV_PROPS_NOT_FOUND, NULL, + _("The PROPFIND response did not include the " + "requested resourcetype value")); + } + + if (strcmp(res_type, "collection") == 0) + *kind = svn_node_dir; + else + *kind = svn_node_file; } return SVN_NO_ERROR; } -struct dirent_walker_baton_t { +/* Baton for fill_dirent_propfunc() */ +struct fill_dirent_baton_t +{ /* Update the fields in this entry. */ svn_dirent_t *entry; @@ -128,76 +129,78 @@ struct dirent_walker_baton_t { apr_pool_t *result_pool; }; +/* Implements svn_ra_serf__prop_func_t */ static svn_error_t * -dirent_walker(void *baton, - const char *ns, - const char *name, - const svn_string_t *val, - apr_pool_t *scratch_pool) +fill_dirent_propfunc(void *baton, + const char *path, + const char *ns, + const char *name, + const svn_string_t *val, + apr_pool_t *scratch_pool) { - struct dirent_walker_baton_t *dwb = baton; + struct fill_dirent_baton_t *fdb = baton; - if (strcmp(ns, SVN_DAV_PROP_NS_CUSTOM) == 0) - { - dwb->entry->has_props = TRUE; - } - else if (strcmp(ns, SVN_DAV_PROP_NS_SVN) == 0) - { - dwb->entry->has_props = TRUE; - } - else if (strcmp(ns, SVN_DAV_PROP_NS_DAV) == 0) - { - if(strcmp(name, "deadprop-count") == 0) - { - if (*val->data) - { - apr_int64_t deadprop_count; - SVN_ERR(svn_cstring_atoi64(&deadprop_count, val->data)); - dwb->entry->has_props = deadprop_count > 0; - if (dwb->supports_deadprop_count) - *dwb->supports_deadprop_count = svn_tristate_true; - } - else if (dwb->supports_deadprop_count) - *dwb->supports_deadprop_count = svn_tristate_false; - } - } - else if (strcmp(ns, "DAV:") == 0) + if (strcmp(ns, "DAV:") == 0) { if (strcmp(name, SVN_DAV__VERSION_NAME) == 0) { apr_int64_t rev; SVN_ERR(svn_cstring_atoi64(&rev, val->data)); - dwb->entry->created_rev = (svn_revnum_t)rev; + fdb->entry->created_rev = (svn_revnum_t)rev; } else if (strcmp(name, "creator-displayname") == 0) { - dwb->entry->last_author = apr_pstrdup(dwb->result_pool, val->data); + fdb->entry->last_author = apr_pstrdup(fdb->result_pool, val->data); } else if (strcmp(name, SVN_DAV__CREATIONDATE) == 0) { - SVN_ERR(svn_time_from_cstring(&dwb->entry->time, + SVN_ERR(svn_time_from_cstring(&fdb->entry->time, val->data, - dwb->result_pool)); + fdb->result_pool)); } else if (strcmp(name, "getcontentlength") == 0) { /* 'getcontentlength' property is empty for directories. */ if (val->len) { - SVN_ERR(svn_cstring_atoi64(&dwb->entry->size, val->data)); + SVN_ERR(svn_cstring_atoi64(&fdb->entry->size, val->data)); } } else if (strcmp(name, "resourcetype") == 0) { if (strcmp(val->data, "collection") == 0) { - dwb->entry->kind = svn_node_dir; + fdb->entry->kind = svn_node_dir; } else { - dwb->entry->kind = svn_node_file; + fdb->entry->kind = svn_node_file; + } + } + } + else if (strcmp(ns, SVN_DAV_PROP_NS_CUSTOM) == 0) + { + fdb->entry->has_props = TRUE; + } + else if (strcmp(ns, SVN_DAV_PROP_NS_SVN) == 0) + { + fdb->entry->has_props = TRUE; + } + else if (strcmp(ns, SVN_DAV_PROP_NS_DAV) == 0) + { + if(strcmp(name, "deadprop-count") == 0) + { + if (*val->data) + { + apr_int64_t deadprop_count; + SVN_ERR(svn_cstring_atoi64(&deadprop_count, val->data)); + fdb->entry->has_props = deadprop_count > 0; + if (fdb->supports_deadprop_count) + *fdb->supports_deadprop_count = svn_tristate_true; } + else if (fdb->supports_deadprop_count) + *fdb->supports_deadprop_count = svn_tristate_false; } } @@ -279,21 +282,47 @@ get_dirent_props(apr_uint32_t dirent_fie /* Implements svn_ra__vtable_t.stat(). */ svn_error_t * svn_ra_serf__stat(svn_ra_session_t *ra_session, - const char *rel_path, + const char *relpath, svn_revnum_t revision, svn_dirent_t **dirent, apr_pool_t *pool) { svn_ra_serf__session_t *session = ra_session->priv; - apr_hash_t *props; svn_error_t *err; - struct dirent_walker_baton_t dwb; + struct fill_dirent_baton_t fdb; svn_tristate_t deadprop_count = svn_tristate_unknown; + svn_ra_serf__handler_t *handler; + const char *url; + + url = session->session_url.path; + + /* If we have a relative path, append it. */ + if (relpath) + url = svn_path_url_add_component2(url, relpath, pool); + + /* If we were given a specific revision, get a URL that refers to that + specific revision (rather than floating with HEAD). */ + if (SVN_IS_VALID_REVNUM(revision)) + { + SVN_ERR(svn_ra_serf__get_stable_url(&url, NULL /* latest_revnum */, + session, + url, revision, + pool, pool)); + } + + fdb.entry = svn_dirent_create(pool); + fdb.supports_deadprop_count = &deadprop_count; + fdb.result_pool = pool; + + SVN_ERR(svn_ra_serf__create_propfind_handler(&handler, session, url, + SVN_INVALID_REVNUM, "0", + get_dirent_props(SVN_DIRENT_ALL, + session, + pool), + fill_dirent_propfunc, &fdb, pool)); + + err = svn_ra_serf__context_run_one(handler, pool); - err = fetch_path_props(&props, - session, rel_path, revision, - get_dirent_props(SVN_DIRENT_ALL, session, pool), - pool, pool); if (err) { if (err->apr_err == SVN_ERR_FS_NOT_FOUND) @@ -306,31 +335,22 @@ svn_ra_serf__stat(svn_ra_session_t *ra_s return svn_error_trace(err); } - dwb.entry = svn_dirent_create(pool); - dwb.supports_deadprop_count = &deadprop_count; - dwb.result_pool = pool; - SVN_ERR(svn_ra_serf__walk_node_props(props, dirent_walker, &dwb, pool)); - if (deadprop_count == svn_tristate_false && session->supports_deadprop_count == svn_tristate_unknown - && !dwb.entry->has_props) + && !fdb.entry->has_props) { /* We have to requery as the server didn't give us the right information */ session->supports_deadprop_count = svn_tristate_false; - SVN_ERR(fetch_path_props(&props, - session, rel_path, SVN_INVALID_REVNUM, - get_dirent_props(SVN_DIRENT_ALL, session, pool), - pool, pool)); - - SVN_ERR(svn_ra_serf__walk_node_props(props, dirent_walker, &dwb, pool)); + /* Run the same handler again */ + SVN_ERR(svn_ra_serf__context_run_one(handler, pool)); } if (deadprop_count != svn_tristate_unknown) session->supports_deadprop_count = deadprop_count; - *dirent = dwb.entry; + *dirent = fdb.entry; return SVN_NO_ERROR; } @@ -346,7 +366,7 @@ struct get_dir_baton_t const char *path; }; -/* Implements svn_ra_serf__prop_func */ +/* Implements svn_ra_serf__prop_func_t */ static svn_error_t * get_dir_dirents_cb(void *baton, const char *path, @@ -362,22 +382,22 @@ get_dir_dirents_cb(void *baton, if (relpath && relpath[0] != '\0') { - struct dirent_walker_baton_t dwb; + struct fill_dirent_baton_t fdb; relpath = svn_path_uri_decode(relpath, scratch_pool); - dwb.entry = svn_hash_gets(db->dirents, relpath); + fdb.entry = svn_hash_gets(db->dirents, relpath); - if (!dwb.entry) + if (!fdb.entry) { - dwb.entry = svn_dirent_create(db->result_pool); + fdb.entry = svn_dirent_create(db->result_pool); svn_hash_sets(db->dirents, apr_pstrdup(db->result_pool, relpath), - dwb.entry); + fdb.entry); } - dwb.result_pool = db->result_pool; - dwb.supports_deadprop_count = &db->supports_deadprop_count; - SVN_ERR(dirent_walker(&dwb, ns, name, value, scratch_pool)); + fdb.result_pool = db->result_pool; + fdb.supports_deadprop_count = &db->supports_deadprop_count; + SVN_ERR(fill_dirent_propfunc(&fdb, path, ns, name, value, scratch_pool)); } else if (relpath && !db->is_directory) { @@ -471,7 +491,7 @@ svn_ra_serf__get_dir(svn_ra_session_t *r if (SVN_IS_VALID_REVNUM(revision) || fetched_rev) { SVN_ERR(svn_ra_serf__get_stable_url(&path, fetched_rev, - session, NULL /* conn */, + session, path, revision, scratch_pool, scratch_pool)); revision = SVN_INVALID_REVNUM; @@ -491,8 +511,8 @@ svn_ra_serf__get_dir(svn_ra_session_t *r gdb.dirents = apr_hash_make(result_pool); - SVN_ERR(svn_ra_serf__deliver_props2(&dirent_handler, - session, session->conns[0], + SVN_ERR(svn_ra_serf__create_propfind_handler( + &dirent_handler, session, path, SVN_INVALID_REVNUM, "1", get_dirent_props(dirent_fields, session, @@ -508,8 +528,8 @@ svn_ra_serf__get_dir(svn_ra_session_t *r if (ret_props) { gdb.ret_props = apr_hash_make(result_pool); - SVN_ERR(svn_ra_serf__deliver_props2(&props_handler, - session, session->conns[0], + SVN_ERR(svn_ra_serf__create_propfind_handler( + &props_handler, session, path, SVN_INVALID_REVNUM, "0", all_props, get_dir_props_cb, &gdb, @@ -526,9 +546,6 @@ svn_ra_serf__get_dir(svn_ra_session_t *r session, scratch_pool)); - if (dirent_handler->sline.code != 207) - return svn_error_trace(svn_ra_serf__unexpected_status(dirent_handler)); - if (gdb.supports_deadprop_count == svn_tristate_false && session->supports_deadprop_count == svn_tristate_unknown && dirent_fields & SVN_DIRENT_HAS_PROPS) @@ -539,8 +556,8 @@ svn_ra_serf__get_dir(svn_ra_session_t *r apr_hash_clear(gdb.dirents); - SVN_ERR(svn_ra_serf__deliver_props2(&dirent_handler, - session, session->conns[0], + SVN_ERR(svn_ra_serf__create_propfind_handler( + &dirent_handler, session, path, SVN_INVALID_REVNUM, "1", get_dirent_props(dirent_fields, session, @@ -557,9 +574,6 @@ svn_ra_serf__get_dir(svn_ra_session_t *r SVN_ERR(svn_ra_serf__context_run_wait(&props_handler->done, session, scratch_pool)); - - if (props_handler->sline.code != 207) - return svn_error_trace(svn_ra_serf__unexpected_status(props_handler)); } /* And dirent again for the case when we had to send the request again */ @@ -568,9 +582,6 @@ svn_ra_serf__get_dir(svn_ra_session_t *r SVN_ERR(svn_ra_serf__context_run_wait(&dirent_handler->done, session, scratch_pool)); - - if (dirent_handler->sline.code != 207) - return svn_error_trace(svn_ra_serf__unexpected_status(dirent_handler)); } if (gdb.supports_deadprop_count != svn_tristate_unknown) Modified: subversion/branches/pin-externals/subversion/libsvn_ra_serf/update.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_ra_serf/update.c?rev=1655005&r1=1655004&r2=1655005&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_ra_serf/update.c (original) +++ subversion/branches/pin-externals/subversion/libsvn_ra_serf/update.c Tue Jan 27 10:51:52 2015 @@ -1429,7 +1429,7 @@ fetch_for_file(file_baton_t *file, file->base_rev, svn_path_uri_encode( file->repos_relpath, - file->pool)); + scratch_pool)); } else if (file->copyfrom_path) { @@ -1440,7 +1440,7 @@ fetch_for_file(file_baton_t *file, file->copyfrom_rev, svn_path_uri_encode( file->copyfrom_path+1, - file->pool)); + scratch_pool)); } } else if (ctx->sess->wc_callbacks->get_wc_prop) @@ -1461,13 +1461,12 @@ fetch_for_file(file_baton_t *file, : NULL; } - handler = svn_ra_serf__create_handler(file->pool); + handler = svn_ra_serf__create_handler(ctx->sess, file->pool); handler->method = "GET"; handler->path = file->url; - handler->conn = conn; - handler->session = ctx->sess; + handler->conn = conn; /* Explicit scheduling */ handler->custom_accept_encoding = TRUE; handler->no_dav_headers = TRUE; @@ -1494,12 +1493,13 @@ fetch_for_file(file_baton_t *file, /* If needed, create the PROPFIND to retrieve the file's properties. */ if (file->fetch_props) { - SVN_ERR(svn_ra_serf__deliver_props2(&file->propfind_handler, - ctx->sess, conn, file->url, - ctx->target_rev, "0", all_props, - set_file_props, file, - file->pool)); - SVN_ERR_ASSERT(file->propfind_handler); + SVN_ERR(svn_ra_serf__create_propfind_handler(&file->propfind_handler, + ctx->sess, file->url, + ctx->target_rev, "0", + all_props, + set_file_props, file, + file->pool)); + file->propfind_handler->conn = conn; /* Explicit scheduling */ file->propfind_handler->done_delegate = file_props_done; file->propfind_handler->done_delegate_baton = file; @@ -1591,13 +1591,14 @@ fetch_for_dir(dir_baton_t *dir, /* If needed, create the PROPFIND to retrieve the file's properties. */ if (dir->fetch_props) { - SVN_ERR(svn_ra_serf__deliver_props2(&dir->propfind_handler, - ctx->sess, conn, dir->url, - ctx->target_rev, "0", all_props, - set_dir_prop, dir, - dir->pool)); - SVN_ERR_ASSERT(dir->propfind_handler); + SVN_ERR(svn_ra_serf__create_propfind_handler(&dir->propfind_handler, + ctx->sess, dir->url, + ctx->target_rev, "0", + all_props, + set_dir_prop, dir, + dir->pool)); + dir->propfind_handler->conn = conn; dir->propfind_handler->done_delegate = dir_props_done; dir->propfind_handler->done_delegate_baton = dir; @@ -2262,10 +2263,8 @@ link_path(void *report_baton, _("Unable to parse URL '%s'"), url); } - SVN_ERR(svn_ra_serf__report_resource(&report_target, report->sess, - NULL, pool)); - SVN_ERR(svn_ra_serf__get_relative_path(&link, uri.path, report->sess, - NULL, pool)); + SVN_ERR(svn_ra_serf__report_resource(&report_target, report->sess, pool)); + SVN_ERR(svn_ra_serf__get_relative_path(&link, uri.path, report->sess, pool)); link = apr_pstrcat(pool, "/", link, SVN_VA_NULL); @@ -2657,15 +2656,15 @@ finish_report(void *report_baton, SVN_ERR(svn_stream_write(report->body_template, buf->data, &buf->len)); SVN_ERR(svn_stream_close(report->body_template)); - SVN_ERR(svn_ra_serf__report_resource(&report_target, sess, NULL, - scratch_pool)); + SVN_ERR(svn_ra_serf__report_resource(&report_target, sess, scratch_pool)); xmlctx = svn_ra_serf__xml_context_create(update_ttable, update_opened, update_closed, update_cdata, report, scratch_pool); - handler = svn_ra_serf__create_expat_handler(xmlctx, NULL, scratch_pool); + handler = svn_ra_serf__create_expat_handler(sess, xmlctx, NULL, + scratch_pool); handler->method = "REPORT"; handler->path = report_target; @@ -2675,8 +2674,6 @@ finish_report(void *report_baton, handler->custom_accept_encoding = TRUE; handler->header_delegate = setup_update_report_headers; handler->header_delegate_baton = report; - handler->conn = sess->conns[0]; - handler->session = sess; svn_ra_serf__request_create(handler); Modified: subversion/branches/pin-externals/subversion/libsvn_ra_serf/util.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_ra_serf/util.c?rev=1655005&r1=1655004&r2=1655005&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_ra_serf/util.c (original) +++ subversion/branches/pin-externals/subversion/libsvn_ra_serf/util.c Tue Jan 27 10:51:52 2015 @@ -567,6 +567,7 @@ accept_response(serf_request_t *request, void *acceptor_baton, apr_pool_t *pool) { + /* svn_ra_serf__handler_t *handler = acceptor_baton; */ serf_bucket_t *c; serf_bucket_alloc_t *bkt_alloc; @@ -584,6 +585,7 @@ accept_head(serf_request_t *request, void *acceptor_baton, apr_pool_t *pool) { + /* svn_ra_serf__handler_t *handler = acceptor_baton; */ serf_bucket_t *response; response = accept_response(request, stream, acceptor_baton, pool); @@ -601,7 +603,7 @@ connection_closed(svn_ra_serf__connectio { if (why) { - return svn_error_wrap_apr(why, NULL); + return svn_ra_serf__wrap_err(why, NULL); } if (conn->session->using_ssl) @@ -831,9 +833,14 @@ setup_serf_req(serf_request_t *request, serf_bucket_headers_setn(*hdrs_bkt, "Accept-Encoding", accept_encoding); } - /* These headers need to be sent with every request except GET; see + /* These headers need to be sent with every request that might need + capability processing (e.g. during commit, reports, etc.), see issue #3255 ("mod_dav_svn does not pass client capabilities to - start-commit hooks") for why. */ + start-commit hooks") for why. + + Some request types like GET/HEAD/PROPFIND are unaware of capability + handling; and in some cases the responses can even be cached by + proxies, so we don't have to send these hearders there. */ if (dav_headers) { serf_bucket_headers_setn(*hdrs_bkt, "DAV", SVN_DAV_NS_DAV_SVN_DEPTH); @@ -1534,7 +1541,7 @@ setup_request_cb(serf_request_t *request *acceptor = accept_head; else *acceptor = accept_response; - *acceptor_baton = handler->session; + *acceptor_baton = handler; *s_handler = handle_response_cb; *s_handler_baton = handler; @@ -1580,8 +1587,7 @@ svn_ra_serf__request_create(svn_ra_serf_ svn_error_t * svn_ra_serf__discover_vcc(const char **vcc_url, svn_ra_serf__session_t *session, - svn_ra_serf__connection_t *conn, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { const char *path; const char *relative_path; @@ -1594,12 +1600,6 @@ svn_ra_serf__discover_vcc(const char **v return SVN_NO_ERROR; } - /* If no connection is provided, use the default one. */ - if (! conn) - { - conn = session->conns[0]; - } - path = session->session_url.path; *vcc_url = NULL; uuid = NULL; @@ -1609,9 +1609,10 @@ svn_ra_serf__discover_vcc(const char **v apr_hash_t *props; svn_error_t *err; - err = svn_ra_serf__fetch_node_props(&props, conn, + err = svn_ra_serf__fetch_node_props(&props, session, path, SVN_INVALID_REVNUM, - base_props, pool, pool); + base_props, + scratch_pool, scratch_pool); if (! err) { apr_hash_t *ns_props; @@ -1639,7 +1640,7 @@ svn_ra_serf__discover_vcc(const char **v svn_error_clear(err); /* Okay, strip off a component from PATH. */ - path = svn_urlpath__dirname(path, pool); + path = svn_urlpath__dirname(path, scratch_pool); } } } @@ -1665,7 +1666,7 @@ svn_ra_serf__discover_vcc(const char **v { svn_stringbuf_t *url_buf; - url_buf = svn_stringbuf_create(path, pool); + url_buf = svn_stringbuf_create(path, scratch_pool); svn_path_remove_components(url_buf, svn_path_component_count(relative_path)); @@ -1693,7 +1694,6 @@ svn_error_t * svn_ra_serf__get_relative_path(const char **rel_path, const char *orig_path, svn_ra_serf__session_t *session, - svn_ra_serf__connection_t *conn, apr_pool_t *pool) { const char *decoded_root, *decoded_orig; @@ -1710,7 +1710,6 @@ svn_ra_serf__get_relative_path(const cha promises to populate the session's root-url cache, and that's what we really want. */ SVN_ERR(svn_ra_serf__discover_vcc(&vcc_url, session, - conn ? conn : session->conns[0], pool)); } @@ -1724,7 +1723,6 @@ svn_ra_serf__get_relative_path(const cha svn_error_t * svn_ra_serf__report_resource(const char **report_target, svn_ra_serf__session_t *session, - svn_ra_serf__connection_t *conn, apr_pool_t *pool) { /* If we have HTTP v2 support, we want to report against the 'me' @@ -1734,7 +1732,7 @@ svn_ra_serf__report_resource(const char /* Otherwise, we'll use the default VCC. */ else - SVN_ERR(svn_ra_serf__discover_vcc(report_target, session, conn, pool)); + SVN_ERR(svn_ra_serf__discover_vcc(report_target, session, pool)); return SVN_NO_ERROR; } @@ -1839,7 +1837,7 @@ svn_ra_serf__register_editor_shim_callba return SVN_NO_ERROR; } -/* Shandard done_delegate handler */ +/* Shared/standard done_delegate handler */ static svn_error_t * response_done(serf_request_t *request, void *handler_baton, @@ -1887,7 +1885,8 @@ handler_cleanup(void *baton) } svn_ra_serf__handler_t * -svn_ra_serf__create_handler(apr_pool_t *result_pool) +svn_ra_serf__create_handler(svn_ra_serf__session_t *session, + apr_pool_t *result_pool) { svn_ra_serf__handler_t *handler; @@ -1897,6 +1896,9 @@ svn_ra_serf__create_handler(apr_pool_t * apr_pool_cleanup_register(result_pool, handler, handler_cleanup, apr_pool_cleanup_null); + handler->session = session; + handler->conn = session->conns[0]; + /* Setup the default done handler, to handle server errors */ handler->done_delegate_baton = handler; handler->done_delegate = response_done; Modified: subversion/branches/pin-externals/subversion/libsvn_ra_serf/xml.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_ra_serf/xml.c?rev=1655005&r1=1655004&r2=1655005&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_ra_serf/xml.c (original) +++ subversion/branches/pin-externals/subversion/libsvn_ra_serf/xml.c Tue Jan 27 10:51:52 2015 @@ -1087,7 +1087,8 @@ expat_response_handler(serf_request_t *r svn_ra_serf__handler_t * -svn_ra_serf__create_expat_handler(svn_ra_serf__xml_context_t *xmlctx, +svn_ra_serf__create_expat_handler(svn_ra_serf__session_t *session, + svn_ra_serf__xml_context_t *xmlctx, const int *expected_status, apr_pool_t *result_pool) { @@ -1100,7 +1101,7 @@ svn_ra_serf__create_expat_handler(svn_ra ectx->expected_status = expected_status; ectx->cleanup_pool = result_pool; - handler = svn_ra_serf__create_handler(result_pool); + handler = svn_ra_serf__create_handler(session, result_pool); handler->response_handler = expat_response_handler; handler->response_baton = ectx; Modified: subversion/branches/pin-externals/subversion/libsvn_repos/dump.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_repos/dump.c?rev=1655005&r1=1655004&r2=1655005&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_repos/dump.c (original) +++ subversion/branches/pin-externals/subversion/libsvn_repos/dump.c Tue Jan 27 10:51:52 2015 @@ -990,6 +990,34 @@ check_mergeinfo_normalization(const char } +/* A special case of dump_node(), for a delete record. + * + * The only thing special about this version is it only writes one blank + * line, not two, after the headers. Why? Historical precedent for the + * case where a delete record is used as part of a (delete + add-with-history) + * in implementing a replacement. + * + * Also it doesn't do a path-tracker check. + */ +static svn_error_t * +dump_node_delete(svn_stream_t *stream, + const char *node_relpath, + apr_pool_t *pool) +{ + apr_array_header_t *headers = svn_repos__dumpfile_headers_create(pool); + + /* Node-path: ... */ + svn_repos__dumpfile_header_push( + headers, SVN_REPOS_DUMPFILE_NODE_PATH, node_relpath); + + /* Node-action: delete */ + svn_repos__dumpfile_header_push( + headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "delete"); + + SVN_ERR(svn_repos__dump_headers(stream, headers, TRUE, pool)); + return SVN_NO_ERROR; +} + /* This helper is the main "meat" of the editor -- it does all the work of writing a node record. @@ -1069,8 +1097,9 @@ dump_node(struct edit_baton *eb, compare_rev = cmp_rev; } - if (action == svn_node_action_change) + switch (action) { + case svn_node_action_change: if (eb->path_tracker) SVN_ERR_W(node_must_exist(eb, path, eb->current_rev, kind, pool), apr_psprintf(pool, _("Change invalid path '%s' in r%ld"), @@ -1091,9 +1120,27 @@ dump_node(struct edit_baton *eb, SVN_ERR(svn_fs_contents_different(&must_dump_text, compare_root, compare_path, eb->fs_root, path, pool)); - } - else if (action == svn_node_action_replace) - { + break; + + case svn_node_action_delete: + if (eb->path_tracker) + { + SVN_ERR_W(node_must_exist(eb, path, eb->current_rev, kind, pool), + apr_psprintf(pool, _("Deleting invalid path '%s' in r%ld"), + path, eb->current_rev)); + tracker_path_delete(eb->path_tracker, path); + } + + svn_repos__dumpfile_header_push( + headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "delete"); + + /* we can leave this routine quietly now, don't need to dump + any content. */ + must_dump_text = FALSE; + must_dump_props = FALSE; + break; + + case svn_node_action_replace: if (eb->path_tracker) SVN_ERR_W(node_must_exist(eb, path, eb->current_rev, svn_node_unknown, pool), @@ -1114,63 +1161,28 @@ dump_node(struct edit_baton *eb, if (kind == svn_node_file) must_dump_text = TRUE; must_dump_props = TRUE; + break; } else { + /* more complex: delete original, then add-with-history. */ + /* ### Why not write a 'replace' record? Don't know. */ + if (eb->path_tracker) { - SVN_ERR_W(node_must_exist(eb, compare_path, compare_rev, - kind, pool), - apr_psprintf(pool, - _("Replacing path '%s' in r%ld " - "with invalid path"), - path, eb->current_rev)); - - /* we will call dump_node again with an addition further - down the road */ tracker_path_delete(eb->path_tracker, path); } - /* more complex: delete original, then add-with-history. */ - - /* the path & kind headers have already been printed; just - add a delete action, and end the current record.*/ - svn_repos__dumpfile_header_push( - headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "delete"); - - SVN_ERR(svn_repos__dump_headers(eb->stream, headers, TRUE, pool)); - /* ### Unusually, here we end this node record with only a single + /* ### Unusually, we end this 'delete' node record with only a single blank line after the header block -- no extra blank line. */ + SVN_ERR(dump_node_delete(eb->stream, path, pool)); - /* recurse: print an additional add-with-history record. */ - SVN_ERR(dump_node(eb, path, kind, svn_node_action_add, - is_copy, compare_path, compare_rev, pool)); - - /* we can leave this routine quietly now, don't need to dump - any content; that was already done in the second record. */ - return SVN_NO_ERROR; + /* The remaining action is a non-replacing add-with-history */ + /* action = svn_node_action_add; */ } - } - else if (action == svn_node_action_delete) - { - if (eb->path_tracker) - { - SVN_ERR_W(node_must_exist(eb, path, eb->current_rev, kind, pool), - apr_psprintf(pool, _("Deleting invalid path '%s' in r%ld"), - path, eb->current_rev)); - tracker_path_delete(eb->path_tracker, path); - } - - svn_repos__dumpfile_header_push( - headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "delete"); + /* FALL THROUGH to 'add' */ - /* we can leave this routine quietly now, don't need to dump - any content. */ - must_dump_text = FALSE; - must_dump_props = FALSE; - } - else if (action == svn_node_action_add) - { + case svn_node_action_add: if (eb->path_tracker) SVN_ERR_W(node_must_not_exist(eb, path, eb->current_rev, pool), apr_psprintf(pool, @@ -1258,6 +1270,7 @@ dump_node(struct edit_baton *eb, headers, SVN_REPOS_DUMPFILE_TEXT_COPY_SOURCE_SHA1, hex_digest); } } + break; } if ((! must_dump_text) && (! must_dump_props)) Modified: subversion/branches/pin-externals/subversion/libsvn_subr/checksum.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_subr/checksum.c?rev=1655005&r1=1655004&r2=1655005&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_subr/checksum.c (original) +++ subversion/branches/pin-externals/subversion/libsvn_subr/checksum.c Tue Jan 27 10:51:52 2015 @@ -165,12 +165,15 @@ checksum_create_without_digest(svn_check return checksum; } +/* Return a checksum object, allocated in POOL. The checksum will be of + * type KIND and contain the given DIGEST. + */ static svn_checksum_t * checksum_create(svn_checksum_kind_t kind, - apr_size_t digest_size, const unsigned char *digest, apr_pool_t *pool) { + apr_size_t digest_size = DIGESTSIZE(kind); svn_checksum_t *checksum = checksum_create_without_digest(kind, digest_size, pool); memcpy((unsigned char *)checksum->digest, digest, digest_size); @@ -206,32 +209,28 @@ svn_checksum_t * svn_checksum__from_digest_md5(const unsigned char *digest, apr_pool_t *result_pool) { - return checksum_create(svn_checksum_md5, APR_MD5_DIGESTSIZE, digest, - result_pool); + return checksum_create(svn_checksum_md5, digest, result_pool); } svn_checksum_t * svn_checksum__from_digest_sha1(const unsigned char *digest, apr_pool_t *result_pool) { - return checksum_create(svn_checksum_sha1, APR_SHA1_DIGESTSIZE, digest, - result_pool); + return checksum_create(svn_checksum_sha1, digest, result_pool); } svn_checksum_t * svn_checksum__from_digest_fnv1a_32(const unsigned char *digest, apr_pool_t *result_pool) { - return checksum_create(svn_checksum_fnv1a_32, sizeof(digest), digest, - result_pool); + return checksum_create(svn_checksum_fnv1a_32, digest, result_pool); } svn_checksum_t * svn_checksum__from_digest_fnv1a_32x4(const unsigned char *digest, apr_pool_t *result_pool) { - return checksum_create(svn_checksum_fnv1a_32x4, sizeof(digest), digest, - result_pool); + return checksum_create(svn_checksum_fnv1a_32x4, digest, result_pool); } svn_error_t * @@ -428,10 +427,7 @@ svn_checksum_dup(const svn_checksum_t *c case svn_checksum_sha1: case svn_checksum_fnv1a_32: case svn_checksum_fnv1a_32x4: - return checksum_create(checksum->kind, - digest_sizes[checksum->kind], - checksum->digest, - pool); + return checksum_create(checksum->kind, checksum->digest, pool); default: SVN_ERR_MALFUNCTION_NO_RETURN(); @@ -492,10 +488,7 @@ svn_checksum_empty_checksum(svn_checksum case svn_checksum_sha1: case svn_checksum_fnv1a_32: case svn_checksum_fnv1a_32x4: - return checksum_create(kind, - digest_sizes[kind], - empty_string_digests[kind], - pool); + return checksum_create(kind, empty_string_digests[kind], pool); default: /* We really shouldn't get here, but if we do... */ Modified: subversion/branches/pin-externals/subversion/libsvn_wc/wc_db.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_wc/wc_db.c?rev=1655005&r1=1655004&r2=1655005&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_wc/wc_db.c (original) +++ subversion/branches/pin-externals/subversion/libsvn_wc/wc_db.c Tue Jan 27 10:51:52 2015 @@ -1591,19 +1591,32 @@ svn_wc__db_init(svn_wc__db_t *db, FALSE /* auto-upgrade */, db->state_pool, scratch_pool)); - /* The WCROOT is complete. Stash it into DB. */ - svn_hash_sets(db->dir_data, wcroot->abspath, wcroot); + /* Any previously cached children may now have a new WCROOT, most likely that + of the new WCROOT, but there might be descendant directories that are their + own working copy, in which case setting WCROOT to our new WCROOT might + actually break things for those. + + Clearing is the safest thing we can do in this case, as a test would lead + to unnecessary probing, while the standard code probes later anyway. So we + only lose a bit of memory - /* Any previously cached children now have a new WCROOT. */ + ### Perhaps we could check wcroot->abspath to detect which case we have + where, but currently it is already very hard to trigger this from + the short living 'svn' client. (GUI clients like TortoiseSVN are far + more likely to get in these cases) + */ for (hi = apr_hash_first(scratch_pool, db->dir_data); hi; hi = apr_hash_next(hi)) { const char *abspath = apr_hash_this_key(hi); if (svn_dirent_is_ancestor(wcroot->abspath, abspath)) - svn_hash_sets(db->dir_data, abspath, wcroot); + svn_hash_sets(db->dir_data, abspath, NULL); } + /* The WCROOT is complete. Stash it into DB. */ + svn_hash_sets(db->dir_data, wcroot->abspath, wcroot); + return SVN_NO_ERROR; } Modified: subversion/branches/pin-externals/subversion/mod_dav_svn/liveprops.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/mod_dav_svn/liveprops.c?rev=1655005&r1=1655004&r2=1655005&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/mod_dav_svn/liveprops.c (original) +++ subversion/branches/pin-externals/subversion/mod_dav_svn/liveprops.c Tue Jan 27 10:51:52 2015 @@ -36,6 +36,7 @@ #include "svn_time.h" #include "svn_dav.h" #include "svn_props.h" +#include "svn_ctype.h" #include "private/svn_dav_protocol.h" @@ -422,7 +423,43 @@ insert_prop_internal(const dav_resource if (last_author == NULL) return DAV_PROP_INSERT_NOTDEF; - value = apr_xml_quote_string(scratch_pool, last_author->data, 1); + if (svn_xml_is_xml_safe(last_author->data, last_author->len) + || !resource->info->repos->is_svn_client) + value = apr_xml_quote_string(scratch_pool, last_author->data, 1); + else + { + /* We are talking to a Subversion client, which will (like any proper + xml parser) error out if we produce control characters in XML. + + However Subversion clients process both the generic + <creator-displayname /> as the custom element for svn:author. + + Let's skip outputting the invalid characters here to make the XML + valid, so clients can see the custom element. + + Subversion Clients will then either use a slightly invalid + author (unlikely) or more likely use the second result, which + will be transferred with full escaping capabilities. + + We have tests in place to assert proper behavior over the RA layer. + */ + apr_size_t i; + svn_stringbuf_t *buf; + + buf = svn_stringbuf_create_from_string(last_author, scratch_pool); + + for (i = 0; i < buf->len; i++) + { + char c = buf->data[i]; + + if (svn_ctype_iscntrl(c)) + { + svn_stringbuf_remove(buf, i--, 1); + } + } + + value = apr_xml_quote_string(scratch_pool, buf->data, 1); + } break; } Modified: subversion/branches/pin-externals/subversion/svnrdump/dump_editor.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/svnrdump/dump_editor.c?rev=1655005&r1=1655004&r2=1655005&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/svnrdump/dump_editor.c (original) +++ subversion/branches/pin-externals/subversion/svnrdump/dump_editor.c Tue Jan 27 10:51:52 2015 @@ -136,11 +136,10 @@ struct dump_edit_baton { /* The revision we're currently dumping. */ svn_revnum_t current_revision; - /* The kind (file or directory) and baton of the item whose block of + /* The baton of the directory node whose block of dump stream data has not been fully completed; NULL if there's no such item. */ - svn_node_kind_t pending_kind; - void *pending_baton; + struct dir_baton *pending_db; }; /* Make a directory baton to represent the directory at PATH (relative @@ -252,16 +251,31 @@ get_props_content(apr_array_header_t *he return SVN_NO_ERROR; } +/* A special case of dump_node(), for a delete record. + * + * The only thing special about this version is it only writes one blank + * line, not two, after the headers. Why? Historical precedent for the + * case where a delete record is used as part of a (delete + add-with-history) + * in implementing a replacement. + */ static svn_error_t * -do_dump_newlines(struct dump_edit_baton *eb, - svn_boolean_t *trigger_var, +dump_node_delete(svn_stream_t *stream, + const char *node_relpath, apr_pool_t *pool) { - if (trigger_var && *trigger_var) - { - SVN_ERR(svn_stream_puts(eb->stream, "\n\n")); - *trigger_var = FALSE; - } + apr_array_header_t *headers = svn_repos__dumpfile_headers_create(pool); + + assert(svn_relpath_is_canonical(node_relpath)); + + /* Node-path: ... */ + svn_repos__dumpfile_header_push( + headers, SVN_REPOS_DUMPFILE_NODE_PATH, node_relpath); + + /* Node-action: delete */ + svn_repos__dumpfile_header_push( + headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "delete"); + + SVN_ERR(svn_repos__dump_headers(stream, headers, TRUE, pool)); return SVN_NO_ERROR; } @@ -327,24 +341,20 @@ dump_node(struct dump_edit_baton *eb, headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "change"); break; - case svn_node_action_replace: - if (is_copy) - { - /* More complex case: is_copy is true, and copyfrom_path/ - copyfrom_rev are present: delete the original, and then re-add - it */ - - svn_repos__dumpfile_header_push( - headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "delete"); + case svn_node_action_delete: + /* Node-action: delete */ + svn_repos__dumpfile_header_push( + headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "delete"); - SVN_ERR(svn_repos__dump_headers(eb->stream, headers, TRUE, pool)); + /* We can leave this routine quietly now. Nothing more to do- + print the headers terminated by one blank line, and an extra + blank line because we're not dumping props or text. */ + SVN_ERR(svn_repos__dump_headers(eb->stream, headers, TRUE, pool)); + SVN_ERR(svn_stream_puts(eb->stream, "\n")); + return SVN_NO_ERROR; - /* Recurse: Print an additional add-with-history record. */ - SVN_ERR(dump_node(eb, repos_relpath, db, fb, svn_node_action_add, - is_copy, copyfrom_path, copyfrom_rev, pool)); - return SVN_NO_ERROR; - } - else + case svn_node_action_replace: + if (! is_copy) { /* Node-action: replace */ svn_repos__dumpfile_header_push( @@ -356,21 +366,23 @@ dump_node(struct dump_edit_baton *eb, fb->dump_props = TRUE; else if (db) db->dump_props = TRUE; + break; } - break; - - case svn_node_action_delete: - /* Node-action: delete */ - svn_repos__dumpfile_header_push( - headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "delete"); + else + { + /* More complex case: is_copy is true, and copyfrom_path/ + copyfrom_rev are present: delete the original, and then re-add + it */ + /* ### Why not write a 'replace' record? Don't know. */ - /* We can leave this routine quietly now. Nothing more to do- - print the headers terminated by one blank line, and an extra - blank line because we're not dumping props or text. */ - SVN_ERR(svn_repos__dump_headers(eb->stream, headers, TRUE, pool)); - SVN_ERR(svn_stream_puts(eb->stream, "\n")); + /* ### Unusually, we end this 'delete' node record with only a single + blank line after the header block -- no extra blank line. */ + SVN_ERR(dump_node_delete(eb->stream, repos_relpath, pool)); - return SVN_NO_ERROR; + /* The remaining action is a non-replacing add-with-history */ + /* action = svn_node_action_add; */ + } + /* FALL THROUGH to 'add' */ case svn_node_action_add: /* Node-action: add */ @@ -466,55 +478,26 @@ dump_mkdir(struct dump_edit_baton *eb, return SVN_NO_ERROR; } -/* Dump pending items from the specified node, to allow starting the dump - of a child node */ +/* Dump pending headers and properties for the directory DB, + to allow starting the dump of a child node */ static svn_error_t * -dump_pending(struct dump_edit_baton *eb, - apr_pool_t *scratch_pool) +dump_pending_dir(struct dump_edit_baton *eb, + apr_pool_t *scratch_pool) { - svn_boolean_t dump_props = FALSE; - apr_hash_t *props, *deleted_props; + struct dir_baton *db = eb->pending_db; - if (! eb->pending_baton) + if (! db) return SVN_NO_ERROR; /* Some pending properties to dump? */ - if (eb->pending_kind == svn_node_dir) - { - struct dir_baton *db = eb->pending_baton; - - if (db->dump_props) - { - dump_props = TRUE; - props = db->props; - deleted_props = db->deleted_props; - - db->dump_props = FALSE; - } - } - else if (eb->pending_kind == svn_node_file) - { - struct file_baton *fb = eb->pending_baton; - - if (fb->dump_props) - { - dump_props = TRUE; - props = fb->props; - deleted_props = fb->deleted_props; - fb->dump_props = FALSE; - } - } - else - abort(); - - if (dump_props) + if (db->dump_props) { apr_array_header_t *headers = svn_repos__dumpfile_headers_create(scratch_pool); svn_stringbuf_t *content; apr_size_t len; - SVN_ERR(get_props_content(headers, &content, props, deleted_props, + SVN_ERR(get_props_content(headers, &content, db->props, db->deleted_props, scratch_pool, scratch_pool)); /* Content-length: 14 */ @@ -533,21 +516,20 @@ dump_pending(struct dump_edit_baton *eb, SVN_ERR(svn_stream_puts(eb->stream, "\n\n")); /* Cleanup so that data is never dumped twice. */ - apr_hash_clear(props); - apr_hash_clear(deleted_props); + apr_hash_clear(db->props); + apr_hash_clear(db->deleted_props); + db->dump_props = FALSE; } - if (eb->pending_kind == svn_node_dir) + /* Some pending newlines to dump? */ + if (db->dump_newlines) { - struct dir_baton *db = eb->pending_baton; - - /* Some pending newlines to dump? */ - SVN_ERR(do_dump_newlines(eb, &(db->dump_newlines), scratch_pool)); + SVN_ERR(svn_stream_puts(eb->stream, "\n\n")); + db->dump_newlines = FALSE; } /* Anything that was pending is pending no longer. */ - eb->pending_baton = NULL; - eb->pending_kind = svn_node_none; + eb->pending_db = NULL; return SVN_NO_ERROR; } @@ -607,8 +589,7 @@ open_root(void *edit_baton, /* Remember that we've started but not yet finished handling this directory. */ - eb->pending_baton = new_db; - eb->pending_kind = svn_node_dir; + eb->pending_db = new_db; } } svn_pool_destroy(iterpool); @@ -632,7 +613,7 @@ delete_entry(const char *path, { struct dir_baton *pb = parent_baton; - SVN_ERR(dump_pending(pb->eb, pool)); + SVN_ERR(dump_pending_dir(pb->eb, pool)); /* We don't dump this deletion immediate. Rather, we add this path to the deleted_entries of the parent directory baton. That way, @@ -656,7 +637,7 @@ add_directory(const char *path, struct dir_baton *new_db; svn_boolean_t is_copy; - SVN_ERR(dump_pending(pb->eb, pool)); + SVN_ERR(dump_pending_dir(pb->eb, pool)); new_db = make_dir_baton(path, copyfrom_path, copyfrom_rev, pb->eb, pb, pb->pool); @@ -681,8 +662,7 @@ add_directory(const char *path, /* Remember that we've started, but not yet finished handling this directory. */ - pb->eb->pending_baton = new_db; - pb->eb->pending_kind = svn_node_dir; + pb->eb->pending_db = new_db; *child_baton = new_db; return SVN_NO_ERROR; @@ -700,7 +680,7 @@ open_directory(const char *path, const char *copyfrom_path = NULL; svn_revnum_t copyfrom_rev = SVN_INVALID_REVNUM; - SVN_ERR(dump_pending(pb->eb, pool)); + SVN_ERR(dump_pending_dir(pb->eb, pool)); /* If the parent directory has explicit comparison path and rev, record the same for this one. */ @@ -728,9 +708,9 @@ close_directory(void *dir_baton, svn_boolean_t this_pending; /* Remember if this directory is the one currently pending. */ - this_pending = (db->eb->pending_baton == db); + this_pending = (db->eb->pending_db == db); - SVN_ERR(dump_pending(db->eb, pool)); + SVN_ERR(dump_pending_dir(db->eb, pool)); /* If this directory was pending, then dump_pending() should have taken care of all the props and such. Of course, the only way @@ -746,9 +726,8 @@ close_directory(void *dir_baton, SVN_ERR(dump_node(db->eb, db->repos_relpath, db, NULL, svn_node_action_change, FALSE, NULL, SVN_INVALID_REVNUM, pool)); - db->eb->pending_baton = db; - db->eb->pending_kind = svn_node_dir; - SVN_ERR(dump_pending(db->eb, pool)); + db->eb->pending_db = db; + SVN_ERR(dump_pending_dir(db->eb, pool)); } /* Dump the deleted directory entries */ @@ -779,7 +758,7 @@ add_file(const char *path, struct file_baton *fb; void *was_deleted; - SVN_ERR(dump_pending(pb->eb, pool)); + SVN_ERR(dump_pending_dir(pb->eb, pool)); /* Make the file baton. */ fb = make_file_baton(path, pb, pool); @@ -814,7 +793,7 @@ open_file(const char *path, struct dir_baton *pb = parent_baton; struct file_baton *fb; - SVN_ERR(dump_pending(pb->eb, pool)); + SVN_ERR(dump_pending_dir(pb->eb, pool)); /* Make the file baton. */ fb = make_file_baton(path, pb, pool); @@ -844,9 +823,9 @@ change_dir_prop(void *parent_baton, /* This directory is not pending, but something else is, so handle the "something else". */ - this_pending = (db->eb->pending_baton == db); + this_pending = (db->eb->pending_db == db); if (! this_pending) - SVN_ERR(dump_pending(db->eb, pool)); + SVN_ERR(dump_pending_dir(db->eb, pool)); if (svn_property_kind2(name) != svn_prop_regular_kind) return SVN_NO_ERROR; @@ -928,7 +907,7 @@ close_file(void *file_baton, svn_stringbuf_t *propstring; apr_array_header_t *headers = svn_repos__dumpfile_headers_create(pool); - SVN_ERR(dump_pending(eb, pool)); + SVN_ERR(dump_pending_dir(eb, pool)); /* Dump the node. */ SVN_ERR(dump_node(eb, fb->repos_relpath, NULL, fb, @@ -1158,7 +1137,7 @@ svn_rdump__get_dump_editor(const svn_del eb->ra_session = ra_session; eb->update_anchor_relpath = update_anchor_relpath; eb->current_revision = revision; - eb->pending_kind = svn_node_none; + eb->pending_db = NULL; /* Create a special per-revision pool */ eb->pool = svn_pool_create(pool); Modified: subversion/branches/pin-externals/subversion/tests/cmdline/prop_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/tests/cmdline/prop_tests.py?rev=1655005&r1=1655004&r2=1655005&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/tests/cmdline/prop_tests.py (original) +++ subversion/branches/pin-externals/subversion/tests/cmdline/prop_tests.py Tue Jan 27 10:51:52 2015 @@ -2619,7 +2619,6 @@ def peg_rev_base_working(sbox): sbox.ospath('iota') + '@BASE') @Issue(4415) -@XFail(svntest.main.is_ra_type_dav) def xml_unsafe_author(sbox): "svn:author with XML unsafe chars" @@ -2646,22 +2645,70 @@ def xml_unsafe_author(sbox): # mod_dav_svn sends svn:author (via PROPFIND for DAV) # Since r1553367 this works correctly on ra_serf, since we now request - # a single property value which somehow triggers different behavior + # a single property value which skips creating the creator-displayname property svntest.actions.run_and_verify_svn(None, ['foo\bbar'], [], 'propget', '--revprop', '-r', '1', 'svn:author', '--strict', wc_dir) + # Ensure a stable date + svntest.actions.run_and_verify_svn(None, None, [], + 'propset', '--revprop', '-r', '1', + 'svn:date', '2015-01-01T00:00:00.0Z', wc_dir) + # But a proplist of this property value still fails via DAV. - expected_output = [ + expected_output = svntest.verify.UnorderedOutput([ 'Unversioned properties on revision 1:\n', ' svn:author\n', + ' foo\bbar\n', ' svn:date\n', - ' svn:log\n' - ] + ' 2015-01-01T00:00:00.0Z\n', + ' svn:log\n', + ' Log message for revision 1.\n' + ]) svntest.actions.run_and_verify_svn(None, expected_output, [], - 'proplist', '--revprop', '-r', '1', + 'proplist', '--revprop', '-r', '1', '-v', wc_dir) +@Issue(4415) +def xml_unsafe_author2(sbox): + "svn:author with XML unsafe chars 2" + + sbox.build(create_wc = False) + repo_url = sbox.repo_url + + svntest.actions.enable_revprop_changes(sbox.repo_dir) + + # client sends svn:author (via PROPPATCH for DAV) + svntest.actions.run_and_verify_svn(None, None, [], + 'propset', '--revprop', '-r', '1', + 'svn:author', 'foo\bbar', repo_url) + + # Ensure a stable date + svntest.actions.run_and_verify_svn(None, None, [], + 'propset', '--revprop', '-r', '1', + 'svn:date', '2000-01-01T12:00:00.0Z', + repo_url) + + if svntest.main.is_ra_type_dav(): + # This receives the filtered author (but that is better than an Xml fail) + expected_author = 'foobar' + else: + expected_author = 'foo\bbar' + + expected_output = svntest.verify.UnorderedOutput([ + ' 1 %-8s Jan 01 2000 ./\n' % expected_author, + ' 1 %-8s Jan 01 2000 A/\n' % expected_author, + ' 1 %-8s 25 Jan 01 2000 iota\n' % expected_author + ]) + svntest.actions.run_and_verify_svn(None, expected_output, [], + 'ls', '-v', repo_url) + + expected_info = [{ + 'Repository Root' : sbox.repo_url, + 'Last Changed Author' : expected_author, + }] + svntest.actions.run_and_verify_info(expected_info, repo_url) + def dir_prop_conflict_details(sbox): "verify dir property conflict details" @@ -2814,6 +2861,7 @@ test_list = [ None, almost_known_prop_names, peg_rev_base_working, xml_unsafe_author, + xml_unsafe_author2, dir_prop_conflict_details, iprops_list_abspath, wc_propop_on_url,
