Index: configure.in =================================================================== --- configure.in (revision 16889) +++ configure.in (working copy) @@ -456,19 +456,11 @@ AC_HELP_STRING([--with-editor=PATH], ]) -AC_ARG_WITH(zlib, -AC_HELP_STRING([--with-zlib], [enable zlib support]), -[ - - if test "$withval" = "yes" ; then AC_CHECK_HEADER(zlib.h, [ AC_CHECK_LIB(z, inflate, [ AC_DEFINE([SVN_HAVE_ZLIB], [1], [Is zlib support enabled?]) LIBS="$LIBS -lz" - ]) - ]) - fi - + ], [AC_MSG_ERROR([subversion requires zlib])]) ]) MOD_ACTIVATION="-a" Index: notes/svndiff =================================================================== --- notes/svndiff (revision 16889) +++ notes/svndiff (working copy) @@ -1,7 +1,7 @@ -This file describes the svndiff format used by the Subversion code. -Its design borrows many ideas from the vdelta and vcdiff encoding -formats from AT&T Research Labs, but it is much simpler and thus a -little less compact. +This file describes the svndiff version 0 and 1 format used by the +Subversion code. Its design borrows many ideas from the vdelta and +vcdiff encoding formats from AT&T Research Labs, but it is much +simpler and thus a little less compact. From the point of view of svndiff, a delta is a sequence of windows, each containing a list of instructions for reconstructing a contiguous @@ -28,13 +28,21 @@ A window is the concatenation of the fol The target view length The length of the instructions in bytes The length of the new data in bytes - The window's instructions - The window's new data (as raw data) + The window's instructions section + The window's new data (as raw data) section -Integers (including the first five items listed above) are encoded -using a variable-length format. The high bit of each byte is used as -a continuation bit; 1 indicates that there is more data and 0 -indicates the final byte. The other seven bits of each byte are data. +In svndiff version 1, the instructions, and new data +sections may be compressed by zlib. In order to determine the +original size, an integer is appended to the beginning of each of the +sections. If the original size matches the encoded size (minus the +length of the original size integer)from the header, the data is not +compressed. If the original size is different than the encoded size +from the header, the remaining data in the section. + +Integers (including the integers described bove) are encoded using a +variable-length format. The high bit of each byte is used as a +continuation bit; 1 indicates that there is more data and 0 indicates +the final byte. The other seven bits of each byte are data. Higher-order bits are encoded before lower-order bits. As an example, 130 would be encoded as two bytes, 10000001 followed by 00000010. Index: subversion/libsvn_fs_base/reps-strings.c =================================================================== --- subversion/libsvn_fs_base/reps-strings.c (revision 16889) +++ subversion/libsvn_fs_base/reps-strings.c (working copy) @@ -1426,8 +1426,8 @@ svn_fs_base__rep_deltify (svn_fs_t *fs, /* Setup a stream to convert the textdelta data into svndiff windows. */ svn_txdelta (&txdelta_stream, source_stream, target_stream, pool); - svn_txdelta_to_svndiff (new_target_stream, pool, - &new_target_handler, &new_target_handler_baton); + svn_txdelta_to_svndiff2 (new_target_stream, pool, + &new_target_handler, &new_target_handler_baton, 1); /* subpool for the windows */ wpool = svn_pool_create (pool); Index: subversion/libsvn_fs_base/util/fs_skels.c =================================================================== --- subversion/libsvn_fs_base/util/fs_skels.c (revision 16889) +++ subversion/libsvn_fs_base/util/fs_skels.c (working copy) @@ -144,7 +144,8 @@ is_valid_rep_delta_chunk_skel (skel_t *s diff = window->children; if ((svn_fs_base__list_length (diff) == 3) && (svn_fs_base__matches_atom (diff->children, "svndiff")) - && (svn_fs_base__matches_atom (diff->children->next, "0")) + && ((svn_fs_base__matches_atom (diff->children->next, "0")) + || (svn_fs_base__matches_atom (diff->children->next, "1"))) && (diff->children->next->next->is_atom)) return TRUE; Index: subversion/include/svn_error_codes.h =================================================================== --- subversion/include/svn_error_codes.h (revision 16889) +++ subversion/include/svn_error_codes.h (working copy) @@ -820,6 +820,15 @@ SVN_ERROR_START SVN_ERR_SVNDIFF_CATEGORY_START + 4, "Svndiff data ends unexpectedly") + SVN_ERRDEF (SVN_ERR_SVNDIFF_INVALID_VERSION, + SVN_ERR_SVNDIFF_CATEGORY_START + 5, + "Svndiff version greater than known max") + + SVN_ERRDEF (SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA, + SVN_ERR_SVNDIFF_CATEGORY_START + 6, + "Svndiff compressed data is invalid") + + /* mod_dav_svn errors */ SVN_ERRDEF (SVN_ERR_APMOD_MISSING_PATH_TO_FS, Index: subversion/include/svn_ra_svn.h =================================================================== --- subversion/include/svn_ra_svn.h (revision 16889) +++ subversion/include/svn_ra_svn.h (working copy) @@ -41,6 +41,7 @@ extern "C" { /** Currently-defined capabilities. */ #define SVN_RA_SVN_CAP_EDIT_PIPELINE "edit-pipeline" +#define SVN_RA_SVN_CAP_SVNDIFF1 "svndiff1" /** A value used to indicate an optional number element in a tuple that was * not received. Index: subversion/include/svn_delta.h =================================================================== --- subversion/include/svn_delta.h (revision 16889) +++ subversion/include/svn_delta.h (working copy) @@ -324,6 +324,19 @@ void svn_txdelta_apply (svn_stream_t *so * @a output is a writable generic stream to write the svndiff data to. * Allocation takes place in a sub-pool of @a pool. On return, @a *handler * is set to a window handler function and @a *handler_baton is set to + * the value to pass as the @a baton argument to @a *handler. The svndiff + * version is @a version. + */ + +void svn_txdelta_to_svndiff2 (svn_stream_t *output, + apr_pool_t *pool, + svn_txdelta_window_handler_t *handler, + void **handler_baton, unsigned int version); + +/** Prepare to produce an svndiff-format diff from text delta windows. + * @a output is a writable generic stream to write the svndiff data to. + * Allocation takes place in a sub-pool of @a pool. On return, @a *handler + * is set to a window handler function and @a *handler_baton is set to * the value to pass as the @a baton argument to @a *handler. */ void svn_txdelta_to_svndiff (svn_stream_t *output, Index: subversion/tests/libsvn_delta/svndiff-test.c =================================================================== --- subversion/tests/libsvn_delta/svndiff-test.c (revision 16889) +++ subversion/tests/libsvn_delta/svndiff-test.c (working copy) @@ -39,10 +39,11 @@ main (int argc, char **argv) svn_stream_t *encoder; void *svndiff_baton; apr_pool_t *pool; + int version = 0; if (argc < 3) { - printf ("usage: %s source target\n", argv[0]); + printf ("usage: %s source target [version]\n", argv[0]); exit (0); } @@ -63,6 +64,8 @@ main (int argc, char **argv) fprintf (stderr, "unable to open \"%s\" for reading\n", argv[2]); exit (1); } + if (argc == 4) + version = atoi (argv[3]); svn_txdelta (&txdelta_stream, svn_stream_from_aprfile (source_file, pool), @@ -78,7 +81,8 @@ main (int argc, char **argv) #else encoder = svn_base64_encode (stdout_stream, pool); #endif - svn_txdelta_to_svndiff (encoder, pool, &svndiff_handler, &svndiff_baton); + svn_txdelta_to_svndiff2 (encoder, pool, &svndiff_handler, &svndiff_baton, + version); err = svn_txdelta_send_txstream (txdelta_stream, svndiff_handler, svndiff_baton, Index: subversion/tests/libsvn_delta/random-test.c =================================================================== --- subversion/tests/libsvn_delta/random-test.c (revision 16889) +++ subversion/tests/libsvn_delta/random-test.c (working copy) @@ -337,7 +337,7 @@ random_test (const char **msg, delta_pool); /* Make stage 2: encode the text delta in svndiff format. */ - svn_txdelta_to_svndiff (stream, delta_pool, &handler, &handler_baton); + svn_txdelta_to_svndiff2 (stream, delta_pool, &handler, &handler_baton, 1); /* Make stage 1: create the text delta. */ svn_txdelta (&txdelta_stream, @@ -429,7 +429,7 @@ do_random_combine_test (const char **msg delta_pool); /* Make stage 2: encode the text delta in svndiff format. */ - svn_txdelta_to_svndiff (stream, delta_pool, &handler, &handler_baton); + svn_txdelta_to_svndiff2 (stream, delta_pool, &handler, &handler_baton, 1); /* Make stage 1: create the text deltas. */ Index: subversion/libsvn_repos/dump.c =================================================================== --- subversion/libsvn_repos/dump.c (revision 16889) +++ subversion/libsvn_repos/dump.c (working copy) @@ -148,7 +148,7 @@ store_delta (apr_file_t **tempfile, svn_ /* Compute the delta and send it to the temporary file. */ SVN_ERR (svn_fs_get_file_delta_stream (&delta_stream, oldroot, oldpath, newroot, newpath, pool)); - svn_txdelta_to_svndiff (temp_stream, pool, &wh, &whb); + svn_txdelta_to_svndiff2 (temp_stream, pool, &wh, &whb, 1); SVN_ERR (svn_txdelta_send_txstream (delta_stream, wh, whb, pool)); /* Get the length of the temporary file and rewind it. */ Index: subversion/libsvn_ra_svn/client.c =================================================================== --- subversion/libsvn_ra_svn/client.c (revision 16889) +++ subversion/libsvn_ra_svn/client.c (working copy) @@ -273,9 +273,9 @@ static svn_error_t *auth_response(svn_ra svn_boolean_t compat) { if (compat) - return svn_ra_svn_write_tuple(conn, pool, "nw(?c)(w)", (apr_uint64_t) 1, + return svn_ra_svn_write_tuple(conn, pool, "nw(?c)(ww)", (apr_uint64_t) 1, mech, mech_arg, - SVN_RA_SVN_CAP_EDIT_PIPELINE); + SVN_RA_SVN_CAP_EDIT_PIPELINE, SVN_RA_SVN_CAP_SVNDIFF1); else return svn_ra_svn_write_tuple(conn, pool, "w(?c)", mech, mech_arg); } @@ -672,8 +672,8 @@ static svn_error_t *open_session(ra_svn_ } else { - SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "n(w)c", (apr_uint64_t) 2, - SVN_RA_SVN_CAP_EDIT_PIPELINE, url)); + SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "n(ww)c", (apr_uint64_t) 2, + SVN_RA_SVN_CAP_EDIT_PIPELINE, SVN_RA_SVN_CAP_SVNDIFF1, url)); SVN_ERR(handle_auth_request(sess, pool)); } Index: subversion/libsvn_ra_svn/protocol =================================================================== --- subversion/libsvn_ra_svn/protocol (revision 16889) +++ subversion/libsvn_ra_svn/protocol (working copy) @@ -164,6 +164,9 @@ The following capabilities are currently edit-pipeline If both the client and server present this capability, edit operations will use pipelining. See section 3.1.2. + svndiff1 If both the client and server support svndiff version + 1, this will be used as the on-the-wire format for svndiff + instead of svndiff version 0. 3. Commands ----------- Index: subversion/libsvn_ra_svn/editor.c =================================================================== --- subversion/libsvn_ra_svn/editor.c (revision 16889) +++ subversion/libsvn_ra_svn/editor.c (working copy) @@ -255,7 +255,10 @@ static svn_error_t *ra_svn_apply_textdel diff_stream = svn_stream_create(b, pool); svn_stream_set_write(diff_stream, ra_svn_svndiff_handler); svn_stream_set_close(diff_stream, ra_svn_svndiff_close_handler); - svn_txdelta_to_svndiff(diff_stream, pool, wh, wh_baton); + if (svn_ra_svn_has_capability(b->conn, SVN_RA_SVN_CAP_SVNDIFF1)) + svn_txdelta_to_svndiff2(diff_stream, pool, wh, wh_baton, 1); + else + svn_txdelta_to_svndiff2(diff_stream, pool, wh, wh_baton, 0); return SVN_NO_ERROR; } Index: subversion/libsvn_ra_svn/editorp.c =================================================================== --- subversion/libsvn_ra_svn/editorp.c (revision 16889) +++ subversion/libsvn_ra_svn/editorp.c (working copy) @@ -294,7 +294,10 @@ static svn_error_t *ra_svn_apply_textdel diff_stream = svn_stream_create(b, pool); svn_stream_set_write(diff_stream, ra_svn_svndiff_handler); svn_stream_set_close(diff_stream, ra_svn_svndiff_close_handler); - svn_txdelta_to_svndiff(diff_stream, pool, wh, wh_baton); + if (svn_ra_svn_has_capability(b->conn, SVN_RA_SVN_CAP_SVNDIFF1)) + svn_txdelta_to_svndiff2(diff_stream, pool, wh, wh_baton, 1); + else + svn_txdelta_to_svndiff2(diff_stream, pool, wh, wh_baton, 0); return SVN_NO_ERROR; } Index: subversion/libsvn_delta/svndiff.c =================================================================== --- subversion/libsvn_delta/svndiff.c (revision 16889) +++ subversion/libsvn_delta/svndiff.c (working copy) @@ -24,7 +24,11 @@ #include "delta.h" #include "svn_pools.h" #include "svn_private_config.h" +#include +/* For svndiff1, address/instruction/new data under this size will not + be compressed using zlib as a secondary compressor. */ +#define MIN_COMPRESS_SIZE 1024 #define NORMAL_BITS 7 #define LENGTH_BITS 5 @@ -37,10 +41,10 @@ struct encoder_baton { svn_stream_t *output; svn_boolean_t header_done; + unsigned int version; apr_pool_t *pool; }; - /* Encode VAL into the buffer P using the variable-length svndiff integer format. Return the incremented value of P after the encoded bytes have been written. @@ -99,6 +103,35 @@ append_encoded_int (svn_stringbuf_t *hea svn_stringbuf_appendbytes (header, buf, p - buf); } +static svn_error_t * +zlib_encode (svn_stringbuf_t *in, svn_stringbuf_t *out) +{ + unsigned long endlen; + unsigned int intlen; + + append_encoded_int (out, in->len, NULL); + intlen = out->len; + + if (in->len < MIN_COMPRESS_SIZE) + { + svn_stringbuf_appendstr (out, in); + } + else + { + svn_stringbuf_ensure (out, compressBound (in->len) + intlen); + endlen = out->blocksize; + + if (compress2 ((unsigned char *)out->data + intlen, &endlen, + (const unsigned char *)in->data, in->len, 5) != Z_OK) + + return svn_error_create (SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA, + NULL, + _("compression of svndiff data failed")); + + out->len = endlen + intlen; + } + return SVN_NO_ERROR; +} static svn_error_t * window_handler (svn_txdelta_window_t *window, void *baton) @@ -106,17 +139,24 @@ window_handler (svn_txdelta_window_t *wi struct encoder_baton *eb = baton; apr_pool_t *pool = svn_pool_create (eb->pool); svn_stringbuf_t *instructions = svn_stringbuf_create ("", pool); + svn_stringbuf_t *i1 = svn_stringbuf_create ("", pool); svn_stringbuf_t *header = svn_stringbuf_create ("", pool); + svn_stringbuf_t *newdata = svn_stringbuf_create ("", pool); char ibuf[128], *ip; + char abuf[128], *ap; const svn_txdelta_op_t *op; - svn_error_t *err; + svn_error_t *err = SVN_NO_ERROR; apr_size_t len; + apr_size_t lastoffset = 0; + apr_size_t bits = 0; /* Make sure we write the header. */ if (eb->header_done == FALSE) { + char svnver[4] = "SVN\0"; len = 4; - SVN_ERR (svn_stream_write (eb->output, "SVN\0", &len)); + svnver[3] = eb->version; + SVN_ERR (svn_stream_write (eb->output, svnver, &len)); eb->header_done = TRUE; } @@ -146,6 +186,7 @@ window_handler (svn_txdelta_window_t *wi { /* Encode the action code and length. */ ip = ibuf; + ap = abuf; switch (op->action_code) { case svn_txdelta_source: *ip = (char)0; break; @@ -156,8 +197,11 @@ window_handler (svn_txdelta_window_t *wi *ip++ |= op->length; else ip = encode_int (ip + 1, op->length); + if (op->action_code != svn_txdelta_new) + { ip = encode_int (ip, op->offset); + } svn_stringbuf_appendbytes (instructions, ibuf, ip - ibuf); } @@ -165,7 +209,20 @@ window_handler (svn_txdelta_window_t *wi append_encoded_int (header, window->sview_offset, pool); append_encoded_int (header, window->sview_len, pool); append_encoded_int (header, window->tview_len, pool); + if (err == SVN_NO_ERROR && eb->version == 1) + { + err = zlib_encode (instructions, i1); + instructions = i1; + } append_encoded_int (header, instructions->len, pool); + if (err == SVN_NO_ERROR && eb->version == 1) + { + svn_stringbuf_t *temp; + temp = svn_stringbuf_create_from_string (window->new_data, pool); + err = zlib_encode (temp, newdata); + window->new_data = svn_string_create_from_buf (newdata, pool); + } + append_encoded_int (header, window->new_data->len, pool); /* Write out the window. */ @@ -187,6 +244,26 @@ window_handler (svn_txdelta_window_t *wi } void +svn_txdelta_to_svndiff2 (svn_stream_t *output, + apr_pool_t *pool, + svn_txdelta_window_handler_t *handler, + void **handler_baton, + unsigned int version) +{ + apr_pool_t *subpool = svn_pool_create (pool); + struct encoder_baton *eb; + + eb = apr_palloc (subpool, sizeof (*eb)); + eb->output = output; + eb->header_done = FALSE; + eb->pool = subpool; + eb->version = version; + + *handler = window_handler; + *handler_baton = eb; +} + +void svn_txdelta_to_svndiff (svn_stream_t *output, apr_pool_t *pool, svn_txdelta_window_handler_t *handler, @@ -199,6 +276,7 @@ svn_txdelta_to_svndiff (svn_stream_t *ou eb->output = output; eb->header_done = FALSE; eb->pool = subpool; + eb->version = 0; *handler = window_handler; *handler_baton = eb; @@ -240,6 +318,10 @@ struct decode_baton not transmit the whole svndiff data stream, you will want this to be FALSE. */ svn_boolean_t error_on_early_close; + + /* svndiff version in use by delta. */ + unsigned char version; + }; @@ -283,6 +365,45 @@ decode_size (apr_size_t *val, return NULL; } +static svn_error_t * +zlib_decode (svn_stringbuf_t *in, svn_stringbuf_t *out) +{ + apr_size_t len; + unsigned long zliblen; + unsigned long origlen; + + assert (sizeof (zliblen) >= sizeof (len)); + /* First thing in the string is the original length. */ + in->data = (char *)decode_size (&len, (unsigned char *)in->data, + (unsigned char *)in->data+in->len); + in->len = len; + if (len < MIN_COMPRESS_SIZE) + { + svn_stringbuf_appendstr (out, in); + return SVN_NO_ERROR; + } + else + { + svn_stringbuf_ensure (out, len); + + origlen = len; + zliblen = len; + if (uncompress ((unsigned char *)out->data, &zliblen, + (const unsigned char *)in->data, in->len) != Z_OK) + return svn_error_create (SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA, + NULL, + _("decompression of svndiff data failed")); + + /* Zlib should not produce something that has a different size than the + original length we stored. */ + assert (zliblen == origlen); + out->len = zliblen; + } + return SVN_NO_ERROR; +} + + + /* Decode an instruction into OP, returning a pointer to the text after the instruction. Note that if the action code is @@ -405,30 +526,55 @@ count_and_verify_instructions (int *nins static svn_error_t * decode_window (svn_txdelta_window_t *window, svn_filesize_t sview_offset, apr_size_t sview_len, apr_size_t tview_len, apr_size_t inslen, - apr_size_t newlen, const unsigned char *data, apr_pool_t *pool) + apr_size_t newlen, const unsigned char *data, apr_pool_t *pool, + unsigned int version) { - const unsigned char *end; + const unsigned char *insend; int ninst; + apr_size_t saved_inslen, saved_newlen; apr_size_t npos; svn_txdelta_op_t *ops, *op; svn_string_t *new_data; + svn_stringbuf_t *instin, *instout; + svn_stringbuf_t *ndin, *ndout; window->sview_offset = sview_offset; window->sview_len = sview_len; window->tview_len = tview_len; + saved_inslen = inslen; + saved_newlen = newlen; + + insend = data + inslen; + + if (version == 1) + { + instin = svn_stringbuf_ncreate ((const char *)data, insend - data, pool); + instout = svn_stringbuf_create ("", pool); + zlib_decode (instin, instout); + + ndin = svn_stringbuf_ncreate ((const char *)insend, newlen, pool); + ndout = svn_stringbuf_create ("", pool); + zlib_decode (ndin, ndout); + + newlen = ndout->len; + data = (unsigned char *)instout->data; + insend = (unsigned char *)instout->data + instout->len; + } /* Count the instructions and make sure they are all valid. */ - end = data + inslen; - SVN_ERR (count_and_verify_instructions (&ninst, data, end, sview_len, - tview_len, newlen)); + + SVN_ERR (count_and_verify_instructions (&ninst, data, insend, + sview_len, tview_len, newlen)); + /* Allocate a buffer for the instructions and decode them. */ ops = apr_palloc (pool, ninst * sizeof (*ops)); npos = 0; + window->src_ops = 0; for (op = ops; op < ops + ninst; op++) { - data = decode_instruction (op, data, end); + data = decode_instruction (op, data, insend); if (op->action_code == svn_txdelta_source) ++window->src_ops; else if (op->action_code == svn_txdelta_new) @@ -442,7 +588,12 @@ decode_window (svn_txdelta_window_t *win window->num_ops = ninst; new_data = apr_palloc (pool, sizeof (*new_data)); + + if (version == 1) + new_data->data = (const char *)ndout->data; + else new_data->data = (const char *) data; + new_data->len = newlen; window->new_data = new_data; @@ -466,7 +617,8 @@ write_handler (void *baton, apr_size_t nheader = 4 - db->header_bytes; if (nheader > buflen) nheader = buflen; - if (memcmp (buffer, "SVN\0" + db->header_bytes, nheader) != 0) + db->version = buffer[3]; + if (memcmp (buffer, "SVN" + db->header_bytes, nheader - 1) != 0) return svn_error_create (SVN_ERR_SVNDIFF_INVALID_HEADER, NULL, _("Svndiff has invalid header")); buflen -= nheader; @@ -541,7 +693,8 @@ write_handler (void *baton, /* Decode the window and send it off. */ SVN_ERR (decode_window (&window, sview_offset, sview_len, tview_len, - inslen, newlen, p, db->subpool)); + inslen, newlen, p, db->subpool, + db->version)); SVN_ERR (db->consumer_func (&window, db->consumer_baton)); /* Make a new subpool and buffer, saving aside the remaining @@ -651,7 +804,8 @@ read_one_size (apr_size_t *size, svn_str /* Read a window header from STREAM and check it for integer overflow. */ static svn_error_t * -read_window_header (svn_stream_t *stream, svn_filesize_t *sview_offset, +read_window_header (svn_stream_t *stream, unsigned int version, + svn_filesize_t *sview_offset, apr_size_t *sview_len, apr_size_t *tview_len, apr_size_t *inslen, apr_size_t *newlen) { @@ -693,7 +847,8 @@ svn_txdelta_read_svndiff_window (svn_txd apr_size_t sview_len, tview_len, inslen, newlen, len; unsigned char *buf; - SVN_ERR (read_window_header (stream, &sview_offset, &sview_len, &tview_len, + SVN_ERR (read_window_header (stream, svndiff_version, + &sview_offset, &sview_len, &tview_len, &inslen, &newlen)); len = inslen + newlen; buf = apr_palloc(pool, len); @@ -702,8 +857,9 @@ svn_txdelta_read_svndiff_window (svn_txd return svn_error_create (SVN_ERR_SVNDIFF_UNEXPECTED_END, NULL, _("Unexpected end of svndiff input")); *window = apr_palloc (pool, sizeof(**window)); + SVN_ERR (decode_window (*window, sview_offset, sview_len, tview_len, inslen, - newlen, buf, pool)); + newlen, buf, pool, svndiff_version)); return SVN_NO_ERROR; } @@ -718,7 +874,8 @@ svn_txdelta_skip_svndiff_window (apr_fil apr_size_t sview_len, tview_len, inslen, newlen; apr_off_t offset; - SVN_ERR (read_window_header (stream, &sview_offset, &sview_len, &tview_len, + SVN_ERR (read_window_header (stream, svndiff_version, + &sview_offset, &sview_len, &tview_len, &inslen, &newlen)); offset = inslen + newlen; Index: subversion/svnserve/serve.c =================================================================== --- subversion/svnserve/serve.c (revision 16889) +++ subversion/svnserve/serve.c (working copy) @@ -2104,8 +2104,8 @@ svn_error_t *serve(svn_ra_svn_conn_t *co SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w(nn(!", "success", (apr_uint64_t) 1, (apr_uint64_t) 2)); SVN_ERR(send_mechs(conn, pool, &b, READ_ACCESS, FALSE)); - SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!)(w))", - SVN_RA_SVN_CAP_EDIT_PIPELINE)); + SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!)(ww))", + SVN_RA_SVN_CAP_EDIT_PIPELINE, SVN_RA_SVN_CAP_SVNDIFF1)); /* Read client response. Because the client response form changed * between version 1 and version 2, we have to do some of this by Index: subversion/libsvn_fs_fs/fs_fs.c =================================================================== --- subversion/libsvn_fs_fs/fs_fs.c (revision 16889) +++ subversion/libsvn_fs_fs/fs_fs.c (working copy) @@ -3119,7 +3119,7 @@ rep_write_get_baton (struct rep_write_ba SVN_ERR (get_file_offset (&b->delta_start, file, b->pool)); /* Prepare to write the svndiff data. */ - svn_txdelta_to_svndiff (b->rep_stream, pool, &wh, &whb); + svn_txdelta_to_svndiff2 (b->rep_stream, pool, &wh, &whb, 1); b->delta_stream = svn_txdelta_target_push (wh, whb, source, b->pool); *wb_p = b;