| /* |
| * svn_delta.h : structures related to delta-parsing |
| * |
| * ==================================================================== |
| * Copyright (c) 2000-2002 CollabNet. All rights reserved. |
| * |
| * This software is licensed as described in the file COPYING, which |
| * you should have received as part of this distribution. The terms |
| * are also available at http://subversion.tigris.org/license-1.html. |
| * If newer versions of this license are posted there, you may use a |
| * newer version instead, at your option. |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals. For exact contribution history, see the revision |
| * history and logs, available at http://subversion.tigris.org/. |
| * ==================================================================== |
| */ |
| |
| /* ==================================================================== */ |
| |
| |
| |
| #ifndef SVN_DELTA_H |
| #define SVN_DELTA_H |
| |
| #include <apr.h> |
| #include <apr_pools.h> |
| #include <apr_tables.h> |
| |
| #include "svn_types.h" |
| #include "svn_string.h" |
| #include "svn_error.h" |
| #include "svn_io.h" |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif /* __cplusplus */ |
| |
| |
| |
| /*** Text deltas. ***/ |
| |
| /* A text delta represents the difference between two strings of |
| bytes, the `source' string and the `target' string. Given a source |
| string and a target string, we can compute a text delta; given a |
| source string and a delta, we can reconstruct the target string. |
| However, note that deltas are not reversible: you cannot always |
| reconstruct the source string given the target string and delta. |
| |
| Since text deltas can be very large, the interface here allows us |
| to produce and consume them in pieces. Each piece, represented by |
| an `svn_txdelta_window_t' structure, describes how to produce the |
| next section of the target string. |
| |
| To compute a new text delta: |
| |
| - We call `svn_txdelta' on the strings we want to compare. That |
| returns us an `svn_txdelta_stream_t' object. |
| |
| - We then call `svn_txdelta_next_window' on the stream object |
| repeatedly. Each call returns a new `svn_txdelta_window_t' |
| object, which describes the next portion of the target string. |
| When `svn_txdelta_next_window' returns zero, we are done building |
| the target string. */ |
| |
| |
| /* An `svn_txdelta_window_t' object describes how to reconstruct a |
| contiguous section of the target string (the "target view") using a |
| specified contiguous region of the source string (the "source |
| view"). It contains a series of instructions which assemble the |
| new target string text by pulling together substrings from: |
| - the source view, |
| - the previously constructed portion of the target view, |
| - a string of new data contained within the window structure |
| |
| The source view must always slide forward from one window to the |
| next; that is, neither the beginning nor the end of the source view |
| may move to the left as we read from a window stream. This |
| property allows us to apply deltas to non-seekable source streams |
| without making a full copy of the source stream. */ |
| |
| enum svn_delta_action { |
| /* Append the LEN bytes at OFFSET in the source view to the |
| target. It must be the case that 0 <= OFFSET < OFFSET + LEN <= |
| size of source view. */ |
| svn_txdelta_source, |
| |
| /* Append the LEN bytes at OFFSET in the target view, to the |
| target. It must be the case that 0 <= OFFSET < current |
| position in the target view. |
| |
| However! OFFSET + LEN may be *beyond* the end of the existing |
| target data. "Where the heck does the text come from, then?" |
| If you start at OFFSET, and append LEN bytes one at a time, |
| it'll work out --- you're adding new bytes to the end at the |
| same rate you're reading them from the middle. Thus, if your |
| current target text is "abcdefgh", and you get an |
| `svn_delta_target' instruction whose OFFSET is 6 and whose LEN |
| is 7, the resulting string is "abcdefghghghghg". This trick is |
| actually useful in encoding long runs of consecutive |
| characters, long runs of CR/LF pairs, etc. */ |
| svn_txdelta_target, |
| |
| /* Append the LEN bytes at OFFSET in the window's NEW string to |
| the target. It must be the case that 0 <= OFFSET < OFFSET + |
| LEN <= length of NEW. Windows MUST use new data in ascending |
| order with no overlap at the moment; svn_txdelta_to_svndiff |
| depends on this. */ |
| svn_txdelta_new |
| }; |
| |
| /* A single text delta instruction. */ |
| typedef struct svn_txdelta_op_t { |
| enum svn_delta_action action_code; |
| apr_off_t offset; |
| apr_off_t length; |
| } svn_txdelta_op_t; |
| |
| |
| /* How to produce the next stretch of the target string. */ |
| typedef struct svn_txdelta_window_t { |
| |
| /* The offset and length of the source view for this window. */ |
| apr_off_t sview_offset; |
| apr_size_t sview_len; |
| |
| /* The length of the target view for this window, i.e. the number of |
| * bytes which will be reconstructed by the instruction stream. */ |
| apr_size_t tview_len; |
| |
| /* The number of instructions in this window. */ |
| int num_ops; |
| |
| /* The instructions for this window. */ |
| const svn_txdelta_op_t *ops; |
| |
| /* New data, for use by any `svn_delta_new' instructions. */ |
| const svn_string_t *new_data; |
| |
| } svn_txdelta_window_t; |
| |
| |
| /* A typedef for functions that consume a series of delta windows, for |
| use in caller-pushes interfaces. Such functions will typically |
| apply the delta windows to produce some file, or save the windows |
| somewhere. At the end of the delta window stream, you must call |
| this function passing zero for the WINDOW argument. */ |
| typedef svn_error_t * (*svn_txdelta_window_handler_t) |
| (svn_txdelta_window_t *window, void *baton); |
| |
| |
| /* A delta stream --- this is the hat from which we pull a series of |
| svn_txdelta_window_t objects, which, taken in order, describe the |
| entire target string. This type is defined within libsvn_delta, and |
| opaque outside that library. */ |
| typedef struct svn_txdelta_stream_t svn_txdelta_stream_t; |
| |
| |
| /* Set *WINDOW to a pointer to the next window from the delta stream |
| STREAM. When we have completely reconstructed the target string, |
| set *WINDOW to zero. |
| |
| The window will be allocated in POOL. */ |
| svn_error_t *svn_txdelta_next_window (svn_txdelta_window_t **window, |
| svn_txdelta_stream_t *stream, |
| apr_pool_t *pool); |
| |
| |
| /* Return the MD5 digest for the complete fulltext deltified by |
| STREAM, or NULL if STREAM has not yet returned its final NULL |
| window. The digest is allocated in the same memory as STREAM. */ |
| const unsigned char *svn_txdelta_md5_digest (svn_txdelta_stream_t *stream); |
| |
| /* Set *STREAM to a pointer to a delta stream that will turn the byte |
| string from SOURCE into the byte stream from TARGET. |
| |
| SOURCE and TARGET are both readable generic streams. When we call |
| `svn_txdelta_next_window' on *STREAM, it will read from SOURCE and |
| TARGET to gather as much data as it needs. |
| |
| Do any necessary allocation in a sub-pool of POOL. */ |
| void svn_txdelta (svn_txdelta_stream_t **stream, |
| svn_stream_t *source, |
| svn_stream_t *target, |
| apr_pool_t *pool); |
| |
| |
| /* Send the contents of STRING to window-handler HANDLER/BATON. This is |
| effectively a 'copy' operation, resulting in delta windows that make |
| the target equivalent to the value of STRING. |
| |
| All temporary allocation is performed in POOL. |
| */ |
| svn_error_t *svn_txdelta_send_string (const svn_string_t *string, |
| svn_txdelta_window_handler_t handler, |
| void *handler_baton, |
| apr_pool_t *pool); |
| |
| /* Send the contents of STREAM to window-handler HANDLER/BATON. This is |
| effectively a 'copy' operation, resulting in delta windows that make |
| the target equivalent to the stream. |
| |
| All temporary allocation is performed in POOL. |
| */ |
| svn_error_t *svn_txdelta_send_stream (svn_stream_t *stream, |
| svn_txdelta_window_handler_t handler, |
| void *handler_baton, |
| apr_pool_t *pool); |
| |
| /* Send the contents of TXSTREAM to window-handler HANDLER/BATON. Windows |
| will be extracted from the stream and delivered to the handler. |
| |
| All temporary allocation is performed in POOL. |
| */ |
| svn_error_t *svn_txdelta_send_txstream (svn_txdelta_stream_t *txstream, |
| svn_txdelta_window_handler_t handler, |
| void *handler_baton, |
| apr_pool_t *pool); |
| |
| |
| /* Prepare to apply a text delta. SOURCE is a readable generic stream |
| yielding the source data, TARGET is a writable generic stream to |
| write target data to, and allocation takes place in a sub-pool of |
| POOL. On return, *HANDLER is set to a window handler function and |
| *HANDLER_BATON is set to the value to pass as the BATON argument to |
| *HANDLER. */ |
| void svn_txdelta_apply (svn_stream_t *source, |
| svn_stream_t *target, |
| apr_pool_t *pool, |
| svn_txdelta_window_handler_t *handler, |
| void **handler_baton); |
| |
| |
| |
| /*** Producing and consuming svndiff-format text deltas. ***/ |
| |
| /* Prepare to produce an svndiff-format diff from text delta windows. |
| OUTPUT is a writable generic stream to write the svndiff data to. |
| Allocation takes place in a sub-pool of POOL. On return, *HANDLER |
| is set to a window handler function and *HANDLER_BATON is set to |
| the value to pass as the BATON argument to *HANDLER. */ |
| void svn_txdelta_to_svndiff (svn_stream_t *output, |
| apr_pool_t *pool, |
| svn_txdelta_window_handler_t *handler, |
| void **handler_baton); |
| |
| /* Return a writable generic stream which will parse svndiff-format |
| data into a text delta, invoking HANDLER with HANDLER_BATON |
| whenever a new window is ready. If ERROR_ON_EARLY_CLOSE is TRUE, |
| attempting to close this stream before it has handled the entire |
| svndiff data set will result in SVN_ERR_SVNDIFF_UNEXPECTED_END, |
| else this error condition will be ignored. */ |
| svn_stream_t *svn_txdelta_parse_svndiff (svn_txdelta_window_handler_t handler, |
| void *handler_baton, |
| svn_boolean_t error_on_early_close, |
| apr_pool_t *pool); |
| |
| |
| |
| /*** Traversing tree deltas. ***/ |
| |
| |
| /* In Subversion, we've got various producers and consumers of tree |
| deltas. |
| |
| In processing a `commit' command: |
| - The client examines its working copy data, and produces a tree |
| delta describing the changes to be committed. |
| - The client networking library consumes that delta, and sends them |
| across the wire as an equivalent series of WebDAV requests. |
| - The Apache WebDAV module receives those requests and produces a |
| tree delta --- hopefully equivalent to the one the client |
| produced above. |
| - The Subversion server module consumes that delta and commits an |
| appropriate transaction to the filesystem. |
| |
| In processing an `update' command, the process is reversed: |
| - The Subversion server module talks to the filesystem and produces |
| a tree delta describing the changes necessary to bring the |
| client's working copy up to date. |
| - The Apache WebDAV module consumes this delta, and assembles a |
| WebDAV reply representing the appropriate changes. |
| - The client networking library receives that WebDAV reply, and |
| produces a tree delta --- hopefully equivalent to the one the |
| Subversion server produced above. |
| - The working copy library consumes that delta, and makes the |
| appropriate changes to the working copy. |
| |
| The simplest approach would be to represent tree deltas using the |
| obvious data structure. To do an update, the server would |
| construct a delta structure, and the working copy library would |
| apply that structure to the working copy; WebDAV's job would simply |
| be to get the structure across the net intact. |
| |
| However, we expect that these deltas will occasionally be too large |
| to fit in a typical workstation's swap area. For example, in |
| checking out a 200Mb source tree, the entire source tree is |
| represented by a single tree delta. So it's important to handle |
| deltas that are too large to fit in swap all at once. |
| |
| So instead of representing the tree delta explicitly, we define a |
| standard way for a consumer to process each piece of a tree delta |
| as soon as the producer creates it. The `svn_delta_edit_fns_t' |
| structure is a set of callback functions to be defined by a delta |
| consumer, and invoked by a delta producer. Each invocation of a |
| callback function describes a piece of the delta --- a file's |
| contents changing, something being renamed, etc. */ |
| |
| /* A structure full of callback functions the delta source will invoke |
| as it produces the delta. */ |
| typedef struct |
| { |
| /* |
| FUNCTION USAGE |
| |
| Here's how to use these functions to express a tree delta. |
| |
| The delta consumer implements the callback functions described in |
| this structure, and the delta producer invokes them. So the |
| caller (producer) is pushing tree delta data at the callee |
| (consumer). |
| |
| At the start of traversal, the consumer provides EDIT_BATON, a |
| baton global to the entire delta edit. In the case of |
| `svn_xml_parse', this would be the EDIT_BATON argument; other |
| producers will work differently. If there is a target revision |
| that needs to be set for this operation, the producer should |
| called the 'set_target_revision' function at this point. Next, |
| the producer should pass this EDIT_BATON to the `open_root' |
| function, to get a baton representing root of the tree being |
| edited. |
| |
| Most of the callbacks work in the obvious way: |
| |
| delete_entry |
| add_file add_directory |
| open_file open_directory |
| |
| Each of these takes a directory baton, indicating the directory |
| in which the change takes place, and a PATH argument, giving the |
| path (relative to the root of the edit) of the file, |
| subdirectory, or directory entry to change. Editors will usually |
| want to join this relative path with some base stored in the edit |
| baton (e.g. a URL, a location in the OS filesystem). |
| |
| Since every call requires a parent directory baton, including |
| add_directory and open_directory, where do we ever get our |
| initial directory baton, to get things started? The `open_root' |
| function returns a baton for the top directory of the change. In |
| general, the producer needs to invoke the editor's `open_root' |
| function before it can get anything of interest done. |
| |
| While `open_root' provides a directory baton for the root of |
| the tree being changed, the `add_directory' and `open_directory' |
| callbacks provide batons for other directories. Like the |
| callbacks above, they take a PARENT_BATON and a relative path |
| PATH, and then return a new baton for the subdirectory being |
| created / modified --- CHILD_BATON. The producer can then use |
| CHILD_BATON to make further changes in that subdirectory. |
| |
| So, if we already have subdirectories named `foo' and `foo/bar', |
| then the producer can create a new file named `foo/bar/baz.c' by |
| calling: |
| open_root () --- yielding a baton ROOT for the top directory |
| open_directory (ROOT, "foo") --- yielding a baton F for `foo' |
| open_directory (F, "foo/bar") --- yielding a baton B for `foo/bar' |
| add_file (B, "foo/bar/baz.c") |
| |
| When the producer is finished making changes to a directory, it |
| should call `close_directory'. This lets the consumer do any |
| necessary cleanup, and free the baton's storage. |
| |
| The `add_file' and `open_file' callbacks each return a baton |
| for the file being created or changed. This baton can then be |
| passed to `apply_textdelta' to change the file's contents, or |
| `change_file_prop' to change the file's properties. When the |
| producer is finished making changes to a file, it should call |
| `close_file', to let the consumer clean up and free the baton. |
| |
| The `add_file' and `add_directory' functions each take arguments |
| COPYFROM_PATH and COPYFROM_REVISION. If COPYFROM_PATH is |
| non-NULL, then COPYFROM_PATH and COPYFROM_REVISION indicate where |
| the file or directory should be copied from (to create the file |
| or directory being added). |
| |
| |
| FUNCTION CALL ORDERING |
| |
| There are six restrictions on the order in which the producer |
| may use the batons: |
| |
| 1. The producer may call `open_directory', `add_directory', |
| `open_file', `add_file', or `delete_entry' at most once on |
| any given directory entry. |
| |
| 2. The producer may not close a directory baton until it has |
| closed all batons for its subdirectories. |
| |
| 3. When a producer calls `open_directory' or `add_directory', |
| it must specify the most recently opened of the currently open |
| directory batons. Put another way, the producer cannot have |
| two sibling directory batons open at the same time. |
| |
| 4. A producer must call `change_dir_prop' on a directory either |
| before opening any of the directory's subdirs or after closing |
| them, but not in the middle. |
| |
| 5. When the producer calls `open_file' or `add_file', either: |
| |
| (a) The producer must follow with the changes to the file |
| (`change_file_prop' and/or `apply_textdelta', as applicable) |
| followed by a `close_file' call, before issuing any other file |
| or directory calls, or |
| |
| (b) The producer must follow with a `change_file_prop' call if |
| it is applicable, before issuing any other file or directory |
| calls; later, after all directory batons including the root |
| have been closed, the producer must issue `apply_textdelta' |
| and `close_file' calls. |
| |
| 6. When the producer calls `apply_textdelta', it must make all of |
| the window handler calls (including the NULL window at the |
| end) before issuing any other svn_delta_editor_t calls. |
| |
| So, the producer needs to use directory and file batons as if it |
| is doing a single depth-first traversal of the tree, with the |
| exception that the producer may keep file batons open in order to |
| make apply_textdelta calls at the end. |
| |
| These restrictions make it easier to write a consumer that |
| generates an XML-style tree delta. An XML tree delta mentions |
| each directory once, and includes all the changes to that |
| directory within the <directory> element. However, it does allow |
| text deltas to appear at the end. |
| |
| |
| POOL USAGE |
| |
| Many editor functions are invoked multiple times, in a sequence |
| determined by the editor "driver". The driver is responsible for |
| creating a pool for use on each iteration of the editor function, |
| and clearing that pool between each iteration. The driver passes |
| the appropriate pool on each function invocation. These "iterative" |
| functions are: |
| |
| open_directory open_file |
| add_directory add_file |
| change_dir_prop change_file_prop |
| delete_entry |
| |
| Based on the requirement of calling the editor functions in a |
| depth-first style, it is usually customary for the driver to similar |
| nest the pools. However, this is only a safety feature to ensure |
| that pools associated with deeper items are always cleared when the |
| top-level items are also cleared. The interface does not assume, nor |
| require, any particular organization of the pools passed to these |
| functions. In fact, if "postfix deltas" are used for files, the file |
| pools definitely need to live outside the scope of their parent |
| directories' pools. |
| |
| Some of the editor functions are called just once, so this interface |
| simplifies their signatures by removing a pool argument. It is |
| assumed that a pool is reachable through a baton for these functions |
| to perform their work. These functions, and pools they will |
| typically use are: |
| |
| set_target_revision EDIT_BATON holds a pool |
| close_directory DIR_BATON holds a pool, and should be |
| the DIR_POOL passed to the function |
| which created DIR_BATON (open_root, |
| open_directory, or add_directory) |
| apply_textdelta FILE_BATON holds a pool, and should be |
| the FILE_POOL passed to the function |
| which created FILE_BATON (open_file |
| or add_File) |
| close_file FILE_BATON holds a pool, and should be |
| the FILE_POOL passed to the function |
| which created FILE_BATON (open_file |
| or add_File) |
| close_edit EDIT_BATON holds a pool |
| abort_edit EDIT_BATON holds a pool |
| |
| Note that close_directory can be called *before* a file in that |
| directory has been closed. That is, the directory's baton is |
| closed before the file's baton. The implication is that |
| apply_textdelta() and close_file() should not refer to a parent |
| directory baton UNLESS the editor has taken precautions to |
| allocate it in a pool of the appropriate lifetime (the DIR_POOL |
| passed to open_directory and add_directory definitely does not |
| have the proper lifetime). In general, it is recommended to simply |
| avoid keeping a parent directory baton in a file baton. |
| */ |
| |
| /* Set the target revision for this edit to TARGET_REVISION. This |
| call, if used, should precede all other editor calls. */ |
| svn_error_t *(*set_target_revision) (void *edit_baton, |
| svn_revnum_t target_revision); |
| |
| /* Set *ROOT_BATON to a baton for the top directory of the change. |
| (This is the top of the subtree being changed, not necessarily |
| the root of the filesystem.) Like any other directory baton, the |
| producer should call `close_directory' on ROOT_BATON when they're |
| done. And like other open_* calls, the BASE_REVISION here is |
| the current revision of the directory (before getting bumped up |
| to the new target revision set with set_target_revision). |
| |
| Allocations for the returned ROOT_BATON should be performed in |
| DIR_POOL. It is also typical to (possibly) save this pool for later |
| usage by close_directory. */ |
| svn_error_t *(*open_root) (void *edit_baton, |
| svn_revnum_t base_revision, |
| apr_pool_t *dir_pool, |
| void **root_baton); |
| |
| |
| /* Deleting things. */ |
| |
| /* Remove the directory entry named PATH, a child of the directory |
| represented by PARENT_BATON. REVISION is used as a sanity check |
| to ensure that you are removing the revision of PATH that you |
| really think you are. |
| |
| All allocations should be performed in POOL. */ |
| svn_error_t *(*delete_entry) (const char *path, |
| svn_revnum_t revision, |
| void *parent_baton, |
| apr_pool_t *pool); |
| |
| |
| /* Creating and modifying directories. */ |
| |
| /* We are going to add a new subdirectory named PATH. We will use |
| the value this callback stores in *CHILD_BATON as the |
| PARENT_BATON for further changes in the new subdirectory. |
| |
| If COPYFROM_PATH is non-NULL, this add has history (i.e., is a |
| copy), and the origin of the copy may be recorded as |
| COPYFROM_PATH under COPYFROM_REVISION. |
| |
| Allocations for the returned CHILD_BATON should be performed in |
| DIR_POOL. It is also typical to (possibly) save this pool for later |
| usage by close_directory. */ |
| svn_error_t *(*add_directory) (const char *path, |
| void *parent_baton, |
| const char *copyfrom_path, |
| svn_revnum_t copyfrom_revision, |
| apr_pool_t *dir_pool, |
| void **child_baton); |
| |
| /* We are going to make changes in a subdirectory (of the directory |
| identified by PARENT_BATON). The subdirectory is specified by |
| PATH. The callback must store a value in *CHILD_BATON that should |
| be used as the PARENT_BATON for subsequent changes in this |
| subdirectory. BASE_REVISION is the current revision of the |
| subdirectory. |
| |
| Allocations for the returned CHILD_BATON should be performed in |
| DIR_POOL. It is also typical to (possibly) save this pool for later |
| usage by close_directory. */ |
| svn_error_t *(*open_directory) (const char *path, |
| void *parent_baton, |
| svn_revnum_t base_revision, |
| apr_pool_t *dir_pool, |
| void **child_baton); |
| |
| /* Change the value of a directory's property. |
| - DIR_BATON specifies the directory whose property should change. |
| - NAME is the name of the property to change. |
| - VALUE is the new value of the property, or NULL if the property |
| should be removed altogether. |
| |
| All allocations should be performed in POOL. */ |
| svn_error_t *(*change_dir_prop) (void *dir_baton, |
| const char *name, |
| const svn_string_t *value, |
| apr_pool_t *pool); |
| |
| /* We are done processing a subdirectory, whose baton is DIR_BATON |
| (set by add_directory or open_directory). We won't be using |
| the baton any more, so whatever resources it refers to may now be |
| freed. */ |
| svn_error_t *(*close_directory) (void *dir_baton); |
| |
| |
| /* Creating and modifying files. */ |
| |
| /* We are going to add a new file named PATH. The callback can |
| store a baton for this new file in **FILE_BATON; whatever value |
| it stores there should be passed through to apply_textdelta |
| and/or apply_propdelta. |
| |
| If COPYFROM_PATH is non-NULL, this add has history (i.e., is a |
| copy), and the origin of the copy may be recorded as |
| COPYFROM_PATH under COPYFROM_REVISION. |
| |
| Allocations for the returned FILE_BATON should be performed in |
| FILE_POOL. It is also typical to save this pool for later usage |
| by apply_textdelta and possibly close_file. */ |
| svn_error_t *(*add_file) (const char *path, |
| void *parent_baton, |
| const char *copy_path, |
| svn_revnum_t copy_revision, |
| apr_pool_t *file_pool, |
| void **file_baton); |
| |
| /* We are going to make change to a file named PATH, which resides |
| in the directory identified by PARENT_BATON. |
| |
| The callback can store a baton for this new file in **FILE_BATON; |
| whatever value it stores there should be passed through to |
| apply_textdelta and/or apply_propdelta. This file has a current |
| revision of BASE_REVISION. |
| |
| Allocations for the returned FILE_BATON should be performed in |
| FILE_POOL. It is also typical to save this pool for later usage |
| by apply_textdelta and possibly close_file. */ |
| svn_error_t *(*open_file) (const char *path, |
| void *parent_baton, |
| svn_revnum_t base_revision, |
| apr_pool_t *file_pool, |
| void **file_baton); |
| |
| /* Apply a text delta, yielding the new revision of a file. |
| |
| FILE_BATON indicates the file we're creating or updating, and the |
| ancestor file on which it is based; it is the baton set by some |
| prior `add_file' or `open_file' callback. |
| |
| The callback should set *HANDLER to a text delta window |
| handler; we will then call *HANDLER on successive text |
| delta windows as we receive them. The callback should set |
| *HANDLER_BATON to the value we should pass as the BATON |
| argument to *HANDLER. |
| |
| If *HANDLER is set to NULL, then the editor is indicating to the |
| driver that it is not interested in receiving information about |
| the changes in this file. The driver can use this information to |
| avoid computing changes. Note that the editor knows the change |
| has occurred (by virtue of this function being invoked), but is |
| simply indicating that it doesn't want the details. */ |
| svn_error_t *(*apply_textdelta) (void *file_baton, |
| svn_txdelta_window_handler_t *handler, |
| void **handler_baton); |
| |
| /* Change the value of a file's property. |
| - FILE_BATON specifies the file whose property should change. |
| - NAME is the name of the property to change. |
| - VALUE is the new value of the property, or NULL if the property |
| should be removed altogether. |
| |
| All allocations should be performed in POOL. */ |
| svn_error_t *(*change_file_prop) (void *file_baton, |
| const char *name, |
| const svn_string_t *value, |
| apr_pool_t *pool); |
| |
| /* We are done processing a file, whose baton is FILE_BATON (set by |
| `add_file' or `open_file'). We won't be using the baton any |
| more, so whatever resources it refers to may now be freed. */ |
| svn_error_t *(*close_file) (void *file_baton); |
| |
| /* All delta processing is done. Call this, with the EDIT_BATON for |
| the entire edit. */ |
| svn_error_t *(*close_edit) (void *edit_baton); |
| |
| /* The editor-driver has decided to bail out. Allow the editor to |
| gracefully clean up things if it needs to. */ |
| svn_error_t *(*abort_edit) (void *edit_baton); |
| |
| } svn_delta_editor_t; |
| |
| |
| |
| /* ### This structure is deprecated. It is the old format of the |
| ### svn_delta_editor_t interface. */ |
| typedef struct svn_delta_edit_fns_t |
| { |
| svn_error_t *(*set_target_revision) (void *edit_baton, |
| svn_revnum_t target_revision); |
| svn_error_t *(*open_root) (void *edit_baton, |
| svn_revnum_t base_revision, |
| void **root_baton); |
| svn_error_t *(*delete_entry) (svn_stringbuf_t *name, |
| svn_revnum_t revision, |
| void *parent_baton); |
| svn_error_t *(*add_directory) (svn_stringbuf_t *name, |
| void *parent_baton, |
| svn_stringbuf_t *copyfrom_path, |
| svn_revnum_t copyfrom_revision, |
| void **child_baton); |
| svn_error_t *(*open_directory) (svn_stringbuf_t *name, |
| void *parent_baton, |
| svn_revnum_t base_revision, |
| void **child_baton); |
| svn_error_t *(*change_dir_prop) (void *dir_baton, |
| svn_stringbuf_t *name, |
| svn_stringbuf_t *value); |
| svn_error_t *(*close_directory) (void *dir_baton); |
| svn_error_t *(*add_file) (svn_stringbuf_t *name, |
| void *parent_baton, |
| svn_stringbuf_t *copy_path, |
| svn_revnum_t copy_revision, |
| void **file_baton); |
| svn_error_t *(*open_file) (svn_stringbuf_t *name, |
| void *parent_baton, |
| svn_revnum_t base_revision, |
| void **file_baton); |
| svn_error_t *(*apply_textdelta) (void *file_baton, |
| svn_txdelta_window_handler_t *handler, |
| void **handler_baton); |
| svn_error_t *(*change_file_prop) (void *file_baton, |
| svn_stringbuf_t *name, |
| svn_stringbuf_t *value); |
| svn_error_t *(*close_file) (void *file_baton); |
| svn_error_t *(*close_edit) (void *edit_baton); |
| svn_error_t *(*abort_edit) (void *edit_baton); |
| |
| } svn_delta_edit_fns_t; |
| |
| /* ### temporary function for wrapping an svn_delta_editor_t interface |
| ### into the old-form svn_delta_edit_fns_t interface. this wrapping |
| ### function enables an old-style editor driver to drive a new-style |
| ### editor. */ |
| void svn_delta_compat_wrap (const svn_delta_edit_fns_t **wrapper_editor, |
| void **wrapper_baton, |
| const svn_delta_editor_t *editor, |
| void *edit_baton, |
| apr_pool_t *pool); |
| |
| |
| /* Return a default delta editor template, allocated in POOL. |
| * |
| * The editor functions in the template do only the most basic |
| * baton-swapping: each editor function that produces a baton does so |
| * by copying its incoming baton into the outgoing baton reference. |
| * |
| * This editor is not intended to be useful by itself, but is meant to |
| * be the basis for a useful editor. After getting a default editor, |
| * you substitute in your own implementations for the editor functions |
| * you care about. The ones you don't care about, you don't have to |
| * implement -- you can rely on the template's implementation to |
| * safely do nothing of consequence. |
| */ |
| svn_delta_editor_t *svn_delta_default_editor (apr_pool_t *pool); |
| |
| /* ### create a default editor for the old-style editor */ |
| svn_delta_edit_fns_t *svn_delta_old_default_editor (apr_pool_t *pool); |
| |
| |
| |
| /* Compose EDITOR_1 and its baton with EDITOR_2 and its baton. |
| * |
| * Returns a new editor in E which each function FUN calls |
| * EDITOR_1->FUN and then EDITOR_2->FUN, with the corresponding batons. |
| * |
| * If EDITOR_1->FUN returns error, that error is returned from E->FUN |
| * and EDITOR_2->FUN is never called; otherwise E->FUN's return value |
| * is the same as EDITOR_2->FUN's. |
| * |
| * If an editor function is null, it is simply never called, and this |
| * is not an error. |
| */ |
| void |
| svn_delta_compose_editors (const svn_delta_editor_t **new_editor, |
| void **new_edit_baton, |
| const svn_delta_editor_t *editor_1, |
| void *edit_baton_1, |
| const svn_delta_editor_t *editor_2, |
| void *edit_baton_2, |
| apr_pool_t *pool); |
| |
| |
| /* Compose BEFORE_EDITOR, BEFORE_EDIT_BATON with MIDDLE_EDITOR, |
| * MIDDLE_EDIT_BATON, then compose the result with AFTER_EDITOR, |
| * AFTER_EDIT_BATON, all according to the conventions of |
| * svn_delta_compose_old_editors(). Return the resulting editor in |
| * *NEW_EDITOR, *NEW_EDIT_BATON. |
| * |
| * If either BEFORE_EDITOR or AFTER_EDITOR is null, that editor will |
| * simply not be included in the composition. It is advised, though |
| * not required, that a null editor pair with a null baton, and a |
| * non-null editor with a non-null baton. |
| * |
| * MIDDLE_EDITOR must not be null. I'm not going to tell you what |
| * happens if it is. |
| */ |
| void svn_delta_wrap_editor (const svn_delta_editor_t **new_editor, |
| void **new_edit_baton, |
| const svn_delta_editor_t *before_editor, |
| void *before_edit_baton, |
| const svn_delta_editor_t *middle_editor, |
| void *middle_edit_baton, |
| const svn_delta_editor_t *after_editor, |
| void *after_edit_baton, |
| apr_pool_t *pool); |
| |
| |
| /* These public structures are for use in customizing a 'pipe' editor; |
| see svn_delta_pipe_editor() below. */ |
| |
| struct svn_pipe_edit_baton |
| { |
| /* This is the "real" editor/baton, the one which we are wrapping. */ |
| const svn_delta_edit_fns_t *real_editor; |
| void *real_edit_baton; |
| |
| /* Pool for all baton usage henceforth. */ |
| apr_pool_t *pool; |
| |
| /* A template field that can be altered in specific instances of |
| this pipe-editor. */ |
| void *my_baton; |
| }; |
| |
| |
| struct svn_pipe_dir_baton |
| { |
| /* Pointers to parent baton and edit baton. */ |
| struct svn_pipe_edit_baton *edit_baton; |
| struct svn_pipe_dir_baton *parent_dir_baton; |
| |
| /* This is the "real" directory baton that we're wrapping. */ |
| void *real_dir_baton; |
| |
| /* A template field that can be altered in specific instances of |
| this pipe-editor. */ |
| void *my_baton; |
| }; |
| |
| |
| struct svn_pipe_file_baton |
| { |
| /* Pointer to parent. */ |
| struct svn_pipe_dir_baton *dir_baton; |
| |
| /* This is the "real" file baton that we're wrapping. */ |
| void *real_file_baton; |
| |
| /* A template field that can be altered in specific instances of |
| this pipe-editor. */ |
| void *my_baton; |
| }; |
| |
| |
| struct svn_pipe_handler_wrapper |
| { |
| /* Wrapped file baton. */ |
| struct svn_pipe_file_baton *file_baton; |
| |
| /* The "real" handler for the real_file_baton */ |
| svn_txdelta_window_handler_t real_handler; |
| void *real_handler_baton; |
| |
| /* A template field that can be altered in specific instances of |
| this pipe-editor. */ |
| void *my_baton; |
| }; |
| |
| |
| |
| /* Wrap EDITOR_TO_WRAP/EDIT_BATON_TO_WRAP in a new editor whose only |
| * purpose is to call the wrapped editor. Return this new editor in |
| * *NEW_EDITOR / *NEW_EDIT_BATON. POOL will be used for all allocation. |
| * |
| * The editor returned acts as a 'pipe' to the real editor. It comes |
| * back in template form; it is expected that the caller of this |
| * function will customize the individual routines and make use of the |
| * "my_baton" pointers within the pipe-editor's own batons. The main |
| * use of a custom pipe-editor to act as a "man-in-the-middle", to |
| * possibly intercept and modify any commands the editor-driver is |
| * sending to the wrapped editor. |
| */ |
| void |
| svn_delta_old_default_pipe_editor (svn_delta_edit_fns_t **new_editor, |
| struct svn_pipe_edit_baton **new_edit_baton, |
| const svn_delta_edit_fns_t *editor_to_wrap, |
| void *edit_baton_to_wrap, |
| apr_pool_t *pool); |
| |
| |
| |
| /* Creates an editor which outputs XML delta streams to OUTPUT. On |
| return, *EDITOR and *EDITOR_BATON will be set to the editor and its |
| associate baton. The editor's memory will live in a sub-pool of |
| POOL. */ |
| svn_error_t * |
| svn_delta_get_xml_editor (svn_stream_t *output, |
| const svn_delta_editor_t **editor, |
| void **edit_baton, |
| apr_pool_t *pool); |
| |
| |
| |
| /* An opaque object that represents a Subversion Delta XML parser. */ |
| |
| typedef struct svn_delta_xml_parser_t svn_delta_xml_parser_t; |
| |
| /* Given a precreated svn_delta_edit_fns_t EDITOR, return a custom xml |
| PARSER that will call into it (and feed EDIT_BATON to its |
| callbacks.) Additionally, this XML parser will use BASE_PATH and |
| BASE_REVISION as default "context variables" when computing ancestry |
| within a tree-delta. */ |
| svn_error_t *svn_delta_make_xml_parser (svn_delta_xml_parser_t **parser, |
| const svn_delta_edit_fns_t *editor, |
| void *edit_baton, |
| const char *base_path, |
| svn_revnum_t base_revision, |
| apr_pool_t *pool); |
| |
| |
| /* Destroy an svn_delta_xml_parser_t when finished with it. */ |
| void svn_delta_free_xml_parser (svn_delta_xml_parser_t *parser); |
| |
| |
| /* Push LEN bytes of xml data in BUFFER at SVN_XML_PARSER. As xml is |
| parsed, EDITOR callbacks will be executed (using context variables |
| and batons that were used to create the parser.) If this is the |
| final parser "push", ISFINAL must be set to true (so that both |
| expat and local cleanup can occur). */ |
| svn_error_t * |
| svn_delta_xml_parsebytes (const char *buffer, apr_size_t len, int isFinal, |
| svn_delta_xml_parser_t *svn_xml_parser); |
| |
| |
| /* Reads an XML stream from SOURCE using expat internally, validating |
| the XML as it goes (according to Subversion's own tree-delta DTD). |
| Whenever an interesting event happens, it calls a caller-specified |
| callback routine from EDITOR. |
| |
| Once called, it retains control and "pulls" data from SOURCE |
| until either the stream runs out or an error occurs. */ |
| svn_error_t *svn_delta_xml_auto_parse (svn_stream_t *source, |
| const svn_delta_edit_fns_t *editor, |
| void *edit_baton, |
| const char *base_path, |
| svn_revnum_t base_revision, |
| apr_pool_t *pool); |
| |
| |
| |
| |
| |
| /* A callback vtable invoked by our diff-editors, as they receive |
| diffs from the server. 'svn diff' and 'svn merge' both implement |
| their own versions of this table. */ |
| typedef struct svn_diff_callbacks_t |
| { |
| /* A file PATH has changed. The changes can be seen by comparing |
| TMPFILE1 and TMPFILE2, which represent REV1 and REV2 of the file, |
| respectively. */ |
| svn_error_t *(*file_changed) (const char *path, |
| const char *tmpfile1, |
| const char *tmpfile2, |
| svn_revnum_t rev1, |
| svn_revnum_t rev2, |
| void *diff_baton); |
| |
| /* A file PATH was added. The contents can be seen by comparing |
| TMPFILE1 and TMPFILE2. */ |
| svn_error_t *(*file_added) (const char *path, |
| const char *tmpfile1, |
| const char *tmpfile2, |
| void *diff_baton); |
| |
| /* A file PATH was deleted. The [loss of] contents can be seen by |
| comparing TMPFILE1 and TMPFILE2. */ |
| svn_error_t *(*file_deleted) (const char *path, |
| const char *tmpfile1, |
| const char *tmpfile2, |
| void *diff_baton); |
| |
| /* A directory PATH was added. */ |
| svn_error_t *(*dir_added) (const char *path, |
| void *diff_baton); |
| |
| /* A directory PATH was deleted. */ |
| svn_error_t *(*dir_deleted) (const char *path, |
| void *diff_baton); |
| |
| /* A list of property changes (PROPCHANGES) was applied to PATH. |
| The array is a list of (svn_prop_t *) structures. */ |
| svn_error_t *(*props_changed) (const char *path, |
| const apr_array_header_t *propchanges, |
| void *diff_baton); |
| |
| } svn_diff_callbacks_t; |
| |
| |
| |
| #ifdef __cplusplus |
| } |
| #endif /* __cplusplus */ |
| |
| #endif /* SVN_DELTA_H */ |
| |
| /* ---------------------------------------------------------------- |
| * local variables: |
| * eval: (load-file "../../tools/dev/svn-dev.el") |
| * end: |
| */ |
| |