summaryrefslogtreecommitdiff
path: root/subversion/include/private/svn_branch.h
blob: 3fbaeb7ef77c37f3a622da5792e508a5e6e5cf53 (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
/**
 * @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_branch.h
 * @brief Operating on a branched version history
 *
 * @since New in ???.
 */

/* Transactions
 *
 * A 'txn' contains a set of changes to the branches/elements.
 *
 * To make changes you say, for example, "for element 5: I want the parent
 * element to be 3 now, and its name to be 'bar', and its content to be
 * {props=... text=...}". That sets up a move and/or rename and/or
 * content-change (or possibly a no-op for all three aspects) for element 5.
 *
 * Before or after (or at the same time, if we make a parallelizable
 * implementation) we can make edits to the other elements, including
 * element 3.
 *
 * So at the time of the edit method 'change e5: let its parent be e3'
 * we might or might not have even created e3, if that happens to be an
 * element that we wish to create rather than one that already existed.
 *
 * We allow this non-ordering because we want the changes to different
 * elements to be totally independent.
 *
 * So at any given 'moment' in time during specifying the changes to a
 * txn, the txn state is not necessarily one that maps directly to a
 * flat tree (single-rooted, no cycles, no clashes of paths, etc.).
 *
 * Once we've finished specifying the edits, then the txn state will be
 * converted to a flat tree, and that's the final result. But we can't
 * query an arbitrary txn (potentially in the middle of making changes
 * to it) by path, because the paths are not fully defined yet.
 *
 * So there are three kinds of operations:
 *
 * - query involving paths
 *   => requires a flat tree state to query, not an in-progress txn
 *
 * - query, not involving paths
 *   => accepts a txn-in-progress or a flat tree
 *
 * - modify (not involving paths)
 *   => requires a txn
 *
 * Currently, a txn is represented by 'svn_branch__txn_t', with
 * 'svn_branch__state_t' for the individual branches in it. A flat tree is
 * represented by 'svn_branch__subtree_t'. But there is currently not a
 * clean separation; there is some overlap and some warts such as the
 * 'svn_branch__txn_sequence_point' method.
 */


#ifndef SVN_BRANCH_H
#define SVN_BRANCH_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"

#include "private/svn_element.h"

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */


/* ### */
#define SVN_BRANCH__ERR 123456

/** Element Identifier (EID).
 *
 * An element may appear in any or all branches, and its EID is the same in
 * each branch in which the element appears.
 * 
 * By definition, an element keeps the same EID for its whole lifetime, even
 * if deleted from all branches and later 'resurrected'.
 *
 * In principle, an EID is an arbitrary token and has no intrinsic
 * relationships (except equality) to other EIDs. The current implementation
 * uses integers and allocates them sequentially from a central counter, but
 * the implementation may be changed.
 *
 * ### In most places the code currently says 'int', verbatim.
 */
typedef int svn_branch__eid_t;

typedef struct svn_branch__el_rev_id_t svn_branch__el_rev_id_t;

typedef struct svn_branch__rev_bid_eid_t svn_branch__rev_bid_eid_t;

typedef struct svn_branch__rev_bid_t svn_branch__rev_bid_t;

typedef struct svn_branch__state_t svn_branch__state_t;

/* Per-repository branching info.
 */
typedef struct svn_branch__repos_t svn_branch__repos_t;

/* Methods (conceptually public, but called indirectly) for a transaction.
 */
typedef struct svn_branch__txn_vtable_t svn_branch__txn_vtable_t;

/* Private data for a transaction.
 */
typedef struct svn_branch__txn_priv_t svn_branch__txn_priv_t;

/* A container for all the branching metadata for a specific revision (or
 * an uncommitted transaction).
 */
typedef struct svn_branch__txn_t
{
  /* Methods (conceptually public, but called indirectly). */
  svn_branch__txn_vtable_t *vtable;

  /* Private data. */
  svn_branch__txn_priv_t *priv;

  /* Public data. */

  /* The repository in which this revision exists. */
  svn_branch__repos_t *repos;

  /* If committed, the revision number; else SVN_INVALID_REVNUM. */
  svn_revnum_t rev;

  /* If committed, the previous revision number, else the revision number
     on which this transaction is based. */
  svn_revnum_t base_rev;

} svn_branch__txn_t;

/* Create a new branch txn object.
 */
svn_branch__txn_t *
svn_branch__txn_create(const svn_branch__txn_vtable_t *vtable,
                       svn_cancel_func_t cancel_func,
                       void *cancel_baton,
                       apr_pool_t *result_pool);

/* Return all the branches in TXN.
 *
 * These branches are available for reading. (Some of them may also be
 * mutable.)
 *
 * ### Rename to 'list_branches' & return only their ids?
 *
 * Return an empty array if there are none.
 */
apr_array_header_t *
svn_branch__txn_get_branches(const svn_branch__txn_t *txn,
                             apr_pool_t *result_pool);

/* Return the branch whose id is BRANCH_ID in TXN.
 *
 * Return NULL if not found.
 *
 * Note: a branch id is, in behavioural terms, an arbitrary token. In the
 * current implementation it is constructed from the hierarchy of subbranch
 * root EIDs leading to the branch, but that may be changed in future.
 *
 * See also: svn_branch__get_id().
 */
svn_branch__state_t *
svn_branch__txn_get_branch_by_id(const svn_branch__txn_t *txn,
                                 const char *branch_id,
                                 apr_pool_t *scratch_pool);

svn_error_t *
svn_branch__txn_get_num_new_eids(const svn_branch__txn_t *txn,
                                 int *num_new_eids_p,
                                 apr_pool_t *scratch_pool);

/* Assign a new txn-scope element id in TXN.
 */
svn_error_t *
svn_branch__txn_new_eid(svn_branch__txn_t *txn,
                        int *new_eid_p,
                        apr_pool_t *scratch_pool);

/** Open for writing, either a new branch or an existing branch.
 *
 * When creating a new branch, declare its root element id to be ROOT_EID. Do
 * not instantiate the root element, nor any other elements.
 *
 * TREE_REF specifies the initial tree content, by reference to a committed
 * tree. It overwrites any existing tree, even if the branch was already
 * mutable in the txn.
 *
 * If TREE_REF is null, then the initial tree is empty for a new branch
 * (not already present in the txn), or the branch's current tree if the
 * branch was already present (readable or mutable) in the txn.
 *
 * ### TODO: Take a 'history' parameter; 'none' is a valid option.
 *
 * We use a common 'open subbranch' method for both 'find' and 'add'
 * cases, according to the principle that 'editing' a txn should dictate
 * the new state without reference to the old state.
 *
 * This method returns a mutable 'branch state' object which is a part of
 * the txn.
 *
 * ### When opening ('finding') an existing branch, ROOT_EID should match
 *     it. (Should we check, and throw an error if not?)
 */
svn_error_t *
svn_branch__txn_open_branch(svn_branch__txn_t *txn,
                            svn_branch__state_t **new_branch_p,
                            const char *branch_id,
                            int root_eid,
                            svn_branch__rev_bid_eid_t *tree_ref,
                            apr_pool_t *result_pool,
                            apr_pool_t *scratch_pool);

/** Register a sequence point.
 *
 * At a sequence point, elements are arranged in a tree hierarchy: each
 * element has exactly one parent element, except the root, and so on.
 * Translation between paths and element addressing is defined only at
 * a sequence point.
 *
 * The other edit operations -- add, alter, delete, etc. -- result in a
 * state that is not a sequence point.
 *
 * The new transaction begins at a sequence point. Completion of editing
 * (svn_branch__txn_complete()) also creates a sequence point.
 */
svn_error_t *
svn_branch__txn_sequence_point(svn_branch__txn_t *txn,
                               apr_pool_t *scratch_pool);

/** Finalize this transaction.
 *
 * Notify that the edit has been completed successfully.
 */
svn_error_t *
svn_branch__txn_complete(svn_branch__txn_t *txn,
                         apr_pool_t *scratch_pool);

/** Abandon this transaction.
 *
 * Notify that editing this transaction was not successful.
 */
svn_error_t *
svn_branch__txn_abort(svn_branch__txn_t *txn,
                      apr_pool_t *scratch_pool);

/* Change txn-local EIDs (negative integers) in TXN to revision EIDs, by
 * assigning a new revision-EID (positive integer) for each one.
 *
 * Rewrite TXN->first_eid and TXN->next_eid accordingly.
 */
svn_error_t *
svn_branch__txn_finalize_eids(svn_branch__txn_t *txn,
                              apr_pool_t *scratch_pool);

/* Often, branches have the same root element. For example,
 * branching /trunk to /branches/br1 results in:
 *
 *      branch 1: (root-EID=100)
 *          EID 100 => /trunk
 *          ...
 *      branch 2: (root-EID=100)
 *          EID 100 => /branches/br1
 *          ...
 *
 * However, the root element of one branch may correspond to a non-root
 * element of another branch.
 *
 * Continuing the same example, branching from the trunk subtree
 * /trunk/D (which is not itself a branch root) results in:
 *
 *      branch 3: (root-EID=104)
 *          EID 100 => (nil)
 *          ...
 *          EID 104 => /branches/branch-of-trunk-subtree-D
 *          ...
 */

/* Methods (conceptually public, but called indirectly) for a branch state.
 */
typedef struct svn_branch__state_vtable_t svn_branch__state_vtable_t;

/* Private data for a branch state.
 */
typedef struct svn_branch__state_priv_t svn_branch__state_priv_t;

/* A branch state.
 *
 * A branch state object describes one version of one branch.
 */
struct svn_branch__state_t
{
  /* Methods (conceptually public, but called indirectly). */
  svn_branch__state_vtable_t *vtable;

  /* Private data. */
  svn_branch__state_priv_t *priv;

  /* Public data. */

  /* The branch identifier (starting with 'B') */
  const char *bid;

  /* The revision to which this branch state belongs */
  /* ### Later we should remove this and let a single state be sharable
     by multiple txns. */
  svn_branch__txn_t *txn;

};

/* Create a new branch state object.
 */
svn_branch__state_t *
svn_branch__state_create(const svn_branch__state_vtable_t *vtable,
                         svn_cancel_func_t cancel_func,
                         void *cancel_baton,
                         apr_pool_t *result_pool);

/* Get the full id of branch BRANCH.
 *
 * Branch id format:
 *      B<top-level-branch-num>[.<1st-level-eid>[.<2nd-level-eid>[...]]]
 *
 * Note: a branch id is, in behavioural terms, an arbitrary token. In the
 * current implementation it is constructed from the hierarchy of subbranch
 * root EIDs leading to the branch, but that may be changed in future.
 *
 * See also: svn_branch__txn_get_branch_by_id().
 */
const char *
svn_branch__get_id(const svn_branch__state_t *branch,
                   apr_pool_t *result_pool);

/* Return the element id of the root element of BRANCH.
 */
int
svn_branch__root_eid(const svn_branch__state_t *branch);

/* Return the id of the branch nested in OUTER_BID at element OUTER_EID.
 *
 * For a top-level branch, OUTER_BID is null and OUTER_EID is the
 * top-level branch number.
 *
 * (Such branches need not exist. This works purely with ids, making use
 * of the fact that nested branch ids are predictable based on the nesting
 * element id.)
 */
const char *
svn_branch__id_nest(const char *outer_bid,
                    int outer_eid,
                    apr_pool_t *result_pool);

/* Given a nested branch id BID, set *OUTER_BID to the outer branch's id
 * and *OUTER_EID to the nesting element in the outer branch.
 *
 * For a top-level branch, set *OUTER_BID to NULL and *OUTER_EID to the
 * top-level branch number.
 *
 * (Such branches need not exist. This works purely with ids, making use
 * of the fact that nested branch ids are predictable based on the nesting
 * element id.)
 */
void
svn_branch__id_unnest(const char **outer_bid,
                      int *outer_eid,
                      const char *bid,
                      apr_pool_t *result_pool);

/* Remove the branch with id BID from the list of branches in TXN.
 */
svn_error_t *
svn_branch__txn_delete_branch(svn_branch__txn_t *txn,
                              const char *bid,
                              apr_pool_t *scratch_pool);

/* Branch-Element-Revision */
struct svn_branch__el_rev_id_t
{
  /* The branch state that applies to REV. */
  svn_branch__state_t *branch;
  /* Element. */
  int eid;
  /* Revision. SVN_INVALID_REVNUM means 'in this transaction', not 'head'.
     ### Do we need this if BRANCH refers to a particular branch-revision? */
  svn_revnum_t rev;

};

/* Revision-branch-element id. */
struct svn_branch__rev_bid_eid_t
{
  /* Revision. SVN_INVALID_REVNUM means 'in this transaction', not 'head'. */
  svn_revnum_t rev;
  /* The branch id in revision REV. */
  const char *bid;
  /* Element id. */
  int eid;

};

/* Revision-branch id. */
struct svn_branch__rev_bid_t
{
  /* Revision. SVN_INVALID_REVNUM means 'in this transaction', not 'head'. */
  svn_revnum_t rev;
  /* The branch id in revision REV. */
  const char *bid;

};

/* Return a new el_rev_id object constructed with *shallow* copies of BRANCH,
 * EID and REV, allocated in RESULT_POOL.
 */
svn_branch__el_rev_id_t *
svn_branch__el_rev_id_create(svn_branch__state_t *branch,
                             int eid,
                             svn_revnum_t rev,
                             apr_pool_t *result_pool);

/* Return a new id object constructed with a deep copy of OLD_ID,
 * allocated in RESULT_POOL. */
svn_branch__el_rev_id_t *
svn_branch__el_rev_id_dup(const svn_branch__el_rev_id_t *old_id,
                          apr_pool_t *result_pool);

/* Return a new id object constructed with deep copies of REV, BRANCH_ID
 * and EID, allocated in RESULT_POOL.
 */
svn_branch__rev_bid_eid_t *
svn_branch__rev_bid_eid_create(svn_revnum_t rev,
                               const char *branch_id,
                               int eid,
                               apr_pool_t *result_pool);
svn_branch__rev_bid_t *
svn_branch__rev_bid_create(svn_revnum_t rev,
                           const char *branch_id,
                           apr_pool_t *result_pool);

/* Return a new id object constructed with a deep copy of OLD_ID,
 * allocated in RESULT_POOL. */
svn_branch__rev_bid_eid_t *
svn_branch__rev_bid_eid_dup(const svn_branch__rev_bid_eid_t *old_id,
                            apr_pool_t *result_pool);
svn_branch__rev_bid_t *
svn_branch__rev_bid_dup(const svn_branch__rev_bid_t *old_id,
                        apr_pool_t *result_pool);

svn_boolean_t
svn_branch__rev_bid_equal(const svn_branch__rev_bid_t *id1,
                          const svn_branch__rev_bid_t *id2);

typedef struct svn_branch__history_t
{
  /* The immediate parents of this state in the branch/merge graph.
     Hash of (BID -> svn_branch__rev_bid_t). */
  apr_hash_t *parents;
} svn_branch__history_t;

svn_branch__history_t *
svn_branch__history_create_empty(apr_pool_t *result_pool);

svn_branch__history_t *
svn_branch__history_create(apr_hash_t *parents,
                           apr_pool_t *result_pool);

svn_branch__history_t *
svn_branch__history_dup(const svn_branch__history_t *old,
                        apr_pool_t *result_pool);

/* Return the mapping of elements in branch BRANCH.
 */
svn_error_t *
svn_branch__state_get_elements(const svn_branch__state_t *branch,
                               svn_element__tree_t **element_tree_p,
                               apr_pool_t *result_pool);

/* In BRANCH, get element EID (parent, name, payload).
 *
 * If element EID is not present, return null.
 */
svn_error_t *
svn_branch__state_get_element(const svn_branch__state_t *branch,
                              svn_element__content_t **element_p,
                              int eid,
                              apr_pool_t *result_pool);

/** Equivalent to
 *    alter_one(..., element->parent_eid, element->name, element->payload),
 * or, if @a element is null, to
 *    delete_one(...).
 */
svn_error_t *
svn_branch__state_set_element(svn_branch__state_t *branch,
                              int eid,
                              const svn_element__content_t *element,
                              apr_pool_t *result_pool);

/** Specify that the element of @a branch identified by @a eid shall not
 * be present.
 *
 * The delete is not explicitly recursive. However, as an effect of the
 * final 'flattening' of a branch state into a single tree, each element
 * in the final state that still has this element as its parent will also
 * be deleted, recursively.
 *
 * The element @a eid must not be the root element of @a branch.
 *
 * ### Options for Out-Of-Date Checking on Rebase
 *
 *   We may want to specify what kind of OOD check takes place. The
 *   following two options differ in what happens to an element that is
 *   added, on the other side, as a child of this deleted element.
 *
 *   Rebase option 1: The rebase checks for changes in the whole subtree,
 *   excluding any portions of the subtree for which an explicit delete or
 *   move-away has been issued. The check includes checking that the other
 *   side has not added any child. In other words, the deletion is
 *   interpreted as an action affecting a subtree (dynamically rooted at
 *   this element), rather than as an action affecting a single element or
 *   a fixed set of elements that was explicitly or implicitly specified
 *   by the sender.
 *
 *   To delete a mixed-rev subtree, the client sends an explicit delete for
 *   each subtree that has a different base revision from its parent.
 *
 *   Rebase option 2: The rebase checks for changes to this element only.
 *   The sender can send an explicit delete for each existing child element
 *   that it requires to be checked as well. However, there is no way for
 *   the sender to specify whether a child element added by the other side
 *   should be considered an out-of-date error or silently deleted.
 *
 *   It would also be possible to let the caller specify, at some suitable
 *   granularity, which option to use.
 */
svn_error_t *
svn_branch__state_delete_one(svn_branch__state_t *branch,
                             svn_branch__eid_t eid,
                             apr_pool_t *scratch_pool);

/** Specify the tree position and payload of the element of @a branch
 * identified by @a eid.
 *
 * Set the element's parent EID, name and payload to @a new_parent_eid,
 * @a new_name and @a new_payload respectively.
 *
 * This may create a new element or alter an existing element.
 *
 * If the element ...                   we can describe the effect as ...
 *
 *   exists in the branch               =>  altering it;
 *   previously existed in the branch   =>  resurrecting it;
 *   only existed in other branches     =>  branching it;
 *   never existed anywhere             =>  creating or adding it.
 *
 * However, these are imprecise descriptions and not mutually exclusive.
 * For example, if it existed previously in this branch and another, then
 * we may describe the result as 'resurrecting' and/or as 'branching'.
 *
 * Duplicate @a new_name and @a new_payload into the branch's pool.
 */
svn_error_t *
svn_branch__state_alter_one(svn_branch__state_t *branch,
                            svn_branch__eid_t eid,
                            svn_branch__eid_t new_parent_eid,
                            const char *new_name,
                            const svn_element__payload_t *new_payload,
                            apr_pool_t *scratch_pool);

svn_error_t *
svn_branch__state_copy_tree(svn_branch__state_t *branch,
                            const svn_branch__rev_bid_eid_t *src_el_rev,
                            svn_branch__eid_t new_parent_eid,
                            const char *new_name,
                            apr_pool_t *scratch_pool);

/* Purge orphaned elements in BRANCH.
 */
svn_error_t *
svn_branch__state_purge(svn_branch__state_t *branch,
                        apr_pool_t *scratch_pool);

/* Get the merge history of BRANCH.
 */
svn_error_t *
svn_branch__state_get_history(svn_branch__state_t *branch,
                              svn_branch__history_t **merge_history_p,
                              apr_pool_t *result_pool);

/* Set the merge history of BRANCH.
 */
svn_error_t *
svn_branch__state_set_history(svn_branch__state_t *branch,
                              const svn_branch__history_t *merge_history,
                              apr_pool_t *scratch_pool);

/* Return the branch-relative path of element EID in BRANCH.
 *
 * If the element EID does not currently exist in BRANCH, return NULL.
 *
 * ### TODO: Clarify sequencing requirements.
 */
const char *
svn_branch__get_path_by_eid(const svn_branch__state_t *branch,
                            int eid,
                            apr_pool_t *result_pool);

/* Return the EID for the branch-relative path PATH in BRANCH.
 *
 * If no element of BRANCH is at this path, return -1.
 *
 * ### TODO: Clarify sequencing requirements.
 */
int
svn_branch__get_eid_by_path(const svn_branch__state_t *branch,
                            const char *path,
                            apr_pool_t *scratch_pool);

/* Get the default branching metadata for r0 of a new repository.
 */
svn_string_t *
svn_branch__get_default_r0_metadata(apr_pool_t *result_pool);

/* Create a new txn object *TXN_P, initialized with info
 * parsed from STREAM, allocated in RESULT_POOL.
 */
svn_error_t *
svn_branch__txn_parse(svn_branch__txn_t **txn_p,
                      svn_branch__repos_t *repos,
                      svn_stream_t *stream,
                      apr_pool_t *result_pool,
                      apr_pool_t *scratch_pool);

/* Write to STREAM a parseable representation of TXN.
 */
svn_error_t *
svn_branch__txn_serialize(svn_branch__txn_t *txn,
                          svn_stream_t *stream,
                          apr_pool_t *scratch_pool);

/* Write to STREAM a parseable representation of BRANCH.
 */
svn_error_t *
svn_branch__state_serialize(svn_stream_t *stream,
                            svn_branch__state_t *branch,
                            apr_pool_t *scratch_pool);


#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* SVN_BRANCH_H */