You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2022/01/14 14:01:51 UTC
svn commit: r1897034 [17/37] - in /subversion/branches/multi-wc-format: ./ build/ build/ac-macros/ build/generator/ build/generator/swig/ build/generator/templates/ contrib/client-side/ contrib/client-side/svn_load_dirs/ contrib/hook-scripts/ contrib/s...
Modified: subversion/branches/multi-wc-format/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_client/merge.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_client/merge.c Fri Jan 14 14:01:45 2022
@@ -51,6 +51,7 @@
#include "svn_sorts.h"
#include "svn_subst.h"
#include "svn_ra.h"
+#include "svn_version.h"
#include "client.h"
#include "mergeinfo.h"
@@ -264,7 +265,7 @@ typedef struct merge_cmd_baton_t {
/* Reference to the one-and-only CHILDREN_WITH_MERGEINFO (see global
comment) or a similar list for single-file-merges */
- const apr_array_header_t *children_with_mergeinfo;
+ apr_array_header_t *children_with_mergeinfo;
svn_client_ctx_t *ctx; /* Client context for callbacks, etc. */
@@ -422,6 +423,37 @@ merge_source_dup(const merge_source_t *s
return s;
}
+/* Decide whether ambiguous foreign merge should be a warning or an error */
+#define WITH_AMBIGUOUS_FOREIGN_MERGE_WARNING \
+ (SVN_VER_MAJOR == 1 && SVN_VER_MINOR < 16)
+
+#if WITH_AMBIGUOUS_FOREIGN_MERGE_WARNING
+/* Notify a warning, given in WARNING, if WARNING is non-null.
+ *
+ * We plan to replace this with a hard error in Subversion 1.16.
+ * This clears the error object WARNING before returning.
+ */
+static void
+notify_pre_1_16_warning(svn_error_t *warning,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
+{
+ if (!warning)
+ return;
+
+ if (ctx->notify_func2)
+ {
+ svn_wc_notify_t *n
+ = svn_wc_create_notify("" /*path*/, svn_wc_notify_warning, pool);
+
+ n->err = svn_error_quick_wrap(warning,
+ _("In Subversion 1.16 this warning will become a fatal error"));
+ ctx->notify_func2(ctx->notify_baton2, n, pool);
+ }
+ svn_error_clear(warning);
+}
+#endif
+
/* Return SVN_ERR_UNSUPPORTED_FEATURE if URL is not inside the repository
of LOCAL_ABSPATH. Use SCRATCH_POOL for temporary allocations. */
static svn_error_t *
@@ -440,38 +472,70 @@ check_repos_match(const merge_target_t *
return SVN_NO_ERROR;
}
-/* Return TRUE iff the repository of LOCATION1 is the same as
- * that of LOCATION2. If STRICT_URLS is true, the URLs must
- * match (and the UUIDs, just to be sure), otherwise just the UUIDs must
- * match and the URLs can differ (a common case is http versus https). */
-static svn_boolean_t
-is_same_repos(const svn_client__pathrev_t *location1,
+/* Decide whether LOCATION1 and LOCATION2 point to the same repository
+ * (with the same root URL) or to two different repositories.
+ * - same repository root URL -> set *SAME_REPOS true
+ * - different repositories -> set *SAME_REPOS false
+ * - different URLs but same UUID -> return an error
+ *
+ * The last case is unsupported for practical and historical reasons
+ * (see issue #4874) even though different URLs pointing to the same or
+ * equivalent repositories could be supported in principle.
+ */
+static svn_error_t *
+is_same_repos(svn_boolean_t *same_repos,
+ const svn_client__pathrev_t *location1,
+ const char *path1,
const svn_client__pathrev_t *location2,
- svn_boolean_t strict_urls)
+ const char *path2,
+ const char *message)
{
- if (strict_urls)
- return (strcmp(location1->repos_root_url, location2->repos_root_url) == 0
- && strcmp(location1->repos_uuid, location2->repos_uuid) == 0);
+ if (strcmp(location1->repos_root_url, location2->repos_root_url) == 0)
+ *same_repos = TRUE;
+ else if (strcmp(location1->repos_uuid, location2->repos_uuid) != 0)
+ *same_repos = FALSE;
else
- return (strcmp(location1->repos_uuid, location2->repos_uuid) == 0);
+ {
+ svn_error_t *err
+ = svn_error_create(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL, message);
+
+ return svn_error_quick_wrapf(err,
+ _("The locations '%s' and '%s' point to repositories with the "
+ "same repository UUID using different repository root URLs "
+ "('%s' and '%s')"),
+ path1, path2,
+ location1->repos_root_url, location2->repos_root_url);
+ }
+ return SVN_NO_ERROR;
}
-/* If the repository identified of LOCATION1 is not the same as that
- * of LOCATION2, throw a SVN_ERR_CLIENT_UNRELATED_RESOURCES
- * error mentioning PATH1 and PATH2. For STRICT_URLS, see is_same_repos().
+/* Check that LOCATION1 and LOCATION2 point to the same repository, with
+ * the same root URL. If not, throw a SVN_ERR_CLIENT_UNRELATED_RESOURCES
+ * error mentioning PATH_OR_URL1 and PATH_OR_URL2.
*/
static svn_error_t *
check_same_repos(const svn_client__pathrev_t *location1,
- const char *path1,
+ const char *path_or_url1,
const svn_client__pathrev_t *location2,
- const char *path2,
- svn_boolean_t strict_urls,
- apr_pool_t *scratch_pool)
+ const char *path_or_url2,
+ const char *message)
{
- if (! is_same_repos(location1, location2, strict_urls))
- return svn_error_createf(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
- _("'%s' must be from the same repository as "
- "'%s'"), path1, path2);
+ svn_boolean_t same_repos;
+
+ SVN_ERR(is_same_repos(&same_repos,
+ location1, path_or_url1, location2, path_or_url2,
+ message));
+ if (! same_repos)
+ {
+ svn_error_t *err
+ = svn_error_create(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL, message);
+
+ return svn_error_quick_wrapf(err,
+ _("The locations '%s' and '%s' point to different repositories "
+ "(root URLs '%s' and '%s', and differing UUIDs)"),
+ path_or_url1, path_or_url2,
+ location1->repos_root_url, location2->repos_root_url);
+ }
return SVN_NO_ERROR;
}
@@ -1545,6 +1609,25 @@ record_update_delete(merge_cmd_baton_t *
svn_node_kind_to_word(kind));
}
+ /* Note in children_with_mergeinfo that all paths in this subtree are
+ * being deleted, to avoid trying to set mergeinfo on them later. */
+ if (merge_b->children_with_mergeinfo)
+ {
+ int i;
+
+ for (i = 0; i < merge_b->children_with_mergeinfo->nelts; i++)
+ {
+ svn_client__merge_path_t *child
+ = APR_ARRAY_IDX(merge_b->children_with_mergeinfo, i,
+ svn_client__merge_path_t *);
+
+ if (svn_dirent_is_ancestor(local_abspath, child->abspath))
+ {
+ SVN_ERR(svn_sort__array_delete2(merge_b->children_with_mergeinfo, i--, 1));
+ }
+ }
+ }
+
return SVN_NO_ERROR;
}
@@ -3387,7 +3470,7 @@ merge_dir_closed(const char *relpath,
We register a skipped path, which will make parent mergeinfo non-
inheritable. This ensures that a future merge might see these skipped
- changes as eligable for merging.
+ changes as eligible for merging.
For legacy reasons we also notify the path as skipped.
*/
@@ -5595,9 +5678,9 @@ svn_client__make_merge_conflict_error(sv
with paths (svn_client__merge_path_t *) arranged in depth first order,
which have mergeinfo set on them or meet one of the other criteria
defined in get_mergeinfo_paths(). Remove any paths absent from disk
- or scheduled for deletion from CHILDREN_WITH_MERGEINFO which are equal to
+ from CHILDREN_WITH_MERGEINFO which are equal to
or are descendants of TARGET_WCPATH by setting those children to NULL. */
-static void
+static svn_error_t *
remove_absent_children(const char *target_wcpath,
apr_array_header_t *children_with_mergeinfo)
{
@@ -5609,12 +5692,13 @@ remove_absent_children(const char *targe
{
svn_client__merge_path_t *child =
APR_ARRAY_IDX(children_with_mergeinfo, i, svn_client__merge_path_t *);
- if ((child->absent || child->scheduled_for_deletion)
+ if (child->absent
&& svn_dirent_is_ancestor(target_wcpath, child->abspath))
{
- svn_sort__array_delete(children_with_mergeinfo, i--, 1);
+ SVN_ERR(svn_sort__array_delete2(children_with_mergeinfo, i--, 1));
}
}
+ return SVN_NO_ERROR;
}
/* Helper for do_directory_merge() to handle the case where a merge editor
@@ -5629,14 +5713,14 @@ remove_absent_children(const char *targe
MERGE_B->target->abspath, this must always be present in
CHILDREN_WITH_MERGEINFO so this is never removed by this
function. */
-static void
+static svn_error_t *
remove_children_with_deleted_mergeinfo(merge_cmd_baton_t *merge_b,
apr_array_header_t *children_with_mergeinfo)
{
int i;
if (!merge_b->paths_with_deleted_mergeinfo)
- return;
+ return SVN_NO_ERROR;
/* CHILDREN_WITH_MERGEINFO[0] is the always the merge target
so start at the first child. */
@@ -5647,9 +5731,10 @@ remove_children_with_deleted_mergeinfo(m
if (svn_hash_gets(merge_b->paths_with_deleted_mergeinfo, child->abspath))
{
- svn_sort__array_delete(children_with_mergeinfo, i--, 1);
+ SVN_ERR(svn_sort__array_delete2(children_with_mergeinfo, i--, 1));
}
}
+ return SVN_NO_ERROR;
}
/* Helper for do_directory_merge().
@@ -5975,7 +6060,7 @@ get_most_inclusive_rev(const apr_array_h
remaining_ranges is inclusive of END_REV, Slice the first range in
to two at END_REV. All the allocations are persistent and allocated
from POOL. */
-static void
+static svn_error_t *
slice_remaining_ranges(apr_array_header_t *children_with_mergeinfo,
svn_boolean_t is_rollback, svn_revnum_t end_rev,
apr_pool_t *pool)
@@ -6005,10 +6090,12 @@ slice_remaining_ranges(apr_array_header_
split_range2->start = end_rev;
APR_ARRAY_IDX(child->remaining_ranges, 0,
svn_merge_range_t *) = split_range1;
- svn_sort__array_insert(child->remaining_ranges, &split_range2, 1);
+ SVN_ERR(svn_sort__array_insert2(child->remaining_ranges,
+ &split_range2, 1));
}
}
}
+ return SVN_NO_ERROR;
}
/* Helper for do_directory_merge().
@@ -6020,7 +6107,7 @@ slice_remaining_ranges(apr_array_header_
If a range is removed from a child's remaining_ranges array, allocate the
new remaining_ranges array in POOL.
*/
-static void
+static svn_error_t *
remove_first_range_from_remaining_ranges(svn_revnum_t revision,
apr_array_header_t
*children_with_mergeinfo,
@@ -6041,10 +6128,11 @@ remove_first_range_from_remaining_ranges
APR_ARRAY_IDX(child->remaining_ranges, 0, svn_merge_range_t *);
if (first_range->end == revision)
{
- svn_sort__array_delete(child->remaining_ranges, 0, 1);
+ SVN_ERR(svn_sort__array_delete2(child->remaining_ranges, 0, 1));
}
}
}
+ return SVN_NO_ERROR;
}
/* Get a file's content and properties from the repository.
@@ -6130,7 +6218,7 @@ get_child_with_mergeinfo(const apr_array
out of order and then sort afterwards. (One caller is doing a qsort
after calling this anyway.)
*/
-static void
+static svn_error_t *
insert_child_to_merge(apr_array_header_t *children_with_mergeinfo,
const svn_client__merge_path_t *insert_element,
apr_pool_t *pool)
@@ -6144,7 +6232,9 @@ insert_child_to_merge(apr_array_header_t
compare_merge_path_t_as_paths);
new_element = svn_client__merge_path_dup(insert_element, pool);
- svn_sort__array_insert(children_with_mergeinfo, &new_element, insert_index);
+ SVN_ERR(svn_sort__array_insert2(children_with_mergeinfo,
+ &new_element, insert_index));
+ return SVN_NO_ERROR;
}
/* Helper for get_mergeinfo_paths().
@@ -6205,7 +6295,7 @@ insert_parent_and_sibs_of_sw_absent_del_
parent->missing_child = child->absent;
parent->switched_child = child->switched;
/* Insert PARENT into CHILDREN_WITH_MERGEINFO. */
- insert_child_to_merge(children_with_mergeinfo, parent, pool);
+ SVN_ERR(insert_child_to_merge(children_with_mergeinfo, parent, pool));
/* Increment for loop index so we don't process the inserted element. */
(*curr_index)++;
} /*(parent == NULL) */
@@ -6242,8 +6332,8 @@ insert_parent_and_sibs_of_sw_absent_del_
sibling_of_missing = svn_client__merge_path_create(child_abspath,
pool);
- insert_child_to_merge(children_with_mergeinfo, sibling_of_missing,
- pool);
+ SVN_ERR(insert_child_to_merge(children_with_mergeinfo,
+ sibling_of_missing, pool));
}
}
@@ -6584,8 +6674,8 @@ get_mergeinfo_paths(apr_array_header_t *
svn_client__merge_path_t *switched_child =
svn_client__merge_path_create(wc_path, result_pool);
switched_child->switched = TRUE;
- insert_child_to_merge(children_with_mergeinfo, switched_child,
- result_pool);
+ SVN_ERR(insert_child_to_merge(children_with_mergeinfo,
+ switched_child, result_pool));
}
}
}
@@ -6637,8 +6727,8 @@ get_mergeinfo_paths(apr_array_header_t *
}
if (new_shallow_child)
- insert_child_to_merge(children_with_mergeinfo, shallow_child,
- result_pool);
+ SVN_ERR(insert_child_to_merge(children_with_mergeinfo,
+ shallow_child, result_pool));
}
}
@@ -6667,8 +6757,8 @@ get_mergeinfo_paths(apr_array_header_t *
svn_client__merge_path_t *absent_child =
svn_client__merge_path_create(wc_path, result_pool);
absent_child->absent = TRUE;
- insert_child_to_merge(children_with_mergeinfo, absent_child,
- result_pool);
+ SVN_ERR(insert_child_to_merge(children_with_mergeinfo,
+ absent_child, result_pool));
}
}
}
@@ -6681,8 +6771,8 @@ get_mergeinfo_paths(apr_array_header_t *
svn_client__merge_path_t *target_child =
svn_client__merge_path_create(target->abspath,
result_pool);
- insert_child_to_merge(children_with_mergeinfo, target_child,
- result_pool);
+ SVN_ERR(insert_child_to_merge(children_with_mergeinfo, target_child,
+ result_pool));
}
/* Case 8: Path is an immediate *directory* child of
@@ -6725,8 +6815,8 @@ get_mergeinfo_paths(apr_array_header_t *
&& depth == svn_depth_immediates)
immediate_child->immediate_child_dir = TRUE;
- insert_child_to_merge(children_with_mergeinfo,
- immediate_child, result_pool);
+ SVN_ERR(insert_child_to_merge(children_with_mergeinfo,
+ immediate_child, result_pool));
}
}
}
@@ -6818,9 +6908,9 @@ get_mergeinfo_paths(apr_array_header_t *
child_of_noninheritable =
svn_client__merge_path_create(child_abspath, result_pool);
child_of_noninheritable->child_of_noninheritable = TRUE;
- insert_child_to_merge(children_with_mergeinfo,
- child_of_noninheritable,
- result_pool);
+ SVN_ERR(insert_child_to_merge(children_with_mergeinfo,
+ child_of_noninheritable,
+ result_pool));
if (!dry_run && same_repos)
{
svn_mergeinfo_t mergeinfo;
@@ -7244,7 +7334,7 @@ normalize_merge_sources_internal(apr_arr
new_segment->path = original_repos_relpath;
new_segment->range_start = original_revision;
new_segment->range_end = original_revision;
- svn_sort__array_insert(segments, &new_segment, 0);
+ SVN_ERR(svn_sort__array_insert2(segments, &new_segment, 0));
}
}
}
@@ -7791,7 +7881,7 @@ do_file_merge(svn_mergeinfo_catalog_t re
(This list is used from notify_merge_begin)
Directory merges use remove_first_range_from_remaining_ranges() */
- svn_sort__array_delete(ranges_to_merge, 0, 1);
+ SVN_ERR(svn_sort__array_delete2(ranges_to_merge, 0, 1));
}
merge_b->notify_begin.last_abspath = NULL;
} /* !merge_b->record_only */
@@ -7889,18 +7979,23 @@ process_children_with_new_mergeinfo(merg
apr_pool_t *pool)
{
apr_pool_t *iterpool;
- apr_hash_index_t *hi;
+ apr_array_header_t *a;
+ int i;
if (!merge_b->paths_with_new_mergeinfo || merge_b->dry_run)
return SVN_NO_ERROR;
- /* Iterate over each path with explicit mergeinfo added by the merge. */
+ /* Iterate over each path with explicit mergeinfo added by the merge.
+ * Iterate in a parent-to-child order so that inherited
+ * mergeinfo is propagated consistently from each parent path to its
+ * children. (Issue #4862) */
+ a = svn_sort__hash(merge_b->paths_with_new_mergeinfo,
+ svn_sort_compare_items_as_paths, pool);
iterpool = svn_pool_create(pool);
- for (hi = apr_hash_first(pool, merge_b->paths_with_new_mergeinfo);
- hi;
- hi = apr_hash_next(hi))
+ for (i = 0; i < a->nelts; i++)
{
- const char *abspath_with_new_mergeinfo = apr_hash_this_key(hi);
+ svn_sort__item_t *item = &APR_ARRAY_IDX(a, i, svn_sort__item_t);
+ const char *abspath_with_new_mergeinfo = item->key;
svn_mergeinfo_t path_inherited_mergeinfo;
svn_mergeinfo_t path_explicit_mergeinfo;
svn_client__merge_path_t *new_child;
@@ -7978,7 +8073,8 @@ process_children_with_new_mergeinfo(merg
/* Set the path's remaining_ranges equal to its parent's. */
new_child->remaining_ranges = svn_rangelist_dup(
parent->remaining_ranges, pool);
- insert_child_to_merge(children_with_mergeinfo, new_child, pool);
+ SVN_ERR(insert_child_to_merge(children_with_mergeinfo,
+ new_child, pool));
}
}
}
@@ -8543,8 +8639,8 @@ record_mergeinfo_for_dir_merge(svn_merge
/* Remove absent children at or under MERGE_B->target->abspath from
CHILDREN_WITH_MERGEINFO
before we calculate the merges performed. */
- remove_absent_children(merge_b->target->abspath,
- children_with_mergeinfo);
+ SVN_ERR(remove_absent_children(merge_b->target->abspath,
+ children_with_mergeinfo));
/* Determine which subtrees of interest need mergeinfo recorded... */
SVN_ERR(flag_subtrees_needing_mergeinfo(operative_merge, &range,
@@ -9510,8 +9606,9 @@ do_mergeinfo_aware_dir_merge(svn_mergein
svn_pool_clear(iterpool);
- slice_remaining_ranges(children_with_mergeinfo,
- is_rollback, end_rev, scratch_pool);
+ SVN_ERR(slice_remaining_ranges(children_with_mergeinfo,
+ is_rollback, end_rev,
+ scratch_pool));
/* Reset variables that must be reset for every drive */
merge_b->notify_begin.last_abspath = NULL;
@@ -9540,12 +9637,12 @@ do_mergeinfo_aware_dir_merge(svn_mergein
to consider these subtrees for subsequent editor drives
nor do we want to record mergeinfo on them describing
the merge itself. */
- remove_children_with_deleted_mergeinfo(
- merge_b, children_with_mergeinfo);
+ SVN_ERR(remove_children_with_deleted_mergeinfo(
+ merge_b, children_with_mergeinfo));
/* Prepare for the next iteration (if any). */
- remove_first_range_from_remaining_ranges(
- end_rev, children_with_mergeinfo, scratch_pool);
+ SVN_ERR(remove_first_range_from_remaining_ranges(
+ end_rev, children_with_mergeinfo, scratch_pool));
/* If we raised any conflicts, break out and report how much
we have merged. */
@@ -10498,16 +10595,34 @@ svn_client__merge_locked(svn_client__con
source2, NULL, revision2, revision2, ctx, sesspool));
/* We can't do a diff between different repositories. */
- /* ### We should also insist that the root URLs of the two sources match,
- * as we are only carrying around a single source-repos-root from now
- * on, and URL calculations will go wrong if they differ.
- * Alternatively, teach the code to cope with differing root URLs. */
- SVN_ERR(check_same_repos(source1_loc, source1_loc->url,
- source2_loc, source2_loc->url,
- FALSE /* strict_urls */, scratch_pool));
+ err = check_same_repos(
+ source1_loc, source1, source2_loc, source2,
+ _("The repository root URLs of the two sources must be identical "
+ "in a two-URL merge"));
+ if (err)
+ /* Add an error code and message compatible with Subversion <= 1.14 */
+ return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, err,
+ _("'%s' isn't in the same repository as '%s'"),
+ source1, source2_loc->repos_root_url);
/* Do our working copy and sources come from the same repository? */
- same_repos = is_same_repos(&target->loc, source1_loc, TRUE /* strict_urls */);
+ err = is_same_repos(&same_repos,
+ source1_loc, source1, &target->loc, target_abspath,
+ _("The given merge source must have the same repository "
+ "root URL as the target WC, in the usual case; "
+ "or, if a foreign repository merge is intended, the repositories "
+ "must have different root URLs and different UUIDs"));
+#if WITH_AMBIGUOUS_FOREIGN_MERGE_WARNING
+ if (err)
+ {
+ /* Subversion 1.14 compatibility: do a foreign-repository merge,
+ * even though the repository UUIDs are identical. Issue a warning. */
+ notify_pre_1_16_warning(err, ctx, scratch_pool);
+ same_repos = FALSE;
+ }
+#else
+ SVN_ERR(err);
+#endif
/* Unless we're ignoring ancestry, see if the two sources are related. */
if (! ignore_mergeinfo)
@@ -11713,13 +11828,12 @@ open_reintegrate_source_and_target(svn_r
/* source_loc and target->loc are required to be in the same repository,
as mergeinfo doesn't come into play for cross-repository merging. */
- SVN_ERR(check_same_repos(source_loc,
- svn_dirent_local_style(source_path_or_url,
- scratch_pool),
- &target->loc,
- svn_dirent_local_style(target->abspath,
- scratch_pool),
- TRUE /* strict_urls */, scratch_pool));
+ SVN_ERR(check_same_repos(
+ source_loc, source_path_or_url,
+ &target->loc, svn_dirent_local_style(target->abspath,
+ scratch_pool),
+ _("The repository root URLs of the source and the target WC "
+ "must be identical in a reintegrate merge")));
*source_loc_p = source_loc;
*target_p = target;
@@ -11881,7 +11995,24 @@ merge_peg_locked(svn_client__conflict_re
scratch_pool, scratch_pool));
/* Check for same_repos. */
- same_repos = is_same_repos(&target->loc, source_loc, TRUE /* strict_urls */);
+ err = is_same_repos(&same_repos,
+ source_loc, source_path_or_url,
+ &target->loc, target_abspath,
+ _("The given merge source must have the same repository "
+ "root URL as the target WC, in the usual case; "
+ "or, if a foreign repository merge is intended, the repositories "
+ "must have different root URLs and different UUIDs"));
+#if WITH_AMBIGUOUS_FOREIGN_MERGE_WARNING
+ if (err)
+ {
+ /* Subversion 1.14 compatibility: do a foreign-repository merge,
+ * even though the repository UUIDs are identical. Issue a warning. */
+ notify_pre_1_16_warning(err, ctx, scratch_pool);
+ same_repos = FALSE;
+ }
+#else
+ SVN_ERR(err);
+#endif
/* Do the real merge! (We say with confidence that our merge
sources are both ancestral and related.) */
@@ -12669,9 +12800,12 @@ client_find_automatic_merge(automatic_me
ctx, result_pool));
/* Check source is in same repos as target. */
- SVN_ERR(check_same_repos(s_t->source, source_path_or_url,
- &s_t->target->loc, target_abspath,
- TRUE /* strict_urls */, scratch_pool));
+ SVN_ERR(check_same_repos(
+ s_t->source, source_path_or_url,
+ &s_t->target->loc, svn_dirent_local_style(target_abspath,
+ scratch_pool),
+ _("The repository root URLs of the source and the target WC "
+ "must be identical in an automatic merge")));
SVN_ERR(find_automatic_merge(&merge->base, &merge->is_reintegrate_like, s_t,
ctx, result_pool, scratch_pool));
@@ -12814,7 +12948,7 @@ do_automatic_merge_locked(svn_client__co
for the root path of the merge).
An improvement would be to change find_automatic_merge() to
- find the base for each sutree, and then here use the oldest base
+ find the base for each subtree, and then here use the oldest base
among all subtrees. */
apr_array_header_t *merge_sources;
svn_ra_session_t *ra_session = NULL;
Modified: subversion/branches/multi-wc-format/subversion/libsvn_client/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_client/mergeinfo.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_client/mergeinfo.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_client/mergeinfo.c Fri Jan 14 14:01:45 2022
@@ -1749,7 +1749,7 @@ svn_client__mergeinfo_log(svn_boolean_t
if (*target_mergeinfo_catalog)
{
/* The caller provided the mergeinfo catalog for
- TARGET_PATH_OR_URL, so we don't need to accquire
+ TARGET_PATH_OR_URL, so we don't need to acquire
it ourselves. We do need to get the repos_root
though, because get_mergeinfo() won't do it for us. */
target_mergeinfo_cat = *target_mergeinfo_catalog;
Modified: subversion/branches/multi-wc-format/subversion/libsvn_client/mergeinfo.h
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_client/mergeinfo.h?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_client/mergeinfo.h (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_client/mergeinfo.h Fri Jan 14 14:01:45 2022
@@ -74,8 +74,6 @@ typedef struct svn_client__merge_path_t
prior to a merge. May be NULL. */
svn_boolean_t inherited_mergeinfo; /* Whether PRE_MERGE_MERGEINFO was
explicit or inherited. */
- svn_boolean_t scheduled_for_deletion; /* ABSPATH is scheduled for
- deletion. */
svn_boolean_t immediate_child_dir; /* ABSPATH is an immediate child
directory of the merge target,
has no explicit mergeinfo prior
@@ -316,7 +314,7 @@ svn_client__get_history_as_mergeinfo(svn
/* Parse any explicit mergeinfo on LOCAL_ABSPATH and store it in
*MERGEINFO. If no record of any mergeinfo exists, set *MERGEINFO to NULL.
- Does not acount for inherited mergeinfo.
+ Does not account for inherited mergeinfo.
Allocate the result deeply in @a result_pool. */
svn_error_t *
Modified: subversion/branches/multi-wc-format/subversion/libsvn_client/mtcc.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_client/mtcc.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_client/mtcc.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_client/mtcc.c Fri Jan 14 14:01:45 2022
@@ -453,7 +453,8 @@ mtcc_verify_create(svn_client__mtcc_t *m
if (op)
return svn_error_createf(SVN_ERR_FS_ALREADY_EXISTS, NULL,
- _("Path '%s' already exists"),
+ _("Path '%s' already exists, or was created "
+ "by an earlier operation"),
new_relpath);
SVN_ERR(mtcc_op_find(&op, NULL, new_relpath, mtcc->root_op, TRUE, TRUE,
@@ -604,7 +605,7 @@ mtcc_op_contains_non_delete(const mtcc_o
static svn_error_t *
mtcc_add_delete(const char *relpath,
svn_boolean_t for_move,
- svn_client__mtcc_t *mtcc,
+ svn_client__mtcc_t *mtcc,
apr_pool_t *scratch_pool)
{
mtcc_op_t *op;
@@ -636,7 +637,7 @@ mtcc_add_delete(const char *relpath,
{
/* Allow deleting directories, that are unmodified except for
one or more deleted descendants */
-
+
SVN_ERR(mtcc_op_find(&op, &created, relpath, mtcc->root_op, TRUE,
FALSE, FALSE, mtcc->pool, scratch_pool));
Modified: subversion/branches/multi-wc-format/subversion/libsvn_client/patch.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_client/patch.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_client/patch.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_client/patch.c Fri Jan 14 14:01:45 2022
@@ -1020,6 +1020,7 @@ init_patch_target(patch_target_t **patch
target_content_t *content;
svn_boolean_t has_text_changes = FALSE;
svn_boolean_t follow_moves;
+ const char *tempdir_abspath;
has_text_changes = ((patch->hunks && patch->hunks->nelts > 0)
|| patch->binary_patch);
@@ -1225,8 +1226,10 @@ init_patch_target(patch_target_t **patch
}
/* Open a temporary file to write the patched result to. */
+ SVN_ERR(svn_wc__get_tmpdir(&tempdir_abspath, wc_ctx,
+ target->local_abspath, scratch_pool, scratch_pool));
SVN_ERR(svn_io_open_unique_file3(&target->patched_file,
- &target->patched_path, NULL,
+ &target->patched_path, tempdir_abspath,
remove_tempfiles ?
svn_io_file_del_on_pool_cleanup :
svn_io_file_del_none,
@@ -1238,7 +1241,7 @@ init_patch_target(patch_target_t **patch
/* Open a temporary stream to write rejected hunks to. */
SVN_ERR(svn_stream_open_unique(&target->reject_stream,
- &target->reject_path, NULL,
+ &target->reject_path, tempdir_abspath,
remove_tempfiles ?
svn_io_file_del_on_pool_cleanup :
svn_io_file_del_none,
@@ -2467,7 +2470,7 @@ send_patch_notification(const patch_targ
/* Implements the callback for svn_sort__array. Puts hunks that match
before hunks that do not match, puts hunks that match in order
- based on postion matched, puts hunks that do not match in order
+ based on position matched, puts hunks that do not match in order
based on original position. */
static int
sort_matched_hunks(const void *a, const void *b)
Modified: subversion/branches/multi-wc-format/subversion/libsvn_client/ra.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_client/ra.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_client/ra.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_client/ra.c Fri Jan 14 14:01:45 2022
@@ -402,8 +402,7 @@ svn_client__open_ra_session_internal(svn
}
}
- /* If the caller allows for auto-following redirections, and the
- RA->open() call above reveals a CORRECTED_URL, try the new URL.
+ /* If the caller allows for auto-following redirections, try the new URL.
We'll do this in a loop up to some maximum number follow-and-retry
attempts. */
if (corrected_url)
@@ -414,12 +413,14 @@ svn_client__open_ra_session_internal(svn
*corrected_url = NULL;
while (attempts_left--)
{
- const char *corrected = NULL;
+ const char *corrected = NULL; /* canonicalized version */
+ const char *redirect_url = NULL; /* non-canonicalized version */
/* Try to open the RA session. If this is our last attempt,
don't accept corrected URLs from the RA provider. */
- SVN_ERR(svn_ra_open4(ra_session,
+ SVN_ERR(svn_ra_open5(ra_session,
attempts_left == 0 ? NULL : &corrected,
+ attempts_left == 0 ? NULL : &redirect_url,
base_url, uuid, cbtable, cb, ctx->config,
result_pool));
@@ -441,19 +442,28 @@ svn_client__open_ra_session_internal(svn
*corrected_url = corrected;
/* Make sure we've not attempted this URL before. */
- if (svn_hash_gets(attempted, corrected))
+ if (svn_hash_gets(attempted, redirect_url))
return svn_error_createf(SVN_ERR_CLIENT_CYCLE_DETECTED, NULL,
_("Redirect cycle detected for URL '%s'"),
- corrected);
+ redirect_url);
+
+ /*
+ * Remember this redirect URL so we don't wind up in a loop.
+ *
+ * Store the non-canonicalized version of the URL. The canonicalized
+ * version is insufficient for loop detection because we might not get
+ * an exact match against URLs used by the RA protocol-layer (the URL
+ * used by the protocol may contain trailing slashes, for example,
+ * which are stripped during canonicalization).
+ */
+ svn_hash_sets(attempted, redirect_url, (void *)1);
- /* Remember this CORRECTED_URL so we don't wind up in a loop. */
- svn_hash_sets(attempted, corrected, (void *)1);
base_url = corrected;
}
}
else
{
- SVN_ERR(svn_ra_open4(ra_session, NULL, base_url,
+ SVN_ERR(svn_ra_open5(ra_session, NULL, NULL, base_url,
uuid, cbtable, cb, ctx->config, result_pool));
}
Modified: subversion/branches/multi-wc-format/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_client/repos_diff.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_client/repos_diff.c Fri Jan 14 14:01:45 2022
@@ -384,7 +384,7 @@ get_file_from_ra(struct file_baton *fb,
See https://issues.apache.org/jira/browse/SVN-3657#desc9 and
http://svn.haxx.se/dev/archive-2010-08/0351.shtml for more details.
*/
-static void
+static svn_error_t *
remove_non_prop_changes(apr_hash_t *pristine_props,
apr_array_header_t *changes)
{
@@ -392,7 +392,7 @@ remove_non_prop_changes(apr_hash_t *pris
/* For added nodes, there is nothing to filter. */
if (apr_hash_count(pristine_props) == 0)
- return;
+ return SVN_NO_ERROR;
for (i = 0; i < changes->nelts; i++)
{
@@ -406,11 +406,12 @@ remove_non_prop_changes(apr_hash_t *pris
if (old_val && svn_string_compare(old_val, change->value))
{
/* Remove the matching change and re-check the current index */
- svn_sort__array_delete(changes, i, 1);
+ SVN_ERR(svn_sort__array_delete2(changes, i, 1));
i--;
}
}
}
+ return SVN_NO_ERROR;
}
/* Get the empty file associated with the edit baton. This is cached so
@@ -1010,7 +1011,7 @@ close_file(void *file_baton,
}
if (fb->pristine_props)
- remove_non_prop_changes(fb->pristine_props, fb->propchanges);
+ SVN_ERR(remove_non_prop_changes(fb->pristine_props, fb->propchanges));
right_props = svn_prop__patch(fb->pristine_props, fb->propchanges,
fb->pool);
@@ -1083,7 +1084,7 @@ close_directory(void *dir_baton,
if (db->propchanges->nelts > 0)
{
- remove_non_prop_changes(pristine_props, db->propchanges);
+ SVN_ERR(remove_non_prop_changes(pristine_props, db->propchanges));
}
if (db->propchanges->nelts > 0 || db->added)
Modified: subversion/branches/multi-wc-format/subversion/libsvn_client/revert.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_client/revert.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_client/revert.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_client/revert.c Fri Jan 14 14:01:45 2022
@@ -57,24 +57,12 @@ struct revert_with_write_lock_baton {
/* (Note: All arguments are in the baton above.)
- Attempt to revert LOCAL_ABSPATH.
+ Attempt to revert LOCAL_ABSPATH by calling svn_wc_revert6(), which
+ see for further details.
- If DEPTH is svn_depth_empty, revert just the properties on the
- directory; else if svn_depth_files, revert the properties and any
- files immediately under the directory; else if
- svn_depth_immediates, revert all of the preceding plus properties
- on immediate subdirectories; else if svn_depth_infinity, revert
- path and everything under it fully recursively.
-
- CHANGELISTS is an array of const char * changelist names, used as a
- restrictive filter on items reverted; that is, don't revert any
- item unless it's a member of one of those changelists. If
- CHANGELISTS is empty (or altogether NULL), no changelist filtering occurs.
-
- Consult CTX to determine whether or not to revert timestamp to the
- time of last commit ('use-commit-times = yes').
-
- If PATH is unversioned, return SVN_ERR_UNVERSIONED_RESOURCE. */
+ If the target isn't versioned, send a 'skip' notification and return
+ no error.
+ */
static svn_error_t *
revert(void *baton, apr_pool_t *result_pool, apr_pool_t *scratch_pool)
{