diff options
author | Peter Wemm <peter@FreeBSD.org> | 2013-06-18 02:07:41 +0000 |
---|---|---|
committer | Peter Wemm <peter@FreeBSD.org> | 2013-06-18 02:07:41 +0000 |
commit | 32547653cc5376642e1231fb644db99933ac8db4 (patch) | |
tree | 135691142dc0e75a5e5d97b5074d03436435b8e0 /subversion/libsvn_ra_serf/ra_serf.h | |
download | src-32547653cc5376642e1231fb644db99933ac8db4.tar.gz src-32547653cc5376642e1231fb644db99933ac8db4.zip |
Import trimmed svn-1.8.0-rc3vendor/subversion/subversion-1.8.0-rc3
Notes
Notes:
svn path=/vendor/subversion/dist/; revision=251881
svn path=/vendor/subversion/subversion-1.8.0-rc3/; revision=251882; tag=vendor/subversion/subversion-1.8.0-rc3
Diffstat (limited to 'subversion/libsvn_ra_serf/ra_serf.h')
-rw-r--r-- | subversion/libsvn_ra_serf/ra_serf.h | 1785 |
1 files changed, 1785 insertions, 0 deletions
diff --git a/subversion/libsvn_ra_serf/ra_serf.h b/subversion/libsvn_ra_serf/ra_serf.h new file mode 100644 index 000000000000..3f3f3ded05af --- /dev/null +++ b/subversion/libsvn_ra_serf/ra_serf.h @@ -0,0 +1,1785 @@ +/* + * ra_serf.h : Private declarations for the Serf-based DAV RA module. + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#ifndef SVN_LIBSVN_RA_SERF_RA_SERF_H +#define SVN_LIBSVN_RA_SERF_RA_SERF_H + + +#include <serf.h> +#include <expat.h> /* for XML_Parser */ +#include <apr_uri.h> + +#include "svn_types.h" +#include "svn_string.h" +#include "svn_pools.h" +#include "svn_ra.h" +#include "svn_delta.h" +#include "svn_version.h" +#include "svn_dav.h" +#include "svn_dirent_uri.h" + +#include "private/svn_dav_protocol.h" +#include "private/svn_subr_private.h" +#include "private/svn_editor.h" + +#include "blncache.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/* Enforce the minimum version of serf. */ +#if !SERF_VERSION_AT_LEAST(1, 2, 1) +#error Please update your version of serf to at least 1.2.1. +#endif + +/** Use this to silence compiler warnings about unused parameters. */ +#define UNUSED_CTX(x) ((void)(x)) + +/** Our User-Agent string. */ +#define USER_AGENT "SVN/" SVN_VER_NUMBER " (" SVN_BUILD_TARGET ")" \ + " serf/" \ + APR_STRINGIFY(SERF_MAJOR_VERSION) "." \ + APR_STRINGIFY(SERF_MINOR_VERSION) "." \ + APR_STRINGIFY(SERF_PATCH_VERSION) + +/** Wait duration (in microseconds) used in calls to serf_context_run() */ +#define SVN_RA_SERF__CONTEXT_RUN_DURATION 500000 + + + +/* Forward declarations. */ +typedef struct svn_ra_serf__session_t svn_ra_serf__session_t; + +/* A serf connection and optionally associated SSL context. */ +typedef struct svn_ra_serf__connection_t { + /* Our connection to a server. */ + serf_connection_t *conn; + + /* Bucket allocator for this connection. */ + serf_bucket_alloc_t *bkt_alloc; + + /* Collected cert failures in chain. */ + int server_cert_failures; + + /* What was the last HTTP status code we got on this connection? */ + int last_status_code; + + /* Optional SSL context for this connection. */ + serf_ssl_context_t *ssl_context; + svn_auth_iterstate_t *ssl_client_auth_state; + svn_auth_iterstate_t *ssl_client_pw_auth_state; + + svn_ra_serf__session_t *session; + +} svn_ra_serf__connection_t; + +/** Maximum value we'll allow for the http-max-connections config option. + * + * Note: minimum 2 connections are required for ra_serf to function + * correctly! + */ +#define SVN_RA_SERF__MAX_CONNECTIONS_LIMIT 8 + +/* + * The master serf RA session. + * + * This is stored in the ra session ->priv field. + */ +struct svn_ra_serf__session_t { + /* Pool for allocations during this session */ + apr_pool_t *pool; + + /* The current context */ + serf_context_t *context; + + /* The maximum number of connections we'll use for parallelized + fetch operations (updates, etc.) */ + apr_int64_t max_connections; + + /* Are we using ssl */ + svn_boolean_t using_ssl; + + /* Should we ask for compressed responses? */ + svn_boolean_t using_compression; + + /* The user agent string */ + const char *useragent; + + /* The current connection */ + svn_ra_serf__connection_t *conns[SVN_RA_SERF__MAX_CONNECTIONS_LIMIT]; + int num_conns; + int cur_conn; + + /* The URL that was passed into _open() */ + apr_uri_t session_url; + const char *session_url_str; + + /* The actual discovered root; may be NULL until we know it. */ + apr_uri_t repos_root; + const char *repos_root_str; + + /* The server is not Apache/mod_dav_svn (directly) and only supports + HTTP/1.0. Thus, we cannot send chunked requests. */ + svn_boolean_t http10; + + /* Our Version-Controlled-Configuration; may be NULL until we know it. */ + const char *vcc_url; + + /* Authentication related properties. */ + svn_auth_iterstate_t *auth_state; + int auth_attempts; + + /* Callback functions to get info from WC */ + const svn_ra_callbacks2_t *wc_callbacks; + void *wc_callback_baton; + + /* Callback function to send progress info to the client */ + svn_ra_progress_notify_func_t progress_func; + void *progress_baton; + + /* Callback function to handle cancellation */ + svn_cancel_func_t cancel_func; + void *cancel_baton; + + /* Ev2 shim callbacks */ + svn_delta_shim_callbacks_t *shim_callbacks; + + /* Error that we've received but not yet returned upstream. */ + svn_error_t *pending_error; + + /* List of authn types supported by the client.*/ + int authn_types; + + /* Maps SVN_RA_CAPABILITY_foo keys to "yes" or "no" values. + If a capability is not yet discovered, it is absent from the table. + The table itself is allocated in the svn_ra_serf__session_t's pool; + keys and values must have at least that lifetime. Most likely + the keys and values are constants anyway (and sufficiently + well-informed internal code may just compare against those + constants' addresses, therefore). */ + apr_hash_t *capabilities; + + /* Activity collection URL. (Cached from the initial OPTIONS + request when run against HTTPv1 servers.) */ + const char *activity_collection_url; + + /* Are we using a proxy? */ + int using_proxy; + + const char *proxy_username; + const char *proxy_password; + int proxy_auth_attempts; + + /* SSL server certificates */ + svn_boolean_t trust_default_ca; + const char *ssl_authorities; + + /* Repository UUID */ + const char *uuid; + + /* Connection timeout value */ + apr_interval_time_t timeout; + + /* HTTPv1 flags */ + svn_tristate_t supports_deadprop_count; + + /*** HTTP v2 protocol stuff. *** + * + * We assume that if mod_dav_svn sends one of the special v2 OPTIONs + * response headers, it has sent all of them. Specifically, we'll + * be looking at the presence of the "me resource" as a flag that + * the server supports v2 of our HTTP protocol. + */ + + /* The "me resource". Typically used as a target for REPORTs that + are path-agnostic. If we have this, we can speak HTTP v2 to the + server. */ + const char *me_resource; + + /* Opaque URL "stubs". If the OPTIONS response returns these, then + we know we're using HTTP protocol v2. */ + const char *rev_stub; /* for accessing revisions (i.e. revprops) */ + const char *rev_root_stub; /* for accessing REV/PATH pairs */ + const char *txn_stub; /* for accessing transactions (i.e. txnprops) */ + const char *txn_root_stub; /* for accessing TXN/PATH pairs */ + const char *vtxn_stub; /* for accessing transactions (i.e. txnprops) */ + const char *vtxn_root_stub; /* for accessing TXN/PATH pairs */ + + /* Hash mapping const char * server-supported POST types to + disinteresting-but-non-null values. */ + apr_hash_t *supported_posts; + + /*** End HTTP v2 stuff ***/ + + svn_ra_serf__blncache_t *blncache; + + /* Trisate flag that indicates user preference for using bulk updates + (svn_tristate_true) with all the properties and content in the + update-report response. If svn_tristate_false, request a skelta + update-report with inlined properties. If svn_tristate_unknown then use + server preference. */ + svn_tristate_t bulk_updates; + + /* Indicates if the server wants bulk update requests (Prefer) or only + accepts skelta requests (Off). If this value is On both options are + allowed. */ + const char *server_allows_bulk; + + /* Indicates if the server supports sending inlined props in update editor + * in skelta mode (send-all == 'false'). */ + svn_boolean_t supports_inline_props; + + /* Indicates whether the server supports issuing replay REPORTs + against rev resources (children of `rev_stub', elsestruct). */ + svn_boolean_t supports_rev_rsrc_replay; +}; + +#define SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(sess) ((sess)->me_resource != NULL) + +/* + * Structure which represents a DAV element with a NAMESPACE and NAME. + */ +typedef struct svn_ra_serf__dav_props_t { + /* Element namespace */ + const char *namespace; + /* Element name */ + const char *name; +} svn_ra_serf__dav_props_t; + +/* + * Structure which represents an XML namespace. + */ +typedef struct ns_t { + /* The assigned name. */ + const char *namespace; + /* The full URL for this namespace. */ + const char *url; + /* The next namespace in our list. */ + struct ns_t *next; +} svn_ra_serf__ns_t; + +/* + * An incredibly simple list. + */ +typedef struct ra_serf_list_t { + void *data; + struct ra_serf_list_t *next; +} svn_ra_serf__list_t; + +/** DAV property sets **/ + +static const svn_ra_serf__dav_props_t base_props[] = +{ + { "DAV:", "version-controlled-configuration" }, + { "DAV:", "resourcetype" }, + { SVN_DAV_PROP_NS_DAV, "baseline-relative-path" }, + { SVN_DAV_PROP_NS_DAV, "repository-uuid" }, + { NULL } +}; + +static const svn_ra_serf__dav_props_t checked_in_props[] = +{ + { "DAV:", "checked-in" }, + { NULL } +}; + +static const svn_ra_serf__dav_props_t baseline_props[] = +{ + { "DAV:", "baseline-collection" }, + { "DAV:", SVN_DAV__VERSION_NAME }, + { NULL } +}; + +static const svn_ra_serf__dav_props_t all_props[] = +{ + { "DAV:", "allprop" }, + { NULL } +}; + +static const svn_ra_serf__dav_props_t check_path_props[] = +{ + { "DAV:", "resourcetype" }, + { NULL } +}; + +static const svn_ra_serf__dav_props_t type_and_checksum_props[] = +{ + { "DAV:", "resourcetype" }, + { SVN_DAV_PROP_NS_DAV, "sha1-checksum" }, + { NULL } +}; + +/* WC props compatibility with ra_neon. */ +#define SVN_RA_SERF__WC_CHECKED_IN_URL SVN_PROP_WC_PREFIX "ra_dav:version-url" + +/** Serf utility functions **/ + +apr_status_t +svn_ra_serf__conn_setup(apr_socket_t *sock, + serf_bucket_t **read_bkt, + serf_bucket_t **write_bkt, + void *baton, + apr_pool_t *pool); + +void +svn_ra_serf__conn_closed(serf_connection_t *conn, + void *closed_baton, + apr_status_t why, + apr_pool_t *pool); + + +/* Helper function to provide SSL client certificates. + * + * NOTE: This function sets the session's 'pending_error' member when + * returning an non-success status. + */ +apr_status_t +svn_ra_serf__handle_client_cert(void *data, + const char **cert_path); + +/* Helper function to provide SSL client certificate passwords. + * + * NOTE: This function sets the session's 'pending_error' member when + * returning an non-success status. + */ +apr_status_t +svn_ra_serf__handle_client_cert_pw(void *data, + const char *cert_path, + const char **password); + + +/* + * This function will run the serf context in SESS until *DONE is TRUE. + */ +svn_error_t * +svn_ra_serf__context_run_wait(svn_boolean_t *done, + svn_ra_serf__session_t *sess, + apr_pool_t *scratch_pool); + +/* Callback for response handlers */ +typedef svn_error_t * +(*svn_ra_serf__response_handler_t)(serf_request_t *request, + serf_bucket_t *response, + void *handler_baton, + apr_pool_t *scratch_pool); + +/* Callback for when a request body is needed. */ +/* ### should pass a scratch_pool */ +typedef svn_error_t * +(*svn_ra_serf__request_body_delegate_t)(serf_bucket_t **body_bkt, + void *baton, + serf_bucket_alloc_t *alloc, + apr_pool_t *request_pool); + +/* Callback for when request headers are needed. */ +/* ### should pass a scratch_pool */ +typedef svn_error_t * +(*svn_ra_serf__request_header_delegate_t)(serf_bucket_t *headers, + void *baton, + apr_pool_t *request_pool); + +/* Callback for when a response has an error. */ +typedef svn_error_t * +(*svn_ra_serf__response_error_t)(serf_request_t *request, + serf_bucket_t *response, + int status_code, + void *baton); + +/* ### we should reorder the types in this file. */ +typedef struct svn_ra_serf__server_error_t svn_ra_serf__server_error_t; + +/* + * Structure that can be passed to our default handler to guide the + * execution of the request through its lifecycle. + */ +typedef struct svn_ra_serf__handler_t { + /* The HTTP method string of the request */ + const char *method; + + /* The resource to the execute the method on. */ + const char *path; + + /* The content-type of the request body. */ + const char *body_type; + + /* If TRUE then default Accept-Encoding request header is not configured for + request. If FALSE then 'gzip' accept encoding will be used if compression + enabled. */ + svn_boolean_t custom_accept_encoding; + + /* Has the request/response been completed? */ + svn_boolean_t done; + + /* If we captured an error from the server, then this will be non-NULL. + It will be allocated from HANDLER_POOL. */ + svn_ra_serf__server_error_t *server_error; + + /* The handler and baton pair for our handler. */ + svn_ra_serf__response_handler_t response_handler; + void *response_baton; + + /* When REPONSE_HANDLER is invoked, the following fields will be set + based on the response header. HANDLER_POOL must be non-NULL for these + values to be filled in. SLINE.REASON and LOCATION will be allocated + within HANDLER_POOL. */ + serf_status_line sline; /* The parsed Status-Line */ + const char *location; /* The Location: header, if any */ + + /* The handler and baton pair to be executed when a non-recoverable error + * is detected. If it is NULL in the presence of an error, an abort() may + * be triggered. + */ + svn_ra_serf__response_error_t response_error; + void *response_error_baton; + + /* This function and baton pair allows for custom request headers to + * be set. + * + * It will be executed after the request has been set up but before it is + * delivered. + */ + svn_ra_serf__request_header_delegate_t header_delegate; + void *header_delegate_baton; + + /* This function and baton pair allows a body to be created right before + * delivery. + * + * It will be executed after the request has been set up but before it is + * delivered. + * + * May be NULL if there is no body to send. + * + */ + svn_ra_serf__request_body_delegate_t body_delegate; + void *body_delegate_baton; + + /* The connection and session to be used for this request. */ + svn_ra_serf__connection_t *conn; + svn_ra_serf__session_t *session; + + /* Internal flag to indicate we've parsed the headers. */ + svn_boolean_t reading_body; + + /* When this flag will be set, the core handler will discard any unread + portion of the response body. The registered response handler will + no longer be called. */ + svn_boolean_t discard_body; + + /* Pool for allocating SLINE.REASON and LOCATION. If this pool is NULL, + then the requestor does not care about SLINE and LOCATION. */ + apr_pool_t *handler_pool; + +} svn_ra_serf__handler_t; + + +/* Run one request and process the response. + + Similar to context_run_wait(), but this creates the request for HANDLER + and then waits for it to complete. + + WARNING: context_run_wait() does NOT create a request, whereas this + function DOES. Avoid a double-create. */ +svn_error_t * +svn_ra_serf__context_run_one(svn_ra_serf__handler_t *handler, + apr_pool_t *scratch_pool); + + +/* + * Helper function to queue a request in the @a handler's connection. + */ +void svn_ra_serf__request_create(svn_ra_serf__handler_t *handler); + +/* XML helper callbacks. */ + +typedef struct svn_ra_serf__xml_state_t { + /* A numeric value that represents the current state in parsing. + * + * Value 0 is reserved for use as the default state. + */ + int current_state; + + /* Private pointer set by the parsing code. */ + void *private; + + /* Allocations should be made in this pool to match the lifetime of the + * state. + */ + apr_pool_t *pool; + + /* The currently-declared namespace for this state. */ + svn_ra_serf__ns_t *ns_list; + + /* Our previous states. */ + struct svn_ra_serf__xml_state_t *prev; +} svn_ra_serf__xml_state_t; + +/* Forward declaration of the XML parser structure. */ +typedef struct svn_ra_serf__xml_parser_t svn_ra_serf__xml_parser_t; + +/* Callback invoked with @a baton by our XML @a parser when an element with + * the @a name containing @a attrs is opened. + */ +typedef svn_error_t * +(*svn_ra_serf__xml_start_element_t)(svn_ra_serf__xml_parser_t *parser, + svn_ra_serf__dav_props_t name, + const char **attrs, + apr_pool_t *scratch_pool); + +/* Callback invoked with @a baton by our XML @a parser when an element with + * the @a name is closed. + */ +typedef svn_error_t * +(*svn_ra_serf__xml_end_element_t)(svn_ra_serf__xml_parser_t *parser, + svn_ra_serf__dav_props_t name, + apr_pool_t *scratch_pool); + +/* Callback invoked with @a baton by our XML @a parser when a CDATA portion + * of @a data with size @a len is encountered. + * + * This may be invoked multiple times for the same tag. + */ +typedef svn_error_t * +(*svn_ra_serf__xml_cdata_chunk_handler_t)(svn_ra_serf__xml_parser_t *parser, + const char *data, + apr_size_t len, + apr_pool_t *scratch_pool); + +/* + * Helper structure associated with handle_xml_parser handler that will + * specify how an XML response will be processed. + */ +struct svn_ra_serf__xml_parser_t { + /* Temporary allocations should be made in this pool. */ + apr_pool_t *pool; + + /* What kind of response are we parsing? If set, this should typically + define the report name. */ + const char *response_type; + + /* Caller-specific data passed to the start, end, cdata callbacks. */ + void *user_data; + + /* Callback invoked when a tag is opened. */ + svn_ra_serf__xml_start_element_t start; + + /* Callback invoked when a tag is closed. */ + svn_ra_serf__xml_end_element_t end; + + /* Callback invoked when a cdata chunk is received. */ + svn_ra_serf__xml_cdata_chunk_handler_t cdata; + + /* Our associated expat-based XML parser. */ + XML_Parser xmlp; + + /* Our current state. */ + svn_ra_serf__xml_state_t *state; + + /* Our previously used states (will be reused). */ + svn_ra_serf__xml_state_t *free_state; + + /* If non-NULL, this value will be set to TRUE when the response is + * completed. + */ + svn_boolean_t *done; + + /* If non-NULL, when this parser completes, it will add done_item to + * the list. + */ + svn_ra_serf__list_t **done_list; + + /* A pointer to the item that will be inserted into the list upon + * completeion. + */ + svn_ra_serf__list_t *done_item; + + /* If this flag is TRUE, errors during parsing will be ignored. + * + * This is mainly used when we are processing an error XML response to + * avoid infinite loops. + */ + svn_boolean_t ignore_errors; + + /* If an error occurred, this value will be non-NULL. */ + svn_error_t *error; + + /* Deciding whether to pause, or not, is performed within the parsing + callbacks. If a callback decides to set this flag, then the loop + driving the parse (generally, a series of calls to serf_context_run()) + is going to need to coordinate the un-pausing of the parser by + processing pending content. Thus, deciding to pause the parser is a + coordinate effort rather than merely setting this flag. + + When an XML parsing callback sets this flag, note that additional + elements may be parsed (as the current buffer is consumed). At some + point, the flag will be recognized and arriving network content will + be stashed away in the PENDING structure (see below). + + At some point, the controlling loop should clear this value. The + underlying network processing will note the change and begin passing + content into the XML callbacks. + + Note that the controlling loop should also process pending content + since the arriving network content will typically finish first. */ + svn_boolean_t paused; + + /* While the XML parser is paused, content arriving from the server + must be saved locally. We cannot stop reading, or the server may + decide to drop the connection. The content will be stored in memory + up to a certain limit, and will then be spilled over to disk. + + See libsvn_ra_serf/util.c */ + struct svn_ra_serf__pending_t *pending; + + /* Response restart support */ + const void *headers_baton; /* Last pointer to headers */ + apr_off_t skip_size; /* Number of bytes to skip */ + apr_off_t read_size; /* Number of bytes read from response */ +}; + + +/* v2 of the XML parsing functions */ + +/* The XML parsing context. */ +typedef struct svn_ra_serf__xml_context_t svn_ra_serf__xml_context_t; + + +/* An opaque structure for the XML parse element/state. */ +typedef struct svn_ra_serf__xml_estate_t svn_ra_serf__xml_estate_t; + +/* Called just after the parser moves into ENTERED_STATE. The tag causing + the transition is passed in TAG. + + This callback is applied to a parsing context by using the + svn_ra_serf__xml_context_customize() function. + + NOTE: this callback, when set, will be invoked on *every* transition. + The callback must examine ENTERED_STATE to determine if any action + must be taken. The original state is not provided, but must be derived + from ENTERED_STATE and/or the TAG causing the transition (if needed). */ +typedef svn_error_t * +(*svn_ra_serf__xml_opened_t)(svn_ra_serf__xml_estate_t *xes, + void *baton, + int entered_state, + const svn_ra_serf__dav_props_t *tag, + apr_pool_t *scratch_pool); + + +/* Called just before the parser leaves LEAVING_STATE. + + If cdata collection was enabled for this state, then CDATA will be + non-NULL and contain the collected cdata. + + If attribute collection was enabled for this state, then ATTRS will + contain the attributes collected for this element only, along with + any values stored via svn_ra_serf__xml_note(). + + Use svn_ra_serf__xml_gather_since() to gather up data from outer states. + + ATTRS is char* -> char*. + + Temporary allocations may be made in SCRATCH_POOL. */ +typedef svn_error_t * +(*svn_ra_serf__xml_closed_t)(svn_ra_serf__xml_estate_t *xes, + void *baton, + int leaving_state, + const svn_string_t *cdata, + apr_hash_t *attrs, + apr_pool_t *scratch_pool); + + +/* Called for all states that are not using the builtin cdata collection. + This callback is (only) appropriate for unbounded-size cdata content. + + CURRENT_STATE may be used to decide what to do with the data. + + Temporary allocations may be made in SCRATCH_POOL. */ +typedef svn_error_t * +(*svn_ra_serf__xml_cdata_t)(svn_ra_serf__xml_estate_t *xes, + void *baton, + int current_state, + const char *data, + apr_size_t len, + apr_pool_t *scratch_pool); + + +/* State transition table. + + When the XML Context is constructed, it is in state 0. User states are + positive integers. + + In a list of transitions, use { 0 } to indicate the end. Specifically, + the code looks for NS == NULL. + + ### more docco +*/ +typedef struct svn_ra_serf__xml_transition_t { + /* This transition applies when in this state */ + int from_state; + + /* And when this tag is observed */ + const char *ns; + const char *name; + + /* Moving to this state */ + int to_state; + + /* Should the cdata of NAME be collected? Note that CUSTOM_CLOSE should + be TRUE in order to capture this cdata. */ + svn_boolean_t collect_cdata; + + /* Which attributes of NAME should be collected? Terminate with NULL. + Maximum of 10 attributes may be collected. Note that attribute + namespaces are ignored at this time. + + Attribute names beginning with "?" are optional. Other names must + exist on the element, or SVN_ERR_XML_ATTRIB_NOT_FOUND will be raised. */ + const char *collect_attrs[11]; + + /* When NAME is closed, should the callback be invoked? */ + svn_boolean_t custom_close; + +} svn_ra_serf__xml_transition_t; + + +/* Construct an XML parsing context, based on the TTABLE transition table. + As content is parsed, the CLOSED_CB callback will be invoked according + to the definition in the table. + + If OPENED_CB is not NULL, then it will be invoked for *every* tag-open + event. The callback will need to use the ENTERED_STATE and TAG parameters + to decide what it would like to do. + + If CDATA_CB is not NULL, then it will be called for all cdata that is + not be automatically collected (based on the transition table record's + COLLECT_CDATA flag). It will be called in every state, so the callback + must examine the CURRENT_STATE parameter to decide what to do. + + The same BATON value will be passed to all three callbacks. + + The context will be created within RESULT_POOL. */ +svn_ra_serf__xml_context_t * +svn_ra_serf__xml_context_create( + const svn_ra_serf__xml_transition_t *ttable, + svn_ra_serf__xml_opened_t opened_cb, + svn_ra_serf__xml_closed_t closed_cb, + svn_ra_serf__xml_cdata_t cdata_cb, + void *baton, + apr_pool_t *result_pool); + +/* Destroy all subpools for this structure. */ +void +svn_ra_serf__xml_context_destroy( + svn_ra_serf__xml_context_t *xmlctx); + +/* Construct a handler with the response function/baton set up to parse + a response body using the given XML context. The handler and its + internal structures are allocated in RESULT_POOL. + + 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, + apr_pool_t *result_pool); + + +/* Allocated within XES->STATE_POOL. Changes are not allowd (callers + should make a deep copy if they need to make changes). + + The resulting hash maps char* names to char* values. */ +apr_hash_t * +svn_ra_serf__xml_gather_since(svn_ra_serf__xml_estate_t *xes, + int stop_state); + + +/* Attach the NAME/VALUE pair onto this/parent state identified by STATE. + The name and value will be copied into the target state's pool. + + These values will be available to the CLOSED_CB for the target state, + or part of the gathered state via xml_gather_since(). + + Typically, this function is used by a child state's close callback, + or within an opening callback to store additional data. + + Note: if the state is not found, then a programmer error has occurred, + so the function will invoke SVN_ERR_MALFUNCTION(). */ +void +svn_ra_serf__xml_note(svn_ra_serf__xml_estate_t *xes, + int state, + const char *name, + const char *value); + + +/* Returns XES->STATE_POOL for allocating structures that should live + as long as the state identified by XES. + + Note: a state pool is created upon demand, so only use this function + when memory is required for a given state. */ +apr_pool_t * +svn_ra_serf__xml_state_pool(svn_ra_serf__xml_estate_t *xes); + + +/* Any XML parser may be used. When an opening tag is seen, call this + function to feed the information into XMLCTX. */ +svn_error_t * +svn_ra_serf__xml_cb_start(svn_ra_serf__xml_context_t *xmlctx, + const char *raw_name, + const char *const *attrs); + + +/* When a close tag is seen, call this function to feed the information + into XMLCTX. */ +svn_error_t * +svn_ra_serf__xml_cb_end(svn_ra_serf__xml_context_t *xmlctx, + const char *raw_name); + + +/* When cdata is parsed by the wrapping XML parser, call this function to + feed the cdata into the XMLCTX. */ +svn_error_t * +svn_ra_serf__xml_cb_cdata(svn_ra_serf__xml_context_t *xmlctx, + const char *data, + apr_size_t len); + + +/* + * Parses a server-side error message into a local Subversion error. + */ +struct svn_ra_serf__server_error_t { + /* Our local representation of the error. */ + svn_error_t *error; + + /* Are we done with the response? */ + svn_boolean_t done; + + /* Have we seen an error tag? */ + svn_boolean_t in_error; + + /* Have we seen a HTTP "412 Precondition Failed" error? */ + svn_boolean_t contains_precondition_error; + + /* Should we be collecting the XML cdata? */ + svn_boolean_t collect_cdata; + + /* Collected cdata. NULL if cdata not needed. */ + svn_stringbuf_t *cdata; + + /* XML parser and namespace used to parse the remote response */ + svn_ra_serf__xml_parser_t parser; +}; + + +/* + * Handler that discards the entire @a response body associated with a + * @a request. Implements svn_ra_serf__response_handler_t. + * + * If @a baton is a svn_ra_serf__server_error_t (i.e. non-NULL) and an + * error is detected, it will be populated for later detection. + * + * All temporary allocations will be made in a @a pool. + */ +svn_error_t * +svn_ra_serf__handle_discard_body(serf_request_t *request, + serf_bucket_t *response, + void *baton, + apr_pool_t *pool); + + +/* + * Handler that retrieves the embedded XML multistatus response from the + * the @a RESPONSE body associated with a @a REQUEST. + * + * Implements svn_ra_serf__response_handler_t. + * + * The @a BATON should be of type svn_ra_serf__handler_t. When the request + * is complete, the handler's DONE flag will be set to TRUE. + * + * All temporary allocations will be made in a @a scratch_pool. + */ +svn_error_t * +svn_ra_serf__handle_multistatus_only(serf_request_t *request, + serf_bucket_t *response, + void *baton, + apr_pool_t *scratch_pool); + + +/* Handler that expects an empty body. + + If a body IS present, and it is text/xml, then it will be parsed for + a server-side error. + + BATON should be the svn_ra_serf__handler_t running REQUEST. + + Status line information will be in HANDLER->SLINE. + + Any parsed errors will be left in HANDLER->SERVER_ERROR. That member + may be NULL if no body was present, or a problem occurred trying to + parse the body. + + All temporary allocations will be made in SCRATCH_POOL. */ +svn_error_t * +svn_ra_serf__expect_empty_body(serf_request_t *request, + serf_bucket_t *response, + void *baton, + apr_pool_t *scratch_pool); + + +/* + * This function will feed the RESPONSE body into XMLP. When parsing is + * completed (i.e. an EOF is received), *DONE is set to TRUE. + * Implements svn_ra_serf__response_handler_t. + * + * If an error occurs during processing RESP_ERR is invoked with the + * RESP_ERR_BATON. + * + * Temporary allocations are made in POOL. + */ +svn_error_t * +svn_ra_serf__handle_xml_parser(serf_request_t *request, + serf_bucket_t *response, + void *handler_baton, + apr_pool_t *pool); + +/* serf_response_handler_t implementation that completely discards + * the response. + * + * All temporary allocations will be made in @a pool. + */ +apr_status_t +svn_ra_serf__response_discard_handler(serf_request_t *request, + serf_bucket_t *response, + void *baton, + apr_pool_t *pool); + + +/** XML helper functions. **/ + +/* + * Advance the internal XML @a parser to the @a state. + */ +void +svn_ra_serf__xml_push_state(svn_ra_serf__xml_parser_t *parser, + int state); + +/* + * Return to the previous internal XML @a parser state. + */ +void +svn_ra_serf__xml_pop_state(svn_ra_serf__xml_parser_t *parser); + + +svn_error_t * +svn_ra_serf__process_pending(svn_ra_serf__xml_parser_t *parser, + svn_boolean_t *network_eof, + apr_pool_t *scratch_pool); + + +/* + * Add the appropriate serf buckets to @a agg_bucket represented by + * the XML * @a tag and @a value. + * + * The bucket will be allocated from @a bkt_alloc. + */ +void +svn_ra_serf__add_tag_buckets(serf_bucket_t *agg_bucket, + const char *tag, + const char *value, + serf_bucket_alloc_t *bkt_alloc); + +/* + * Add the appropriate serf buckets to AGG_BUCKET with standard XML header: + * <?xml version="1.0" encoding="utf-8"?> + * + * The bucket will be allocated from BKT_ALLOC. + */ +void +svn_ra_serf__add_xml_header_buckets(serf_bucket_t *agg_bucket, + serf_bucket_alloc_t *bkt_alloc); + +/* + * Add the appropriate serf buckets to AGG_BUCKET representing the XML + * open tag with name TAG. + * + * Take the tag's attributes from varargs, a NULL-terminated list of + * alternating <tt>char *</tt> key and <tt>char *</tt> val. Attribute + * will be ignored if it's value is NULL. + * + * NOTE: Callers are responsible for XML-escaping attribute values as + * necessary. + * + * The bucket will be allocated from BKT_ALLOC. + */ +void +svn_ra_serf__add_open_tag_buckets(serf_bucket_t *agg_bucket, + serf_bucket_alloc_t *bkt_alloc, + const char *tag, + ...); + +/* + * Add the appropriate serf buckets to AGG_BUCKET representing xml tag close + * with name TAG. + * + * The bucket will be allocated from BKT_ALLOC. + */ +void +svn_ra_serf__add_close_tag_buckets(serf_bucket_t *agg_bucket, + serf_bucket_alloc_t *bkt_alloc, + const char *tag); + +/* + * Add the appropriate serf buckets to AGG_BUCKET with xml-escaped + * version of DATA. + * + * The bucket will be allocated from BKT_ALLOC. + */ +void +svn_ra_serf__add_cdata_len_buckets(serf_bucket_t *agg_bucket, + serf_bucket_alloc_t *bkt_alloc, + const char *data, apr_size_t len); +/* + * Look up the @a attrs array for namespace definitions and add each one + * to the @a ns_list of namespaces. + * + * New namespaces will be allocated in RESULT_POOL. + */ +void +svn_ra_serf__define_ns(svn_ra_serf__ns_t **ns_list, + const char *const *attrs, + apr_pool_t *result_pool); + +/* + * 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, + const svn_ra_serf__ns_t *ns_list, + const char *name); + + +/** PROPFIND-related functions **/ + +/* + * 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_props(svn_ra_serf__handler_t **propfind_handler, + apr_hash_t *prop_vals, + svn_ra_serf__session_t *sess, + svn_ra_serf__connection_t *conn, + const char *url, + svn_revnum_t rev, + const char *depth, + const svn_ra_serf__dav_props_t *lookup_props, + svn_ra_serf__list_t **done_list, + 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); + +/* This is a blocking version of deliver_props. + + The properties are fetched and placed into RESULTS, allocated in + RESULT_POOL. + + ### more docco about the other params. + + Temporary allocations are made in SCRATCH_POOL. +*/ +svn_error_t * +svn_ra_serf__retrieve_props(apr_hash_t **results, + svn_ra_serf__session_t *sess, + svn_ra_serf__connection_t *conn, + const char *url, + svn_revnum_t rev, + const char *depth, + const svn_ra_serf__dav_props_t *props, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + + +/* Using CONN, 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. + + If REVISION is SVN_INVALID_REVNUM, then the properties are fetched + from HEAD for URL. + + This function performs the request synchronously. + + 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, + const char *url, + svn_revnum_t revision, + const svn_ra_serf__dav_props_t *which_props, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + + +/* Using CONN, fetch a DAV: property from the resource identified by URL + within REVISION. The PROPNAME may be one of: + + "checked-in" + "href" + + The resulting value will be allocated in RESULT_POOL, and may be NULL + if the property does not exist (note: "href" always exists). + + This function performs the request synchronously. + + 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, + const char *url, + svn_revnum_t revision, + const char *propname, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + + +/* Set PROPS for PATH at REV revision with a NS:NAME VAL. + * + * The POOL governs allocation. + */ +void +svn_ra_serf__set_ver_prop(apr_hash_t *props, + const char *path, svn_revnum_t rev, + const char *ns, const char *name, + const svn_string_t *val, apr_pool_t *pool); +#define svn_ra_serf__set_rev_prop svn_ra_serf__set_ver_prop + +/** 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); + +svn_error_t * +svn_ra_serf__walk_all_props(apr_hash_t *props, + const char *name, + svn_revnum_t rev, + svn_ra_serf__walker_visitor_t walker, + void *baton, + 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); + + +typedef svn_error_t * +(*svn_ra_serf__path_rev_walker_t)(void *baton, + const char *path, apr_ssize_t path_len, + const char *ns, apr_ssize_t ns_len, + const char *name, apr_ssize_t name_len, + const svn_string_t *val, + apr_pool_t *pool); +svn_error_t * +svn_ra_serf__walk_all_paths(apr_hash_t *props, + svn_revnum_t rev, + svn_ra_serf__path_rev_walker_t walker, + void *baton, + apr_pool_t *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. + + If the property should be ignored (eg. some DAV properties), then NULL + will be returned. */ +const char * +svn_ra_serf__svnname_from_wirename(const char *ns, + const char *name, + apr_pool_t *result_pool); + + +/* Select the basic revision properties from the set of "all" properties. + Return these in *REVPROPS, allocated from RESULT_POOL. */ +svn_error_t * +svn_ra_serf__select_revprops(apr_hash_t **revprops, + const char *name, + svn_revnum_t rev, + apr_hash_t *all_revprops, + apr_pool_t *result_pool, + apr_pool_t *scratch_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); + + +/* Return the property value for PATH at REV revision with a NS:NAME. + * PROPS is a four-level nested hash: (svn_revnum_t => char *path => + * char *ns => char *name => svn_string_t *). */ +const svn_string_t * +svn_ra_serf__get_ver_prop_string(apr_hash_t *props, + const char *path, svn_revnum_t rev, + const char *ns, const char *name); + +/* Same as svn_ra_serf__get_ver_prop_string(), but returns a C string. */ +const char * +svn_ra_serf__get_ver_prop(apr_hash_t *props, + const char *path, svn_revnum_t rev, + const char *ns, const char *name); + +/* Same as svn_ra_serf__get_ver_prop_string(), but for the unknown revision. */ +const svn_string_t * +svn_ra_serf__get_prop_string(apr_hash_t *props, + const char *path, + const char *ns, + const char *name); + +/* Same as svn_ra_serf__get_ver_prop(), but for the unknown revision. */ +const char * +svn_ra_serf__get_prop(apr_hash_t *props, + const char *path, + const char *ns, + const char *name); + +/* Same as svn_ra_serf__set_rev_prop(), but for the unknown revision. */ +void +svn_ra_serf__set_prop(apr_hash_t *props, const char *path, + const char *ns, const char *name, + const svn_string_t *val, apr_pool_t *pool); + +svn_error_t * +svn_ra_serf__get_resource_type(svn_node_kind_t *kind, + apr_hash_t *props); + + +/** MERGE-related functions **/ + +void +svn_ra_serf__merge_lock_token_list(apr_hash_t *lock_tokens, + const char *parent, + serf_bucket_t *body, + serf_bucket_alloc_t *alloc, + apr_pool_t *pool); + +/* Create an MERGE request aimed at the SESSION url, requesting the + merge of the resource identified by MERGE_RESOURCE_URL. + LOCK_TOKENS is a hash mapping paths to lock tokens owned by the + client. If KEEP_LOCKS is set, instruct the server to not release + locks set on the paths included in this commit. */ +svn_error_t * +svn_ra_serf__run_merge(const svn_commit_info_t **commit_info, + int *response_code, + 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, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + + +/** OPTIONS-related functions **/ + +/* On HTTPv2 connections, run an OPTIONS request over CONN to fetch the + current youngest revnum, returning it in *YOUNGEST. + + (the revnum is headers of the OPTIONS response) + + This function performs the request synchronously. + + 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, + apr_pool_t *scratch_pool); + + +/* On HTTPv1 connections, run an OPTIONS request over CONN to fetch the + activity collection set and return it in *ACTIVITY_URL, allocated + from RESULT_POOL. + + (the activity-collection-set is in the body of the OPTIONS response) + + This function performs the request synchronously. + + 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, + 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. + * + * All temporary allocations will be made in @a 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); + +/* 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. + * + * 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 + * the repository pointed to by @a SESSION, based on original path + * (URI-encoded) @a ORIG_PATH. Use @a CONN for any required network + * communications if it is non-NULL; otherwise use the default + * connection. Use POOL for allocations. */ +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); + + +/* Using the default connection in SESSION (conns[0]), get the youngest + revnum from the server, returning it in *YOUNGEST. + + This function operates synchronously. + + All temporary allocations are performed in SCRATCH_POOL. */ +svn_error_t * +svn_ra_serf__get_youngest_revnum(svn_revnum_t *youngest, + svn_ra_serf__session_t *session, + apr_pool_t *scratch_pool); + + +/* Generate a revision-stable URL. + + The RA APIs all refer to user/public URLs that float along with the + youngest revision. In many cases, we do NOT want to work with that URL + since it can change from one moment to the next. Especially if we + attempt to operation against multiple floating URLs -- we could end up + referring to two separate revisions. + + 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. + + If URL is NULL, then the session root will be used. + + The stable URL will be placed into *STABLE_URL, allocated from RESULT_POOL. + + If LATEST_REVNUM is not NULL, then the revision used will be placed into + *LATEST_REVNUM. That will be equal to youngest, or the given REVISION. + + This function operates synchronously, if any communication to the server + is required. Communication is needed if REVISION is SVN_INVALID_REVNUM + (to get the current youngest revnum), or if the specified REVISION is not + (yet) in our cache of baseline collections. + + All temporary allocations are performed in SCRATCH_POOL. */ +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, + apr_pool_t *scratch_pool); + + +/** RA functions **/ + +/* Implements svn_ra__vtable_t.get_log(). */ +svn_error_t * +svn_ra_serf__get_log(svn_ra_session_t *session, + const apr_array_header_t *paths, + svn_revnum_t start, + svn_revnum_t end, + int limit, + svn_boolean_t discover_changed_paths, + svn_boolean_t strict_node_history, + svn_boolean_t include_merged_revisions, + const apr_array_header_t *revprops, + svn_log_entry_receiver_t receiver, + void *receiver_baton, + apr_pool_t *pool); + +/* Implements svn_ra__vtable_t.get_locations(). */ +svn_error_t * +svn_ra_serf__get_locations(svn_ra_session_t *session, + apr_hash_t **locations, + const char *path, + svn_revnum_t peg_revision, + const apr_array_header_t *location_revisions, + apr_pool_t *pool); + +/* Implements svn_ra__vtable_t.get_location_segments(). */ +svn_error_t * +svn_ra_serf__get_location_segments(svn_ra_session_t *session, + const char *path, + svn_revnum_t peg_revision, + svn_revnum_t start_rev, + svn_revnum_t end_rev, + svn_location_segment_receiver_t receiver, + void *receiver_baton, + apr_pool_t *pool); + +/* Implements svn_ra__vtable_t.do_diff(). */ +svn_error_t * +svn_ra_serf__do_diff(svn_ra_session_t *session, + const svn_ra_reporter3_t **reporter, + void **report_baton, + svn_revnum_t revision, + const char *diff_target, + svn_depth_t depth, + svn_boolean_t ignore_ancestry, + svn_boolean_t text_deltas, + const char *versus_url, + const svn_delta_editor_t *diff_editor, + void *diff_baton, + apr_pool_t *pool); + +/* Implements svn_ra__vtable_t.do_status(). */ +svn_error_t * +svn_ra_serf__do_status(svn_ra_session_t *ra_session, + const svn_ra_reporter3_t **reporter, + void **report_baton, + const char *status_target, + svn_revnum_t revision, + svn_depth_t depth, + const svn_delta_editor_t *status_editor, + void *status_baton, + apr_pool_t *pool); + +/* Implements svn_ra__vtable_t.do_update(). */ +svn_error_t * +svn_ra_serf__do_update(svn_ra_session_t *ra_session, + const svn_ra_reporter3_t **reporter, + void **report_baton, + svn_revnum_t revision_to_update_to, + const char *update_target, + svn_depth_t depth, + svn_boolean_t send_copyfrom_args, + svn_boolean_t ignore_ancestry, + const svn_delta_editor_t *update_editor, + void *update_baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/* Implements svn_ra__vtable_t.do_switch(). */ +svn_error_t * +svn_ra_serf__do_switch(svn_ra_session_t *ra_session, + const svn_ra_reporter3_t **reporter, + void **report_baton, + svn_revnum_t revision_to_switch_to, + const char *switch_target, + svn_depth_t depth, + const char *switch_url, + svn_boolean_t send_copyfrom_args, + svn_boolean_t ignore_ancestry, + const svn_delta_editor_t *switch_editor, + void *switch_baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/* Implements svn_ra__vtable_t.get_file_revs(). */ +svn_error_t * +svn_ra_serf__get_file_revs(svn_ra_session_t *session, + const char *path, + svn_revnum_t start, + svn_revnum_t end, + svn_boolean_t include_merged_revisions, + svn_file_rev_handler_t handler, + void *handler_baton, + apr_pool_t *pool); + +/* Implements svn_ra__vtable_t.get_dated_revision(). */ +svn_error_t * +svn_ra_serf__get_dated_revision(svn_ra_session_t *session, + svn_revnum_t *revision, + apr_time_t tm, + apr_pool_t *pool); + +/* Implements svn_ra__vtable_t.get_commit_editor(). */ +svn_error_t * +svn_ra_serf__get_commit_editor(svn_ra_session_t *session, + const svn_delta_editor_t **editor, + void **edit_baton, + apr_hash_t *revprop_table, + svn_commit_callback2_t callback, + void *callback_baton, + apr_hash_t *lock_tokens, + svn_boolean_t keep_locks, + apr_pool_t *pool); + +/* Implements svn_ra__vtable_t.get_file(). */ +svn_error_t * +svn_ra_serf__get_file(svn_ra_session_t *session, + const char *path, + svn_revnum_t revision, + svn_stream_t *stream, + svn_revnum_t *fetched_rev, + apr_hash_t **props, + apr_pool_t *pool); + +/* Implements svn_ra__vtable_t.change_rev_prop(). */ +svn_error_t * +svn_ra_serf__change_rev_prop(svn_ra_session_t *session, + svn_revnum_t rev, + const char *name, + const svn_string_t *const *old_value_p, + const svn_string_t *value, + apr_pool_t *pool); + +/* Implements svn_ra__vtable_t.replay(). */ +svn_error_t * +svn_ra_serf__replay(svn_ra_session_t *ra_session, + svn_revnum_t revision, + svn_revnum_t low_water_mark, + svn_boolean_t text_deltas, + const svn_delta_editor_t *editor, + void *edit_baton, + apr_pool_t *pool); + +/* Implements svn_ra__vtable_t.replay_range(). */ +svn_error_t * +svn_ra_serf__replay_range(svn_ra_session_t *ra_session, + svn_revnum_t start_revision, + svn_revnum_t end_revision, + svn_revnum_t low_water_mark, + svn_boolean_t send_deltas, + svn_ra_replay_revstart_callback_t revstart_func, + svn_ra_replay_revfinish_callback_t revfinish_func, + void *replay_baton, + apr_pool_t *pool); + +/* Implements svn_ra__vtable_t.lock(). */ +svn_error_t * +svn_ra_serf__lock(svn_ra_session_t *ra_session, + apr_hash_t *path_revs, + const char *comment, + svn_boolean_t force, + svn_ra_lock_callback_t lock_func, + void *lock_baton, + apr_pool_t *pool); + +/* Implements svn_ra__vtable_t.unlock(). */ +svn_error_t * +svn_ra_serf__unlock(svn_ra_session_t *ra_session, + apr_hash_t *path_tokens, + svn_boolean_t force, + svn_ra_lock_callback_t lock_func, + void *lock_baton, + apr_pool_t *pool); + +/* Implements svn_ra__vtable_t.get_lock(). */ +svn_error_t * +svn_ra_serf__get_lock(svn_ra_session_t *ra_session, + svn_lock_t **lock, + const char *path, + apr_pool_t *pool); + +/* Implements svn_ra__vtable_t.get_locks(). */ +svn_error_t * +svn_ra_serf__get_locks(svn_ra_session_t *ra_session, + apr_hash_t **locks, + const char *path, + svn_depth_t depth, + apr_pool_t *pool); + +/* Request a mergeinfo-report from the URL attached to SESSION, + and fill in the MERGEINFO hash with the results. + + Implements svn_ra__vtable_t.get_mergeinfo(). + */ +svn_error_t * +svn_ra_serf__get_mergeinfo(svn_ra_session_t *ra_session, + apr_hash_t **mergeinfo, + const apr_array_header_t *paths, + svn_revnum_t revision, + svn_mergeinfo_inheritance_t inherit, + svn_boolean_t include_descendants, + apr_pool_t *pool); + +/* Exchange capabilities with the server, by sending an OPTIONS + * request announcing the client's capabilities, and by filling + * SERF_SESS->capabilities with the server's capabilities as read from + * the response headers. Use POOL only for temporary allocation. + * + * If the CORRECTED_URL is non-NULL, allow the OPTIONS response to + * report a server-dictated redirect or relocation (HTTP 301 or 302 + * error codes), setting *CORRECTED_URL to the value of the corrected + * repository URL. Otherwise, such responses from the server will + * generate an error. (In either case, no capabilities are exchanged + * if there is, in fact, such a response from the server.) + */ +svn_error_t * +svn_ra_serf__exchange_capabilities(svn_ra_serf__session_t *serf_sess, + const char **corrected_url, + apr_pool_t *pool); + +/* Implements svn_ra__vtable_t.has_capability(). */ +svn_error_t * +svn_ra_serf__has_capability(svn_ra_session_t *ra_session, + svn_boolean_t *has, + const char *capability, + apr_pool_t *pool); + +/* Implements svn_ra__vtable_t.get_deleted_rev(). */ +svn_error_t * +svn_ra_serf__get_deleted_rev(svn_ra_session_t *session, + const char *path, + svn_revnum_t peg_revision, + svn_revnum_t end_revision, + svn_revnum_t *revision_deleted, + apr_pool_t *pool); + +/* Implements the get_inherited_props RA layer function. */ +svn_error_t * svn_ra_serf__get_inherited_props(svn_ra_session_t *session, + apr_array_header_t **iprops, + const char *path, + svn_revnum_t revision, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/* Implements svn_ra__vtable_t.get_repos_root(). */ +svn_error_t * +svn_ra_serf__get_repos_root(svn_ra_session_t *ra_session, + const char **url, + apr_pool_t *pool); + +/* Implements svn_ra__vtable_t.register_editor_shim_callbacks(). */ +svn_error_t * +svn_ra_serf__register_editor_shim_callbacks(svn_ra_session_t *session, + svn_delta_shim_callbacks_t *callbacks); + +/*** Authentication handler declarations ***/ + +/** + * Callback function that loads the credentials for Basic and Digest + * authentications, both for server and proxy authentication. + */ +apr_status_t +svn_ra_serf__credentials_callback(char **username, char **password, + serf_request_t *request, void *baton, + int code, const char *authn_type, + const char *realm, + apr_pool_t *pool); + + +/*** General utility functions ***/ + +/** + * Convert an HTTP STATUS_CODE resulting from a WebDAV request against + * PATH to the relevant error code. Use the response-supplied LOCATION + * where it necessary. + */ +svn_error_t * +svn_ra_serf__error_on_status(int status_code, + const char *path, + const char *location); + +/* ###? */ +svn_error_t * +svn_ra_serf__copy_into_spillbuf(svn_spillbuf_t **spillbuf, + serf_bucket_t *bkt, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/* ###? */ +serf_bucket_t * +svn_ra_serf__create_sb_bucket(svn_spillbuf_t *spillbuf, + serf_bucket_alloc_t *allocator, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/** Wrap STATUS from an serf function. If STATUS is not serf error code, + * this is equivalent to svn_error_wrap_apr(). + */ +svn_error_t * +svn_ra_serf__wrap_err(apr_status_t status, + const char *fmt, + ...); + + +#if defined(SVN_DEBUG) +/* Wrapper macros to collect file and line information */ +#define svn_ra_serf__wrap_err \ + (svn_error__locate(__FILE__,__LINE__), (svn_ra_serf__wrap_err)) + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SVN_LIBSVN_RA_SERF_RA_SERF_H */ |