summaryrefslogtreecommitdiff
path: root/subversion/include/private/svn_editor.h
blob: d714bb17a00db89a9352ba8c8f47c11b4d9b7d75 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
/**
 * @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_rotate() \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
 *      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
 *    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/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.
 *
 * - 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
 *   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.
 *
 * - 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.
 *   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,
  apr_hash_t *props,
  const svn_checksum_t *checksum,
  svn_stream_t *contents,
  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,
  apr_hash_t *props,
  const char *target,
  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_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.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_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.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_rotate_t cb_rotate;
  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,
                      apr_hash_t *props,
                      const svn_checksum_t *checksum,
                      svn_stream_t *contents);

/** 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,
                         apr_hash_t *props,
                         const char *target);

/** 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() and svn_editor_rotate().
 *
 * 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_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 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 */