Beautiful Code [93]
void *parent_baton,
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 *handle to a text delta window
* handler; we will then call *handle 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.
*/
svn_error_t *(*apply_textdelta)(void *file_baton,
apr_pool_t *pool,
svn_txdelta_window_handler_t *handler,
void **handler_baton);
/** 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,
apr_pool_t *pool)
/** All delta processing is done. Call this, with the edit_baton for
* the entire edit.
*/
svn_error_t *(*close_edit)(void *edit_baton,
apr_pool_t *pool);]
/** 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,
apr_pool_t *pool);
} svn_delta_editor_t;
Subversion's Delta Editor: Interface As Ontology > But Is It Art?
2.4. But Is It Art?
I cannot claim that the beauty of this interface was immediately obvious to me. I'm not sure it was obvious to Jim either; he was probably just trying to get Ben and me out of his house. But he'd been pondering the problem for a long time, too, and he followed his instincts about how tree structures behave.
The first thing that strikes one about the delta editor is that it chooses constraint: even though there is no philosophical requirement that tree edits be done in depth-first order (or indeed in any order at all), the interface enforces depth-firstness anyway, by means of the baton relationships. This makes the interface's usage and behavior more predictable.
The second thing is that an entire edit operation unobtrusively carries its context with it, again by means of the batons. A file baton can contain a pointer to its parent directory baton, a directory baton can contain a pointer to its parent directory baton (with a null parent for the root of the edit), and everyone can contain a pointer to the global edit baton. Although an individual baton may be a disposable object—for example, when a file is closed, its baton is destroyed—any given baton allows access to the global edit context, which may contain, for example, the revision number the client side is being updated to. Thus, batons are overloaded: they provide scope (i.e., lifetime, because a baton only lasts as long as the pool in which it is allocated) to portions of the edit, but they also carry global context.
The third important feature is that the interface provides clear boundaries between the various suboperations involved in expressing a tree change. For example, opening a file merely indicates that something changed in that file between the two trees, but doesn't give details; calling apply_textdelta gives the details, but you don't have to call apply_ textdelta if you don't want to. Similarly, opening a directory indicates that something changed in or under that directory, but if you don't need to say any more than that, you can just close the directory and move on. These boundaries are a consequence of the interface's dedication to streaminess, as expressed in its introductory comment: "…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." It would have been tempting to stream only the largest data chunks (that is, the file diffs), but the delta editor interface goes the whole way and streams the entire tree delta, thus giving both producer and