aboutsummaryrefslogtreecommitdiff
path: root/subversion/libsvn_client
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_client')
-rw-r--r--subversion/libsvn_client/merge.c40
-rw-r--r--subversion/libsvn_client/mergeinfo.h2
-rw-r--r--subversion/libsvn_client/mtcc.c3
3 files changed, 34 insertions, 11 deletions
diff --git a/subversion/libsvn_client/merge.c b/subversion/libsvn_client/merge.c
index 9d9a1c300a10..e535647d8649 100644
--- a/subversion/libsvn_client/merge.c
+++ b/subversion/libsvn_client/merge.c
@@ -264,7 +264,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. */
@@ -1545,6 +1545,25 @@ record_update_delete(merge_cmd_baton_t *merge_b,
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;
}
@@ -5595,7 +5614,7 @@ svn_client__make_merge_conflict_error(svn_client__conflict_report_t *report,
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 svn_error_t *
remove_absent_children(const char *target_wcpath,
@@ -5609,7 +5628,7 @@ remove_absent_children(const char *target_wcpath,
{
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_ERR(svn_sort__array_delete2(children_with_mergeinfo, i--, 1));
@@ -7896,18 +7915,23 @@ process_children_with_new_mergeinfo(merge_cmd_baton_t *merge_b,
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 the paths 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;
diff --git a/subversion/libsvn_client/mergeinfo.h b/subversion/libsvn_client/mergeinfo.h
index 1d6d524f5dd2..99e1bf9f80c7 100644
--- a/subversion/libsvn_client/mergeinfo.h
+++ b/subversion/libsvn_client/mergeinfo.h
@@ -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
diff --git a/subversion/libsvn_client/mtcc.c b/subversion/libsvn_client/mtcc.c
index 48ddcccbc164..a7c86a49a472 100644
--- a/subversion/libsvn_client/mtcc.c
+++ b/subversion/libsvn_client/mtcc.c
@@ -453,7 +453,8 @@ mtcc_verify_create(svn_client__mtcc_t *mtcc,
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,