File fix-missing-log-item-closure.patch of Package subversion
Index: subversion-1.14.x/subversion/libsvn_ra_serf/log.c
===================================================================
--- subversion-1.14.x/subversion/libsvn_ra_serf/log.c (revision 1921329)
+++ subversion-1.14.x/subversion/libsvn_ra_serf/log.c (working copy)
@@ -299,6 +299,7 @@
"subtractive-merge",
FALSE);
+ SVN_ERR_ASSERT(attrs != NULL);
rev_str = svn_hash_gets(attrs, "revision");
if (rev_str)
{
Index: subversion-1.14.x/subversion/libsvn_repos/log.c
===================================================================
--- subversion-1.14.x/subversion/libsvn_repos/log.c (revision 1921329)
+++ subversion-1.14.x/subversion/libsvn_repos/log.c (working copy)
@@ -1216,9 +1216,19 @@
/* Set to TRUE if we found it. */
svn_boolean_t found_rev_of_interest;
+ /* Set to TRUE if we called PATH_CHANGE_RECEIVER via INNER. */
+ svn_boolean_t inner_got_used;
+
+ /* Set to TRUE if we need the simple mode of interesting_merge() */
+ svn_boolean_t simple_mode;
+
+ svn_boolean_t handling_merged_revision;
+ svn_bit_array__t *nested_merges;
+
/* We need to invoke this user-provided callback if not NULL. */
svn_repos_path_change_receiver_t inner;
void *inner_baton;
+
} interesting_merge_baton_t;
/* Implements svn_repos_path_change_receiver_t.
@@ -1235,12 +1245,9 @@
interesting_merge_baton_t *b = baton;
apr_hash_index_t *hi;
- if (b->inner)
- SVN_ERR(b->inner(b->inner_baton, change, scratch_pool));
+ if (!(b->found_rev_of_interest || b->simple_mode))
+ {
- if (b->found_rev_of_interest)
- return SVN_NO_ERROR;
-
/* Look at each path on the log target's mergeinfo. */
for (hi = apr_hash_first(scratch_pool, b->log_target_history_as_mergeinfo);
hi;
@@ -1264,7 +1271,14 @@
}
}
}
+ }
+ if (b->inner && !(b->nested_merges && b->handling_merged_revision && svn_bit_array__get(b->nested_merges, b->rev)))
+ {
+ SVN_ERR(b->inner(b->inner_baton, change, scratch_pool));
+ b->inner_got_used = TRUE;
+ }
+
b->found_rev_of_interest = TRUE;
return SVN_NO_ERROR;
@@ -1310,9 +1324,19 @@
{
svn_repos_log_entry_t log_entry = { 0 };
log_callbacks_t my_callbacks = *callbacks;
+ apr_pool_t *scratch_pool;
interesting_merge_baton_t baton;
+ baton.inner_got_used = FALSE;
+ baton.inner = callbacks->path_change_receiver;
+ baton.inner_baton = callbacks->path_change_receiver_baton;
+ baton.handling_merged_revision = handling_merged_revision;
+ baton.nested_merges = nested_merges;
+ my_callbacks.path_change_receiver = interesting_merge;
+ my_callbacks.path_change_receiver_baton = &baton;
+ callbacks = &my_callbacks;
+
/* Is REV a merged revision that is already part of
LOG_TARGET_HISTORY_AS_MERGEINFO? If so then there is no
need to send it, since it already was (or will be) sent.
@@ -1323,18 +1347,14 @@
&& apr_hash_count(log_target_history_as_mergeinfo))
{
baton.found_rev_of_interest = FALSE;
+ baton.simple_mode = FALSE;
baton.rev = rev;
baton.log_target_history_as_mergeinfo = log_target_history_as_mergeinfo;
- baton.inner = callbacks->path_change_receiver;
- baton.inner_baton = callbacks->path_change_receiver_baton;
-
- my_callbacks.path_change_receiver = interesting_merge;
- my_callbacks.path_change_receiver_baton = &baton;
- callbacks = &my_callbacks;
}
else
{
baton.found_rev_of_interest = TRUE;
+ baton.simple_mode = TRUE;
}
SVN_ERR(fill_log_entry(&log_entry, rev, fs, revprops, callbacks, pool));
@@ -1345,15 +1365,15 @@
revision. */
if (baton.found_rev_of_interest)
{
- apr_pool_t *scratch_pool;
-
/* Is REV a merged revision we've already sent? */
if (nested_merges && handling_merged_revision)
{
if (svn_bit_array__get(nested_merges, rev))
{
- /* We already sent REV. */
- return SVN_NO_ERROR;
+ if (!baton.inner_got_used)
+ /* We already sent REV and no log was streamed yet. */
+ return SVN_NO_ERROR;
+ log_entry.revision = SVN_INVALID_REVNUM;
}
else
{
@@ -1371,7 +1391,20 @@
&log_entry, scratch_pool));
svn_pool_destroy(scratch_pool);
}
+ else if (baton.inner_got_used)
+ {
+ svn_repos_log_entry_t empty_log_entry = { 0 };
+ /* Send the empty revision. */
+ empty_log_entry.revision = SVN_INVALID_REVNUM;
+ /* Pass a scratch pool to ensure no temporary state stored
+ by the receiver callback persists. */
+ scratch_pool = svn_pool_create(pool);
+ SVN_ERR(callbacks->revision_receiver(callbacks->revision_receiver_baton,
+ &empty_log_entry, scratch_pool));
+ svn_pool_destroy(scratch_pool);
+ }
+
return SVN_NO_ERROR;
}
@@ -1719,8 +1752,8 @@
int limit,
svn_boolean_t strict_node_history,
svn_boolean_t include_merged_revisions,
+ svn_boolean_t subtractive_merge,
svn_boolean_t handling_merged_revisions,
- svn_boolean_t subtractive_merge,
svn_boolean_t ignore_missing_locations,
const apr_array_header_t *revprops,
svn_boolean_t descending_order,