[[[ Update Subversion to work with either Neon 0.24.7 or 0.25.0. Thanks to Joe Orton for help. ################################################################ ### ### ### PATCH IN PROGRESS, DO NOT COMMIT YET. ### ### ### ################################################################ This updates configury to allow either Neon 0.24.7 or 0.25.0, then adds compile-time conditional blocks throughout libsvn_ra_dav to DTRT for whichever version of Neon is in effect. The patch is theoretically complete, but with Neon 0.25.0 it doesn't pass 'make davcheck' yet. Don't know why yet, still debugging. It does pass with Neon 0.24.7, so we haven't lost any ground at least. Search for "###" in the diff for a few minor cleanups/tweaks that should be considered. * build/ac-macros/neon.m4 (NEON_ALLOWED_LIST): Replaces NEON_WANTED_REGEX because there isn't actually enough regexp support in Bourne shell to test for both 0.24.7 and 0.25.0 in one 'case' statement. (NEON_LATEST_WORKING_VER): Bump up to 0.25.0. (SVN_LIB_NEON, SVN_NEON_CONFIG): Rewrite version testing accordingly, and define SVN_NEON_0_25_0 if find Neon 0.25.0. * subversion/libsvn_ra_dav/ra_dav.h (svn_ra_dav__request_interrogator): New callback type. (svn_ra_dav__request_dispatch): Add interrogator callback and baton to parameters, in Neon 0.25.0.5 (struct lock_request_baton): Store an ne_request * pointer. * subversion/libsvn_ra_dav/commit.c (interrogate_for_location): New interrogator callback. (do_checkout): Get "location" header from the response in either the Neon 0.24.7 way or the 0.25.0 way, depending on which is operative. (simple_request, commit_delete_entry, commit_close_file): Pass null interrogators to svn_ra_dav__request_dispatch if Neon 0.25.0. * subversion/libsvn_ra_dav/fetch.c (fetch_file_reader, get_file_reader): Return int if Neon 0.25.0. Document that these implement the ne_block_reader interface. (interrogate_for_content_type): New interrogator callback. (custom_get_request): Get the content-type from the request response in the 0.24.7 way or the 0.25.0 way as appropriate. Also, lose the effectively unused 'code' variable, and explicitly ignore the integer returned from svn_ra_dav__request_dispatch(), which we were implicitly ignoring anyway. * subversion/libsvn_ra_dav/session.c (handle_creationdate_header, handle_lock_owner_header): Only define these if Neon 0.24.7. (post_send_hook): New function to get lock metadata; define this function only if Neon 0.25.0. (setup_neon_request_hook): Register post_send_hook, if Neon 0.25.0. (ra_dav_get_schemes, svn_ra_dav__open): Use the new ne_has_support() interface instead of ne_supports_ssl(), in Neon 0.25.0. (svn_ra_dav__lock, svn_ra_dav__unlock, svn_ra_dav__get_lock): Add comments about what remains to be done. (create_request_hook): Store the request pointer in the baton. * subversion/libsvn_ra_dav/util.c (spool_reader): Return int if Neon 0.25.0. Document that this implements the ne_block_reader interface. (parsed_request): Handle ne_decompress_destroy correctly for both 0.24.7 and 0.25.0. (svn_ra_dav__request_dispatch): If Neon 0.25.0, take a request interrogator and baton, and invoke them on the request. (ra_dav_error_accepter): If Neon 0.25.0, only accept the request if the content-type is text/xml. * subversion/libsvn_ra_dav/file_revs.c (svn_ra_dav__get_file_revs): Return error from baton in preference to error from svn_ra_dav__request_dispatch. Fix error leak. * subversion/include/svn_error_codes.h (SVN_ERR_RA_DAV_RESPONSE_HEADER_BADNESS): New error code. ]]] Index: configure.in =================================================================== --- configure.in (revision 14779) +++ configure.in (working copy) @@ -225,8 +225,10 @@ esac AC_SUBST(LT_NO_UNDEFINED) -NEON_WANTED_REGEX=0.24.7 -NEON_LATEST_WORKING_VER=0.24.7 +# Either a space-separated list of allowable Neon versions, or "any" to +# mean allow anything. +NEON_ALLOWED_LIST="0.24.7 0.25.0" +NEON_LATEST_WORKING_VER=0.25.0 NEON_URL="http://www.webdav.org/neon/neon-${NEON_LATEST_WORKING_VER}.tar.gz" dnl You can skip the neon version check only if you know what you are doing AC_ARG_ENABLE(neon-version-check, @@ -234,11 +236,11 @@ [do not check the Neon version]), [ if test "$enableval" = "no" ; then - NEON_WANTED_REGEX="*" + NEON_ALLOWED_LIST="any" fi ], []) -SVN_LIB_NEON($NEON_WANTED_REGEX, $NEON_LATEST_WORKING_VER, $NEON_URL) +SVN_LIB_NEON($NEON_ALLOWED_LIST, $NEON_LATEST_WORKING_VER, $NEON_URL) dnl find Apache with a recent-enough magic module number. SVN_FIND_APACHE(20020903) Index: subversion/include/svn_error_codes.h =================================================================== --- subversion/include/svn_error_codes.h (revision 14779) +++ subversion/include/svn_error_codes.h (working copy) @@ -704,6 +704,10 @@ SVN_ERR_RA_DAV_CATEGORY_START + 9, "Malformed network data") + /* @since New in 1.3 */ + SVN_ERRDEF (SVN_ERR_RA_DAV_RESPONSE_HEADER_BADNESS, + SVN_ERR_RA_DAV_CATEGORY_START + 10, + "Unable to extract data from response header") /* ra_local errors */ Index: subversion/libsvn_ra_dav/file_revs.c =================================================================== --- subversion/libsvn_ra_dav/file_revs.c (revision 14779) +++ subversion/libsvn_ra_dav/file_revs.c (working copy) @@ -358,8 +358,17 @@ if (http_status == 501) return svn_error_create (SVN_ERR_RA_NOT_IMPLEMENTED, err, _("'get-file-revs' REPORT not implemented")); + + /* rb.err contains the relevant error if the response was aborted by + * a callback returning NE_XML_ABORT; always return that error if + * present. */ + if (rb.err != NULL) + { + if (err) + svn_error_clear (err); + return rb.err; + } SVN_ERR (err); - SVN_ERR (rb.err); /* Caller expects at least one revision. Signal error otherwise. */ if (!SVN_IS_VALID_REVNUM(rb.revnum)) Index: subversion/libsvn_ra_dav/ra_dav.h =================================================================== --- subversion/libsvn_ra_dav/ra_dav.h (revision 14779) +++ subversion/libsvn_ra_dav/ra_dav.h (working copy) @@ -143,6 +143,9 @@ /* If is returned, here's where the parsed result goes. */ svn_error_t *err; + /* The neon request being executed */ + ne_request *request; + /* A place for allocating fields in this structure. */ apr_pool_t *pool; }; @@ -743,6 +746,17 @@ apr_pool_t *pool); +/* Callback to get data from a Neon request after it has been sent. + + REQUEST is the request, DISPATCH_RETURN_VAL is the value that + ne_request_dispatch(REQUEST) returned to the caller. + + USERDATA is a closure baton. */ +typedef svn_error_t * +svn_ra_dav__request_interrogator(ne_request *request, + int dispatch_return_val, + void *userdata); + /* Given a neon REQUEST and SESSION, run the request; if CODE_P is non-null, return the http status code in *CODE_P. Return any resulting error (from neon, a body response, or any @@ -757,6 +771,16 @@ specified (e.g. as 200); use 0 for OKAY_2 if a second result code is not allowed. + #if SVN_NEON_0_25_0 + + If INTERROGATOR is non-NULL, invoke it with the Neon request, + the dispatch result, and INTERROGATOR_BATON. This is done + regardless of whether the request appears successful or not. If + the interrogator has an error result, return that error + immediately, after freeing the request. + + #endif // SVN_NEON_0_25_0 + ### not super sure on this "okay" stuff, but it means that the request ### dispatching code can generate much better errors than the callers ### when something goes wrong. if we need more than two, then we could @@ -771,6 +795,10 @@ const char *url, int okay_1, int okay_2, +#if SVN_NEON_0_25_0 + svn_ra_dav__request_interrogator interrogator, + void *interrogator_baton, +#endif /* SVN_NEON_0_25_0 */ apr_pool_t *pool); Index: subversion/libsvn_ra_dav/session.c =================================================================== --- subversion/libsvn_ra_dav/session.c (revision 14779) +++ subversion/libsvn_ra_dav/session.c (working copy) @@ -553,7 +553,11 @@ static const char *schemes_no_ssl[] = { "http", NULL }; static const char *schemes_ssl[] = { "http", "https", NULL }; +#if SVN_NEON_0_25_0 + return ne_has_support(NE_FEATURE_SSL) ? schemes_ssl : schemes_no_ssl; +#else /* ! SVN_NEON_0_25_0 */ return ne_supports_ssl() ? schemes_ssl : schemes_no_ssl; +#endif /* if/else SVN_NEON_0_25_0 */ } @@ -602,7 +606,11 @@ is_ssl_session = (strcasecmp(uri.scheme, "https") == 0); if (is_ssl_session) { +#if SVN_NEON_0_25_0 + if (ne_has_support(NE_FEATURE_SSL) == 0) +#else /* ! SVN_NEON_0_25_0 */ if (ne_supports_ssl() == 0) +#endif /* if/else SVN_NEON_0_25_0 */ { ne_uri_free(&uri); return svn_error_create(SVN_ERR_RA_DAV_SOCK_INIT, NULL, @@ -856,6 +864,7 @@ } +#ifndef SVN_NEON_0_25_0 /* A callback of type ne_header_handler, invoked when neon encounters mod_dav_svn's custom 'creationdate' header in a LOCK response. */ static void @@ -890,10 +899,9 @@ lrb->lock_owner = apr_pstrdup(lrb->pool, value); } +#endif /* ! SVN_NEON_0_25_0 */ - - /* A callback of type ne_create_request_fn; called whenever neon creates a request. */ static void @@ -909,7 +917,10 @@ if ((strcmp(method, "LOCK") == 0) || (strcmp(method, "UNLOCK") == 0) || (strcmp(method, "PROPFIND") == 0)) - lrb->method = apr_pstrdup(lrb->pool, method); + { + lrb->method = apr_pstrdup(lrb->pool, method); + lrb->request = req; + } } @@ -951,12 +962,14 @@ ne_buffer_zappend(header, buf); } +#ifndef SVN_NEON_0_25_0 /* Register callbacks to read any custom 'creationdate' and 'lock owner' response headers sent by mod_dav_svn. */ ne_add_response_header_handler(req, SVN_DAV_CREATIONDATE_HEADER, handle_creationdate_header, lrb); ne_add_response_header_handler(req, SVN_DAV_LOCK_OWNER_HEADER, handle_lock_owner_header, lrb); +#endif /* ! SVN_NEON_0_25_0 */ } if (strcmp(lrb->method, "UNLOCK") == 0) @@ -977,6 +990,49 @@ } +#if SVN_NEON_0_25_0 +/* A callback of type ne_post_send_fn; called after neon has sent a + request and received a response header back. */ +static int +post_send_hook(ne_request *req, + void *userdata, + const ne_status *status) +{ + struct lock_request_baton *lrb = userdata; + + if (! lrb->method) + return NE_OK; + + if ((strcmp(lrb->method, "LOCK") == 0) + || (strcmp(lrb->method, "PROPFIND") == 0)) + { + const char *val; + + val = ne_get_response_header(req, SVN_DAV_CREATIONDATE_HEADER); + if (val) + { + svn_error_t *err = svn_time_from_cstring(&(lrb->creation_date), + val, lrb->pool); + if (err) + { + svn_error_clear(err); + lrb->creation_date = 0; + /* ### Should we return NE_RETRY in this case? And if + ### we were to do that, would we also set *status + ### and call ne_set_error? */ + } + } + + val = ne_get_response_header(req, SVN_DAV_LOCK_OWNER_HEADER); + if (val) + lrb->lock_owner = apr_pstrdup(lrb->pool, val); + } + + return NE_OK; +} +#endif /* SVN_NEON_0_25_0 */ + + static void setup_neon_request_hook(svn_ra_dav__session_t *ras) { @@ -991,6 +1047,9 @@ ne_hook_create_request(ras->sess, create_request_hook, lrb); ne_hook_pre_send(ras->sess, pre_send_hook, lrb); +#if SVN_NEON_0_25_0 + ne_hook_post_send(ras->sess, post_send_hook, lrb); +#endif /* SVN_NEON_0_25_0 */ lrb->pool = ras->pool; ras->lrb = lrb; @@ -1315,6 +1374,16 @@ if (lock) { +#if SVN_NEON_0_25_0 + /* The post_send hook has not run at this stage; so grab the + * response headers early. */ + if (post_send_hook(rb->lrb->request, rb->lrb, + ne_get_status(rb->lrb->request))) + { + return; + } +#endif + if (!rb->lrb->lock_owner || !rb->lrb->creation_date) { rb->err = svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL, Index: subversion/libsvn_ra_dav/commit.c =================================================================== --- subversion/libsvn_ra_dav/commit.c (revision 14779) +++ subversion/libsvn_ra_dav/commit.c (working copy) @@ -211,6 +211,9 @@ /* run the request and get the resulting status code (and svn_error_t) */ SVN_ERR( svn_ra_dav__request_dispatch(code, req, ras->sess, method, url, okay_1, okay_2, +#if SVN_NEON_0_25_0 + NULL, NULL, +#endif /* SVN_NEON_0_25_0 */ pool) ); return SVN_NO_ERROR; @@ -438,6 +441,27 @@ return SVN_NO_ERROR; } +#if SVN_NEON_0_25_0 +/* This implements the svn_ra_dav__request_interrogator() interface. + USERDATA is 'char **'. */ +static svn_error_t *interrogate_for_location(ne_request *request, + int dispatch_return_val, + void *userdata) +{ + char **location = userdata; + + if (location) + { + const char *val = ne_get_response_header(request, "location"); + if (val) + *location = strdup(val); + } + + return SVN_NO_ERROR; +} +#endif /* SVN_NEON_0_25_0 */ + + static svn_error_t * do_checkout(commit_ctx_t *cc, const char *vsn_url, svn_boolean_t allow_404, @@ -448,6 +472,7 @@ { ne_request *req; const char *body; + svn_error_t *err; /* assert: vsn_url != NULL */ @@ -472,12 +497,14 @@ "", cc->activity_url); ne_set_request_body_buffer(req, body, strlen(body)); +#ifndef SVN_NEON_0_25_0 /* * We have different const qualifiers here. locn is const char **, * but the prototype is void * (as opposed to const void *). */ ne_add_response_header_handler(req, "location", ne_duplicate_header, (void *)locn); +#endif /* ! SVN_NEON_0_25_0 */ if (token) { @@ -487,11 +514,16 @@ } /* run the request and get the resulting status code (and svn_error_t) */ - return svn_ra_dav__request_dispatch(code, req, cc->ras->sess, - "CHECKOUT", vsn_url, - 201 /* Created */, - allow_404 ? 404 /* Not Found */ : 0, - pool); + err = svn_ra_dav__request_dispatch(code, req, cc->ras->sess, + "CHECKOUT", vsn_url, + 201 /* Created */, + allow_404 ? 404 /* Not Found */ : 0, +#if SVN_NEON_0_25_0 + interrogate_for_location, locn, +#endif /* SVN_NEON_0_25_0 */ + pool); + + return err; } @@ -857,7 +889,11 @@ SVN_ERR (svn_ra_dav__request_dispatch(&code, req, parent->cc->ras->sess, "DELETE", child, 204 /* Created */, - 404 /* Not Found */, pool)); + 404 /* Not Found */, +#if SVN_NEON_0_25_0 + NULL, NULL, +#endif /* SVN_NEON_0_25_0 */ + pool)); } else if (serr) return serr; @@ -1399,6 +1435,9 @@ err = svn_ra_dav__request_dispatch(&code, req, sess, "PUT", url, 201 /* Created */, 204 /* No Content */, +#if SVN_NEON_0_25_0 + NULL, NULL, +#endif /* SVN_NEON_0_25_0 */ pool); /* we're done with the file. this should delete it. */ Index: subversion/libsvn_ra_dav/fetch.c =================================================================== --- subversion/libsvn_ra_dav/fetch.c (revision 14779) +++ subversion/libsvn_ra_dav/fetch.c (working copy) @@ -383,6 +383,25 @@ } +#if SVN_NEON_0_25_0 +/* This implements the svn_ra_dav__request_interrogator() interface. + USERDATA is 'ne_content_type *'. */ +static svn_error_t *interrogate_for_content_type(ne_request *request, + int dispatch_return_val, + void *userdata) +{ + ne_content_type *ctype = userdata; + + if (ne_get_content_type(request, ctype) != 0) + return svn_error_createf + (SVN_ERR_RA_DAV_RESPONSE_HEADER_BADNESS, NULL, + _("Could not get content-type from response.")); + + return SVN_NO_ERROR; +} +#endif /* SVN_NEON_0_25_0 */ + + static svn_error_t *custom_get_request(ne_session *sess, const char *url, const char *relpath, @@ -398,8 +417,9 @@ ne_request *req; ne_decompress *decompress; svn_error_t *err; - int code; +#ifndef SVN_NEON_0_25_0 int decompress_rv; +#endif /* ! SVN_NEON_0_25_0 */ svn_ra_dav__session_t *ras = ne_get_session_private(sess, SVN_RA_NE_SESSION_ID); @@ -424,10 +444,12 @@ url); } +#ifndef SVN_NEON_0_25_0 /* we want to get the Content-Type so that we can figure out whether this is an svndiff or a fulltext */ ne_add_response_header_handler(req, "Content-Type", ne_content_type_handler, &cgc.ctype); +#endif /* ! SVN_NEON_0_25_0 */ if (delta_base) { @@ -456,16 +478,24 @@ /* complete initialization of the body reading context */ cgc.subctx = subctx; - /* run the request and get the resulting status code (and svn_error_t) */ - err = svn_ra_dav__request_dispatch(&code, req, sess, "GET", url, + /* run the request */ + err = svn_ra_dav__request_dispatch(NULL, req, sess, "GET", url, 200 /* OK */, 226 /* IM Used */, +#if SVN_NEON_0_25_0 + interrogate_for_content_type, &cgc.ctype, +#endif /* SVN_NEON_0_25_0 */ pool); +#if SVN_NEON_0_25_0 + if (decompress) + ne_decompress_destroy(decompress); +#else /* ! SVN_NEON_0_25_0 */ if (decompress) decompress_rv = ne_decompress_destroy(decompress); else decompress_rv = 0; +#endif /* if/else SVN_NEON_0_25_0 */ /* we no longer need this */ if (cgc.ctype.value != NULL) @@ -480,6 +510,7 @@ return cgc.err; } +#ifndef SVN_NEON_0_25_0 if (decompress_rv != 0) { const char *msg; @@ -489,34 +520,49 @@ svn_error_clear (err); err = svn_ra_dav__convert_error(sess, msg, decompress_rv, pool); } - +#endif /* ! SVN_NEON_0_25_0 */ + if (err) return err; return SVN_NO_ERROR; } -static void fetch_file_reader(void *userdata, const char *buf, size_t len) +/* This implements the ne_block_reader() callback interface. */ +#if SVN_NEON_0_25_0 +static int +#else /* ! SVN_NEON_0_25_0 */ +static void +#endif /* if/else SVN_NEON_0_25_0 */ +fetch_file_reader(void *userdata, const char *buf, size_t len) { custom_get_ctx_t *cgc = userdata; file_read_ctx_t *frc = cgc->subctx; if (cgc->err) { - /* We must have gotten an error during the last read... + /* We must have gotten an error during the last read. */ +#if SVN_NEON_0_25_0 + /* Abort the rest of the read. */ + /* ### Call ne_set_error(), as ne_block_reader doc implies? */ + return 1; +#else /* ! SVN_NEON_0_25_0 */ + /* In Neon < 0.25.0, we have no way to abort the read process, + so we'll just have to eat all the data, even though we + already know we can't handle it. */ + return; +#endif /* if/else SVN_NEON_0_25_0 */ - ### what we'd *really* like to do here (or actually, at the - bottom of this function) is to somehow abort the read - process...no sense on banging a server for 10 megs of data - when we've already established that we, for some reason, - can't handle that data. */ - return; } if (len == 0) { /* file is complete. */ +#if SVN_NEON_0_25_0 + return 0; +#else /* ! SVN_NEON_0_25_0 */ return; +#endif /* if/else SVN_NEON_0_25_0 */ } if (!cgc->checked_type) @@ -587,6 +633,10 @@ written, len); #endif } + +#if SVN_NEON_0_25_0 + return 0; +#endif /* SVN_NEON_0_25_0 */ } static svn_error_t *simple_fetch_file(ne_session *sess, @@ -629,11 +679,18 @@ return SVN_NO_ERROR; } -/* Helper (neon callback) for svn_ra_dav__get_file. */ -static void get_file_reader(void *userdata, const char *buf, size_t len) +/* Helper (neon callback) for svn_ra_dav__get_file. This implements + the ne_block_reader() callback interface. */ +#if SVN_NEON_0_25_0 +static int +#else /* ! SVN_NEON_0_25_0 */ +static void +#endif /* if/else SVN_NEON_0_25_0 */ +get_file_reader(void *userdata, const char *buf, size_t len) { custom_get_ctx_t *cgc = userdata; apr_size_t wlen; + svn_error_t *err; /* The stream we want to push data at. */ file_write_ctx_t *fwc = cgc->subctx; @@ -644,22 +701,22 @@ /* Write however many bytes were passed in by neon. */ wlen = len; - svn_error_clear(svn_stream_write(stream, buf, &wlen)); + err = svn_stream_write(stream, buf, &wlen); -#if 0 - /* Neon's callback won't let us return error. Joe knows this is a - bug in his API, so this section can be reactivated someday. */ - - SVN_ERR(svn_stream_write(stream, buf, &wlen)); - if (wlen != len) +#if SVN_NEON_0_25_0 + /* Technically, if the write came up short then there's guaranteed + to be an error anyway, so we only really need to check for error. + But heck, why not gather as much information as possible about + what happened before tossing it all and just returning non-zero? */ + if (err || (wlen != len)) { - /* Uh oh, didn't write as many bytes as neon gave us. */ - return - svn_error_create(SVN_ERR_STREAM_UNEXPECTED_EOF, NULL, - _("Error writing to stream: unexpected EOF")); + /* ### Call ne_set_error(), as ne_block_reader doc implies? */ + svn_error_clear(err); + return 1; } -#endif - + + return 0; +#endif /* SVN_NEON_0_25_0 */ } @@ -2805,10 +2862,17 @@ /* we're done with the file */ (void) apr_file_close(rb->tmpfile); + /* rb->err contains the relevant error if the response was aborted + * by a callback returning NE_XML_ABORT; always return that error if + * present. */ + if (rb->err != NULL) + { + if (err) + svn_error_clear(err); + return rb->err; + } if (err != NULL) return err; - if (rb->err != NULL) - return rb->err; /* We got the whole HTTP response thing done. *Whew*. Our edit baton should have been closed by now, so return a failure if it Index: subversion/libsvn_ra_dav/util.c =================================================================== --- subversion/libsvn_ra_dav/util.c (revision 14779) +++ subversion/libsvn_ra_dav/util.c (working copy) @@ -24,6 +24,7 @@ #include #include #include +#include #include "svn_pools.h" #include "svn_path.h" @@ -306,8 +307,23 @@ ne_request *req, const ne_status *st) { +#if SVN_NEON_0_25_0 + ne_content_type ctype; + + /* Only accept non-2xx responses with text/xml content-type */ + if (st->klass != 2 && ne_get_content_type(req, &ctype) == 0) + { + int is_xml = + (strcmp(ctype.type, "text") == 0 && strcmp(ctype.subtype, "xml") == 0); + ne_free(ctype.value); + return is_xml; + } + else + return 0; +#else /* Only accept the body-response if the HTTP status code is *not* 2XX. */ return (st->klass != 2); +#endif } @@ -483,7 +499,12 @@ } spool_reader_baton_t; -static void +/* This implements the ne_block_reader() callback interface. */ +#if SVN_NEON_0_25_0 +static int +#else /* ! SVN_NEON_0_25_0 */ +static void +#endif /* if/else SVN_NEON_0_25_0 */ spool_reader(void *userdata, const char *buf, size_t len) @@ -492,6 +513,14 @@ if (! baton->error) baton->error = svn_io_file_write_full(baton->spool_file, buf, len, NULL, baton->pool); + +#if SVN_NEON_0_25_0 + if (baton->error) + /* ### Call ne_set_error(), as ne_block_reader doc implies? */ + return 1; + else + return 0; +#endif /* SVN_NEON_0_25_0 */ } @@ -556,7 +585,9 @@ ne_xml_parser *success_parser = NULL; ne_xml_parser *error_parser = NULL; int rv; +#ifndef SVN_NEON_0_25_0 int decompress_rv; +#endif /* ! SVN_NEON_0_25_0 */ int code; int expected_code; const char *msg; @@ -691,7 +722,14 @@ } } +#if SVN_NEON_0_25_0 if (decompress_main) + ne_decompress_destroy(decompress_main); + + if (decompress_err) + ne_decompress_destroy(decompress_err); +#else /* ! SVN_NEON_0_25_0 */ + if (decompress_main) { decompress_rv = ne_decompress_destroy(decompress_main); if (decompress_rv != 0) @@ -708,6 +746,7 @@ rv = decompress_rv; } } +#endif /* if/else SVN_NEON_0_25_0 */ code = ne_get_status(req)->code; if (status_code) @@ -883,6 +922,10 @@ const char *url, int okay_1, int okay_2, +#if SVN_NEON_0_25_0 + svn_ra_dav__request_interrogator interrogator, + void *interrogator_baton, +#endif /* SVN_NEON_0_25_0 */ apr_pool_t *pool) { ne_xml_parser *error_parser; @@ -892,6 +935,9 @@ int code; const char *msg; svn_error_t *err = SVN_NO_ERROR; +#if SVN_NEON_0_25_0 + svn_error_t *err2 = SVN_NO_ERROR; +#endif /* SVN_NEON_0_25_0 */ /* attach a standard body parser to the request */ error_parser = ne_xml_create(); @@ -910,9 +956,20 @@ if (code_p) *code_p = code; +#if SVN_NEON_0_25_0 + if (interrogator) + err2 = (*interrogator)(request, rv, interrogator_baton); +#endif /* SVN_NEON_0_25_0 */ + ne_request_destroy(request); ne_xml_destroy(error_parser); +#if SVN_NEON_0_25_0 + /* If the request interrogator returned error, pass that along now. */ + if (err2) + return err2; +#endif /* SVN_NEON_0_25_0 */ + /* If the status code was one of the two that we expected, then go ahead and return now. IGNORE any marshalled error. */ if (rv == NE_OK && (code == okay_1 || code == okay_2)) Index: build/ac-macros/neon.m4 =================================================================== --- build/ac-macros/neon.m4 (revision 14779) +++ build/ac-macros/neon.m4 (working copy) @@ -22,7 +22,7 @@ AC_DEFUN(SVN_LIB_NEON, [ - NEON_WANTED_REGEX="$1" + NEON_ALLOWED_LIST="$1" NEON_LATEST_WORKING_VER="$2" NEON_URL="$3" @@ -49,18 +49,26 @@ NEON_VERSION=`cat $abs_srcdir/neon/.version` AC_MSG_RESULT([$NEON_VERSION]) - case "$NEON_VERSION" in - $NEON_WANTED_REGEX) + + if test $NEON_VERSION = "0.25.0" ; then + AC_DEFINE_UNQUOTED([SVN_NEON_0_25_0], [1], + [Defined if have Neon 0.25.0 instead of 0.24.7.]) + fi + + for svn_allowed_neon in $NEON_ALLOWED_LIST; do + if test "$NEON_VERSION" = "$svn_allowed_neon" -o $svn_allowed_neon = "any"; then echo "Using neon found in source directory." + svn_allowed_neon_in_srcdir="yes" SVN_NEON_INCLUDES=-'I$(abs_srcdir)/neon/src' NEON_LIBS="\$(abs_builddir)/neon/src/libneon.la" dnl Configure neon -------------------------- - # The arguments passed to this configure script are passed down to - # neon's configure script, but, since neon defaults to *not* building - # shared libs, and we default to building shared libs, we have to - # explicitly pass down an --{enable,disable}-shared argument, to make - # sure neon does the same as we do. + # The arguments passed to this configure script are passed + # down to neon's configure script, but, since neon + # defaults to *not* building shared libs, and we default + # to building shared libs, we have to explicitly pass down + # an --{enable,disable}-shared argument, to make sure neon + # does the same as we do. if test "$enable_shared" = "yes"; then args="--enable-shared" else @@ -72,7 +80,7 @@ if test -f "$abs_builddir/apr-util/xml/expat/lib/expat.h" ; then args="$args --with-expat='$abs_builddir/apr-util/xml/expat/lib/libexpat.la'" fi - SVN_SUBDIR_CONFIG(neon, $args) + SVN_SUBDIR_CONFIG(neon, $args) if test -f "$abs_builddir/neon/neon-config" ; then AC_MSG_CHECKING([for any extra libraries neon needs]) @@ -89,14 +97,16 @@ fi SVN_SUBDIRS="$SVN_SUBDIRS neon" - ;; + break + fi + done - *) - echo "You have a neon/ subdir containing version $NEON_VERSION," - echo "but Subversion needs neon ${NEON_LATEST_WORKING_VER}." - SVN_DOWNLOAD_NEON() - ;; - esac + if test -z $svn_allowed_neon_in_srcdir; then + echo "You have a neon/ subdir containing version $NEON_VERSION," + echo "but Subversion needs neon ${NEON_LATEST_WORKING_VER}." + SVN_DOWNLOAD_NEON() + fi + else # no --with-neon switch, and no neon subdir, look in PATH AC_PATH_PROG(neon_config,neon-config) @@ -119,25 +129,35 @@ NEON_VERSION=`$neon_config --version | sed -e 's/^neon //'` AC_MSG_RESULT([$NEON_VERSION]) - case "$NEON_VERSION" in - $NEON_WANTED_REGEX) - SVN_NEON_INCLUDES=[`$neon_config --cflags | sed -e 's/-D[^ ]*//g'`] - NEON_LIBS=`$neon_config --libs` - CFLAGS=["$CFLAGS `$neon_config --cflags | sed -e 's/-I[^ ]*//g'`"] - svn_lib_neon="yes" - ;; - *) - echo "You have neon version $NEON_VERSION," - echo "but Subversion needs neon $NEON_LATEST_WORKING_VER." - SVN_DOWNLOAD_NEON() - ;; - esac + if test $NEON_VERSION = "0.25.0" ; then + AC_DEFINE_UNQUOTED([SVN_NEON_0_25_0], [1], + [Defined if have Neon 0.25.0 instead of 0.24.7.]) + fi + + for svn_allowed_neon in $NEON_ALLOWED_LIST; do + if test "$NEON_VERSION" = "$svn_allowed_neon" -o $svn_allowed_neon = "any"; then + svn_allowed_neon_on_system="yes" + SVN_NEON_INCLUDES=[`$neon_config --cflags | sed -e 's/-D[^ ]*//g'`] + NEON_LIBS=`$neon_config --libs` + CFLAGS=["$CFLAGS `$neon_config --cflags | sed -e 's/-I[^ ]*//g'`"] + svn_lib_neon="yes" + break + fi + done + + if test -z $svn_allowed_neon_on_system; then + echo "You have neon version $NEON_VERSION," + echo "but Subversion needs neon $NEON_LATEST_WORKING_VER." + SVN_DOWNLOAD_NEON() + fi + else # no neon subdir, no neon-config in PATH AC_MSG_RESULT([nothing]) echo "No suitable neon can be found." SVN_DOWNLOAD_NEON() fi + else # user probably passed --without-neon, or --with-neon=/something/dumb SVN_DOWNLOAD_NEON()