Beautiful Code [92]
* 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. When the producer calls open_file or add_file, it must
* follow with any changes to the file (using apply_textdelta),
* followed by a close_file call, before issuing any other
* file or directory calls.
*
* 5. 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.
*
* 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.
*/
typedef struct svn_delta_editor_t
{
/** 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.
*/
svn_error_t *(*open_root)(void *edit_baton,
apr_pool_t *dir_pool,
void **root_baton);
/** Remove the directory entry named path, a child of the directory
* represented by parent_baton.
*/
svn_error_t *(*delete_entry)(const char *path,
void *parent_baton,
apr_pool_t *pool);
/** 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.
*/
svn_error_t *(*add_directory)(const char *path,
void *parent_baton,
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.
*/
svn_error_t *(*open_directory)(const char *path,
void *parent_baton,
apr_pool_t *dir_pool,
void **child_baton);
/** 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,
apr_pool_t *pool);
/** 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.
*/
svn_error_t *(*add_file)(const char *path,
void *parent_baton,
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.
*/
svn_error_t *(*open_file)(const