00001 /** 00002 * @copyright 00003 * ==================================================================== 00004 * Licensed to the Apache Software Foundation (ASF) under one 00005 * or more contributor license agreements. See the NOTICE file 00006 * distributed with this work for additional information 00007 * regarding copyright ownership. The ASF licenses this file 00008 * to you under the Apache License, Version 2.0 (the 00009 * "License"); you may not use this file except in compliance 00010 * with the License. You may obtain a copy of the License at 00011 * 00012 * http://www.apache.org/licenses/LICENSE-2.0 00013 * 00014 * Unless required by applicable law or agreed to in writing, 00015 * software distributed under the License is distributed on an 00016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 00017 * KIND, either express or implied. See the License for the 00018 * specific language governing permissions and limitations 00019 * under the License. 00020 * ==================================================================== 00021 * @endcopyright 00022 * 00023 * @file svn_delta.h 00024 * @brief Delta-parsing 00025 */ 00026 00027 /* ==================================================================== */ 00028 00029 00030 00031 #ifndef SVN_DELTA_H 00032 #define SVN_DELTA_H 00033 00034 #include <apr.h> 00035 #include <apr_pools.h> 00036 #include <apr_hash.h> 00037 #include <apr_tables.h> 00038 #include <apr_file_io.h> /* for apr_file_t */ 00039 00040 #include "svn_types.h" 00041 #include "svn_string.h" 00042 #include "svn_io.h" 00043 #include "svn_version.h" 00044 #include "svn_checksum.h" 00045 00046 #ifdef __cplusplus 00047 extern "C" { 00048 #endif /* __cplusplus */ 00049 00050 00051 00052 /** 00053 * Get libsvn_delta version information. 00054 * 00055 * @since New in 1.1. 00056 */ 00057 const svn_version_t * 00058 svn_delta_version(void); 00059 00060 /** 00061 * @defgroup delta_support Delta generation and handling 00062 * 00063 * @{ 00064 */ 00065 00066 /** Text deltas. 00067 * 00068 * A text delta represents the difference between two strings of 00069 * bytes, the `source' string and the `target' string. Given a source 00070 * string and a target string, we can compute a text delta; given a 00071 * source string and a delta, we can reconstruct the target string. 00072 * However, note that deltas are not reversible: you cannot always 00073 * reconstruct the source string given the target string and delta. 00074 * 00075 * Since text deltas can be very large, the interface here allows us 00076 * to produce and consume them in pieces. Each piece, represented by 00077 * an #svn_txdelta_window_t structure, describes how to produce the 00078 * next section of the target string. 00079 * 00080 * To compute a new text delta: 00081 * 00082 * - We call svn_txdelta() on the streams we want to compare. That 00083 * returns us an #svn_txdelta_stream_t object. 00084 * 00085 * - We then call svn_txdelta_next_window() on the stream object 00086 * repeatedly. Each call returns a new #svn_txdelta_window_t 00087 * object, which describes the next portion of the target string. 00088 * When svn_txdelta_next_window() returns zero, we are done building 00089 * the target string. 00090 * 00091 * @defgroup svn_delta_txt_delta Text deltas 00092 * @{ 00093 */ 00094 00095 /** Action codes for text delta instructions. */ 00096 enum svn_delta_action { 00097 /** Append the @a length bytes at @a offset in the source view to the 00098 * target. 00099 * 00100 * It must be the case that 0 <= @a offset < @a offset + 00101 * @a length <= size of source view. 00102 */ 00103 svn_txdelta_source, 00104 00105 /** Append the @a length bytes at @a offset in the target view, to the 00106 * target. 00107 * 00108 * It must be the case that 0 <= @a offset < current position in the 00109 * target view. 00110 * 00111 * However! @a offset + @a length may be *beyond* the end of the existing 00112 * target data. "Where the heck does the text come from, then?" 00113 * If you start at @a offset, and append @a length bytes one at a time, 00114 * it'll work out --- you're adding new bytes to the end at the 00115 * same rate you're reading them from the middle. Thus, if your 00116 * current target text is "abcdefgh", and you get an #svn_txdelta_target 00117 * instruction whose @a offset is 6 and whose @a length is 7, 00118 * the resulting string is "abcdefghghghghg". This trick is actually 00119 * useful in encoding long runs of consecutive characters, long runs 00120 * of CR/LF pairs, etc. 00121 */ 00122 svn_txdelta_target, 00123 00124 /** Append the @a length bytes at @a offset in the window's @a new string 00125 * to the target. 00126 * 00127 * It must be the case that 0 <= @a offset < @a offset + 00128 * @a length <= length of @a new. Windows MUST use new data in ascending 00129 * order with no overlap at the moment; svn_txdelta_to_svndiff() 00130 * depends on this. 00131 */ 00132 svn_txdelta_new 00133 }; 00134 00135 /** A single text delta instruction. */ 00136 typedef struct svn_txdelta_op_t 00137 { 00138 /** Action code of delta instruction */ 00139 enum svn_delta_action action_code; 00140 /** Offset of delta, see #svn_delta_action for more details. */ 00141 apr_size_t offset; 00142 /** Number of bytes of delta, see #svn_delta_action for more details. */ 00143 apr_size_t length; 00144 } svn_txdelta_op_t; 00145 00146 00147 /** An #svn_txdelta_window_t object describes how to reconstruct a 00148 * contiguous section of the target string (the "target view") using a 00149 * specified contiguous region of the source string (the "source 00150 * view"). It contains a series of instructions which assemble the 00151 * new target string text by pulling together substrings from: 00152 * 00153 * - the source view, 00154 * 00155 * - the previously constructed portion of the target view, 00156 * 00157 * - a string of new data contained within the window structure 00158 * 00159 * The source view must always slide forward from one window to the 00160 * next; that is, neither the beginning nor the end of the source view 00161 * may move to the left as we read from a window stream. This 00162 * property allows us to apply deltas to non-seekable source streams 00163 * without making a full copy of the source stream. 00164 */ 00165 typedef struct svn_txdelta_window_t 00166 { 00167 00168 /** The offset of the source view for this window. */ 00169 svn_filesize_t sview_offset; 00170 00171 /** The length of the source view for this window. */ 00172 apr_size_t sview_len; 00173 00174 /** The length of the target view for this window, i.e. the number of 00175 * bytes which will be reconstructed by the instruction stream. */ 00176 apr_size_t tview_len; 00177 00178 /** The number of instructions in this window. */ 00179 int num_ops; 00180 00181 /** The number of svn_txdelta_source instructions in this window. If 00182 * this number is 0, we don't need to read the source in order to 00183 * reconstruct the target view. 00184 */ 00185 int src_ops; 00186 00187 /** The instructions for this window. */ 00188 const svn_txdelta_op_t *ops; 00189 00190 /** New data, for use by any `svn_txdelta_new' instructions. */ 00191 const svn_string_t *new_data; 00192 00193 } svn_txdelta_window_t; 00194 00195 /** 00196 * Return a deep copy of @a window, allocated in @a pool. 00197 * 00198 * @since New in 1.3. 00199 */ 00200 svn_txdelta_window_t * 00201 svn_txdelta_window_dup(const svn_txdelta_window_t *window, 00202 apr_pool_t *pool); 00203 00204 /** 00205 * Compose two delta windows, yielding a third, allocated in @a pool. 00206 * 00207 * @since New in 1.4 00208 * 00209 */ 00210 svn_txdelta_window_t * 00211 svn_txdelta_compose_windows(const svn_txdelta_window_t *window_A, 00212 const svn_txdelta_window_t *window_B, 00213 apr_pool_t *pool); 00214 00215 /** 00216 * Apply the instructions from @a window to a source view @a sbuf to 00217 * produce a target view @a tbuf. 00218 * 00219 * @a sbuf is assumed to have @a window->sview_len bytes of data and 00220 * @a tbuf is assumed to have room for @a tlen bytes of output. @a 00221 * tlen may be more than @a window->tview_len, so return the actual 00222 * number of bytes written. @a sbuf is not touched and may be NULL if 00223 * @a window contains no source-copy operations. This is purely a 00224 * memory operation; nothing can go wrong as long as we have a valid 00225 * window. 00226 * 00227 * @since New in 1.4 00228 * 00229 */ 00230 void 00231 svn_txdelta_apply_instructions(svn_txdelta_window_t *window, 00232 const char *sbuf, char *tbuf, 00233 apr_size_t *tlen); 00234 00235 /** A typedef for functions that consume a series of delta windows, for 00236 * use in caller-pushes interfaces. Such functions will typically 00237 * apply the delta windows to produce some file, or save the windows 00238 * somewhere. At the end of the delta window stream, you must call 00239 * this function passing zero for the @a window argument. 00240 */ 00241 typedef svn_error_t *(*svn_txdelta_window_handler_t)( 00242 svn_txdelta_window_t *window, void *baton); 00243 00244 00245 /** This function will generate delta windows that turn @a source into 00246 * @a target, and pushing these windows into the @a handler window handler 00247 * callback (passing @a handler_baton to each invocation). 00248 * 00249 * If @a checksum is not NULL, then a checksum (of kind @a checksum_kind) 00250 * will be computed for the target stream, and placed into *checksum. 00251 * 00252 * If @a cancel_func is not NULL, then it should refer to a cancellation 00253 * function (along with @a cancel_baton). 00254 * 00255 * Results (the checksum) will be allocated from @a result_pool, and all 00256 * temporary allocations will be performed in @a scratch_pool. 00257 * 00258 * Note: this function replaces the combination of svn_txdelta() and 00259 * svn_txdelta_send_txstream(). 00260 * 00261 * @since New in 1.6. 00262 */ 00263 svn_error_t * 00264 svn_txdelta_run(svn_stream_t *source, 00265 svn_stream_t *target, 00266 svn_txdelta_window_handler_t handler, 00267 void *handler_baton, 00268 svn_checksum_kind_t checksum_kind, 00269 svn_checksum_t **checksum, 00270 svn_cancel_func_t cancel_func, 00271 void *cancel_baton, 00272 apr_pool_t *result_pool, 00273 apr_pool_t *scratch_pool); 00274 00275 00276 /** A delta stream --- this is the hat from which we pull a series of 00277 * svn_txdelta_window_t objects, which, taken in order, describe the 00278 * entire target string. This type is defined within libsvn_delta, and 00279 * opaque outside that library. 00280 */ 00281 typedef struct svn_txdelta_stream_t svn_txdelta_stream_t; 00282 00283 00284 /** A typedef for a function that will set @a *window to the next 00285 * window from a #svn_txdelta_stream_t object. If there are no more 00286 * delta windows, NULL will be used. The returned window, if any, 00287 * will be allocated in @a pool. @a baton is the baton specified 00288 * when the stream was created. 00289 * 00290 * @since New in 1.4. 00291 */ 00292 typedef svn_error_t * 00293 (*svn_txdelta_next_window_fn_t)(svn_txdelta_window_t **window, 00294 void *baton, 00295 apr_pool_t *pool); 00296 00297 /** A typedef for a function that will return the md5 checksum of the 00298 * fulltext deltified by a #svn_txdelta_stream_t object. Will 00299 * return NULL if the final null window hasn't yet been returned by 00300 * the stream. The returned value will be allocated in the same pool 00301 * as the stream. @a baton is the baton specified when the stream was 00302 * created. 00303 * 00304 * @since New in 1.4. 00305 */ 00306 typedef const unsigned char * 00307 (*svn_txdelta_md5_digest_fn_t)(void *baton); 00308 00309 /** Create and return a generic text delta stream with @a baton, @a 00310 * next_window and @a md5_digest. Allocate the new stream in @a 00311 * pool. 00312 * 00313 * @since New in 1.4. 00314 */ 00315 svn_txdelta_stream_t * 00316 svn_txdelta_stream_create(void *baton, 00317 svn_txdelta_next_window_fn_t next_window, 00318 svn_txdelta_md5_digest_fn_t md5_digest, 00319 apr_pool_t *pool); 00320 00321 /** Set @a *window to a pointer to the next window from the delta stream 00322 * @a stream. When we have completely reconstructed the target string, 00323 * set @a *window to zero. 00324 * 00325 * The window will be allocated in @a pool. 00326 */ 00327 svn_error_t * 00328 svn_txdelta_next_window(svn_txdelta_window_t **window, 00329 svn_txdelta_stream_t *stream, 00330 apr_pool_t *pool); 00331 00332 00333 /** Return the md5 digest for the complete fulltext deltified by 00334 * @a stream, or @c NULL if @a stream has not yet returned its final 00335 * @c NULL window. The digest is allocated in the same memory as @a 00336 * STREAM. 00337 */ 00338 const unsigned char * 00339 svn_txdelta_md5_digest(svn_txdelta_stream_t *stream); 00340 00341 /** Set @a *stream to a pointer to a delta stream that will turn the byte 00342 * string from @a source into the byte stream from @a target. 00343 * 00344 * @a source and @a target are both readable generic streams. When we call 00345 * svn_txdelta_next_window() on @a *stream, it will read from @a source and 00346 * @a target to gather as much data as it needs. 00347 * 00348 * Do any necessary allocation in a sub-pool of @a pool. 00349 */ 00350 void 00351 svn_txdelta(svn_txdelta_stream_t **stream, 00352 svn_stream_t *source, 00353 svn_stream_t *target, 00354 apr_pool_t *pool); 00355 00356 00357 /** 00358 * Return a writable stream which, when fed target data, will send 00359 * delta windows to @a handler/@a handler_baton which transform the 00360 * data in @a source to the target data. As usual, the window handler 00361 * will receive a NULL window to signify the end of the window stream. 00362 * The stream handler functions will read data from @a source as 00363 * necessary. 00364 * 00365 * @since New in 1.1. 00366 */ 00367 svn_stream_t * 00368 svn_txdelta_target_push(svn_txdelta_window_handler_t handler, 00369 void *handler_baton, 00370 svn_stream_t *source, 00371 apr_pool_t *pool); 00372 00373 00374 /** Send the contents of @a string to window-handler @a handler/@a baton. 00375 * This is effectively a 'copy' operation, resulting in delta windows that 00376 * make the target equivalent to the value of @a string. 00377 * 00378 * All temporary allocation is performed in @a pool. 00379 */ 00380 svn_error_t * 00381 svn_txdelta_send_string(const svn_string_t *string, 00382 svn_txdelta_window_handler_t handler, 00383 void *handler_baton, 00384 apr_pool_t *pool); 00385 00386 /** Send the contents of @a stream to window-handler @a handler/@a baton. 00387 * This is effectively a 'copy' operation, resulting in delta windows that 00388 * make the target equivalent to the stream. 00389 * 00390 * If @a digest is non-NULL, populate it with the md5 checksum for the 00391 * fulltext that was deltified (@a digest must be at least 00392 * @c APR_MD5_DIGESTSIZE bytes long). 00393 * 00394 * All temporary allocation is performed in @a pool. 00395 */ 00396 svn_error_t * 00397 svn_txdelta_send_stream(svn_stream_t *stream, 00398 svn_txdelta_window_handler_t handler, 00399 void *handler_baton, 00400 unsigned char *digest, 00401 apr_pool_t *pool); 00402 00403 /** Send the contents of @a txstream to window-handler @a handler/@a baton. 00404 * Windows will be extracted from the stream and delivered to the handler. 00405 * 00406 * All temporary allocation is performed in @a pool. 00407 */ 00408 svn_error_t * 00409 svn_txdelta_send_txstream(svn_txdelta_stream_t *txstream, 00410 svn_txdelta_window_handler_t handler, 00411 void *handler_baton, 00412 apr_pool_t *pool); 00413 00414 00415 /** Prepare to apply a text delta. @a source is a readable generic stream 00416 * yielding the source data, @a target is a writable generic stream to 00417 * write target data to, and allocation takes place in a sub-pool of 00418 * @a pool. On return, @a *handler is set to a window handler function and 00419 * @a *handler_baton is set to the value to pass as the @a baton argument to 00420 * @a *handler. 00421 * 00422 * If @a result_digest is non-NULL, it points to APR_MD5_DIGESTSIZE bytes 00423 * of storage, and the final call to @a handler populates it with the 00424 * MD5 digest of the resulting fulltext. 00425 * 00426 * If @a error_info is non-NULL, it is inserted parenthetically into 00427 * the error string for any error returned by svn_txdelta_apply() or 00428 * @a *handler. (It is normally used to provide path information, 00429 * since there's nothing else in the delta application's context to 00430 * supply a path for error messages.) 00431 * 00432 * @note To avoid lifetime issues, @a error_info is copied into 00433 * @a pool or a subpool thereof. 00434 */ 00435 void 00436 svn_txdelta_apply(svn_stream_t *source, 00437 svn_stream_t *target, 00438 unsigned char *result_digest, 00439 const char *error_info, 00440 apr_pool_t *pool, 00441 svn_txdelta_window_handler_t *handler, 00442 void **handler_baton); 00443 00444 00445 00446 /*** Producing and consuming svndiff-format text deltas. ***/ 00447 00448 /** Prepare to produce an svndiff-format diff from text delta windows. 00449 * @a output is a writable generic stream to write the svndiff data to. 00450 * Allocation takes place in a sub-pool of @a pool. On return, @a *handler 00451 * is set to a window handler function and @a *handler_baton is set to 00452 * the value to pass as the @a baton argument to @a *handler. The svndiff 00453 * version is @a svndiff_version. 00454 * 00455 * @since New in 1.4. 00456 */ 00457 void 00458 svn_txdelta_to_svndiff2(svn_txdelta_window_handler_t *handler, 00459 void **handler_baton, 00460 svn_stream_t *output, 00461 int svndiff_version, 00462 apr_pool_t *pool); 00463 00464 /** Similar to svn_txdelta_to_svndiff2, but always using svndiff 00465 * version 0. 00466 * 00467 * @deprecated Provided for backward compatibility with the 1.3 API. 00468 */ 00469 SVN_DEPRECATED 00470 void 00471 svn_txdelta_to_svndiff(svn_stream_t *output, 00472 apr_pool_t *pool, 00473 svn_txdelta_window_handler_t *handler, 00474 void **handler_baton); 00475 00476 /** Return a writable generic stream which will parse svndiff-format 00477 * data into a text delta, invoking @a handler with @a handler_baton 00478 * whenever a new window is ready. If @a error_on_early_close is @c 00479 * TRUE, attempting to close this stream before it has handled the entire 00480 * svndiff data set will result in #SVN_ERR_SVNDIFF_UNEXPECTED_END, 00481 * else this error condition will be ignored. 00482 */ 00483 svn_stream_t * 00484 svn_txdelta_parse_svndiff(svn_txdelta_window_handler_t handler, 00485 void *handler_baton, 00486 svn_boolean_t error_on_early_close, 00487 apr_pool_t *pool); 00488 00489 /** 00490 * Read and parse one delta window in svndiff format from the 00491 * readable stream @a stream and place it in @a *window, allocating 00492 * the result in @a pool. The caller must take responsibility for 00493 * stripping off the four-byte 'SVN@<ver@>' header at the beginning of 00494 * the svndiff document before reading the first window, and must 00495 * provide the version number (the value of the fourth byte) to each 00496 * invocation of this routine with the @a svndiff_version argument. 00497 * 00498 * @since New in 1.1. 00499 */ 00500 svn_error_t * 00501 svn_txdelta_read_svndiff_window(svn_txdelta_window_t **window, 00502 svn_stream_t *stream, 00503 int svndiff_version, 00504 apr_pool_t *pool); 00505 00506 /** 00507 * Read and skip one delta window in svndiff format from the 00508 * file @a file. @a pool is used for temporary allocations. The 00509 * caller must take responsibility for stripping off the four-byte 00510 * 'SVN@<ver@>' header at the beginning of the svndiff document before 00511 * reading or skipping the first window, and must provide the version 00512 * number (the value of the fourth byte) to each invocation of this 00513 * routine with the @a svndiff_version argument. 00514 * 00515 * @since New in 1.1. 00516 */ 00517 svn_error_t * 00518 svn_txdelta_skip_svndiff_window(apr_file_t *file, 00519 int svndiff_version, 00520 apr_pool_t *pool); 00521 00522 /** @} */ 00523 00524 00525 /** Traversing tree deltas. 00526 * 00527 * In Subversion, we've got various producers and consumers of tree 00528 * deltas. 00529 * 00530 * In processing a `commit' command: 00531 * - The client examines its working copy data, and produces a tree 00532 * delta describing the changes to be committed. 00533 * - The client networking library consumes that delta, and sends them 00534 * across the wire as an equivalent series of network requests (for 00535 * example, to svnserve as an ra_svn protocol stream, or to an 00536 * Apache httpd server as WebDAV commands) 00537 * - The server receives those requests and produces a tree delta --- 00538 * hopefully equivalent to the one the client produced above. 00539 * - The Subversion server module consumes that delta and commits an 00540 * appropriate transaction to the filesystem. 00541 * 00542 * In processing an `update' command, the process is reversed: 00543 * - The Subversion server module talks to the filesystem and produces 00544 * a tree delta describing the changes necessary to bring the 00545 * client's working copy up to date. 00546 * - The server consumes this delta, and assembles a reply 00547 * representing the appropriate changes. 00548 * - The client networking library receives that reply, and produces a 00549 * tree delta --- hopefully equivalent to the one the Subversion 00550 * server produced above. 00551 * - The working copy library consumes that delta, and makes the 00552 * appropriate changes to the working copy. 00553 * 00554 * The simplest approach would be to represent tree deltas using the 00555 * obvious data structure. To do an update, the server would 00556 * construct a delta structure, and the working copy library would 00557 * apply that structure to the working copy; the network layer's job 00558 * would simply be to get the structure across the net intact. 00559 * 00560 * However, we expect that these deltas will occasionally be too large 00561 * to fit in a typical workstation's swap area. For example, in 00562 * checking out a 200Mb source tree, the entire source tree is 00563 * represented by a single tree delta. So it's important to handle 00564 * deltas that are too large to fit in swap all at once. 00565 * 00566 * So instead of representing the tree delta explicitly, we define a 00567 * standard way for a consumer to process each piece of a tree delta 00568 * as soon as the producer creates it. The #svn_delta_editor_t 00569 * structure is a set of callback functions to be defined by a delta 00570 * consumer, and invoked by a delta producer. Each invocation of a 00571 * callback function describes a piece of the delta --- a file's 00572 * contents changing, something being renamed, etc. 00573 * 00574 * @defgroup svn_delta_tree_deltas Tree deltas 00575 * @{ 00576 */ 00577 00578 /** A structure full of callback functions the delta source will invoke 00579 * as it produces the delta. 00580 * 00581 * @note Don't try to allocate one of these yourself. Instead, always 00582 * use svn_delta_default_editor() or some other constructor, to ensure 00583 * that unused slots are filled in with no-op functions. 00584 * 00585 * <h3>Function Usage</h3> 00586 * 00587 * Here's how to use these functions to express a tree delta. 00588 * 00589 * The delta consumer implements the callback functions described in 00590 * this structure, and the delta producer invokes them. So the 00591 * caller (producer) is pushing tree delta data at the callee 00592 * (consumer). 00593 * 00594 * At the start of traversal, the consumer provides @a edit_baton, a 00595 * baton global to the entire delta edit. If there is a target 00596 * revision that needs to be set for this operation, the producer 00597 * should call the @c set_target_revision function at this point. 00598 * 00599 * Next, if there are any tree deltas to express, the producer should 00600 * pass the @a edit_baton to the @c open_root function, to get a baton 00601 * representing root of the tree being edited. 00602 * 00603 * Most of the callbacks work in the obvious way: 00604 * 00605 * @c delete_entry 00606 * @c add_file 00607 * @c add_directory 00608 * @c open_file 00609 * @c open_directory 00610 * 00611 * Each of these takes a directory baton, indicating the directory 00612 * in which the change takes place, and a @a path argument, giving the 00613 * path (relative to the root of the edit) of the file, 00614 * subdirectory, or directory entry to change. Editors will usually 00615 * want to join this relative path with some base stored in the edit 00616 * baton (e.g. a URL, a location in the OS filesystem). 00617 * 00618 * Since every call requires a parent directory baton, including 00619 * @c add_directory and @c open_directory, where do we ever get our 00620 * initial directory baton, to get things started? The @c open_root 00621 * function returns a baton for the top directory of the change. In 00622 * general, the producer needs to invoke the editor's @c open_root 00623 * function before it can get anything of interest done. 00624 * 00625 * While @c open_root provides a directory baton for the root of 00626 * the tree being changed, the @c add_directory and @c open_directory 00627 * callbacks provide batons for other directories. Like the 00628 * callbacks above, they take a @a parent_baton and a relative path 00629 * @a path, and then return a new baton for the subdirectory being 00630 * created / modified --- @a child_baton. The producer can then use 00631 * @a child_baton to make further changes in that subdirectory. 00632 * 00633 * So, if we already have subdirectories named `foo' and `foo/bar', 00634 * then the producer can create a new file named `foo/bar/baz.c' by 00635 * calling: 00636 * 00637 * - @c open_root () --- yielding a baton @a root for the top directory 00638 * 00639 * - @c open_directory (@a root, "foo") --- yielding a baton @a f for `foo' 00640 * 00641 * - @c open_directory (@a f, "foo/bar") --- yielding a baton @a b for 00642 * `foo/bar' 00643 * 00644 * - @c add_file (@a b, "foo/bar/baz.c") 00645 * 00646 * When the producer is finished making changes to a directory, it 00647 * should call @c close_directory. This lets the consumer do any 00648 * necessary cleanup, and free the baton's storage. 00649 * 00650 * The @c add_file and @c open_file callbacks each return a baton 00651 * for the file being created or changed. This baton can then be 00652 * passed to @c apply_textdelta to change the file's contents, or 00653 * @c change_file_prop to change the file's properties. When the 00654 * producer is finished making changes to a file, it should call 00655 * @c close_file, to let the consumer clean up and free the baton. 00656 * 00657 * The @c add_file and @c add_directory functions each take arguments 00658 * @a copyfrom_path and @a copyfrom_revision. If @a copyfrom_path is 00659 * non-@c NULL, then @a copyfrom_path and @a copyfrom_revision indicate where 00660 * the file or directory should be copied from (to create the file 00661 * or directory being added). In that case, @a copyfrom_path must be 00662 * either a path relative to the root of the edit, or a URI from the 00663 * repository being edited. If @a copyfrom_path is @c NULL, then @a 00664 * copyfrom_revision must be #SVN_INVALID_REVNUM; it is invalid to 00665 * pass a mix of valid and invalid copyfrom arguments. 00666 * 00667 * 00668 * <h3>Function Call Ordering</h3> 00669 * 00670 * There are six restrictions on the order in which the producer 00671 * may use the batons: 00672 * 00673 * 1. The producer may call @c open_directory, @c add_directory, 00674 * @c open_file, @c add_file at most once on any given directory 00675 * entry. @c delete_entry may be called at most once on any given 00676 * directory entry and may later be followed by @c add_directory or 00677 * @c add_file on the same directory entry. @c delete_entry may 00678 * not be called on any directory entry after @c open_directory, 00679 * @c add_directory, @c open_file or @c add_file has been called on 00680 * that directory entry. 00681 * 00682 * 2. The producer may not close a directory baton until it has 00683 * closed all batons for its subdirectories. 00684 * 00685 * 3. When a producer calls @c open_directory or @c add_directory, 00686 * it must specify the most recently opened of the currently open 00687 * directory batons. Put another way, the producer cannot have 00688 * two sibling directory batons open at the same time. 00689 * 00690 * 4. A producer must call @c change_dir_prop on a directory either 00691 * before opening any of the directory's subdirs or after closing 00692 * them, but not in the middle. 00693 * 00694 * 5. When the producer calls @c open_file or @c add_file, either: 00695 * 00696 * (a) The producer must follow with any changes to the file 00697 * (@c change_file_prop and/or @c apply_textdelta, as applicable), 00698 * followed by a @c close_file call, before issuing any other file 00699 * or directory calls, or 00700 * 00701 * (b) The producer must follow with a @c change_file_prop call if 00702 * it is applicable, before issuing any other file or directory 00703 * calls; later, after all directory batons including the root 00704 * have been closed, the producer must issue @c apply_textdelta 00705 * and @c close_file calls. 00706 * 00707 * 6. When the producer calls @c apply_textdelta, it must make all of 00708 * the window handler calls (including the @c NULL window at the 00709 * end) before issuing any other #svn_delta_editor_t calls. 00710 * 00711 * So, the producer needs to use directory and file batons as if it 00712 * is doing a single depth-first traversal of the tree, with the 00713 * exception that the producer may keep file batons open in order to 00714 * make @c apply_textdelta calls at the end. 00715 * 00716 * 00717 * <h3>Pool Usage</h3> 00718 * 00719 * Many editor functions are invoked multiple times, in a sequence 00720 * determined by the editor "driver". The driver is responsible for 00721 * creating a pool for use on each iteration of the editor function, 00722 * and clearing that pool between each iteration. The driver passes 00723 * the appropriate pool on each function invocation. 00724 * 00725 * Based on the requirement of calling the editor functions in a 00726 * depth-first style, it is usually customary for the driver to similarly 00727 * nest the pools. However, this is only a safety feature to ensure 00728 * that pools associated with deeper items are always cleared when the 00729 * top-level items are also cleared. The interface does not assume, nor 00730 * require, any particular organization of the pools passed to these 00731 * functions. In fact, if "postfix deltas" are used for files, the file 00732 * pools definitely need to live outside the scope of their parent 00733 * directories' pools. 00734 * 00735 * Note that close_directory can be called *before* a file in that 00736 * directory has been closed. That is, the directory's baton is 00737 * closed before the file's baton. The implication is that 00738 * @c apply_textdelta and @c close_file should not refer to a parent 00739 * directory baton UNLESS the editor has taken precautions to 00740 * allocate it in a pool of the appropriate lifetime (the @a dir_pool 00741 * passed to @c open_directory and @c add_directory definitely does not 00742 * have the proper lifetime). In general, it is recommended to simply 00743 * avoid keeping a parent directory baton in a file baton. 00744 * 00745 * 00746 * <h3>Errors</h3> 00747 * 00748 * At least one implementation of the editor interface is 00749 * asynchronous; an error from one operation may be detected some 00750 * number of operations later. As a result, an editor driver must not 00751 * assume that an error from an editing function resulted from the 00752 * particular operation being detected. Moreover, once an editing 00753 * function returns an error, the edit is dead; the only further 00754 * operation which may be called on the editor is abort_edit. 00755 */ 00756 typedef struct svn_delta_editor_t 00757 { 00758 /** Set the target revision for this edit to @a target_revision. This 00759 * call, if used, should precede all other editor calls. 00760 * 00761 * @note This is typically used only for server->client update-type 00762 * operations. It doesn't really make much sense for commit-type 00763 * operations, because the revision of a commit isn't known until 00764 * the commit is finalized. 00765 */ 00766 svn_error_t *(*set_target_revision)(void *edit_baton, 00767 svn_revnum_t target_revision, 00768 apr_pool_t *pool); 00769 00770 /** Set @a *root_baton to a baton for the top directory of the change. 00771 * (This is the top of the subtree being changed, not necessarily 00772 * the root of the filesystem.) As with any other directory baton, the 00773 * producer should call @c close_directory on @a root_baton when done. 00774 * And as with other @c open_* calls, the @a base_revision here is the 00775 * current revision of the directory (before getting bumped up to the 00776 * new target revision set with @c set_target_revision). 00777 * 00778 * Allocations for the returned @a root_baton should be performed in 00779 * @a dir_pool. It is also typical to (possibly) save this pool for later 00780 * usage by @c close_directory. 00781 */ 00782 svn_error_t *(*open_root)(void *edit_baton, 00783 svn_revnum_t base_revision, 00784 apr_pool_t *dir_pool, 00785 void **root_baton); 00786 00787 00788 /** Remove the directory entry named @a path, a child of the directory 00789 * represented by @a parent_baton. If @a revision is a valid 00790 * revision number, it is used as a sanity check to ensure that you 00791 * are really removing the revision of @a path that you think you are. 00792 * 00793 * All allocations should be performed in @a pool. 00794 * 00795 * @note The @a revision parameter is typically used only for 00796 * client->server commit-type operations, allowing the server to 00797 * verify that it is deleting what the client thinks it should be 00798 * deleting. It only really makes sense in the opposite direction 00799 * (during server->client update-type operations) when the trees 00800 * whose delta is being described are ancestrally related (that is, 00801 * one tree is an ancestor of the other). 00802 */ 00803 svn_error_t *(*delete_entry)(const char *path, 00804 svn_revnum_t revision, 00805 void *parent_baton, 00806 apr_pool_t *pool); 00807 00808 00809 /** We are going to add a new subdirectory named @a path. We will use 00810 * the value this callback stores in @a *child_baton as the 00811 * @a parent_baton for further changes in the new subdirectory. 00812 * 00813 * If @a copyfrom_path is non-@c NULL, this add has history (i.e., is a 00814 * copy), and the origin of the copy may be recorded as 00815 * @a copyfrom_path under @a copyfrom_revision. 00816 * 00817 * Allocations for the returned @a child_baton should be performed in 00818 * @a dir_pool. It is also typical to (possibly) save this pool for later 00819 * usage by @c close_directory. 00820 */ 00821 svn_error_t *(*add_directory)(const char *path, 00822 void *parent_baton, 00823 const char *copyfrom_path, 00824 svn_revnum_t copyfrom_revision, 00825 apr_pool_t *dir_pool, 00826 void **child_baton); 00827 00828 /** We are going to make changes in a subdirectory (of the directory 00829 * identified by @a parent_baton). The subdirectory is specified by 00830 * @a path. The callback must store a value in @a *child_baton that 00831 * should be used as the @a parent_baton for subsequent changes in this 00832 * subdirectory. If a valid revnum, @a base_revision is the current 00833 * revision of the subdirectory. 00834 * 00835 * Allocations for the returned @a child_baton should be performed in 00836 * @a dir_pool. It is also typical to (possibly) save this pool for later 00837 * usage by @c close_directory. 00838 */ 00839 svn_error_t *(*open_directory)(const char *path, 00840 void *parent_baton, 00841 svn_revnum_t base_revision, 00842 apr_pool_t *dir_pool, 00843 void **child_baton); 00844 00845 /** Change the value of a directory's property. 00846 * - @a dir_baton specifies the directory whose property should change. 00847 * - @a name is the name of the property to change. 00848 * - @a value is the new (final) value of the property, or @c NULL if the 00849 * property should be removed altogether. 00850 * 00851 * The callback is guaranteed to be called exactly once for each property 00852 * whose value differs between the start and the end of the edit. 00853 * 00854 * All allocations should be performed in @a pool. 00855 */ 00856 svn_error_t *(*change_dir_prop)(void *dir_baton, 00857 const char *name, 00858 const svn_string_t *value, 00859 apr_pool_t *pool); 00860 00861 /** We are done processing a subdirectory, whose baton is @a dir_baton 00862 * (set by @c add_directory or @c open_directory). We won't be using 00863 * the baton any more, so whatever resources it refers to may now be 00864 * freed. 00865 */ 00866 svn_error_t *(*close_directory)(void *dir_baton, 00867 apr_pool_t *pool); 00868 00869 00870 /** In the directory represented by @a parent_baton, indicate that 00871 * @a path is present as a subdirectory in the edit source, but 00872 * cannot be conveyed to the edit consumer (perhaps because of 00873 * authorization restrictions). 00874 */ 00875 svn_error_t *(*absent_directory)(const char *path, 00876 void *parent_baton, 00877 apr_pool_t *pool); 00878 00879 /** We are going to add a new file named @a path. The callback can 00880 * store a baton for this new file in @a **file_baton; whatever value 00881 * it stores there should be passed through to @c apply_textdelta. 00882 * 00883 * If @a copyfrom_path is non-@c NULL, this add has history (i.e., is a 00884 * copy), and the origin of the copy may be recorded as 00885 * @a copyfrom_path under @a copyfrom_revision. 00886 * 00887 * Allocations for the returned @a file_baton should be performed in 00888 * @a file_pool. It is also typical to save this pool for later usage 00889 * by @c apply_textdelta and possibly @c close_file. 00890 */ 00891 svn_error_t *(*add_file)(const char *path, 00892 void *parent_baton, 00893 const char *copyfrom_path, 00894 svn_revnum_t copyfrom_revision, 00895 apr_pool_t *file_pool, 00896 void **file_baton); 00897 00898 /** We are going to make change to a file named @a path, which resides 00899 * in the directory identified by @a parent_baton. 00900 * 00901 * The callback can store a baton for this new file in @a **file_baton; 00902 * whatever value it stores there should be passed through to 00903 * @c apply_textdelta. If a valid revnum, @a base_revision is the 00904 * current revision of the file. 00905 * 00906 * Allocations for the returned @a file_baton should be performed in 00907 * @a file_pool. It is also typical to save this pool for later usage 00908 * by @c apply_textdelta and possibly @c close_file. 00909 */ 00910 svn_error_t *(*open_file)(const char *path, 00911 void *parent_baton, 00912 svn_revnum_t base_revision, 00913 apr_pool_t *file_pool, 00914 void **file_baton); 00915 00916 /** Apply a text delta, yielding the new revision of a file. 00917 * 00918 * @a file_baton indicates the file we're creating or updating, and the 00919 * ancestor file on which it is based; it is the baton set by some 00920 * prior @c add_file or @c open_file callback. 00921 * 00922 * The callback should set @a *handler to a text delta window 00923 * handler; we will then call @a *handler on successive text 00924 * delta windows as we receive them. The callback should set 00925 * @a *handler_baton to the value we should pass as the @a baton 00926 * argument to @a *handler. 00927 * 00928 * @a base_checksum is the hex MD5 digest for the base text against 00929 * which the delta is being applied; it is ignored if NULL, and may 00930 * be ignored even if not NULL. If it is not ignored, it must match 00931 * the checksum of the base text against which svndiff data is being 00932 * applied; if it does not, @c apply_textdelta or the @a *handler call 00933 * which detects the mismatch will return the error 00934 * SVN_ERR_CHECKSUM_MISMATCH (if there is no base text, there may 00935 * still be an error if @a base_checksum is neither NULL nor the hex 00936 * MD5 checksum of the empty string). 00937 */ 00938 svn_error_t *(*apply_textdelta)(void *file_baton, 00939 const char *base_checksum, 00940 apr_pool_t *pool, 00941 svn_txdelta_window_handler_t *handler, 00942 void **handler_baton); 00943 00944 /** Change the value of a file's property. 00945 * - @a file_baton specifies the file whose property should change. 00946 * - @a name is the name of the property to change. 00947 * - @a value is the new (final) value of the property, or @c NULL if the 00948 * property should be removed altogether. 00949 * 00950 * The callback is guaranteed to be called exactly once for each property 00951 * whose value differs between the start and the end of the edit. 00952 * 00953 * All allocations should be performed in @a pool. 00954 */ 00955 svn_error_t *(*change_file_prop)(void *file_baton, 00956 const char *name, 00957 const svn_string_t *value, 00958 apr_pool_t *pool); 00959 00960 /** We are done processing a file, whose baton is @a file_baton (set by 00961 * @c add_file or @c open_file). We won't be using the baton any 00962 * more, so whatever resources it refers to may now be freed. 00963 * 00964 * @a text_checksum is the hex MD5 digest for the fulltext that 00965 * resulted from a delta application, see @c apply_textdelta. The 00966 * checksum is ignored if NULL. If not null, it is compared to the 00967 * checksum of the new fulltext, and the error 00968 * SVN_ERR_CHECKSUM_MISMATCH is returned if they do not match. If 00969 * there is no new fulltext, @a text_checksum is ignored. 00970 */ 00971 svn_error_t *(*close_file)(void *file_baton, 00972 const char *text_checksum, 00973 apr_pool_t *pool); 00974 00975 /** In the directory represented by @a parent_baton, indicate that 00976 * @a path is present as a file in the edit source, but cannot be 00977 * conveyed to the edit consumer (perhaps because of authorization 00978 * restrictions). 00979 */ 00980 svn_error_t *(*absent_file)(const char *path, 00981 void *parent_baton, 00982 apr_pool_t *pool); 00983 00984 /** All delta processing is done. Call this, with the @a edit_baton for 00985 * the entire edit. 00986 */ 00987 svn_error_t *(*close_edit)(void *edit_baton, 00988 apr_pool_t *pool); 00989 00990 /** The editor-driver has decided to bail out. Allow the editor to 00991 * gracefully clean up things if it needs to. 00992 */ 00993 svn_error_t *(*abort_edit)(void *edit_baton, 00994 apr_pool_t *pool); 00995 00996 /* Be sure to update svn_delta_get_cancellation_editor() and 00997 * svn_delta_default_editor() if you add a new callback here. */ 00998 } svn_delta_editor_t; 00999 01000 01001 /** Return a default delta editor template, allocated in @a pool. 01002 * 01003 * The editor functions in the template do only the most basic 01004 * baton-swapping: each editor function that produces a baton does so 01005 * by copying its incoming baton into the outgoing baton reference. 01006 * 01007 * This editor is not intended to be useful by itself, but is meant to 01008 * be the basis for a useful editor. After getting a default editor, 01009 * you substitute in your own implementations for the editor functions 01010 * you care about. The ones you don't care about, you don't have to 01011 * implement -- you can rely on the template's implementation to 01012 * safely do nothing of consequence. 01013 */ 01014 svn_delta_editor_t * 01015 svn_delta_default_editor(apr_pool_t *pool); 01016 01017 /** A text-delta window handler which does nothing. 01018 * 01019 * Editors can return this handler from @c apply_textdelta if they don't 01020 * care about text delta windows. 01021 */ 01022 svn_error_t * 01023 svn_delta_noop_window_handler(svn_txdelta_window_t *window, 01024 void *baton); 01025 01026 /** Set @a *editor and @a *edit_baton to a cancellation editor that 01027 * wraps @a wrapped_editor and @a wrapped_baton. 01028 * 01029 * The @a editor will call @a cancel_func with @a cancel_baton when each of 01030 * its functions is called, continuing on to call the corresponding wrapped 01031 * function if @a cancel_func returns #SVN_NO_ERROR. 01032 * 01033 * If @a cancel_func is @c NULL, set @a *editor to @a wrapped_editor and 01034 * @a *edit_baton to @a wrapped_baton. 01035 */ 01036 svn_error_t * 01037 svn_delta_get_cancellation_editor(svn_cancel_func_t cancel_func, 01038 void *cancel_baton, 01039 const svn_delta_editor_t *wrapped_editor, 01040 void *wrapped_baton, 01041 const svn_delta_editor_t **editor, 01042 void **edit_baton, 01043 apr_pool_t *pool); 01044 01045 /** Set @a *editor and @a *edit_baton to an depth-based filtering 01046 * editor that wraps @a wrapped_editor and @a wrapped_baton. 01047 * 01048 * The @a editor will track the depth of this drive against the @a 01049 * requested_depth, taking into account whether not the edit drive is 01050 * making use of a target (via @a has_target), and forward editor 01051 * calls which operate "within" the request depth range through to @a 01052 * wrapped_editor. 01053 * 01054 * @a requested_depth must be one of the following depth values: 01055 * #svn_depth_infinity, #svn_depth_empty, #svn_depth_files, 01056 * #svn_depth_immediates, or #svn_depth_unknown. 01057 * 01058 * If filtering is deemed unncessary (or if @a requested_depth is 01059 * #svn_depth_unknown), @a *editor and @a *edit_baton will be set to @a 01060 * wrapped_editor and @a wrapped_baton, respectively; otherwise, 01061 * they'll be set to new objects allocated from @a pool. 01062 * 01063 * @note Because the svn_delta_editor_t interface's @c delete_entry() 01064 * function doesn't carry node kind information, a depth-based 01065 * filtering editor being asked to filter for #svn_depth_files but 01066 * receiving a @c delete_entry() call on an immediate child of the 01067 * editor's target is unable to know if that deletion should be 01068 * allowed or filtered out -- a delete of a top-level file is okay in 01069 * this case, a delete of a top-level subdirectory is not. As such, 01070 * this filtering editor takes a conservative approach, and ignores 01071 * top-level deletion requests when filtering for #svn_depth_files. 01072 * Fortunately, most non-depth-aware (pre-1.5) Subversion editor 01073 * drivers can be told to drive non-recursively (where non-recursive 01074 * means essentially #svn_depth_files), which means they won't 01075 * transmit out-of-scope editor commands anyway. 01076 * 01077 * @since New in 1.5. 01078 */ 01079 svn_error_t * 01080 svn_delta_depth_filter_editor(const svn_delta_editor_t **editor, 01081 void **edit_baton, 01082 const svn_delta_editor_t *wrapped_editor, 01083 void *wrapped_edit_baton, 01084 svn_depth_t requested_depth, 01085 svn_boolean_t has_target, 01086 apr_pool_t *pool); 01087 01088 /** @} */ 01089 01090 01091 /** Path-based editor drives. 01092 * 01093 * @defgroup svn_delta_path_delta_drivers Path-based delta drivers 01094 * @{ 01095 */ 01096 01097 /** Callback function type for svn_delta_path_driver(). 01098 * 01099 * The handler of this callback is given the callback baton @a 01100 * callback_baton, @a path, and the @a parent_baton which represents 01101 * path's parent directory as created by the editor passed to 01102 * svn_delta_path_driver(). 01103 * 01104 * If @a path represents a directory, the handler must return a @a 01105 * *dir_baton for @a path, generated from the same editor (so that the 01106 * driver can later close that directory). 01107 * 01108 * If, however, @a path represents a file, the handler should NOT 01109 * return any file batons. It can close any opened or added files 01110 * immediately, or delay that close until the end of the edit when 01111 * svn_delta_path_driver() returns. 01112 * 01113 * Finally, if @a parent_baton is @c NULL, then the root of the edit 01114 * is also one of the paths passed to svn_delta_path_driver(). The 01115 * handler of this callback must call the editor's open_root() 01116 * function and return the top-level root dir baton in @a *dir_baton. 01117 */ 01118 typedef svn_error_t *(*svn_delta_path_driver_cb_func_t)( 01119 void **dir_baton, 01120 void *parent_baton, 01121 void *callback_baton, 01122 const char *path, 01123 apr_pool_t *pool); 01124 01125 01126 /** Drive @a editor (with its @a edit_baton) in such a way that 01127 * each path in @a paths is traversed in a depth-first fashion. As 01128 * each path is hit as part of the editor drive, use @a 01129 * callback_func and @a callback_baton to allow the caller to handle 01130 * the portion of the editor drive related to that path. 01131 * 01132 * Use @a revision as the revision number passed to intermediate 01133 * directory openings. 01134 * 01135 * Use @a pool for all necessary allocations. 01136 */ 01137 svn_error_t * 01138 svn_delta_path_driver(const svn_delta_editor_t *editor, 01139 void *edit_baton, 01140 svn_revnum_t revision, 01141 const apr_array_header_t *paths, 01142 svn_delta_path_driver_cb_func_t callback_func, 01143 void *callback_baton, 01144 apr_pool_t *pool); 01145 01146 /** @} */ 01147 01148 01149 /*** File revision iterator types ***/ 01150 01151 /** 01152 * The callback invoked by file rev loopers, such as 01153 * svn_ra_plugin_t.get_file_revs2() and svn_repos_get_file_revs2(). 01154 * 01155 * @a baton is provided by the caller, @a path is the pathname of the file 01156 * in revision @a rev and @a rev_props are the revision properties. 01157 * 01158 * If @a delta_handler and @a delta_baton are non-NULL, they may be set to a 01159 * handler/baton which will be called with the delta between the previous 01160 * revision and this one after the return of this callback. They may be 01161 * left as NULL/NULL. 01162 * 01163 * @a result_of_merge will be @c TRUE if the revision being returned was 01164 * included as the result of a merge. 01165 * 01166 * @a prop_diffs is an array of svn_prop_t elements indicating the property 01167 * delta for this and the previous revision. 01168 * 01169 * @a pool may be used for temporary allocations, but you can't rely 01170 * on objects allocated to live outside of this particular call and 01171 * the immediately following calls to @a *delta_handler if any. (Pass 01172 * in a pool via @a baton if need be.) 01173 * 01174 * @since New in 1.5. 01175 */ 01176 typedef svn_error_t *(*svn_file_rev_handler_t)( 01177 void *baton, 01178 const char *path, 01179 svn_revnum_t rev, 01180 apr_hash_t *rev_props, 01181 svn_boolean_t result_of_merge, 01182 svn_txdelta_window_handler_t *delta_handler, 01183 void **delta_baton, 01184 const apr_array_header_t *prop_diffs, 01185 apr_pool_t *pool); 01186 01187 /** 01188 * The old file rev handler interface. 01189 * 01190 * @note #svn_file_rev_handler_old_t is a placeholder type for both 01191 * #svn_repos_file_rev_handler_t and #svn_ra_file_rev_handler_t. It is 01192 * reproduced here for dependency reasons. 01193 * 01194 * @deprecated This type is provided for the svn_compat_wrap_file_rev_handler() 01195 * compatibilty wrapper, and should not be used for new development. 01196 * @since New in 1.5. 01197 */ 01198 typedef svn_error_t *(*svn_file_rev_handler_old_t)( 01199 void *baton, 01200 const char *path, 01201 svn_revnum_t rev, 01202 apr_hash_t *rev_props, 01203 svn_txdelta_window_handler_t *delta_handler, 01204 void **delta_baton, 01205 const apr_array_header_t *prop_diffs, 01206 apr_pool_t *pool); 01207 01208 /** Return, in @a *handler2 and @a *handler2_baton a function/baton that 01209 * will call @a handler/@a handler_baton, allocating the @a *handler2_baton 01210 * in @a pool. 01211 * 01212 * @note This is used by compatibility wrappers, which exist in more than 01213 * Subversion core library. 01214 * 01215 * @note #svn_file_rev_handler_old_t is a placeholder type for both 01216 * #svn_repos_file_rev_handler_t and #svn_ra_file_rev_handler_t. It is 01217 * reproduced here for dependency reasons. 01218 * 01219 * @since New in 1.5. 01220 */ 01221 void 01222 svn_compat_wrap_file_rev_handler(svn_file_rev_handler_t *handler2, 01223 void **handler2_baton, 01224 svn_file_rev_handler_old_t handler, 01225 void *handler_baton, 01226 apr_pool_t *pool); 01227 01228 /** @} end group: delta_support */ 01229 01230 01231 #ifdef __cplusplus 01232 } 01233 #endif /* __cplusplus */ 01234 01235 #endif /* SVN_DELTA_H */
1.3.9.1