Subversion mergeinfo command bug

iceyuan1991 <[email protected]>
Newsgroups gmane.comp.version-control.subversion.user
Message-ID <[email protected]>
Hello,

Recently, we encountered a bug while using mergeinfo in SVN. Here is an example:

Our source branch has the following branch changes (through copy or rename) history:

- Branch 1: /products/xy1/develop/mos2/trunk, revision a-b

- Branch 2: /products/xy1/develop/mos2/server, revision b-c

- Branch 3: /products/xy1/develop/mos2/server/branches/zlp_20240306, revision c-d

From the current code, in the svn_client__mergeinfo_log function, when constructing merge_source_fspaths, all the changed branches are added to merge_source_fspaths:

```

for (hi = apr_hash_first(scratch_pool, source_history);

hi;
hi = apr_hash_next(hi))
{
const char *key = apr_hash_this_key(hi);
svn_rangelist_t *subtree_merged_rangelist = apr_hash_this_val(hi);
svn_rangelist_t *intersecting_rangelist;

svn_pool_clear(iterpool);
SVN_ERR(svn_rangelist_intersect(&intersecting_rangelist,
youngest_rangelist,
subtree_merged_rangelist,
FALSE, iterpool));

APR_ARRAY_PUSH(merge_source_fspaths, const char *) = key;

if (intersecting_rangelist->nelts)
log_target = key;
}

```

In filter_log_entry_with_rangelist function, when searching for the changed_path for each revision, there is some code based on merge_source_fspaths to match the common prefix and calculate the relative path as follows:

```

for (i = 0; i merge_source_fspaths->nelts; i++)
{
merge_source_fspath = APR_ARRAY_IDX(fleb->merge_source_fspaths,
i, const char *);

merge_source_rel_target
= svn_fspath__skip_ancestor(merge_source_fspath, path);
…

```

When a revision has a changed_path such as /products/xy1/develop/mos2/server/branches/zlp_20240306/engine/src/gameplay/mosprop/src/prop_desc.cpp, its corresponding merge_source is /products/xy1/develop/mos2/server/branches/zlp_20240306. However, due to the fact that the for-loop does not guarantee order, if merge_source_fspath first matches /products/xy1/develop/mos2/server, it will still proceed with the subsequent processing because of the common prefix, eventually obtaining an incorrect relative path merge_source_rel_target, leading to an incorrect judgment in the subsequent steps.

One modification approach is, since when calling logs_for_mergeinfo_rangelist in the svn_client__mergeinfo_log function, the revision range of master_inheritable_rangelist is used:
```

--- a/ext/Subversion/subversion/libsvn_client/mergeinfo.c
+++ b/ext/Subversion/subversion/libsvn_client/mergeinfo.c
@@ -2139,6 +2139,7 @@ svn_client__mergeinfo_log(svn_boolean_t finding_merged,
const char *key = apr_hash_this_key(hi);
svn_rangelist_t *subtree_merged_rangelist = apr_hash_this_val(hi);
svn_rangelist_t *intersecting_rangelist;
+ svn_rangelist_t *intersecting_rangelist_merge_source_filter;

svn_pool_clear(iterpool);
SVN_ERR(svn_rangelist_intersect(&intersecting_rangelist,
@@ -2146,7 +2147,13 @@ svn_client__mergeinfo_log(svn_boolean_t finding_merged,
subtree_merged_rangelist,
FALSE, iterpool));

- APR_ARRAY_PUSH(merge_source_fspaths, const char *) = key;
+ SVN_ERR(svn_rangelist_intersect(&intersecting_rangelist_merge_source_filter,
+ master_inheritable_rangelist,
+ subtree_merged_rangelist,
+ FALSE, iterpool));
+
+ if (intersecting_rangelist_merge_source_filter->nelts)
+ APR_ARRAY_PUSH(merge_source_fspaths, const char *) = key;

if (intersecting_rangelist->nelts)
log_target = key;

```

Yuanzhongliang

[email protected]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.