I narrowed it down to the code in subversion/libsvn_subr/mergeinfo.c line 892-898 in adjust_remaining_ranges. At that point next_range actually starts before modified_range, so my guess is svn_sort__array_insert has some unexpected behaviour.
x892 svn_merge_range_t *new_modified_range = x
x893 apr_palloc(result_pool, sizeof(*new_modified_range)); x
x894 new_modified_range->start = next_range->end; x
x895 new_modified_range->end = modified_range->end; x
x896 new_modified_range->inheritable = FALSE; x
x897 modified_range->end = next_range->start; x
x898 (*range_index)+=2; x
x899 svn_sort__array_insert(rangelist, &new_modified_range, x
*range_index); x
x901 /* Recurse with the new range. */ x
x902 adjust_remaining_ranges(rangelist, range_index, result_pool); x
Intuitively it seems to be awfully complicated to expand a range to the end of a change, and then cut it down recursively with adjust_remaining_ranges. My first thought would be to step through "rangelist" and "changes" side by side in svn_rangelist_merge2, and to modify, insert or skip a range in either list until you're at the end. Though obviously I have no idea about all the edge cases the current code most likely fixes...
So how should I proceed from here? Should I open a bug with my findings and the test case?
-----Original Message-----
From: Jens Restemeier [mailto:***@playtonicgames.com]
Sent: 02 July 2017 23:44
To: Johan Corveleyn <***@gmail.com>
Cc: Stefan Sperling <***@elego.de>; ***@subversion.apache.org
Subject: Re: "Unable to parse reversed revision range" when merging from trunk to branch
The problem seems to come from svn_rangelist_merge2.
This test program recreates the problem.
#include <svn_pools.h>
#include <svn_mergeinfo.h>
int main(int argc, char * argv[])
{
apr_pool_t *pool;
int exit_code = EXIT_SUCCESS;
svn_error_t *err;
if (svn_cmdline_init("svn", stderr) != EXIT_SUCCESS)
return EXIT_FAILURE;
pool = apr_allocator_owner_get(svn_pool_create_allocator(FALSE));
// 15014-19472,19473-19612*,19613-19614,19615-19630*,19631-19634,19635-20055*
svn_rangelist_t * rangelist = apr_array_make(pool, 1, sizeof(svn_merge_range_t *));
svn_merge_range_t *mrange = apr_pcalloc(pool, sizeof(*mrange));
mrange->start = 15013;
mrange->end = 19472;
mrange->inheritable = TRUE;
APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = mrange;
mrange = apr_pcalloc(pool, sizeof(*mrange));
mrange->start = 19472;
mrange->end = 19612;
mrange->inheritable = FALSE;
APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = mrange;
mrange = apr_pcalloc(pool, sizeof(*mrange));
mrange->start = 19612;
mrange->end = 19614;
mrange->inheritable = TRUE;
APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = mrange;
mrange = apr_pcalloc(pool, sizeof(*mrange));
mrange->start = 19614;
mrange->end = 19630;
mrange->inheritable = FALSE;
APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = mrange;
mrange = apr_pcalloc(pool, sizeof(*mrange));
mrange->start = 19630;
mrange->end = 19634;
mrange->inheritable = TRUE;
APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = mrange;
mrange = apr_pcalloc(pool, sizeof(*mrange));
mrange->start = 19634;
mrange->end = 20055;
mrange->inheritable = FALSE;
APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = mrange;
// 15014-20515*
svn_rangelist_t * changes = apr_array_make(pool, 1, sizeof(svn_merge_range_t *));
mrange = apr_pcalloc(pool, sizeof(*mrange));
mrange->start = 15013;
mrange->end = 20515;
mrange->inheritable = FALSE;
APR_ARRAY_PUSH(changes, svn_merge_range_t *) = mrange;
{
svn_string_t * tmpString;
svn_rangelist_to_string(&tmpString, rangelist, pool);
printf("rangelist %s\n", tmpString->data);
}
{
svn_string_t * tmpString;
svn_rangelist_to_string(&tmpString, changes, pool);
printf("changes %s\n", tmpString->data);
}
svn_rangelist_merge2(rangelist, changes, pool, pool);
{
svn_string_t * tmpString;
svn_rangelist_to_string(&tmpString, rangelist, pool);
printf("result %s\n", tmpString->data);
}
// wrong result
// result 15014-19472,19473-19612*,19613-19614,19615-19630*,19634-19631*,19631-19634,19635-20515*
svn_pool_destroy(pool);
return exit_code;
}
So while this correctly expands the last range from 20055 to 20515 it inserts a wrong inverse range. It’s a bit late, I’ll have a look tomorrow unless someone beats me to it. ;)
On Fri, Jun 30, 2017 at 6:10 PM, Jens Christian Restemeier
Post by Jens Christian RestemeierI narrowed it down to somewhere in update_wc_mergeinfo. At the start
/trunk:15014-19472,19473-19612*,19613-19614,19615-19630*,19631-19634,
19635-2
0055*
A bit later where this gets parsed again from
/trunk:15014-19472,19473-19612*,19613-19614,19615-19630*,19634-19631*
,19631-
19634,19635-20511*
So somewhere in the mergeinfo update this gets added.
Debugging this in gdb is not fun, though...
Maybe it comes from a parent or child of your root directory (either
in the working copy, or even part of the repository but outside of the
scope of your working copy). Mergeinfo has some inheritance semantics,
so it doesn't have to be directly defined on your root directory to be
applicable.
--
Johan