1/* 2 * mergeinfo.h : Client library-internal mergeinfo APIs. 3 * 4 * ==================================================================== 5 * Licensed to the Apache Software Foundation (ASF) under one 6 * or more contributor license agreements. See the NOTICE file 7 * distributed with this work for additional information 8 * regarding copyright ownership. The ASF licenses this file 9 * to you under the Apache License, Version 2.0 (the 10 * "License"); you may not use this file except in compliance 11 * with the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, 16 * software distributed under the License is distributed on an 17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18 * KIND, either express or implied. See the License for the 19 * specific language governing permissions and limitations 20 * under the License. 21 * ==================================================================== 22 */ 23 24#ifndef SVN_LIBSVN_CLIENT_MERGEINFO_H 25#define SVN_LIBSVN_CLIENT_MERGEINFO_H 26 27#include "svn_wc.h" 28#include "svn_client.h" 29#include "private/svn_client_private.h" 30 31 32/*** Data Structures ***/ 33 34 35/* Structure to store information about working copy paths that need special 36 consideration during a mergeinfo aware merge -- See the 37 'THE CHILDREN_WITH_MERGEINFO ARRAY' meta comment and the doc string for the 38 function get_mergeinfo_paths() in libsvn_client/merge.c. 39*/ 40typedef struct svn_client__merge_path_t 41{ 42 const char *abspath; /* Absolute working copy path. */ 43 svn_boolean_t missing_child; /* ABSPATH has an immediate child which 44 is missing, but is not switched. */ 45 svn_boolean_t switched_child; /* ABSPATH has an immediate child which 46 is switched. */ 47 svn_boolean_t switched; /* ABSPATH is switched. */ 48 svn_boolean_t has_noninheritable; /* ABSPATH has svn:mergeinfo set on it 49 which includes non-inheritable 50 revision ranges. */ 51 svn_boolean_t absent; /* ABSPATH is absent from the WC, 52 probably due to authz 53 restrictions. */ 54 55 svn_boolean_t child_of_noninheritable; /* ABSPATH has no explicit mergeinfo 56 itself but is the child of a 57 path with noniheritable 58 mergeinfo. */ 59 60 /* The remaining ranges to be merged to ABSPATH. When describing a forward 61 merge this rangelist adheres to the rules for rangelists described in 62 svn_mergeinfo.h. However, when describing reverse merges this 63 rangelist can contain reverse merge ranges that are not sorted per 64 svn_sort_compare_ranges(), but rather are sorted such that the ranges 65 with the youngest start revisions come first. In both the forward and 66 reverse merge cases the ranges should never overlap. This rangelist 67 may be empty but should never be NULL unless ABSENT is true. */ 68 svn_rangelist_t *remaining_ranges; 69 70 svn_mergeinfo_t pre_merge_mergeinfo; /* Explicit or inherited mergeinfo 71 on ABSPATH prior to a merge. 72 May be NULL. */ 73 svn_mergeinfo_t implicit_mergeinfo; /* Implicit mergeinfo on ABSPATH 74 prior to a merge. May be NULL. */ 75 svn_boolean_t inherited_mergeinfo; /* Whether PRE_MERGE_MERGEINFO was 76 explicit or inherited. */ 77 svn_boolean_t immediate_child_dir; /* ABSPATH is an immediate child 78 directory of the merge target, 79 has no explicit mergeinfo prior 80 to the merge, and the operational 81 depth of the merge is 82 svn_depth_immediates. */ 83 svn_boolean_t record_mergeinfo; /* Mergeinfo needs to be recorded 84 on ABSPATH to describe the 85 merge. */ 86 svn_boolean_t record_noninheritable; /* Non-inheritable mergeinfo needs to 87 be recorded on ABSPATH to describe 88 the merge. Implies RECORD_MERGEINFO 89 is true. */ 90} svn_client__merge_path_t; 91 92/* Return a deep copy of the merge-path structure OLD, allocated in POOL. */ 93svn_client__merge_path_t * 94svn_client__merge_path_dup(const svn_client__merge_path_t *old, 95 apr_pool_t *pool); 96 97/* Create a new merge path structure, allocated in POOL. Initialize the 98 * 'abspath' member to a deep copy of ABSPATH and all other fields to zero 99 * bytes. */ 100svn_client__merge_path_t * 101svn_client__merge_path_create(const char *abspath, 102 apr_pool_t *pool); 103 104 105 106/*** Functions ***/ 107 108/* Find explicit or inherited WC mergeinfo for LOCAL_ABSPATH, and return it 109 in *MERGEINFO (NULL if no mergeinfo is set). Set *INHERITED to 110 whether the mergeinfo was inherited (TRUE or FALSE), if INHERITED is 111 non-null. 112 113 This function will search for inherited mergeinfo in the parents of 114 LOCAL_ABSPATH only if the base revision of LOCAL_ABSPATH falls within 115 the range of the parent's last committed revision to the parent's base 116 revision (inclusive) or is LOCAL_ABSPATH is a local addition. If asking 117 for the inherited mergeinfo of an added path (i.e. one with no base 118 revision), that path may inherit mergeinfo from its nearest parent 119 with a base revision and explicit mergeinfo. 120 121 INHERIT indicates whether explicit, explicit or inherited, or only 122 inherited mergeinfo for LOCAL_ABSPATH is retrieved. 123 124 Don't look for inherited mergeinfo any higher than LIMIT_ABSPATH 125 (ignored if NULL) or beyond any switched path. 126 127 Set *WALKED_PATH to the path climbed from LOCAL_ABSPATH to find inherited 128 mergeinfo, or "" if none was found. (ignored if NULL). 129 130 If IGNORE_INVALID_MERGEINFO is true, then syntactically invalid explicit 131 mergeinfo on found on LOCAL_ABSPATH is ignored and *MERGEINFO is set to an 132 empty hash. If IGNORE_INVALID_MERGEINFO is false, then syntactically 133 invalid explicit mergeinfo on found on LOCAL_ABSPATH results in a 134 SVN_ERR_MERGEINFO_PARSE_ERROR error. Regardless of 135 IGNORE_INVALID_MERGEINFO, if LOCAL_ABSPATH inherits invalid mergeinfo, 136 then *MERGEINFO is always set to an empty hash and no parse error is 137 raised. */ 138svn_error_t * 139svn_client__get_wc_mergeinfo(svn_mergeinfo_t *mergeinfo, 140 svn_boolean_t *inherited, 141 svn_mergeinfo_inheritance_t inherit, 142 const char *local_abspath, 143 const char *limit_abspath, 144 const char **walked_path, 145 svn_boolean_t ignore_invalid_mergeinfo, 146 svn_client_ctx_t *ctx, 147 apr_pool_t *result_pool, 148 apr_pool_t *scratch_pool); 149 150/* If INCLUDE_DESCENDANTS is FALSE, behave exactly like 151 svn_client__get_wc_mergeinfo() except the mergeinfo for LOCAL_ABSPATH is 152 put in the mergeinfo catalog MERGEINFO_CAT, mapped from LOCAL_ABSPATH's 153 repository root-relative path. 154 155 If INCLUDE_DESCENDANTS is true, then any subtrees under LOCAL_ABSPATH with 156 explicit mergeinfo are also included in MERGEINFO_CAT and again the 157 keys are the repository root-relative paths of the subtrees. If no 158 mergeinfo is found, then *MERGEINFO_CAT is set to NULL. */ 159svn_error_t * 160svn_client__get_wc_mergeinfo_catalog(svn_mergeinfo_catalog_t *mergeinfo_cat, 161 svn_boolean_t *inherited, 162 svn_boolean_t include_descendants, 163 svn_mergeinfo_inheritance_t inherit, 164 const char *local_abspath, 165 const char *limit_path, 166 const char **walked_path, 167 svn_boolean_t ignore_invalid_mergeinfo, 168 svn_client_ctx_t *ctx, 169 apr_pool_t *result_pool, 170 apr_pool_t *scratch_pool); 171 172/* Obtain any mergeinfo for URL from the repository, and set 173 it in *TARGET_MERGEINFO. 174 175 INHERIT indicates whether explicit, explicit or inherited, or only 176 inherited mergeinfo for URL is obtained. 177 178 If URL does not exist at REV, SVN_ERR_FS_NOT_FOUND or 179 SVN_ERR_RA_DAV_REQUEST_FAILED is returned and *TARGET_MERGEINFO 180 is untouched. 181 182 If there is no mergeinfo available for URL, or if the server 183 doesn't support a mergeinfo capability and SQUELCH_INCAPABLE is 184 TRUE, set *TARGET_MERGEINFO to NULL. If the server doesn't support 185 a mergeinfo capability and SQUELCH_INCAPABLE is FALSE, return an 186 SVN_ERR_UNSUPPORTED_FEATURE error. 187 188 RA_SESSION is an open RA session to the repository in which URL lives; 189 it may be temporarily reparented by this function. 190*/ 191svn_error_t * 192svn_client__get_repos_mergeinfo(svn_mergeinfo_t *target_mergeinfo, 193 svn_ra_session_t *ra_session, 194 const char *url, 195 svn_revnum_t rev, 196 svn_mergeinfo_inheritance_t inherit, 197 svn_boolean_t squelch_incapable, 198 apr_pool_t *pool); 199 200/* If INCLUDE_DESCENDANTS is FALSE, behave exactly like 201 svn_client__get_repos_mergeinfo() except the mergeinfo for URL 202 is put in the mergeinfo catalog MERGEINFO_CAT, with the key being 203 the repository root-relative path of URL. 204 205 If INCLUDE_DESCENDANTS is true, then any subtrees under URL 206 with explicit mergeinfo are also included in MERGEINFO_CAT. The 207 keys for the subtree mergeinfo are the repository root-relative 208 paths of the subtrees. If no mergeinfo is found, then 209 *TARGET_MERGEINFO_CAT is set to NULL. */ 210svn_error_t * 211svn_client__get_repos_mergeinfo_catalog(svn_mergeinfo_catalog_t *mergeinfo_cat, 212 svn_ra_session_t *ra_session, 213 const char *url, 214 svn_revnum_t rev, 215 svn_mergeinfo_inheritance_t inherit, 216 svn_boolean_t squelch_incapable, 217 svn_boolean_t include_descendants, 218 apr_pool_t *result_pool, 219 apr_pool_t *scratch_pool); 220 221/* Retrieve the direct mergeinfo for the TARGET_WCPATH from the WC's 222 mergeinfo prop, or that inherited from its nearest ancestor if the 223 target has no info of its own. 224 225 If no mergeinfo can be obtained from the WC or REPOS_ONLY is TRUE, 226 get it from the repository. If the repository is contacted for mergeinfo 227 and RA_SESSION does not point to TARGET_WCPATH's URL, then it is 228 temporarily reparented. If RA_SESSION is NULL, then a temporary session 229 is opened as needed. 230 231 Store any mergeinfo obtained for TARGET_WCPATH in 232 *TARGET_MERGEINFO, if no mergeinfo is found *TARGET_MERGEINFO is 233 NULL. 234 235 Like svn_client__get_wc_mergeinfo(), this function considers no 236 inherited mergeinfo to be found in the WC when trying to crawl into 237 a parent path with a different working revision. 238 239 INHERIT indicates whether explicit, explicit or inherited, or only 240 inherited mergeinfo for TARGET_WCPATH is retrieved. 241 242 If FROM_REPOS is not NULL, then set *FROM_REPOS to true if 243 *TARGET_MERGEINFO is inherited and the repository was contacted to 244 obtain it. Set *FROM_REPOS to false otherwise. 245 246 If TARGET_WCPATH inherited its mergeinfo from a working copy ancestor 247 or if it was obtained from the repository, set *INHERITED to TRUE, set it 248 to FALSE otherwise, if INHERITED is non-null. */ 249svn_error_t * 250svn_client__get_wc_or_repos_mergeinfo(svn_mergeinfo_t *target_mergeinfo, 251 svn_boolean_t *inherited, 252 svn_boolean_t *from_repos, 253 svn_boolean_t repos_only, 254 svn_mergeinfo_inheritance_t inherit, 255 svn_ra_session_t *ra_session, 256 const char *target_wcpath, 257 svn_client_ctx_t *ctx, 258 apr_pool_t *pool); 259 260/* If INCLUDE_DESCENDANTS is false then behaves exactly like 261 svn_client__get_wc_or_repos_mergeinfo() except the mergeinfo for 262 TARGET_WCPATH is put in the mergeinfo catalog 263 TARGET_MERGEINFO_CATALOG, mapped from TARGET_WCPATH's repository 264 root-relative path. 265 266 IGNORE_INVALID_MERGEINFO behaves as per the argument of the same 267 name to svn_client__get_wc_mergeinfo(). It is applicable only if 268 the mergeinfo for TARGET_WCPATH is obtained from the working copy. 269 270 If INCLUDE_DESCENDANTS is true, then any subtrees under 271 TARGET_WCPATH with explicit mergeinfo are also included in 272 TARGET_MERGEINFO_CATALOG and again the keys are the repository 273 root-relative paths of the subtrees. If no mergeinfo is found, 274 then *TARGET_MERGEINFO_CAT is set to NULL. */ 275svn_error_t * 276svn_client__get_wc_or_repos_mergeinfo_catalog( 277 svn_mergeinfo_catalog_t *target_mergeinfo_catalog, 278 svn_boolean_t *inherited, 279 svn_boolean_t *from_repos, 280 svn_boolean_t include_descendants, 281 svn_boolean_t repos_only, 282 svn_boolean_t ignore_invalid_mergeinfo, 283 svn_mergeinfo_inheritance_t inherit, 284 svn_ra_session_t *ra_session, 285 const char *target_wcpath, 286 svn_client_ctx_t *ctx, 287 apr_pool_t *result_pool, 288 apr_pool_t *scratch_pool); 289 290/* Set *MERGEINFO_P to a mergeinfo constructed solely from the 291 natural history of PATHREV. 292 293 If RANGE_YOUNGEST and RANGE_OLDEST are valid, use them as inclusive 294 bounds on the revision ranges of returned mergeinfo. PATHREV->rev, 295 RANGE_YOUNGEST and RANGE_OLDEST are governed by the same rules as the 296 PEG_REVISION, START_REV, and END_REV parameters (respectively) of 297 svn_ra_get_location_segments(). 298 299 If HAS_REV_ZERO_HISTORY is not NULL, then set *HAS_REV_ZERO_HISTORY to 300 TRUE if the natural history includes revision 0, else to FALSE. 301 302 RA_SESSION is an open RA session to the repository of PATHREV; 303 it may be temporarily reparented by this function. 304*/ 305svn_error_t * 306svn_client__get_history_as_mergeinfo(svn_mergeinfo_t *mergeinfo_p, 307 svn_boolean_t *has_rev_zero_history, 308 const svn_client__pathrev_t *pathrev, 309 svn_revnum_t range_youngest, 310 svn_revnum_t range_oldest, 311 svn_ra_session_t *ra_session, 312 svn_client_ctx_t *ctx, 313 apr_pool_t *pool); 314 315/* Parse any explicit mergeinfo on LOCAL_ABSPATH and store it in 316 *MERGEINFO. If no record of any mergeinfo exists, set *MERGEINFO to NULL. 317 Does not acount for inherited mergeinfo. 318 319 Allocate the result deeply in @a result_pool. */ 320svn_error_t * 321svn_client__parse_mergeinfo(svn_mergeinfo_t *mergeinfo, 322 svn_wc_context_t *wc_ctx, 323 const char *local_abspath, 324 apr_pool_t *result_pool, 325 apr_pool_t *scratch_pool); 326 327/* Write MERGEINFO into the WC for LOCAL_ABSPATH. If MERGEINFO is NULL, 328 remove any SVN_PROP_MERGEINFO for LOCAL_ABSPATH. If MERGEINFO is empty, 329 record an empty property value (e.g. ""). If CTX->NOTIFY_FUNC2 is 330 not null call it with notification type svn_wc_notify_merge_record_info 331 if DO_NOTIFICATION is true. 332 333 Use WC_CTX to access the working copy, and SCRATCH_POOL for any temporary 334 allocations. */ 335svn_error_t * 336svn_client__record_wc_mergeinfo(const char *local_abspath, 337 svn_mergeinfo_t mergeinfo, 338 svn_boolean_t do_notification, 339 svn_client_ctx_t *ctx, 340 apr_pool_t *scratch_pool); 341 342/* Write mergeinfo into the WC. 343 * 344 * For each path in RESULT_CATALOG, set the SVN_PROP_MERGEINFO 345 * property to represent the given mergeinfo, or remove the property 346 * if the given mergeinfo is null, and notify the change. Leave 347 * other paths unchanged. RESULT_CATALOG maps (const char *) WC paths 348 * to (svn_mergeinfo_t) mergeinfo. */ 349svn_error_t * 350svn_client__record_wc_mergeinfo_catalog(apr_hash_t *result_catalog, 351 svn_client_ctx_t *ctx, 352 apr_pool_t *scratch_pool); 353 354/* Elide any svn:mergeinfo set on TARGET_ABSPATH to its nearest working 355 copy (or possibly repository) ancestor with equivalent mergeinfo. 356 357 If WC_ELISION_LIMIT_ABSPATH is NULL check up to the root of the 358 working copy or the nearest switched parent for an elision 359 destination, if none is found check the repository, otherwise check 360 as far as WC_ELISION_LIMIT_ABSPATH within the working copy. 361 362 Elision occurs if: 363 364 A) TARGET_ABSPATH has empty mergeinfo and no parent path with 365 explicit mergeinfo can be found in either the WC or the 366 repository (WC_ELISION_LIMIT_PATH must be NULL for this to 367 occur). 368 369 B) TARGET_ABSPATH has empty mergeinfo and its nearest parent also 370 has empty mergeinfo. 371 372 C) TARGET_ABSPATH has the same mergeinfo as its nearest parent 373 when that parent's mergeinfo is adjusted for the path 374 difference between the two, e.g.: 375 376 TARGET_ABSPATH = A_COPY/D/H 377 TARGET_ABSPATH's mergeinfo = '/A/D/H:3' 378 TARGET_ABSPATH nearest parent = A_COPY 379 Parent's mergeinfo = '/A:3' 380 Path difference = 'D/H' 381 Parent's adjusted mergeinfo = '/A/D/H:3' 382 383 If Elision occurs remove the svn:mergeinfo property from 384 TARGET_ABSPATH. */ 385svn_error_t * 386svn_client__elide_mergeinfo(const char *target_abspath, 387 const char *wc_elision_limit_abspath, 388 svn_client_ctx_t *ctx, 389 apr_pool_t *pool); 390 391/* Simplify a mergeinfo catalog, if possible, via elision. 392 393 For each path in MERGEINFO_CATALOG, check if the path's mergeinfo can 394 elide to the path's nearest path-wise parent in MERGEINFO_CATALOG. If 395 so, remove that path from MERGEINFO_CATALOG. Elidability is determined 396 as per svn_client__elide_mergeinfo except that elision to the repository 397 is not considered. 398 399 SCRATCH_POOL is used for temporary allocations. */ 400svn_error_t * 401svn_client__elide_mergeinfo_catalog(svn_mergeinfo_catalog_t mergeinfo_catalog, 402 apr_pool_t *scratch_pool); 403 404/* Set *MERGEINFO_CHANGES to TRUE if LOCAL_ABSPATH has locally modified 405 mergeinfo, set *MERGEINFO_CHANGES to FALSE otherwise. */ 406svn_error_t * 407svn_client__mergeinfo_status(svn_boolean_t *mergeinfo_changes, 408 svn_wc_context_t *wc_ctx, 409 const char *local_abspath, 410 apr_pool_t *scratch_pool); 411 412#endif /* SVN_LIBSVN_CLIENT_MERGEINFO_H */ 413