summaryrefslogtreecommitdiff
path: root/subversion/include/private/svn_editor.h
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/include/private/svn_editor.h')
-rw-r--r--subversion/include/private/svn_editor.h641
1 files changed, 458 insertions, 183 deletions
diff --git a/subversion/include/private/svn_editor.h b/subversion/include/private/svn_editor.h
index 38c3e2b..d714bb1 100644
--- a/subversion/include/private/svn_editor.h
+++ b/subversion/include/private/svn_editor.h
@@ -32,11 +32,90 @@
#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
@@ -79,15 +158,15 @@ extern "C" {
* coupling between those subsystems.
*
* The set of changes, and the data necessary to describe it entirely, is
- * completely unbounded. An addition of one simple 20Gb file would be well
- * past the available memory of any machine processing these operations.
+ * 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.
*
*
- * HISTORY
+ * <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
@@ -96,7 +175,7 @@ extern "C" {
* 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 "@c svn_delta_editor_t" interface focused
+ * 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
@@ -105,7 +184,7 @@ extern "C" {
* a set of operations describing the change, and a "receiver" accepts and
* applies them to its tree.
*
- * The classic interface was named "@c svn_delta_editor_t" and was described
+ * 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.
@@ -117,12 +196,51 @@ extern "C" {
* 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>
*
@@ -146,12 +264,13 @@ extern "C" {
* svn_editor_setcb_add_file() \n
* svn_editor_setcb_add_symlink() \n
* svn_editor_setcb_add_absent() \n
- * svn_editor_setcb_set_props() \n
- * svn_editor_setcb_set_text() \n
- * svn_editor_setcb_set_target() \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_rotate() \n
* svn_editor_setcb_complete() \n
* svn_editor_setcb_abort()
*
@@ -168,17 +287,18 @@ extern "C" {
* svn_editor_add_file() \n
* svn_editor_add_symlink() \n
* svn_editor_add_absent() \n
- * svn_editor_set_props() \n
- * svn_editor_set_text() \n
- * svn_editor_set_target() \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()
+ * svn_editor_move() \n
+ * svn_editor_rotate()
* \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
+ * 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.
@@ -205,33 +325,42 @@ extern "C" {
* 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/rotated, 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.
*
- * - svn_editor_add_file() -- An svn_editor_set_text() call must follow
- * for the same path (at some point).
- *
- * - svn_editor_set_props()
- * - The @a complete argument must be TRUE if no more calls will follow on
- * the same path. @a complete must always be TRUE for directories.
- * - If @a complete is FALSE, and:
- * - if @a relpath is a file, this must (at some point) be followed by
- * an svn_editor_set_text() call on the same path.
- * - if @a relpath is a symlink, this must (at some point) be followed by
- * an svn_editor_set_target() call on the same path.
- *
- * - svn_editor_set_text() and svn_editor_set_target() must always occur
- * @b after an svn_editor_set_props() or svn_editor_add_file() call on
- * the same path, if any.\n
- * In other words, if there are two calls coming in on the same path, the
- * first of them has to be either svn_editor_set_props() or
- * svn_editor_add_file().
+ * - 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, move, or rotate 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). Paths listed in a rotation are both sources and
+ * destinations, so they may not be referenced again in an add_* or a
+ * deletion; these paths may have alter_* operations applied.
+ *
+ * - The ancestor of an added, copied-here, moved-here, rotated, 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
@@ -242,6 +371,13 @@ extern "C" {
* - 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.
+ *
+ * - Paths mentioned in svn_editor_rotate() may have their properties
+ * and contents edited (via alter_* calls) by a previous or later call,
+ * but they may not be subject to a later move, rotate, or deletion.
*
* - One of svn_editor_complete() or svn_editor_abort() must be called
* exactly once, which must be the final call the driver invokes.
@@ -250,19 +386,16 @@ extern "C" {
* svn_editor_abort() must imply that the transformation was not completed
* successfully.
*
- * - If any callback invocation returns with an error, the driver must
- * invoke svn_editor_abort() and stop transmitting operations.
+ * - 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, except for the following pairs, where a change must be completed
- * when receiving the second callback in each pair:
- * - svn_editor_add_file() and svn_editor_set_text()
- * - svn_editor_set_props() (if @a complete is FALSE) and
- * svn_editor_set_text() (if the node is a file)
- * - svn_editor_set_props() (if @a complete is FALSE) and
- * svn_editor_set_target() (if the node is a symbolic link)
+ *
+ * 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.
@@ -276,16 +409,34 @@ extern "C" {
* 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 path for the paths sent and received via the
- * callbacks' @a relpath arguments.
- *
- * For example, during an "update", the driver has a working copy checked
- * out at a specific repository URL. The receiver sees the repository as a
- * whole. 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.
+ * 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>
@@ -322,16 +473,19 @@ extern "C" {
* context.
*
*
- * ### TODO @todo anything missing? -- allow text and prop change to follow
- * a move or copy. -- set_text() vs. apply_text_delta()? -- If a
- * set_props/set_text/set_target/copy/move/delete in a merge source is
- * applied to a different branch, which side will REVISION arguments reflect
- * and is there still a problem?
+ * @todo ### TODO anything missing?
*
- * @since New in 1.7.
+ * @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.
@@ -358,7 +512,7 @@ typedef struct svn_editor_t svn_editor_t;
*/
/** @see svn_editor_add_directory(), svn_editor_t.
- * @since New in 1.7.
+ * @since New in 1.8.
*/
typedef svn_error_t *(*svn_editor_cb_add_directory_t)(
void *baton,
@@ -369,17 +523,19 @@ typedef svn_error_t *(*svn_editor_cb_add_directory_t)(
apr_pool_t *scratch_pool);
/** @see svn_editor_add_file(), svn_editor_t.
- * @since New in 1.7.
+ * @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.7.
+ * @since New in 1.8.
*/
typedef svn_error_t *(*svn_editor_cb_add_symlink_t)(
void *baton,
@@ -390,7 +546,7 @@ typedef svn_error_t *(*svn_editor_cb_add_symlink_t)(
apr_pool_t *scratch_pool);
/** @see svn_editor_add_absent(), svn_editor_t.
- * @since New in 1.7.
+ * @since New in 1.8.
*/
typedef svn_error_t *(*svn_editor_cb_add_absent_t)(
void *baton,
@@ -399,40 +555,42 @@ typedef svn_error_t *(*svn_editor_cb_add_absent_t)(
svn_revnum_t replaces_rev,
apr_pool_t *scratch_pool);
-/** @see svn_editor_set_props(), svn_editor_t.
- * @since New in 1.7.
+/** @see svn_editor_alter_directory(), svn_editor_t.
+ * @since New in 1.8.
*/
-typedef svn_error_t *(*svn_editor_cb_set_props_t)(
+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,
- svn_boolean_t complete,
apr_pool_t *scratch_pool);
-/** @see svn_editor_set_text(), svn_editor_t.
- * @since New in 1.7.
+/** @see svn_editor_alter_file(), svn_editor_t.
+ * @since New in 1.8.
*/
-typedef svn_error_t *(*svn_editor_cb_set_text_t)(
+typedef svn_error_t *(*svn_editor_cb_alter_file_t)(
void *baton,
const char *relpath,
svn_revnum_t revision,
+ apr_hash_t *props,
const svn_checksum_t *checksum,
svn_stream_t *contents,
apr_pool_t *scratch_pool);
-/** @see svn_editor_set_target(), svn_editor_t.
- * @since New in 1.7.
+/** @see svn_editor_alter_symlink(), svn_editor_t.
+ * @since New in 1.8.
*/
-typedef svn_error_t *(*svn_editor_cb_set_target_t)(
+typedef svn_error_t *(*svn_editor_cb_alter_symlink_t)(
void *baton,
const char *relpath,
svn_revnum_t revision,
+ apr_hash_t *props,
const char *target,
apr_pool_t *scratch_pool);
/** @see svn_editor_delete(), svn_editor_t.
- * @since New in 1.7.
+ * @since New in 1.8.
*/
typedef svn_error_t *(*svn_editor_cb_delete_t)(
void *baton,
@@ -441,7 +599,7 @@ typedef svn_error_t *(*svn_editor_cb_delete_t)(
apr_pool_t *scratch_pool);
/** @see svn_editor_copy(), svn_editor_t.
- * @since New in 1.7.
+ * @since New in 1.8.
*/
typedef svn_error_t *(*svn_editor_cb_copy_t)(
void *baton,
@@ -452,7 +610,7 @@ typedef svn_error_t *(*svn_editor_cb_copy_t)(
apr_pool_t *scratch_pool);
/** @see svn_editor_move(), svn_editor_t.
- * @since New in 1.7.
+ * @since New in 1.8.
*/
typedef svn_error_t *(*svn_editor_cb_move_t)(
void *baton,
@@ -462,15 +620,24 @@ typedef svn_error_t *(*svn_editor_cb_move_t)(
svn_revnum_t replaces_rev,
apr_pool_t *scratch_pool);
+/** @see svn_editor_rotate(), svn_editor_t.
+ * @since New in 1.8.
+ */
+typedef svn_error_t *(*svn_editor_cb_rotate_t)(
+ void *baton,
+ const apr_array_header_t *relpaths,
+ const apr_array_header_t *revisions,
+ apr_pool_t *scratch_pool);
+
/** @see svn_editor_complete(), svn_editor_t.
- * @since New in 1.7.
+ * @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.7.
+ * @since New in 1.8.
*/
typedef svn_error_t *(*svn_editor_cb_abort_t)(
void *baton,
@@ -491,7 +658,7 @@ typedef svn_error_t *(*svn_editor_cb_abort_t)(
* @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.7.
+ * @since New in 1.8.
*/
svn_error_t *
svn_editor_create(svn_editor_t **editor,
@@ -502,11 +669,22 @@ svn_editor_create(svn_editor_t **editor,
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.7.
+ * @since New in 1.8.
*/
svn_error_t *
svn_editor_setcb_add_directory(svn_editor_t *editor,
@@ -517,7 +695,7 @@ svn_editor_setcb_add_directory(svn_editor_t *editor,
* to @a callback.
* @a scratch_pool is used for temporary allocations (if any).
* @see also svn_editor_setcb_many().
- * @since New in 1.7.
+ * @since New in 1.8.
*/
svn_error_t *
svn_editor_setcb_add_file(svn_editor_t *editor,
@@ -528,7 +706,7 @@ svn_editor_setcb_add_file(svn_editor_t *editor,
* to @a callback.
* @a scratch_pool is used for temporary allocations (if any).
* @see also svn_editor_setcb_many().
- * @since New in 1.7.
+ * @since New in 1.8.
*/
svn_error_t *
svn_editor_setcb_add_symlink(svn_editor_t *editor,
@@ -539,51 +717,51 @@ svn_editor_setcb_add_symlink(svn_editor_t *editor,
* to @a callback.
* @a scratch_pool is used for temporary allocations (if any).
* @see also svn_editor_setcb_many().
- * @since New in 1.7.
+ * @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_set_props_t callback in @a editor
+/** 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.7.
+ * @since New in 1.8.
*/
svn_error_t *
-svn_editor_setcb_set_props(svn_editor_t *editor,
- svn_editor_cb_set_props_t callback,
- apr_pool_t *scratch_pool);
+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_set_text_t callback in @a editor
+/** 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.7.
+ * @since New in 1.8.
*/
svn_error_t *
-svn_editor_setcb_set_text(svn_editor_t *editor,
- svn_editor_cb_set_text_t callback,
- apr_pool_t *scratch_pool);
+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_set_target_t callback in @a editor
+/** 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.7.
+ * @since New in 1.8.
*/
svn_error_t *
-svn_editor_setcb_set_target(svn_editor_t *editor,
- svn_editor_cb_set_target_t callback,
- apr_pool_t *scratch_pool);
+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.7.
+ * @since New in 1.8.
*/
svn_error_t *
svn_editor_setcb_delete(svn_editor_t *editor,
@@ -594,7 +772,7 @@ svn_editor_setcb_delete(svn_editor_t *editor,
* to @a callback.
* @a scratch_pool is used for temporary allocations (if any).
* @see also svn_editor_setcb_many().
- * @since New in 1.7.
+ * @since New in 1.8.
*/
svn_error_t *
svn_editor_setcb_copy(svn_editor_t *editor,
@@ -605,18 +783,29 @@ svn_editor_setcb_copy(svn_editor_t *editor,
* to @a callback.
* @a scratch_pool is used for temporary allocations (if any).
* @see also svn_editor_setcb_many().
- * @since New in 1.7.
+ * @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_rotate_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_rotate(svn_editor_t *editor,
+ svn_editor_cb_rotate_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.7.
+ * @since New in 1.8.
*/
svn_error_t *
svn_editor_setcb_complete(svn_editor_t *editor,
@@ -627,7 +816,7 @@ svn_editor_setcb_complete(svn_editor_t *editor,
* to @a callback.
* @a scratch_pool is used for temporary allocations (if any).
* @see also svn_editor_setcb_many().
- * @since New in 1.7.
+ * @since New in 1.8.
*/
svn_error_t *
svn_editor_setcb_abort(svn_editor_t *editor,
@@ -638,7 +827,7 @@ svn_editor_setcb_abort(svn_editor_t *editor,
/** 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.7.
+ * @since New in 1.8.
*/
typedef struct svn_editor_cb_many_t
{
@@ -646,12 +835,13 @@ typedef struct svn_editor_cb_many_t
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_set_props_t cb_set_props;
- svn_editor_cb_set_text_t cb_set_text;
- svn_editor_cb_set_target_t cb_set_target;
+ 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_rotate_t cb_rotate;
svn_editor_cb_complete_t cb_complete;
svn_editor_cb_abort_t cb_abort;
@@ -660,7 +850,7 @@ typedef struct 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.7.
+ * @since New in 1.8.
*/
svn_error_t *
svn_editor_setcb_many(svn_editor_t *editor,
@@ -683,21 +873,14 @@ svn_editor_setcb_many(svn_editor_t *editor,
* Create a new directory at @a relpath. The immediate parent of @a relpath
* is expected to exist.
*
- * Set the properties of the new directory 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 directory, @a props must be NULL.
- *
- * If this add is expected to replace a previously existing file 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 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.
+ * 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.
*/
@@ -713,24 +896,30 @@ svn_editor_add_directory(svn_editor_t *editor,
* 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 NULL.
+ * 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 or
+ * 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
+ * #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.7.
+ * @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);
@@ -743,7 +932,7 @@ svn_editor_add_file(svn_editor_t *editor,
* svn_editor_add_file().
*
* For all restrictions on driving the editor, see #svn_editor_t.
- * @since New in 1.7.
+ * @since New in 1.8.
*/
svn_error_t *
svn_editor_add_symlink(svn_editor_t *editor,
@@ -757,11 +946,12 @@ svn_editor_add_symlink(svn_editor_t *editor,
* 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.7.
+ * @since New in 1.8.
*/
svn_error_t *
svn_editor_add_absent(svn_editor_t *editor,
@@ -769,61 +959,96 @@ svn_editor_add_absent(svn_editor_t *editor,
svn_node_kind_t kind,
svn_revnum_t replaces_rev);
-/** Drive @a editor's #svn_editor_cb_set_props_t callback.
+/** 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.
*
- * Set or change properties on the existing node at @a relpath.
- * ### TODO @todo Does this send *all* properties, always?
- * ### TODO @todo What is REVISION for?
- * ### what about "entry props"? will these still be handled via
- * ### the general prop function?
+ * 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.
*
- * @a complete must be FALSE if and only if
- * - @a relpath is a file and an svn_editor_set_text() call will follow on
- * the same path, or
- * - @a relpath is a symbolic link and an svn_editor_set_target() call will
- * follow on the same path.
+ * 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.7.
+ * @since New in 1.8.
*/
svn_error_t *
-svn_editor_set_props(svn_editor_t *editor,
- const char *relpath,
- svn_revnum_t revision,
- apr_hash_t *props,
- svn_boolean_t complete);
+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_set_text_t callback.
+/** Drive @a editor's #svn_editor_cb_alter_file_t callback.
*
- * Set/change the text content of a file at @a relpath to @a contents
- * with checksum @a checksum.
- * ### TODO @todo Does this send the *complete* content, always?
- * ### TODO @todo What is REVISION for?
+ * 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.7.
+ * @since New in 1.8.
*/
svn_error_t *
-svn_editor_set_text(svn_editor_t *editor,
- const char *relpath,
- svn_revnum_t revision,
- const svn_checksum_t *checksum,
- svn_stream_t *contents);
+svn_editor_alter_file(svn_editor_t *editor,
+ const char *relpath,
+ svn_revnum_t revision,
+ apr_hash_t *props,
+ const svn_checksum_t *checksum,
+ svn_stream_t *contents);
-/** Drive @a editor's #svn_editor_cb_set_target_t callback.
+/** 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.
*
- * Set/change the link target that a symbolic link at @a relpath points at
- * to @a target.
- * ### TODO @todo What is REVISION for?
+ * 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.7.
+ * @since New in 1.8.
*/
svn_error_t *
-svn_editor_set_target(svn_editor_t *editor,
- const char *relpath,
- svn_revnum_t revision,
- const char *target);
+svn_editor_alter_symlink(svn_editor_t *editor,
+ const char *relpath,
+ svn_revnum_t revision,
+ apr_hash_t *props,
+ const char *target);
/** Drive @a editor's #svn_editor_cb_delete_t callback.
*
@@ -831,7 +1056,7 @@ svn_editor_set_target(svn_editor_t *editor,
* revision @a revision of that path.
*
* For all restrictions on driving the editor, see #svn_editor_t.
- * @since New in 1.7.
+ * @since New in 1.8.
*/
svn_error_t *
svn_editor_delete(svn_editor_t *editor,
@@ -845,8 +1070,13 @@ svn_editor_delete(svn_editor_t *editor,
*
* 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.7.
+ * @since New in 1.8.
*/
svn_error_t *
svn_editor_copy(svn_editor_t *editor,
@@ -856,29 +1086,22 @@ svn_editor_copy(svn_editor_t *editor,
svn_revnum_t replaces_rev);
/** Drive @a editor's #svn_editor_cb_move_t callback.
- * Move the node at @a src_relpath, expected to be identical to revision @a
- * src_revision of that path, to @a dst_relpath.
+ *
+ * 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() and svn_editor_rotate().
*
* For a description of @a replaces_rev, see svn_editor_add_file().
*
- * ### stsp: How would I describe a merge of revision range rA-rB,
- * ### within which a file foo.c was delete in rN, re-created in rM,
- * ### and then renamed to bar.c in rX?
- * ### Would the following be valid?
- * ### svn_editor_add_file(ed, "foo.c", props, rN);
- * ### svn_editor_move(ed, "foo.c", rM, "bar.c", rN);
- * ###
- * ### gstein: no, it would be:
- * ### svn_editor_delete(e, "foo.c", rN);
- * ### svn_editor_add_file(e, "foo.c", props, SVN_INVALID_REVNUM);
- * ### svn_editor_move(e, "foo.c", rM, "bar.c", SVN_INVALID_REVNUM);
- * ###
- * ### replaces_rev is to indicate a deletion of the destination node
- * ### that occurs as part of the move. there are no replacements in
- * ### your example.
+ * ### 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.7.
+ * @since New in 1.8.
*/
svn_error_t *
svn_editor_move(svn_editor_t *editor,
@@ -887,23 +1110,53 @@ svn_editor_move(svn_editor_t *editor,
const char *dst_relpath,
svn_revnum_t replaces_rev);
+/** Drive @a editor's #svn_editor_cb_rotate_t callback.
+ *
+ * Perform a rotation among multiple nodes in the target tree.
+ *
+ * The @a relpaths and @a revisions arrays (pair-wise) specify nodes in the
+ * tree which are located at a path and expected to be at a specific
+ * revision. These nodes are simultaneously moved in a rotation pattern.
+ * For example, the node at index 0 of @a relpaths and @a revisions will
+ * be moved to the relpath specified at index 1 of @a relpaths. The node
+ * at index 1 will be moved to the location at index 2. The node at index
+ * N-1 will be moved to the relpath specified at index 0.
+ *
+ * The simplest form of this operation is to swap nodes A and B. One may
+ * think to move A to a temporary location T, then move B to A, then move
+ * T to B. However, this last move violations the Once Rule by moving T
+ * (which had already by edited by the move from A). In order to keep the
+ * restrictions against multiple moves of a single node, the rotation
+ * operation is needed for certain types of tree edits.
+ *
+ * ### what happens if one of the paths of the rotation 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_rotate(svn_editor_t *editor,
+ const apr_array_header_t *relpaths,
+ const apr_array_header_t *revisions);
+
/** Drive @a editor's #svn_editor_cb_complete_t callback.
*
- * Send word that the tree delta has been completed successfully.
+ * Send word that the edit has been completed successfully.
*
* For all restrictions on driving the editor, see #svn_editor_t.
- * @since New in 1.7.
+ * @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 tree delta transmission was not successful.
+ * 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.7.
+ * @since New in 1.8.
*/
svn_error_t *
svn_editor_abort(svn_editor_t *editor);
@@ -912,6 +1165,28 @@ 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 */