diff options
Diffstat (limited to 'subversion/libsvn_wc/adm_crawler.c')
-rw-r--r-- | subversion/libsvn_wc/adm_crawler.c | 114 |
1 files changed, 78 insertions, 36 deletions
diff --git a/subversion/libsvn_wc/adm_crawler.c b/subversion/libsvn_wc/adm_crawler.c index ebdc75e105f41..864535f6a70bc 100644 --- a/subversion/libsvn_wc/adm_crawler.c +++ b/subversion/libsvn_wc/adm_crawler.c @@ -906,6 +906,27 @@ close_handler_copy(void *baton) return svn_stream_close(btn->source); } +/* Implements svn_stream_seek_fn_t */ +static svn_error_t * +seek_handler_copy(void *baton, const svn_stream_mark_t *mark) +{ + struct copying_stream_baton *btn = baton; + + /* Only reset support. */ + if (mark) + { + return svn_error_create(SVN_ERR_STREAM_SEEK_NOT_SUPPORTED, + NULL, NULL); + } + else + { + SVN_ERR(svn_stream_reset(btn->source)); + SVN_ERR(svn_stream_reset(btn->target)); + } + + return SVN_NO_ERROR; +} + /* Return a stream - allocated in POOL - which reads its input * from SOURCE and, while returning that to the caller, at the @@ -928,6 +949,11 @@ copying_stream(svn_stream_t *source, read_handler_copy); svn_stream_set_close(stream, close_handler_copy); + if (svn_stream_supports_reset(source) && svn_stream_supports_reset(target)) + { + svn_stream_set_seek(stream, seek_handler_copy); + } + return stream; } @@ -995,9 +1021,38 @@ read_and_checksum_pristine_text(svn_stream_t **stream, return SVN_NO_ERROR; } +typedef struct open_txdelta_stream_baton_t +{ + svn_boolean_t need_reset; + svn_stream_t *base_stream; + svn_stream_t *local_stream; +} open_txdelta_stream_baton_t; + +/* Implements svn_txdelta_stream_open_func_t */ +static svn_error_t * +open_txdelta_stream(svn_txdelta_stream_t **txdelta_stream_p, + void *baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + open_txdelta_stream_baton_t *b = baton; + + if (b->need_reset) + { + /* Under rare circumstances, we can be restarted and would need to + * supply the delta stream again. In this case, reset both streams. */ + SVN_ERR(svn_stream_reset(b->base_stream)); + SVN_ERR(svn_stream_reset(b->local_stream)); + } + + svn_txdelta2(txdelta_stream_p, b->base_stream, b->local_stream, + FALSE, result_pool); + b->need_reset = TRUE; + return SVN_NO_ERROR; +} svn_error_t * -svn_wc__internal_transmit_text_deltas(const char **tempfile, +svn_wc__internal_transmit_text_deltas(svn_stream_t *tempstream, const svn_checksum_t **new_text_base_md5_checksum, const svn_checksum_t **new_text_base_sha1_checksum, svn_wc__db_t *db, @@ -1008,8 +1063,6 @@ svn_wc__internal_transmit_text_deltas(const char **tempfile, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - svn_txdelta_window_handler_t handler; - void *wh_baton; const svn_checksum_t *expected_md5_checksum; /* recorded MD5 of BASE_S. */ svn_checksum_t *verify_checksum; /* calc'd MD5 of BASE_STREAM */ svn_checksum_t *local_md5_checksum; /* calc'd MD5 of LOCAL_STREAM */ @@ -1027,22 +1080,13 @@ svn_wc__internal_transmit_text_deltas(const char **tempfile, scratch_pool, scratch_pool)); /* If the caller wants a copy of the working file translated to - * repository-normal form, make the copy by tee-ing the stream and set - * *TEMPFILE to the path to it. This is only needed for the 1.6 API, - * 1.7 doesn't set TEMPFILE. Even when using the 1.6 API this file - * is not used by the functions that would have used it when using - * the 1.6 code. It's possible that 3rd party users (if there are any) - * might expect this file to be a text-base. */ - if (tempfile) + * repository-normal form, make the copy by tee-ing the TEMPSTREAM. + * This is only needed for the 1.6 API. Even when using the 1.6 API + * this temporary file is not used by the functions that would have used + * it when using the 1.6 code. It's possible that 3rd party users (if + * there are any) might expect this file to be a text-base. */ + if (tempstream) { - svn_stream_t *tempstream; - - /* It can't be the same location as in 1.6 because the admin directory - no longer exists. */ - SVN_ERR(svn_stream_open_unique(&tempstream, tempfile, - NULL, svn_io_file_del_none, - result_pool, scratch_pool)); - /* Wrap the translated stream with a new stream that writes the translated contents into the new text base file as we read from it. Note that the new text base file will be closed when the new stream @@ -1088,30 +1132,33 @@ svn_wc__internal_transmit_text_deltas(const char **tempfile, verify_checksum = NULL; } - /* Tell the editor that we're about to apply a textdelta to the - file baton; the editor returns to us a window consumer and baton. */ + /* Arrange the stream to calculate the resulting MD5. */ + local_stream = svn_stream_checksummed2(local_stream, &local_md5_checksum, + NULL, svn_checksum_md5, TRUE, + scratch_pool); + + /* Tell the editor to apply a textdelta stream to the file baton. */ { - /* apply_textdelta() is working against a base with this checksum */ + open_txdelta_stream_baton_t baton = { 0 }; + + /* apply_textdelta_stream() is working against a base with this checksum */ const char *base_digest_hex = NULL; if (expected_md5_checksum) /* ### Why '..._display()'? expected_md5_checksum should never be all- * zero, but if it is, we would want to pass NULL not an all-zero - * digest to apply_textdelta(), wouldn't we? */ + * digest to apply_textdelta_stream(), wouldn't we? */ base_digest_hex = svn_checksum_to_cstring_display(expected_md5_checksum, scratch_pool); - SVN_ERR(editor->apply_textdelta(file_baton, base_digest_hex, scratch_pool, - &handler, &wh_baton)); + baton.need_reset = FALSE; + baton.base_stream = svn_stream_disown(base_stream, scratch_pool); + baton.local_stream = svn_stream_disown(local_stream, scratch_pool); + err = editor->apply_textdelta_stream(editor, file_baton, base_digest_hex, + open_txdelta_stream, &baton, + scratch_pool); } - /* Run diff processing, throwing windows at the handler. */ - err = svn_txdelta_run(base_stream, local_stream, - handler, wh_baton, - svn_checksum_md5, &local_md5_checksum, - NULL, NULL, - scratch_pool, scratch_pool); - /* Close the two streams to force writing the digest */ err2 = svn_stream_close(base_stream); if (err2) @@ -1141,11 +1188,6 @@ svn_wc__internal_transmit_text_deltas(const char **tempfile, investigate. Other commands could be affected, too, such as `svn diff'. */ - if (tempfile) - err = svn_error_compose_create( - err, - svn_io_remove_file2(*tempfile, TRUE, scratch_pool)); - err = svn_error_compose_create( svn_checksum_mismatch_err(expected_md5_checksum, verify_checksum, scratch_pool, |