Data Structures | |
struct | svn_delta_editor_t |
A structure full of callback functions the delta source will invoke as it produces the delta. More... | |
Typedefs | |
typedef svn_delta_editor_t | svn_delta_editor_t |
A structure full of callback functions the delta source will invoke as it produces the delta. | |
Functions | |
svn_delta_editor_t * | svn_delta_default_editor (apr_pool_t *pool) |
Return a default delta editor template, allocated in pool. | |
svn_error_t * | svn_delta_noop_window_handler (svn_txdelta_window_t *window, void *baton) |
A text-delta window handler which does nothing. | |
svn_error_t * | svn_delta_get_cancellation_editor (svn_cancel_func_t cancel_func, void *cancel_baton, const svn_delta_editor_t *wrapped_editor, void *wrapped_baton, const svn_delta_editor_t **editor, void **edit_baton, apr_pool_t *pool) |
Return a cancellation editor that wraps wrapped_editor. |
In Subversion, we've got various producers and consumers of tree deltas.
In processing a `commit' command:
In processing an `update' command, the process is reversed:
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_editor_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.
Function UsageHere'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. If there is a target revision that needs to be set for this operation, the producer should call the
Next, if there are any tree deltas to express, the producer should pass the edit_baton to the Most of the callbacks work in the obvious way:
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
While 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:
When the producer is finished making changes to a directory, it should call
The
The
Function Call OrderingThere are six restrictions on the order in which the producer may use the batons:
1. The producer may call 2. The producer may not close a directory baton until it has closed all batons for its subdirectories.
3. When a producer calls
4. A producer must call
5. When the producer calls
(a) The producer must follow with the changes to the file (
(b) The producer must follow with a
6. When the producer 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.
Pool UsageMany 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. 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.
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
ErrorsAt least one implementation of the editor interface is asynchronous; an error from one operation may be detected some number of operations later. As a result, an editor driver must not assume that an error from an editing function resulted from the particular operation being detected. Moreover, once an editing function returns an error, the edit is dead; the only further operation which may be called on the editor is abort_edit. |
|
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. |
|
Return a cancellation editor that wraps wrapped_editor.
The editor will call cancel_func with cancel_baton when each of its functions is called, continuing on to call the corresponding wrapped function if it returns
If cancel_func is |
|
A text-delta window handler which does nothing. Editors can return this handler from apply_textdelta if they don't care about text delta windows. |