Return-Path: X-Original-To: apmail-subversion-commits-archive@minotaur.apache.org Delivered-To: apmail-subversion-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 24373C4B6 for ; Mon, 7 May 2012 20:25:14 +0000 (UTC) Received: (qmail 12021 invoked by uid 500); 7 May 2012 20:25:14 -0000 Delivered-To: apmail-subversion-commits-archive@subversion.apache.org Received: (qmail 11994 invoked by uid 500); 7 May 2012 20:25:14 -0000 Mailing-List: contact commits-help@subversion.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@subversion.apache.org Delivered-To: mailing list commits@subversion.apache.org Received: (qmail 11985 invoked by uid 99); 7 May 2012 20:25:13 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 07 May 2012 20:25:13 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 07 May 2012 20:25:11 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 858232388978; Mon, 7 May 2012 20:24:51 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1335238 - in /subversion/branches/ev2-export: ./ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_fs/ subversion/libsvn_ra_serf/ subversion/libsvn_wc/ Date: Mon, 07 May 2012 20:24:51 -0000 To: commits@subversion.apache.org From: hwright@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20120507202451.858232388978@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: hwright Date: Mon May 7 20:24:50 2012 New Revision: 1335238 URL: http://svn.apache.org/viewvc?rev=1335238&view=rev Log: On the ev2-export branch: Bring up-to-date with trunk, which fixes a few errors. Modified: subversion/branches/ev2-export/ (props changed) subversion/branches/ev2-export/subversion/include/private/svn_wc_private.h subversion/branches/ev2-export/subversion/include/svn_ra.h subversion/branches/ev2-export/subversion/libsvn_client/ra.c subversion/branches/ev2-export/subversion/libsvn_fs/editor.c subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c subversion/branches/ev2-export/subversion/libsvn_wc/adm_ops.c Propchange: subversion/branches/ev2-export/ ------------------------------------------------------------------------------ Merged /subversion/trunk:r1335172-1335224 Modified: subversion/branches/ev2-export/subversion/include/private/svn_wc_private.h URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/include/private/svn_wc_private.h?rev=1335238&r1=1335237&r2=1335238&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/include/private/svn_wc_private.h (original) +++ subversion/branches/ev2-export/subversion/include/private/svn_wc_private.h Mon May 7 20:24:50 2012 @@ -1089,13 +1089,12 @@ svn_wc__node_pristine_install(svn_wc_con /* Like svn_wc_get_pristine_contents2(), but keyed on the SHA1_CHECKSUM rather than on the local absolute path of the working - file. WCROOT_ABSPATH is the absolute path of the root of the - working copy in whose pristine database we'll be looking for these - contents. */ + file. WRI_ABSPATH is any versioned path of the working copy in + whose pristine database we'll be looking for these contents. */ svn_error_t * svn_wc__get_pristine_contents_by_checksum(svn_stream_t **contents, svn_wc_context_t *wc_ctx, - const char *wcroot_abspath, + const char *wri_abspath, const svn_checksum_t *sha1_checksum, apr_pool_t *result_pool, apr_pool_t *scratch_pool); Modified: subversion/branches/ev2-export/subversion/include/svn_ra.h URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/include/svn_ra.h?rev=1335238&r1=1335237&r2=1335238&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/include/svn_ra.h (original) +++ subversion/branches/ev2-export/subversion/include/svn_ra.h Mon May 7 20:24:50 2012 @@ -127,7 +127,7 @@ typedef svn_error_t *(*svn_ra_invalidate */ typedef svn_error_t *(*svn_ra_get_wc_contents_func_t)(void *baton, svn_stream_t **contents, - svn_checksum_t *sha1_checksum, + const svn_checksum_t *sha1_checksum, apr_pool_t *pool); Modified: subversion/branches/ev2-export/subversion/libsvn_client/ra.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/ra.c?rev=1335238&r1=1335237&r2=1335238&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/libsvn_client/ra.c (original) +++ subversion/branches/ev2-export/subversion/libsvn_client/ra.c Mon May 7 20:24:50 2012 @@ -52,9 +52,12 @@ typedef struct callback_baton_t this base directory. */ const char *base_dir_abspath; - /* Holds the absolute path of the working copy root for the working - copy in which BASE_DIR_ABSPATH is found. */ - const char *wcroot_abspath; + /* TEMPORARY: Is 'base_dir_abspath' a versioned path? cmpilato + suspects that the commit-to-multiple-disjoint-working-copies + code is getting this all wrong, sometimes passing an unversioned + (or versioned in a foreign wc) path here which sorta kinda + happens to work most of the time but is ultimately incorrect. */ + svn_boolean_t base_dir_isversioned; /* An array of svn_client_commit_item3_t * structures, present only during working copy commits. */ @@ -242,12 +245,12 @@ invalidate_wc_props(void *baton, static svn_error_t * get_wc_contents(void *baton, svn_stream_t **contents, - svn_checksum_t *sha1_checksum, + const svn_checksum_t *sha1_checksum, apr_pool_t *pool) { callback_baton_t *cb = baton; - if (! cb->wcroot_abspath) + if (! (cb->base_dir_abspath && cb->base_dir_isversioned)) { *contents = NULL; return SVN_NO_ERROR; @@ -256,7 +259,7 @@ get_wc_contents(void *baton, return svn_error_trace( svn_wc__get_pristine_contents_by_checksum(contents, cb->ctx->wc_ctx, - cb->wcroot_abspath, + cb->base_dir_abspath, sha1_checksum, pool, pool)); } @@ -320,7 +323,6 @@ svn_client__open_ra_session_internal(svn if (base_dir_abspath) { - const char *wcroot_abspath; svn_error_t *err = svn_wc__node_get_repos_info(NULL, &uuid, ctx->wc_ctx, base_dir_abspath, pool, pool); @@ -335,25 +337,7 @@ svn_client__open_ra_session_internal(svn else { SVN_ERR(err); - } - - err = svn_wc__get_wc_root(&wcroot_abspath, ctx->wc_ctx, - base_dir_abspath, pool, pool); - if (err) - { - if (err->apr_err == SVN_ERR_WC_NOT_WORKING_COPY) - { - svn_error_clear(err); - err = SVN_NO_ERROR; - } - else - { - return err; - } - } - else - { - cb->wcroot_abspath = wcroot_abspath; + cb->base_dir_isversioned = TRUE; } } Modified: subversion/branches/ev2-export/subversion/libsvn_fs/editor.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs/editor.c?rev=1335238&r1=1335237&r2=1335238&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/libsvn_fs/editor.c (original) +++ subversion/branches/ev2-export/subversion/libsvn_fs/editor.c Mon May 7 20:24:50 2012 @@ -168,17 +168,54 @@ can_modify(svn_fs_root_t *txn_root, { svn_revnum_t created_rev; - /* Out-of-dateness check: compare the created-rev of the noden + /* Out-of-dateness check: compare the created-rev of the node in the txn against the created-rev of FSPATH. */ SVN_ERR(svn_fs_node_created_rev(&created_rev, txn_root, fspath, scratch_pool)); - /* If CREATED_REV is invalid, that means it's already mutable in the + /* Uncommitted nodes (eg. a descendent of a copy/move/rotate destination) + have no (committed) revision number. Let the caller go ahead and + modify these nodes. + + Note: strictly speaking, they might be performing an "illegal" edit + in certain cases, but let's just assume they're Good Little Boys. + + If CREATED_REV is invalid, that means it's already mutable in the txn, which means it has already passed this out-of-dateness check. (Usually, this happens when looking at a parent directory of an already-modified node) */ - if (SVN_IS_VALID_REVNUM(created_rev) && revision != created_rev) - { + if (!SVN_IS_VALID_REVNUM(created_rev)) + return SVN_NO_ERROR; + + /* If the node is immutable (has a revision), then the caller should + have supplied a valid revision number [that they expect to change]. + The checks further below will determine the out-of-dateness of the + specified revision. */ + /* ### ugh. descendents of copy/move/rotate destinations carry along + ### their original immutable state and (thus) a valid CREATED_REV. + ### but they are logically uncommitted, so the caller will pass + ### SVN_INVALID_REVNUM. (technically, the caller could provide + ### ORIGINAL_REV, but that is semantically incorrect for the Ev2 + ### API). + ### + ### for now, we will assume the caller knows what they are doing + ### and an invalid revision implies such a descendent. in the + ### future, we could examine the ancestor chain looking for a + ### copy/move/rotate-here node and allow the modification (and the + ### converse: if no such ancestor, the caller must specify the + ### correct/intended revision to modify). + */ +#if 1 + if (!SVN_IS_VALID_REVNUM(revision)) + return SVN_NO_ERROR; +#else + if (!SVN_IS_VALID_REVNUM(revision)) + /* ### use a custom error code? */ + return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, + N_("Revision for modifying '%s' is required"), + fspath); +#endif + if (revision < created_rev) { /* We asked to change a node that is *older* than what we found @@ -188,7 +225,7 @@ can_modify(svn_fs_root_t *txn_root, fspath); } - /* revision > created_rev */ + if (revision > created_rev) { /* We asked to change a node that is *newer* than what we found in the transaction. Given that the transaction was based off @@ -226,7 +263,6 @@ can_modify(svn_fs_root_t *txn_root, fspath); } } - } return SVN_NO_ERROR; } @@ -370,13 +406,6 @@ alter_directory_cb(void *baton, /* Note: we ignore CHILDREN. We have no "incomplete" state to worry about, so we don't need to be aware of what children will be created. */ - if (!SVN_IS_VALID_REVNUM(revision)) - /* ### use a custom error code? */ - return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, - N_("Revision for modification of '%s' " - "is required"), - fspath); - SVN_ERR(get_root(&root, eb)); SVN_ERR(can_modify(root, fspath, revision, scratch_pool)); @@ -400,13 +429,6 @@ alter_file_cb(void *baton, const char *fspath = FSPATH(relpath, scratch_pool); svn_fs_root_t *root; - if (!SVN_IS_VALID_REVNUM(revision)) - /* ### use a custom error code? */ - return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, - N_("Revision for modification of '%s' " - "is required"), - fspath); - SVN_ERR(get_root(&root, eb)); SVN_ERR(can_modify(root, fspath, revision, scratch_pool)); @@ -452,13 +474,6 @@ delete_cb(void *baton, const char *fspath = FSPATH(relpath, scratch_pool); svn_fs_root_t *root; - if (!SVN_IS_VALID_REVNUM(revision)) - /* ### use a custom error code? */ - return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, - N_("Revision for deletion of '%s' " - "is required"), - fspath); - SVN_ERR(get_root(&root, eb)); SVN_ERR(can_modify(root, fspath, revision, scratch_pool)); @@ -483,13 +498,6 @@ copy_cb(void *baton, svn_fs_root_t *root; svn_fs_root_t *src_root; - if (!SVN_IS_VALID_REVNUM(src_revision)) - /* ### use a custom error code? */ - return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, - N_("Source revision for copy of '%s' " - "is required"), - src_fspath); - SVN_ERR(get_root(&root, eb)); /* Check if we can we replace the maybe-specified destination (revision). */ @@ -523,13 +531,6 @@ move_cb(void *baton, svn_fs_root_t *root; svn_fs_root_t *src_root; - if (!SVN_IS_VALID_REVNUM(src_revision)) - /* ### use a custom error code? */ - return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, - N_("Source revision for move of '%s' " - "is required"), - src_fspath); - SVN_ERR(get_root(&root, eb)); /* Check if we delete the specified source (revision), and can we replace Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c?rev=1335238&r1=1335237&r2=1335238&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c (original) +++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c Mon May 7 20:24:50 2012 @@ -1241,10 +1241,6 @@ static svn_error_t * local_fetch(report_info_t *info) { const svn_delta_editor_t *update_editor = info->dir->update_editor; - svn_txdelta_window_t delta_window = { 0 }; - svn_txdelta_op_t delta_op; - svn_string_t window_data; - char read_buf[SVN__STREAM_CHUNK_SIZE + 1]; SVN_ERR(open_dir(info->dir)); info->editor_pool = svn_pool_create(info->dir->dir_baton_pool); @@ -1280,33 +1276,8 @@ local_fetch(report_info_t *info) &info->textdelta, &info->textdelta_baton)); - while (1) - { - apr_size_t read_len = SVN__STREAM_CHUNK_SIZE; - - SVN_ERR(svn_stream_read(info->cached_contents, read_buf, &read_len)); - if (read_len == 0) - break; - - window_data.data = read_buf; - window_data.len = read_len; - - delta_op.action_code = svn_txdelta_new; - delta_op.offset = 0; - delta_op.length = read_len; - - delta_window.tview_len = read_len; - delta_window.num_ops = 1; - delta_window.ops = &delta_op; - delta_window.new_data = &window_data; - - SVN_ERR(info->textdelta(&delta_window, info->textdelta_baton)); - - if (read_len < SVN__STREAM_CHUNK_SIZE) - break; - } - - SVN_ERR(info->textdelta(NULL, info->textdelta_baton)); + SVN_ERR(svn_txdelta_send_stream(info->cached_contents, info->textdelta, + info->textdelta_baton, NULL, info->pool)); SVN_ERR(svn_stream_close(info->cached_contents)); info->cached_contents = NULL; @@ -1370,7 +1341,7 @@ handle_local_fetch(serf_request_t *reque if (sl.code != 200) { err = svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL, - _("GET request failed: %d %s"), + _("HEAD request failed: %d %s"), sl.code, sl.reason); return error_fetch(request, fetch_ctx, err); } Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c?rev=1335238&r1=1335237&r2=1335238&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c (original) +++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c Mon May 7 20:24:50 2012 @@ -1109,26 +1109,24 @@ svn_ra_serf__handle_multistatus_only(ser { svn_ra_serf__handler_t *handler = baton; - /* This response handler requires a pool for the server error. */ - SVN_ERR_ASSERT(handler->handler_pool); + /* We should see this just once, in order to initialize SERVER_ERROR. + At that point, the core error processing will take over. If we choose + not to parse an error, then we'll never return here (because we + change the response handler). */ + SVN_ERR_ASSERT(handler->server_error == NULL); - /* If necessary, initialize our XML parser. */ - if (handler->server_error == NULL) { - svn_ra_serf__server_error_t *server_err; serf_bucket_t *hdrs; const char *val; - /* ### it would be nice to avoid allocating this every time. we - ### could potentially have a flag indicating we have examined - ### the Content-Type header already. */ - server_err = apr_pcalloc(handler->handler_pool, sizeof(*server_err)); - server_err->init = TRUE; - hdrs = serf_bucket_response_get_headers(response); val = serf_bucket_headers_get(hdrs, "Content-Type"); if (val && strncasecmp(val, "text/xml", sizeof("text/xml") - 1) == 0) { + svn_ra_serf__server_error_t *server_err; + + server_err = apr_pcalloc(handler->handler_pool, sizeof(*server_err)); + server_err->init = TRUE; server_err->error = svn_error_create(APR_SUCCESS, NULL, NULL); server_err->has_xml_response = TRUE; server_err->contains_precondition_error = FALSE; @@ -1143,6 +1141,8 @@ svn_ra_serf__handle_multistatus_only(ser /* Get the parser to set our DONE flag. */ server_err->parser.done = &handler->done; + + handler->server_error = server_err; } else { @@ -1150,53 +1150,18 @@ svn_ra_serf__handle_multistatus_only(ser ### caller thinks we are "done", then it may never call into ### serf_context_run() again to flush the response. */ handler->done = TRUE; - server_err->error = SVN_NO_ERROR; - } - - handler->server_error = server_err; - } - - /* If server_err->error still contains APR_SUCCESS, it means that we - have not successfully parsed the XML yet. */ - if (handler->server_error - && handler->server_error->error - && handler->server_error->error->apr_err == APR_SUCCESS) - { - svn_error_t *err; - err = svn_ra_serf__handle_xml_parser(request, response, - &handler->server_error->parser, - scratch_pool); - - /* APR_EOF will be returned when parsing is complete. If we see - any other error, return it immediately. In practice the only - other error we expect to see is APR_EAGAIN, which indicates that - we could not parse the XML because the contents are not yet - available to be read. */ - if (!err || !APR_STATUS_IS_EOF(err->apr_err)) - { - return svn_error_trace(err); + /* The body was not text/xml, so we don't know what to do with it. + Toss anything that arrives. */ + handler->response_handler = svn_ra_serf__handle_discard_body; + handler->response_baton = NULL; } - else if (handler->done - && handler->server_error->error->apr_err == APR_SUCCESS) - { - svn_error_clear(handler->server_error->error); - handler->server_error->error = SVN_NO_ERROR; - - /* ### it would be nice to do this, but if we enter this response - ### handler again, it would be re-created. this throws back to - ### the idea of a flag determining whether we haved looked for - ### a server error. */ -#if 0 - handler->server_error = NULL; -#endif - } - - svn_error_clear(err); } - return svn_error_trace(svn_ra_serf__handle_discard_body( - request, response, NULL, scratch_pool)); + /* Returning SVN_NO_ERROR will return APR_SUCCESS to serf, which tells it + to call the response handler again. That will start up the XML parsing, + or it will be dropped on the floor (per the decision above). */ + return SVN_NO_ERROR; } @@ -1674,40 +1639,52 @@ handle_response(serf_request_t *request, serf_bucket_t *response, svn_ra_serf__handler_t *handler, apr_status_t *serf_status, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { - serf_status_line sl; apr_status_t status; svn_error_t *err; + /* ### need to verify whether this already gets init'd on every + ### successful exit. for an error-exit, it will (properly) be + ### ignored by the caller. */ + *serf_status = APR_SUCCESS; + if (!response) { - /* Uh-oh. Our connection died. Requeue. */ + /* Uh-oh. Our connection died. */ if (handler->response_error) SVN_ERR(handler->response_error(request, response, 0, handler->response_error_baton)); + /* Requeue another request for this handler. + ### how do we know if the handler can deal with this?! */ svn_ra_serf__request_create(handler); - return APR_SUCCESS; + return SVN_NO_ERROR; } /* If we're reading the body, then skip all this preparation. */ if (handler->reading_body) goto process_body; - status = serf_bucket_response_status(response, &sl); - if (SERF_BUCKET_READ_ERROR(status)) - { - *serf_status = status; - return SVN_NO_ERROR; /* Handled by serf */ - } - if (!sl.version && (APR_STATUS_IS_EOF(status) || - APR_STATUS_IS_EAGAIN(status))) + /* Copy the Status-Line info into HANDLER, if we don't yet have it. */ + if (handler->sline.version == 0) { - /* The response line is not (yet) ready. */ - *serf_status = status; - return SVN_NO_ERROR; /* Handled by serf */ + serf_status_line sl; + + status = serf_bucket_response_status(response, &sl); + if (status != APR_SUCCESS) + { + /* The response line is not (yet) ready, or some other error. */ + *serf_status = status; + return SVN_NO_ERROR; /* Handled by serf */ + } + + /* If we got APR_SUCCESS, then we should have Status-Line info. */ + SVN_ERR_ASSERT(sl.version != 0); + + handler->sline = sl; + handler->sline.reason = apr_pstrdup(handler->handler_pool, sl.reason); } status = serf_bucket_response_wait_for_headers(response); @@ -1715,10 +1692,20 @@ handle_response(serf_request_t *request, { if (!APR_STATUS_IS_EOF(status)) { + /* Either the headers are not (yet) complete, or there really + was an error. */ *serf_status = status; return SVN_NO_ERROR; } + /* wait_for_headers() will return EOF if there is no body in this + response, or if we completely read the body. The latter is not + true since we would have set READING_BODY to get the body read, + and we would not be back to this code block. + + It can also return EOF if we truly hit EOF while (say) processing + the headers. aka Badness. */ + /* Cases where a lack of a response body (via EOF) is okay: * - A HEAD request * - 204/304 response @@ -1728,21 +1715,24 @@ handle_response(serf_request_t *request, * scream loudly. */ if (strcmp(handler->method, "HEAD") != 0 - && sl.code != 204 - && sl.code != 304) + && handler->sline.code != 204 + && handler->sline.code != 304) { err = svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, svn_error_wrap_apr(status, NULL), _("Premature EOF seen from server" - " (http status=%d)"), sl.code); + " (http status=%d)"), + handler->sline.code); + /* This discard may be no-op, but let's preserve the algorithm used elsewhere in this function for clarity's sake. */ - svn_ra_serf__response_discard_handler(request, response, NULL, pool); + svn_ra_serf__response_discard_handler(request, response, NULL, + scratch_pool); return err; } } - if (handler->conn->last_status_code == 401 && sl.code < 400) + if (handler->conn->last_status_code == 401 && handler->sline.code < 400) { SVN_ERR(svn_auth_save_credentials(handler->session->auth_state, handler->session->pool)); @@ -1750,14 +1740,20 @@ handle_response(serf_request_t *request, handler->session->auth_state = NULL; } - handler->conn->last_status_code = sl.code; + handler->conn->last_status_code = handler->sline.code; - if (sl.code == 405 || sl.code == 409 || sl.code >= 500) + if (handler->sline.code == 405 + || handler->sline.code == 409 + || handler->sline.code >= 500) { /* 405 Method Not allowed. 409 Conflict: can indicate a hook error. 5xx (Internal) Server error. */ - SVN_ERR(svn_ra_serf__handle_server_error(request, response, pool)); + /* ### this is completely wrong. it only catches the current network + ### packet. we need ongoing parsing. see SERVER_ERROR down below + ### in the process_body: area. we'll eventually move to that. */ + SVN_ERR(svn_ra_serf__handle_server_error(request, response, + scratch_pool)); if (!handler->session->pending_error) { @@ -1765,38 +1761,75 @@ handle_response(serf_request_t *request, /* 405 == Method Not Allowed (Occurs when trying to lock a working copy path which no longer exists at HEAD in the repository. */ - - if (sl.code == 405 && !strcmp(handler->method, "LOCK")) + if (handler->sline.code == 405 + && strcmp(handler->method, "LOCK") == 0) apr_err = SVN_ERR_FS_OUT_OF_DATE; - return - svn_error_createf(apr_err, NULL, - _("%s request on '%s' failed: %d %s"), - handler->method, handler->path, - sl.code, sl.reason); + return svn_error_createf(apr_err, NULL, + _("%s request on '%s' failed: %d %s"), + handler->method, handler->path, + handler->sline.code, handler->sline.reason); } return SVN_NO_ERROR; /* Error is set in caller */ } + /* ... and set up the header fields in HANDLER. */ + handler->location = svn_ra_serf__response_get_location( + response, handler->handler_pool); + /* Stop processing the above, on every packet arrival. */ handler->reading_body = TRUE; - /* ... and set up the header fields in HANDLER if the caller is - interested. */ - if (handler->handler_pool != NULL) + process_body: + + /* If we are supposed to parse the body as a server_error, then do + that now. */ + if (handler->server_error != NULL) { - handler->sline = sl; - handler->sline.reason = apr_pstrdup(handler->handler_pool, - handler->sline.reason); - handler->location = svn_ra_serf__response_get_location( - response, handler->handler_pool); + err = svn_ra_serf__handle_xml_parser(request, response, + &handler->server_error->parser, + scratch_pool); + + /* APR_EOF will be returned when parsing is complete. If we see + any other error, return it immediately. + + In practice the only other error we expect to see is APR_EAGAIN, + which indicates the network has no more data right now. This + svn_error_t will get unwrapped, and that APR_EAGAIN will be + returned to serf. We'll get called later, when more network data + is available. */ + if (!err || !APR_STATUS_IS_EOF(err->apr_err)) + return svn_error_trace(err); + + /* Clear the EOF. We don't need it. */ + svn_error_clear(err); + + /* If the parsing is done, and we did not extract an error, then + simply toss everything, and anything else that might arrive. + The higher-level code will need to investigate HANDLER->SLINE, + as we have no further information for them. */ + if (handler->done + && handler->server_error->error->apr_err == APR_SUCCESS) + { + svn_error_clear(handler->server_error->error); + + /* Stop parsing for a server error. */ + handler->server_error = NULL; + + /* If anything arrives after this, then just discard it. */ + handler->response_handler = svn_ra_serf__handle_discard_body; + handler->response_baton = NULL; + } + + *serf_status = APR_EOF; + return SVN_NO_ERROR; } - process_body: + /* Pass the body along to the registered response handler. */ err = handler->response_handler(request, response, handler->response_baton, - pool); + scratch_pool); if (err && (!SERF_BUCKET_READ_ERROR(err->apr_err) @@ -1917,6 +1950,20 @@ svn_ra_serf__request_create(svn_ra_serf_ { SVN_ERR_ASSERT_NO_RETURN(handler->handler_pool != NULL); + /* In case HANDLER is re-queued, reset the various transient fields. + + ### prior to recent changes, HANDLER was constant. maybe we should + ### break out these processing fields, apart from the request + ### definition. */ + handler->done = FALSE; + handler->server_error = NULL; + handler->sline.version = 0; + handler->location = NULL; + handler->reading_body = FALSE; + + /* ### sometimes, we alter the >response_handler. how to reset that? + ### so far, that is just to discard the body. maybe a flag? */ + /* ### do we need to hold onto the returned request object, or just ### not worry about it (the serf ctx will manage it). */ (void) serf_connection_request_create(handler->conn->conn, Modified: subversion/branches/ev2-export/subversion/libsvn_wc/adm_ops.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/adm_ops.c?rev=1335238&r1=1335237&r2=1335238&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/libsvn_wc/adm_ops.c (original) +++ subversion/branches/ev2-export/subversion/libsvn_wc/adm_ops.c Mon May 7 20:24:50 2012 @@ -2253,13 +2253,13 @@ svn_wc_get_pristine_contents2(svn_stream svn_error_t * svn_wc__get_pristine_contents_by_checksum(svn_stream_t **contents, svn_wc_context_t *wc_ctx, - const char *wcroot_abspath, + const char *wri_abspath, const svn_checksum_t *sha1_checksum, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { return svn_error_trace(svn_wc__db_pristine_read(contents, NULL, wc_ctx->db, - wcroot_abspath, sha1_checksum, + wri_abspath, sha1_checksum, result_pool, scratch_pool)); }