299
299
SVN_ERR(get_type_of_intersection(new_range, lastrange,
300
300
&intersection_type));
302
switch (intersection_type)
304
case svn__no_intersection:
305
/* NEW_RANGE and *LASTRANGE *really* don't intersect so
306
just push NEW_RANGE only RANGELIST. */
307
APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) =
308
svn_merge_range_dup(new_range, result_pool);
309
sorted = (svn_sort_compare_ranges(&lastrange,
313
case svn__equal_intersection:
314
/* They range are equal so all we do is force the
315
inheritability of lastrange to true. */
316
lastrange->inheritable = TRUE;
320
case svn__adjoining_intersection:
321
/* They adjoin but don't overlap so just push NEW_RANGE
323
APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) =
324
svn_merge_range_dup(new_range, result_pool);
325
sorted = (svn_sort_compare_ranges(&lastrange,
329
case svn__overlapping_intersection:
330
/* They ranges overlap but neither is a proper subset of
331
the other. We'll end up pusing two new ranges onto
332
RANGELIST, the intersecting part and the part unique to
335
svn_merge_range_t *r1 = svn_merge_range_dup(lastrange,
337
svn_merge_range_t *r2 = svn_merge_range_dup(new_range,
340
/* Pop off *LASTRANGE to make our manipulations
342
apr_array_pop(rangelist);
344
/* Ensure R1 is the older range. */
345
if (r2->start < r1->start)
347
/* Swap R1 and R2. */
352
/* Absorb the intersecting ranges into the
353
inheritable range. */
359
/* Push everything back onto RANGELIST. */
360
APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = r1;
361
sorted = (svn_sort_compare_ranges(&lastrange,
302
switch (intersection_type)
304
case svn__no_intersection:
305
/* NEW_RANGE and *LASTRANGE *really* don't intersect so
306
just push NEW_RANGE only RANGELIST. */
307
APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) =
308
svn_merge_range_dup(new_range, result_pool);
309
sorted = (svn_sort_compare_ranges(&lastrange,
313
case svn__equal_intersection:
314
/* They range are equal so all we do is force the
315
inheritability of lastrange to true. */
316
lastrange->inheritable = TRUE;
320
case svn__adjoining_intersection:
321
/* They adjoin but don't overlap so just push NEW_RANGE
323
APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) =
324
svn_merge_range_dup(new_range, result_pool);
325
sorted = (svn_sort_compare_ranges(&lastrange,
329
case svn__overlapping_intersection:
330
/* They ranges overlap but neither is a proper subset of
331
the other. We'll end up pusing two new ranges onto
332
RANGELIST, the intersecting part and the part unique to
335
svn_merge_range_t *r1 = svn_merge_range_dup(lastrange,
337
svn_merge_range_t *r2 = svn_merge_range_dup(new_range,
340
/* Pop off *LASTRANGE to make our manipulations
342
apr_array_pop(rangelist);
344
/* Ensure R1 is the older range. */
345
if (r2->start < r1->start)
347
/* Swap R1 and R2. */
352
/* Absorb the intersecting ranges into the
353
inheritable range. */
359
/* Push everything back onto RANGELIST. */
360
APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = r1;
361
sorted = (svn_sort_compare_ranges(&lastrange,
363
APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = r2;
365
sorted = (svn_sort_compare_ranges(&r1, &r2) < 0);
369
default: /* svn__proper_subset_intersection */
371
/* One range is a proper subset of the other. */
372
svn_merge_range_t *r1 = svn_merge_range_dup(lastrange,
374
svn_merge_range_t *r2 = svn_merge_range_dup(new_range,
376
svn_merge_range_t *r3 = NULL;
378
/* Pop off *LASTRANGE to make our manipulations
380
apr_array_pop(rangelist);
382
/* Ensure R1 is the superset. */
383
if (r2->start < r1->start || r2->end > r1->end)
385
/* Swap R1 and R2. */
392
/* The simple case: The superset is inheritable, so
393
just combine r1 and r2. */
394
r1->start = MIN(r1->start, r2->start);
395
r1->end = MAX(r1->end, r2->end);
398
else if (r1->start == r2->start)
400
svn_revnum_t tmp_revnum;
402
/* *LASTRANGE and NEW_RANGE share an end point. */
403
tmp_revnum = r1->end;
405
r2->inheritable = r1->inheritable;
406
r1->inheritable = TRUE;
408
r2->end = tmp_revnum;
410
else if (r1->end == r2->end)
412
/* *LASTRANGE and NEW_RANGE share an end point. */
414
r2->inheritable = TRUE;
418
/* NEW_RANGE and *LASTRANGE share neither start
420
r3 = apr_pcalloc(result_pool, sizeof(*r3));
423
r3->inheritable = r1->inheritable;
424
r2->inheritable = TRUE;
428
/* Push everything back onto RANGELIST. */
429
APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = r1;
430
sorted = (svn_sort_compare_ranges(&lastrange, &r1) < 0);
363
433
APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = r2;
365
435
sorted = (svn_sort_compare_ranges(&r1, &r2) < 0);
369
default: /* svn__proper_subset_intersection */
371
/* One range is a proper subset of the other. */
372
svn_merge_range_t *r1 = svn_merge_range_dup(lastrange,
374
svn_merge_range_t *r2 = svn_merge_range_dup(new_range,
376
svn_merge_range_t *r3 = NULL;
378
/* Pop off *LASTRANGE to make our manipulations
380
apr_array_pop(rangelist);
382
/* Ensure R1 is the superset. */
383
if (r2->start < r1->start || r2->end > r1->end)
385
/* Swap R1 and R2. */
392
/* The simple case: The superset is inheritable, so
393
just combine r1 and r2. */
394
r1->start = MIN(r1->start, r2->start);
395
r1->end = MAX(r1->end, r2->end);
398
else if (r1->start == r2->start)
400
svn_revnum_t tmp_revnum;
402
/* *LASTRANGE and NEW_RANGE share an end point. */
403
tmp_revnum = r1->end;
405
r2->inheritable = r1->inheritable;
406
r1->inheritable = TRUE;
408
r2->end = tmp_revnum;
410
else if (r1->end == r2->end)
412
/* *LASTRANGE and NEW_RANGE share an end point. */
414
r2->inheritable = TRUE;
418
/* NEW_RANGE and *LASTRANGE share neither start
420
r3 = apr_pcalloc(result_pool, sizeof(*r3));
423
r3->inheritable = r1->inheritable;
424
r2->inheritable = TRUE;
428
/* Push everything back onto RANGELIST. */
429
APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = r1;
430
sorted = (svn_sort_compare_ranges(&lastrange, &r1) < 0);
433
APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = r2;
435
sorted = (svn_sort_compare_ranges(&r1, &r2) < 0);
439
APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = r3;
443
sorted = (svn_sort_compare_ranges(&r2,
446
sorted = (svn_sort_compare_ranges(&r1,
439
APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = r3;
443
sorted = (svn_sort_compare_ranges(&r2,
446
sorted = (svn_sort_compare_ranges(&r1,
454
/* Some of the above cases might have put *RANGELIST out of
457
qsort(rangelist->elts, rangelist->nelts, rangelist->elt_size,
458
svn_sort_compare_ranges);
454
/* Some of the above cases might have put *RANGELIST out of
457
qsort(rangelist->elts, rangelist->nelts, rangelist->elt_size,
458
svn_sort_compare_ranges);
604
599
return SVN_NO_ERROR;
603
svn_rangelist__parse(svn_rangelist_t **rangelist,
605
apr_pool_t *result_pool)
609
*rangelist = apr_array_make(result_pool, 1, sizeof(svn_merge_range_t *));
610
SVN_ERR(parse_rangelist(&s, s + strlen(s), *rangelist, result_pool));
615
svn_rangelist__combine_adjacent_ranges(svn_rangelist_t *rangelist,
616
apr_pool_t *scratch_pool)
619
svn_merge_range_t *range, *lastrange;
621
lastrange = APR_ARRAY_IDX(rangelist, 0, svn_merge_range_t *);
623
for (i = 1; i < rangelist->nelts; i++)
625
range = APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *);
626
if (lastrange->start <= range->end
627
&& range->start <= lastrange->end)
629
/* The ranges are adjacent or intersect. */
631
/* svn_mergeinfo_parse promises to combine overlapping
632
ranges as long as their inheritability is the same. */
633
if (range->start < lastrange->end
634
&& range->inheritable != lastrange->inheritable)
636
return svn_error_createf(SVN_ERR_MERGEINFO_PARSE_ERROR, NULL,
637
_("Unable to parse overlapping "
638
"revision ranges '%s' and '%s' "
639
"with different inheritance "
641
range_to_string(lastrange,
643
range_to_string(range,
647
/* Combine overlapping or adjacent ranges with the
648
same inheritability. */
649
if (lastrange->inheritable == range->inheritable)
651
lastrange->end = MAX(range->end, lastrange->end);
652
svn_sort__array_delete(rangelist, i, 1);
656
lastrange = APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *);
607
662
/* revisionline -> PATHNAME COLON revisionlist */
608
663
static svn_error_t *
609
664
parse_revision_line(const char **input, const char *end, svn_mergeinfo_t hash,
665
apr_pool_t *scratch_pool)
612
const char *pathname;
613
apr_array_header_t *existing_rangelist;
614
apr_array_header_t *rangelist = apr_array_make(pool, 1,
615
sizeof(svn_merge_range_t *));
667
const char *pathname = "";
669
svn_rangelist_t *existing_rangelist;
670
svn_rangelist_t *rangelist = apr_array_make(scratch_pool, 1,
671
sizeof(svn_merge_range_t *));
617
SVN_ERR(parse_pathname(input, end, &pathname, pool));
673
SVN_ERR(parse_pathname(input, end, &pathname, scratch_pool));
619
675
if (*(*input) != ':')
620
676
return svn_error_create(SVN_ERR_MERGEINFO_PARSE_ERROR, NULL,
636
696
and make sure there are no overlapping ranges. */
637
697
if (rangelist->nelts > 1)
640
svn_merge_range_t *range, *lastrange;
642
699
qsort(rangelist->elts, rangelist->nelts, rangelist->elt_size,
643
700
svn_sort_compare_ranges);
644
lastrange = APR_ARRAY_IDX(rangelist, 0, svn_merge_range_t *);
646
for (i = 1; i < rangelist->nelts; i++)
648
range = APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *);
649
if (lastrange->start <= range->end
650
&& range->start <= lastrange->end)
652
/* The ranges are adjacent or intersect. */
654
/* svn_mergeinfo_parse promises to combine overlapping
655
ranges as long as their inheritability is the same. */
656
if (range->start < lastrange->end
657
&& range->inheritable != lastrange->inheritable)
659
return svn_error_createf(SVN_ERR_MERGEINFO_PARSE_ERROR, NULL,
660
_("Unable to parse overlapping "
661
"revision ranges '%s' and '%s' "
662
"with different inheritance "
664
range_to_string(lastrange, pool),
665
range_to_string(range, pool));
668
/* Combine overlapping or adjacent ranges with the
669
same inheritability. */
670
if (lastrange->inheritable == range->inheritable)
672
lastrange->end = MAX(range->end, lastrange->end);
673
if (i + 1 < rangelist->nelts)
674
memmove(rangelist->elts + (rangelist->elt_size * i),
675
rangelist->elts + (rangelist->elt_size * (i + 1)),
676
rangelist->elt_size * (rangelist->nelts - i));
681
lastrange = APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *);
702
SVN_ERR(svn_rangelist__combine_adjacent_ranges(rangelist, scratch_pool));
685
705
/* Handle any funky mergeinfo with relative merge source paths that
729
/* Cleanup after svn_rangelist_merge when it modifies the ending range of
758
/* Cleanup after svn_rangelist_merge2 when it modifies the ending range of
730
759
a single rangelist element in-place.
732
If *INDEX is not a valid element in RANGELIST do nothing. Otherwise ensure
733
that RANGELIST[*INDEX]->END does not adjoin or overlap any subsequent
761
If *RANGE_INDEX is not a valid element in RANGELIST do nothing. Otherwise
762
ensure that RANGELIST[*RANGE_INDEX]->END does not adjoin or overlap any
763
subsequent ranges in RANGELIST.
736
765
If overlap is found, then remove, modify, and/or add elements to RANGELIST
737
766
as per the invariants for rangelists documented in svn_mergeinfo.h. If
738
RANGELIST[*INDEX]->END adjoins a subsequent element then combine the
767
RANGELIST[*RANGE_INDEX]->END adjoins a subsequent element then combine the
739
768
elements if their inheritability permits -- The inheritance of intersecting
740
769
and adjoining ranges is handled as per svn_mergeinfo_merge2. Upon return
741
set *INDEX to the index of the youngest element modified, added, or
742
adjoined to RANGELIST[*INDEX].
770
set *RANGE_INDEX to the index of the youngest element modified, added, or
771
adjoined to RANGELIST[*RANGE_INDEX].
744
773
Note: Adjoining rangelist elements are those where the end rev of the older
745
774
element is equal to the start rev of the younger element.
747
776
Any new elements inserted into RANGELIST are allocated in RESULT_POOL.*/
749
adjust_remaining_ranges(apr_array_header_t *rangelist,
778
adjust_remaining_ranges(svn_rangelist_t *rangelist,
751
780
apr_pool_t *result_pool)
1080
1110
/* CHANGE and RANGE overlap. Set RANGE equal to its
1081
1111
intersection with CHANGE and take the remainder
1082
of RANGE and insert it into *RANGELIST. */
1112
of RANGE and insert it into RANGELIST. */
1083
1113
svn_merge_range_t *range_copy =
1084
svn_merge_range_dup(range, pool);
1114
svn_merge_range_dup(range, result_pool);
1085
1115
range_copy->start = change->end;
1086
1116
range->start = change->start;
1087
1117
range->end = change->end;
1088
1118
range->inheritable = TRUE;
1089
svn_sort__array_insert(&range_copy, *rangelist, ++i);
1119
svn_sort__array_insert(&range_copy, rangelist, ++i);
1095
1125
/* CHANGE and RANGE share the same start rev, but
1096
1126
CHANGE is considered older because its end rev
1099
1129
Insert the intersection of RANGE and CHANGE into
1100
*RANGELIST and then set RANGE to the non-intersecting
1130
RANGELIST and then set RANGE to the non-intersecting
1101
1131
portion of RANGE. */
1102
1132
svn_merge_range_t *range_copy =
1103
svn_merge_range_dup(range, pool);
1133
svn_merge_range_dup(range, result_pool);
1104
1134
range_copy->end = change->end;
1105
1135
range_copy->inheritable = TRUE;
1106
1136
range->start = change->end;
1107
svn_sort__array_insert(&range_copy, *rangelist, i++);
1137
svn_sort__array_insert(&range_copy, rangelist, i++);
1169
svn_rangelist_reverse(apr_array_header_t *rangelist, apr_pool_t *pool)
1198
svn_rangelist_reverse(svn_rangelist_t *rangelist, apr_pool_t *pool)
1172
svn_merge_range_t range;
1173
for (i = 0; i < rangelist->nelts / 2; i++)
1202
svn_sort__array_reverse(rangelist, pool);
1204
for (i = 0; i < rangelist->nelts; i++)
1175
swap_index = rangelist->nelts - i - 1;
1176
range = *APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *);
1177
*APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *) =
1178
*APR_ARRAY_IDX(rangelist, swap_index, svn_merge_range_t *);
1179
*APR_ARRAY_IDX(rangelist, swap_index, svn_merge_range_t *) = range;
1180
range_swap_endpoints(APR_ARRAY_IDX(rangelist, swap_index,
1181
svn_merge_range_t *));
1182
1206
range_swap_endpoints(APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *));
1185
/* If there's an odd number of elements, we still need to swap the
1186
end points of the remaining range. */
1187
if (rangelist->nelts % 2 == 1)
1188
range_swap_endpoints(APR_ARRAY_IDX(rangelist, rangelist->nelts / 2,
1189
svn_merge_range_t *));
1191
1209
return SVN_NO_ERROR;
1195
svn_rangelist__set_inheritance(apr_array_header_t *rangelist,
1213
svn_rangelist__set_inheritance(svn_rangelist_t *rangelist,
1196
1214
svn_boolean_t inheritable)
1532
1550
/* hash_a is FROM mergeinfo,
1533
1551
hash_b is TO mergeinfo. */
1534
1552
struct mergeinfo_diff_baton *cb = baton;
1535
apr_array_header_t *from_rangelist, *to_rangelist;
1553
svn_rangelist_t *from_rangelist, *to_rangelist;
1536
1554
const char *path = key;
1537
1555
if (status == svn_hash_diff_key_both)
1539
1557
/* Record any deltas (additions or deletions). */
1540
apr_array_header_t *deleted_rangelist, *added_rangelist;
1541
from_rangelist = apr_hash_get(cb->from, path, APR_HASH_KEY_STRING);
1542
to_rangelist = apr_hash_get(cb->to, path, APR_HASH_KEY_STRING);
1558
svn_rangelist_t *deleted_rangelist, *added_rangelist;
1559
from_rangelist = apr_hash_get(cb->from, path, klen);
1560
to_rangelist = apr_hash_get(cb->to, path, klen);
1543
1561
SVN_ERR(svn_rangelist_diff(&deleted_rangelist, &added_rangelist,
1544
1562
from_rangelist, to_rangelist,
1545
1563
cb->consider_inheritance, cb->pool));
1546
1564
if (cb->deleted && deleted_rangelist->nelts > 0)
1547
apr_hash_set(cb->deleted, apr_pstrdup(cb->pool, path),
1548
APR_HASH_KEY_STRING, deleted_rangelist);
1565
apr_hash_set(cb->deleted, apr_pstrmemdup(cb->pool, path, klen),
1566
klen, deleted_rangelist);
1549
1567
if (cb->added && added_rangelist->nelts > 0)
1550
apr_hash_set(cb->added, apr_pstrdup(cb->pool, path),
1551
APR_HASH_KEY_STRING, added_rangelist);
1568
apr_hash_set(cb->added, apr_pstrmemdup(cb->pool, path, klen),
1569
klen, added_rangelist);
1553
1571
else if ((status == svn_hash_diff_key_a) && cb->deleted)
1555
from_rangelist = apr_hash_get(cb->from, path, APR_HASH_KEY_STRING);
1556
apr_hash_set(cb->deleted, apr_pstrdup(cb->pool, path),
1557
APR_HASH_KEY_STRING,
1573
from_rangelist = apr_hash_get(cb->from, path, klen);
1574
apr_hash_set(cb->deleted, apr_pstrmemdup(cb->pool, path, klen), klen,
1558
1575
svn_rangelist_dup(from_rangelist, cb->pool));
1560
1577
else if ((status == svn_hash_diff_key_b) && cb->added)
1562
to_rangelist = apr_hash_get(cb->to, path, APR_HASH_KEY_STRING);
1563
apr_hash_set(cb->added, apr_pstrdup(cb->pool, path), APR_HASH_KEY_STRING,
1579
to_rangelist = apr_hash_get(cb->to, path, klen);
1580
apr_hash_set(cb->added, apr_pstrmemdup(cb->pool, path, klen), klen,
1564
1581
svn_rangelist_dup(to_rangelist, cb->pool));
1566
1583
return SVN_NO_ERROR;
1591
svn_mergeinfo_diff(svn_mergeinfo_t *deleted, svn_mergeinfo_t *added,
1592
svn_mergeinfo_t from, svn_mergeinfo_t to,
1593
svn_boolean_t consider_inheritance,
1608
svn_mergeinfo_diff2(svn_mergeinfo_t *deleted, svn_mergeinfo_t *added,
1609
svn_mergeinfo_t from, svn_mergeinfo_t to,
1610
svn_boolean_t consider_inheritance,
1611
apr_pool_t *result_pool,
1612
apr_pool_t *scratch_pool)
1596
1614
if (from && to == NULL)
1598
*deleted = svn_mergeinfo_dup(from, pool);
1599
*added = apr_hash_make(pool);
1616
*deleted = svn_mergeinfo_dup(from, result_pool);
1617
*added = svn_hash__make(result_pool);
1601
1619
else if (from == NULL && to)
1603
*deleted = apr_hash_make(pool);
1604
*added = svn_mergeinfo_dup(to, pool);
1621
*deleted = svn_hash__make(result_pool);
1622
*added = svn_mergeinfo_dup(to, result_pool);
1608
*deleted = apr_hash_make(pool);
1609
*added = apr_hash_make(pool);
1626
*deleted = svn_hash__make(result_pool);
1627
*added = svn_hash__make(result_pool);
1611
1629
if (from && to)
1613
1631
SVN_ERR(walk_mergeinfo_hash_for_diff(from, to, *deleted, *added,
1614
consider_inheritance, pool,
1632
consider_inheritance,
1633
result_pool, scratch_pool));
1626
1644
svn_boolean_t consider_inheritance,
1627
1645
apr_pool_t *pool)
1629
if (apr_hash_count(info1) == apr_hash_count(info2))
1631
svn_mergeinfo_t deleted, added;
1632
SVN_ERR(svn_mergeinfo_diff(&deleted, &added, info1, info2,
1633
consider_inheritance, pool));
1634
*is_equal = apr_hash_count(deleted) == 0 && apr_hash_count(added) == 0;
1647
apr_hash_index_t *hi;
1651
/* special cases: at least one side has no merge info */
1652
if (info1 == NULL && info2 == NULL)
1655
return SVN_NO_ERROR;
1658
if (info1 == NULL || info2 == NULL)
1659
return SVN_NO_ERROR;
1661
/* trivial case: different number of paths -> unequal */
1662
if (apr_hash_count(info1) != apr_hash_count(info2))
1663
return SVN_NO_ERROR;
1665
/* compare range lists for all paths */
1666
for (hi = apr_hash_first(pool, info1); hi; hi = apr_hash_next(hi))
1669
apr_ssize_t key_length;
1670
svn_rangelist_t *lhs, *rhs;
1672
svn_rangelist_t *deleted, *added;
1674
/* get both path lists */
1675
apr_hash_this(hi, (const void**)&key, &key_length, (void **)&lhs);
1676
rhs = apr_hash_get(info2, key, key_length);
1678
/* missing on one side? */
1680
return SVN_NO_ERROR;
1682
/* quick compare: the range lists will often be a perfect match */
1683
if (lhs->nelts == rhs->nelts)
1685
for (i = 0; i < lhs->nelts; ++i)
1687
svn_merge_range_t *lrange
1688
= APR_ARRAY_IDX(lhs, i, svn_merge_range_t *);
1689
svn_merge_range_t *rrange
1690
= APR_ARRAY_IDX(rhs, i, svn_merge_range_t *);
1692
/* range mismatch? -> needs detailed comparison */
1693
if ( lrange->start != rrange->start
1694
|| lrange->end != rrange->end)
1697
/* inheritance mismatch? -> merge info differs */
1698
if ( consider_inheritance
1699
&& lrange->inheritable != rrange->inheritable)
1700
return SVN_NO_ERROR;
1703
/* all ranges found to match -> next path */
1704
if (i == lhs->nelts)
1708
/* range lists differ but there are many ways to sort and aggregate
1709
revisions into ranges. Do a full diff on them. */
1710
SVN_ERR(svn_rangelist_diff(&deleted, &added, lhs, rhs,
1711
consider_inheritance, pool));
1712
if (deleted->nelts || added->nelts)
1713
return SVN_NO_ERROR;
1716
/* no mismatch found */
1640
1718
return SVN_NO_ERROR;
1644
svn_mergeinfo_merge(svn_mergeinfo_t mergeinfo, svn_mergeinfo_t changes,
1722
svn_mergeinfo_merge2(svn_mergeinfo_t mergeinfo,
1723
svn_mergeinfo_t changes,
1724
apr_pool_t *result_pool,
1725
apr_pool_t *scratch_pool)
1647
apr_array_header_t *sorted1, *sorted2;
1727
apr_hash_index_t *hi;
1728
apr_pool_t *iterpool;
1650
1730
if (!apr_hash_count(changes))
1651
1731
return SVN_NO_ERROR;
1653
sorted1 = svn_sort__hash(mergeinfo, svn_sort_compare_items_as_paths, pool);
1654
sorted2 = svn_sort__hash(changes, svn_sort_compare_items_as_paths, pool);
1658
while (i < sorted1->nelts && j < sorted2->nelts)
1733
iterpool = svn_pool_create(scratch_pool);
1734
for (hi = apr_hash_first(scratch_pool, changes); hi; hi = apr_hash_next(hi))
1660
svn_sort__item_t elt1, elt2;
1663
elt1 = APR_ARRAY_IDX(sorted1, i, svn_sort__item_t);
1664
elt2 = APR_ARRAY_IDX(sorted2, j, svn_sort__item_t);
1665
res = svn_sort_compare_items_as_paths(&elt1, &elt2);
1669
apr_array_header_t *rl1, *rl2;
1674
SVN_ERR(svn_rangelist_merge(&rl1, rl2,
1676
apr_hash_set(mergeinfo, elt1.key, elt1.klen, rl1);
1738
svn_rangelist_t *to_insert;
1739
svn_rangelist_t *target;
1741
/* get ranges to insert and the target ranges list of that insertion */
1742
apr_hash_this(hi, (const void**)&key, &klen, (void*)&to_insert);
1743
target = apr_hash_get(mergeinfo, key, klen);
1745
/* if range list exists, just expand on it.
1746
* Otherwise, add new hash entry. */
1749
SVN_ERR(svn_rangelist_merge2(target, to_insert, result_pool,
1751
svn_pool_clear(iterpool);
1686
apr_hash_set(mergeinfo, elt2.key, elt2.klen, elt2.value);
1754
apr_hash_set(mergeinfo, key, klen, to_insert);
1691
/* Copy back any remaining elements from the second hash. */
1692
for (; j < sorted2->nelts; j++)
1694
svn_sort__item_t elt = APR_ARRAY_IDX(sorted2, j, svn_sort__item_t);
1695
apr_hash_set(mergeinfo, elt.key, elt.klen, elt.value);
1757
svn_pool_destroy(iterpool);
1698
1759
return SVN_NO_ERROR;
2183
2205
hi = apr_hash_next(hi))
2185
const char *path = svn__apr_hash_index_key(hi);
2186
apr_array_header_t *rangelist = svn__apr_hash_index_val(hi);
2207
const char *fspath = svn__apr_hash_index_key(hi);
2208
svn_rangelist_t *rangelist = svn__apr_hash_index_val(hi);
2188
apr_hash_set(*out_mergeinfo,
2189
svn_dirent_join(path, suffix_relpath, result_pool),
2190
APR_HASH_KEY_STRING,
2191
svn_rangelist_dup(rangelist, result_pool));
2210
svn_hash_sets(*out_mergeinfo,
2211
svn_fspath__join(fspath, suffix_relpath, result_pool),
2194
2215
return SVN_NO_ERROR;
2197
apr_array_header_t *
2198
svn_rangelist_dup(const apr_array_header_t *rangelist, apr_pool_t *pool)
2219
svn_rangelist_dup(const svn_rangelist_t *rangelist, apr_pool_t *pool)
2200
apr_array_header_t *new_rl = apr_array_make(pool, rangelist->nelts,
2201
sizeof(svn_merge_range_t *));
2221
svn_rangelist_t *new_rl = apr_array_make(pool, rangelist->nelts,
2222
sizeof(svn_merge_range_t *));
2224
/* allocate target range buffer with a single operation */
2225
svn_merge_range_t *copy = apr_palloc(pool, sizeof(*copy) * rangelist->nelts);
2228
/* fill it iteratively and link it into the range list */
2204
2229
for (i = 0; i < rangelist->nelts; i++)
2206
APR_ARRAY_PUSH(new_rl, svn_merge_range_t *) =
2207
svn_merge_range_dup(APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *),
2232
APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *),
2234
APR_ARRAY_PUSH(new_rl, svn_merge_range_t *) = copy + i;
2601
2572
range->end = segment->range_end;
2602
2573
range->inheritable = TRUE;
2603
2574
APR_ARRAY_PUSH(path_ranges, svn_merge_range_t *) = range;
2604
apr_hash_set(mergeinfo, source_path, APR_HASH_KEY_STRING, path_ranges);
2575
svn_hash_sets(mergeinfo, source_path, path_ranges);
2607
2578
*mergeinfo_p = mergeinfo;
2608
2579
return SVN_NO_ERROR;
2583
svn_rangelist__merge_many(svn_rangelist_t *merged_rangelist,
2584
svn_mergeinfo_t merge_history,
2585
apr_pool_t *result_pool,
2586
apr_pool_t *scratch_pool)
2588
if (apr_hash_count(merge_history))
2590
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
2591
apr_hash_index_t *hi;
2593
for (hi = apr_hash_first(scratch_pool, merge_history);
2595
hi = apr_hash_next(hi))
2597
svn_rangelist_t *subtree_rangelist = svn__apr_hash_index_val(hi);
2599
svn_pool_clear(iterpool);
2600
SVN_ERR(svn_rangelist_merge2(merged_rangelist, subtree_rangelist,
2601
result_pool, iterpool));
2603
svn_pool_destroy(iterpool);
2605
return SVN_NO_ERROR;
2610
svn_inheritance_to_word(svn_mergeinfo_inheritance_t inherit)
2614
case svn_mergeinfo_inherited:
2616
case svn_mergeinfo_nearest_ancestor:
2617
return "nearest-ancestor";
2623
svn_mergeinfo_inheritance_t
2624
svn_inheritance_from_word(const char *word)
2626
if (strcmp(word, "inherited") == 0)
2627
return svn_mergeinfo_inherited;
2628
if (strcmp(word, "nearest-ancestor") == 0)
2629
return svn_mergeinfo_nearest_ancestor;
2630
return svn_mergeinfo_explicit;