1 | /** |
2 | * @copyright |
3 | * ==================================================================== |
4 | * Licensed to the Apache Software Foundation (ASF) under one |
5 | * or more contributor license agreements. See the NOTICE file |
6 | * distributed with this work for additional information |
7 | * regarding copyright ownership. The ASF licenses this file |
8 | * to you under the Apache License, Version 2.0 (the |
9 | * "License"); you may not use this file except in compliance |
10 | * with the License. You may obtain a copy of the License at |
11 | * |
12 | * http://www.apache.org/licenses/LICENSE-2.0 |
13 | * |
14 | * Unless required by applicable law or agreed to in writing, |
15 | * software distributed under the License is distributed on an |
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
17 | * KIND, either express or implied. See the License for the |
18 | * specific language governing permissions and limitations |
19 | * under the License. |
20 | * ==================================================================== |
21 | * @endcopyright |
22 | * |
23 | * @file svn_delta.h |
24 | * @brief Delta-parsing |
25 | */ |
26 | |
27 | /* ==================================================================== */ |
28 | |
29 | |
30 | |
31 | #ifndef SVN_DELTA_H |
32 | #define SVN_DELTA_H |
33 | |
34 | #include <apr.h> |
35 | #include <apr_pools.h> |
36 | #include <apr_hash.h> |
37 | #include <apr_tables.h> |
38 | #include <apr_file_io.h> /* for apr_file_t */ |
39 | |
40 | #include "svn_types.h" |
41 | #include "svn_string.h" |
42 | #include "svn_io.h" |
43 | #include "svn_checksum.h" |
44 | |
45 | #ifdef __cplusplus |
46 | extern "C" { |
47 | #endif /* __cplusplus */ |
48 | |
49 | |
50 | |
51 | /** This compression level effectively disables data compression. |
52 | * However, the data pre-processing costs may still not be zero. |
53 | * |
54 | * @since New in 1.7. |
55 | */ |
56 | #define SVN_DELTA_COMPRESSION_LEVEL_NONE 0 |
57 | |
58 | /** This is the maximum compression level we can pass to zlib. |
59 | * |
60 | * @since New in 1.7. |
61 | */ |
62 | #define SVN_DELTA_COMPRESSION_LEVEL_MAX 9 |
63 | |
64 | /** This is the default compression level we pass to zlib. It |
65 | * should be between 0 and 9, with higher numbers resulting in |
66 | * better compression rates but slower operation. |
67 | * |
68 | * @since New in 1.7. |
69 | */ |
70 | #define SVN_DELTA_COMPRESSION_LEVEL_DEFAULT 5 |
71 | |
72 | /** |
73 | * Get libsvn_delta version information. |
74 | * |
75 | * @since New in 1.1. |
76 | */ |
77 | const svn_version_t * |
78 | svn_delta_version(void); |
79 | |
80 | /** |
81 | * @defgroup delta_support Delta generation and handling |
82 | * |
83 | * @{ |
84 | */ |
85 | |
86 | /** Text deltas. |
87 | * |
88 | * A text delta represents the difference between two strings of |
89 | * bytes, the `source' string and the `target' string. Given a source |
90 | * string and a target string, we can compute a text delta; given a |
91 | * source string and a delta, we can reconstruct the target string. |
92 | * However, note that deltas are not reversible: you cannot always |
93 | * reconstruct the source string given the target string and delta. |
94 | * |
95 | * Since text deltas can be very large, the interface here allows us |
96 | * to produce and consume them in pieces. Each piece, represented by |
97 | * an #svn_txdelta_window_t structure, describes how to produce the |
98 | * next section of the target string. |
99 | * |
100 | * To compute a new text delta: |
101 | * |
102 | * - We call svn_txdelta() on the streams we want to compare. That |
103 | * returns us an #svn_txdelta_stream_t object. |
104 | * |
105 | * - We then call svn_txdelta_next_window() on the stream object |
106 | * repeatedly. Each call returns a new #svn_txdelta_window_t |
107 | * object, which describes the next portion of the target string. |
108 | * When svn_txdelta_next_window() returns zero, we are done building |
109 | * the target string. |
110 | * |
111 | * @defgroup svn_delta_txt_delta Text deltas |
112 | * @{ |
113 | */ |
114 | |
115 | /** Action codes for text delta instructions. */ |
116 | enum svn_delta_action { |
117 | /* Note: The svndiff implementation relies on the values assigned in |
118 | * this enumeration matching the instruction encoding values. */ |
119 | |
120 | /** Append the @a length bytes at @a offset in the source view to the |
121 | * target. |
122 | * |
123 | * It must be the case that 0 <= @a offset < @a offset + |
124 | * @a length <= size of source view. |
125 | */ |
126 | svn_txdelta_source, |
127 | |
128 | /** Append the @a length bytes at @a offset in the target view, to the |
129 | * target. |
130 | * |
131 | * It must be the case that 0 <= @a offset < current position in the |
132 | * target view. |
133 | * |
134 | * However! @a offset + @a length may be *beyond* the end of the existing |
135 | * target data. "Where the heck does the text come from, then?" |
136 | * If you start at @a offset, and append @a length bytes one at a time, |
137 | * it'll work out --- you're adding new bytes to the end at the |
138 | * same rate you're reading them from the middle. Thus, if your |
139 | * current target text is "abcdefgh", and you get an #svn_txdelta_target |
140 | * instruction whose @a offset is 6 and whose @a length is 7, |
141 | * the resulting string is "abcdefghghghghg". This trick is actually |
142 | * useful in encoding long runs of consecutive characters, long runs |
143 | * of CR/LF pairs, etc. |
144 | */ |
145 | svn_txdelta_target, |
146 | |
147 | /** Append the @a length bytes at @a offset in the window's @a new string |
148 | * to the target. |
149 | * |
150 | * It must be the case that 0 <= @a offset < @a offset + |
151 | * @a length <= length of @a new. Windows MUST use new data in ascending |
152 | * order with no overlap at the moment; svn_txdelta_to_svndiff() |
153 | * depends on this. |
154 | */ |
155 | svn_txdelta_new |
156 | }; |
157 | |
158 | /** A single text delta instruction. */ |
159 | typedef struct svn_txdelta_op_t |
160 | { |
161 | /** Action code of delta instruction */ |
162 | enum svn_delta_action action_code; |
163 | /** Offset of delta, see #svn_delta_action for more details. */ |
164 | apr_size_t offset; |
165 | /** Number of bytes of delta, see #svn_delta_action for more details. */ |
166 | apr_size_t length; |
167 | } svn_txdelta_op_t; |
168 | |
169 | |
170 | /** An #svn_txdelta_window_t object describes how to reconstruct a |
171 | * contiguous section of the target string (the "target view") using a |
172 | * specified contiguous region of the source string (the "source |
173 | * view"). It contains a series of instructions which assemble the |
174 | * new target string text by pulling together substrings from: |
175 | * |
176 | * - the source view, |
177 | * |
178 | * - the previously constructed portion of the target view, |
179 | * |
180 | * - a string of new data contained within the window structure |
181 | * |
182 | * The source view must always slide forward from one window to the |
183 | * next; that is, neither the beginning nor the end of the source view |
184 | * may move to the left as we read from a window stream. This |
185 | * property allows us to apply deltas to non-seekable source streams |
186 | * without making a full copy of the source stream. |
187 | */ |
188 | typedef struct svn_txdelta_window_t |
189 | { |
190 | |
191 | /** The offset of the source view for this window. */ |
192 | svn_filesize_t sview_offset; |
193 | |
194 | /** The length of the source view for this window. */ |
195 | apr_size_t sview_len; |
196 | |
197 | /** The length of the target view for this window, i.e. the number of |
198 | * bytes which will be reconstructed by the instruction stream. */ |
199 | apr_size_t tview_len; |
200 | |
201 | /** The number of instructions in this window. */ |
202 | int num_ops; |
203 | |
204 | /** The number of svn_txdelta_source instructions in this window. If |
205 | * this number is 0, we don't need to read the source in order to |
206 | * reconstruct the target view. |
207 | */ |
208 | int src_ops; |
209 | |
210 | /** The instructions for this window. */ |
211 | const svn_txdelta_op_t *ops; |
212 | |
213 | /** New data, for use by any `svn_txdelta_new' instructions. */ |
214 | const svn_string_t *new_data; |
215 | |
216 | } svn_txdelta_window_t; |
217 | |
218 | /** |
219 | * Return a deep copy of @a window, allocated in @a pool. |
220 | * |
221 | * @since New in 1.3. |
222 | */ |
223 | svn_txdelta_window_t * |
224 | svn_txdelta_window_dup(const svn_txdelta_window_t *window, |
225 | apr_pool_t *pool); |
226 | |
227 | /** |
228 | * Compose two delta windows, yielding a third, allocated in @a pool. |
229 | * |
230 | * @since New in 1.4 |
231 | * |
232 | */ |
233 | svn_txdelta_window_t * |
234 | svn_txdelta_compose_windows(const svn_txdelta_window_t *window_A, |
235 | const svn_txdelta_window_t *window_B, |
236 | apr_pool_t *pool); |
237 | |
238 | /** |
239 | * Apply the instructions from @a window to a source view @a sbuf to |
240 | * produce a target view @a tbuf. |
241 | * |
242 | * @a sbuf is assumed to have @a window->sview_len bytes of data and |
243 | * @a tbuf is assumed to have room for @a tlen bytes of output. @a |
244 | * tlen may be more than @a window->tview_len, so return the actual |
245 | * number of bytes written. @a sbuf is not touched and may be NULL if |
246 | * @a window contains no source-copy operations. This is purely a |
247 | * memory operation; nothing can go wrong as long as we have a valid |
248 | * window. |
249 | * |
250 | * @since New in 1.4 |
251 | * |
252 | */ |
253 | void |
254 | svn_txdelta_apply_instructions(svn_txdelta_window_t *window, |
255 | const char *sbuf, char *tbuf, |
256 | apr_size_t *tlen); |
257 | |
258 | /** A typedef for functions that consume a series of delta windows, for |
259 | * use in caller-pushes interfaces. Such functions will typically |
260 | * apply the delta windows to produce some file, or save the windows |
261 | * somewhere. At the end of the delta window stream, you must call |
262 | * this function passing zero for the @a window argument. |
263 | */ |
264 | typedef svn_error_t *(*svn_txdelta_window_handler_t)( |
265 | svn_txdelta_window_t *window, void *baton); |
266 | |
267 | |
268 | /** This function will generate delta windows that turn @a source into |
269 | * @a target, and pushing these windows into the @a handler window handler |
270 | * callback (passing @a handler_baton to each invocation). |
271 | * |
272 | * If @a checksum is not NULL, then a checksum (of kind @a checksum_kind) |
273 | * will be computed for the target stream, and placed into *checksum. |
274 | * |
275 | * If @a cancel_func is not NULL, then it should refer to a cancellation |
276 | * function (along with @a cancel_baton). |
277 | * |
278 | * Results (the checksum) will be allocated from @a result_pool, and all |
279 | * temporary allocations will be performed in @a scratch_pool. |
280 | * |
281 | * Note: this function replaces the combination of svn_txdelta() and |
282 | * svn_txdelta_send_txstream(). |
283 | * |
284 | * @since New in 1.6. |
285 | */ |
286 | svn_error_t * |
287 | svn_txdelta_run(svn_stream_t *source, |
288 | svn_stream_t *target, |
289 | svn_txdelta_window_handler_t handler, |
290 | void *handler_baton, |
291 | svn_checksum_kind_t checksum_kind, |
292 | svn_checksum_t **checksum, |
293 | svn_cancel_func_t cancel_func, |
294 | void *cancel_baton, |
295 | apr_pool_t *result_pool, |
296 | apr_pool_t *scratch_pool); |
297 | |
298 | |
299 | /** A delta stream --- this is the hat from which we pull a series of |
300 | * svn_txdelta_window_t objects, which, taken in order, describe the |
301 | * entire target string. This type is defined within libsvn_delta, and |
302 | * opaque outside that library. |
303 | */ |
304 | typedef struct svn_txdelta_stream_t svn_txdelta_stream_t; |
305 | |
306 | |
307 | /** A typedef for a function that will set @a *window to the next |
308 | * window from a #svn_txdelta_stream_t object. If there are no more |
309 | * delta windows, NULL will be used. The returned window, if any, |
310 | * will be allocated in @a pool. @a baton is the baton specified |
311 | * when the stream was created. |
312 | * |
313 | * @since New in 1.4. |
314 | */ |
315 | typedef svn_error_t * |
316 | (*svn_txdelta_next_window_fn_t)(svn_txdelta_window_t **window, |
317 | void *baton, |
318 | apr_pool_t *pool); |
319 | |
320 | /** A typedef for a function that will return the md5 checksum of the |
321 | * fulltext deltified by a #svn_txdelta_stream_t object. Will |
322 | * return NULL if the final null window hasn't yet been returned by |
323 | * the stream. The returned value will be allocated in the same pool |
324 | * as the stream. @a baton is the baton specified when the stream was |
325 | * created. |
326 | * |
327 | * @since New in 1.4. |
328 | */ |
329 | typedef const unsigned char * |
330 | (*svn_txdelta_md5_digest_fn_t)(void *baton); |
331 | |
332 | /** Create and return a generic text delta stream with @a baton, @a |
333 | * next_window and @a md5_digest. Allocate the new stream in @a |
334 | * pool. |
335 | * |
336 | * @since New in 1.4. |
337 | */ |
338 | svn_txdelta_stream_t * |
339 | svn_txdelta_stream_create(void *baton, |
340 | svn_txdelta_next_window_fn_t next_window, |
341 | svn_txdelta_md5_digest_fn_t md5_digest, |
342 | apr_pool_t *pool); |
343 | |
344 | /** Set @a *window to a pointer to the next window from the delta stream |
345 | * @a stream. When we have completely reconstructed the target string, |
346 | * set @a *window to zero. |
347 | * |
348 | * The window will be allocated in @a pool. |
349 | */ |
350 | svn_error_t * |
351 | svn_txdelta_next_window(svn_txdelta_window_t **window, |
352 | svn_txdelta_stream_t *stream, |
353 | apr_pool_t *pool); |
354 | |
355 | |
356 | /** Return the md5 digest for the complete fulltext deltified by |
357 | * @a stream, or @c NULL if @a stream has not yet returned its final |
358 | * @c NULL window. The digest is allocated in the same memory as @a |
359 | * STREAM. |
360 | */ |
361 | const unsigned char * |
362 | svn_txdelta_md5_digest(svn_txdelta_stream_t *stream); |
363 | |
364 | /** Set @a *stream to a pointer to a delta stream that will turn the byte |
365 | * string from @a source into the byte stream from @a target. |
366 | * |
367 | * @a source and @a target are both readable generic streams. When we call |
368 | * svn_txdelta_next_window() on @a *stream, it will read from @a source and |
369 | * @a target to gather as much data as it needs. If @a calculate_checksum |
370 | * is set, you may call svn_txdelta_md5_digest() to get an MD5 checksum |
371 | * for @a target. |
372 | * |
373 | * Do any necessary allocation in a sub-pool of @a pool. |
374 | * |
375 | * @since New in 1.8. |
376 | */ |
377 | void |
378 | svn_txdelta2(svn_txdelta_stream_t **stream, |
379 | svn_stream_t *source, |
380 | svn_stream_t *target, |
381 | svn_boolean_t calculate_checksum, |
382 | apr_pool_t *pool); |
383 | |
384 | /** Similar to svn_txdelta2 but always calculating the target checksum. |
385 | * |
386 | * @deprecated Provided for backward compatibility with the 1.7 API. |
387 | */ |
388 | SVN_DEPRECATED |
389 | void |
390 | svn_txdelta(svn_txdelta_stream_t **stream, |
391 | svn_stream_t *source, |
392 | svn_stream_t *target, |
393 | apr_pool_t *pool); |
394 | |
395 | |
396 | /** |
397 | * Return a writable stream which, when fed target data, will send |
398 | * delta windows to @a handler/@a handler_baton which transform the |
399 | * data in @a source to the target data. As usual, the window handler |
400 | * will receive a NULL window to signify the end of the window stream. |
401 | * The stream handler functions will read data from @a source as |
402 | * necessary. |
403 | * |
404 | * @since New in 1.1. |
405 | */ |
406 | svn_stream_t * |
407 | svn_txdelta_target_push(svn_txdelta_window_handler_t handler, |
408 | void *handler_baton, |
409 | svn_stream_t *source, |
410 | apr_pool_t *pool); |
411 | |
412 | |
413 | /** Send the contents of @a string to window-handler @a handler/@a baton. |
414 | * This is effectively a 'copy' operation, resulting in delta windows that |
415 | * make the target equivalent to the value of @a string. |
416 | * |
417 | * All temporary allocation is performed in @a pool. |
418 | */ |
419 | svn_error_t * |
420 | svn_txdelta_send_string(const svn_string_t *string, |
421 | svn_txdelta_window_handler_t handler, |
422 | void *handler_baton, |
423 | apr_pool_t *pool); |
424 | |
425 | /** Send the contents of @a stream to window-handler @a handler/@a baton. |
426 | * This is effectively a 'copy' operation, resulting in delta windows that |
427 | * make the target equivalent to the stream. |
428 | * |
429 | * If @a digest is non-NULL, populate it with the md5 checksum for the |
430 | * fulltext that was deltified (@a digest must be at least |
431 | * @c APR_MD5_DIGESTSIZE bytes long). |
432 | * |
433 | * All temporary allocation is performed in @a pool. |
434 | */ |
435 | svn_error_t * |
436 | svn_txdelta_send_stream(svn_stream_t *stream, |
437 | svn_txdelta_window_handler_t handler, |
438 | void *handler_baton, |
439 | unsigned char *digest, |
440 | apr_pool_t *pool); |
441 | |
442 | /** Send the contents of @a txstream to window-handler @a handler/@a baton. |
443 | * Windows will be extracted from the stream and delivered to the handler. |
444 | * |
445 | * All temporary allocation is performed in @a pool. |
446 | */ |
447 | svn_error_t * |
448 | svn_txdelta_send_txstream(svn_txdelta_stream_t *txstream, |
449 | svn_txdelta_window_handler_t handler, |
450 | void *handler_baton, |
451 | apr_pool_t *pool); |
452 | |
453 | |
454 | /** Send the @a contents of length @a len as a txdelta against an empty |
455 | * source directly to window-handler @a handler/@a handler_baton. |
456 | * |
457 | * All temporary allocation is performed in @a pool. |
458 | * |
459 | * @since New in 1.8. |
460 | */ |
461 | svn_error_t * |
462 | svn_txdelta_send_contents(const unsigned char *contents, |
463 | apr_size_t len, |
464 | svn_txdelta_window_handler_t handler, |
465 | void *handler_baton, |
466 | apr_pool_t *pool); |
467 | |
468 | /** Prepare to apply a text delta. @a source is a readable generic stream |
469 | * yielding the source data, @a target is a writable generic stream to |
470 | * write target data to, and allocation takes place in a sub-pool of |
471 | * @a pool. On return, @a *handler is set to a window handler function and |
472 | * @a *handler_baton is set to the value to pass as the @a baton argument to |
473 | * @a *handler. |
474 | * |
475 | * If @a result_digest is non-NULL, it points to APR_MD5_DIGESTSIZE bytes |
476 | * of storage, and the final call to @a handler populates it with the |
477 | * MD5 digest of the resulting fulltext. |
478 | * |
479 | * If @a error_info is non-NULL, it is inserted parenthetically into |
480 | * the error string for any error returned by svn_txdelta_apply() or |
481 | * @a *handler. (It is normally used to provide path information, |
482 | * since there's nothing else in the delta application's context to |
483 | * supply a path for error messages.) |
484 | * |
485 | * @note To avoid lifetime issues, @a error_info is copied into |
486 | * @a pool or a subpool thereof. |
487 | */ |
488 | void |
489 | svn_txdelta_apply(svn_stream_t *source, |
490 | svn_stream_t *target, |
491 | unsigned char *result_digest, |
492 | const char *error_info, |
493 | apr_pool_t *pool, |
494 | svn_txdelta_window_handler_t *handler, |
495 | void **handler_baton); |
496 | |
497 | |
498 | |
499 | |
500 | /*** Producing and consuming svndiff-format text deltas. ***/ |
501 | |
502 | /** Prepare to produce an svndiff-format diff from text delta windows. |
503 | * @a output is a writable generic stream to write the svndiff data to. |
504 | * Allocation takes place in a sub-pool of @a pool. On return, @a *handler |
505 | * is set to a window handler function and @a *handler_baton is set to |
506 | * the value to pass as the @a baton argument to @a *handler. The svndiff |
507 | * version is @a svndiff_version. @a compression_level is the zlib |
508 | * compression level from 0 (no compression) and 9 (maximum compression). |
509 | * |
510 | * @since New in 1.7. |
511 | */ |
512 | void |
513 | svn_txdelta_to_svndiff3(svn_txdelta_window_handler_t *handler, |
514 | void **handler_baton, |
515 | svn_stream_t *output, |
516 | int svndiff_version, |
517 | int compression_level, |
518 | apr_pool_t *pool); |
519 | |
520 | /** Similar to svn_txdelta_to_svndiff3(), but always using the SVN default |
521 | * compression level (#SVN_DELTA_COMPRESSION_LEVEL_DEFAULT). |
522 | * |
523 | * @since New in 1.4. |
524 | * @deprecated Provided for backward compatibility with the 1.6 API. |
525 | */ |
526 | SVN_DEPRECATED |
527 | void |
528 | svn_txdelta_to_svndiff2(svn_txdelta_window_handler_t *handler, |
529 | void **handler_baton, |
530 | svn_stream_t *output, |
531 | int svndiff_version, |
532 | apr_pool_t *pool); |
533 | |
534 | /** Similar to svn_txdelta_to_svndiff2, but always using svndiff |
535 | * version 0. |
536 | * |
537 | * @deprecated Provided for backward compatibility with the 1.3 API. |
538 | */ |
539 | SVN_DEPRECATED |
540 | void |
541 | svn_txdelta_to_svndiff(svn_stream_t *output, |
542 | apr_pool_t *pool, |
543 | svn_txdelta_window_handler_t *handler, |
544 | void **handler_baton); |
545 | |
546 | /** Return a writable generic stream which will parse svndiff-format |
547 | * data into a text delta, invoking @a handler with @a handler_baton |
548 | * whenever a new window is ready. If @a error_on_early_close is @c |
549 | * TRUE, attempting to close this stream before it has handled the entire |
550 | * svndiff data set will result in #SVN_ERR_SVNDIFF_UNEXPECTED_END, |
551 | * else this error condition will be ignored. |
552 | */ |
553 | svn_stream_t * |
554 | svn_txdelta_parse_svndiff(svn_txdelta_window_handler_t handler, |
555 | void *handler_baton, |
556 | svn_boolean_t error_on_early_close, |
557 | apr_pool_t *pool); |
558 | |
559 | /** |
560 | * Read and parse one delta window in svndiff format from the |
561 | * readable stream @a stream and place it in @a *window, allocating |
562 | * the result in @a pool. The caller must take responsibility for |
563 | * stripping off the four-byte 'SVN@<ver@>' header at the beginning of |
564 | * the svndiff document before reading the first window, and must |
565 | * provide the version number (the value of the fourth byte) to each |
566 | * invocation of this routine with the @a svndiff_version argument. |
567 | * |
568 | * @since New in 1.1. |
569 | */ |
570 | svn_error_t * |
571 | svn_txdelta_read_svndiff_window(svn_txdelta_window_t **window, |
572 | svn_stream_t *stream, |
573 | int svndiff_version, |
574 | apr_pool_t *pool); |
575 | |
576 | /** |
577 | * Read and skip one delta window in svndiff format from the |
578 | * file @a file. @a pool is used for temporary allocations. The |
579 | * caller must take responsibility for stripping off the four-byte |
580 | * 'SVN@<ver@>' header at the beginning of the svndiff document before |
581 | * reading or skipping the first window, and must provide the version |
582 | * number (the value of the fourth byte) to each invocation of this |
583 | * routine with the @a svndiff_version argument. |
584 | * |
585 | * @since New in 1.1. |
586 | */ |
587 | svn_error_t * |
588 | svn_txdelta_skip_svndiff_window(apr_file_t *file, |
589 | int svndiff_version, |
590 | apr_pool_t *pool); |
591 | |
592 | /** @} */ |
593 | |
594 | |
595 | /** Traversing tree deltas. |
596 | * |
597 | * In Subversion, we've got various producers and consumers of tree |
598 | * deltas. |
599 | * |
600 | * In processing a `commit' command: |
601 | * - The client examines its working copy data, and produces a tree |
602 | * delta describing the changes to be committed. |
603 | * - The client networking library consumes that delta, and sends them |
604 | * across the wire as an equivalent series of network requests (for |
605 | * example, to svnserve as an ra_svn protocol stream, or to an |
606 | * Apache httpd server as WebDAV commands) |
607 | * - The server receives those requests and produces a tree delta --- |
608 | * hopefully equivalent to the one the client produced above. |
609 | * - The Subversion server module consumes that delta and commits an |
610 | * appropriate transaction to the filesystem. |
611 | * |
612 | * In processing an `update' command, the process is reversed: |
613 | * - The Subversion server module talks to the filesystem and produces |
614 | * a tree delta describing the changes necessary to bring the |
615 | * client's working copy up to date. |
616 | * - The server consumes this delta, and assembles a reply |
617 | * representing the appropriate changes. |
618 | * - The client networking library receives that reply, and produces a |
619 | * tree delta --- hopefully equivalent to the one the Subversion |
620 | * server produced above. |
621 | * - The working copy library consumes that delta, and makes the |
622 | * appropriate changes to the working copy. |
623 | * |
624 | * The simplest approach would be to represent tree deltas using the |
625 | * obvious data structure. To do an update, the server would |
626 | * construct a delta structure, and the working copy library would |
627 | * apply that structure to the working copy; the network layer's job |
628 | * would simply be to get the structure across the net intact. |
629 | * |
630 | * However, we expect that these deltas will occasionally be too large |
631 | * to fit in a typical workstation's swap area. For example, in |
632 | * checking out a 200Mb source tree, the entire source tree is |
633 | * represented by a single tree delta. So it's important to handle |
634 | * deltas that are too large to fit in swap all at once. |
635 | * |
636 | * So instead of representing the tree delta explicitly, we define a |
637 | * standard way for a consumer to process each piece of a tree delta |
638 | * as soon as the producer creates it. The #svn_delta_editor_t |
639 | * structure is a set of callback functions to be defined by a delta |
640 | * consumer, and invoked by a delta producer. Each invocation of a |
641 | * callback function describes a piece of the delta --- a file's |
642 | * contents changing, something being renamed, etc. |
643 | * |
644 | * @defgroup svn_delta_tree_deltas Tree deltas |
645 | * @{ |
646 | */ |
647 | |
648 | /** A structure full of callback functions the delta source will invoke |
649 | * as it produces the delta. |
650 | * |
651 | * @note Don't try to allocate one of these yourself. Instead, always |
652 | * use svn_delta_default_editor() or some other constructor, to ensure |
653 | * that unused slots are filled in with no-op functions. |
654 | * |
655 | * <h3>Function Usage</h3> |
656 | * |
657 | * Here's how to use these functions to express a tree delta. |
658 | * |
659 | * The delta consumer implements the callback functions described in |
660 | * this structure, and the delta producer invokes them. So the |
661 | * caller (producer) is pushing tree delta data at the callee |
662 | * (consumer). |
663 | * |
664 | * At the start of traversal, the consumer provides @a edit_baton, a |
665 | * baton global to the entire delta edit. If there is a target |
666 | * revision that needs to be set for this operation, the producer |
667 | * should call the @c set_target_revision function at this point. |
668 | * |
669 | * Next, if there are any tree deltas to express, the producer should |
670 | * pass the @a edit_baton to the @c open_root function, to get a baton |
671 | * representing root of the tree being edited. |
672 | * |
673 | * Most of the callbacks work in the obvious way: |
674 | * |
675 | * @c delete_entry |
676 | * @c add_file |
677 | * @c add_directory |
678 | * @c open_file |
679 | * @c open_directory |
680 | * |
681 | * Each of these takes a directory baton, indicating the directory |
682 | * in which the change takes place, and a @a path argument, giving the |
683 | * path of the file, subdirectory, or directory entry to change. |
684 | * |
685 | * The @a path argument to each of the callbacks is relative to the |
686 | * root of the edit. Editors will usually want to join this relative |
687 | * path with some base stored in the edit baton (e.g. a URL, or a |
688 | * location in the OS filesystem). |
689 | * |
690 | * Since every call requires a parent directory baton, including |
691 | * @c add_directory and @c open_directory, where do we ever get our |
692 | * initial directory baton, to get things started? The @c open_root |
693 | * function returns a baton for the top directory of the change. In |
694 | * general, the producer needs to invoke the editor's @c open_root |
695 | * function before it can get anything of interest done. |
696 | * |
697 | * While @c open_root provides a directory baton for the root of |
698 | * the tree being changed, the @c add_directory and @c open_directory |
699 | * callbacks provide batons for other directories. Like the |
700 | * callbacks above, they take a @a parent_baton and a relative path |
701 | * @a path, and then return a new baton for the subdirectory being |
702 | * created / modified --- @a child_baton. The producer can then use |
703 | * @a child_baton to make further changes in that subdirectory. |
704 | * |
705 | * So, if we already have subdirectories named `foo' and `foo/bar', |
706 | * then the producer can create a new file named `foo/bar/baz.c' by |
707 | * calling: |
708 | * |
709 | * - @c open_root () --- yielding a baton @a root for the top directory |
710 | * |
711 | * - @c open_directory (@a root, "foo") --- yielding a baton @a f for `foo' |
712 | * |
713 | * - @c open_directory (@a f, "foo/bar") --- yielding a baton @a b for |
714 | * `foo/bar' |
715 | * |
716 | * - @c add_file (@a b, "foo/bar/baz.c") |
717 | * |
718 | * When the producer is finished making changes to a directory, it |
719 | * should call @c close_directory. This lets the consumer do any |
720 | * necessary cleanup, and free the baton's storage. |
721 | * |
722 | * The @c add_file and @c open_file callbacks each return a baton |
723 | * for the file being created or changed. This baton can then be |
724 | * passed to @c apply_textdelta to change the file's contents, or |
725 | * @c change_file_prop to change the file's properties. When the |
726 | * producer is finished making changes to a file, it should call |
727 | * @c close_file, to let the consumer clean up and free the baton. |
728 | * |
729 | * The @c add_file and @c add_directory functions each take arguments |
730 | * @a copyfrom_path and @a copyfrom_revision. If @a copyfrom_path is |
731 | * non-@c NULL, then @a copyfrom_path and @a copyfrom_revision indicate where |
732 | * the file or directory should be copied from (to create the file |
733 | * or directory being added). In that case, @a copyfrom_path must be |
734 | * either a path relative to the root of the edit, or a URI from the |
735 | * repository being edited. If @a copyfrom_path is @c NULL, then @a |
736 | * copyfrom_revision must be #SVN_INVALID_REVNUM; it is invalid to |
737 | * pass a mix of valid and invalid copyfrom arguments. |
738 | * |
739 | * |
740 | * <h3>Function Call Ordering</h3> |
741 | * |
742 | * There are six restrictions on the order in which the producer |
743 | * may use the batons: |
744 | * |
745 | * 1. The producer may call @c open_directory, @c add_directory, |
746 | * @c open_file, @c add_file at most once on any given directory |
747 | * entry. @c delete_entry may be called at most once on any given |
748 | * directory entry and may later be followed by @c add_directory or |
749 | * @c add_file on the same directory entry. @c delete_entry may |
750 | * not be called on any directory entry after @c open_directory, |
751 | * @c add_directory, @c open_file or @c add_file has been called on |
752 | * that directory entry. |
753 | * |
754 | * 2. The producer may not close a directory baton until it has |
755 | * closed all batons for its subdirectories. |
756 | * |
757 | * 3. When a producer calls @c open_directory or @c add_directory, |
758 | * it must specify the most recently opened of the currently open |
759 | * directory batons. Put another way, the producer cannot have |
760 | * two sibling directory batons open at the same time. |
761 | * |
762 | * 4. A producer must call @c change_dir_prop on a directory either |
763 | * before opening any of the directory's subdirs or after closing |
764 | * them, but not in the middle. |
765 | * |
766 | * 5. When the producer calls @c open_file or @c add_file, either: |
767 | * |
768 | * (a) The producer must follow with any changes to the file |
769 | * (@c change_file_prop and/or @c apply_textdelta, as applicable), |
770 | * followed by a @c close_file call, before issuing any other file |
771 | * or directory calls, or |
772 | * |
773 | * (b) The producer must follow with a @c change_file_prop call if |
774 | * it is applicable, before issuing any other file or directory |
775 | * calls; later, after all directory batons including the root |
776 | * have been closed, the producer must issue @c apply_textdelta |
777 | * and @c close_file calls. |
778 | * |
779 | * 6. When the producer calls @c apply_textdelta, it must make all of |
780 | * the window handler calls (including the @c NULL window at the |
781 | * end) before issuing any other #svn_delta_editor_t calls. |
782 | * |
783 | * So, the producer needs to use directory and file batons as if it |
784 | * is doing a single depth-first traversal of the tree, with the |
785 | * exception that the producer may keep file batons open in order to |
786 | * make @c apply_textdelta calls at the end. |
787 | * |
788 | * |
789 | * <h3>Pool Usage</h3> |
790 | * |
791 | * Many editor functions are invoked multiple times, in a sequence |
792 | * determined by the editor "driver". The driver is responsible for |
793 | * creating a pool for use on each iteration of the editor function, |
794 | * and clearing that pool between each iteration. The driver passes |
795 | * the appropriate pool on each function invocation. |
796 | * |
797 | * Based on the requirement of calling the editor functions in a |
798 | * depth-first style, it is usually customary for the driver to similarly |
799 | * nest the pools. However, this is only a safety feature to ensure |
800 | * that pools associated with deeper items are always cleared when the |
801 | * top-level items are also cleared. The interface does not assume, nor |
802 | * require, any particular organization of the pools passed to these |
803 | * functions. In fact, if "postfix deltas" are used for files, the file |
804 | * pools definitely need to live outside the scope of their parent |
805 | * directories' pools. |
806 | * |
807 | * Note that close_directory can be called *before* a file in that |
808 | * directory has been closed. That is, the directory's baton is |
809 | * closed before the file's baton. The implication is that |
810 | * @c apply_textdelta and @c close_file should not refer to a parent |
811 | * directory baton UNLESS the editor has taken precautions to |
812 | * allocate it in a pool of the appropriate lifetime (the @a dir_pool |
813 | * passed to @c open_directory and @c add_directory definitely does not |
814 | * have the proper lifetime). In general, it is recommended to simply |
815 | * avoid keeping a parent directory baton in a file baton. |
816 | * |
817 | * |
818 | * <h3>Errors</h3> |
819 | * |
820 | * At least one implementation of the editor interface is |
821 | * asynchronous; an error from one operation may be detected some |
822 | * number of operations later. As a result, an editor driver must not |
823 | * assume that an error from an editing function resulted from the |
824 | * particular operation being detected. Moreover, once an editing |
825 | * function (including @c close_edit) returns an error, the edit is |
826 | * dead; the only further operation which may be called on the editor |
827 | * is @c abort_edit. |
828 | */ |
829 | typedef struct svn_delta_editor_t |
830 | { |
831 | /** Set the target revision for this edit to @a target_revision. This |
832 | * call, if used, should precede all other editor calls. |
833 | * |
834 | * @note This is typically used only for server->client update-type |
835 | * operations. It doesn't really make much sense for commit-type |
836 | * operations, because the revision of a commit isn't known until |
837 | * the commit is finalized. |
838 | * |
839 | * Any temporary allocations may be performed in @a scratch_pool. |
840 | */ |
841 | svn_error_t *(*set_target_revision)(void *edit_baton, |
842 | svn_revnum_t target_revision, |
843 | apr_pool_t *scratch_pool); |
844 | |
845 | /** Set @a *root_baton to a baton for the top directory of the change. |
846 | * (This is the top of the subtree being changed, not necessarily |
847 | * the root of the filesystem.) As with any other directory baton, the |
848 | * producer should call @c close_directory on @a root_baton when done. |
849 | * And as with other @c open_* calls, the @a base_revision here is the |
850 | * current revision of the directory (before getting bumped up to the |
851 | * new target revision set with @c set_target_revision). |
852 | * |
853 | * Allocations for the returned @a root_baton should be performed in |
854 | * @a result_pool. It is also typical to (possibly) save this pool for |
855 | * later usage by @c close_directory. |
856 | */ |
857 | svn_error_t *(*open_root)(void *edit_baton, |
858 | svn_revnum_t base_revision, |
859 | apr_pool_t *result_pool, |
860 | void **root_baton); |
861 | |
862 | |
863 | /** Remove the directory entry at @a path, a child of the directory |
864 | * represented by @a parent_baton. If @a revision is a valid |
865 | * revision number, it is used as a sanity check to ensure that you |
866 | * are really removing the revision of @a path that you think you are. |
867 | * |
868 | * Any temporary allocations may be performed in @a scratch_pool. |
869 | * |
870 | * @note The @a revision parameter is typically used only for |
871 | * client->server commit-type operations, allowing the server to |
872 | * verify that it is deleting what the client thinks it should be |
873 | * deleting. It only really makes sense in the opposite direction |
874 | * (during server->client update-type operations) when the trees |
875 | * whose delta is being described are ancestrally related (that is, |
876 | * one tree is an ancestor of the other). |
877 | */ |
878 | svn_error_t *(*delete_entry)(const char *path, |
879 | svn_revnum_t revision, |
880 | void *parent_baton, |
881 | apr_pool_t *scratch_pool); |
882 | |
883 | |
884 | /** We are going to add a new subdirectory at @a path, a child of |
885 | * the directory represented by @a parent_baton. We will use |
886 | * the value this callback stores in @a *child_baton as the |
887 | * parent baton for further changes in the new subdirectory. |
888 | * |
889 | * If @a copyfrom_path is non-@c NULL, this add has history (i.e., is a |
890 | * copy), and the origin of the copy may be recorded as |
891 | * @a copyfrom_path under @a copyfrom_revision. |
892 | * |
893 | * Allocations for the returned @a child_baton should be performed in |
894 | * @a result_pool. It is also typical to (possibly) save this pool for |
895 | * later usage by @c close_directory. |
896 | */ |
897 | svn_error_t *(*add_directory)(const char *path, |
898 | void *parent_baton, |
899 | const char *copyfrom_path, |
900 | svn_revnum_t copyfrom_revision, |
901 | apr_pool_t *result_pool, |
902 | void **child_baton); |
903 | |
904 | /** We are going to make changes in the subdirectory at @a path, a |
905 | * child of the directory represented by @a parent_baton. |
906 | * The callback must store a value in @a *child_baton that |
907 | * should be used as the parent baton for subsequent changes in this |
908 | * subdirectory. If a valid revnum, @a base_revision is the current |
909 | * revision of the subdirectory. |
910 | * |
911 | * Allocations for the returned @a child_baton should be performed in |
912 | * @a result_pool. It is also typical to (possibly) save this pool for |
913 | * later usage by @c close_directory. |
914 | */ |
915 | svn_error_t *(*open_directory)(const char *path, |
916 | void *parent_baton, |
917 | svn_revnum_t base_revision, |
918 | apr_pool_t *result_pool, |
919 | void **child_baton); |
920 | |
921 | /** Change the value of a directory's property. |
922 | * - @a dir_baton specifies the directory whose property should change. |
923 | * - @a name is the name of the property to change. |
924 | * - @a value is the new (final) value of the property, or @c NULL if the |
925 | * property should be removed altogether. |
926 | * |
927 | * The callback is guaranteed to be called exactly once for each property |
928 | * whose value differs between the start and the end of the edit. |
929 | * |
930 | * Any temporary allocations may be performed in @a scratch_pool. |
931 | */ |
932 | svn_error_t *(*change_dir_prop)(void *dir_baton, |
933 | const char *name, |
934 | const svn_string_t *value, |
935 | apr_pool_t *scratch_pool); |
936 | |
937 | /** We are done processing a subdirectory, whose baton is @a dir_baton |
938 | * (set by @c add_directory or @c open_directory). We won't be using |
939 | * the baton any more, so whatever resources it refers to may now be |
940 | * freed. |
941 | * |
942 | * Any temporary allocations may be performed in @a scratch_pool. |
943 | */ |
944 | svn_error_t *(*close_directory)(void *dir_baton, |
945 | apr_pool_t *scratch_pool); |
946 | |
947 | |
948 | /** In the directory represented by @a parent_baton, indicate that |
949 | * @a path is present as a subdirectory in the edit source, but |
950 | * cannot be conveyed to the edit consumer. Currently, this would |
951 | * only occur because of authorization restrictions, but may change |
952 | * in the future. |
953 | * |
954 | * Any temporary allocations may be performed in @a scratch_pool. |
955 | */ |
956 | svn_error_t *(*absent_directory)(const char *path, |
957 | void *parent_baton, |
958 | apr_pool_t *scratch_pool); |
959 | |
960 | /** We are going to add a new file at @a path, a child of the |
961 | * directory represented by @a parent_baton. The callback can |
962 | * store a baton for this new file in @a **file_baton; whatever value |
963 | * it stores there should be passed through to @c apply_textdelta. |
964 | * |
965 | * If @a copyfrom_path is non-@c NULL, this add has history (i.e., is a |
966 | * copy), and the origin of the copy may be recorded as |
967 | * @a copyfrom_path under @a copyfrom_revision. |
968 | * |
969 | * Allocations for the returned @a file_baton should be performed in |
970 | * @a result_pool. It is also typical to save this pool for later usage |
971 | * by @c apply_textdelta and possibly @c close_file. |
972 | * |
973 | * @note Because the editor driver could be employing the "postfix |
974 | * deltas" paradigm, @a result_pool could potentially be relatively |
975 | * long-lived. Every file baton created by the editor for a given |
976 | * editor drive might be resident in memory similtaneously. Editor |
977 | * implementations should ideally keep their file batons as |
978 | * conservative (memory-usage-wise) as possible, and use @a result_pool |
979 | * only for those batons. (Consider using a subpool of @a result_pool |
980 | * for scratch work, destroying the subpool before exiting this |
981 | * function's implementation.) |
982 | */ |
983 | svn_error_t *(*add_file)(const char *path, |
984 | void *parent_baton, |
985 | const char *copyfrom_path, |
986 | svn_revnum_t copyfrom_revision, |
987 | apr_pool_t *result_pool, |
988 | void **file_baton); |
989 | |
990 | /** We are going to make changes to a file at @a path, a child of the |
991 | * directory represented by @a parent_baton. |
992 | * |
993 | * The callback can store a baton for this new file in @a **file_baton; |
994 | * whatever value it stores there should be passed through to |
995 | * @c apply_textdelta. If a valid revnum, @a base_revision is the |
996 | * current revision of the file. |
997 | * |
998 | * Allocations for the returned @a file_baton should be performed in |
999 | * @a result_pool. It is also typical to save this pool for later usage |
1000 | * by @c apply_textdelta and possibly @c close_file. |
1001 | * |
1002 | * @note See note about memory usage on @a add_file, which also |
1003 | * applies here. |
1004 | */ |
1005 | svn_error_t *(*open_file)(const char *path, |
1006 | void *parent_baton, |
1007 | svn_revnum_t base_revision, |
1008 | apr_pool_t *result_pool, |
1009 | void **file_baton); |
1010 | |
1011 | /** Apply a text delta, yielding the new revision of a file. |
1012 | * |
1013 | * @a file_baton indicates the file we're creating or updating, and the |
1014 | * ancestor file on which it is based; it is the baton set by some |
1015 | * prior @c add_file or @c open_file callback. |
1016 | * |
1017 | * The callback should set @a *handler to a text delta window |
1018 | * handler; we will then call @a *handler on successive text |
1019 | * delta windows as we receive them. The callback should set |
1020 | * @a *handler_baton to the value we should pass as the @a baton |
1021 | * argument to @a *handler. These values should be allocated within |
1022 | * @a result_pool. |
1023 | * |
1024 | * @a base_checksum is the hex MD5 digest for the base text against |
1025 | * which the delta is being applied; it is ignored if NULL, and may |
1026 | * be ignored even if not NULL. If it is not ignored, it must match |
1027 | * the checksum of the base text against which svndiff data is being |
1028 | * applied; if it does not, @c apply_textdelta or the @a *handler call |
1029 | * which detects the mismatch will return the error |
1030 | * SVN_ERR_CHECKSUM_MISMATCH (if there is no base text, there may |
1031 | * still be an error if @a base_checksum is neither NULL nor the hex |
1032 | * MD5 checksum of the empty string). |
1033 | */ |
1034 | svn_error_t *(*apply_textdelta)(void *file_baton, |
1035 | const char *base_checksum, |
1036 | apr_pool_t *result_pool, |
1037 | svn_txdelta_window_handler_t *handler, |
1038 | void **handler_baton); |
1039 | |
1040 | /** Change the value of a file's property. |
1041 | * - @a file_baton specifies the file whose property should change. |
1042 | * - @a name is the name of the property to change. |
1043 | * - @a value is the new (final) value of the property, or @c NULL if the |
1044 | * property should be removed altogether. |
1045 | * |
1046 | * The callback is guaranteed to be called exactly once for each property |
1047 | * whose value differs between the start and the end of the edit. |
1048 | * |
1049 | * Any temporary allocations may be performed in @a scratch_pool. |
1050 | */ |
1051 | svn_error_t *(*change_file_prop)(void *file_baton, |
1052 | const char *name, |
1053 | const svn_string_t *value, |
1054 | apr_pool_t *scratch_pool); |
1055 | |
1056 | /** We are done processing a file, whose baton is @a file_baton (set by |
1057 | * @c add_file or @c open_file). We won't be using the baton any |
1058 | * more, so whatever resources it refers to may now be freed. |
1059 | * |
1060 | * @a text_checksum is the hex MD5 digest for the fulltext that |
1061 | * resulted from a delta application, see @c apply_textdelta. The |
1062 | * checksum is ignored if NULL. If not null, it is compared to the |
1063 | * checksum of the new fulltext, and the error |
1064 | * SVN_ERR_CHECKSUM_MISMATCH is returned if they do not match. If |
1065 | * there is no new fulltext, @a text_checksum is ignored. |
1066 | * |
1067 | * Any temporary allocations may be performed in @a scratch_pool. |
1068 | */ |
1069 | svn_error_t *(*close_file)(void *file_baton, |
1070 | const char *text_checksum, |
1071 | apr_pool_t *scratch_pool); |
1072 | |
1073 | /** In the directory represented by @a parent_baton, indicate that |
1074 | * @a path is present as a file in the edit source, but cannot be |
1075 | * cannot be conveyed to the edit consumer. Currently, this would |
1076 | * only occur because of authorization restrictions, but may change |
1077 | * in the future. |
1078 | * |
1079 | * Any temporary allocations may be performed in @a scratch_pool. |
1080 | */ |
1081 | svn_error_t *(*absent_file)(const char *path, |
1082 | void *parent_baton, |
1083 | apr_pool_t *scratch_pool); |
1084 | |
1085 | /** All delta processing is done. Call this, with the @a edit_baton for |
1086 | * the entire edit. |
1087 | * |
1088 | * Any temporary allocations may be performed in @a scratch_pool. |
1089 | */ |
1090 | svn_error_t *(*close_edit)(void *edit_baton, |
1091 | apr_pool_t *scratch_pool); |
1092 | |
1093 | /** The editor-driver has decided to bail out. Allow the editor to |
1094 | * gracefully clean up things if it needs to. |
1095 | * |
1096 | * Any temporary allocations may be performed in @a scratch_pool. |
1097 | */ |
1098 | svn_error_t *(*abort_edit)(void *edit_baton, |
1099 | apr_pool_t *scratch_pool); |
1100 | |
1101 | /* Be sure to update svn_delta_get_cancellation_editor() and |
1102 | * svn_delta_default_editor() if you add a new callback here. */ |
1103 | } svn_delta_editor_t; |
1104 | |
1105 | |
1106 | /** Return a default delta editor template, allocated in @a pool. |
1107 | * |
1108 | * The editor functions in the template do only the most basic |
1109 | * baton-swapping: each editor function that produces a baton does so |
1110 | * by copying its incoming baton into the outgoing baton reference. |
1111 | * |
1112 | * This editor is not intended to be useful by itself, but is meant to |
1113 | * be the basis for a useful editor. After getting a default editor, |
1114 | * you substitute in your own implementations for the editor functions |
1115 | * you care about. The ones you don't care about, you don't have to |
1116 | * implement -- you can rely on the template's implementation to |
1117 | * safely do nothing of consequence. |
1118 | */ |
1119 | svn_delta_editor_t * |
1120 | svn_delta_default_editor(apr_pool_t *pool); |
1121 | |
1122 | /** A text-delta window handler which does nothing. |
1123 | * |
1124 | * Editors can return this handler from @c apply_textdelta if they don't |
1125 | * care about text delta windows. |
1126 | */ |
1127 | svn_error_t * |
1128 | svn_delta_noop_window_handler(svn_txdelta_window_t *window, |
1129 | void *baton); |
1130 | |
1131 | /** Set @a *editor and @a *edit_baton to a cancellation editor that |
1132 | * wraps @a wrapped_editor and @a wrapped_baton. |
1133 | * |
1134 | * The @a editor will call @a cancel_func with @a cancel_baton when each of |
1135 | * its functions is called, continuing on to call the corresponding wrapped |
1136 | * function if @a cancel_func returns #SVN_NO_ERROR. |
1137 | * |
1138 | * If @a cancel_func is @c NULL, set @a *editor to @a wrapped_editor and |
1139 | * @a *edit_baton to @a wrapped_baton. |
1140 | */ |
1141 | svn_error_t * |
1142 | svn_delta_get_cancellation_editor(svn_cancel_func_t cancel_func, |
1143 | void *cancel_baton, |
1144 | const svn_delta_editor_t *wrapped_editor, |
1145 | void *wrapped_baton, |
1146 | const svn_delta_editor_t **editor, |
1147 | void **edit_baton, |
1148 | apr_pool_t *pool); |
1149 | |
1150 | /** Set @a *editor and @a *edit_baton to an depth-based filtering |
1151 | * editor that wraps @a wrapped_editor and @a wrapped_baton. |
1152 | * |
1153 | * The @a editor will track the depth of this drive against the @a |
1154 | * requested_depth, taking into account whether not the edit drive is |
1155 | * making use of a target (via @a has_target), and forward editor |
1156 | * calls which operate "within" the request depth range through to @a |
1157 | * wrapped_editor. |
1158 | * |
1159 | * @a requested_depth must be one of the following depth values: |
1160 | * #svn_depth_infinity, #svn_depth_empty, #svn_depth_files, |
1161 | * #svn_depth_immediates, or #svn_depth_unknown. |
1162 | * |
1163 | * If filtering is deemed unnecessary (or if @a requested_depth is |
1164 | * #svn_depth_unknown), @a *editor and @a *edit_baton will be set to @a |
1165 | * wrapped_editor and @a wrapped_baton, respectively; otherwise, |
1166 | * they'll be set to new objects allocated from @a pool. |
1167 | * |
1168 | * @note Because the svn_delta_editor_t interface's @c delete_entry() |
1169 | * function doesn't carry node kind information, a depth-based |
1170 | * filtering editor being asked to filter for #svn_depth_files but |
1171 | * receiving a @c delete_entry() call on an immediate child of the |
1172 | * editor's target is unable to know if that deletion should be |
1173 | * allowed or filtered out -- a delete of a top-level file is okay in |
1174 | * this case, a delete of a top-level subdirectory is not. As such, |
1175 | * this filtering editor takes a conservative approach, and ignores |
1176 | * top-level deletion requests when filtering for #svn_depth_files. |
1177 | * Fortunately, most non-depth-aware (pre-1.5) Subversion editor |
1178 | * drivers can be told to drive non-recursively (where non-recursive |
1179 | * means essentially #svn_depth_files), which means they won't |
1180 | * transmit out-of-scope editor commands anyway. |
1181 | * |
1182 | * @since New in 1.5. |
1183 | */ |
1184 | svn_error_t * |
1185 | svn_delta_depth_filter_editor(const svn_delta_editor_t **editor, |
1186 | void **edit_baton, |
1187 | const svn_delta_editor_t *wrapped_editor, |
1188 | void *wrapped_edit_baton, |
1189 | svn_depth_t requested_depth, |
1190 | svn_boolean_t has_target, |
1191 | apr_pool_t *pool); |
1192 | |
1193 | /** @} */ |
1194 | |
1195 | |
1196 | /** Path-based editor drives. |
1197 | * |
1198 | * @defgroup svn_delta_path_delta_drivers Path-based delta drivers |
1199 | * @{ |
1200 | */ |
1201 | |
1202 | /** Callback function type for svn_delta_path_driver(). |
1203 | * |
1204 | * The handler of this callback is given the callback baton @a |
1205 | * callback_baton, @a path which is a relpath relative to the |
1206 | * root of the edit, and the @a parent_baton which represents |
1207 | * path's parent directory as created by the editor passed to |
1208 | * svn_delta_path_driver(). |
1209 | * |
1210 | * If @a path represents a directory, the handler must return a @a |
1211 | * *dir_baton for @a path, generated from the same editor (so that the |
1212 | * driver can later close that directory). |
1213 | * |
1214 | * If, however, @a path represents a file, the handler should NOT |
1215 | * return any file batons. It can close any opened or added files |
1216 | * immediately, or delay that close until the end of the edit when |
1217 | * svn_delta_path_driver() returns. |
1218 | * |
1219 | * Finally, if @a parent_baton is @c NULL, then the root of the edit |
1220 | * is also one of the paths passed to svn_delta_path_driver(). The |
1221 | * handler of this callback must call the editor's open_root() |
1222 | * function and return the top-level root dir baton in @a *dir_baton. |
1223 | */ |
1224 | typedef svn_error_t *(*svn_delta_path_driver_cb_func_t)( |
1225 | void **dir_baton, |
1226 | void *parent_baton, |
1227 | void *callback_baton, |
1228 | const char *path, |
1229 | apr_pool_t *pool); |
1230 | |
1231 | |
1232 | /** Drive @a editor (with its @a edit_baton) to visit each path in @a paths. |
1233 | * As each path is hit as part of the editor drive, use |
1234 | * @a callback_func and @a callback_baton to allow the caller to handle |
1235 | * the portion of the editor drive related to that path. |
1236 | * |
1237 | * Each path in @a paths is a (const char *) relpath, relative |
1238 | * to the root path of the @a edit. The editor drive will be |
1239 | * performed in the same order as @a paths. The paths should be sorted |
1240 | * using something like svn_sort_compare_paths to ensure that a depth-first |
1241 | * pattern is observed for directory/file baton creation. If @a sort_paths |
1242 | * is set, the function will sort the paths for you. Some callers may need |
1243 | * further customization of the order (ie. libsvn_delta/compat.c). |
1244 | * |
1245 | * Use @a scratch_pool for all necessary allocations. |
1246 | * |
1247 | * @since New in 1.8. |
1248 | */ |
1249 | svn_error_t * |
1250 | svn_delta_path_driver2(const svn_delta_editor_t *editor, |
1251 | void *edit_baton, |
1252 | const apr_array_header_t *paths, |
1253 | svn_boolean_t sort_paths, |
1254 | svn_delta_path_driver_cb_func_t callback_func, |
1255 | void *callback_baton, |
1256 | apr_pool_t *scratch_pool); |
1257 | |
1258 | |
1259 | /** Similar to svn_delta_path_driver2, but takes an (unused) revision, |
1260 | * and will sort the provided @a paths using svn_sort_compare_paths. |
1261 | * |
1262 | * @note In versions prior to 1.8, this function would modify the order |
1263 | * of elements in @a paths, despite the 'const' marker on the parameter. |
1264 | * This has been fixed in 1.8. |
1265 | * |
1266 | * @deprecated Provided for backward compatibility with the 1.7 API. |
1267 | */ |
1268 | SVN_DEPRECATED |
1269 | svn_error_t * |
1270 | svn_delta_path_driver(const svn_delta_editor_t *editor, |
1271 | void *edit_baton, |
1272 | svn_revnum_t revision, |
1273 | const apr_array_header_t *paths, |
1274 | svn_delta_path_driver_cb_func_t callback_func, |
1275 | void *callback_baton, |
1276 | apr_pool_t *scratch_pool); |
1277 | |
1278 | /** @} */ |
1279 | |
1280 | |
1281 | /*** File revision iterator types ***/ |
1282 | |
1283 | /** |
1284 | * The callback invoked by file rev loopers, such as |
1285 | * svn_ra_plugin_t.get_file_revs2() and svn_repos_get_file_revs2(). |
1286 | * |
1287 | * @a baton is provided by the caller, @a path is the pathname of the file |
1288 | * in revision @a rev and @a rev_props are the revision properties. |
1289 | * |
1290 | * If @a delta_handler and @a delta_baton are non-NULL, they may be set to a |
1291 | * handler/baton which will be called with the delta between the previous |
1292 | * revision and this one after the return of this callback. They may be |
1293 | * left as NULL/NULL. |
1294 | * |
1295 | * @a result_of_merge will be @c TRUE if the revision being returned was |
1296 | * included as the result of a merge. |
1297 | * |
1298 | * @a prop_diffs is an array of svn_prop_t elements indicating the property |
1299 | * delta for this and the previous revision. |
1300 | * |
1301 | * @a pool may be used for temporary allocations, but you can't rely |
1302 | * on objects allocated to live outside of this particular call and |
1303 | * the immediately following calls to @a *delta_handler if any. (Pass |
1304 | * in a pool via @a baton if need be.) |
1305 | * |
1306 | * @since New in 1.5. |
1307 | */ |
1308 | typedef svn_error_t *(*svn_file_rev_handler_t)( |
1309 | void *baton, |
1310 | const char *path, |
1311 | svn_revnum_t rev, |
1312 | apr_hash_t *rev_props, |
1313 | svn_boolean_t result_of_merge, |
1314 | svn_txdelta_window_handler_t *delta_handler, |
1315 | void **delta_baton, |
1316 | apr_array_header_t *prop_diffs, |
1317 | apr_pool_t *pool); |
1318 | |
1319 | /** |
1320 | * The old file rev handler interface. |
1321 | * |
1322 | * @note #svn_file_rev_handler_old_t is a placeholder type for both |
1323 | * #svn_repos_file_rev_handler_t and #svn_ra_file_rev_handler_t. It is |
1324 | * reproduced here for dependency reasons. |
1325 | * |
1326 | * @deprecated This type is provided for the svn_compat_wrap_file_rev_handler() |
1327 | * compatibility wrapper, and should not be used for new development. |
1328 | * @since New in 1.5. |
1329 | */ |
1330 | typedef svn_error_t *(*svn_file_rev_handler_old_t)( |
1331 | void *baton, |
1332 | const char *path, |
1333 | svn_revnum_t rev, |
1334 | apr_hash_t *rev_props, |
1335 | svn_txdelta_window_handler_t *delta_handler, |
1336 | void **delta_baton, |
1337 | apr_array_header_t *prop_diffs, |
1338 | apr_pool_t *pool); |
1339 | |
1340 | /** Return, in @a *handler2 and @a *handler2_baton a function/baton that |
1341 | * will call @a handler/@a handler_baton, allocating the @a *handler2_baton |
1342 | * in @a pool. |
1343 | * |
1344 | * @note This is used by compatibility wrappers, which exist in more than |
1345 | * Subversion core library. |
1346 | * |
1347 | * @note #svn_file_rev_handler_old_t is a placeholder type for both |
1348 | * #svn_repos_file_rev_handler_t and #svn_ra_file_rev_handler_t. It is |
1349 | * reproduced here for dependency reasons. |
1350 | * |
1351 | * @since New in 1.5. |
1352 | */ |
1353 | void |
1354 | svn_compat_wrap_file_rev_handler(svn_file_rev_handler_t *handler2, |
1355 | void **handler2_baton, |
1356 | svn_file_rev_handler_old_t handler, |
1357 | void *handler_baton, |
1358 | apr_pool_t *pool); |
1359 | |
1360 | /** @} end group: delta_support */ |
1361 | |
1362 | |
1363 | #ifdef __cplusplus |
1364 | } |
1365 | #endif /* __cplusplus */ |
1366 | |
1367 | #endif /* SVN_DELTA_H */ |
1368 | |