3 * ====================================================================
\r
4 * Copyright (c) 2006-2008 CollabNet. All rights reserved.
\r
6 * This software is licensed as described in the file COPYING, which
\r
7 * you should have received as part of this distribution. The terms
\r
8 * are also available at http://subversion.tigris.org/license-1.html.
\r
9 * If newer versions of this license are posted there, you may use a
\r
10 * newer version instead, at your option.
\r
12 * This software consists of voluntary contributions made by many
\r
13 * individuals. For exact contribution history, see the revision
\r
14 * history and logs, available at http://subversion.tigris.org/.
\r
15 * ====================================================================
\r
18 * @file svn_mergeinfo.h
\r
19 * @brief mergeinfo handling and processing
\r
23 #ifndef SVN_MERGEINFO_H
\r
24 #define SVN_MERGEINFO_H
\r
26 #include <apr_pools.h>
\r
27 #include <apr_tables.h> /* for apr_array_header_t */
\r
28 #include <apr_hash.h>
\r
30 #include "svn_types.h"
\r
31 #include "svn_string.h" /* for svn_string_t */
\r
36 #endif /* __cplusplus */
\r
38 /** Overview of the @c SVN_PROP_MERGEINFO property.
\r
40 * Merge history is stored in the @c SVN_PROP_MERGEINFO property of files
\r
41 * and directories. The @c SVN_PROP_MERGEINFO property on a path stores the
\r
42 * complete list of changes merged to that path, either directly or via the
\r
43 * path's parent, grand-parent, etc.. A path may have empty mergeinfo which
\r
44 * means that nothing has been merged to that path or all previous merges
\r
45 * to the path were reversed. Note that a path may have no mergeinfo, this
\r
46 * is not the same as empty mergeinfo.
\r
48 * Every path in a tree may have @c SVN_PROP_MERGEINFO set, but if the
\r
49 * @c SVN_PROP_MERGEINFO for a path is equivalent to the
\r
50 * @c SVN_PROP_MERGEINFO for its parent, then the @c SVN_PROP_MERGEINFO on
\r
51 * the path will 'elide' (be removed) from the path as a post step to any
\r
52 * merge. If a path's parent does not have any @c SVN_PROP_MERGEINFO set,
\r
53 * the path's mergeinfo can elide to its nearest grand-parent,
\r
54 * great-grand-parent, etc. that has equivalent @c SVN_PROP_MERGEINFO set
\r
57 * If a path has no @c SVN_PROP_MERGEINFO of its own, it inherits mergeinfo
\r
58 * from its nearest parent that has @c SVN_PROP_MERGEINFO set. The
\r
59 * exception to this is @c SVN_PROP_MERGEINFO with non-ineritable revision
\r
60 * ranges. These non-inheritable ranges apply only to the path which they
\r
63 * Due to Subversion's allowance for mixed revision working copies, both
\r
64 * elision and inheritance within the working copy presume the path
\r
65 * between a path and its nearest parent with mergeinfo is at the same
\r
66 * working revision. If this is not the case then neither inheritance nor
\r
67 * elision can occur.
\r
69 * The value of the @c SVN_PROP_MERGEINFO property is either an empty string
\r
70 * (representing empty mergeinfo) or a non-empty string consisting of
\r
71 * a path, a colon, and comma separated revision list, containing one or more
\r
72 * revision or revision ranges. Revision range start and end points are
\r
73 * separated by "-". Revisions and revision ranges may have the optional
\r
74 * @c SVN_MERGEINFO_NONINHERITABLE_STR suffix to signify a non-inheritable
\r
75 * revision/revision range.
\r
77 * @c SVN_PROP_MERGEINFO Value Grammar:
\r
81 * revisionrange REVISION1 "-" REVISION2
\r
82 * revisioneelement (revisionrange | REVISION)"*"?
\r
83 * rangelist revisioneelement (COMMA revisioneelement)*
\r
84 * revisionline PATHNAME COLON rangelist
\r
85 * top "" | (revisionline (NEWLINE revisionline))*
\r
87 * The PATHNAME is the source of a merge and the rangelist the revision(s)
\r
88 * merged to the path @c SVN_PROP_MERGEINFO is set on directly or indirectly
\r
89 * via inheritance. PATHNAME must always exist at the specified rangelist
\r
90 * and thus a single merge may result in multiple revisionlines if the source
\r
93 * Rangelists must be sorted from lowest to highest revision and cannot
\r
94 * contain overlapping revisionlistelements. REVISION1 must be less than
\r
95 * REVISION2. Consecutive single revisions that can be represented by a
\r
96 * revisionrange are allowed however (e.g. '5,6,7,8,9-12' or '5-12' are
\r
100 /* Suffix for SVN_PROP_MERGEINFO revision ranges indicating a given
\r
101 range is non-inheritable. */
\r
102 #define SVN_MERGEINFO_NONINHERITABLE_STR "*"
\r
104 /** Terminology for data structures that contain mergeinfo.
\r
106 * Subversion commonly uses several data structures to represent
\r
107 * mergeinfo in RAM:
\r
109 * (a) Strings (@c svn_string_t *) containing "unparsed mergeinfo".
\r
111 * (b) A "rangelist". An array (@c apr_array_header_t *) of non-overlapping
\r
112 * merge ranges (@c svn_merge_range_t *), sorted as said by
\r
113 * @c svn_sort_compare_ranges(). An empty range list is represented by
\r
114 * an empty array. Unless specifically noted otherwise, all APIs require
\r
115 * rangelists that describe only forward ranges, i.e. the range's start
\r
116 * revision is less than its end revision.
\r
118 * (c) @c svn_mergeinfo_t, called "mergeinfo". A hash mapping merge
\r
119 * source paths (@c const char *, starting with slashes) to
\r
120 * non-empty rangelist arrays. A @c NULL hash is used to represent
\r
121 * no mergeinfo and an empty hash is used to represent empty
\r
124 * (d) @c svn_mergeinfo_catalog_t, called a "mergeinfo catalog". A hash
\r
125 * mapping paths (@c const char *, starting with slashes) to
\r
126 * @c svn_mergeinfo_t.
\r
128 * Both @c svn_mergeinfo_t and @c svn_mergeinfo_catalog_t are just
\r
129 * typedefs for @c apr_hash_t *; there is no static type-checking, and
\r
130 * you still use standard @c apr_hash_t functions to interact with
\r
133 * Note that while the keys of mergeinfos are always relative to the
\r
134 * repository root, the keys of a catalog may be relative to something
\r
135 * else, such as an RA session root.
\r
138 typedef apr_hash_t *svn_mergeinfo_t;
\r
139 typedef apr_hash_t *svn_mergeinfo_catalog_t;
\r
141 /** Parse the mergeinfo from @a input into @a *mergeinfo. If no
\r
142 * mergeinfo is available, return an empty mergeinfo (never @c NULL).
\r
143 * Perform temporary allocations in @a pool.
\r
145 * If @a input is not a grammatically correct @c SVN_PROP_MERGEINFO
\r
146 * property, contains overlapping revision ranges of differing
\r
147 * inheritability, or revision ranges with a start revision greater
\r
148 * than or equal to its end revision, or contains paths mapped to empty
\r
149 * revision ranges, then return @c SVN_ERR_MERGEINFO_PARSE_ERROR.
\r
150 * Unordered revision ranges are allowed, but will be sorted when
\r
151 * placed into @a *mergeinfo. Overlapping revision ranges of the same
\r
152 * inheritability are also allowed, but will be combined into a single
\r
153 * range when placed into @a *mergeinfo.
\r
155 * @since New in 1.5.
\r
158 svn_mergeinfo_parse(svn_mergeinfo_t *mergeinfo, const char *input,
\r
161 /** Calculate the delta between two mergeinfos, @a mergefrom and @a mergeto
\r
162 * (which may be @c NULL), and place the result in @a *deleted and @a
\r
163 * *added (neither output argument may be @c NULL).
\r
165 * @a consider_inheritance determines how the rangelists in the two
\r
166 * hashes are compared for equality. If @a consider_inheritance is FALSE,
\r
167 * then the start and end revisions of the @c svn_merge_range_t's being
\r
168 * compared are the only factors considered when determining equality.
\r
170 * e.g. '/trunk: 1,3-4*,5' == '/trunk: 1,3-5'
\r
172 * If @a consider_inheritance is TRUE, then the inheritability of the
\r
173 * @c svn_merge_range_t's is also considered and must be the same for two
\r
174 * otherwise identical ranges to be judged equal.
\r
176 * e.g. '/trunk: 1,3-4*,5' != '/trunk: 1,3-5'
\r
177 * '/trunk: 1,3-4*,5' == '/trunk: 1,3-4*,5'
\r
178 * '/trunk: 1,3-4,5' == '/trunk: 1,3-4,5'
\r
180 * @since New in 1.5.
\r
183 svn_mergeinfo_diff(svn_mergeinfo_t *deleted, svn_mergeinfo_t *added,
\r
184 svn_mergeinfo_t mergefrom, svn_mergeinfo_t mergeto,
\r
185 svn_boolean_t consider_inheritance,
\r
188 /** Merge one mergeinfo, @a changes, into another mergeinfo @a
\r
191 * When intersecting rangelists for a path are merged, the inheritability of
\r
192 * the resulting svn_merge_range_t depends on the inheritability of the
\r
193 * operands. If two non-inheritable ranges are merged the result is always
\r
194 * non-inheritable, in all other cases the resulting range is inheritable.
\r
196 * e.g. '/A: 1,3-4' merged with '/A: 1,3,4*,5' --> '/A: 1,3-5'
\r
197 * '/A: 1,3-4*' merged with '/A: 1,3,4*,5' --> '/A: 1,3,4*,5'
\r
199 * @since New in 1.5.
\r
202 svn_mergeinfo_merge(svn_mergeinfo_t mergeinfo, svn_mergeinfo_t changes,
\r
205 /** Removes @a eraser (the subtrahend) from @a whiteboard (the
\r
206 * minuend), and places the resulting difference in @a *mergeinfo.
\r
208 * @since New in 1.5.
\r
211 svn_mergeinfo_remove(svn_mergeinfo_t *mergeinfo, svn_mergeinfo_t eraser,
\r
212 svn_mergeinfo_t whiteboard, apr_pool_t *pool);
\r
214 /** Calculate the delta between two rangelists consisting of @c
\r
215 * svn_merge_range_t * elements (sorted in ascending order), @a from
\r
216 * and @a to, and place the result in @a *deleted and @a *added
\r
217 * (neither output argument will ever be @c NULL).
\r
219 * @a consider_inheritance determines how to account for the inheritability
\r
220 * of the two rangelist's ranges when calculating the diff,
\r
221 * as described for svn_mergeinfo_diff().
\r
223 * @since New in 1.5.
\r
226 svn_rangelist_diff(apr_array_header_t **deleted, apr_array_header_t **added,
\r
227 apr_array_header_t *from, apr_array_header_t *to,
\r
228 svn_boolean_t consider_inheritance,
\r
231 /** Merge two rangelists consisting of @c svn_merge_range_t *
\r
232 * elements, @a *rangelist and @a changes, placing the results in
\r
233 * @a *rangelist. Either rangelist may be empty.
\r
235 * When intersecting rangelists are merged, the inheritability of
\r
236 * the resulting svn_merge_range_t depends on the inheritability of the
\r
237 * operands: see svn_mergeinfo_merge().
\r
239 * Note: @a *rangelist and @a changes must be sorted as said by @c
\r
240 * svn_sort_compare_ranges(). @a *rangelist is guaranteed to remain
\r
241 * in sorted order and be compacted to the minimal number of ranges
\r
242 * needed to represent the merged result.
\r
244 * @since New in 1.5.
\r
247 svn_rangelist_merge(apr_array_header_t **rangelist,
\r
248 apr_array_header_t *changes,
\r
251 /** Removes @a eraser (the subtrahend) from @a whiteboard (the
\r
252 * minuend), and places the resulting difference in @a output.
\r
254 * Note: @a eraser and @a whiteboard must be sorted as said by @c
\r
255 * svn_sort_compare_ranges(). @a output is guaranteed to be in sorted
\r
258 * @a consider_inheritance determines how to account for the
\r
259 * @c svn_merge_range_t inheritable field when comparing @a whiteboard's
\r
260 * and @a *eraser's rangelists for equality. @see svn_mergeinfo_diff().
\r
262 * @since New in 1.5.
\r
265 svn_rangelist_remove(apr_array_header_t **output, apr_array_header_t *eraser,
\r
266 apr_array_header_t *whiteboard,
\r
267 svn_boolean_t consider_inheritance,
\r
270 /** Find the intersection of two mergeinfos, @a mergeinfo1 and @a
\r
271 * mergeinfo2, and place the result in @a *mergeinfo, which is (deeply)
\r
272 * allocated in @a pool.
\r
274 * @since New in 1.5.
\r
277 svn_mergeinfo_intersect(svn_mergeinfo_t *mergeinfo,
\r
278 svn_mergeinfo_t mergeinfo1,
\r
279 svn_mergeinfo_t mergeinfo2,
\r
282 /** Find the intersection of two rangelists consisting of @c
\r
283 * svn_merge_range_t * elements, @a rangelist1 and @a rangelist2, and
\r
284 * place the result in @a *rangelist (which is never @c NULL).
\r
286 * @a consider_inheritance determines how to account for the inheritability
\r
287 * of the two rangelist's ranges when calculating the intersection,
\r
288 * @see svn_mergeinfo_diff().
\r
290 * Note: @a rangelist1 and @a rangelist2 must be sorted as said by @c
\r
291 * svn_sort_compare_ranges(). @a *rangelist is guaranteed to be in sorted
\r
293 * @since New in 1.5.
\r
296 svn_rangelist_intersect(apr_array_header_t **rangelist,
\r
297 apr_array_header_t *rangelist1,
\r
298 apr_array_header_t *rangelist2,
\r
299 svn_boolean_t consider_inheritance,
\r
302 /** Reverse @a rangelist, and the @c start and @c end fields of each
\r
303 * range in @a rangelist, in place.
\r
305 * TODO(miapi): Is this really a valid function? Rangelists that
\r
306 * aren't sorted, or rangelists containing reverse ranges, are
\r
307 * generally not valid in mergeinfo code. Can we rewrite the two
\r
308 * places where this is used?
\r
310 * @since New in 1.5.
\r
313 svn_rangelist_reverse(apr_array_header_t *rangelist, apr_pool_t *pool);
\r
315 /** Take an array of svn_merge_range_t *'s in @a rangelist, and convert it
\r
316 * back to a text format rangelist in @a output. If @a rangelist contains
\r
317 * no elements, sets @a output to the empty string.
\r
319 * @since New in 1.5.
\r
322 svn_rangelist_to_string(svn_string_t **output,
\r
323 const apr_array_header_t *rangelist,
\r
326 /** Return a deep copy of @c svn_merge_range_t *'s in @a rangelist excluding
\r
327 * all non-inheritable @c svn_merge_range_t. If @a start and @a end are valid
\r
328 * revisions and @a start is less than or equal to @a end, then exclude only the
\r
329 * non-inheritable revision ranges that intersect inclusively with the range
\r
330 * defined by @a start and @a end. If @a rangelist contains no elements, return
\r
331 * an empty array. Allocate the copy in @a pool.
\r
333 * @since New in 1.5.
\r
336 svn_rangelist_inheritable(apr_array_header_t **inheritable_rangelist,
\r
337 apr_array_header_t *rangelist,
\r
338 svn_revnum_t start,
\r
342 /** Return a deep copy of @a mergeinfo, excluding all non-inheritable
\r
343 * @c svn_merge_range_t. If @a start and @a end are valid revisions
\r
344 * and @a start is less than or equal to @a end, then exclude only the
\r
345 * non-inheritable revisions that intersect inclusively with the range
\r
346 * defined by @a start and @a end. If @a path is not NULL remove
\r
347 * non-inheritable ranges only for @a path. If all ranges are removed
\r
348 * for a given path then remove that path as well. If all paths are
\r
349 * removed or @a rangelist is empty then set @a *inheritable_rangelist
\r
350 * to an empty array. Allocate the copy in @a pool.
\r
352 * @since New in 1.5.
\r
355 svn_mergeinfo_inheritable(svn_mergeinfo_t *inheritable_mergeinfo,
\r
356 svn_mergeinfo_t mergeinfo,
\r
358 svn_revnum_t start,
\r
362 /** Take a mergeinfo in MERGEINPUT, and convert it back to unparsed
\r
363 * mergeinfo in *OUTPUT. If INPUT contains no elements, return the
\r
366 * @since New in 1.5.
\r
369 svn_mergeinfo_to_string(svn_string_t **output,
\r
370 svn_mergeinfo_t mergeinput,
\r
373 /** Take a hash of mergeinfo in @a mergeinfo, and sort the rangelists
\r
374 * associated with each key (in place).
\r
376 * TODO(miapi): mergeinfos should *always* be sorted. This should be
\r
377 * a private function.
\r
379 * @since New in 1.5
\r
382 svn_mergeinfo_sort(svn_mergeinfo_t mergeinfo, apr_pool_t *pool);
\r
384 /** Return a deep copy of @a mergeinfo_catalog, allocated in @a pool.
\r
386 * @since New in 1.6.
\r
388 svn_mergeinfo_catalog_t
\r
389 svn_mergeinfo_catalog_dup(svn_mergeinfo_catalog_t mergeinfo_catalog,
\r
392 /** Return a deep copy of @a mergeinfo, allocated in @a pool.
\r
394 * @since New in 1.5.
\r
397 svn_mergeinfo_dup(svn_mergeinfo_t mergeinfo, apr_pool_t *pool);
\r
399 /** Return a deep copy of @a rangelist, allocated in @a pool.
\r
401 * @since New in 1.5.
\r
403 apr_array_header_t *
\r
404 svn_rangelist_dup(apr_array_header_t *rangelist, apr_pool_t *pool);
\r
408 * The three ways to request mergeinfo affecting a given path.
\r
410 * @since New in 1.5.
\r
414 /** Explicit mergeinfo only. */
\r
415 svn_mergeinfo_explicit,
\r
417 /** Explicit mergeinfo, or if that doesn't exist, the inherited
\r
418 mergeinfo from a target's nearest (path-wise, not history-wise)
\r
420 svn_mergeinfo_inherited,
\r
422 /** Mergeinfo on target's nearest (path-wise, not history-wise)
\r
423 ancestor, regardless of whether target has explict mergeinfo. */
\r
424 svn_mergeinfo_nearest_ancestor
\r
425 } svn_mergeinfo_inheritance_t;
\r
427 /** Return a constant string expressing @a inherit as an English word,
\r
428 * i.e., "explicit" (default), "inherited", or "nearest_ancestor".
\r
429 * The string is not localized, as it may be used for client<->server
\r
432 * @since New in 1.5.
\r
435 svn_inheritance_to_word(svn_mergeinfo_inheritance_t inherit);
\r
438 /** Return the appropriate @c svn_mergeinfo_inheritance_t for @a word.
\r
439 * @a word is as returned from svn_inheritance_to_word(). Defaults to
\r
440 * @c svn_mergeinfo_explicit.
\r
442 * @since New in 1.5.
\r
444 svn_mergeinfo_inheritance_t
\r
445 svn_inheritance_from_word(const char *word);
\r
450 #endif /* __cplusplus */
\r
452 #endif /* SVN_MERGEINFO_H */
\r