blob: c837b7ce79209ea78af58273d26f7d1c976f5fe6 [file] [log] [blame]
/**
* @copyright
* ====================================================================
* Copyright (c) 2006-2007 CollabNet. All rights reserved.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://subversion.tigris.org/license-1.html.
* If newer versions of this license are posted there, you may use a
* newer version instead, at your option.
*
* This software consists of voluntary contributions made by many
* individuals. For exact contribution history, see the revision
* history and logs, available at http://subversion.tigris.org/.
* ====================================================================
* @endcopyright
*
* @file svn_mergeinfo.h
* @brief mergeinfo handling and processing
*/
#ifndef SVN_MERGEINFO_H
#define SVN_MERGEINFO_H
#include <apr_pools.h>
#include <apr_tables.h> /* for apr_array_header_t */
#include <apr_hash.h>
#include "svn_error.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/** Overview of the @c SVN_PROP_MERGE_INFO property.
*
* Merge history is stored in the @c SVN_PROP_MERGE_INFO property of files
* and directories. The @c SVN_PROP_MERGE_INFO property on a path stores the
* complete list of changes merged to that path, either directly or via the
* path's parent, grand-parent, etc..
*
* Every path in a tree may have @c SVN_PROP_MERGE_INFO set, but if the
* @c SVN_PROP_MERGE_INFO for a path is equivalent to the
* @c SVN_PROP_MERGE_INFO for its parent, then the @c SVN_PROP_MERGE_INFO on
* the path will 'elide' (be removed) from the path as a post step to any
* merge, switch, or update. If a path's parent does not have any
* @c SVN_PROP_MERGE_INFO set, the path's mergeinfo can elide to its nearest
* grand-parent, great-grand-parent, etc. that has equivalent
* @c SVN_PROP_MERGE_INFO set on it.
*
* If a path has no @c SVN_PROP_MERGE_INFO of its own, it inherits mergeinfo
* from its nearest parent that has @c SVN_PROP_MERGE_INFO set. The
* exception to this is @c SVN_PROP_MERGE_INFO with non-ineritable revision
* ranges. These non-inheritable ranges apply only to the path which they
* are set on.
*
* The value of the @c SVN_PROP_MERGE_INFO property is a string consisting of
* a path, a colon, and comma separated revision list, containing one or more
* revision or revision ranges. Revision range start and end points are
* separated by "-". Revisions and revision ranges may have the optional
* @c SVN_MERGEINFO_NONINHERITABLE_STR suffix to signify a non-inheritable
* revision/revision range.
*
* @c SVN_PROP_MERGE_INFO Value Grammar:
*
* Token Definition
* ----- ----------
* revisionrange REVISION "-" REVISION
* revisioneelement (revisionrange | REVISION)"*"?
* rangelist revisioneelement (COMMA revisioneelement)*
* revisionline PATHNAME COLON rangelist
* top revisionline (NEWLINE revisionline)*
*
* The PATHNAME is the source of a merge and the rangelist the revision(s)
* merged to the path @c SVN_PROP_MERGE_INFO is set on directly or indirectly
* via inheritance. PATHNAME must always exist at the specified rangelist
* and thus multiple revisionlines are required to account for renames of
* the source pathname.
*
* Rangelists must be sorted from lowest to highest revision and cannot
* contain overlapping revisionlistelements. Single revisions that can be
* represented by a revisionrange are allowed (e.g. '5,6,7,8,9-12' or '5-12'
* are both acceptable).
*/
/* Suffix for SVN_PROP_MERGE_INFO revision ranges indicating a given
range is non-inheritable. */
#define SVN_MERGEINFO_NONINHERITABLE_STR "*"
/** Parse the mergeinfo from @a input into @a *mergeinfo, mapping from
* paths to @c apr_array_header_t *'s of @c svn_merge_range_t *
* elements. If no mergeinfo is available, return an empty hash
* (never @c NULL). Perform temporary allocations in @a pool.
*
* Note: @a *mergeinfo will contain rangelists that are guaranteed to
* be sorted (ordered by smallest revision ranges to largest).
* @since New in 1.5.
*/
svn_error_t *
svn_mergeinfo_parse(apr_hash_t **mergeinfo, const char *input,
apr_pool_t *pool);
/** Calculate the delta between two hashes of mergeinfo (with
* rangelists sorted in ascending order), @a mergefrom and @a mergeto
* (which may be @c NULL), and place the result in @a deleted and @a
* added (neither output argument will ever be @c NULL), stored as the
* usual mapping of paths to lists of @c svn_merge_range_t *'s.
*
* @a consider_inheritance determines how to account for the inheritability
* of the rangelists in @a mergefrom and @a mergeto when calculating the
* diff.
*
* @since New in 1.5.
*/
svn_error_t *
svn_mergeinfo_diff(apr_hash_t **deleted, apr_hash_t **added,
apr_hash_t *mergefrom, apr_hash_t *mergeto,
svn_merge_range_inheritance_t consider_inheritance,
apr_pool_t *pool);
/** Merge hash of mergeinfo, @a changes, into existing hash @a
* mergeinfo. @a consider_inheritance determines how to account for
* the inheritability of the rangelists in @a changes and @a *mergeinfo
* when merging.
*
* Note: @a mergeinfo and @a changes must have rangelists that are
* sorted as said by @c svn_sort_compare_ranges(). After the merge @a
* mergeinfo will have rangelists that are guaranteed to be in sorted
* order.
*
* @since New in 1.5.
*/
svn_error_t *
svn_mergeinfo_merge(apr_hash_t *mergeinfo, apr_hash_t *changes,
svn_merge_range_inheritance_t consider_inheritance,
apr_pool_t *pool);
/** Removes @a eraser (the subtrahend) from @a whiteboard (the
* minuend), and places the resulting difference in @a *mergeinfo.
*
* @since New in 1.5.
*/
svn_error_t *
svn_mergeinfo_remove(apr_hash_t **mergeinfo, apr_hash_t *eraser,
apr_hash_t *whiteboard, apr_pool_t *pool);
/** Calculate the delta between two rangelists consisting of @c
* svn_merge_range_t * elements (sorted in ascending order), @a from
* and @a to, and place the result in @a deleted and @a added (neither
* output argument will ever be @c NULL).
*
* @a consider_inheritance determines how to account for the inheritability
* of @a to and @a from when calculating the diff.
*
* @since New in 1.5.
*/
svn_error_t *
svn_rangelist_diff(apr_array_header_t **deleted, apr_array_header_t **added,
apr_array_header_t *from, apr_array_header_t *to,
svn_merge_range_inheritance_t consider_inheritance,
apr_pool_t *pool);
/** Merge two rangelists consisting of @c svn_merge_range_t *
* elements, @a *rangelist and @a changes, placing the results in
* @a *rangelist.
*
* @a consider_inheritance determines how to account for the inheritability
* of @a changes and @a *rangelist when merging.
*
* Note: @a *rangelist and @a changes must be sorted as said by @c
* svn_sort_compare_ranges(). @a *rangelist is guaranteed to remain
* in sorted order.
*
* @since New in 1.5.
*/
svn_error_t *
svn_rangelist_merge(apr_array_header_t **rangelist,
apr_array_header_t *changes,
svn_merge_range_inheritance_t consider_inheritance,
apr_pool_t *pool);
/** Removes @a eraser (the subtrahend) from @a whiteboard (the
* minuend), and places the resulting difference in @a output.
*
* Note: @a eraser and @a whiteboard must be sorted as said by @c
* svn_sort_compare_ranges(). @a output is guaranteed to be in sorted
* order.
*
* @a consider_inheritance determines how to account for the inheritability
* of @a whiteboard and @a *eraser when removing ranges.
*
* @since New in 1.5.
*/
svn_error_t *
svn_rangelist_remove(apr_array_header_t **output, apr_array_header_t *eraser,
apr_array_header_t *whiteboard,
svn_merge_range_inheritance_t consider_inheritance,
apr_pool_t *pool);
/** Find the intersection of two rangelists consisting of @c
* svn_merge_range_t * elements, @a rangelist1 and @a rangelist2, and
* place the result in @a output.
*
* Note: @a rangelist1 and @a rangelist2 must be sorted as said by @c
* svn_sort_compare_ranges(). @a output is guaranteed to be in sorted
* order.
* @since New in 1.5.
*/
svn_error_t *
svn_rangelist_intersect(apr_array_header_t **output,
apr_array_header_t *rangelist1,
apr_array_header_t *rangelist2,
apr_pool_t *pool);
/** Reverse @a rangelist, and the @c start and @c end fields of each
* range in @a rangelist, in place.
* @since New in 1.5.
*/
svn_error_t *
svn_rangelist_reverse(apr_array_header_t *rangelist, apr_pool_t *pool);
/** Take an array of svn_merge_range_t *'s in @a input, and convert it
* back to a text format rangelist in @a output. If @a input contains
* no elements, return the empty string.
*
* @since New in 1.5.
*/
svn_error_t *
svn_rangelist_to_stringbuf(svn_stringbuf_t **output,
apr_array_header_t *rangeinput,
apr_pool_t *pool);
/** Take an array of svn_merge_range_t *'s in @a rangelist, and return the
* number of distint revisions included in it.
*
* @since New in 1.5.
*/
apr_uint64_t
svn_rangelist_count_revs(apr_array_header_t *rangelist);
/** Take an array of @c svn_merge_range_t *'s in @a rangelist, and convert it
* to an array of @c svn_revnum_t's in @a revs. If @a rangelist contains
* no elements, return an empty array.
*
* @since New in 1.5.
*/
svn_error_t *
svn_rangelist_to_revs(apr_array_header_t **revs,
const apr_array_header_t *rangelist,
apr_pool_t *pool);
/** Return a deep copy of @c svn_merge_range_t *'s in @a rangelist excluding
* all non-inheritable @c svn_merge_range_t. If @a start and @a end are valid
* revisions and @a start is less than or equal to @a end, then exclude only the
* non-inheritable revision ranges that intersect inclusively with the range
* defined by @a start and @a end. If @a rangelist contains no elements, return
* an empty array. Allocate the copy in @a pool.
*
* @since New in 1.5.
*/
svn_error_t *
svn_rangelist_inheritable(apr_array_header_t **inheritable_rangelist,
apr_array_header_t *rangelist,
svn_revnum_t start,
svn_revnum_t end,
apr_pool_t *pool);
/** Remove redundancies between @ *range_1 and @ *range_2. @ *range_1 and/or
* @ *range_2 may be additive or subtractive ranges. The ranges should be
* sorted such that the minimum of @ *range_1->start and @ *range_1->end is
* less than or equal to the minimum of @ *range_2->start and
* @ *range_2->end.
*
* If either @ *range_1 or @ *range_2 is NULL, either range contains
* invalid svn_revnum_t's, or the two ranges do not intersect, then do
* nothing and return FALSE.
*
* If the two ranges can be reduced to one range, set @ *range_1 to represent
* that range, set @ *range_2 to NULL, and return TRUE.
*
* If the two ranges cancel each other out set both @ *range_1 and
* @ *range_2 to NULL and return TRUE.
*
* If the two ranges intersect but cannot be represented by one range (because
* one range is additive and the other subtractive) then modify @ *range_1 and
* @ *range_2 to remove the intersecting ranges and return TRUE.
*
* The inheritability of @ *range_1 or @ *range_2 is not taken into account.
*
* @since New in 1.5.
*/
svn_boolean_t
svn_range_compact(svn_merge_range_t **range_1,
svn_merge_range_t **range_2);
/** Return a deep copy of @a mergeinfo, a mapping from paths to
* @c apr_array_header_t *'s of @c svn_merge_range_t *, excluding all
* non-inheritable @c svn_merge_range_t. If @a start and @a end are valid
* revisions and @a start is less than or equal to @a end, then exclude only the
* non-inheritable revisions that intersect inclusively with the range
* defined by @a start and @a end. If @a path is not NULL remove
* non-inheritable ranges only for @a path. If @a mergeinfo is an empty hash,
* return an empty hash. Allocate the copy in @a pool.
*
* @since New in 1.5.
*/
svn_error_t *
svn_mergeinfo_inheritable(apr_hash_t **inheritable_mergeinfo,
apr_hash_t *mergeinfo,
const char *path,
svn_revnum_t start,
svn_revnum_t end,
apr_pool_t *pool);
/** Take a hash of mergeinfo in @a mergeinfo, and convert it back to
* a text format mergeinfo in @a output. If @a input contains no
* elements, return the empty string.
*
* @since New in 1.5.
*/
svn_error_t *
svn_mergeinfo_to_stringbuf(svn_stringbuf_t **output, apr_hash_t *mergeinfo,
apr_pool_t *pool);
/** Take a hash of mergeinfo in @a mergeinfo, and sort the rangelists
* associated with each key (in place).
* Note: This does not sort the hash, only the range lists in the
* hash.
* @since New in 1.5
*/
svn_error_t *
svn_mergeinfo_sort(apr_hash_t *mergeinfo, apr_pool_t *pool);
/** Return a deep copy of @a mergeinfo, allocated in @a pool.
*
* @since New in 1.5.
*/
apr_hash_t *
svn_mergeinfo_dup(apr_hash_t *mergeinfo, apr_pool_t *pool);
/** Return a deep copy of @a rangelist, allocated in @a pool.
*
* @since New in 1.5.
*/
apr_array_header_t *
svn_rangelist_dup(apr_array_header_t *rangelist, apr_pool_t *pool);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* SVN_MERGEINFO_H */