Subversion
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
svn_mergeinfo.h
Go to the documentation of this file.
1 /**
2  * @copyright
3  * ====================================================================
4  * Copyright (c) 2006-2008 CollabNet. All rights reserved.
5  *
6  * This software is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution. The terms
8  * are also available at http://subversion.tigris.org/license-1.html.
9  * If newer versions of this license are posted there, you may use a
10  * newer version instead, at your option.
11  *
12  * This software consists of voluntary contributions made by many
13  * individuals. For exact contribution history, see the revision
14  * history and logs, available at http://subversion.tigris.org/.
15  * ====================================================================
16  * @endcopyright
17  *
18  * @file svn_mergeinfo.h
19  * @brief mergeinfo handling and processing
20  */
21 
22 
23 #ifndef SVN_MERGEINFO_H
24 #define SVN_MERGEINFO_H
25 
26 #include <apr_pools.h>
27 #include <apr_tables.h> /* for apr_array_header_t */
28 #include <apr_hash.h>
29 
30 #include "svn_types.h"
31 #include "svn_string.h" /* for svn_string_t */
32 
33 
34 #ifdef __cplusplus
35 extern "C" {
36 #endif /* __cplusplus */
37 
38 /** Overview of the @c SVN_PROP_MERGEINFO property.
39  *
40  * Merge history is stored in the @c SVN_PROP_MERGEINFO property of files
41  * and directories. The @c SVN_PROP_MERGEINFO property on a path stores the
42  * complete list of changes merged to that path, either directly or via the
43  * path's parent, grand-parent, etc.. A path may have empty mergeinfo which
44  * means that nothing has been merged to that path or all previous merges
45  * to the path were reversed. Note that a path may have no mergeinfo, this
46  * is not the same as empty mergeinfo.
47  *
48  * Every path in a tree may have @c SVN_PROP_MERGEINFO set, but if the
49  * @c SVN_PROP_MERGEINFO for a path is equivalent to the
50  * @c SVN_PROP_MERGEINFO for its parent, then the @c SVN_PROP_MERGEINFO on
51  * the path will 'elide' (be removed) from the path as a post step to any
52  * merge. If a path's parent does not have any @c SVN_PROP_MERGEINFO set,
53  * the path's mergeinfo can elide to its nearest grand-parent,
54  * great-grand-parent, etc. that has equivalent @c SVN_PROP_MERGEINFO set
55  * on it.
56  *
57  * If a path has no @c SVN_PROP_MERGEINFO of its own, it inherits mergeinfo
58  * from its nearest parent that has @c SVN_PROP_MERGEINFO set. The
59  * exception to this is @c SVN_PROP_MERGEINFO with non-ineritable revision
60  * ranges. These non-inheritable ranges apply only to the path which they
61  * are set on.
62  *
63  * Due to Subversion's allowance for mixed revision working copies, both
64  * elision and inheritance within the working copy presume the path
65  * between a path and its nearest parent with mergeinfo is at the same
66  * working revision. If this is not the case then neither inheritance nor
67  * elision can occur.
68  *
69  * The value of the @c SVN_PROP_MERGEINFO property is either an empty string
70  * (representing empty mergeinfo) or a non-empty string consisting of
71  * a path, a colon, and comma separated revision list, containing one or more
72  * revision or revision ranges. Revision range start and end points are
73  * separated by "-". Revisions and revision ranges may have the optional
74  * @c SVN_MERGEINFO_NONINHERITABLE_STR suffix to signify a non-inheritable
75  * revision/revision range.
76  *
77  * @c SVN_PROP_MERGEINFO Value Grammar:
78  *
79  * Token Definition
80  * ----- ----------
81  * revisionrange REVISION1 "-" REVISION2
82  * revisioneelement (revisionrange | REVISION)"*"?
83  * rangelist revisioneelement (COMMA revisioneelement)*
84  * revisionline PATHNAME COLON rangelist
85  * top "" | (revisionline (NEWLINE revisionline))*
86  *
87  * The PATHNAME is the source of a merge and the rangelist the revision(s)
88  * merged to the path @c SVN_PROP_MERGEINFO is set on directly or indirectly
89  * via inheritance. PATHNAME must always exist at the specified rangelist
90  * and thus a single merge may result in multiple revisionlines if the source
91  * was renamed.
92  *
93  * Rangelists must be sorted from lowest to highest revision and cannot
94  * contain overlapping revisionlistelements. REVISION1 must be less than
95  * REVISION2. Consecutive single revisions that can be represented by a
96  * revisionrange are allowed however (e.g. '5,6,7,8,9-12' or '5-12' are
97  * both acceptable).
98  */
99 
100 /* Suffix for SVN_PROP_MERGEINFO revision ranges indicating a given
101  range is non-inheritable. */
102 #define SVN_MERGEINFO_NONINHERITABLE_STR "*"
103 
104 /** Terminology for data structures that contain mergeinfo.
105  *
106  * Subversion commonly uses several data structures to represent
107  * mergeinfo in RAM:
108  *
109  * (a) Strings (@c svn_string_t *) containing "unparsed mergeinfo".
110  *
111  * (b) A "rangelist". An array (@c apr_array_header_t *) of non-overlapping
112  * merge ranges (@c svn_merge_range_t *), sorted as said by
113  * @c svn_sort_compare_ranges(). An empty range list is represented by
114  * an empty array. Unless specifically noted otherwise, all APIs require
115  * rangelists that describe only forward ranges, i.e. the range's start
116  * revision is less than its end revision.
117  *
118  * (c) @c svn_mergeinfo_t, called "mergeinfo". A hash mapping merge
119  * source paths (@c const char *, starting with slashes) to
120  * non-empty rangelist arrays. A @c NULL hash is used to represent
121  * no mergeinfo and an empty hash is used to represent empty
122  * mergeinfo.
123  *
124  * (d) @c svn_mergeinfo_catalog_t, called a "mergeinfo catalog". A hash
125  * mapping paths (@c const char *, starting with slashes) to
126  * @c svn_mergeinfo_t.
127  *
128  * Both @c svn_mergeinfo_t and @c svn_mergeinfo_catalog_t are just
129  * typedefs for @c apr_hash_t *; there is no static type-checking, and
130  * you still use standard @c apr_hash_t functions to interact with
131  * them.
132  *
133  * Note that while the keys of mergeinfos are always relative to the
134  * repository root, the keys of a catalog may be relative to something
135  * else, such as an RA session root.
136  */
137 
138 typedef apr_hash_t *svn_mergeinfo_t;
139 typedef apr_hash_t *svn_mergeinfo_catalog_t;
140 
141 /** Parse the mergeinfo from @a input into @a *mergeinfo. If no
142  * mergeinfo is available, return an empty mergeinfo (never @c NULL).
143  * Perform temporary allocations in @a pool.
144  *
145  * If @a input is not a grammatically correct @c SVN_PROP_MERGEINFO
146  * property, contains overlapping revision ranges of differing
147  * inheritability, or revision ranges with a start revision greater
148  * than or equal to its end revision, or contains paths mapped to empty
149  * revision ranges, then return @c SVN_ERR_MERGEINFO_PARSE_ERROR.
150  * Unordered revision ranges are allowed, but will be sorted when
151  * placed into @a *mergeinfo. Overlapping revision ranges of the same
152  * inheritability are also allowed, but will be combined into a single
153  * range when placed into @a *mergeinfo.
154  *
155  * @a input may contain relative merge source paths, but these are
156  * converted to absolute paths in @a *mergeinfo.
157  *
158  * @since New in 1.5.
159  */
160 svn_error_t *
161 svn_mergeinfo_parse(svn_mergeinfo_t *mergeinfo, const char *input,
162  apr_pool_t *pool);
163 
164 /** Calculate the delta between two mergeinfos, @a mergefrom and @a mergeto
165  * (which may be @c NULL), and place the result in @a *deleted and @a
166  * *added (neither output argument may be @c NULL).
167  *
168  * @a consider_inheritance determines how the rangelists in the two
169  * hashes are compared for equality. If @a consider_inheritance is FALSE,
170  * then the start and end revisions of the @c svn_merge_range_t's being
171  * compared are the only factors considered when determining equality.
172  *
173  * e.g. '/trunk: 1,3-4*,5' == '/trunk: 1,3-5'
174  *
175  * If @a consider_inheritance is TRUE, then the inheritability of the
176  * @c svn_merge_range_t's is also considered and must be the same for two
177  * otherwise identical ranges to be judged equal.
178  *
179  * e.g. '/trunk: 1,3-4*,5' != '/trunk: 1,3-5'
180  * '/trunk: 1,3-4*,5' == '/trunk: 1,3-4*,5'
181  * '/trunk: 1,3-4,5' == '/trunk: 1,3-4,5'
182  *
183  * @since New in 1.5.
184  */
185 svn_error_t *
186 svn_mergeinfo_diff(svn_mergeinfo_t *deleted, svn_mergeinfo_t *added,
187  svn_mergeinfo_t mergefrom, svn_mergeinfo_t mergeto,
188  svn_boolean_t consider_inheritance,
189  apr_pool_t *pool);
190 
191 /** Merge one mergeinfo, @a changes, into another mergeinfo @a
192  * mergeinfo.
193  *
194  * When intersecting rangelists for a path are merged, the inheritability of
195  * the resulting svn_merge_range_t depends on the inheritability of the
196  * operands. If two non-inheritable ranges are merged the result is always
197  * non-inheritable, in all other cases the resulting range is inheritable.
198  *
199  * e.g. '/A: 1,3-4' merged with '/A: 1,3,4*,5' --> '/A: 1,3-5'
200  * '/A: 1,3-4*' merged with '/A: 1,3,4*,5' --> '/A: 1,3,4*,5'
201  *
202  * @since New in 1.5.
203  */
204 svn_error_t *
205 svn_mergeinfo_merge(svn_mergeinfo_t mergeinfo, svn_mergeinfo_t changes,
206  apr_pool_t *pool);
207 
208 /** Removes @a eraser (the subtrahend) from @a whiteboard (the
209  * minuend), and places the resulting difference in @a *mergeinfo.
210  *
211  * @since New in 1.5.
212  */
213 svn_error_t *
214 svn_mergeinfo_remove(svn_mergeinfo_t *mergeinfo, svn_mergeinfo_t eraser,
215  svn_mergeinfo_t whiteboard, apr_pool_t *pool);
216 
217 /** Calculate the delta between two rangelists consisting of @c
218  * svn_merge_range_t * elements (sorted in ascending order), @a from
219  * and @a to, and place the result in @a *deleted and @a *added
220  * (neither output argument will ever be @c NULL).
221  *
222  * @a consider_inheritance determines how to account for the inheritability
223  * of the two rangelist's ranges when calculating the diff,
224  * as described for svn_mergeinfo_diff().
225  *
226  * @since New in 1.5.
227  */
228 svn_error_t *
229 svn_rangelist_diff(apr_array_header_t **deleted, apr_array_header_t **added,
230  apr_array_header_t *from, apr_array_header_t *to,
231  svn_boolean_t consider_inheritance,
232  apr_pool_t *pool);
233 
234 /** Merge two rangelists consisting of @c svn_merge_range_t *
235  * elements, @a *rangelist and @a changes, placing the results in
236  * @a *rangelist. Either rangelist may be empty.
237  *
238  * When intersecting rangelists are merged, the inheritability of
239  * the resulting svn_merge_range_t depends on the inheritability of the
240  * operands: see svn_mergeinfo_merge().
241  *
242  * Note: @a *rangelist and @a changes must be sorted as said by @c
243  * svn_sort_compare_ranges(). @a *rangelist is guaranteed to remain
244  * in sorted order and be compacted to the minimal number of ranges
245  * needed to represent the merged result.
246  *
247  * @since New in 1.5.
248  */
249 svn_error_t *
250 svn_rangelist_merge(apr_array_header_t **rangelist,
251  apr_array_header_t *changes,
252  apr_pool_t *pool);
253 
254 /** Removes @a eraser (the subtrahend) from @a whiteboard (the
255  * minuend), and places the resulting difference in @a output.
256  *
257  * Note: @a eraser and @a whiteboard must be sorted as said by @c
258  * svn_sort_compare_ranges(). @a output is guaranteed to be in sorted
259  * order.
260  *
261  * @a consider_inheritance determines how to account for the
262  * @c svn_merge_range_t inheritable field when comparing @a whiteboard's
263  * and @a *eraser's rangelists for equality. @see svn_mergeinfo_diff().
264  *
265  * @since New in 1.5.
266  */
267 svn_error_t *
268 svn_rangelist_remove(apr_array_header_t **output, apr_array_header_t *eraser,
269  apr_array_header_t *whiteboard,
270  svn_boolean_t consider_inheritance,
271  apr_pool_t *pool);
272 
273 /** Find the intersection of two mergeinfos, @a mergeinfo1 and @a
274  * mergeinfo2, and place the result in @a *mergeinfo, which is (deeply)
275  * allocated in @a pool.
276  *
277  * @since New in 1.5.
278  */
279 svn_error_t *
280 svn_mergeinfo_intersect(svn_mergeinfo_t *mergeinfo,
281  svn_mergeinfo_t mergeinfo1,
282  svn_mergeinfo_t mergeinfo2,
283  apr_pool_t *pool);
284 
285 /** Find the intersection of two rangelists consisting of @c
286  * svn_merge_range_t * elements, @a rangelist1 and @a rangelist2, and
287  * place the result in @a *rangelist (which is never @c NULL).
288  *
289  * @a consider_inheritance determines how to account for the inheritability
290  * of the two rangelist's ranges when calculating the intersection,
291  * @see svn_mergeinfo_diff(). If @a consider_inheritance is FALSE then
292  * ranges with different inheritance can intersect, but the the resulting
293  * @a *rangelist is non-inheritable only if the corresponding ranges from
294  * both @a rangelist1 and @a rangelist2 are non-inheritable.
295  * If @a consider_inheritance is TRUE, then ranges with different
296  * inheritance can never intersect.
297  *
298  * Note: @a rangelist1 and @a rangelist2 must be sorted as said by @c
299  * svn_sort_compare_ranges(). @a *rangelist is guaranteed to be in sorted
300  * order.
301  * @since New in 1.5.
302  */
303 svn_error_t *
304 svn_rangelist_intersect(apr_array_header_t **rangelist,
305  apr_array_header_t *rangelist1,
306  apr_array_header_t *rangelist2,
307  svn_boolean_t consider_inheritance,
308  apr_pool_t *pool);
309 
310 /** Reverse @a rangelist, and the @c start and @c end fields of each
311  * range in @a rangelist, in place.
312  *
313  * TODO(miapi): Is this really a valid function? Rangelists that
314  * aren't sorted, or rangelists containing reverse ranges, are
315  * generally not valid in mergeinfo code. Can we rewrite the two
316  * places where this is used?
317  *
318  * @since New in 1.5.
319  */
320 svn_error_t *
321 svn_rangelist_reverse(apr_array_header_t *rangelist, apr_pool_t *pool);
322 
323 /** Take an array of svn_merge_range_t *'s in @a rangelist, and convert it
324  * back to a text format rangelist in @a output. If @a rangelist contains
325  * no elements, sets @a output to the empty string.
326  *
327  * @since New in 1.5.
328  */
329 svn_error_t *
331  const apr_array_header_t *rangelist,
332  apr_pool_t *pool);
333 
334 /** Return a deep copy of @c svn_merge_range_t *'s in @a rangelist excluding
335  * all non-inheritable @c svn_merge_range_t. If @a start and @a end are valid
336  * revisions and @a start is less than or equal to @a end, then exclude only the
337  * non-inheritable revision ranges that intersect inclusively with the range
338  * defined by @a start and @a end. If @a rangelist contains no elements, return
339  * an empty array. Allocate the copy in @a pool.
340  *
341  * @since New in 1.5.
342  */
343 svn_error_t *
344 svn_rangelist_inheritable(apr_array_header_t **inheritable_rangelist,
345  apr_array_header_t *rangelist,
346  svn_revnum_t start,
347  svn_revnum_t end,
348  apr_pool_t *pool);
349 
350 /** Return a deep copy of @a mergeinfo, excluding all non-inheritable
351  * @c svn_merge_range_t. If @a start and @a end are valid revisions
352  * and @a start is less than or equal to @a end, then exclude only the
353  * non-inheritable revisions that intersect inclusively with the range
354  * defined by @a start and @a end. If @a path is not NULL remove
355  * non-inheritable ranges only for @a path. If all ranges are removed
356  * for a given path then remove that path as well. If all paths are
357  * removed or @a rangelist is empty then set @a *inheritable_rangelist
358  * to an empty array. Allocate the copy in @a pool.
359  *
360  * @since New in 1.5.
361  */
362 svn_error_t *
363 svn_mergeinfo_inheritable(svn_mergeinfo_t *inheritable_mergeinfo,
364  svn_mergeinfo_t mergeinfo,
365  const char *path,
366  svn_revnum_t start,
367  svn_revnum_t end,
368  apr_pool_t *pool);
369 
370 /** Take a mergeinfo in MERGEINPUT, and convert it back to unparsed
371  * mergeinfo in *OUTPUT. If INPUT contains no elements, return the
372  * empty string.
373  *
374  * @a mergeinput may contain relative merge source paths, but these are
375  * converted to absolute paths in @a *output.
376  *
377  * @since New in 1.5.
378 */
379 svn_error_t *
381  svn_mergeinfo_t mergeinput,
382  apr_pool_t *pool);
383 
384 /** Take a hash of mergeinfo in @a mergeinfo, and sort the rangelists
385  * associated with each key (in place).
386  *
387  * TODO(miapi): mergeinfos should *always* be sorted. This should be
388  * a private function.
389  *
390  * @since New in 1.5
391  */
392 svn_error_t *
393 svn_mergeinfo_sort(svn_mergeinfo_t mergeinfo, apr_pool_t *pool);
394 
395 /** Return a deep copy of @a mergeinfo_catalog, allocated in @a pool.
396  *
397  * @since New in 1.6.
398  */
399 svn_mergeinfo_catalog_t
400 svn_mergeinfo_catalog_dup(svn_mergeinfo_catalog_t mergeinfo_catalog,
401  apr_pool_t *pool);
402 
403 /** Return a deep copy of @a mergeinfo, allocated in @a pool.
404  *
405  * @since New in 1.5.
406  */
407 svn_mergeinfo_t
408 svn_mergeinfo_dup(svn_mergeinfo_t mergeinfo, apr_pool_t *pool);
409 
410 /** Return a deep copy of @a rangelist, allocated in @a pool.
411  *
412  * @since New in 1.5.
413  */
414 apr_array_header_t *
415 svn_rangelist_dup(apr_array_header_t *rangelist, apr_pool_t *pool);
416 
417 
418 /**
419  * The three ways to request mergeinfo affecting a given path.
420  *
421  * @since New in 1.5.
422  */
423 typedef enum
424 {
425  /** Explicit mergeinfo only. */
427 
428  /** Explicit mergeinfo, or if that doesn't exist, the inherited
429  mergeinfo from a target's nearest (path-wise, not history-wise)
430  ancestor. */
432 
433  /** Mergeinfo on target's nearest (path-wise, not history-wise)
434  ancestor, regardless of whether target has explict mergeinfo. */
437 
438 /** Return a constant string expressing @a inherit as an English word,
439  * i.e., "explicit" (default), "inherited", or "nearest_ancestor".
440  * The string is not localized, as it may be used for client<->server
441  * communications.
442  *
443  * @since New in 1.5.
444  */
445 const char *
447 
448 
449 /** Return the appropriate @c svn_mergeinfo_inheritance_t for @a word.
450  * @a word is as returned from svn_inheritance_to_word(). Defaults to
451  * @c svn_mergeinfo_explicit.
452  *
453  * @since New in 1.5.
454  */
456 svn_inheritance_from_word(const char *word);
457 
458 
459 #ifdef __cplusplus
460 }
461 #endif /* __cplusplus */
462 
463 #endif /* SVN_MERGEINFO_H */