svn_mergeinfo.h

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

Generated on Sun Dec 21 21:45:19 2008 for Subversion by  doxygen 1.4.7