pbu...@apache.org wrote:
> Fix issue #2915 'Handle mergeinfo for subtrees missing due to removal by
> non-svn command'.
> 
> With this change, if you attempt a merge-tracking aware merge to a WC
> which is missing subtrees due to an OS-level deletion, then an error is
> raised before any editor drives begin.  The error message describes the
> root of each missing path.

+1 to this solution.

Review comments below.

> * subversion/libsvn_client/merge.c
> 
>  (get_mergeinfo_walk_baton): Add some new members for tracking sub-
>   directories' dirents.
> 
>  (record_missing_subtree_roots): New function.
> 
>  (get_mergeinfo_walk_cb): Use new function to flag missing subtree
>   roots.
> 
>  (get_mergeinfo_paths): Raise a SVN_ERR_CLIENT_NOT_READY_TO_MERGE error if
>   any unexpectedly missing subtrees are found.
> 
> * subversion/tests/cmdline/merge_authz_tests.py
> 
>   (skipped paths get overriding mergeinfo): Don't test the file missing via
>    OS-delete scenario, this is now covered in a much clearer manner in the
>    new merge_tests.py.merge_with_os_deleted_subtrees test.  Also remove not
>    about testing a missing directory, that is also covered in the new test.
> 
> * subversion/tests/cmdline/merge_tests.py
> 
>  (merge_into_missing): Use --ignore-ancestry during this test's merge to
>   disregard mergeinfo and preserve the original intent of the test.
>  
>  (skipped_files_get_correct_mergeinfo): Use a shallow WC to rather than an
>   OS-level delete to test issue #3440.  Remove the second part of this test
>   which has no relevance now that merge tracking doesn't tolerate subtrees
>   missing via OS-deletion.
> 
>  (merge_with_os_deleted_subtrees): New test.
> 
>  (test_list): Add merge_with_os_deleted_subtrees.
> 
> * subversion/tests/cmdline/merge_tree_conflict_tests.py
> 
>   (tree_conflicts_merge_edit_onto_missing,
>    tree_conflicts_merge_del_onto_missing): Use --ignore-ancestry during these
>    tests' merges to disregard mergeinfo and preserve the original intent of
>    the test.  Don't bother with the post-merge commit either, since there is
>    nothing to commit as there are no mergeinfo changes.
> 
> * subversion/tests/cmdline/svntest/actions.py
> 
>   (deep_trees_run_tests_scheme_for_merge): Add new args allowing caller to
>    use --ignore-ancestry during the merge and to skip the post merge commit
>    if desired.

[...]

> @@ -5718,6 +5849,37 @@ get_mergeinfo_paths(apr_array_header_t *
>                                       merge_cmd_baton->ctx->cancel_baton,
>                                       scratch_pool));
>  
> +  if (apr_hash_count(wb.missing_subtrees))
> +    {
> +      apr_hash_index_t *hi;
> +      apr_pool_t *iterpool = svn_pool_create(scratch_pool);
> +      const char *missing_subtree_err_str = NULL;
> +      
> +      for (hi = apr_hash_first(iterpool, wb.missing_subtrees);

Iterpool isn't being used effectively here.  Normally, we would allocate
the iterator in the outer pool ("hi =
apr_hash_first(scratch_pool, ...)"), and use 'iterpool' for any
temporary allocations within the loop and clear it each time round.  In
this loop there aren't any, so it's redundant.

> +           hi;
> +           hi = apr_hash_next(hi))
> +        {
> +          const char *missing_abspath = svn__apr_hash_index_key(hi);
> +
> +          missing_subtree_err_str = apr_psprintf(
> +            scratch_pool, "%s%s\n",
> +            missing_subtree_err_str ? missing_subtree_err_str : "",
> +            svn_dirent_local_style(missing_abspath, scratch_pool));

In most realistic cases this way of constructing the string is fine, but
it looks like it's quadratic in time and memory space which might become
a problem when a merge is attempted into a pathological tree with
several thousand individual missing subtree roots.

Off the top of my head I would look at accumulating the string in an
svn_stringbuf, which will expand and occasionally re-alloc as you append
to it rather than re-allocating every time, and which remembers its
length so appending is quick.

> +        }
> +
> +      if (missing_subtree_err_str)

Minor point: Either this "if" or the "if (apr_hash_count ...)" is
redundant.

> +        return svn_error_createf(SVN_ERR_CLIENT_NOT_READY_TO_MERGE,
> +                                 NULL,
> +                                 _("Merge tracking not allowed with missing "
> +                                   "subtrees; try restoring these items "
> +                                   "first:\n%s"),
> +                                 missing_subtree_err_str);
> +  }
> +
> +  /* This pool is only needed across all the callbacks to detect
> +     missing subtrees. */
> +  svn_pool_destroy(wb.cb_pool);
> +

[...]

- Julian


Reply via email to