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