Modified: subversion/branches/addremove/subversion/libsvn_subr/iter.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_subr/iter.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_subr/iter.c (original) +++ subversion/branches/addremove/subversion/libsvn_subr/iter.c Sat May 23 14:16:56 2020 @@ -37,7 +37,6 @@ static svn_error_t internal_break_error __LINE__ /* line number */ }; -#if APR_VERSION_AT_LEAST(1, 4, 0) struct hash_do_baton { void *baton; @@ -59,7 +58,6 @@ int hash_do_callback(void *baton, return hdb->err == SVN_NO_ERROR; } -#endif svn_error_t * svn_iter_apr_hash(svn_boolean_t *completed, @@ -68,7 +66,6 @@ svn_iter_apr_hash(svn_boolean_t *complet void *baton, apr_pool_t *pool) { -#if APR_VERSION_AT_LEAST(1, 4, 0) struct hash_do_baton hdb; svn_boolean_t error_received; @@ -97,43 +94,6 @@ svn_iter_apr_hash(svn_boolean_t *complet } return hdb.err; -#else - svn_error_t *err = SVN_NO_ERROR; - apr_pool_t *iterpool = svn_pool_create(pool); - apr_hash_index_t *hi; - - for (hi = apr_hash_first(pool, hash); - ! err && hi; hi = apr_hash_next(hi)) - { - const void *key; - void *val; - apr_ssize_t len; - - svn_pool_clear(iterpool); - - apr_hash_this(hi, &key, &len, &val); - err = (*func)(baton, key, len, val, iterpool); - } - - if (completed) - *completed = ! err; - - if (err && err->apr_err == SVN_ERR_ITER_BREAK) - { - if (err != &internal_break_error) - /* Errors - except those created by svn_iter_break() - - need to be cleared when not further propagated. */ - svn_error_clear(err); - - err = SVN_NO_ERROR; - } - - /* Clear iterpool, because callers may clear the error but have no way - to clear the iterpool with potentially lots of allocated memory */ - svn_pool_destroy(iterpool); - - return err; -#endif } svn_error_t * @@ -183,29 +143,3 @@ svn_iter__break(void) { return &internal_break_error; } - -#if !APR_VERSION_AT_LEAST(1, 5, 0) -const void *apr_hash_this_key(apr_hash_index_t *hi) -{ - const void *key; - - apr_hash_this((apr_hash_index_t *)hi, &key, NULL, NULL); - return key; -} - -apr_ssize_t apr_hash_this_key_len(apr_hash_index_t *hi) -{ - apr_ssize_t klen; - - apr_hash_this((apr_hash_index_t *)hi, NULL, &klen, NULL); - return klen; -} - -void *apr_hash_this_val(apr_hash_index_t *hi) -{ - void *val; - - apr_hash_this((apr_hash_index_t *)hi, NULL, NULL, &val); - return val; -} -#endif
Propchange: subversion/branches/addremove/subversion/libsvn_subr/lz4/ ------------------------------------------------------------------------------ --- svn:ignore (added) +++ svn:ignore Sat May 23 14:16:56 2020 @@ -0,0 +1 @@ +.libs Modified: subversion/branches/addremove/subversion/libsvn_subr/lz4/lz4.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_subr/lz4/lz4.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_subr/lz4/lz4.c (original) +++ subversion/branches/addremove/subversion/libsvn_subr/lz4/lz4.c Sat May 23 14:16:56 2020 @@ -1,5 +1,5 @@ #include "svn_private_config.h" -#if SVN_INTERNAL_LZ4 +#ifdef SVN_INTERNAL_LZ4 /* LZ4 - Fast LZ compression algorithm Copyright (C) 2011-2016, Yann Collet. @@ -1471,4 +1471,11 @@ int LZ4_decompress_fast_withPrefix64k(co } #endif /* LZ4_COMMONDEFS_ONLY */ +#else /* !SVN_INTERNAL_LZ4 */ + +/* Silence OSX ranlib warnings about object files with no symbols. */ +#include <apr.h> +extern const apr_uint32_t svn__fake__lz4internal; +const apr_uint32_t svn__fake__lz4internal = 0xdeadbeef; + #endif /* SVN_INTERNAL_LZ4 */ Modified: subversion/branches/addremove/subversion/libsvn_subr/lz4/lz4internal.h URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_subr/lz4/lz4internal.h?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_subr/lz4/lz4internal.h (original) +++ subversion/branches/addremove/subversion/libsvn_subr/lz4/lz4internal.h Sat May 23 14:16:56 2020 @@ -1,5 +1,5 @@ #include "svn_private_config.h" -#if SVN_INTERNAL_LZ4 +#ifdef SVN_INTERNAL_LZ4 /* * LZ4 - Fast LZ compression algorithm * Header File Modified: subversion/branches/addremove/subversion/libsvn_subr/mergeinfo.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_subr/mergeinfo.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_subr/mergeinfo.c (original) +++ subversion/branches/addremove/subversion/libsvn_subr/mergeinfo.c Sat May 23 14:16:56 2020 @@ -44,8 +44,9 @@ /* Return TRUE iff the forward revision range FIRST wholly contains the * forward revision range SECOND and (if CONSIDER_INHERITANCE is TRUE) has * the same inheritability. */ -static svn_boolean_t -range_contains(const svn_merge_range_t *first, const svn_merge_range_t *second, +static svn_error_t * +range_contains(svn_boolean_t *result, + const svn_merge_range_t *first, const svn_merge_range_t *second, svn_boolean_t consider_inheritance); @@ -457,21 +458,48 @@ combine_with_lastrange(const svn_merge_r } /* Convert a single svn_merge_range_t *RANGE back into a string. */ -static char * -range_to_string(const svn_merge_range_t *range, +static svn_error_t * +range_to_string(char **s, + const svn_merge_range_t *range, apr_pool_t *pool) { const char *mark = range->inheritable ? "" : SVN_MERGEINFO_NONINHERITABLE_STR; if (range->start == range->end - 1) - return apr_psprintf(pool, "%ld%s", range->end, mark); + *s = apr_psprintf(pool, "%ld%s", range->end, mark); else if (range->start - 1 == range->end) - return apr_psprintf(pool, "-%ld%s", range->start, mark); + *s = apr_psprintf(pool, "-%ld%s", range->start, mark); else if (range->start < range->end) - return apr_psprintf(pool, "%ld-%ld%s", range->start + 1, range->end, mark); + *s = apr_psprintf(pool, "%ld-%ld%s", range->start + 1, range->end, mark); + else if (range->start > range->end) + *s = apr_psprintf(pool, "%ld-%ld%s", range->start, range->end + 1, mark); else - return apr_psprintf(pool, "%ld-%ld%s", range->start, range->end + 1, mark); + { + return svn_error_createf(SVN_ERR_ASSERTION_FAIL, NULL, + _("bad range {start=%ld,end=%ld,inheritable=%d}"), + range->start, range->end, range->inheritable); + } + + return SVN_NO_ERROR; +} + +/* Convert a single svn_merge_range_t *RANGE back into a string. */ +static char * +range_to_string_debug(const svn_merge_range_t *range, + apr_pool_t *pool) +{ + svn_error_t *err; + char *s; + + err = range_to_string(&s, range, pool); + if (err) + { + svn_error_clear(err); + s = apr_psprintf(pool, _("bad range {start=%ld,end=%ld,inheritable=%d}"), + range->start, range->end, range->inheritable); + } + return s; } /* Helper for svn_mergeinfo_parse() @@ -667,10 +695,10 @@ svn_rangelist__canonicalize(svn_rangelis "revision ranges '%s' and '%s' " "with different inheritance " "types"), - range_to_string(lastrange, - scratch_pool), - range_to_string(range, - scratch_pool)); + range_to_string_debug(lastrange, + scratch_pool), + range_to_string_debug(range, + scratch_pool)); } /* Combine overlapping or adjacent ranges with the @@ -678,7 +706,7 @@ svn_rangelist__canonicalize(svn_rangelis if (lastrange->inheritable == range->inheritable) { lastrange->end = MAX(range->end, lastrange->end); - svn_sort__array_delete(rangelist, i, 1); + SVN_ERR(svn_sort__array_delete2(rangelist, i, 1)); i--; } } @@ -788,490 +816,349 @@ svn_mergeinfo_parse(svn_mergeinfo_t *mer return err; } -/* Cleanup after svn_rangelist_merge2 when it modifies the ending range of - a single rangelist element in-place. - - If *RANGE_INDEX is not a valid element in RANGELIST do nothing. Otherwise - ensure that RANGELIST[*RANGE_INDEX]->END does not adjoin or overlap any - subsequent ranges in RANGELIST. - - If overlap is found, then remove, modify, and/or add elements to RANGELIST - as per the invariants for rangelists documented in svn_mergeinfo.h. If - RANGELIST[*RANGE_INDEX]->END adjoins a subsequent element then combine the - elements if their inheritability permits -- The inheritance of intersecting - and adjoining ranges is handled as per svn_mergeinfo_merge2. Upon return - set *RANGE_INDEX to the index of the youngest element modified, added, or - adjoined to RANGELIST[*RANGE_INDEX]. +static const char * +rangelist_to_string_debug(const svn_rangelist_t *rl, + apr_pool_t *pool) +{ + svn_string_t *rls; + svn_error_t *err; - Note: Adjoining rangelist elements are those where the end rev of the older - element is equal to the start rev of the younger element. + err = svn_rangelist_to_string(&rls, rl, pool); + if (err) + { + char *s = apr_psprintf(pool, _("<bad rangelist [%d ranges]: %s>"), + rl->nelts, err->message); + svn_error_clear(err); + return s; + } + return rls->data; +} - Any new elements inserted into RANGELIST are allocated in RESULT_POOL.*/ -static void -adjust_remaining_ranges(svn_rangelist_t *rangelist, - int *range_index, - apr_pool_t *result_pool) +static svn_boolean_t +rangelist_is_sorted(const svn_rangelist_t *rangelist) { int i; - int starting_index; - int elements_to_delete = 0; - svn_merge_range_t *modified_range; - - if (*range_index >= rangelist->nelts) - return; - starting_index = *range_index + 1; - modified_range = APR_ARRAY_IDX(rangelist, *range_index, svn_merge_range_t *); - - for (i = *range_index + 1; i < rangelist->nelts; i++) + for (i = 1; i < rangelist->nelts; i++) { - svn_merge_range_t *next_range = APR_ARRAY_IDX(rangelist, i, - svn_merge_range_t *); + const svn_merge_range_t *lastrange + = APR_ARRAY_IDX(rangelist, i-1, svn_merge_range_t *); + const svn_merge_range_t *thisrange + = APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *); - /* If MODIFIED_RANGE doesn't adjoin or overlap the next range in - RANGELIST then we are finished. */ - if (modified_range->end < next_range->start) - break; + if (svn_sort_compare_ranges(&lastrange, &thisrange) > 0) + return FALSE; + } + return TRUE; +} - /* Does MODIFIED_RANGE adjoin NEXT_RANGE? */ - if (modified_range->end == next_range->start) - { - if (modified_range->inheritable == next_range->inheritable) - { - /* Combine adjoining ranges with the same inheritability. */ - modified_range->end = next_range->end; - elements_to_delete++; - } - else - { - /* Cannot join because inheritance differs. */ - (*range_index)++; - } - break; - } +/* Mergeinfo inheritance or absence in a rangelist interval */ +enum rangelist_interval_kind_t { MI_NONE, MI_NON_INHERITABLE, MI_INHERITABLE }; - /* Alright, we know MODIFIED_RANGE overlaps NEXT_RANGE, but how? */ - if (modified_range->end > next_range->end) - { - /* NEXT_RANGE is a proper subset of MODIFIED_RANGE and the two - don't share the same end range. */ - if (modified_range->inheritable - || (modified_range->inheritable == next_range->inheritable)) - { - /* MODIFIED_RANGE absorbs NEXT_RANGE. */ - elements_to_delete++; - } - else - { - /* NEXT_RANGE is a proper subset MODIFIED_RANGE but - MODIFIED_RANGE is non-inheritable and NEXT_RANGE is - inheritable. This means MODIFIED_RANGE is truncated, - NEXT_RANGE remains, and the portion of MODIFIED_RANGE - younger than NEXT_RANGE is added as a separate range: - ______________________________________________ - | | - M MODIFIED_RANGE N - | (!inheritable) | - |______________________________________________| - | | - O NEXT_RANGE P - | (inheritable)| - |______________| - | - V - _______________________________________________ - | | | | - M MODIFIED_RANGE O NEXT_RANGE P NEW_RANGE N - | (!inheritable) | (inheritable)| (!inheritable)| - |________________|______________|_______________| - */ - svn_merge_range_t *new_modified_range = - apr_palloc(result_pool, sizeof(*new_modified_range)); - new_modified_range->start = next_range->end; - new_modified_range->end = modified_range->end; - new_modified_range->inheritable = FALSE; - modified_range->end = next_range->start; - (*range_index)+=2; - svn_sort__array_insert(rangelist, &new_modified_range, - *range_index); - /* Recurse with the new range. */ - adjust_remaining_ranges(rangelist, range_index, result_pool); - break; - } - } - else if (modified_range->end == next_range->end) - { - /* NEXT_RANGE is a proper subset MODIFIED_RANGE and share - the same end range. */ - if (modified_range->inheritable - || (modified_range->inheritable == next_range->inheritable)) - { - /* MODIFIED_RANGE absorbs NEXT_RANGE. */ - elements_to_delete++; - } - else - { - /* The intersection between MODIFIED_RANGE and NEXT_RANGE is - absorbed by the latter. */ - modified_range->end = next_range->start; - (*range_index)++; - } - break; - } - else - { - /* NEXT_RANGE and MODIFIED_RANGE intersect but NEXT_RANGE is not - a proper subset of MODIFIED_RANGE, nor do the two share the - same end revision, i.e. they overlap. */ - if (modified_range->inheritable == next_range->inheritable) - { - /* Combine overlapping ranges with the same inheritability. */ - modified_range->end = next_range->end; - elements_to_delete++; - } - else if (modified_range->inheritable) - { - /* MODIFIED_RANGE absorbs the portion of NEXT_RANGE it overlaps - and NEXT_RANGE is truncated. */ - next_range->start = modified_range->end; - (*range_index)++; - } - else - { - /* NEXT_RANGE absorbs the portion of MODIFIED_RANGE it overlaps - and MODIFIED_RANGE is truncated. */ - modified_range->end = next_range->start; - (*range_index)++; - } - break; - } +/* A rangelist interval: like svn_merge_range_t but an interval can represent + * a gap in the rangelist (kind = MI_NONE). */ +typedef struct rangelist_interval_t +{ + svn_revnum_t start, end; + enum rangelist_interval_kind_t kind; +} rangelist_interval_t; + +/* Iterator for intervals in a rangelist. */ +typedef struct rangelist_interval_iterator_t { + /* iteration state: */ + const svn_rangelist_t *rl; /* input */ + int i; /* current interval is this range in RL or the gap before it */ + svn_boolean_t in_range; /* current interval is range RL[I], not a gap? */ + + /* current interval: */ + rangelist_interval_t interval; +} rangelist_interval_iterator_t; + +/* Update IT->interval to match the current iteration state of IT. + * Return the iterator, or NULL if the iteration has reached its end. + */ +static rangelist_interval_iterator_t * +rlii_update(rangelist_interval_iterator_t *it) +{ + const svn_merge_range_t *range + = (it->i < it->rl->nelts + ? APR_ARRAY_IDX(it->rl, it->i, void *) : NULL); + + if (!range) + return NULL; + + if (!it->in_range) + { + it->interval.start + = (it->i > 0 + ? APR_ARRAY_IDX(it->rl, it->i - 1, svn_merge_range_t *)->end + : 0); + it->interval.end = range->start; + it->interval.kind = MI_NONE; + } + else + { + it->interval.start = range->start; + it->interval.end = range->end; + it->interval.kind + = (range->inheritable ? MI_INHERITABLE : MI_NON_INHERITABLE); } + return it; +} - if (elements_to_delete) - svn_sort__array_delete(rangelist, starting_index, elements_to_delete); +/* Move to the next interval, which might be a zero-length interval. + * Return IT, or return NULL at the end of iteration. */ +static rangelist_interval_iterator_t * +rlii_next_any_interval(rangelist_interval_iterator_t *it) +{ + /* Should be called before iteration is finished. */ + if (it->i >= it->rl->nelts) + return NULL; + + /* If we are in a range, move to the next pre-range gap; + * else, move from this pre-range gap into this range. */ + if (it->in_range) + it->i++; + it->in_range = !it->in_range; + return it; } -#if 0 /* Temporary debug helper code */ -static svn_error_t * -dual_dump(const char *prefix, - const svn_rangelist_t *rangelist, - const svn_rangelist_t *changes, - apr_pool_t *scratch_pool) +/* Return an iterator pointing at the first non-zero-length interval in RL, + * or NULL if there are none. */ +static rangelist_interval_iterator_t * +rlii_first(const svn_rangelist_t *rl, + apr_pool_t *pool) { - svn_string_t *rls, *chg; + rangelist_interval_iterator_t *it = apr_palloc(pool, sizeof(*it)); - SVN_ERR(svn_rangelist_to_string(&rls, rangelist, scratch_pool)); - SVN_ERR(svn_rangelist_to_string(&chg, changes, scratch_pool)); + it->rl = rl; + it->i = 0; + it->in_range = FALSE; - SVN_DBG(("%s: %s / %s", prefix, rls->data, chg->data)); - return SVN_NO_ERROR; + /* Update, and skip empty intervals */ + while ((it = rlii_update(it)) && it->interval.start == it->interval.end) + { + it = rlii_next_any_interval(it); + } + return it; } -#endif -svn_error_t * -svn_rangelist_merge2(svn_rangelist_t *rangelist, - const svn_rangelist_t *chg, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) +/* Move to the next non-empty interval. + * Intervals will be generated in this sequence: + * (0, MI_NONE, RL[0]->start), // i=0, !in_range + * (RL[0]->start, MI_* RL[0]->end), // i=0, in_range + * (RL[0]->end, MI_NONE, RL[1]->start), + * (RL[1]->start, MI_* RL[1]->end), + * ... + * (RL[n-2]->end, MI_NONE, RL[n-1]->start), + * (RL[n-1]->start, MI_* RL[n-1]->end), + * but excluding empty intervals. + * Return IT, or return NULL at the end of iteration. */ +static rangelist_interval_iterator_t * +rlii_next(rangelist_interval_iterator_t *it) { - svn_rangelist_t *changes; - int i = 0; - int j; + it = rlii_next_any_interval(it); - SVN_ERR(svn_rangelist__canonicalize(rangelist, scratch_pool)); + /* Update, and skip empty intervals */ + while ((it = rlii_update(it)) && it->interval.start == it->interval.end) + { + it = rlii_next_any_interval(it); + } + return it; +} - /* We may modify CHANGES, so make a copy in SCRATCH_POOL. */ - changes = svn_rangelist_dup(chg, scratch_pool); - SVN_ERR(svn_rangelist__canonicalize(changes, scratch_pool)); +/* Rangelist builder. Accumulates consecutive intervals, combining them + * when possible. */ +typedef struct rangelist_builder_t { + svn_rangelist_t *rl; /* rangelist to build */ + rangelist_interval_t accu_interval; /* current interval accumulator */ + apr_pool_t *pool; /* from which to allocate ranges */ +} rangelist_builder_t; - for (j = 0; j < changes->nelts; j++) - { - svn_merge_range_t *range; - svn_merge_range_t *change = - APR_ARRAY_IDX(changes, j, svn_merge_range_t *); - int res; +/* Return an initialized rangelist builder. */ +static rangelist_builder_t * +rl_builder_new(svn_rangelist_t *rl, + apr_pool_t *pool) +{ + rangelist_builder_t *b = apr_pcalloc(pool, sizeof(*b)); - range = (i < rangelist->nelts) - ? APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *) - : NULL; - - if (!range || change->end < range->start) - { - /* No overlap, nor adjoin, copy change to result range */ - svn_merge_range_t *chg_copy = svn_merge_range_dup(change, - result_pool); - svn_sort__array_insert(rangelist, &chg_copy, i++); - continue; - } - else if ((change->start > range->end) - || (change->start == range->end - && change->inheritable != range->inheritable)) - { - /* No overlap, nor adjoin. Check next range item against change */ - i++; - j--; - continue; - } + b->rl = rl; + /* b->accu_interval = {0, 0, RL_NONE} */ + b->pool = pool; + return b; +} - if (change->start < range->start - && range->inheritable != change->inheritable - && ! (change->inheritable && range_contains(change, range, FALSE)) - && ! (range->inheritable && range_contains(range, change, FALSE))) - { - /* Can't fold change into existing range. - Insert new range before range */ +/* Flush the last accumulated interval in the rangelist builder B. */ +static void +rl_builder_flush(rangelist_builder_t *b) +{ + if (b->accu_interval.kind > MI_NONE) + { + svn_merge_range_t *mrange = apr_pcalloc(b->pool, sizeof(*mrange)); + mrange->start = b->accu_interval.start; + mrange->end = b->accu_interval.end; + mrange->inheritable = (b->accu_interval.kind == MI_INHERITABLE); + APR_ARRAY_PUSH(b->rl, svn_merge_range_t *) = mrange; + } +} - svn_merge_range_t *chg_copy = svn_merge_range_dup(change, - result_pool); +/* Add a new INTERVAL to the rangelist builder B. */ +static void +rl_builder_add_interval(rangelist_builder_t *b, + const rangelist_interval_t *interval) +{ + SVN_ERR_ASSERT_NO_RETURN(interval->start < interval->end); + SVN_ERR_ASSERT_NO_RETURN(interval->start == b->accu_interval.end); - chg_copy->start = MIN(change->start, range->start); - if (! change->inheritable) - chg_copy->end = range->start; - else - range->start = change->end; + /* Extend the accumulating interval, or end it and start another? */ + if (interval->kind == b->accu_interval.kind) + { + b->accu_interval.end = interval->end; + } + else + { + /* Push the accumulated interval onto the building rangelist. */ + rl_builder_flush(b); + /* Start accumulating a new interval */ + b->accu_interval = *interval; + } +} - svn_sort__array_insert(rangelist, &chg_copy, i++); +/* Set RL_OUT to the union (merge) of RL1 and RL2. + * On entry, RL_OUT must be an empty rangelist. + * + * Each range added to RL_OUT will be either shallow-copied from RL1 or + * allocated from RESULT_POOL. + */ +static svn_error_t * +rangelist_merge(svn_rangelist_t *rl_out, + const svn_rangelist_t *rl1, + const svn_rangelist_t *rl2, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + rangelist_interval_iterator_t *it[2]; + rangelist_builder_t *rl_builder = rl_builder_new(rl_out, result_pool); + svn_revnum_t r_last = 0; + + /*SVN_ERR_ASSERT(svn_rangelist__is_canonical(rl1));*/ + /*SVN_ERR_ASSERT(svn_rangelist__is_canonical(rl2));*/ + SVN_ERR_ASSERT(rangelist_is_sorted(rl1)); + SVN_ERR_ASSERT(rangelist_is_sorted(rl2)); + SVN_ERR_ASSERT(rl_out->nelts == 0); + + /* Initialize the input iterators and the output generator */ + it[0] = rlii_first(rl1, scratch_pool); + it[1] = rlii_first(rl2, scratch_pool); + + /* Keep choosing the next input revision (whether a start or end of a range) + * at which to consider making an output transition. */ + while (it[0] || it[1]) + { + svn_revnum_t r_next = !it[1] ? it[0]->interval.end + : !it[0] ? it[1]->interval.end + : MIN(it[0]->interval.end, it[1]->interval.end); + rangelist_interval_t interval; + + interval.start = r_last; + interval.end = r_next; + interval.kind = !it[1] ? it[0]->interval.kind + : !it[0] ? it[1]->interval.kind + : MAX(it[0]->interval.kind, it[1]->interval.kind); + + /* Accumulate */ + SVN_ERR_ASSERT(interval.start < interval.end); + rl_builder_add_interval(rl_builder, &interval); + + /* if we have used up either or both input intervals, increment them */ + if (it[0] && it[0]->interval.end <= r_next) + it[0] = rlii_next(it[0]); + if (it[1] && it[1]->interval.end <= r_next) + it[1] = rlii_next(it[1]); - change->start = chg_copy->end; - if (change->start >= change->end) - continue; /* No overlap with range left */ - } - else - { - range->start = MIN(range->start, change->start); - } + r_last = interval.end; + } + rl_builder_flush(rl_builder); + return SVN_NO_ERROR; +} - SVN_ERR_ASSERT(change->start >= range->start); +svn_error_t * +svn_rangelist_merge2(svn_rangelist_t *rangelist, + const svn_rangelist_t *chg, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_error_t *err; + svn_rangelist_t *rangelist_orig; - res = svn_sort_compare_ranges(&range, &change); +#ifdef SVN_DEBUG + SVN_ERR_ASSERT(rangelist_is_sorted(rangelist)); + SVN_ERR_ASSERT(rangelist_is_sorted(chg)); +#endif - if (res == 0) - { - /* Only when merging two non-inheritable ranges is the result also - non-inheritable. In all other cases ensure an inheritable - result. */ - if (range->inheritable || change->inheritable) - range->inheritable = TRUE; - i++; - continue; - } - else if (res < 0) /* CHANGE is younger than RANGE */ - { - if (range->end == change->start) - { - /* RANGE and CHANGE adjoin */ - if (range->inheritable == change->inheritable) - { - /* RANGE and CHANGE have the same inheritability so - RANGE expands to absord CHANGE. */ - range->end = change->end; - adjust_remaining_ranges(rangelist, &i, result_pool); - continue; - } - else - { - /* RANGE and CHANGE adjoin, but have different - inheritability. Since RANGE is older, just - move on to the next RANGE. */ - SVN_ERR_MALFUNCTION(); - } - } - else - { - /* RANGE and CHANGE overlap, but how? */ - if ((range->inheritable == change->inheritable) - || range->inheritable) - { - /* If CHANGE is a proper subset of RANGE, it absorbs RANGE - with no adjustment otherwise only the intersection is - absorbed and CHANGE is truncated. */ - if (range->end >= change->end) - continue; - else - { - change->start = range->end; - j--; - continue; - } - } - else - { - /* RANGE is non-inheritable and CHANGE is inheritable. */ - if (range->start < change->start) - { - /* CHANGE absorbs intersection with RANGE and RANGE - is truncated. */ - svn_merge_range_t *range_copy = - svn_merge_range_dup(range, result_pool); - range_copy->end = change->start; - range->start = change->start; - svn_sort__array_insert(rangelist, &range_copy, i++); - j--; - continue; - } - else - { - /* CHANGE and RANGE share the same start rev, but - RANGE is considered older because its end rev - is older. */ - range->inheritable = TRUE; - change->start = range->end; - j--; - continue; - } - } - } - } - else /* res > 0, CHANGE is older than RANGE */ - { - if (change->end == range->start) - { - /* RANGE and CHANGE adjoin */ - if (range->inheritable == change->inheritable) - { - /* RANGE and CHANGE have the same inheritability so we - can simply combine the two in place. */ - range->start = change->start; - continue; - } - else - { - /* RANGE and CHANGE have different inheritability so insert - a copy of CHANGE into RANGELIST. */ - SVN_ERR_MALFUNCTION(); /* Already handled */ - } - } - else - { - /* RANGE and CHANGE overlap. */ - if (range->inheritable == change->inheritable) - { - /* RANGE and CHANGE have the same inheritability so we - can simply combine the two in place... */ - range->start = change->start; - if (range->end < change->end) - { - /* ...but if RANGE is expanded ensure that we don't - violate any rangelist invariants. */ - range->end = change->end; - adjust_remaining_ranges(rangelist, &i, result_pool); - } - continue; - } - else if (range->inheritable) - { - if (change->start < range->start) - { - /* RANGE is inheritable so absorbs any part of CHANGE - it overlaps. CHANGE is truncated and the remainder - inserted into RANGELIST. */ - SVN_ERR_MALFUNCTION(); /* Already handled */ - } - else - { - /* CHANGE and RANGE share the same start rev, but - CHANGE is considered older because CHANGE->END is - older than RANGE->END. */ - continue; - } - } - else - { - /* RANGE is non-inheritable and CHANGE is inheritable. */ - if (change->start < range->start) - { - if (change->end == range->end) - { - /* RANGE is a proper subset of CHANGE and share the - same end revision, so set RANGE equal to CHANGE. */ - range->start = change->start; - range->inheritable = TRUE; - continue; - } - else if (change->end > range->end) - { - /* RANGE is a proper subset of CHANGE and CHANGE has - a younger end revision, so set RANGE equal to its - intersection with CHANGE and truncate CHANGE. */ - range->start = change->start; - range->inheritable = TRUE; - change->start = range->end; - j--; - continue; - } - else - { - /* CHANGE and RANGE overlap. Set RANGE equal to its - intersection with CHANGE and take the remainder - of RANGE and insert it into RANGELIST. */ - svn_merge_range_t *range_copy = - svn_merge_range_dup(range, result_pool); - range_copy->start = change->end; - range->start = change->start; - range->end = change->end; - range->inheritable = TRUE; - svn_sort__array_insert(rangelist, &range_copy, ++i); - continue; - } - } - else - { - /* CHANGE and RANGE share the same start rev, but - CHANGE is considered older because its end rev - is older. - - Insert the intersection of RANGE and CHANGE into - RANGELIST and then set RANGE to the non-intersecting - portion of RANGE. */ - svn_merge_range_t *range_copy = - svn_merge_range_dup(range, result_pool); - range_copy->end = change->end; - range_copy->inheritable = TRUE; - range->start = change->end; - svn_sort__array_insert(rangelist, &range_copy, i++); - continue; - } - } - } - } - SVN_ERR_MALFUNCTION(); /* Unreachable */ - } + /* Move the original rangelist aside. A shallow copy suffices, + * as rangelist_merge() won't modify its inputs. */ + rangelist_orig = apr_array_copy(scratch_pool, rangelist); + apr_array_clear(rangelist); + err = svn_error_trace(rangelist_merge(rangelist, rangelist_orig, chg, + result_pool, scratch_pool)); #ifdef SVN_DEBUG - SVN_ERR_ASSERT(svn_rangelist__is_canonical(rangelist)); + if (err) + { + err = svn_error_createf(SVN_ERR_ASSERTION_FAIL, err, + "svn_rangelist_merge2( %s / %s ): internal error", + rangelist_to_string_debug(rangelist_orig, scratch_pool), + rangelist_to_string_debug(chg, scratch_pool)); + } + else if (! svn_rangelist__is_canonical(rangelist) + && svn_rangelist__is_canonical(rangelist_orig) + && svn_rangelist__is_canonical(chg)) + { + err = svn_error_createf(SVN_ERR_ASSERTION_FAIL, NULL, + "svn_rangelist_merge2( %s / %s ): canonical inputs, " + "non-canonical result ( %s )", + rangelist_to_string_debug(rangelist_orig, scratch_pool), + rangelist_to_string_debug(chg, scratch_pool), + rangelist_to_string_debug(rangelist, scratch_pool)); + } #endif - return SVN_NO_ERROR; + return err; } -/* Return TRUE iff the forward revision ranges FIRST and SECOND overlap and - * (if CONSIDER_INHERITANCE is TRUE) have the same inheritability. */ -static svn_boolean_t -range_intersect(const svn_merge_range_t *first, const svn_merge_range_t *second, +/* Set *RESULT to TRUE iff the forward revision ranges FIRST and SECOND overlap + * and (if CONSIDER_INHERITANCE is TRUE) have the same inheritability. */ +static svn_error_t * +range_intersect(svn_boolean_t *result, + const svn_merge_range_t *first, const svn_merge_range_t *second, svn_boolean_t consider_inheritance) { - SVN_ERR_ASSERT_NO_RETURN(IS_VALID_FORWARD_RANGE(first)); - SVN_ERR_ASSERT_NO_RETURN(IS_VALID_FORWARD_RANGE(second)); + SVN_ERR_ASSERT(IS_VALID_FORWARD_RANGE(first)); + SVN_ERR_ASSERT(IS_VALID_FORWARD_RANGE(second)); - return (first->start + 1 <= second->end) - && (second->start + 1 <= first->end) - && (!consider_inheritance - || (!(first->inheritable) == !(second->inheritable))); + *result = (first->start + 1 <= second->end) + && (second->start + 1 <= first->end) + && (!consider_inheritance + || (!(first->inheritable) == !(second->inheritable))); + return SVN_NO_ERROR; } -/* Return TRUE iff the forward revision range FIRST wholly contains the +/* Set *RESULT to TRUE iff the forward revision range FIRST wholly contains the * forward revision range SECOND and (if CONSIDER_INHERITANCE is TRUE) has * the same inheritability. */ -static svn_boolean_t -range_contains(const svn_merge_range_t *first, const svn_merge_range_t *second, +static svn_error_t * +range_contains(svn_boolean_t *result, + const svn_merge_range_t *first, const svn_merge_range_t *second, svn_boolean_t consider_inheritance) { - SVN_ERR_ASSERT_NO_RETURN(IS_VALID_FORWARD_RANGE(first)); - SVN_ERR_ASSERT_NO_RETURN(IS_VALID_FORWARD_RANGE(second)); + SVN_ERR_ASSERT(IS_VALID_FORWARD_RANGE(first)); + SVN_ERR_ASSERT(IS_VALID_FORWARD_RANGE(second)); - return (first->start <= second->start) && (second->end <= first->end) - && (!consider_inheritance - || (!(first->inheritable) == !(second->inheritable))); + *result = (first->start <= second->start) && (second->end <= first->end) + && (!consider_inheritance + || (!(first->inheritable) == !(second->inheritable))); + return SVN_NO_ERROR; } /* Swap start and end fields of RANGE. */ @@ -1390,6 +1277,7 @@ rangelist_intersect_or_remove(svn_rangel while (i1 < rangelist1->nelts && i2 < rangelist2->nelts) { svn_merge_range_t *elt1, *elt2; + svn_boolean_t elt1_contains_elt2, elt1_intersects_elt2; elt1 = APR_ARRAY_IDX(rangelist1, i1, svn_merge_range_t *); @@ -1405,6 +1293,10 @@ rangelist_intersect_or_remove(svn_rangel elt2 = &working_elt2; + SVN_ERR(range_contains(&elt1_contains_elt2, + elt1, elt2, consider_inheritance)); + SVN_ERR(range_intersect(&elt1_intersects_elt2, + elt1, elt2, consider_inheritance)); /* If the rangelist2 range is contained completely in the rangelist1, we increment the rangelist2. If the ranges intersect, and match exactly, we increment both @@ -1413,7 +1305,7 @@ rangelist_intersect_or_remove(svn_rangel the removal of rangelist1 from rangelist2, and possibly change the rangelist2 to the remaining portion of the right part of the removal, to test against. */ - if (range_contains(elt1, elt2, consider_inheritance)) + if (elt1_contains_elt2) { if (!do_remove) { @@ -1434,7 +1326,7 @@ rangelist_intersect_or_remove(svn_rangel if (elt2->start == elt1->start && elt2->end == elt1->end) i1++; } - else if (range_intersect(elt1, elt2, consider_inheritance)) + else if (elt1_intersects_elt2) { if (elt2->start < elt1->start) { @@ -1977,18 +1869,21 @@ svn_rangelist_to_string(svn_string_t **o { int i; svn_merge_range_t *range; + char *s; /* Handle the elements that need commas at the end. */ for (i = 0; i < rangelist->nelts - 1; i++) { range = APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *); - svn_stringbuf_appendcstr(buf, range_to_string(range, pool)); + SVN_ERR(range_to_string(&s, range, pool)); + svn_stringbuf_appendcstr(buf, s); svn_stringbuf_appendcstr(buf, ","); } /* Now handle the last element, which needs no comma. */ range = APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *); - svn_stringbuf_appendcstr(buf, range_to_string(range, pool)); + SVN_ERR(range_to_string(&s, range, pool)); + svn_stringbuf_appendcstr(buf, s); } *output = svn_stringbuf__morph_into_string(buf); Modified: subversion/branches/addremove/subversion/libsvn_subr/object_pool.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_subr/object_pool.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_subr/object_pool.c (original) +++ subversion/branches/addremove/subversion/libsvn_subr/object_pool.c Sat May 23 14:16:56 2020 @@ -172,9 +172,11 @@ add_object_ref(object_ref_t *object_ref, if (svn_atomic_inc(&object_ref->ref_count) == 0) svn_atomic_dec(&object_ref->object_pool->unused_count); - /* make sure the reference gets released automatically */ - apr_pool_cleanup_register(pool, object_ref, object_ref_cleanup, - apr_pool_cleanup_null); + /* Make sure the reference gets released automatically. + Since POOL might be a parent pool of OBJECT_REF->OBJECT_POOL, + to the reference counting update before destroying any of the + pool hierarchy. */ + apr_pool_pre_cleanup_register(pool, object_ref, object_ref_cleanup); } /* Actual implementation of svn_object_pool__lookup. @@ -319,7 +321,7 @@ svn_object_pool__insert(void **object, { *object = NULL; SVN_MUTEX__WITH_LOCK(object_pool->mutex, - insert(object, object_pool, key, item, + insert(object, object_pool, key, item, item_pool, result_pool)); return SVN_NO_ERROR; } Modified: subversion/branches/addremove/subversion/libsvn_subr/opt.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_subr/opt.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_subr/opt.c (original) +++ subversion/branches/addremove/subversion/libsvn_subr/opt.c Sat May 23 14:16:56 2020 @@ -55,8 +55,8 @@ /*** Code. ***/ -const svn_opt_subcommand_desc2_t * -svn_opt_get_canonical_subcommand2(const svn_opt_subcommand_desc2_t *table, +const svn_opt_subcommand_desc3_t * +svn_opt_get_canonical_subcommand3(const svn_opt_subcommand_desc3_t *table, const char *cmd_name) { int i = 0; @@ -80,9 +80,9 @@ svn_opt_get_canonical_subcommand2(const } const apr_getopt_option_t * -svn_opt_get_option_from_code2(int code, +svn_opt_get_option_from_code3(int code, const apr_getopt_option_t *option_table, - const svn_opt_subcommand_desc2_t *command, + const svn_opt_subcommand_desc3_t *command, apr_pool_t *pool) { apr_size_t i; @@ -111,34 +111,19 @@ svn_opt_get_option_from_code2(int code, return NULL; } - -const apr_getopt_option_t * -svn_opt_get_option_from_code(int code, - const apr_getopt_option_t *option_table) -{ - apr_size_t i; - - for (i = 0; option_table[i].optch; i++) - if (option_table[i].optch == code) - return &(option_table[i]); - - return NULL; -} - - -/* Like svn_opt_get_option_from_code2(), but also, if CODE appears a second +/* Like svn_opt_get_option_from_code3(), but also, if CODE appears a second * time in OPTION_TABLE with a different name, then set *LONG_ALIAS to that * second name, else set it to NULL. */ static const apr_getopt_option_t * -get_option_from_code(const char **long_alias, - int code, - const apr_getopt_option_t *option_table, - const svn_opt_subcommand_desc2_t *command, - apr_pool_t *pool) +get_option_from_code3(const char **long_alias, + int code, + const apr_getopt_option_t *option_table, + const svn_opt_subcommand_desc3_t *command, + apr_pool_t *pool) { const apr_getopt_option_t *i; const apr_getopt_option_t *opt - = svn_opt_get_option_from_code2(code, option_table, command, pool); + = svn_opt_get_option_from_code3(code, option_table, command, pool); /* Find a long alias in the table, if there is one. */ *long_alias = NULL; @@ -205,7 +190,7 @@ svn_opt_format_option(const char **strin svn_boolean_t -svn_opt_subcommand_takes_option3(const svn_opt_subcommand_desc2_t *command, +svn_opt_subcommand_takes_option4(const svn_opt_subcommand_desc3_t *command, int option_code, const int *global_options) { @@ -223,38 +208,19 @@ svn_opt_subcommand_takes_option3(const s return FALSE; } -svn_boolean_t -svn_opt_subcommand_takes_option2(const svn_opt_subcommand_desc2_t *command, - int option_code) -{ - return svn_opt_subcommand_takes_option3(command, - option_code, - NULL); -} - - -svn_boolean_t -svn_opt_subcommand_takes_option(const svn_opt_subcommand_desc_t *command, - int option_code) -{ - apr_size_t i; - - for (i = 0; i < SVN_OPT_MAX_OPTIONS; i++) - if (command->valid_options[i] == option_code) - return TRUE; - - return FALSE; -} - /* Print the canonical command name for CMD, and all its aliases, to STREAM. If HELP is set, print CMD's help string too, in which case - obtain option usage from OPTIONS_TABLE. */ + obtain option usage from OPTIONS_TABLE. + + Include global and experimental options iff VERBOSE is true. + */ static svn_error_t * -print_command_info2(const svn_opt_subcommand_desc2_t *cmd, +print_command_info3(const svn_opt_subcommand_desc3_t *cmd, const apr_getopt_option_t *options_table, const int *global_options, svn_boolean_t help, + svn_boolean_t verbose, apr_pool_t *pool, FILE *stream) { @@ -289,8 +255,14 @@ print_command_info2(const svn_opt_subcom const apr_getopt_option_t *option; const char *long_alias; svn_boolean_t have_options = FALSE; + svn_boolean_t have_experimental = FALSE; - SVN_ERR(svn_cmdline_fprintf(stream, pool, ": %s", _(cmd->help))); + SVN_ERR(svn_cmdline_fprintf(stream, pool, ": ")); + + for (i = 0; i < SVN_OPT_MAX_PARAGRAPHS && cmd->help[i]; i++) + { + SVN_ERR(svn_cmdline_fprintf(stream, pool, "%s", _(cmd->help[i]))); + } /* Loop over all valid option codes attached to the subcommand */ for (i = 0; i < SVN_OPT_MAX_OPTIONS; i++) @@ -305,13 +277,24 @@ print_command_info2(const svn_opt_subcom } /* convert each option code into an option */ - option = get_option_from_code(&long_alias, cmd->valid_options[i], - options_table, cmd, pool); + option = get_option_from_code3(&long_alias, cmd->valid_options[i], + options_table, cmd, pool); /* print the option's docstring */ if (option && option->description) { const char *optstr; + + if (option->name && strncmp(option->name, "x-", 2) == 0) + { + if (verbose && !have_experimental) + SVN_ERR(svn_cmdline_fputs(_("\nExperimental options:\n"), + stream, pool)); + have_experimental = TRUE; + if (!verbose) + continue; + } + format_option(&optstr, option, long_alias, TRUE, pool); SVN_ERR(svn_cmdline_fprintf(stream, pool, " %s\n", optstr)); @@ -319,7 +302,7 @@ print_command_info2(const svn_opt_subcom } } /* And global options too */ - if (global_options && *global_options) + if (verbose && global_options && *global_options) { SVN_ERR(svn_cmdline_fputs(_("\nGlobal options:\n"), stream, pool)); @@ -329,8 +312,8 @@ print_command_info2(const svn_opt_subcom { /* convert each option code into an option */ - option = get_option_from_code(&long_alias, global_options[i], - options_table, cmd, pool); + option = get_option_from_code3(&long_alias, global_options[i], + options_table, cmd, pool); /* print the option's docstring */ if (option && option->description) @@ -343,6 +326,9 @@ print_command_info2(const svn_opt_subcom } } + if (!verbose) + SVN_ERR(svn_cmdline_fputs(_("\n(Use '-v' to show global and experimental options.)\n"), + stream, pool)); if (have_options) SVN_ERR(svn_cmdline_fprintf(stream, pool, "\n")); } @@ -350,30 +336,44 @@ print_command_info2(const svn_opt_subcom return SVN_NO_ERROR; } -/* The body for svn_opt_print_generic_help2() function with standard error +/* The body for svn_opt_print_generic_help3() function with standard error * handling semantic. Handling of errors implemented at caller side. */ static svn_error_t * -print_generic_help_body(const char *header, - const svn_opt_subcommand_desc2_t *cmd_table, - const apr_getopt_option_t *opt_table, - const char *footer, - apr_pool_t *pool, FILE *stream) +print_generic_help_body3(const char *header, + const svn_opt_subcommand_desc3_t *cmd_table, + const apr_getopt_option_t *opt_table, + const char *footer, + svn_boolean_t with_experimental, + apr_pool_t *pool, FILE *stream) { - int i = 0; + svn_boolean_t have_experimental = FALSE; + int i; if (header) SVN_ERR(svn_cmdline_fputs(header, stream, pool)); - while (cmd_table[i].name) + for (i = 0; cmd_table[i].name; i++) { + if (strncmp(cmd_table[i].name, "x-", 2) == 0) + { + if (with_experimental && !have_experimental) + SVN_ERR(svn_cmdline_fputs(_("\nExperimental subcommands:\n"), + stream, pool)); + have_experimental = TRUE; + if (!with_experimental) + continue; + } SVN_ERR(svn_cmdline_fputs(" ", stream, pool)); - SVN_ERR(print_command_info2(cmd_table + i, opt_table, - NULL, FALSE, + SVN_ERR(print_command_info3(cmd_table + i, opt_table, + NULL, FALSE, FALSE, pool, stream)); SVN_ERR(svn_cmdline_fputs("\n", stream, pool)); - i++; } + if (have_experimental && !with_experimental) + SVN_ERR(svn_cmdline_fputs(_("\n(Use '-v' to show experimental subcommands.)\n"), + stream, pool)); + SVN_ERR(svn_cmdline_fputs("\n", stream, pool)); if (footer) @@ -382,17 +382,19 @@ print_generic_help_body(const char *head return SVN_NO_ERROR; } -void -svn_opt_print_generic_help2(const char *header, - const svn_opt_subcommand_desc2_t *cmd_table, - const apr_getopt_option_t *opt_table, - const char *footer, - apr_pool_t *pool, FILE *stream) +static void +print_generic_help(const char *header, + const svn_opt_subcommand_desc3_t *cmd_table, + const apr_getopt_option_t *opt_table, + const char *footer, + svn_boolean_t with_experimental, + apr_pool_t *pool, FILE *stream) { svn_error_t *err; - err = print_generic_help_body(header, cmd_table, opt_table, footer, pool, - stream); + err = print_generic_help_body3(header, cmd_table, opt_table, footer, + with_experimental, + pool, stream); /* Issue #3014: * Don't print anything on broken pipes. The pipe was likely @@ -406,21 +408,37 @@ svn_opt_print_generic_help2(const char * svn_error_clear(err); } - void -svn_opt_subcommand_help3(const char *subcommand, - const svn_opt_subcommand_desc2_t *table, - const apr_getopt_option_t *options_table, - const int *global_options, - apr_pool_t *pool) +svn_opt_print_generic_help3(const char *header, + const svn_opt_subcommand_desc3_t *cmd_table, + const apr_getopt_option_t *opt_table, + const char *footer, + apr_pool_t *pool, FILE *stream) { - const svn_opt_subcommand_desc2_t *cmd = - svn_opt_get_canonical_subcommand2(table, subcommand); + print_generic_help(header, cmd_table, opt_table, footer, + TRUE, pool, stream); +} + + +/* The body of svn_opt_subcommand_help4(), which see. + * + * VERBOSE means show also the subcommand's global and experimental options. + */ +static void +subcommand_help(const char *subcommand, + const svn_opt_subcommand_desc3_t *table, + const apr_getopt_option_t *options_table, + const int *global_options, + svn_boolean_t verbose, + apr_pool_t *pool) +{ + const svn_opt_subcommand_desc3_t *cmd = + svn_opt_get_canonical_subcommand3(table, subcommand); svn_error_t *err; if (cmd) - err = print_command_info2(cmd, options_table, global_options, - TRUE, pool, stdout); + err = print_command_info3(cmd, options_table, global_options, + TRUE, verbose, pool, stdout); else err = svn_cmdline_fprintf(stderr, pool, _("\"%s\": unknown command.\n\n"), subcommand); @@ -433,6 +451,17 @@ svn_opt_subcommand_help3(const char *sub } } +void +svn_opt_subcommand_help4(const char *subcommand, + const svn_opt_subcommand_desc3_t *table, + const apr_getopt_option_t *options_table, + const int *global_options, + apr_pool_t *pool) +{ + subcommand_help(subcommand, table, options_table, global_options, + TRUE, pool); +} + /*** Parsing revision and date options. ***/ @@ -1194,14 +1223,14 @@ svn_opt__print_version_info(const char * } svn_error_t * -svn_opt_print_help4(apr_getopt_t *os, +svn_opt_print_help5(apr_getopt_t *os, const char *pgm_name, svn_boolean_t print_version, svn_boolean_t quiet, svn_boolean_t verbose, const char *version_footer, const char *header, - const svn_opt_subcommand_desc2_t *cmd_table, + const svn_opt_subcommand_desc3_t *cmd_table, const apr_getopt_option_t *option_table, const int *global_options, const char *footer, @@ -1218,9 +1247,9 @@ svn_opt_print_help4(apr_getopt_t *os, for (i = 0; i < targets->nelts; i++) { - svn_opt_subcommand_help3(APR_ARRAY_IDX(targets, i, const char *), - cmd_table, option_table, - global_options, pool); + subcommand_help(APR_ARRAY_IDX(targets, i, const char *), + cmd_table, option_table, global_options, + verbose, pool); } } else if (print_version) /* just --version */ @@ -1230,12 +1259,9 @@ svn_opt_print_help4(apr_getopt_t *os, quiet, verbose, pool)); } else if (os && !targets->nelts) /* `-h', `--help', or `help' */ - svn_opt_print_generic_help2(header, - cmd_table, - option_table, - footer, - pool, - stdout); + print_generic_help(header, cmd_table, option_table, footer, + verbose, + pool, stdout); else /* unknown option or cmd */ SVN_ERR(svn_cmdline_fprintf(stderr, pool, _("Type '%s help' for usage.\n"), pgm_name)); Modified: subversion/branches/addremove/subversion/libsvn_subr/path.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_subr/path.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_subr/path.c (original) +++ subversion/branches/addremove/subversion/libsvn_subr/path.c Sat May 23 14:16:56 2020 @@ -590,7 +590,7 @@ svn_path_is_ancestor(const char *path1, { apr_size_t path1_len = strlen(path1); - /* If path1 is empty and path2 is not absoulte, then path1 is an ancestor. */ + /* If path1 is empty and path2 is not absolute, then path1 is an ancestor. */ if (SVN_PATH_IS_EMPTY(path1)) return *path2 != '/'; Modified: subversion/branches/addremove/subversion/libsvn_subr/pool.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_subr/pool.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_subr/pool.c (original) +++ subversion/branches/addremove/subversion/libsvn_subr/pool.c Sat May 23 14:16:56 2020 @@ -133,7 +133,7 @@ svn_pool_create_allocator(svn_boolean_t #endif /* By default, allocators are *not* thread-safe. We must provide a mutex - * if we want thread-safety for that mutex. */ + * if we want thread-safety for that pool. */ #if APR_HAS_THREADS if (thread_safe) @@ -151,16 +151,6 @@ svn_pool_create_allocator(svn_boolean_t } -/* - * apr_pool_create_core_ex was introduced in APR 1.3.0, then - * deprecated and renamed to apr_pool_create_unmanaged_ex in 1.3.3. - * Since our minimum requirement is APR 1.3.0, one or the other of - * these functions will always be available. - */ -#if !APR_VERSION_AT_LEAST(1,3,3) -#define apr_pool_create_unmanaged_ex apr_pool_create_core_ex -#endif - /* Private function that creates an unmanaged pool. */ apr_pool_t * svn_pool__create_unmanaged(svn_boolean_t thread_safe) Modified: subversion/branches/addremove/subversion/libsvn_subr/prompt.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_subr/prompt.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_subr/prompt.c (original) +++ subversion/branches/addremove/subversion/libsvn_subr/prompt.c Sat May 23 14:16:56 2020 @@ -262,7 +262,7 @@ terminal_puts(const char *string, termin /* These codes can be returned from terminal_getc instead of a character. */ #define TERMINAL_NONE 0x80000 /* no character read, retry */ -#define TERMINAL_DEL (TERMINAL_NONE + 1) /* the input was a deleteion */ +#define TERMINAL_DEL (TERMINAL_NONE + 1) /* the input was a deletion */ #define TERMINAL_EOL (TERMINAL_NONE + 2) /* end of input/end of line */ #define TERMINAL_EOF (TERMINAL_NONE + 3) /* end of file during input */ Modified: subversion/branches/addremove/subversion/libsvn_subr/sorts.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_subr/sorts.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_subr/sorts.c (original) +++ subversion/branches/addremove/subversion/libsvn_subr/sorts.c Sat May 23 14:16:56 2020 @@ -34,6 +34,8 @@ #include "svn_error.h" #include "private/svn_sorts_private.h" +#include "svn_private_config.h" + /*** svn_sort__hash() ***/ @@ -299,15 +301,20 @@ svn_sort__array_lookup(const apr_array_h return compare_func(result, key) ? NULL : result; } -void -svn_sort__array_insert(apr_array_header_t *array, - const void *new_element, - int insert_index) +svn_error_t * +svn_sort__array_insert2(apr_array_header_t *array, + const void *new_element, + int insert_index) { int elements_to_move; char *new_position; - assert(0 <= insert_index && insert_index <= array->nelts); + if (insert_index < 0 || insert_index > array->nelts) + return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, + _("svn_sort__array_insert2: Attempted insert " + "at index %d in array length %d"), + insert_index, array->nelts); + elements_to_move = array->nelts - insert_index; /* before bumping nelts */ /* Grow the array, allocating a new space at the end. Note: this can @@ -322,31 +329,35 @@ svn_sort__array_insert(apr_array_header_ /* Copy in the new element */ memcpy(new_position, new_element, array->elt_size); + return SVN_NO_ERROR; } -void -svn_sort__array_delete(apr_array_header_t *arr, - int delete_index, - int elements_to_delete) -{ - /* Do we have a valid index and are there enough elements? */ - if (delete_index >= 0 - && delete_index < arr->nelts - && elements_to_delete > 0 - && (arr->nelts - delete_index) >= elements_to_delete) - { - /* If we are not deleting a block of elements that extends to the end - of the array, then we need to move the remaining elements to keep - the array contiguous. */ - if ((elements_to_delete + delete_index) < arr->nelts) - memmove( - arr->elts + arr->elt_size * delete_index, - arr->elts + (arr->elt_size * (delete_index + elements_to_delete)), - arr->elt_size * (arr->nelts - elements_to_delete - delete_index)); - - /* Delete the last ELEMENTS_TO_DELETE elements. */ - arr->nelts -= elements_to_delete; - } +svn_error_t * +svn_sort__array_delete2(apr_array_header_t *arr, + int delete_index, + int elements_to_delete) +{ + if (!(delete_index >= 0 + && delete_index < arr->nelts + && elements_to_delete > 0 + && (arr->nelts - delete_index) >= elements_to_delete)) + return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, + _("svn_sort__array_delete2: Attempted delete " + "at index %d, %d elements, in array length %d"), + delete_index, elements_to_delete, arr->nelts); + + /* If we are deleting a block of elements that does not extend to the end + of the array, then we need to move the remaining elements to keep + the array contiguous. */ + if ((elements_to_delete + delete_index) < arr->nelts) + memmove( + arr->elts + arr->elt_size * delete_index, + arr->elts + (arr->elt_size * (delete_index + elements_to_delete)), + arr->elt_size * (arr->nelts - elements_to_delete - delete_index)); + + /* Delete the last ELEMENTS_TO_DELETE elements. */ + arr->nelts -= elements_to_delete; + return SVN_NO_ERROR; } void Modified: subversion/branches/addremove/subversion/libsvn_subr/sqlite.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_subr/sqlite.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_subr/sqlite.c (original) +++ subversion/branches/addremove/subversion/libsvn_subr/sqlite.c Sat May 23 14:16:56 2020 @@ -65,8 +65,8 @@ extern int (*const svn_sqlite3__api_conf # include <sqlite3.h> #endif -#if !SQLITE_VERSION_AT_LEAST(3,7,12) -#error SQLite is too old -- version 3.7.12 is the minimum required version +#if !SQLITE_VERSION_AT_LEAST(3,8,2) +#error SQLite is too old -- version 3.8.2 is the minimum required version #endif #ifndef SQLITE_DETERMINISTIC Modified: subversion/branches/addremove/subversion/libsvn_subr/sqlite3wrapper.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_subr/sqlite3wrapper.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_subr/sqlite3wrapper.c (original) +++ subversion/branches/addremove/subversion/libsvn_subr/sqlite3wrapper.c Sat May 23 14:16:56 2020 @@ -25,6 +25,8 @@ /* Include sqlite3 inline, making all symbols private. */ #ifdef SVN_SQLITE_INLINE # define SQLITE_OMIT_DEPRECATED 1 +# define SQLITE_DEFAULT_MEMSTATUS 0 +# define SQLITE_OMIT_WAL 1 # define SQLITE_API static # if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2) # pragma GCC diagnostic ignored "-Wunreachable-code" @@ -41,6 +43,12 @@ # endif # endif # ifdef __APPLE__ + /* SQLite uses OSAtomicCompareAndSwapPtrBarrier from libkern/OSAtomic.h, + which has been deprecated since macOS 10.12. This will silence the + warning. */ +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2) +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +# endif # include <Availability.h> # if __MAC_OS_X_VERSION_MIN_REQUIRED < 1060 /* <libkern/OSAtomic.h> is included on OS X by sqlite3.c, and Modified: subversion/branches/addremove/subversion/libsvn_subr/ssl_client_cert_pw_providers.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_subr/ssl_client_cert_pw_providers.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_subr/ssl_client_cert_pw_providers.c (original) +++ subversion/branches/addremove/subversion/libsvn_subr/ssl_client_cert_pw_providers.c Sat May 23 14:16:56 2020 @@ -36,7 +36,7 @@ #include "svn_private_config.h" /*-----------------------------------------------------------------------*/ -/* File provider */ +/* File password provider */ /*-----------------------------------------------------------------------*/ /* Baton type for the ssl client cert passphrase provider. */ @@ -51,6 +51,13 @@ typedef struct ssl_client_cert_pw_file_p apr_hash_t *plaintext_answers; } ssl_client_cert_pw_file_provider_baton_t; +/* The client cert password provider only deals with a password and + realm (the client cert filename), there is no username. The gnome + keyring backend based on libsecret requires a non-NULL username so + we have to invent one. An empty string is acceptable and doesn't + change the value stored by the kwallet backend. */ +#define DUMMY_USERNAME "" + /* This implements the svn_auth__password_get_t interface. Set **PASSPHRASE to the plaintext passphrase retrieved from CREDS; ignore other parameters. */ @@ -132,7 +139,8 @@ svn_auth__ssl_client_cert_pw_cache_get(v svn_boolean_t done; SVN_ERR(passphrase_get(&done, &password, creds_hash, realmstring, - NULL, parameters, non_interactive, pool)); + DUMMY_USERNAME, parameters, non_interactive, + pool)); if (!done) password = NULL; } @@ -293,7 +301,7 @@ svn_auth__ssl_client_cert_pw_cache_set(s if (may_save_passphrase) { SVN_ERR(passphrase_set(saved, creds_hash, realmstring, - NULL, creds->password, parameters, + DUMMY_USERNAME, creds->password, parameters, non_interactive, pool)); if (*saved && passtype) Modified: subversion/branches/addremove/subversion/libsvn_subr/stream.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_subr/stream.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_subr/stream.c (original) +++ subversion/branches/addremove/subversion/libsvn_subr/stream.c Sat May 23 14:16:56 2020 @@ -922,7 +922,7 @@ readline_apr_lf(apr_file_t *file, } /* Otherwise, prepare to read the next chunk. */ - svn_stringbuf_ensure(buf, buf->blocksize + SVN__LINE_CHUNK_SIZE); + svn_stringbuf_ensure(buf, buf->len + SVN__LINE_CHUNK_SIZE); } } @@ -982,7 +982,7 @@ readline_apr_generic(apr_file_t *file, } /* Prepare to read the next chunk. */ - svn_stringbuf_ensure(buf, buf->blocksize + SVN__LINE_CHUNK_SIZE); + svn_stringbuf_ensure(buf, buf->len + SVN__LINE_CHUNK_SIZE); } } @@ -1468,10 +1468,10 @@ seek_handler_checksum(void *baton, const else { if (btn->read_ctx) - svn_checksum_ctx_reset(btn->read_ctx); + SVN_ERR(svn_checksum_ctx_reset(btn->read_ctx)); if (btn->write_ctx) - svn_checksum_ctx_reset(btn->write_ctx); + SVN_ERR(svn_checksum_ctx_reset(btn->write_ctx)); SVN_ERR(svn_stream_reset(btn->proxy)); } Modified: subversion/branches/addremove/subversion/libsvn_subr/string.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_subr/string.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_subr/string.c (original) +++ subversion/branches/addremove/subversion/libsvn_subr/string.c Sat May 23 14:16:56 2020 @@ -65,7 +65,7 @@ membuf_create(void **data, apr_size_t *s * this function does nothing. * * If *SIZE is 0, the allocated buffer size will be MINIMUM_SIZE - * rounded up to the nearest APR alignment boundary. Otherwse, *SIZE + * rounded up to the nearest APR alignment boundary. Otherwise, *SIZE * will be multiplied by a power of two such that the result is * greater or equal to MINIMUM_SIZE. The pointer to the new buffer * will be returned in *DATA, and its size in *SIZE. Modified: subversion/branches/addremove/subversion/libsvn_subr/sysinfo.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_subr/sysinfo.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_subr/sysinfo.c (original) +++ subversion/branches/addremove/subversion/libsvn_subr/sysinfo.c Sat May 23 14:16:56 2020 @@ -1,3 +1,4 @@ + /* * sysinfo.c : information about the running system * @@ -51,10 +52,22 @@ #include "sysinfo.h" #include "svn_private_config.h" +#if HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + #if HAVE_SYS_UTSNAME_H #include <sys/utsname.h> #endif +#if HAVE_UNISTD_H +#include <unistd.h> +#endif + +#if HAVE_ELF_H +#include <elf.h> +#endif + #ifdef SVN_HAVE_MACOS_PLIST #include <CoreFoundation/CoreFoundation.h> #include <AvailabilityMacros.h> @@ -92,6 +105,7 @@ static const apr_array_header_t *macos_s #if __linux__ static const char *linux_release_name(apr_pool_t *pool); +static const apr_array_header_t *linux_shared_libs(apr_pool_t *pool); #endif const char * @@ -127,7 +141,8 @@ const apr_array_header_t * svn_sysinfo__linked_libs(apr_pool_t *pool) { svn_version_ext_linked_lib_t *lib; - apr_array_header_t *array = apr_array_make(pool, 6, sizeof(*lib)); + apr_array_header_t *array = apr_array_make(pool, 7, sizeof(*lib)); + int lz4_version = svn_lz4__runtime_version(); lib = &APR_ARRAY_PUSH(array, svn_version_ext_linked_lib_t); lib->name = "APR"; @@ -167,6 +182,15 @@ svn_sysinfo__linked_libs(apr_pool_t *poo lib->compiled_version = apr_pstrdup(pool, svn_zlib__compiled_version()); lib->runtime_version = apr_pstrdup(pool, svn_zlib__runtime_version()); + lib = &APR_ARRAY_PUSH(array, svn_version_ext_linked_lib_t); + lib->name = "LZ4"; + lib->compiled_version = apr_pstrdup(pool, svn_lz4__compiled_version()); + + lib->runtime_version = apr_psprintf(pool, "%d.%d.%d", + lz4_version / 100 / 100, + (lz4_version / 100) % 100, + lz4_version % 100); + return array; } @@ -177,6 +201,8 @@ svn_sysinfo__loaded_libs(apr_pool_t *poo return win32_shared_libs(pool); #elif defined(SVN_HAVE_MACHO_ITERATE) return macos_shared_libs(pool); +#elif __linux__ + return linux_shared_libs(pool); #else return NULL; #endif @@ -290,6 +316,31 @@ release_name_from_uname(apr_pool_t *pool #if __linux__ +/* Find the first whitespace character in a stringbuf. + Analogous to svn_stringbuf_first_non_whitespace. */ +static apr_size_t +stringbuf_first_whitespace(const svn_stringbuf_t *str) +{ + apr_size_t i; + for (i = 0; i < str->len; ++i) + { + if (svn_ctype_isspace(str->data[i])) + return i; + } + return str->len; +} + +/* Skip a whitespace-delimited field in a stringbuf. */ +static void +stringbuf_skip_whitespace_field(svn_stringbuf_t *str) +{ + apr_size_t i; + i = stringbuf_first_whitespace(str); + svn_stringbuf_leftchop(str, i); + i = svn_stringbuf_first_non_whitespace(str); + svn_stringbuf_leftchop(str, i); +} + /* Split a stringbuf into a key/value pair. Return the key, leaving the stripped value in the stringbuf. */ static const char * @@ -625,6 +676,168 @@ linux_release_name(apr_pool_t *pool) return apr_psprintf(pool, "%s [%s]", release_name, uname_release); } + +#if HAVE_ELF_H +/* Parse a hexadecimal number as a pointer value. */ +static const unsigned char * +parse_pointer_value(const char *start, const char *limit, char **end) +{ + const unsigned char *ptr; + const apr_uint64_t val = (apr_uint64_t)apr_strtoi64(start, end, 16); + + if (errno /* overflow */ + || *end == start /* no valid digits */ + || *end >= limit) /* representation too long */ + return NULL; + + ptr = (const unsigned char*)val; + if (val != (apr_uint64_t)ptr) /* truncated value */ + return NULL; + + return ptr; +} + +/* Read the ELF header at the mapping position to check if this is a shared + library. We only look at the ELF identification and the type. The format is + described here: + http://www.skyfree.org/linux/references/ELF_Format.pdf +*/ +static svn_boolean_t +check_elf_header(const unsigned char *map_start, + const unsigned char *map_end) +{ + /* A union of all known ELF header types, for size checks. */ + union max_elf_header_size_t + { + Elf32_Ehdr header_32; + Elf64_Ehdr header_64; + }; + + /* Check the size of the mapping and the ELF magic tag. */ + if (map_end < map_start + || map_end - map_start < sizeof(union max_elf_header_size_t) + || memcmp(map_start, ELFMAG, SELFMAG)) + { + return FALSE; + } + + /* Check that this is an ELF shared library or executable file. This also + implicitly checks that the data encoding of the current process is the + same as in the loaded library. */ + if (map_start[EI_CLASS] == ELFCLASS32) + { + const Elf32_Ehdr *hdr = (void*)map_start; + return (hdr->e_type == ET_DYN || hdr->e_type == ET_EXEC); + } + else if (map_start[EI_CLASS] == ELFCLASS64) + { + const Elf64_Ehdr *hdr = (void*)map_start; + return (hdr->e_type == ET_DYN || hdr->e_type == ET_EXEC); + } + + return FALSE; +} +#endif /* HAVE_ELF_H */ + +static const apr_array_header_t * +linux_shared_libs(apr_pool_t *pool) +{ + /* Read the list of loaded modules from /proc/[pid]/maps + The format is described here: + http://man7.org/linux/man-pages/man5/proc.5.html + */ + + const char *maps = apr_psprintf(pool, "/proc/%ld/maps", (long)getpid()); + apr_array_header_t *result = NULL; + svn_boolean_t eof = FALSE; + svn_stream_t *stream; + svn_error_t *err; + + err = svn_stream_open_readonly(&stream, maps, pool, pool); + if (err) + { + svn_error_clear(err); + return NULL; + } + + /* Each line in /proc/[pid]/maps consists of whitespace-delimited fields. */ + while (!eof) + { + svn_stringbuf_t *line; + +#if HAVE_ELF_H + const unsigned char *map_start; + const unsigned char *map_end; +#endif + + err = svn_stream_readline(stream, &line, "\n", &eof, pool); + if (err) + { + svn_error_clear(err); + return NULL; + } + +#if HAVE_ELF_H + /* Address: The mapped memory address range. */ + { + const char *const limit = line->data + line->len; + char *end; + + /* The start of the address range */ + map_start = parse_pointer_value(line->data, limit, &end); + if (!map_start || *end != '-') + continue; + + /* The end of the address range */ + map_end = parse_pointer_value(end + 1, limit, &end); + if (!map_end || !svn_ctype_isspace(*end)) + continue; + } +#endif + + stringbuf_skip_whitespace_field(line); /* skip address */ + + /* Permissions: The memory region must be readable and executable. */ + if (line->len < 4 || line->data[0] != 'r' || line->data[2] != 'x') + continue; + + stringbuf_skip_whitespace_field(line); /* skip perms */ + stringbuf_skip_whitespace_field(line); /* skip offset */ + stringbuf_skip_whitespace_field(line); /* skip device */ + + /* I-Node: If it is 0, there is no file associated with the region. */ + if (line->len < 2 + || (line->data[0] == '0' && svn_ctype_isspace(line->data[1]))) + continue; + + stringbuf_skip_whitespace_field(line); /* skip inode */ + + /* Consider only things that look like absolute paths. + Files that were removed since the process was created (due to an + upgrade, for example) are marked as '(deleted)'. */ + if (line->data[0] == '/') + { + svn_version_ext_loaded_lib_t *lib; + +#if HAVE_ELF_H + if (!check_elf_header(map_start, map_end)) + continue; +#endif + + /* We've done our best to find a mapped shared library. */ + if (!result) + { + result = apr_array_make(pool, 32, sizeof(*lib)); + } + lib = &APR_ARRAY_PUSH(result, svn_version_ext_loaded_lib_t); + lib->name = line->data; + lib->version = NULL; + } + } + + svn_error_clear(svn_stream_close(stream)); + return result; +} #endif /* __linux__ */ @@ -864,7 +1077,7 @@ win32_release_name(apr_pool_t *pool) /* Get a list of handles of shared libs loaded by the current - process. Returns a NULL-terminated array alocated from POOL. */ + process. Returns a NULL-terminated array allocated from POOL. */ static HMODULE * enum_loaded_modules(apr_pool_t *pool) { @@ -1112,41 +1325,71 @@ value_from_dict(CFDictionaryRef plist, C return value; } -/* Return the commercial name of the OS, given the version number in +/* Return the minor version the operating system, given the number in a format that matches the regular expression /^10\.\d+(\..*)?$/ */ -static const char * -release_name_from_version(const char *osver) +static int +macos_minor_version(const char *osver) { char *end = NULL; unsigned long num = strtoul(osver, &end, 10); if (!end || *end != '.' || num != 10) - return NULL; + return -1; osver = end + 1; end = NULL; num = strtoul(osver, &end, 10); if (!end || (*end && *end != '.')) - return NULL; + return -1; + + return (int)num; +} + +/* Return the product name of the operating system. */ +static const char * +product_name_from_minor_version(int minor, const char* product_name) +{ + /* We can only do this if we know the official product name. */ + if (0 != strcmp(product_name, "Mac OS X")) + return product_name; + + if (minor <= 7) + return product_name; + + if (minor <= 11) + return "OS X"; - /* See http://en.wikipedia.org/wiki/History_of_OS_X#Release_timeline */ - switch(num) + return "macOS"; +} + +/* Return the commercial name of the operating system. */ +static const char * +release_name_from_minor_version(int minor, const char* product_name) +{ + /* We can only do this if we know the official product name. */ + if (0 == strcmp(product_name, "Mac OS X")) { - case 0: return "Cheetah"; - case 1: return "Puma"; - case 2: return "Jaguar"; - case 3: return "Panther"; - case 4: return "Tiger"; - case 5: return "Leopard"; - case 6: return "Snow Leopard"; - case 7: return "Lion"; - case 8: return "Mountain Lion"; - case 9: return "Mavericks"; - case 10: return "Yosemite"; - case 11: return "El Capitan"; - case 12: return "Sierra"; + /* See https://en.wikipedia.org/wiki/MacOS_version_history#Releases */ + switch(minor) + { + case 0: return "Cheetah"; + case 1: return "Puma"; + case 2: return "Jaguar"; + case 3: return "Panther"; + case 4: return "Tiger"; + case 5: return "Leopard"; + case 6: return "Snow Leopard"; + case 7: return "Lion"; + case 8: return "Mountain Lion"; + case 9: return "Mavericks"; + case 10: return "Yosemite"; + case 11: return "El Capitan"; + case 12: return "Sierra"; + case 13: return "High Sierra"; + case 14: return "Mojave"; + case 15: return "Catalina"; + } } - return NULL; } @@ -1169,20 +1412,23 @@ macos_release_name(apr_pool_t *pool) CFSTR("ProductBuildVersion"), pool); const char *release; + int minor_version; if (!osver) osver = value_from_dict(plist, CFSTR("ProductVersion"), pool); - release = release_name_from_version(osver); + minor_version = macos_minor_version(osver); + release = release_name_from_minor_version(minor_version, osname); + osname = product_name_from_minor_version(minor_version, osname); CFRelease(plist); return apr_psprintf(pool, "%s%s%s%s%s%s%s%s", (osname ? osname : ""), - (osver ? (osname ? " " : "") : ""), - (osver ? osver : ""), - (release ? (osname||osver ? " " : "") : ""), + (release ? (osname ? " " : "") : ""), (release ? release : ""), + (osver ? (osname||release ? " " : "") : ""), + (osver ? osver : ""), (build - ? (osname||osver||release ? ", " : "") + ? (osname||release||osver ? ", " : "") : ""), (build ? (server ? "server build " : "build ") Modified: subversion/branches/addremove/subversion/libsvn_subr/temp_serializer.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_subr/temp_serializer.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_subr/temp_serializer.c (original) +++ subversion/branches/addremove/subversion/libsvn_subr/temp_serializer.c Sat May 23 14:16:56 2020 @@ -143,7 +143,7 @@ svn_temp_serializer__init(const void *so * been serialized to BUFFER but contains references to new objects yet to * serialize. The current size of the serialized data is given in * CURRENTLY_USED. If the allocated data buffer is actually larger, you may - * specifiy that in CURRENTLY_ALLOCATED to prevent unnecessary allocations. + * specify that in CURRENTLY_ALLOCATED to prevent unnecessary allocations. * Otherwise, set it to 0. All allocations will be made from POOl. */ svn_temp_serializer__context_t * @@ -261,7 +261,7 @@ svn_temp_serializer__push(svn_temp_seria svn_stringbuf_appendbytes(context->buffer, source, struct_size); } -/* Remove the lastest structure from the stack. +/* Remove the latest structure from the stack. */ void svn_temp_serializer__pop(svn_temp_serializer__context_t *context) Modified: subversion/branches/addremove/subversion/libsvn_subr/utf.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_subr/utf.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_subr/utf.c (original) +++ subversion/branches/addremove/subversion/libsvn_subr/utf.c Sat May 23 14:16:56 2020 @@ -72,7 +72,7 @@ typedef apr_xlate_t xlate_handle_t; * If there is no handle for a particular key when needed, a new is * handle is created and put in the cache after use. * This means that there will be at most N handles open for a key, where N - * is the number of simultanous handles in use for that key. */ + * is the number of simultaneous handles in use for that key. */ typedef struct xlate_handle_node_t { xlate_handle_t *handle; @@ -960,7 +960,7 @@ svn_utf__cstring_from_utf8_fuzzy(const c /* ### Check the client locale, maybe we can avoid that second * conversion! See Ulrich Drepper's patch at - * http://subversion.tigris.org/issues/show_bug.cgi?id=807. + * https://issues.apache.org/jira/browse/SVN-807. */ } Propchange: subversion/branches/addremove/subversion/libsvn_subr/utf8proc/ ------------------------------------------------------------------------------ Reverse-merged /subversion/branches/wc-collate-path/subversion/libsvn_subr/utf8proc:r1405766-1480384 Merged /subversion/branches/swig-py3/subversion/libsvn_subr/utf8proc:r1813660-1869353 Merged /subversion/trunk/subversion/libsvn_subr/utf8proc:r1813173-1878056 Merged /subversion/branches/shelve/subversion/libsvn_subr/utf8proc:r1802592-1815226 Merged /subversion/branches/shelve-checkpoint/subversion/libsvn_subr/utf8proc:r1801593-1801923,1801970