Loading...
Searching...
No Matches
Tree deltas
Delta generation and handling

Traversing tree deltas. More...

## 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)
| Set *editor and *edit_baton to a cancellation editor that wraps wrapped_editor and wrapped_baton.
svn_error_t * | svn_delta_depth_filter_editor (const svn_delta_editor_t **editor, void **edit_baton, const svn_delta_editor_t *wrapped_editor, void *wrapped_edit_baton, svn_depth_t requested_depth, svn_boolean_t has_target, apr_pool_t *pool)
| Set *editor and *edit_baton to an depth-based filtering editor that wraps wrapped_editor and wrapped_baton.

## Variables

svn_error_t *(* | set_target_revision )(void *edit_baton, svn_revnum_t target_revision, apr_pool_t *scratch_pool)
| A structure full of callback functions the delta source will invoke as it produces the delta.
svn_error_t *(* | open_root )(void *edit_baton, svn_revnum_t base_revision, apr_pool_t *result_pool, void **root_baton)
| Set *root_baton to a baton for the top directory of the change.
svn_error_t *(* | delete_entry )(const char *path, svn_revnum_t revision, void *parent_baton, apr_pool_t *scratch_pool)
| Remove the directory entry at path, a child of the directory represented by parent_baton.
svn_error_t *(* | add_directory )(const char *path, void *parent_baton, const char *copyfrom_path, svn_revnum_t copyfrom_revision, apr_pool_t *result_pool, void **child_baton)
| We are going to add a new subdirectory at path, a child of the directory represented by parent_baton.
svn_error_t *(* | open_directory )(const char *path, void *parent_baton, svn_revnum_t base_revision, apr_pool_t *result_pool, void **child_baton)
| We are going to make changes in the subdirectory at path, a child of the directory represented by parent_baton.
svn_error_t *(* | change_dir_prop )(void *dir_baton, const char *name, const svn_string_t *value, apr_pool_t *scratch_pool)
| Change the value of a directory's property.
svn_error_t *(* | close_directory )(void *dir_baton, apr_pool_t *scratch_pool)
| We are done processing a subdirectory, whose baton is dir_baton (set by `add_directory` or `open_directory`).
svn_error_t *(* | absent_directory )(const char *path, void *parent_baton, apr_pool_t *scratch_pool)
| In the directory represented by parent_baton, indicate that path is present as a subdirectory in the edit source, but cannot be conveyed to the edit consumer.
svn_error_t *(* | add_file )(const char *path, void *parent_baton, const char *copyfrom_path, svn_revnum_t copyfrom_revision, apr_pool_t *result_pool, void **file_baton)
| We are going to add a new file at path, a child of the directory represented by parent_baton.
svn_error_t *(* | open_file )(const char *path, void *parent_baton, svn_revnum_t base_revision, apr_pool_t *result_pool, void **file_baton)
| We are going to make changes to a file at path, a child of the directory represented by parent_baton.
svn_error_t *(* | apply_textdelta )(void *file_baton, const char *base_checksum, apr_pool_t *result_pool, svn_txdelta_window_handler_t *handler, void **handler_baton)
| Apply a text delta, yielding the new revision of a file.
svn_error_t *(* | change_file_prop )(void *file_baton, const char *name, const svn_string_t *value, apr_pool_t *scratch_pool)
| Change the value of a file's property.
svn_error_t *(* | close_file )(void *file_baton, const char *text_checksum, apr_pool_t *scratch_pool)
| We are done processing a file, whose baton is file_baton (set by `add_file` or `open_file`).
svn_error_t *(* | absent_file )(const char *path, void *parent_baton, apr_pool_t *scratch_pool)
| In the directory represented by parent_baton, indicate that path is present as a file in the edit source, but cannot be cannot be conveyed to the edit consumer.
svn_error_t *(* | close_edit )(void *edit_baton, apr_pool_t *scratch_pool)
| All delta processing is done.
svn_error_t *(* | abort_edit )(void *edit_baton, apr_pool_t *scratch_pool)
| The editor-driver has decided to bail out.
svn_error_t *(* | apply_textdelta_stream )(const struct svn_delta_editor_t *editor, void *file_baton, const char *base_checksum, svn_txdelta_stream_open_func_t open_func, void *open_baton, apr_pool_t *scratch_pool)
| Apply a text delta stream, yielding the new revision of a file.
| svn_delta_editor_t

## Detailed Description

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 network requests (for example, to svnserve as an ra_svn protocol stream, or to an Apache httpd server as WebDAV commands)
- The server 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 server consumes this delta, and assembles a reply representing the appropriate changes.
- The client networking library receives that 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; the network layer'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.

## Function Documentation

## svn_delta_default_editor()

svn_delta_editor_t * svn_delta_default_editor | ( | 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_depth_filter_editor()

svn_error_t * svn_delta_depth_filter_editor | ( | const svn_delta_editor_t ** | editor,
|  | void ** | edit_baton,
|  | const svn_delta_editor_t * | wrapped_editor,
|  | void * | wrapped_edit_baton,
|  | svn_depth_t | requested_depth,
|  | svn_boolean_t | has_target,
|  | apr_pool_t * | pool )

Set *editor and *edit_baton to an depth-based filtering editor that wraps wrapped_editor and wrapped_baton.

The editor will track the depth of this drive against the requested_depth, taking into account whether not the edit drive is making use of a target (via has_target), and forward editor calls which operate "within" the request depth range through to wrapped_editor.

requested_depth must be one of the following depth values: svn_depth_infinity, svn_depth_empty, svn_depth_files, svn_depth_immediates, or svn_depth_unknown.

If filtering is deemed unnecessary (or if requested_depth is svn_depth_unknown), *editor and *edit_baton will be set to wrapped_editor and wrapped_baton, respectively; otherwise, they'll be set to new objects allocated from pool.

Note
  Because the svn_delta_editor_t interface's `delete_entry()` function doesn't carry node kind information, a depth-based filtering editor being asked to filter for svn_depth_files but receiving a `delete_entry()` call on an immediate child of the editor's target is unable to know if that deletion should be allowed or filtered out – a delete of a top-level file is okay in this case, a delete of a top-level subdirectory is not. As such, this filtering editor takes a conservative approach, and ignores top-level deletion requests when filtering for svn_depth_files. Fortunately, most non-depth-aware (pre-1.5) Subversion editor drivers can be told to drive non-recursively (where non-recursive means essentially svn_depth_files), which means they won't transmit out-of-scope editor commands anyway.

Since
  New in 1.5.

## svn_delta_get_cancellation_editor()

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 )

Set *editor and *edit_baton to a cancellation editor that wraps wrapped_editor and wrapped_baton.

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 cancel_func returns SVN_NO_ERROR.

If cancel_func is `NULL`, set *editor to wrapped_editor and *edit_baton to wrapped_baton.

## svn_delta_noop_window_handler()

svn_error_t * svn_delta_noop_window_handler | ( | svn_txdelta_window_t * | window,
|  | void * | baton )

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.

## Variable Documentation

## abort_edit

svn_error_t *(* abort_edit) (void *edit_baton, apr_pool_t *scratch_pool) | ( | void * | edit_baton,
|  | apr_pool_t * | scratch_pool )

The editor-driver has decided to bail out.

Allow the editor to gracefully clean up things if it needs to.

Any temporary allocations may be performed in scratch_pool.

Definition at line 1153 of file svn_delta.h.

## absent_directory

svn_error_t *(* absent_directory) (const char *path, void *parent_baton, apr_pool_t *scratch_pool) | ( | const char * | path,
|  | void * | parent_baton,
|  | apr_pool_t * | scratch_pool )

In the directory represented by parent_baton, indicate that path is present as a subdirectory in the edit source, but cannot be conveyed to the edit consumer.

Currently, this would only occur because of authorization restrictions, but may change in the future.

Any temporary allocations may be performed in scratch_pool.

Definition at line 1010 of file svn_delta.h.

## absent_file

svn_error_t *(* absent_file) (const char *path, void *parent_baton, apr_pool_t *scratch_pool) | ( | const char * | path,
|  | void * | parent_baton,
|  | apr_pool_t * | scratch_pool )

In the directory represented by parent_baton, indicate that path is present as a file in the edit source, but cannot be cannot be conveyed to the edit consumer.

Currently, this would only occur because of authorization restrictions, but may change in the future.

Any temporary allocations may be performed in scratch_pool.

Definition at line 1136 of file svn_delta.h.

## add_directory

svn_error_t *(* add_directory) (const char *path, void *parent_baton, const char *copyfrom_path, svn_revnum_t copyfrom_revision, apr_pool_t *result_pool, void **child_baton) | ( | const char * | path,
|  | void * | parent_baton,
|  | const char * | copyfrom_path,
|  | svn_revnum_t | copyfrom_revision,
|  | apr_pool_t * | result_pool,
|  | void ** | child_baton )

We are going to add a new subdirectory at path, a child of the directory represented by parent_baton.

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 result_pool. It is also typical to (possibly) save this pool for later usage by `close_directory`.

Definition at line 951 of file svn_delta.h.

## add_file

svn_error_t *(* add_file) (const char *path, void *parent_baton, const char *copyfrom_path, svn_revnum_t copyfrom_revision, apr_pool_t *result_pool, void **file_baton) | ( | const char * | path,
|  | void * | parent_baton,
|  | const char * | copyfrom_path,
|  | svn_revnum_t | copyfrom_revision,
|  | apr_pool_t * | result_pool,
|  | void ** | file_baton )

We are going to add a new file at path, a child of the directory represented 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` or `apply_textdelta_stream`.

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 result_pool. It is also typical to save this pool for later usage by `apply_textdelta` and possibly `close_file`.

Note
  Because the editor driver could be employing the "postfix deltas" paradigm, result_pool could potentially be relatively long-lived. Every file baton created by the editor for a given editor drive might be resident in memory similtaneously. Editor implementations should ideally keep their file batons as conservative (memory-usage-wise) as possible, and use result_pool only for those batons. (Consider using a subpool of result_pool for scratch work, destroying the subpool before exiting this function's implementation.)

Definition at line 1038 of file svn_delta.h.

## apply_textdelta

svn_error_t *(* apply_textdelta) (void *file_baton, const char *base_checksum, apr_pool_t *result_pool, svn_txdelta_window_handler_t *handler, void **handler_baton) | ( | void * | file_baton,
|  | const char * | base_checksum,
|  | apr_pool_t * | result_pool,
|  | svn_txdelta_window_handler_t * | handler,
|  | void ** | handler_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. These values should be allocated within result_pool.

base_checksum is the hex MD5 digest for the base text against which the delta is being applied; it is ignored if NULL, and may be ignored even if not NULL. If it is not ignored, it must match the checksum of the base text against which svndiff data is being applied; if it does not, `apply_textdelta` or the *handler call which detects the mismatch will return the error SVN_ERR_CHECKSUM_MISMATCH (if there is no base text, there may still be an error if base_checksum is neither NULL nor the hex MD5 checksum of the empty string).

Definition at line 1089 of file svn_delta.h.

## apply_textdelta_stream

svn_error_t *(* apply_textdelta_stream) (const struct svn_delta_editor_t *editor, void *file_baton, const char *base_checksum, svn_txdelta_stream_open_func_t open_func, void *open_baton, apr_pool_t *scratch_pool) | ( | const struct svn_delta_editor_t * | editor,
|  | void * | file_baton,
|  | const char * | base_checksum,
|  | svn_txdelta_stream_open_func_t | open_func,
|  | void * | open_baton,
|  | apr_pool_t * | scratch_pool )

Apply a text delta stream, yielding the new revision of a file.

This callback operates on the passed-in editor instance.

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.

open_func is a function that opens a svn_txdelta_stream_t object. open_baton is provided by the caller.

base_checksum is the hex MD5 digest for the base text against which the delta is being applied; it is ignored if NULL, and may be ignored even if not NULL. If it is not ignored, it must match the checksum of the base text against which svndiff data is being applied; if it does not, `apply_textdelta_stream` call which detects the mismatch will return the error SVN_ERR_CHECKSUM_MISMATCH (if there is no base text, there may still be an error if base_checksum is neither NULL nor the hex MD5 checksum of the empty string).

Any temporary allocations may be performed in scratch_pool.

Since
  New in 1.10.

Definition at line 1180 of file svn_delta.h.

## change_dir_prop

svn_error_t *(* change_dir_prop) (void *dir_baton, const char *name, const svn_string_t *value, apr_pool_t *scratch_pool) | ( | void * | dir_baton,
|  | const char * | name,
|  | const svn_string_t * | value,
|  | apr_pool_t * | scratch_pool )

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 (final) value of the property, or `NULL` if the property should be removed altogether.

The callback is guaranteed to be called exactly once for each property whose value differs between the start and the end of the edit.

Any temporary allocations may be performed in scratch_pool.

Definition at line 986 of file svn_delta.h.

## change_file_prop

svn_error_t *(* change_file_prop) (void *file_baton, const char *name, const svn_string_t *value, apr_pool_t *scratch_pool) | ( | void * | file_baton,
|  | const char * | name,
|  | const svn_string_t * | value,
|  | apr_pool_t * | scratch_pool )

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 (final) value of the property, or `NULL` if the property should be removed altogether.

The callback is guaranteed to be called exactly once for each property whose value differs between the start and the end of the edit.

Any temporary allocations may be performed in scratch_pool.

Definition at line 1106 of file svn_delta.h.

## close_directory

svn_error_t *(* close_directory) (void *dir_baton, apr_pool_t *scratch_pool) | ( | void * | dir_baton,
|  | apr_pool_t * | scratch_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.

Any temporary allocations may be performed in scratch_pool.

Definition at line 998 of file svn_delta.h.

## close_edit

svn_error_t *(* close_edit) (void *edit_baton, apr_pool_t *scratch_pool) | ( | void * | edit_baton,
|  | apr_pool_t * | scratch_pool )

All delta processing is done.

Call this, with the edit_baton for the entire edit.

Any temporary allocations may be performed in scratch_pool.

Definition at line 1145 of file svn_delta.h.

## close_file

svn_error_t *(* close_file) (void *file_baton, const char *text_checksum, apr_pool_t *scratch_pool) | ( | void * | file_baton,
|  | const char * | text_checksum,
|  | apr_pool_t * | scratch_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.

text_checksum is the hex MD5 digest for the fulltext that resulted from a delta application, see `apply_textdelta` and `apply_textdelta_stream`. The checksum is ignored if NULL. If not null, it is compared to the checksum of the new fulltext, and the error SVN_ERR_CHECKSUM_MISMATCH is returned if they do not match. If there is no new fulltext, text_checksum is ignored.

Any temporary allocations may be performed in scratch_pool.

Definition at line 1124 of file svn_delta.h.

## delete_entry

svn_error_t *(* delete_entry) (const char *path, svn_revnum_t revision, void *parent_baton, apr_pool_t *scratch_pool) | ( | const char * | path,
|  | svn_revnum_t | revision,
|  | void * | parent_baton,
|  | apr_pool_t * | scratch_pool )

Remove the directory entry at path, a child of the directory represented by parent_baton.

If revision is a valid revision number, it is used as a sanity check to ensure that you are really removing the revision of path that you think you are.

Any temporary allocations may be performed in scratch_pool.

Note
  The revision parameter is typically used only for client->server commit-type operations, allowing the server to verify that it is deleting what the client thinks it should be deleting. It only really makes sense in the opposite direction (during server->client update-type operations) when the trees whose delta is being described are ancestrally related (that is, one tree is an ancestor of the other).

Definition at line 932 of file svn_delta.h.

## open_directory

svn_error_t *(* open_directory) (const char *path, void *parent_baton, svn_revnum_t base_revision, apr_pool_t *result_pool, void **child_baton) | ( | const char * | path,
|  | void * | parent_baton,
|  | svn_revnum_t | base_revision,
|  | apr_pool_t * | result_pool,
|  | void ** | child_baton )

We are going to make changes in the subdirectory at path, a child of the directory represented by parent_baton.

The callback must store a value in *child_baton that should be used as the parent baton for subsequent changes in this subdirectory. If a valid revnum, base_revision is the current revision of the subdirectory.

Allocations for the returned child_baton should be performed in result_pool. It is also typical to (possibly) save this pool for later usage by `close_directory`.

Definition at line 969 of file svn_delta.h.

## open_file

svn_error_t *(* open_file) (const char *path, void *parent_baton, svn_revnum_t base_revision, apr_pool_t *result_pool, void **file_baton) | ( | const char * | path,
|  | void * | parent_baton,
|  | svn_revnum_t | base_revision,
|  | apr_pool_t * | result_pool,
|  | void ** | file_baton )

We are going to make changes to a file at path, a child of the directory represented 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` or `apply_textdelta_stream`. If a valid revnum, base_revision is the current revision of the file.

Allocations for the returned file_baton should be performed in result_pool. It is also typical to save this pool for later usage by `apply_textdelta` and possibly `close_file`.

Note
  See note about memory usage on add_file, which also applies here.

Definition at line 1060 of file svn_delta.h.

## open_root

svn_error_t *(* open_root) (void *edit_baton, svn_revnum_t base_revision, apr_pool_t *result_pool, void **root_baton) | ( | void * | edit_baton,
|  | svn_revnum_t | base_revision,
|  | apr_pool_t * | result_pool,
|  | void ** | root_baton )

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.) As with any other directory baton, the producer should call `close_directory` on root_baton when done. And as with 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 result_pool. It is also typical to (possibly) save this pool for later usage by `close_directory`.

Definition at line 911 of file svn_delta.h.

## set_target_revision

svn_error_t *(* set_target_revision) (void *edit_baton, svn_revnum_t target_revision, apr_pool_t *scratch_pool) | ( | void * | edit_baton,
|  | svn_revnum_t | target_revision,
|  | apr_pool_t * | scratch_pool )

A structure full of callback functions the delta source will invoke as it produces the delta.

Note
  Don't try to allocate one of these yourself. Instead, always use svn_delta_default_editor() or some other constructor, to avoid backwards compatibility problems if the structure is extended in future releases and to ensure that unused slots are filled in with no-op functions.

### 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. If there is a target revision that needs to be set for this operation, the producer should call the `set_target_revision` function at this point.

Next, if there are any tree deltas to express, the producer should pass the 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:

    @c delete_entry
    @c add_file
    @c add_directory
    @c open_file
    @c 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 of the file, subdirectory, or directory entry to change.

The path argument to each of the callbacks is relative to the root of the edit. Editors will usually want to join this relative path with some base stored in the edit baton (e.g. a URL, or 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` or `apply_textdelta_stream` 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). In that case, copyfrom_path must be either a path relative to the root of the edit, or a URI from the repository being edited. If copyfrom_path is `NULL`, then copyfrom_revision must be SVN_INVALID_REVNUM; it is invalid to pass a mix of valid and invalid copyfrom arguments.

### 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` at most once on any given directory entry. `delete_entry` may be called at most once on any given directory entry and may later be followed by `add_directory` or `add_file` on the same directory entry. `delete_entry` may not be called on any directory entry after `open_directory`, `add_directory`, `open_file` or `add_file` has been called on that 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 any changes to the file (`change_file_prop` and/or `apply_textdelta` / `apply_textdelta_stream`, 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` / `apply_textdelta_stream` 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` / `apply_textdelta_stream` calls 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.

Based on the requirement of calling the editor functions in a depth-first style, it is usually customary for the driver to similarly 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 `apply_textdelta` / `apply_textdelta_stream` 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 result_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.

### Errors

At 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 (including `close_edit`) returns an error, the edit is dead; the only further operation which may be called on the editor is `abort_edit`. */ typedef struct svn_delta_editor_t { /** Set the target revision for this edit to target_revision. This call, if used, should precede all other editor calls.

Note
  This is typically used only for server->client update-type operations. It doesn't really make much sense for commit-type operations, because the revision of a commit isn't known until the commit is finalized.

Any temporary allocations may be performed in scratch_pool.

Definition at line 895 of file svn_delta.h.

## svn_delta_editor_t

svn_delta_editor_t

Definition at line 1190 of file svn_delta.h.