Subversion 1.6.16
|
00001 /** 00002 * @copyright 00003 * ==================================================================== 00004 * Copyright (c) 2006-2008 CollabNet. All rights reserved. 00005 * 00006 * This software is licensed as described in the file COPYING, which 00007 * you should have received as part of this distribution. The terms 00008 * are also available at http://subversion.tigris.org/license-1.html. 00009 * If newer versions of this license are posted there, you may use a 00010 * newer version instead, at your option. 00011 * 00012 * This software consists of voluntary contributions made by many 00013 * individuals. For exact contribution history, see the revision 00014 * history and logs, available at http://subversion.tigris.org/. 00015 * ==================================================================== 00016 * @endcopyright 00017 * 00018 * @file svn_mergeinfo.h 00019 * @brief mergeinfo handling and processing 00020 */ 00021 00022 00023 #ifndef SVN_MERGEINFO_H 00024 #define SVN_MERGEINFO_H 00025 00026 #include <apr_pools.h> 00027 #include <apr_tables.h> /* for apr_array_header_t */ 00028 #include <apr_hash.h> 00029 00030 #include "svn_types.h" 00031 #include "svn_string.h" /* for svn_string_t */ 00032 00033 00034 #ifdef __cplusplus 00035 extern "C" { 00036 #endif /* __cplusplus */ 00037 00038 /** Overview of the @c SVN_PROP_MERGEINFO property. 00039 * 00040 * Merge history is stored in the @c SVN_PROP_MERGEINFO property of files 00041 * and directories. The @c SVN_PROP_MERGEINFO property on a path stores the 00042 * complete list of changes merged to that path, either directly or via the 00043 * path's parent, grand-parent, etc.. A path may have empty mergeinfo which 00044 * means that nothing has been merged to that path or all previous merges 00045 * to the path were reversed. Note that a path may have no mergeinfo, this 00046 * is not the same as empty mergeinfo. 00047 * 00048 * Every path in a tree may have @c SVN_PROP_MERGEINFO set, but if the 00049 * @c SVN_PROP_MERGEINFO for a path is equivalent to the 00050 * @c SVN_PROP_MERGEINFO for its parent, then the @c SVN_PROP_MERGEINFO on 00051 * the path will 'elide' (be removed) from the path as a post step to any 00052 * merge. If a path's parent does not have any @c SVN_PROP_MERGEINFO set, 00053 * the path's mergeinfo can elide to its nearest grand-parent, 00054 * great-grand-parent, etc. that has equivalent @c SVN_PROP_MERGEINFO set 00055 * on it. 00056 * 00057 * If a path has no @c SVN_PROP_MERGEINFO of its own, it inherits mergeinfo 00058 * from its nearest parent that has @c SVN_PROP_MERGEINFO set. The 00059 * exception to this is @c SVN_PROP_MERGEINFO with non-ineritable revision 00060 * ranges. These non-inheritable ranges apply only to the path which they 00061 * are set on. 00062 * 00063 * Due to Subversion's allowance for mixed revision working copies, both 00064 * elision and inheritance within the working copy presume the path 00065 * between a path and its nearest parent with mergeinfo is at the same 00066 * working revision. If this is not the case then neither inheritance nor 00067 * elision can occur. 00068 * 00069 * The value of the @c SVN_PROP_MERGEINFO property is either an empty string 00070 * (representing empty mergeinfo) or a non-empty string consisting of 00071 * a path, a colon, and comma separated revision list, containing one or more 00072 * revision or revision ranges. Revision range start and end points are 00073 * separated by "-". Revisions and revision ranges may have the optional 00074 * @c SVN_MERGEINFO_NONINHERITABLE_STR suffix to signify a non-inheritable 00075 * revision/revision range. 00076 * 00077 * @c SVN_PROP_MERGEINFO Value Grammar: 00078 * 00079 * Token Definition 00080 * ----- ---------- 00081 * revisionrange REVISION1 "-" REVISION2 00082 * revisioneelement (revisionrange | REVISION)"*"? 00083 * rangelist revisioneelement (COMMA revisioneelement)* 00084 * revisionline PATHNAME COLON rangelist 00085 * top "" | (revisionline (NEWLINE revisionline))* 00086 * 00087 * The PATHNAME is the source of a merge and the rangelist the revision(s) 00088 * merged to the path @c SVN_PROP_MERGEINFO is set on directly or indirectly 00089 * via inheritance. PATHNAME must always exist at the specified rangelist 00090 * and thus a single merge may result in multiple revisionlines if the source 00091 * was renamed. 00092 * 00093 * Rangelists must be sorted from lowest to highest revision and cannot 00094 * contain overlapping revisionlistelements. REVISION1 must be less than 00095 * REVISION2. Consecutive single revisions that can be represented by a 00096 * revisionrange are allowed however (e.g. '5,6,7,8,9-12' or '5-12' are 00097 * both acceptable). 00098 */ 00099 00100 /* Suffix for SVN_PROP_MERGEINFO revision ranges indicating a given 00101 range is non-inheritable. */ 00102 #define SVN_MERGEINFO_NONINHERITABLE_STR "*" 00103 00104 /** Terminology for data structures that contain mergeinfo. 00105 * 00106 * Subversion commonly uses several data structures to represent 00107 * mergeinfo in RAM: 00108 * 00109 * (a) Strings (@c svn_string_t *) containing "unparsed mergeinfo". 00110 * 00111 * (b) A "rangelist". An array (@c apr_array_header_t *) of non-overlapping 00112 * merge ranges (@c svn_merge_range_t *), sorted as said by 00113 * @c svn_sort_compare_ranges(). An empty range list is represented by 00114 * an empty array. Unless specifically noted otherwise, all APIs require 00115 * rangelists that describe only forward ranges, i.e. the range's start 00116 * revision is less than its end revision. 00117 * 00118 * (c) @c svn_mergeinfo_t, called "mergeinfo". A hash mapping merge 00119 * source paths (@c const char *, starting with slashes) to 00120 * non-empty rangelist arrays. A @c NULL hash is used to represent 00121 * no mergeinfo and an empty hash is used to represent empty 00122 * mergeinfo. 00123 * 00124 * (d) @c svn_mergeinfo_catalog_t, called a "mergeinfo catalog". A hash 00125 * mapping paths (@c const char *, starting with slashes) to 00126 * @c svn_mergeinfo_t. 00127 * 00128 * Both @c svn_mergeinfo_t and @c svn_mergeinfo_catalog_t are just 00129 * typedefs for @c apr_hash_t *; there is no static type-checking, and 00130 * you still use standard @c apr_hash_t functions to interact with 00131 * them. 00132 * 00133 * Note that while the keys of mergeinfos are always relative to the 00134 * repository root, the keys of a catalog may be relative to something 00135 * else, such as an RA session root. 00136 */ 00137 00138 typedef apr_hash_t *svn_mergeinfo_t; 00139 typedef apr_hash_t *svn_mergeinfo_catalog_t; 00140 00141 /** Parse the mergeinfo from @a input into @a *mergeinfo. If no 00142 * mergeinfo is available, return an empty mergeinfo (never @c NULL). 00143 * Perform temporary allocations in @a pool. 00144 * 00145 * If @a input is not a grammatically correct @c SVN_PROP_MERGEINFO 00146 * property, contains overlapping revision ranges of differing 00147 * inheritability, or revision ranges with a start revision greater 00148 * than or equal to its end revision, or contains paths mapped to empty 00149 * revision ranges, then return @c SVN_ERR_MERGEINFO_PARSE_ERROR. 00150 * Unordered revision ranges are allowed, but will be sorted when 00151 * placed into @a *mergeinfo. Overlapping revision ranges of the same 00152 * inheritability are also allowed, but will be combined into a single 00153 * range when placed into @a *mergeinfo. 00154 * 00155 * @a input may contain relative merge source paths, but these are 00156 * converted to absolute paths in @a *mergeinfo. 00157 * 00158 * @since New in 1.5. 00159 */ 00160 svn_error_t * 00161 svn_mergeinfo_parse(svn_mergeinfo_t *mergeinfo, const char *input, 00162 apr_pool_t *pool); 00163 00164 /** Calculate the delta between two mergeinfos, @a mergefrom and @a mergeto 00165 * (which may be @c NULL), and place the result in @a *deleted and @a 00166 * *added (neither output argument may be @c NULL). 00167 * 00168 * @a consider_inheritance determines how the rangelists in the two 00169 * hashes are compared for equality. If @a consider_inheritance is FALSE, 00170 * then the start and end revisions of the @c svn_merge_range_t's being 00171 * compared are the only factors considered when determining equality. 00172 * 00173 * e.g. '/trunk: 1,3-4*,5' == '/trunk: 1,3-5' 00174 * 00175 * If @a consider_inheritance is TRUE, then the inheritability of the 00176 * @c svn_merge_range_t's is also considered and must be the same for two 00177 * otherwise identical ranges to be judged equal. 00178 * 00179 * e.g. '/trunk: 1,3-4*,5' != '/trunk: 1,3-5' 00180 * '/trunk: 1,3-4*,5' == '/trunk: 1,3-4*,5' 00181 * '/trunk: 1,3-4,5' == '/trunk: 1,3-4,5' 00182 * 00183 * @since New in 1.5. 00184 */ 00185 svn_error_t * 00186 svn_mergeinfo_diff(svn_mergeinfo_t *deleted, svn_mergeinfo_t *added, 00187 svn_mergeinfo_t mergefrom, svn_mergeinfo_t mergeto, 00188 svn_boolean_t consider_inheritance, 00189 apr_pool_t *pool); 00190 00191 /** Merge one mergeinfo, @a changes, into another mergeinfo @a 00192 * mergeinfo. 00193 * 00194 * When intersecting rangelists for a path are merged, the inheritability of 00195 * the resulting svn_merge_range_t depends on the inheritability of the 00196 * operands. If two non-inheritable ranges are merged the result is always 00197 * non-inheritable, in all other cases the resulting range is inheritable. 00198 * 00199 * e.g. '/A: 1,3-4' merged with '/A: 1,3,4*,5' --> '/A: 1,3-5' 00200 * '/A: 1,3-4*' merged with '/A: 1,3,4*,5' --> '/A: 1,3,4*,5' 00201 * 00202 * @since New in 1.5. 00203 */ 00204 svn_error_t * 00205 svn_mergeinfo_merge(svn_mergeinfo_t mergeinfo, svn_mergeinfo_t changes, 00206 apr_pool_t *pool); 00207 00208 /** Removes @a eraser (the subtrahend) from @a whiteboard (the 00209 * minuend), and places the resulting difference in @a *mergeinfo. 00210 * 00211 * @since New in 1.5. 00212 */ 00213 svn_error_t * 00214 svn_mergeinfo_remove(svn_mergeinfo_t *mergeinfo, svn_mergeinfo_t eraser, 00215 svn_mergeinfo_t whiteboard, apr_pool_t *pool); 00216 00217 /** Calculate the delta between two rangelists consisting of @c 00218 * svn_merge_range_t * elements (sorted in ascending order), @a from 00219 * and @a to, and place the result in @a *deleted and @a *added 00220 * (neither output argument will ever be @c NULL). 00221 * 00222 * @a consider_inheritance determines how to account for the inheritability 00223 * of the two rangelist's ranges when calculating the diff, 00224 * as described for svn_mergeinfo_diff(). 00225 * 00226 * @since New in 1.5. 00227 */ 00228 svn_error_t * 00229 svn_rangelist_diff(apr_array_header_t **deleted, apr_array_header_t **added, 00230 apr_array_header_t *from, apr_array_header_t *to, 00231 svn_boolean_t consider_inheritance, 00232 apr_pool_t *pool); 00233 00234 /** Merge two rangelists consisting of @c svn_merge_range_t * 00235 * elements, @a *rangelist and @a changes, placing the results in 00236 * @a *rangelist. Either rangelist may be empty. 00237 * 00238 * When intersecting rangelists are merged, the inheritability of 00239 * the resulting svn_merge_range_t depends on the inheritability of the 00240 * operands: see svn_mergeinfo_merge(). 00241 * 00242 * Note: @a *rangelist and @a changes must be sorted as said by @c 00243 * svn_sort_compare_ranges(). @a *rangelist is guaranteed to remain 00244 * in sorted order and be compacted to the minimal number of ranges 00245 * needed to represent the merged result. 00246 * 00247 * @since New in 1.5. 00248 */ 00249 svn_error_t * 00250 svn_rangelist_merge(apr_array_header_t **rangelist, 00251 apr_array_header_t *changes, 00252 apr_pool_t *pool); 00253 00254 /** Removes @a eraser (the subtrahend) from @a whiteboard (the 00255 * minuend), and places the resulting difference in @a output. 00256 * 00257 * Note: @a eraser and @a whiteboard must be sorted as said by @c 00258 * svn_sort_compare_ranges(). @a output is guaranteed to be in sorted 00259 * order. 00260 * 00261 * @a consider_inheritance determines how to account for the 00262 * @c svn_merge_range_t inheritable field when comparing @a whiteboard's 00263 * and @a *eraser's rangelists for equality. @see svn_mergeinfo_diff(). 00264 * 00265 * @since New in 1.5. 00266 */ 00267 svn_error_t * 00268 svn_rangelist_remove(apr_array_header_t **output, apr_array_header_t *eraser, 00269 apr_array_header_t *whiteboard, 00270 svn_boolean_t consider_inheritance, 00271 apr_pool_t *pool); 00272 00273 /** Find the intersection of two mergeinfos, @a mergeinfo1 and @a 00274 * mergeinfo2, and place the result in @a *mergeinfo, which is (deeply) 00275 * allocated in @a pool. 00276 * 00277 * @since New in 1.5. 00278 */ 00279 svn_error_t * 00280 svn_mergeinfo_intersect(svn_mergeinfo_t *mergeinfo, 00281 svn_mergeinfo_t mergeinfo1, 00282 svn_mergeinfo_t mergeinfo2, 00283 apr_pool_t *pool); 00284 00285 /** Find the intersection of two rangelists consisting of @c 00286 * svn_merge_range_t * elements, @a rangelist1 and @a rangelist2, and 00287 * place the result in @a *rangelist (which is never @c NULL). 00288 * 00289 * @a consider_inheritance determines how to account for the inheritability 00290 * of the two rangelist's ranges when calculating the intersection, 00291 * @see svn_mergeinfo_diff(). If @a consider_inheritance is FALSE then 00292 * ranges with different inheritance can intersect, but the the resulting 00293 * @a *rangelist is non-inheritable only if the corresponding ranges from 00294 * both @a rangelist1 and @a rangelist2 are non-inheritable. 00295 * If @a consider_inheritance is TRUE, then ranges with different 00296 * inheritance can never intersect. 00297 * 00298 * Note: @a rangelist1 and @a rangelist2 must be sorted as said by @c 00299 * svn_sort_compare_ranges(). @a *rangelist is guaranteed to be in sorted 00300 * order. 00301 * @since New in 1.5. 00302 */ 00303 svn_error_t * 00304 svn_rangelist_intersect(apr_array_header_t **rangelist, 00305 apr_array_header_t *rangelist1, 00306 apr_array_header_t *rangelist2, 00307 svn_boolean_t consider_inheritance, 00308 apr_pool_t *pool); 00309 00310 /** Reverse @a rangelist, and the @c start and @c end fields of each 00311 * range in @a rangelist, in place. 00312 * 00313 * TODO(miapi): Is this really a valid function? Rangelists that 00314 * aren't sorted, or rangelists containing reverse ranges, are 00315 * generally not valid in mergeinfo code. Can we rewrite the two 00316 * places where this is used? 00317 * 00318 * @since New in 1.5. 00319 */ 00320 svn_error_t * 00321 svn_rangelist_reverse(apr_array_header_t *rangelist, apr_pool_t *pool); 00322 00323 /** Take an array of svn_merge_range_t *'s in @a rangelist, and convert it 00324 * back to a text format rangelist in @a output. If @a rangelist contains 00325 * no elements, sets @a output to the empty string. 00326 * 00327 * @since New in 1.5. 00328 */ 00329 svn_error_t * 00330 svn_rangelist_to_string(svn_string_t **output, 00331 const apr_array_header_t *rangelist, 00332 apr_pool_t *pool); 00333 00334 /** Return a deep copy of @c svn_merge_range_t *'s in @a rangelist excluding 00335 * all non-inheritable @c svn_merge_range_t. If @a start and @a end are valid 00336 * revisions and @a start is less than or equal to @a end, then exclude only the 00337 * non-inheritable revision ranges that intersect inclusively with the range 00338 * defined by @a start and @a end. If @a rangelist contains no elements, return 00339 * an empty array. Allocate the copy in @a pool. 00340 * 00341 * @since New in 1.5. 00342 */ 00343 svn_error_t * 00344 svn_rangelist_inheritable(apr_array_header_t **inheritable_rangelist, 00345 apr_array_header_t *rangelist, 00346 svn_revnum_t start, 00347 svn_revnum_t end, 00348 apr_pool_t *pool); 00349 00350 /** Return a deep copy of @a mergeinfo, excluding all non-inheritable 00351 * @c svn_merge_range_t. If @a start and @a end are valid revisions 00352 * and @a start is less than or equal to @a end, then exclude only the 00353 * non-inheritable revisions that intersect inclusively with the range 00354 * defined by @a start and @a end. If @a path is not NULL remove 00355 * non-inheritable ranges only for @a path. If all ranges are removed 00356 * for a given path then remove that path as well. If all paths are 00357 * removed or @a rangelist is empty then set @a *inheritable_rangelist 00358 * to an empty array. Allocate the copy in @a pool. 00359 * 00360 * @since New in 1.5. 00361 */ 00362 svn_error_t * 00363 svn_mergeinfo_inheritable(svn_mergeinfo_t *inheritable_mergeinfo, 00364 svn_mergeinfo_t mergeinfo, 00365 const char *path, 00366 svn_revnum_t start, 00367 svn_revnum_t end, 00368 apr_pool_t *pool); 00369 00370 /** Take a mergeinfo in MERGEINPUT, and convert it back to unparsed 00371 * mergeinfo in *OUTPUT. If INPUT contains no elements, return the 00372 * empty string. 00373 * 00374 * @a mergeinput may contain relative merge source paths, but these are 00375 * converted to absolute paths in @a *output. 00376 * 00377 * @since New in 1.5. 00378 */ 00379 svn_error_t * 00380 svn_mergeinfo_to_string(svn_string_t **output, 00381 svn_mergeinfo_t mergeinput, 00382 apr_pool_t *pool); 00383 00384 /** Take a hash of mergeinfo in @a mergeinfo, and sort the rangelists 00385 * associated with each key (in place). 00386 * 00387 * TODO(miapi): mergeinfos should *always* be sorted. This should be 00388 * a private function. 00389 * 00390 * @since New in 1.5 00391 */ 00392 svn_error_t * 00393 svn_mergeinfo_sort(svn_mergeinfo_t mergeinfo, apr_pool_t *pool); 00394 00395 /** Return a deep copy of @a mergeinfo_catalog, allocated in @a pool. 00396 * 00397 * @since New in 1.6. 00398 */ 00399 svn_mergeinfo_catalog_t 00400 svn_mergeinfo_catalog_dup(svn_mergeinfo_catalog_t mergeinfo_catalog, 00401 apr_pool_t *pool); 00402 00403 /** Return a deep copy of @a mergeinfo, allocated in @a pool. 00404 * 00405 * @since New in 1.5. 00406 */ 00407 svn_mergeinfo_t 00408 svn_mergeinfo_dup(svn_mergeinfo_t mergeinfo, apr_pool_t *pool); 00409 00410 /** Return a deep copy of @a rangelist, allocated in @a pool. 00411 * 00412 * @since New in 1.5. 00413 */ 00414 apr_array_header_t * 00415 svn_rangelist_dup(apr_array_header_t *rangelist, apr_pool_t *pool); 00416 00417 00418 /** 00419 * The three ways to request mergeinfo affecting a given path. 00420 * 00421 * @since New in 1.5. 00422 */ 00423 typedef enum 00424 { 00425 /** Explicit mergeinfo only. */ 00426 svn_mergeinfo_explicit, 00427 00428 /** Explicit mergeinfo, or if that doesn't exist, the inherited 00429 mergeinfo from a target's nearest (path-wise, not history-wise) 00430 ancestor. */ 00431 svn_mergeinfo_inherited, 00432 00433 /** Mergeinfo on target's nearest (path-wise, not history-wise) 00434 ancestor, regardless of whether target has explict mergeinfo. */ 00435 svn_mergeinfo_nearest_ancestor 00436 } svn_mergeinfo_inheritance_t; 00437 00438 /** Return a constant string expressing @a inherit as an English word, 00439 * i.e., "explicit" (default), "inherited", or "nearest_ancestor". 00440 * The string is not localized, as it may be used for client<->server 00441 * communications. 00442 * 00443 * @since New in 1.5. 00444 */ 00445 const char * 00446 svn_inheritance_to_word(svn_mergeinfo_inheritance_t inherit); 00447 00448 00449 /** Return the appropriate @c svn_mergeinfo_inheritance_t for @a word. 00450 * @a word is as returned from svn_inheritance_to_word(). Defaults to 00451 * @c svn_mergeinfo_explicit. 00452 * 00453 * @since New in 1.5. 00454 */ 00455 svn_mergeinfo_inheritance_t 00456 svn_inheritance_from_word(const char *word); 00457 00458 00459 #ifdef __cplusplus 00460 } 00461 #endif /* __cplusplus */ 00462 00463 #endif /* SVN_MERGEINFO_H */