/**
* @copyright
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
* @endcopyright
*
* @file svn_editor.h
* @brief Tree editing functions and structures
*/
#ifndef SVN_EDITOR_H
#define SVN_EDITOR_H
#include <apr_pools.h>
#include "svn_types.h"
#include "svn_error.h"
#include "svn_io.h" /* for svn_stream_t */
#include "svn_delta.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/*** Temporarily private stuff (should move to svn_delta.h when Editor
V2 is made public) ***/
/** Callback to retrieve a node's entire set of properties. This is
* needed by the various editor shims in order to effect backwards
* compatibility.
*
* Implementations should set @a *props to the hash of properties
* associated with @a path in @a base_revision, allocating that hash
* and its contents in @a result_pool, and should use @a scratch_pool
* for temporary allocations.
*
* @a baton is an implementation-specific closure.
*/
typedef svn_error_t *(*svn_delta_fetch_props_func_t)(
apr_hash_t **props,
void *baton,
const char *path,
svn_revnum_t base_revision,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool
);
/** Callback to retrieve a node's kind. This is needed by the various
* editor shims in order to effect backwards compatibility.
*
* Implementations should set @a *kind to the node kind of @a path in
* @a base_revision, using @a scratch_pool for temporary allocations.
*
* @a baton is an implementation-specific closure.
*/
typedef svn_error_t *(*svn_delta_fetch_kind_func_t)(
svn_node_kind_t *kind,
void *baton,
const char *path,
svn_revnum_t base_revision,
apr_pool_t *scratch_pool
);
/** Callback to fetch the name of a file to use as a delta base.
*
* Implementations should set @a *filename to the name of a file
* suitable for use as a delta base for @a path in @a base_revision
* (allocating @a *filename from @a result_pool), or to @c NULL if the
* base stream is empty. @a scratch_pool is provided for temporary
* allocations.
*
* @a baton is an implementation-specific closure.
*/
typedef svn_error_t *(*svn_delta_fetch_base_func_t)(
const char **filename,
void *baton,
const char *path,
svn_revnum_t base_revision,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool
);
/** Collection of callbacks used for the shim code. This structure
* may grow additional fields in the future. Therefore, always use
* svn_delta_shim_callbacks_default() to allocate new instances of it.
*/
typedef struct svn_delta_shim_callbacks_t
{
svn_delta_fetch_props_func_t fetch_props_func;
svn_delta_fetch_kind_func_t fetch_kind_func;
svn_delta_fetch_base_func_t fetch_base_func;
void *fetch_baton;
} svn_delta_shim_callbacks_t;
/** Return a collection of default shim functions in @a result_pool.
*/
svn_delta_shim_callbacks_t *
svn_delta_shim_callbacks_default(apr_pool_t *result_pool);
/** Transforming trees ("editing").
*
* In Subversion, we have a number of occasions where we transform a tree
* from one state into another. This process is called "editing" a tree.
*
* In processing a `commit' command:
* - The client examines its working copy data to determine the set of
* changes necessary to transform its base tree into the desired target.
* - The client networking library delivers that set of changes/operations
* 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 applies the sequence of
* operations on a revision, producing a transaction representing the
* desired target.
* - The Subversion server then commits the transaction to the filesystem.
*
* In processing an `update' command, the process is reversed:
* - The Subversion server module talks to the filesystem and computes a
* set of changes necessary to bring the client's working copy up to date.
* - The server serializes this description of changes, and delivers it to
* the client.
* - The client networking library receives that reply, producing a set
* of changes/operations to alter the working copy into the revision
* requested by the update command.
* - The working copy library applies those operations to the working copy
* to align it with the requested update target.
*
* The series of changes (or operations) necessary to transform a tree from
* one state into another is passed between subsystems using this "editor"
* interface. The "receiver" edits its tree according to the operations
* described by the "driver".
*
* Note that the driver must have a perfect understanding of the tree which
* the receiver will be applying edits upon. There is no room for error here,
* and the interface embodies assumptions/requirements that the driver has
* about the targeted tree. As a result, this interface is a standardized
* mechanism of *describing* those change operations, but the intimate
* knowledge between the driver and the receiver implies some level of
* coupling between those subsystems.
*
* The set of changes, and the data necessary to describe it entirely, is
* completely unbounded. An addition of one simple 20 GB file might be well
* past the available memory of a machine processing these operations.
* As a result, the API to describe the changes is designed to be applied
* in a sequential (and relatively random-access) model. The operations
* can be streamed from the driver to the receiver, resulting in the
* receiver editing its tree to the target state defined by the driver.
*
*
* <h3>History</h3>
*
* Classically, Subversion had a notion of a "tree delta" which could be
* passed around as an independent entity. Theory implied this delta was an
* entity in its own right, to be used when and where necessary.
* Unfortunately, this theory did not work well in practice. The producer
* and consumer of these tree deltas were (and are) tightly coupled. As noted
* above, the tree delta producer needed to be *totally* aware of the tree
* that it needed to edit. So rather than telling the delta consumer how to
* edit its tree, the classic #svn_delta_editor_t interface focused
* entirely on the tree delta, an intermediate (logical) data structure
* which was unusable outside of the particular, coupled pairing of producer
* and consumer. This generation of the API forgoes the logical tree delta
* entity and directly passes the necessary edits/changes/operations from
* the producer to the consumer. In our new parlance, one subsystem "drives"
* a set of operations describing the change, and a "receiver" accepts and
* applies them to its tree.
*
* The classic interface was named #svn_delta_editor_t and was described
* idiomatically as the "editor interface". This generation of the interface
* retains the "editor" name for that reason. All notions of a "tree delta"
* structure are no longer part of this interface.
*
* The old interface was purely vtable-based and used a number of special
* editors which could be interposed between the driver and receiver. Those
* editors provided cancellation, debugging, and other various operations.
* While the "interposition" pattern is still possible with this interface,
* the most common functionality (cancellation and debugging) have been
* integrated directly into this new editor system.
*
*
* <h3>Implementation Plan</h3>
* @note This section can be removed after Ev2 is fully implemented.
*
* The delta editor is pretty engrained throughout Subversion, so attempting
* to replace it in situ is somewhat akin to performing open heart surgery
* while the patient is running a marathon. However, a viable plan should
* make things a bit easier, and help parallelize the work.
*
* In short, the following items need to be done:
* -# Implement backward compatibility wrappers ("shims")
* -# Use shims to update editor consumers to Ev2
* -# Update editor producers to drive Ev2
* - This will largely involve rewriting the RA layers to accept and
* send Ev2 commands
* -# Optimize consumers and producers to leverage the features of Ev2
*
* The shims are largely self-contained, and as of this writing, are almost
* complete. They can be released without much ado. However, they do add
* <em>significant</em> performance regressions, which make releasing code
* which is half-delta-editor and half-Ev2 inadvisable. As such, the updating
* of producers and consumers to Ev2 will probably need to wait until 1.9,
* though it could be largely parallelized.
*
*
* @defgroup svn_editor The editor interface
* @{
*/
/** An abstract object that edits a target tree.
*
* @note The term "follow" means at any later time in the editor drive.
* Terms such as "must", "must not", "required", "shall", "shall not",
* "should", "should not", "recommended", "may", and "optional" in this
* document are to be interpreted as described in RFC 2119.
*
* @note The editor objects are *not* reentrant. The receiver should not
* directly or indirectly invoke an editor API with the same object unless
* it has been marked as explicitly supporting reentrancy during a
* receiver's callback. This limitation extends to the cancellation
* callback, too. (This limitation is due to the scratch_pool shared by
* all callbacks, and cleared after each callback; a reentrant call could
* clear the outer call's pool). Note that the code itself is reentrant, so
* there is no problem using the APIs on different editor objects.
*
* \n
* <h3>Life-Cycle</h3>
*
* - @b Create: A receiver uses svn_editor_create() to create an
* "empty" svn_editor_t. It cannot be used yet, since it still lacks
* actual callback functions. svn_editor_create() sets the
* #svn_editor_t's callback baton and scratch pool that the callback
* functions receive, as well as a cancellation callback and baton
* (see "Cancellation" below).
*
* - @b Set callbacks: The receiver calls svn_editor_setcb_many() or a
* succession of the other svn_editor_setcb_*() functions to tell
* #svn_editor_t which functions to call when driven by the various
* operations. Callback functions are implemented by the receiver and must
* adhere to the @c svn_editor_cb_*_t function types as expected by the
* svn_editor_setcb_*() functions. See: \n
* svn_editor_cb_many_t \n
* svn_editor_setcb_many() \n
* or \n
* svn_editor_setcb_add_directory() \n
* svn_editor_setcb_add_file() \n
* svn_editor_setcb_add_symlink() \n
* svn_editor_setcb_add_absent() \n
* svn_editor_setcb_alter_directory() \n
* svn_editor_setcb_alter_file() \n
* svn_editor_setcb_alter_symlink() \n
* svn_editor_setcb_delete() \n
* svn_editor_setcb_copy() \n
* svn_editor_setcb_move() \n
* svn_editor_setcb_complete() \n
* svn_editor_setcb_abort()
*
* - @b Drive: The driver is provided with the completed #svn_editor_t
* instance. (It is typically passed to a generic driving
* API, which could receive the driving editor calls over the network
* by providing a proxy #svn_editor_t on the remote side.)
* The driver invokes the #svn_editor_t instance's callback functions
* according to the restrictions defined below, in order to describe the
* entire set of operations necessary to transform the receiver's tree
* into the desired target. The callbacks can be invoked using the
* svn_editor_*() functions, i.e.: \n
* svn_editor_add_directory() \n
* svn_editor_add_file() \n
* svn_editor_add_symlink() \n
* svn_editor_add_absent() \n
* svn_editor_alter_directory() \n
* svn_editor_alter_file() \n
* svn_editor_alter_symlink() \n
* svn_editor_delete() \n
* svn_editor_copy() \n
* svn_editor_move() \n
* \n\n
* Just before each callback invocation is carried out, the @a cancel_func
* that was passed to svn_editor_create() is invoked to poll any
* external reasons to cancel the sequence of operations. Unless it
* overrides the cancellation (denoted by #SVN_ERR_CANCELLED), the driver
* aborts the transmission by invoking the svn_editor_abort() callback.
* Exceptions to this are calls to svn_editor_complete() and
* svn_editor_abort(), which cannot be canceled externally.
*
* - @b Receive: While the driver invokes operations upon the editor, the
* receiver finds its callback functions called with the information
* to operate on its tree. Each actual callback function receives those
* arguments that the driver passed to the "driving" functions, plus these:
* - @a baton: This is the @a editor_baton pointer originally passed to
* svn_editor_create(). It may be freely used by the callback
* implementation to store information across all callbacks.
* - @a scratch_pool: This temporary pool is cleared directly after
* each callback returns. See "Pool Usage".
* \n\n
* If the receiver encounters an error within a callback, it returns an
* #svn_error_t*. The driver receives this and aborts transmission.
*
* - @b Complete/Abort: The driver will end transmission by calling \n
* svn_editor_complete() if successful, or \n
* svn_editor_abort() if an error or cancellation occurred.
* \n\n
*
* <h3>Driving Order Restrictions</h3>
* In order to reduce complexity of callback receivers, the editor callbacks
* must be driven in adherence to these rules:
*
* - If any path is added (with add_*) or deleted/moved, then
* an svn_editor_alter_directory() call must be made for its parent
* directory with the target/eventual set of children.
*
* - svn_editor_add_directory() -- Another svn_editor_add_*() call must
* follow for each child mentioned in the @a children argument of any
* svn_editor_add_directory() call.
*
* - For each node created with add_*, if its parent was created using
* svn_editor_add_directory(), then the new child node MUST have been
* mentioned in the @a children parameter of the parent's creation.
* This allows the parent directory to properly mark the child as
* "incomplete" until the child's add_* call arrives.
*
* - A path should never be referenced more than once by the add_*, alter_*,
* and delete operations (the "Once Rule"). The source path of a copy (and
* its children, if a directory) may be copied many times, and are
* otherwise subject to the Once Rule. The destination path of a copy
* or move may have alter_* operations applied, but not add_* or delete.
* If the destination path of a copy or move is a directory,
* then its children are subject to the Once Rule. The source path of
* a move (and its child paths) may be referenced in add_*, or as the
* destination of a copy (where these new or copied nodes are subject
* to the Once Rule).
*
* - The ancestor of an added, copied-here, moved-here, or
* modified node may not be deleted. The ancestor may not be moved
* (instead: perform the move, *then* the edits).
*
* - svn_editor_delete() must not be used to replace a path -- i.e.
* svn_editor_delete() must not be followed by an svn_editor_add_*() on
* the same path, nor by an svn_editor_copy() or svn_editor_move() with
* the same path as the copy/move target.
*
* Instead of a prior delete call, the add/copy/move callbacks should be
* called with the @a replaces_rev argument set to the revision number of
* the node at this path that is being replaced. Note that the path and
* revision number are the key to finding any other information about the
* replaced node, like node kind, etc.
* @todo say which function(s) to use.
*
* - svn_editor_delete() must not be used to move a path -- i.e.
* svn_editor_delete() must not delete the source path of a previous
* svn_editor_copy() call. Instead, svn_editor_move() must be used.
* Note: if the desired semantics is one (or more) copies, followed
* by a delete... that is fine. It is simply that svn_editor_move()
* should be used to describe a semantic move.
*
* - One of svn_editor_complete() or svn_editor_abort() must be called
* exactly once, which must be the final call the driver invokes.
* Invoking svn_editor_complete() must imply that the set of changes has
* been transmitted completely and without errors, and invoking
* svn_editor_abort() must imply that the transformation was not completed
* successfully.
*
* - If any callback invocation (besides svn_editor_complete()) returns
* with an error, the driver must invoke svn_editor_abort() and stop
* transmitting operations.
* \n\n
*
* <h3>Receiving Restrictions</h3>
*
* All callbacks must complete their handling of a path before they return.
* Since future callbacks will never reference this path again (due to the
* Once Rule), the changes can and should be completed.
*
* This restriction is not recursive -- a directory's children may remain
* incomplete until later callback calls are received.
*
* For example, an svn_editor_add_directory() call during an 'update'
* operation will create the directory itself, including its properties,
* and will complete any client notification for the directory itself.
* The immediate children of the added directory, given in @a children,
* will be recorded in the WC as 'incomplete' and will be completed in the
* course of the same operation sequence, when the corresponding callbacks
* for these items are invoked.
* \n\n
*
* <h3>Timing and State</h3>
* The calls made by the driver to alter the state in the receiver are
* based on the receiver's *current* state, which includes all prior changes
* made during the edit.
*
* Example: copy A to B; set-props on A; copy A to C. The props on C
* should reflect the updated properties of A.
*
* Example: mv A@N to B; mv C@M to A. The second move cannot be marked as
* a "replacing" move since it is not replacing A. The node at A was moved
* away. The second operation is simply moving C to the now-empty path
* known as A.
*
* <h3>Paths</h3>
* Each driver/receiver implementation of this editor interface must
* establish the expected root for all the paths sent and received via
* the callbacks' @a relpath arguments.
*
* For example, during an "update", the driver is the repository, as a
* whole. The receiver may have just a portion of that repository. Here,
* the receiver could tell the driver which repository URL the working
* copy refers to, and thus the driver could send @a relpath arguments
* that are relative to the receiver's working copy.
*
* @note Because the source of a copy may be located *anywhere* in the
* repository, editor drives should typically use the repository root
* as the negotiated root. This allows the @a src_relpath argument in
* svn_editor_copy() to specify any possible source.
* \n\n
*
* <h3>Pool Usage</h3>
* The @a result_pool passed to svn_editor_create() is used to allocate
* the #svn_editor_t instance, and thus it must not be cleared before the
* driver has finished driving the editor.
*
* The @a scratch_pool passed to each callback invocation is derived from
* the @a result_pool that was passed to svn_editor_create(). It is
* cleared directly after each single callback invocation.
* To allocate memory with a longer lifetime from within a callback
* function, you may use your own pool kept in the @a editor_baton.
*
* The @a scratch_pool passed to svn_editor_create() may be used to help
* during construction of the #svn_editor_t instance, but it is assumed to
* live only until svn_editor_create() returns.
* \n\n
*
* <h3>Cancellation</h3>
* To allow graceful interruption by external events (like a user abort),
* svn_editor_create() can be passed an #svn_cancel_func_t that is
* polled every time the driver invokes a callback, just before the
* actual editor callback implementation is invoked. If this function
* decides to return with an error, the driver will receive this error
* as if the callback function had returned it, i.e. as the result from
* calling any of the driving functions (e.g. svn_editor_add_directory()).
* As with any other error, the driver must then invoke svn_editor_abort()
* and abort the transformation sequence. See #svn_cancel_func_t.
*
* The @a cancel_baton argument to svn_editor_create() is passed
* unchanged to each poll of @a cancel_func.
*
* The cancellation function and baton are typically provided by the client
* context.
*
*
* @todo ### TODO anything missing?
*
* @since New in 1.8.
*/
typedef struct svn_editor_t svn_editor_t;
/** The kind of the checksum to be used throughout the #svn_editor_t APIs.
*
* @note ### This may change before Ev2 is official released, so just like
* everything else in this file, please don't rely upon it until then.
*/
#define SVN_EDITOR_CHECKSUM_KIND svn_checksum_sha1
/** These function types define the callback functions a tree delta consumer
* implements.
*
* Each of these "receiving" function types matches a "driving" function,
* which has the same arguments with these differences:
*
* - These "receiving" functions have a @a baton argument, which is the
* @a editor_baton originally passed to svn_editor_create(), as well as
* a @a scratch_pool argument.
*
* - The "driving" functions have an #svn_editor_t* argument, in order to
* call the implementations of the function types defined here that are
* registered with the given #svn_editor_t instance.
*
* Note that any remaining arguments for these function types are explained
* in the comment for the "driving" functions. Each function type links to
* its corresponding "driver".
*
* @see svn_editor_t, svn_editor_cb_many_t.
*
* @defgroup svn_editor_callbacks Editor callback definitions
* @{
*/
/** @see svn_editor_add_directory(), svn_editor_t.
* @since New in 1.8.
*/
typedef svn_error_t *(*svn_editor_cb_add_directory_t)(
void *baton,
const char *relpath,
const apr_array_header_t *children,
apr_hash_t *props,
svn_revnum_t replaces_rev,
apr_pool_t *scratch_pool);
/** @see svn_editor_add_file(), svn_editor_t.
* @since New in 1.8.
*/
typedef svn_error_t *(*svn_editor_cb_add_file_t)(
void *baton,
const char *relpath,
const svn_checksum_t *checksum,
svn_stream_t *contents,
apr_hash_t *props,
svn_revnum_t replaces_rev,
apr_pool_t *scratch_pool);
/** @see svn_editor_add_symlink(), svn_editor_t.
* @since New in 1.8.
*/
typedef svn_error_t *(*svn_editor_cb_add_symlink_t)(
void *baton,
const char *relpath,
const char *target,
apr_hash_t *props,
svn_revnum_t replaces_rev,
apr_pool_t *scratch_pool);
/** @see svn_editor_add_absent(), svn_editor_t.
* @since New in 1.8.
*/
typedef svn_error_t *(*svn_editor_cb_add_absent_t)(
void *baton,
const char *relpath,
svn_node_kind_t kind,
svn_revnum_t replaces_rev,
apr_pool_t *scratch_pool);
/** @see svn_editor_alter_directory(), svn_editor_t.
* @since New in 1.8.
*/
typedef svn_error_t *(*svn_editor_cb_alter_directory_t)(
void *baton,
const char *relpath,
svn_revnum_t revision,
const apr_array_header_t *children,
apr_hash_t *props,
apr_pool_t *scratch_pool);
/** @see svn_editor_alter_file(), svn_editor_t.
* @since New in 1.8.
*/
typedef svn_error_t *(*svn_editor_cb_alter_file_t)(
void *baton,
const char *relpath,
svn_revnum_t revision,
const svn_checksum_t *checksum,
svn_stream_t *contents,
apr_hash_t *props,
apr_pool_t *scratch_pool);
/** @see svn_editor_alter_symlink(), svn_editor_t.
* @since New in 1.8.
*/
typedef svn_error_t *(*svn_editor_cb_alter_symlink_t)(
void *baton,
const char *relpath,
svn_revnum_t revision,
const char *target,
apr_hash_t *props,
apr_pool_t *scratch_pool);
/** @see svn_editor_delete(), svn_editor_t.
* @since New in 1.8.
*/
typedef svn_error_t *(*svn_editor_cb_delete_t)(
void *baton,
const char *relpath,
svn_revnum_t revision,
apr_pool_t *scratch_pool);
/** @see svn_editor_copy(), svn_editor_t.
* @since New in 1.8.
*/
typedef svn_error_t *(*svn_editor_cb_copy_t)(
void *baton,
const char *src_relpath,
svn_revnum_t src_revision,
const char *dst_relpath,
svn_revnum_t replaces_rev,
apr_pool_t *scratch_pool);
/** @see svn_editor_move(), svn_editor_t.
* @since New in 1.8.
*/
typedef svn_error_t *(*svn_editor_cb_move_t)(
void *baton,
const char *src_relpath,
svn_revnum_t src_revision,
const char *dst_relpath,
svn_revnum_t replaces_rev,
apr_pool_t *scratch_pool);
/** @see svn_editor_complete(), svn_editor_t.
* @since New in 1.8.
*/
typedef svn_error_t *(*svn_editor_cb_complete_t)(
void *baton,
apr_pool_t *scratch_pool);
/** @see svn_editor_abort(), svn_editor_t.
* @since New in 1.8.
*/
typedef svn_error_t *(*svn_editor_cb_abort_t)(
void *baton,
apr_pool_t *scratch_pool);
/** @} */
/** These functions create an editor instance so that it can be driven.
*
* @defgroup svn_editor_create Editor creation
* @{
*/
/** Allocate an #svn_editor_t instance from @a result_pool, store
* @a editor_baton, @a cancel_func and @a cancel_baton in the new instance
* and return it in @a editor.
* @a scratch_pool is used for temporary allocations (if any). Note that
* this is NOT the same @a scratch_pool that is passed to callback functions.
* @see svn_editor_t
* @since New in 1.8.
*/
svn_error_t *
svn_editor_create(svn_editor_t **editor,
void *editor_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/** Return an editor's private baton.
*
* In some cases, the baton is required outside of the callbacks. This
* function returns the private baton for use.
*
* @since New in 1.8.
*/
void *
svn_editor_get_baton(const svn_editor_t *editor);
/** Sets the #svn_editor_cb_add_directory_t callback in @a editor
* to @a callback.
* @a scratch_pool is used for temporary allocations (if any).
* @see also svn_editor_setcb_many().
* @since New in 1.8.
*/
svn_error_t *
svn_editor_setcb_add_directory(svn_editor_t *editor,
svn_editor_cb_add_directory_t callback,
apr_pool_t *scratch_pool);
/** Sets the #svn_editor_cb_add_file_t callback in @a editor
* to @a callback.
* @a scratch_pool is used for temporary allocations (if any).
* @see also svn_editor_setcb_many().
* @since New in 1.8.
*/
svn_error_t *
svn_editor_setcb_add_file(svn_editor_t *editor,
svn_editor_cb_add_file_t callback,
apr_pool_t *scratch_pool);
/** Sets the #svn_editor_cb_add_symlink_t callback in @a editor
* to @a callback.
* @a scratch_pool is used for temporary allocations (if any).
* @see also svn_editor_setcb_many().
* @since New in 1.8.
*/
svn_error_t *
svn_editor_setcb_add_symlink(svn_editor_t *editor,
svn_editor_cb_add_symlink_t callback,
apr_pool_t *scratch_pool);
/** Sets the #svn_editor_cb_add_absent_t callback in @a editor
* to @a callback.
* @a scratch_pool is used for temporary allocations (if any).
* @see also svn_editor_setcb_many().
* @since New in 1.8.
*/
svn_error_t *
svn_editor_setcb_add_absent(svn_editor_t *editor,
svn_editor_cb_add_absent_t callback,
apr_pool_t *scratch_pool);
/** Sets the #svn_editor_cb_alter_directory_t callback in @a editor
* to @a callback.
* @a scratch_pool is used for temporary allocations (if any).
* @see also svn_editor_setcb_many().
* @since New in 1.8.
*/
svn_error_t *
svn_editor_setcb_alter_directory(svn_editor_t *editor,
svn_editor_cb_alter_directory_t callback,
apr_pool_t *scratch_pool);
/** Sets the #svn_editor_cb_alter_file_t callback in @a editor
* to @a callback.
* @a scratch_pool is used for temporary allocations (if any).
* @see also svn_editor_setcb_many().
* @since New in 1.8.
*/
svn_error_t *
svn_editor_setcb_alter_file(svn_editor_t *editor,
svn_editor_cb_alter_file_t callback,
apr_pool_t *scratch_pool);
/** Sets the #svn_editor_cb_alter_symlink_t callback in @a editor
* to @a callback.
* @a scratch_pool is used for temporary allocations (if any).
* @see also svn_editor_setcb_many().
* @since New in 1.8.
*/
svn_error_t *
svn_editor_setcb_alter_symlink(svn_editor_t *editor,
svn_editor_cb_alter_symlink_t callback,
apr_pool_t *scratch_pool);
/** Sets the #svn_editor_cb_delete_t callback in @a editor
* to @a callback.
* @a scratch_pool is used for temporary allocations (if any).
* @see also svn_editor_setcb_many().
* @since New in 1.8.
*/
svn_error_t *
svn_editor_setcb_delete(svn_editor_t *editor,
svn_editor_cb_delete_t callback,
apr_pool_t *scratch_pool);
/** Sets the #svn_editor_cb_copy_t callback in @a editor
* to @a callback.
* @a scratch_pool is used for temporary allocations (if any).
* @see also svn_editor_setcb_many().
* @since New in 1.8.
*/
svn_error_t *
svn_editor_setcb_copy(svn_editor_t *editor,
svn_editor_cb_copy_t callback,
apr_pool_t *scratch_pool);
/** Sets the #svn_editor_cb_move_t callback in @a editor
* to @a callback.
* @a scratch_pool is used for temporary allocations (if any).
* @see also svn_editor_setcb_many().
* @since New in 1.8.
*/
svn_error_t *
svn_editor_setcb_move(svn_editor_t *editor,
svn_editor_cb_move_t callback,
apr_pool_t *scratch_pool);
/** Sets the #svn_editor_cb_complete_t callback in @a editor
* to @a callback.
* @a scratch_pool is used for temporary allocations (if any).
* @see also svn_editor_setcb_many().
* @since New in 1.8.
*/
svn_error_t *
svn_editor_setcb_complete(svn_editor_t *editor,
svn_editor_cb_complete_t callback,
apr_pool_t *scratch_pool);
/** Sets the #svn_editor_cb_abort_t callback in @a editor
* to @a callback.
* @a scratch_pool is used for temporary allocations (if any).
* @see also svn_editor_setcb_many().
* @since New in 1.8.
*/
svn_error_t *
svn_editor_setcb_abort(svn_editor_t *editor,
svn_editor_cb_abort_t callback,
apr_pool_t *scratch_pool);
/** Lists a complete set of editor callbacks.
* This is a convenience structure.
* @see svn_editor_setcb_many(), svn_editor_create(), svn_editor_t.
* @since New in 1.8.
*/
typedef struct svn_editor_cb_many_t
{
svn_editor_cb_add_directory_t cb_add_directory;
svn_editor_cb_add_file_t cb_add_file;
svn_editor_cb_add_symlink_t cb_add_symlink;
svn_editor_cb_add_absent_t cb_add_absent;
svn_editor_cb_alter_directory_t cb_alter_directory;
svn_editor_cb_alter_file_t cb_alter_file;
svn_editor_cb_alter_symlink_t cb_alter_symlink;
svn_editor_cb_delete_t cb_delete;
svn_editor_cb_copy_t cb_copy;
svn_editor_cb_move_t cb_move;
svn_editor_cb_complete_t cb_complete;
svn_editor_cb_abort_t cb_abort;
} svn_editor_cb_many_t;
/** Sets all the callback functions in @a editor at once, according to the
* callback functions stored in @a many.
* @a scratch_pool is used for temporary allocations (if any).
* @since New in 1.8.
*/
svn_error_t *
svn_editor_setcb_many(svn_editor_t *editor,
const svn_editor_cb_many_t *many,
apr_pool_t *scratch_pool);
/** @} */
/** These functions are called by the tree delta driver to edit the target.
*
* @see svn_editor_t.
*
* @defgroup svn_editor_drive Driving the editor
* @{
*/
/** Drive @a editor's #svn_editor_cb_add_directory_t callback.
*
* Create a new directory at @a relpath. The immediate parent of @a relpath
* is expected to exist.
*
* For descriptions of @a props and @a replaces_rev, see
* svn_editor_add_file().
*
* A complete listing of the immediate children of @a relpath that will be
* added subsequently is given in @a children. @a children is an array of
* const char*s, each giving the basename of an immediate child. It is an
* error to pass NULL for @a children; use an empty array to indicate
* the new directory will have no children.
*
* For all restrictions on driving the editor, see #svn_editor_t.
*/
svn_error_t *
svn_editor_add_directory(svn_editor_t *editor,
const char *relpath,
const apr_array_header_t *children,
apr_hash_t *props,
svn_revnum_t replaces_rev);
/** Drive @a editor's #svn_editor_cb_add_file_t callback.
*
* Create a new file at @a relpath. The immediate parent of @a relpath
* is expected to exist.
*
* The file's contents are specified in @a contents which has a checksum
* matching @a checksum. Both values must be non-NULL.
*
* Set the properties of the new file to @a props, which is an
* apr_hash_t holding key-value pairs. Each key is a const char* of a
* property name, each value is a const svn_string_t*. If no properties are
* being set on the new file, @a props must be the empty hash. It is an
* error to pass NULL for @a props.
*
* If this add is expected to replace a previously existing file, symlink or
* directory at @a relpath, the revision number of the node to be replaced
* must be given in @a replaces_rev. Otherwise, @a replaces_rev must be
* #SVN_INVALID_REVNUM. Note: it is not allowed to call a "delete" followed
* by an "add" on the same path. Instead, an "add" with @a replaces_rev set
* accordingly MUST be used.
*
* For all restrictions on driving the editor, see #svn_editor_t.
* @since New in 1.8.
*/
svn_error_t *
svn_editor_add_file(svn_editor_t *editor,
const char *relpath,
const svn_checksum_t *checksum,
svn_stream_t *contents,
apr_hash_t *props,
svn_revnum_t replaces_rev);
/** Drive @a editor's #svn_editor_cb_add_symlink_t callback.
*
* Create a new symbolic link at @a relpath, with a link target of @a
* target. The immediate parent of @a relpath is expected to exist.
*
* For descriptions of @a props and @a replaces_rev, see
* svn_editor_add_file().
*
* For all restrictions on driving the editor, see #svn_editor_t.
* @since New in 1.8.
*/
svn_error_t *
svn_editor_add_symlink(svn_editor_t *editor,
const char *relpath,
const char *target,
apr_hash_t *props,
svn_revnum_t replaces_rev);
/** Drive @a editor's #svn_editor_cb_add_absent_t callback.
*
* Create an "absent" node of kind @a kind at @a relpath. The immediate
* parent of @a relpath is expected to exist.
* ### TODO @todo explain "absent".
* ### JAF: What are the allowed values of 'kind'?
*
* For a description of @a replaces_rev, see svn_editor_add_file().
*
* For all restrictions on driving the editor, see #svn_editor_t.
* @since New in 1.8.
*/
svn_error_t *
svn_editor_add_absent(svn_editor_t *editor,
const char *relpath,
svn_node_kind_t kind,
svn_revnum_t replaces_rev);
/** Drive @a editor's #svn_editor_cb_alter_directory_t callback.
*
* Alter the properties of the directory at @a relpath.
*
* @a revision specifies the revision at which the receiver should
* expect to find this node. That is, @a relpath at the start of the
* whole edit and @a relpath at @a revision must lie within the same
* node-rev (aka location history segment). This information may be used
* to catch an attempt to alter and out-of-date directory. If the
* directory does not have a corresponding revision in the repository
* (e.g. it has not yet been committed), then @a revision should be
* #SVN_INVALID_REVNUM.
*
* If any changes to the set of children will be made in the future of
* the edit drive, then @a children MUST specify the resulting set of
* children. See svn_editor_add_directory() for the format of @a children.
* If not changes will be made, then NULL may be specified.
*
* For a description of @a props, see svn_editor_add_file(). If no changes
* to the properties will be made (ie. only future changes to the set of
* children), then @a props may be NULL.
*
* It is an error to pass NULL for both @a children and @a props.
*
* For all restrictions on driving the editor, see #svn_editor_t.
* @since New in 1.8.
*/
svn_error_t *
svn_editor_alter_directory(svn_editor_t *editor,
const char *relpath,
svn_revnum_t revision,
const apr_array_header_t *children,
apr_hash_t *props);
/** Drive @a editor's #svn_editor_cb_alter_file_t callback.
*
* Alter the properties and/or the contents of the file at @a relpath
* with @a revision as its expected revision. See svn_editor_alter_directory()
* for more information about @a revision.
*
* If @a props is non-NULL, then the properties will be applied.
*
* If @a contents is non-NULL, then the stream will be copied to
* the file, and its checksum must match @a checksum (which must also
* be non-NULL). If @a contents is NULL, then @a checksum must also
* be NULL, and no change will be applied to the file's contents.
*
* The properties and/or the contents must be changed. It is an error to
* pass NULL for @a props, @a checksum, and @a contents.
*
* For a description of @a checksum and @a contents see
* svn_editor_add_file(). This function allows @a props to be NULL, but
* the parameter is otherwise described by svn_editor_add_file().
*
* For all restrictions on driving the editor, see #svn_editor_t.
* @since New in 1.8.
*/
svn_error_t *
svn_editor_alter_file(svn_editor_t *editor,
const char *relpath,
svn_revnum_t revision,
const svn_checksum_t *checksum,
svn_stream_t *contents,
apr_hash_t *props);
/** Drive @a editor's #svn_editor_cb_alter_symlink_t callback.
*
* Alter the properties and/or the target of the symlink at @a relpath
* with @a revision as its expected revision. See svn_editor_alter_directory()
* for more information about @a revision.
*
* If @a props is non-NULL, then the properties will be applied.
*
* If @a target is non-NULL, then the symlink's target will be updated.
*
* The properties and/or the target must be changed. It is an error to
* pass NULL for @a props and @a target.
*
* This function allows @a props to be NULL, but the parameter is
* otherwise described by svn_editor_add_file().
*
* For all restrictions on driving the editor, see #svn_editor_t.
* @since New in 1.8.
*/
svn_error_t *
svn_editor_alter_symlink(svn_editor_t *editor,
const char *relpath,
svn_revnum_t revision,
const char *target,
apr_hash_t *props);
/** Drive @a editor's #svn_editor_cb_delete_t callback.
*
* Delete the existing node at @a relpath, expected to be identical to
* revision @a revision of that path.
*
* For all restrictions on driving the editor, see #svn_editor_t.
* @since New in 1.8.
*/
svn_error_t *
svn_editor_delete(svn_editor_t *editor,
const char *relpath,
svn_revnum_t revision);
/** Drive @a editor's #svn_editor_cb_copy_t callback.
*
* Copy the node at @a src_relpath, expected to be identical to revision @a
* src_revision of that path, to @a dst_relpath.
*
* For a description of @a replaces_rev, see svn_editor_add_file().
*
* @note See the general instructions on paths for this API. Since the
* @a src_relpath argument must generally be able to reference any node
* in the repository, the implication is that the editor's root must be
* the repository root.
*
* For all restrictions on driving the editor, see #svn_editor_t.
* @since New in 1.8.
*/
svn_error_t *
svn_editor_copy(svn_editor_t *editor,
const char *src_relpath,
svn_revnum_t src_revision,
const char *dst_relpath,
svn_revnum_t replaces_rev);
/** Drive @a editor's #svn_editor_cb_move_t callback.
*
* Move the node at @a src_relpath to @a dst_relpath.
*
* @a src_revision specifies the revision at which the receiver should
* expect to find this node. That is, @a src_relpath at the start of
* the whole edit and @a src_relpath at @a src_revision must lie within
* the same node-rev (aka history-segment). This is just like the
* revisions specified to svn_editor_delete().
*
* For a description of @a replaces_rev, see svn_editor_add_file().
*
* ### what happens if one side of this move is not "within" the receiver's
* ### set of paths?
*
* For all restrictions on driving the editor, see #svn_editor_t.
* @since New in 1.8.
*/
svn_error_t *
svn_editor_move(svn_editor_t *editor,
const char *src_relpath,
svn_revnum_t src_revision,
const char *dst_relpath,
svn_revnum_t replaces_rev);
/** Drive @a editor's #svn_editor_cb_complete_t callback.
*
* Send word that the edit has been completed successfully.
*
* For all restrictions on driving the editor, see #svn_editor_t.
* @since New in 1.8.
*/
svn_error_t *
svn_editor_complete(svn_editor_t *editor);
/** Drive @a editor's #svn_editor_cb_abort_t callback.
*
* Notify that the edit transmission was not successful.
* ### TODO @todo Shouldn't we add a reason-for-aborting argument?
*
* For all restrictions on driving the editor, see #svn_editor_t.
* @since New in 1.8.
*/
svn_error_t *
svn_editor_abort(svn_editor_t *editor);
/** @} */
/** @} */
/** A temporary API which conditionally inserts a double editor shim
* into the chain of delta editors. Used for testing Editor v2.
*
* Whether or not the shims are inserted is controlled by a compile-time
* option in libsvn_delta/compat.c.
*
* @note The use of these shims and this API will likely cause all kinds
* of performance degredation. (Which is actually a moot point since they
* don't even work properly yet anyway.)
*/
svn_error_t *
svn_editor__insert_shims(const svn_delta_editor_t **deditor_out,
void **dedit_baton_out,
const svn_delta_editor_t *deditor_in,
void *dedit_baton_in,
const char *repos_root,
const char *base_dir,
svn_delta_shim_callbacks_t *shim_callbacks,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* SVN_EDITOR_H */