Author: julianfoad
Date: Tue Feb 19 17:10:11 2019
New Revision: 1853900
URL: http://svn.apache.org/viewvc?rev=1853900&view=rev
Log:
On the 'shelving-v3' branch: Catch up with trunk@1853898.
Modified:
subversion/branches/shelving-v3/ (props changed)
subversion/branches/shelving-v3/subversion/include/private/svn_client_mtcc.h
subversion/branches/shelving-v3/subversion/include/private/svn_wc_private.h
subversion/branches/shelving-v3/subversion/libsvn_client/conflicts.c
subversion/branches/shelving-v3/subversion/libsvn_client/shelf.c
subversion/branches/shelving-v3/subversion/libsvn_repos/dump.c
subversion/branches/shelving-v3/subversion/libsvn_subr/error.c
subversion/branches/shelving-v3/subversion/libsvn_wc/node.c
subversion/branches/shelving-v3/subversion/libsvn_wc/wc-queries.sql
subversion/branches/shelving-v3/subversion/libsvn_wc/wc_db.c
subversion/branches/shelving-v3/subversion/libsvn_wc/wc_db.h
subversion/branches/shelving-v3/subversion/libsvn_wc/wcroot_anchor.c
subversion/branches/shelving-v3/subversion/tests/cmdline/svnadmin_tests.py
subversion/branches/shelving-v3/subversion/tests/cmdline/svntest/sandbox.py
subversion/branches/shelving-v3/subversion/tests/libsvn_client/conflicts-test.c
subversion/branches/shelving-v3/subversion/tests/libsvn_wc/wc-queries-test.c
Propchange: subversion/branches/shelving-v3/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Feb 19 17:10:11 2019
@@ -101,3 +101,4 @@
/subversion/branches/verify-at-commit:1462039-1462408
/subversion/branches/verify-keep-going:1439280-1546110
/subversion/branches/wc-collate-path:1402685-1480384
+/subversion/trunk:1853394-1853898
Modified:
subversion/branches/shelving-v3/subversion/include/private/svn_client_mtcc.h
URL:
http://svn.apache.org/viewvc/subversion/branches/shelving-v3/subversion/include/private/svn_client_mtcc.h?rev=1853900&r1=1853899&r2=1853900&view=diff
==============================================================================
---
subversion/branches/shelving-v3/subversion/include/private/svn_client_mtcc.h
(original)
+++
subversion/branches/shelving-v3/subversion/include/private/svn_client_mtcc.h
Tue Feb 19 17:10:11 2019
@@ -207,6 +207,17 @@ svn_client__mtcc_check_path(svn_node_kin
/** Commits all operations stored in @a mtcc as a new revision and destroys
* @a mtcc.
*
+ * A log message is obtained from the log message callback in the client
+ * context in @a mtcc.
+ *
+ * @a revprop_table (if non-NULL) supplies additional revision properties;
+ * it may not supply any "svn:*" revision properties.
+ *
+ * As with svn_ra_get_commit_editor3(), after the commit has succeeded,
+ * it will invoke @a commit_callback (if non-NULL) with filled-in
+ * #svn_commit_info_t *, @a commit_baton, and @a scratch_pool or some subpool
+ * thereof as arguments.
+ *
* @since New in 1.9.
*/
svn_error_t *
Modified:
subversion/branches/shelving-v3/subversion/include/private/svn_wc_private.h
URL:
http://svn.apache.org/viewvc/subversion/branches/shelving-v3/subversion/include/private/svn_wc_private.h?rev=1853900&r1=1853899&r2=1853900&view=diff
==============================================================================
--- subversion/branches/shelving-v3/subversion/include/private/svn_wc_private.h
(original)
+++ subversion/branches/shelving-v3/subversion/include/private/svn_wc_private.h
Tue Feb 19 17:10:11 2019
@@ -348,9 +348,9 @@ svn_wc__get_wcroot(const char **wcroot_a
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
-/** Set @a *dir to the abspath of the directory in which shelved patches
- * are stored, which is inside the WC's administrative directory, and ensure
- * the directory exists.
+/** Set @a *dir to the abspath of the directory in which administrative
+ * data for experimental features may be stored. This directory is inside
+ * the WC's administrative directory. Ensure the directory exists.
*
* @a local_abspath is any path in the WC, and is used to find the WC root.
*
@@ -358,11 +358,11 @@ svn_wc__get_wcroot(const char **wcroot_a
*/
SVN_EXPERIMENTAL
svn_error_t *
-svn_wc__get_shelves_dir(char **dir,
- svn_wc_context_t *wc_ctx,
- const char *local_abspath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool);
+svn_wc__get_experimental_dir(char **dir,
+ svn_wc_context_t *wc_ctx,
+ const char *local_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
/**
* The following are temporary APIs to aid in the transition from wc-1 to
@@ -635,6 +635,24 @@ svn_wc__find_working_nodes_with_basename
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
+/* Return an array of const char * elements, which represent local absolute
+ * paths for nodes, within the working copy indicated by WRI_ABSPATH, which
+ * are copies of REPOS_RELPATH and have node kind KIND.
+ * If no such nodes exist, return an empty array.
+ *
+ * This function returns only paths to nodes which are present in the highest
+ * layer of the WC. In other words, paths to deleted and/or excluded nodes are
+ * never returned.
+ */
+svn_error_t *
+svn_wc__find_copies_of_repos_path(apr_array_header_t **abspaths,
+ const char *wri_abspath,
+ const char *repos_relpath,
+ svn_node_kind_t kind,
+ svn_wc_context_t *wc_ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
/* Get the working revision of @a local_abspath using @a wc_ctx. If @a
* local_abspath is not in the working copy, return @c
* SVN_ERR_WC_PATH_NOT_FOUND.
Modified: subversion/branches/shelving-v3/subversion/libsvn_client/conflicts.c
URL:
http://svn.apache.org/viewvc/subversion/branches/shelving-v3/subversion/libsvn_client/conflicts.c?rev=1853900&r1=1853899&r2=1853900&view=diff
==============================================================================
--- subversion/branches/shelving-v3/subversion/libsvn_client/conflicts.c
(original)
+++ subversion/branches/shelving-v3/subversion/libsvn_client/conflicts.c Tue
Feb 19 17:10:11 2019
@@ -10773,6 +10773,7 @@ configure_option_incoming_move_file_merg
{
svn_node_kind_t victim_node_kind;
svn_wc_conflict_action_t incoming_change;
+ svn_wc_conflict_reason_t local_change;
const char *incoming_old_repos_relpath;
svn_revnum_t incoming_old_pegrev;
svn_node_kind_t incoming_old_kind;
@@ -10781,6 +10782,7 @@ configure_option_incoming_move_file_merg
svn_node_kind_t incoming_new_kind;
incoming_change = svn_client_conflict_get_incoming_change(conflict);
+ local_change = svn_client_conflict_get_local_change(conflict);
victim_node_kind = svn_client_conflict_tree_get_victim_node_kind(conflict);
SVN_ERR(svn_client_conflict_get_incoming_old_repos_location(
&incoming_old_repos_relpath, &incoming_old_pegrev,
@@ -10794,7 +10796,8 @@ configure_option_incoming_move_file_merg
if (victim_node_kind == svn_node_file &&
incoming_old_kind == svn_node_file &&
incoming_new_kind == svn_node_none &&
- incoming_change == svn_wc_conflict_action_delete)
+ incoming_change == svn_wc_conflict_action_delete &&
+ local_change == svn_wc_conflict_reason_edited)
{
struct conflict_tree_incoming_delete_details *details;
const char *description;
@@ -11068,6 +11071,648 @@ configure_option_sibling_move_merge(svn_
return SVN_NO_ERROR;
}
+struct conflict_tree_update_local_moved_away_details {
+ /*
+ * This array consists of "const char *" absolute paths to working copy
+ * nodes which are uncomitted copies and correspond to the repository path
+ * of the conflict victim.
+ * Each such working copy node is a potential local move target which can
+ * be chosen to find a suitable merge target when resolving a tree conflict.
+ *
+ * This may be an empty array in case if there is no move target path in
+ * the working copy. */
+ apr_array_header_t *wc_move_targets;
+
+ /* Current index into the list of working copy paths in WC_MOVE_TARGETS. */
+ int preferred_move_target_idx;
+};
+
+/* Implements conflict_option_resolve_func_t.
+ * Resolve an incoming move vs local move conflict by merging from the
+ * incoming move's target location to the local move's target location,
+ * overriding the incoming move. The original local move was broken during
+ * update/switch, so overriding the incoming move involves recording a new
+ * move from the incoming move's target location to the local move's target
+ * location. */
+static svn_error_t *
+resolve_both_moved_file_update_keep_local_move(
+ svn_client_conflict_option_t *option,
+ svn_client_conflict_t *conflict,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *scratch_pool)
+{
+ svn_client_conflict_option_id_t option_id;
+ const char *victim_abspath;
+ const char *local_moved_to_abspath;
+ svn_wc_operation_t operation;
+ const char *lock_abspath;
+ svn_error_t *err;
+ const char *repos_root_url;
+ const char *incoming_old_repos_relpath;
+ svn_revnum_t incoming_old_pegrev;
+ const char *incoming_new_repos_relpath;
+ svn_revnum_t incoming_new_pegrev;
+ const char *wc_tmpdir;
+ const char *ancestor_abspath;
+ svn_stream_t *ancestor_stream;
+ apr_hash_t *ancestor_props;
+ apr_hash_t *incoming_props;
+ apr_hash_t *local_props;
+ const char *ancestor_url;
+ const char *corrected_url;
+ svn_ra_session_t *ra_session;
+ svn_wc_merge_outcome_t merge_content_outcome;
+ svn_wc_notify_state_t merge_props_outcome;
+ apr_array_header_t *propdiffs;
+ struct conflict_tree_incoming_delete_details *incoming_details;
+ apr_array_header_t *possible_moved_to_abspaths;
+ const char *incoming_moved_to_abspath;
+ struct conflict_tree_update_local_moved_away_details *local_details;
+
+ victim_abspath = svn_client_conflict_get_local_abspath(conflict);
+ operation = svn_client_conflict_get_operation(conflict);
+ incoming_details = conflict->tree_conflict_incoming_details;
+ if (incoming_details == NULL || incoming_details->moves == NULL)
+ return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
+ _("The specified conflict resolution option "
+ "requires details for tree conflict at '%s' "
+ "to be fetched from the repository first."),
+ svn_dirent_local_style(victim_abspath,
+ scratch_pool));
+ if (operation == svn_wc_operation_none)
+ return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
+ _("Invalid operation code '%d' recorded for "
+ "conflict at '%s'"), operation,
+ svn_dirent_local_style(victim_abspath,
+ scratch_pool));
+
+ option_id = svn_client_conflict_option_get_id(option);
+ SVN_ERR_ASSERT(option_id ==
svn_client_conflict_option_both_moved_file_merge);
+
+ SVN_ERR(svn_client_conflict_get_repos_info(&repos_root_url, NULL,
+ conflict, scratch_pool,
+ scratch_pool));
+ SVN_ERR(svn_client_conflict_get_incoming_old_repos_location(
+ &incoming_old_repos_relpath, &incoming_old_pegrev,
+ NULL, conflict, scratch_pool,
+ scratch_pool));
+ SVN_ERR(svn_client_conflict_get_incoming_new_repos_location(
+ &incoming_new_repos_relpath, &incoming_new_pegrev,
+ NULL, conflict, scratch_pool,
+ scratch_pool));
+
+ /* Set up temporary storage for the common ancestor version of the file. */
+ SVN_ERR(svn_wc__get_tmpdir(&wc_tmpdir, ctx->wc_ctx, victim_abspath,
+ scratch_pool, scratch_pool));
+ SVN_ERR(svn_stream_open_unique(&ancestor_stream,
+ &ancestor_abspath, wc_tmpdir,
+ svn_io_file_del_on_pool_cleanup,
+ scratch_pool, scratch_pool));
+
+ /* Fetch the ancestor file's content. */
+ ancestor_url = svn_path_url_add_component2(repos_root_url,
+ incoming_old_repos_relpath,
+ scratch_pool);
+ SVN_ERR(svn_client__open_ra_session_internal(&ra_session, &corrected_url,
+ ancestor_url, NULL, NULL,
+ FALSE, FALSE, ctx,
+ scratch_pool, scratch_pool));
+ SVN_ERR(svn_ra_get_file(ra_session, "", incoming_old_pegrev,
+ ancestor_stream, NULL, /* fetched_rev */
+ &ancestor_props, scratch_pool));
+ filter_props(ancestor_props, scratch_pool);
+
+ /* Close stream to flush ancestor file to disk. */
+ SVN_ERR(svn_stream_close(ancestor_stream));
+
+ possible_moved_to_abspaths =
+ svn_hash_gets(incoming_details->wc_move_targets,
+ get_moved_to_repos_relpath(incoming_details, scratch_pool));
+ incoming_moved_to_abspath =
+ APR_ARRAY_IDX(possible_moved_to_abspaths,
+ incoming_details->wc_move_target_idx, const char *);
+
+ local_details = conflict->tree_conflict_local_details;
+ local_moved_to_abspath =
+ APR_ARRAY_IDX(local_details->wc_move_targets,
+ local_details->preferred_move_target_idx, const char *);
+
+ /* ### The following WC modifications should be atomic. */
+ SVN_ERR(svn_wc__acquire_write_lock_for_resolve(
+ &lock_abspath, ctx->wc_ctx,
+ svn_dirent_get_longest_ancestor(victim_abspath,
+ local_moved_to_abspath,
+ scratch_pool),
+ scratch_pool, scratch_pool));
+
+ /* Get a copy of the incoming moved item's properties. */
+ err = svn_wc_prop_list2(&incoming_props, ctx->wc_ctx,
+ incoming_moved_to_abspath,
+ scratch_pool, scratch_pool);
+ if (err)
+ goto unlock_wc;
+
+ /* Get a copy of the local move target's properties. */
+ err = svn_wc_prop_list2(&local_props, ctx->wc_ctx,
+ local_moved_to_abspath,
+ scratch_pool, scratch_pool);
+ if (err)
+ goto unlock_wc;
+
+ /* Create a property diff for the files. */
+ err = svn_prop_diffs(&propdiffs, incoming_props, local_props,
+ scratch_pool);
+ if (err)
+ goto unlock_wc;
+
+ /* Perform the file merge. */
+ err = svn_wc_merge5(&merge_content_outcome, &merge_props_outcome,
+ ctx->wc_ctx, ancestor_abspath,
+ incoming_moved_to_abspath, local_moved_to_abspath,
+ NULL, NULL, NULL, /* labels */
+ NULL, NULL, /* conflict versions */
+ FALSE, /* dry run */
+ NULL, NULL, /* diff3_cmd, merge_options */
+ apr_hash_count(ancestor_props) ? ancestor_props : NULL,
+ propdiffs,
+ NULL, NULL, /* conflict func/baton */
+ NULL, NULL, /* don't allow user to cancel here */
+ scratch_pool);
+ if (err)
+ goto unlock_wc;
+
+ if (ctx->notify_func2)
+ {
+ svn_wc_notify_t *notify;
+
+ /* Tell the world about the file merge that just happened. */
+ notify = svn_wc_create_notify(local_moved_to_abspath,
+ svn_wc_notify_update_update,
+ scratch_pool);
+ if (merge_content_outcome == svn_wc_merge_conflict)
+ notify->content_state = svn_wc_notify_state_conflicted;
+ else
+ notify->content_state = svn_wc_notify_state_merged;
+ notify->prop_state = merge_props_outcome;
+ notify->kind = svn_node_file;
+ ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool);
+ }
+
+ /* Record a new move which overrides the incoming move. */
+ err = svn_wc__move2(ctx->wc_ctx, incoming_moved_to_abspath,
+ local_moved_to_abspath,
+ TRUE, /* meta-data only move */
+ FALSE, /* mixed-revisions don't apply to files */
+ NULL, NULL, /* don't allow user to cancel here */
+ NULL, NULL, /* no extra notification */
+ scratch_pool);
+ if (err)
+ goto unlock_wc;
+
+ /* Remove moved-away file from disk. */
+ err = svn_io_remove_file2(incoming_moved_to_abspath, TRUE, scratch_pool);
+ if (err)
+ goto unlock_wc;
+
+ err = svn_wc__del_tree_conflict(ctx->wc_ctx, victim_abspath, scratch_pool);
+ if (err)
+ goto unlock_wc;
+
+ if (ctx->notify_func2)
+ {
+ svn_wc_notify_t *notify;
+
+ notify = svn_wc_create_notify(victim_abspath,
svn_wc_notify_resolved_tree,
+ scratch_pool);
+ ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool);
+ }
+
+ svn_io_sleep_for_timestamps(local_moved_to_abspath, scratch_pool);
+
+ conflict->resolution_tree = option_id;
+
+unlock_wc:
+ err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx,
+ lock_abspath,
+
scratch_pool));
+ SVN_ERR(err);
+
+ return SVN_NO_ERROR;
+}
+
+/* Implements conflict_option_resolve_func_t.
+ * Resolve an incoming move vs local move conflict by merging from the
+ * local move's target location to the incoming move's target location,
+ * and reverting the local move. */
+static svn_error_t *
+resolve_both_moved_file_update_keep_incoming_move(
+ svn_client_conflict_option_t *option,
+ svn_client_conflict_t *conflict,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *scratch_pool)
+{
+ svn_client_conflict_option_id_t option_id;
+ const char *victim_abspath;
+ const char *local_moved_to_abspath;
+ svn_wc_operation_t operation;
+ const char *lock_abspath;
+ svn_error_t *err;
+ const char *repos_root_url;
+ const char *incoming_old_repos_relpath;
+ svn_revnum_t incoming_old_pegrev;
+ const char *incoming_new_repos_relpath;
+ svn_revnum_t incoming_new_pegrev;
+ const char *wc_tmpdir;
+ const char *ancestor_abspath;
+ svn_stream_t *ancestor_stream;
+ apr_hash_t *ancestor_props;
+ apr_hash_t *incoming_props;
+ apr_hash_t *local_props;
+ const char *ancestor_url;
+ const char *corrected_url;
+ svn_ra_session_t *ra_session;
+ svn_wc_merge_outcome_t merge_content_outcome;
+ svn_wc_notify_state_t merge_props_outcome;
+ apr_array_header_t *propdiffs;
+ struct conflict_tree_incoming_delete_details *incoming_details;
+ apr_array_header_t *possible_moved_to_abspaths;
+ const char *incoming_moved_to_abspath;
+ struct conflict_tree_update_local_moved_away_details *local_details;
+
+ victim_abspath = svn_client_conflict_get_local_abspath(conflict);
+ operation = svn_client_conflict_get_operation(conflict);
+ incoming_details = conflict->tree_conflict_incoming_details;
+ if (incoming_details == NULL || incoming_details->moves == NULL)
+ return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
+ _("The specified conflict resolution option "
+ "requires details for tree conflict at '%s' "
+ "to be fetched from the repository first."),
+ svn_dirent_local_style(victim_abspath,
+ scratch_pool));
+ if (operation == svn_wc_operation_none)
+ return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
+ _("Invalid operation code '%d' recorded for "
+ "conflict at '%s'"), operation,
+ svn_dirent_local_style(victim_abspath,
+ scratch_pool));
+
+ option_id = svn_client_conflict_option_get_id(option);
+ SVN_ERR_ASSERT(option_id ==
+ svn_client_conflict_option_both_moved_file_move_merge);
+
+ SVN_ERR(svn_client_conflict_get_repos_info(&repos_root_url, NULL,
+ conflict, scratch_pool,
+ scratch_pool));
+ SVN_ERR(svn_client_conflict_get_incoming_old_repos_location(
+ &incoming_old_repos_relpath, &incoming_old_pegrev,
+ NULL, conflict, scratch_pool,
+ scratch_pool));
+ SVN_ERR(svn_client_conflict_get_incoming_new_repos_location(
+ &incoming_new_repos_relpath, &incoming_new_pegrev,
+ NULL, conflict, scratch_pool,
+ scratch_pool));
+
+ /* Set up temporary storage for the common ancestor version of the file. */
+ SVN_ERR(svn_wc__get_tmpdir(&wc_tmpdir, ctx->wc_ctx, victim_abspath,
+ scratch_pool, scratch_pool));
+ SVN_ERR(svn_stream_open_unique(&ancestor_stream,
+ &ancestor_abspath, wc_tmpdir,
+ svn_io_file_del_on_pool_cleanup,
+ scratch_pool, scratch_pool));
+
+ /* Fetch the ancestor file's content. */
+ ancestor_url = svn_path_url_add_component2(repos_root_url,
+ incoming_old_repos_relpath,
+ scratch_pool);
+ SVN_ERR(svn_client__open_ra_session_internal(&ra_session, &corrected_url,
+ ancestor_url, NULL, NULL,
+ FALSE, FALSE, ctx,
+ scratch_pool, scratch_pool));
+ SVN_ERR(svn_ra_get_file(ra_session, "", incoming_old_pegrev,
+ ancestor_stream, NULL, /* fetched_rev */
+ &ancestor_props, scratch_pool));
+ filter_props(ancestor_props, scratch_pool);
+
+ /* Close stream to flush ancestor file to disk. */
+ SVN_ERR(svn_stream_close(ancestor_stream));
+
+ possible_moved_to_abspaths =
+ svn_hash_gets(incoming_details->wc_move_targets,
+ get_moved_to_repos_relpath(incoming_details, scratch_pool));
+ incoming_moved_to_abspath =
+ APR_ARRAY_IDX(possible_moved_to_abspaths,
+ incoming_details->wc_move_target_idx, const char *);
+
+ local_details = conflict->tree_conflict_local_details;
+ local_moved_to_abspath =
+ APR_ARRAY_IDX(local_details->wc_move_targets,
+ local_details->preferred_move_target_idx, const char *);
+
+ /* ### The following WC modifications should be atomic. */
+ SVN_ERR(svn_wc__acquire_write_lock_for_resolve(
+ &lock_abspath, ctx->wc_ctx,
+ svn_dirent_get_longest_ancestor(victim_abspath,
+ local_moved_to_abspath,
+ scratch_pool),
+ scratch_pool, scratch_pool));
+
+ /* Get a copy of the incoming moved item's properties. */
+ err = svn_wc_prop_list2(&incoming_props, ctx->wc_ctx,
+ incoming_moved_to_abspath,
+ scratch_pool, scratch_pool);
+ if (err)
+ goto unlock_wc;
+
+ /* Get a copy of the local move target's properties. */
+ err = svn_wc_prop_list2(&local_props, ctx->wc_ctx,
+ local_moved_to_abspath,
+ scratch_pool, scratch_pool);
+ if (err)
+ goto unlock_wc;
+
+ /* Create a property diff for the files. */
+ err = svn_prop_diffs(&propdiffs, incoming_props, local_props,
+ scratch_pool);
+ if (err)
+ goto unlock_wc;
+
+ /* Perform the file merge. */
+ err = svn_wc_merge5(&merge_content_outcome, &merge_props_outcome,
+ ctx->wc_ctx, ancestor_abspath,
+ local_moved_to_abspath, incoming_moved_to_abspath,
+ NULL, NULL, NULL, /* labels */
+ NULL, NULL, /* conflict versions */
+ FALSE, /* dry run */
+ NULL, NULL, /* diff3_cmd, merge_options */
+ apr_hash_count(ancestor_props) ? ancestor_props : NULL,
+ propdiffs,
+ NULL, NULL, /* conflict func/baton */
+ NULL, NULL, /* don't allow user to cancel here */
+ scratch_pool);
+ if (err)
+ goto unlock_wc;
+
+ if (ctx->notify_func2)
+ {
+ svn_wc_notify_t *notify;
+
+ /* Tell the world about the file merge that just happened. */
+ notify = svn_wc_create_notify(local_moved_to_abspath,
+ svn_wc_notify_update_update,
+ scratch_pool);
+ if (merge_content_outcome == svn_wc_merge_conflict)
+ notify->content_state = svn_wc_notify_state_conflicted;
+ else
+ notify->content_state = svn_wc_notify_state_merged;
+ notify->prop_state = merge_props_outcome;
+ notify->kind = svn_node_file;
+ ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool);
+ }
+
+ /* Revert the copy-half of the local move. The delete-half of this move
+ * has already been deleted during the update/switch operation. */
+ err = svn_wc_revert6(ctx->wc_ctx, local_moved_to_abspath, svn_depth_empty,
+ FALSE, NULL, TRUE, FALSE,
+ TRUE /*added_keep_local*/,
+ NULL, NULL, /* no cancellation */
+ ctx->notify_func2, ctx->notify_baton2,
+ scratch_pool);
+ if (err)
+ goto unlock_wc;
+
+ err = svn_wc__del_tree_conflict(ctx->wc_ctx, victim_abspath, scratch_pool);
+ if (err)
+ goto unlock_wc;
+
+ if (ctx->notify_func2)
+ {
+ svn_wc_notify_t *notify;
+
+ notify = svn_wc_create_notify(victim_abspath,
svn_wc_notify_resolved_tree,
+ scratch_pool);
+ ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool);
+ }
+
+ svn_io_sleep_for_timestamps(local_moved_to_abspath, scratch_pool);
+
+ conflict->resolution_tree = option_id;
+
+unlock_wc:
+ err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx,
+ lock_abspath,
+
scratch_pool));
+ SVN_ERR(err);
+
+ return SVN_NO_ERROR;
+}
+
+/* Implements tree_conflict_get_details_func_t. */
+static svn_error_t *
+conflict_tree_get_details_update_local_moved_away(
+ svn_client_conflict_t *conflict,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *scratch_pool)
+{
+ struct conflict_tree_update_local_moved_away_details *details;
+ const char *incoming_old_repos_relpath;
+ svn_node_kind_t incoming_old_kind;
+
+ SVN_ERR(svn_client_conflict_get_incoming_old_repos_location(
+ &incoming_old_repos_relpath, NULL, &incoming_old_kind,
+ conflict, scratch_pool, scratch_pool));
+
+ details = apr_pcalloc(conflict->pool, sizeof(*details));
+
+ details->wc_move_targets = apr_array_make(conflict->pool, 1,
+ sizeof(const char *));
+
+ /* Search the WC for copies of the conflict victim. */
+ SVN_ERR(svn_wc__find_copies_of_repos_path(&details->wc_move_targets,
+ conflict->local_abspath,
+ incoming_old_repos_relpath,
+ incoming_old_kind,
+ ctx->wc_ctx,
+ conflict->pool,
+ scratch_pool));
+
+ conflict->tree_conflict_local_details = details;
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+get_both_moved_file_paths(const char **incoming_moved_to_abspath,
+ const char **local_moved_to_abspath,
+ svn_client_conflict_t *conflict,
+ apr_pool_t *scratch_pool)
+{
+ struct conflict_tree_incoming_delete_details *incoming_details;
+ apr_array_header_t *incoming_move_target_wc_abspaths;
+ svn_wc_operation_t operation;
+
+ operation = svn_client_conflict_get_operation(conflict);
+
+ *incoming_moved_to_abspath = NULL;
+ *local_moved_to_abspath = NULL;
+
+ incoming_details = conflict->tree_conflict_incoming_details;
+ if (incoming_details == NULL || incoming_details->moves == NULL ||
+ apr_hash_count(incoming_details->wc_move_targets) == 0)
+ return SVN_NO_ERROR;
+
+ incoming_move_target_wc_abspaths =
+ svn_hash_gets(incoming_details->wc_move_targets,
+ get_moved_to_repos_relpath(incoming_details,
+ scratch_pool));
+ *incoming_moved_to_abspath =
+ APR_ARRAY_IDX(incoming_move_target_wc_abspaths,
+ incoming_details->wc_move_target_idx, const char *);
+
+ if (operation == svn_wc_operation_merge)
+ {
+ struct conflict_tree_local_missing_details *local_details;
+ apr_array_header_t *local_moves;
+
+ local_details = conflict->tree_conflict_local_details;
+ if (local_details == NULL ||
+ apr_hash_count(local_details->wc_move_targets) == 0)
+ return SVN_NO_ERROR;
+
+ local_moves = svn_hash_gets(local_details->wc_move_targets,
+ local_details->move_target_repos_relpath);
+ *local_moved_to_abspath =
+ APR_ARRAY_IDX(local_moves, local_details->wc_move_target_idx,
+ const char *);
+ }
+ else
+ {
+ struct conflict_tree_update_local_moved_away_details *local_details;
+
+ local_details = conflict->tree_conflict_local_details;
+ if (local_details == NULL ||
+ local_details->wc_move_targets->nelts == 0)
+ return SVN_NO_ERROR;
+
+ *local_moved_to_abspath =
+ APR_ARRAY_IDX(local_details->wc_move_targets,
+ local_details->preferred_move_target_idx,
+ const char *);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+conflict_tree_get_description_update_both_moved_file_merge(
+ const char **description,
+ svn_client_conflict_t *conflict,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ const char *incoming_moved_to_abspath;
+ const char *local_moved_to_abspath;
+ svn_wc_operation_t operation;
+ const char *wcroot_abspath;
+
+ *description = NULL;
+
+ SVN_ERR(get_both_moved_file_paths(&incoming_moved_to_abspath,
+ &local_moved_to_abspath,
+ conflict, scratch_pool));
+ if (incoming_moved_to_abspath == NULL || local_moved_to_abspath == NULL)
+ return SVN_NO_ERROR;
+
+ SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, ctx->wc_ctx,
+ conflict->local_abspath, scratch_pool,
+ scratch_pool));
+
+ operation = svn_client_conflict_get_operation(conflict);
+
+ if (operation == svn_wc_operation_merge)
+ {
+ /* In case of a merge, the incoming move has A+ (copied) status... */
+ *description =
+ apr_psprintf(
+ scratch_pool,
+ _("apply changes to '%s' and revert addition of '%s'"),
+ svn_dirent_local_style(
+ svn_dirent_skip_ancestor(wcroot_abspath, local_moved_to_abspath),
+ scratch_pool),
+ svn_dirent_local_style(
+ svn_dirent_skip_ancestor(wcroot_abspath,
incoming_moved_to_abspath),
+ scratch_pool));
+ }
+ else
+ {
+ /* ...but in case of update/switch the local move has "A+" status. */
+ *description =
+ apr_psprintf(
+ scratch_pool,
+ _("override incoming move and merge incoming changes from '%s' "
+ "to '%s'"),
+ svn_dirent_local_style(
+ svn_dirent_skip_ancestor(wcroot_abspath,
incoming_moved_to_abspath),
+ scratch_pool),
+ svn_dirent_local_style(
+ svn_dirent_skip_ancestor(wcroot_abspath, local_moved_to_abspath),
+ scratch_pool));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+conflict_tree_get_description_update_both_moved_file_move_merge(
+ const char **description,
+ svn_client_conflict_t *conflict,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ const char *incoming_moved_to_abspath;
+ const char *local_moved_to_abspath;
+ svn_wc_operation_t operation;
+ const char *wcroot_abspath;
+
+ *description = NULL;
+
+ SVN_ERR(get_both_moved_file_paths(&incoming_moved_to_abspath,
+ &local_moved_to_abspath,
+ conflict, scratch_pool));
+ if (incoming_moved_to_abspath == NULL || local_moved_to_abspath == NULL)
+ return SVN_NO_ERROR;
+
+ SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, ctx->wc_ctx,
+ conflict->local_abspath, scratch_pool,
+ scratch_pool));
+
+ operation = svn_client_conflict_get_operation(conflict);
+
+ if (operation == svn_wc_operation_merge)
+ {
+ SVN_ERR(describe_incoming_move_merge_conflict_option(
+ description, conflict, ctx, local_moved_to_abspath,
+ scratch_pool, scratch_pool));
+ }
+ else
+ {
+ *description =
+ apr_psprintf(
+ scratch_pool,
+ _("accept incoming move and merge local changes from "
+ "'%s' to '%s'"),
+ svn_dirent_local_style(
+ svn_dirent_skip_ancestor(wcroot_abspath, local_moved_to_abspath),
+ scratch_pool),
+ svn_dirent_local_style(
+ svn_dirent_skip_ancestor(wcroot_abspath,
incoming_moved_to_abspath),
+ scratch_pool));
+ }
+
+ return SVN_NO_ERROR;
+}
+
/* Configure 'both moved file merge' resolution options for a tree conflict. */
static svn_error_t *
configure_option_both_moved_file_merge(svn_client_conflict_t *conflict,
@@ -11104,66 +11749,44 @@ configure_option_both_moved_file_merge(s
&incoming_new_kind, conflict, scratch_pool,
scratch_pool));
- if (operation == svn_wc_operation_merge &&
- victim_node_kind == svn_node_none &&
+ /* ### what about the switch operation? */
+ if (((operation == svn_wc_operation_merge &&
+ victim_node_kind == svn_node_none) ||
+ (operation == svn_wc_operation_update &&
+ victim_node_kind == svn_node_file)) &&
incoming_old_kind == svn_node_file &&
incoming_new_kind == svn_node_none &&
- local_change == svn_wc_conflict_reason_missing &&
+ ((operation == svn_wc_operation_merge &&
+ local_change == svn_wc_conflict_reason_missing) ||
+ (operation == svn_wc_operation_update &&
+ local_change == svn_wc_conflict_reason_moved_away)) &&
incoming_change == svn_wc_conflict_action_delete)
{
- struct conflict_tree_incoming_delete_details *incoming_details;
- struct conflict_tree_local_missing_details *local_details;
const char *description;
- apr_array_header_t *local_moves;
- const char *local_moved_to_abspath;
- const char *incoming_moved_to_abspath;
- apr_array_header_t *incoming_move_target_wc_abspaths;
- incoming_details = conflict->tree_conflict_incoming_details;
- if (incoming_details == NULL || incoming_details->moves == NULL ||
- apr_hash_count(incoming_details->wc_move_targets) == 0)
- return SVN_NO_ERROR;
+ SVN_ERR(conflict_tree_get_description_update_both_moved_file_merge(
+ &description, conflict, ctx, conflict->pool, scratch_pool));
- local_details = conflict->tree_conflict_local_details;
- if (local_details == NULL ||
- apr_hash_count(local_details->wc_move_targets) == 0)
- return SVN_NO_ERROR;
-
- local_moves = svn_hash_gets(local_details->wc_move_targets,
- local_details->move_target_repos_relpath);
- local_moved_to_abspath =
- APR_ARRAY_IDX(local_moves, local_details->wc_move_target_idx,
- const char *);
-
- incoming_move_target_wc_abspaths =
- svn_hash_gets(incoming_details->wc_move_targets,
- get_moved_to_repos_relpath(incoming_details,
- scratch_pool));
- incoming_moved_to_abspath =
- APR_ARRAY_IDX(incoming_move_target_wc_abspaths,
- incoming_details->wc_move_target_idx, const char *);
+ if (description == NULL) /* details not fetched yet */
+ return SVN_NO_ERROR;
- description =
- apr_psprintf(
- scratch_pool, _("apply changes to '%s' and revert addition of '%s'"),
- svn_dirent_local_style(
- svn_dirent_skip_ancestor(wcroot_abspath, local_moved_to_abspath),
- scratch_pool),
- svn_dirent_local_style(
- svn_dirent_skip_ancestor(wcroot_abspath,
incoming_moved_to_abspath),
- scratch_pool));
add_resolution_option(
options, conflict, svn_client_conflict_option_both_moved_file_merge,
_("Merge to corresponding local location"),
- description, resolve_both_moved_file_text_merge);
+ description,
+ operation == svn_wc_operation_merge ?
+ resolve_both_moved_file_text_merge :
+ resolve_both_moved_file_update_keep_local_move);
+
+ SVN_ERR(conflict_tree_get_description_update_both_moved_file_move_merge(
+ &description, conflict, ctx, conflict->pool, scratch_pool));
- SVN_ERR(describe_incoming_move_merge_conflict_option(
- &description, conflict, ctx, local_moved_to_abspath,
- scratch_pool, scratch_pool));
add_resolution_option(options, conflict,
svn_client_conflict_option_both_moved_file_move_merge,
_("Move and merge"), description,
- resolve_incoming_move_file_text_merge);
+ operation == svn_wc_operation_merge ?
+ resolve_incoming_move_file_text_merge :
+ resolve_both_moved_file_update_keep_incoming_move);
}
return SVN_NO_ERROR;
@@ -11648,6 +12271,36 @@ svn_client_conflict_option_get_moved_to_
}
}
}
+ else if ((operation == svn_wc_operation_update ||
+ operation == svn_wc_operation_switch) &&
+ incoming_change == svn_wc_conflict_action_delete &&
+ local_change == svn_wc_conflict_reason_moved_away)
+ {
+ struct conflict_tree_update_local_moved_away_details *details;
+
+ details = conflict->tree_conflict_local_details;
+ if (details == NULL || details->wc_move_targets == NULL)
+ return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
+ _("Getting a list of possible move targets "
+ "requires details for tree conflict at '%s'
"
+ "to be fetched from the repository first"),
+ svn_dirent_local_style(victim_abspath,
+ scratch_pool));
+
+ /* Return a copy of the option's move target candidate list. */
+ *possible_moved_to_abspaths =
+ apr_array_make(result_pool, details->wc_move_targets->nelts,
+ sizeof (const char *));
+ for (i = 0; i < details->wc_move_targets->nelts; i++)
+ {
+ const char *moved_to_abspath;
+
+ moved_to_abspath = APR_ARRAY_IDX(details->wc_move_targets, i,
+ const char *);
+ APR_ARRAY_PUSH(*possible_moved_to_abspaths, const char *) =
+ apr_pstrdup(result_pool, moved_to_abspath);
+ }
+ }
else
{
struct conflict_tree_incoming_delete_details *details;
@@ -11805,6 +12458,54 @@ svn_client_conflict_option_set_moved_to_
conflict->pool, scratch_pool));
}
}
+ else if ((operation == svn_wc_operation_update ||
+ operation == svn_wc_operation_switch) &&
+ incoming_change == svn_wc_conflict_action_delete &&
+ local_change == svn_wc_conflict_reason_moved_away)
+ {
+ struct conflict_tree_update_local_moved_away_details *details;
+
+ details = conflict->tree_conflict_local_details;
+ if (details == NULL || details->wc_move_targets == NULL)
+ return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
+ _("Setting a move target requires details "
+ "for tree conflict at '%s' to be fetched "
+ "from the repository first"),
+ svn_dirent_local_style(victim_abspath,
+ scratch_pool));
+
+ if (preferred_move_target_idx < 0 ||
+ preferred_move_target_idx > details->wc_move_targets->nelts)
+ return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
+ _("Index '%d' is out of bounds of the "
+ "possible move target list for '%s'"),
+ preferred_move_target_idx,
+ svn_dirent_local_style(victim_abspath,
+ scratch_pool));
+
+ /* Record the user's preference. */
+ details->preferred_move_target_idx = preferred_move_target_idx;
+
+ /* Update option description. */
+ if (id == svn_client_conflict_option_both_moved_file_merge)
+ SVN_ERR(conflict_tree_get_description_update_both_moved_file_merge(
+ &option->description, conflict, ctx, conflict->pool,
+ scratch_pool));
+ else if (id == svn_client_conflict_option_both_moved_file_move_merge)
+
SVN_ERR(conflict_tree_get_description_update_both_moved_file_move_merge(
+ &option->description, conflict, ctx, conflict->pool, scratch_pool));
+#if 0 /* ### TODO: Also handle options for directories! */
+ else if (id == svn_client_conflict_option_both_moved_dir_merge)
+ {
+ }
+ else if (id == svn_client_conflict_option_both_moved_dir_move_merge)
+ {
+ }
+#endif
+ else
+ return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
+ _("Unexpected option id '%d'"), id);
+ }
else
{
struct conflict_tree_incoming_delete_details *details;
@@ -12471,6 +13172,7 @@ conflict_type_specific_setup(svn_client_
apr_pool_t *scratch_pool)
{
svn_boolean_t tree_conflicted;
+ svn_wc_operation_t operation;
svn_wc_conflict_action_t incoming_change;
svn_wc_conflict_reason_t local_change;
@@ -12487,6 +13189,7 @@ conflict_type_specific_setup(svn_client_
conflict->tree_conflict_get_local_description_func =
conflict_tree_get_local_description_generic;
+ operation = svn_client_conflict_get_operation(conflict);
incoming_change = svn_client_conflict_get_incoming_change(conflict);
local_change = svn_client_conflict_get_local_change(conflict);
@@ -12521,6 +13224,12 @@ conflict_type_specific_setup(svn_client_
conflict->tree_conflict_get_local_details_func =
conflict_tree_get_details_local_missing;
}
+ else if (local_change == svn_wc_conflict_reason_moved_away &&
+ operation == svn_wc_operation_update /* ### what about switch? */)
+ {
+ conflict->tree_conflict_get_local_details_func =
+ conflict_tree_get_details_update_local_moved_away;
+ }
return SVN_NO_ERROR;
}
Modified: subversion/branches/shelving-v3/subversion/libsvn_client/shelf.c
URL:
http://svn.apache.org/viewvc/subversion/branches/shelving-v3/subversion/libsvn_client/shelf.c?rev=1853900&r1=1853899&r2=1853900&view=diff
==============================================================================
--- subversion/branches/shelving-v3/subversion/libsvn_client/shelf.c (original)
+++ subversion/branches/shelving-v3/subversion/libsvn_client/shelf.c Tue Feb 19
17:10:11 2019
@@ -114,6 +114,28 @@ shelf_name_from_filename(char **name,
return SVN_NO_ERROR;
}
+/* Set *DIR to the shelf storage directory inside the WC's administrative
+ * area. Ensure the directory exists. */
+static svn_error_t *
+get_shelves_dir(char **dir,
+ svn_wc_context_t *wc_ctx,
+ const char *local_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ char *experimental_abspath;
+
+ SVN_ERR(svn_wc__get_experimental_dir(&experimental_abspath,
+ wc_ctx, local_abspath,
+ scratch_pool, scratch_pool));
+ *dir = svn_dirent_join(experimental_abspath, "shelves/v3", result_pool);
+
+ /* Ensure the directory exists. (Other versions of svn don't create it.) */
+ SVN_ERR(svn_io_make_dir_recursively(*dir, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
/* Set *ABSPATH to the abspath of the file storage dir for SHELF
* version VERSION, no matter whether it exists.
*/
@@ -522,33 +544,6 @@ svn_client__shelf_version_status_walk(sv
/*-------------------------------------------------------------------------*/
/* Shelf Storage */
-/* Get the WC root and corresponding shelves dir.
- *
- * ### Presently, this returns a shelves dir OUTSIDE the WC; this is a
- * (temporary) convenience for shelf_copy_base() which would need to be
- * smarter if it were inside '.svn'.
- */
-static svn_error_t *
-get_shelves_dir(const char **wc_root_abspath_p,
- char **shelves_dir_abspath_p,
- const char *local_abspath,
- svn_client_ctx_t *ctx,
- apr_pool_t *result_pool)
-{
- SVN_ERR(svn_client_get_wc_root(wc_root_abspath_p,
- local_abspath, ctx,
- result_pool, result_pool));
- /*SVN_ERR(svn_wc__get_shelves_dir(shelves_dir_abspath_p,
- ctx->wc_ctx, local_abspath,
- result_pool, result_pool));*/
- *shelves_dir_abspath_p = apr_pstrcat(result_pool,
- *wc_root_abspath_p, ".shelves",
- SVN_VA_NULL);
- /* Ensure the directory exists. */
- SVN_ERR(svn_io_make_dir_recursively(*shelves_dir_abspath_p, result_pool));
- return SVN_NO_ERROR;
-}
-
/* Construct a shelf object representing an empty shelf: no versions,
* no revprops, no looking to see if such a shelf exists on disk.
*/
@@ -562,8 +557,11 @@ shelf_construct(svn_client__shelf_t **sh
svn_client__shelf_t *shelf = apr_palloc(result_pool, sizeof(*shelf));
char *shelves_dir;
- SVN_ERR(get_shelves_dir(&shelf->wc_root_abspath, &shelves_dir,
- local_abspath, ctx, result_pool));
+ SVN_ERR(svn_client_get_wc_root(&shelf->wc_root_abspath,
+ local_abspath, ctx,
+ result_pool, result_pool));
+ SVN_ERR(get_shelves_dir(&shelves_dir, ctx->wc_ctx, local_abspath,
+ result_pool, result_pool));
shelf->shelves_dir = shelves_dir;
shelf->ctx = ctx;
shelf->pool = result_pool;
@@ -1184,8 +1182,10 @@ svn_client__shelf_list(apr_hash_t **shel
apr_hash_t *dirents;
apr_hash_index_t *hi;
- SVN_ERR(get_shelves_dir(&wc_root_abspath, &shelves_dir,
- local_abspath, ctx, scratch_pool));
+ SVN_ERR(svn_wc__get_wcroot(&wc_root_abspath, ctx->wc_ctx, local_abspath,
+ scratch_pool, scratch_pool));
+ SVN_ERR(get_shelves_dir(&shelves_dir, ctx->wc_ctx, local_abspath,
+ scratch_pool, scratch_pool));
SVN_ERR(svn_io_get_dirents3(&dirents, shelves_dir, FALSE /*only_check_type*/,
result_pool, scratch_pool));
Modified: subversion/branches/shelving-v3/subversion/libsvn_repos/dump.c
URL:
http://svn.apache.org/viewvc/subversion/branches/shelving-v3/subversion/libsvn_repos/dump.c?rev=1853900&r1=1853899&r2=1853900&view=diff
==============================================================================
--- subversion/branches/shelving-v3/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/shelving-v3/subversion/libsvn_repos/dump.c Tue Feb 19
17:10:11 2019
@@ -44,6 +44,7 @@
#include "private/svn_sorts_private.h"
#include "private/svn_utf_private.h"
#include "private/svn_cache.h"
+#include "private/svn_fspath.h"
#define ARE_VALID_COPY_ARGS(p,r) ((p) && SVN_IS_VALID_REVNUM(r))
@@ -1996,6 +1997,11 @@ dump_filter_authz_func(svn_boolean_t *al
{
dump_filter_baton_t *b = baton;
+ /* For some nodes (e.g. files under copied directory) PATH may be
+ * non-canonical (missing leading '/'). Canonicalize PATH before
+ * passing it to FILTER_FUNC. */
+ path = svn_fspath__canonicalize(path, pool);
+
return svn_error_trace(b->filter_func(allowed, root, path, b->filter_baton,
pool));
}
Modified: subversion/branches/shelving-v3/subversion/libsvn_subr/error.c
URL:
http://svn.apache.org/viewvc/subversion/branches/shelving-v3/subversion/libsvn_subr/error.c?rev=1853900&r1=1853899&r2=1853900&view=diff
==============================================================================
--- subversion/branches/shelving-v3/subversion/libsvn_subr/error.c (original)
+++ subversion/branches/shelving-v3/subversion/libsvn_subr/error.c Tue Feb 19
17:10:11 2019
@@ -146,6 +146,7 @@ svn_error__locate(const char *file, long
/* Cleanup function for errors. svn_error_clear () removes this so
errors that are properly handled *don't* hit this code. */
+#ifdef SVN_DEBUG
static apr_status_t err_abort(void *data)
{
svn_error_t *err = data; /* For easy viewing in a debugger */
@@ -155,6 +156,7 @@ static apr_status_t err_abort(void *data
abort();
return APR_SUCCESS;
}
+#endif
static svn_error_t *
Modified: subversion/branches/shelving-v3/subversion/libsvn_wc/node.c
URL:
http://svn.apache.org/viewvc/subversion/branches/shelving-v3/subversion/libsvn_wc/node.c?rev=1853900&r1=1853899&r2=1853900&view=diff
==============================================================================
--- subversion/branches/shelving-v3/subversion/libsvn_wc/node.c (original)
+++ subversion/branches/shelving-v3/subversion/libsvn_wc/node.c Tue Feb 19
17:10:11 2019
@@ -1140,3 +1140,17 @@ svn_wc__find_working_nodes_with_basename
abspaths, wc_ctx->db, wri_abspath, basename, kind,
result_pool, scratch_pool));
}
+
+svn_error_t *
+svn_wc__find_copies_of_repos_path(apr_array_header_t **abspaths,
+ const char *wri_abspath,
+ const char *repos_relpath,
+ svn_node_kind_t kind,
+ svn_wc_context_t *wc_ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ return svn_error_trace(svn_wc__db_find_copies_of_repos_path(
+ abspaths, wc_ctx->db, wri_abspath, repos_relpath,
+ kind, result_pool, scratch_pool));
+}
Modified: subversion/branches/shelving-v3/subversion/libsvn_wc/wc-queries.sql
URL:
http://svn.apache.org/viewvc/subversion/branches/shelving-v3/subversion/libsvn_wc/wc-queries.sql?rev=1853900&r1=1853899&r2=1853900&view=diff
==============================================================================
--- subversion/branches/shelving-v3/subversion/libsvn_wc/wc-queries.sql
(original)
+++ subversion/branches/shelving-v3/subversion/libsvn_wc/wc-queries.sql Tue Feb
19 17:10:11 2019
@@ -1796,6 +1796,17 @@ WHERE wc_id = ?1
SELECT 1 FROM sqlite_master WHERE name='sqlite_stat1' AND type='table'
LIMIT 1
+-- STMT_SELECT_COPIES_OF_REPOS_RELPATH
+SELECT local_relpath
+FROM nodes n
+WHERE wc_id = ?1 AND repos_path = ?2 AND kind = ?3
+ AND presence = MAP_NORMAL
+ AND op_depth = (SELECT MAX(op_depth)
+ FROM NODES w
+ WHERE w.wc_id = ?1
+ AND w.local_relpath = n.local_relpath)
+ORDER BY local_relpath ASC
+
/* ------------------------------------------------------------------------- */
/* Grab all the statements related to the schema. */
Modified: subversion/branches/shelving-v3/subversion/libsvn_wc/wc_db.c
URL:
http://svn.apache.org/viewvc/subversion/branches/shelving-v3/subversion/libsvn_wc/wc_db.c?rev=1853900&r1=1853899&r2=1853900&view=diff
==============================================================================
--- subversion/branches/shelving-v3/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/shelving-v3/subversion/libsvn_wc/wc_db.c Tue Feb 19
17:10:11 2019
@@ -16663,3 +16663,47 @@ svn_wc__db_find_working_nodes_with_basen
return svn_error_trace(svn_sqlite__reset(stmt));
}
+
+svn_error_t *
+svn_wc__db_find_copies_of_repos_path(apr_array_header_t **local_abspaths,
+ svn_wc__db_t *db,
+ const char *wri_abspath,
+ const char *repos_relpath,
+ svn_node_kind_t kind,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_wcroot_t *wcroot;
+ const char *wri_relpath;
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
+
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
+
+ SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &wri_relpath, db,
+ wri_abspath, scratch_pool,
+ scratch_pool));
+ VERIFY_USABLE_WCROOT(wcroot);
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_SELECT_COPIES_OF_REPOS_RELPATH));
+ SVN_ERR(svn_sqlite__bindf(stmt, "ist", wcroot->wc_id, repos_relpath,
+ kind_map, kind));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+ *local_abspaths = apr_array_make(result_pool, 1, sizeof(const char *));
+
+ while (have_row)
+ {
+ const char *local_relpath;
+ const char *local_abspath;
+
+ local_relpath = svn_sqlite__column_text(stmt, 0, NULL);
+ local_abspath = svn_dirent_join(wcroot->abspath, local_relpath,
+ result_pool);
+ APR_ARRAY_PUSH(*local_abspaths, const char *) = local_abspath;
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ }
+
+ return svn_error_trace(svn_sqlite__reset(stmt));
+}
Modified: subversion/branches/shelving-v3/subversion/libsvn_wc/wc_db.h
URL:
http://svn.apache.org/viewvc/subversion/branches/shelving-v3/subversion/libsvn_wc/wc_db.h?rev=1853900&r1=1853899&r2=1853900&view=diff
==============================================================================
--- subversion/branches/shelving-v3/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/shelving-v3/subversion/libsvn_wc/wc_db.h Tue Feb 19
17:10:11 2019
@@ -3520,6 +3520,24 @@ svn_wc__db_find_working_nodes_with_basen
svn_node_kind_t kind,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
+
+/* Return an array of const char * elements, which represent local absolute
+ * paths for nodes, within the working copy indicated by WRI_ABSPATH, which
+ * are copies of REPOS_RELPATH and have node kind KIND.
+ * If no such nodes exist, return an empty array.
+ *
+ * This function returns only paths to nodes which are present in the highest
+ * layer of the WC. In other words, paths to deleted and/or excluded nodes are
+ * never returned.
+ */
+svn_error_t *
+svn_wc__db_find_copies_of_repos_path(apr_array_header_t **local_abspaths,
+ svn_wc__db_t *db,
+ const char *wri_abspath,
+ const char *repos_relpath,
+ svn_node_kind_t kind,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
/* @} */
typedef svn_error_t * (*svn_wc__db_verify_cb_t)(void *baton,
Modified: subversion/branches/shelving-v3/subversion/libsvn_wc/wcroot_anchor.c
URL:
http://svn.apache.org/viewvc/subversion/branches/shelving-v3/subversion/libsvn_wc/wcroot_anchor.c?rev=1853900&r1=1853899&r2=1853900&view=diff
==============================================================================
--- subversion/branches/shelving-v3/subversion/libsvn_wc/wcroot_anchor.c
(original)
+++ subversion/branches/shelving-v3/subversion/libsvn_wc/wcroot_anchor.c Tue
Feb 19 17:10:11 2019
@@ -183,21 +183,20 @@ svn_wc__get_wcroot(const char **wcroot_a
svn_error_t *
-svn_wc__get_shelves_dir(char **dir,
- svn_wc_context_t *wc_ctx,
- const char *local_abspath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
+svn_wc__get_experimental_dir(char **dir,
+ svn_wc_context_t *wc_ctx,
+ const char *local_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
const char *wcroot_abspath;
SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, wc_ctx, local_abspath,
scratch_pool, scratch_pool));
*dir = svn_dirent_join(wcroot_abspath,
- SVN_WC_ADM_DIR_NAME "/" SVN_WC__ADM_EXPERIMENTAL "/"
- "shelves/v2",
+ SVN_WC_ADM_DIR_NAME "/" SVN_WC__ADM_EXPERIMENTAL,
result_pool);
-
+
/* Ensure the directory exists. (Other versions of svn don't create it.) */
SVN_ERR(svn_io_make_dir_recursively(*dir, scratch_pool));
Modified:
subversion/branches/shelving-v3/subversion/tests/cmdline/svnadmin_tests.py
URL:
http://svn.apache.org/viewvc/subversion/branches/shelving-v3/subversion/tests/cmdline/svnadmin_tests.py?rev=1853900&r1=1853899&r2=1853900&view=diff
==============================================================================
--- subversion/branches/shelving-v3/subversion/tests/cmdline/svnadmin_tests.py
(original)
+++ subversion/branches/shelving-v3/subversion/tests/cmdline/svnadmin_tests.py
Tue Feb 19 17:10:11 2019
@@ -3920,6 +3920,51 @@ def recover_prunes_rep_cache_when_disabl
check_recover_prunes_rep_cache(sbox, enable_rep_sharing=False)
+@Issue(4760)
+def dump_include_copied_directory(sbox):
+ "include copied directory with nested nodes"
+
+ sbox.build(create_wc=False)
+
+ svntest.actions.run_and_verify_svn(svntest.verify.AnyOutput, [], "copy",
+ sbox.repo_url + '/A/D',
+ sbox.repo_url + '/COPY',
+ "-m", "Create branch.")
+
+ # Dump repository with only /COPY path included.
+ _, dump, _ = svntest.actions.run_and_verify_svnadmin(None, [],
+ 'dump', '-q',
+ '--include', '/COPY',
+ sbox.repo_dir)
+
+ # Load repository from dump.
+ sbox2 = sbox.clone_dependent()
+ sbox2.build(create_wc=False, empty=True)
+ load_and_verify_dumpstream(sbox2, None, [], None, False, dump)
+
+ # Check log.
+ expected_output = svntest.verify.RegexListOutput([
+ '-+\\n',
+ 'r2\ .*\n',
+ # Only '/COPY' is added
+ re.escape('Changed paths:\n'),
+ re.escape(' A /COPY'),
+ re.escape(' A /COPY/G'),
+ re.escape(' A /COPY/G/pi'),
+ re.escape(' A /COPY/G/rho'),
+ re.escape(' A /COPY/G/tau'),
+ re.escape(' A /COPY/H'),
+ re.escape(' A /COPY/H/chi'),
+ re.escape(' A /COPY/H/omega'),
+ re.escape(' A /COPY/H/psi'),
+ re.escape(' A /COPY/gamma'),
+ '-+\\n',
+ 'r1\ .*\n',
+ '-+\\n'
+ ])
+ svntest.actions.run_and_verify_svn(expected_output, [],
+ 'log', '-v', '-q', sbox2.repo_url)
+
########################################################################
# Run the tests
@@ -3997,6 +4042,7 @@ test_list = [ None,
dump_no_canonicalize_svndate,
recover_prunes_rep_cache_when_enabled,
recover_prunes_rep_cache_when_disabled,
+ dump_include_copied_directory,
]
if __name__ == '__main__':
Modified:
subversion/branches/shelving-v3/subversion/tests/cmdline/svntest/sandbox.py
URL:
http://svn.apache.org/viewvc/subversion/branches/shelving-v3/subversion/tests/cmdline/svntest/sandbox.py?rev=1853900&r1=1853899&r2=1853900&view=diff
==============================================================================
--- subversion/branches/shelving-v3/subversion/tests/cmdline/svntest/sandbox.py
(original)
+++ subversion/branches/shelving-v3/subversion/tests/cmdline/svntest/sandbox.py
Tue Feb 19 17:10:11 2019
@@ -162,8 +162,6 @@ class Sandbox:
self._ensure_authz()
svntest.actions.make_repo_and_wc(self, create_wc, read_only, empty,
minor_version, tree)
- if create_wc:
- self.add_test_path(self.wc_dir + '.shelves')
self._is_built = True
def _ensure_authz(self):
Modified:
subversion/branches/shelving-v3/subversion/tests/libsvn_client/conflicts-test.c
URL:
http://svn.apache.org/viewvc/subversion/branches/shelving-v3/subversion/tests/libsvn_client/conflicts-test.c?rev=1853900&r1=1853899&r2=1853900&view=diff
==============================================================================
---
subversion/branches/shelving-v3/subversion/tests/libsvn_client/conflicts-test.c
(original)
+++
subversion/branches/shelving-v3/subversion/tests/libsvn_client/conflicts-test.c
Tue Feb 19 17:10:11 2019
@@ -7197,6 +7197,268 @@ test_merge_dir_move_vs_dir_move_accept_m
return SVN_NO_ERROR;
}
+static svn_error_t *
+create_file_move_vs_file_move_update_conflict(svn_client_conflict_t **conflict,
+ svn_test__sandbox_t *b,
+ svn_client_ctx_t *ctx)
+{
+ apr_array_header_t *options;
+ svn_client_conflict_option_t *option;
+ apr_array_header_t *possible_moved_to_abspaths;
+
+ /* Move a file. */
+ SVN_ERR(sbox_wc_move(b, "A/mu", "A/mu-moved"));
+
+ /* Edit moved file. */
+ SVN_ERR(sbox_file_write(b, "A/mu-moved", modified_file_content));
+ SVN_ERR(sbox_wc_commit(b, ""));
+
+ /* Update back to r1, */
+ SVN_ERR(sbox_wc_update(b, "", 1)); /* r2 */
+
+ /* Copy the file to test handling of ambiguous moves. */
+ SVN_ERR(sbox_wc_copy(b, "A/mu", "A/mu-copied"));
+
+ /* Move the same file to a different location. */
+ SVN_ERR(sbox_wc_move(b, "A/mu", "A/mu-also-moved"));
+
+ /* Edit moved file. */
+ SVN_ERR(sbox_file_write(b, "A/mu-also-moved",
+ modified_file_in_working_copy_content));
+
+ /* Update to r2. */
+ /* This should raise an "incoming delete vs local delete" tree conflict. */
+ SVN_ERR(sbox_wc_update(b, "", SVN_INVALID_REVNUM));
+
+ SVN_ERR(svn_client_conflict_get(conflict, sbox_wc_path(b, "A/mu"),
+ ctx, b->pool, b->pool));
+ {
+ svn_client_conflict_option_id_t expected_opts[] = {
+ svn_client_conflict_option_postpone,
+ svn_client_conflict_option_accept_current_wc_state,
+ svn_client_conflict_option_incoming_delete_ignore,
+ svn_client_conflict_option_incoming_delete_accept,
+ -1 /* end of list */
+ };
+ SVN_ERR(assert_tree_conflict_options(*conflict, ctx, expected_opts,
+ b->pool));
+ }
+
+ SVN_ERR(svn_client_conflict_tree_get_details(*conflict, ctx, b->pool));
+ {
+ svn_client_conflict_option_id_t expected_opts[] = {
+ svn_client_conflict_option_postpone,
+ svn_client_conflict_option_accept_current_wc_state,
+ svn_client_conflict_option_both_moved_file_merge,
+ svn_client_conflict_option_both_moved_file_move_merge,
+ -1 /* end of list */
+ };
+ SVN_ERR(assert_tree_conflict_options(*conflict, ctx, expected_opts,
+ b->pool));
+ }
+
+ /* Check possible move destinations for the file. */
+ SVN_ERR(svn_client_conflict_tree_get_resolution_options(&options, *conflict,
+ ctx, b->pool,
+ b->pool));
+ option = svn_client_conflict_option_find_by_id(
+ options, svn_client_conflict_option_both_moved_file_merge);
+ SVN_TEST_ASSERT(option != NULL);
+
+ SVN_ERR(svn_client_conflict_option_get_moved_to_abspath_candidates(
+ &possible_moved_to_abspaths, option, b->pool, b->pool));
+
+ /* The resolver finds two possible destinations for the moved file:
+ *
+ * Possible working copy destinations for moved-away 'A/mu' are:
+ * (1): 'A/mu-also-moved'
+ * (2): 'A/mu-copied'
+ * Only one destination can be a move; the others are copies.
+ */
+ SVN_TEST_INT_ASSERT(possible_moved_to_abspaths->nelts, 2);
+ SVN_TEST_STRING_ASSERT(
+ APR_ARRAY_IDX(possible_moved_to_abspaths, 0, const char *),
+ sbox_wc_path(b, "A/mu-also-moved"));
+ SVN_TEST_STRING_ASSERT(
+ APR_ARRAY_IDX(possible_moved_to_abspaths, 1, const char *),
+ sbox_wc_path(b, "A/mu-copied"));
+
+ return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+test_update_file_move_vs_file_move(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ svn_test__sandbox_t *b = apr_palloc(pool, sizeof(*b));
+ svn_client_ctx_t *ctx;
+ svn_client_conflict_t *conflict;
+ svn_opt_revision_t opt_rev;
+ struct status_baton sb;
+ struct svn_client_status_t *status;
+ svn_stringbuf_t *buf;
+ svn_node_kind_t kind;
+ char *conflicted_content;
+
+ SVN_ERR(svn_test__sandbox_create(b, "update_file_move_vs_file_move",
+ opts, pool));
+
+ SVN_ERR(sbox_add_and_commit_greek_tree(b)); /* r1 */
+
+ SVN_ERR(svn_test__create_client_ctx(&ctx, b, b->pool));
+ SVN_ERR(create_file_move_vs_file_move_update_conflict(&conflict, b, ctx));
+
+ SVN_ERR(svn_client_conflict_tree_resolve_by_id(
+ conflict,
+ svn_client_conflict_option_both_moved_file_merge,
+ ctx, b->pool));
+
+ /* The node "A/mu" should no longer exist. */
+ SVN_TEST_ASSERT_ERROR(svn_client_conflict_get(
+ &conflict, sbox_wc_path(b, "A/mu"), ctx, pool, pool),
+ SVN_ERR_WC_PATH_NOT_FOUND);
+
+ /* The node "A/mu-moved" should now have moved to "A/mu-also-moved. */
+ SVN_ERR(svn_io_check_path(sbox_wc_path(b, "A/mu"), &kind, b->pool));
+ SVN_TEST_ASSERT(kind == svn_node_none);
+ opt_rev.kind = svn_opt_revision_working;
+ sb.result_pool = b->pool;
+ SVN_ERR(svn_client_status6(NULL, ctx, sbox_wc_path(b, "A/mu-moved"),
+ &opt_rev, svn_depth_unknown, TRUE, TRUE,
+ TRUE, TRUE, FALSE, TRUE, NULL,
+ status_func, &sb, b->pool));
+ status = sb.status;
+ SVN_TEST_ASSERT(status->kind == svn_node_file);
+ SVN_TEST_ASSERT(status->versioned);
+ SVN_TEST_ASSERT(!status->conflicted);
+ SVN_TEST_ASSERT(status->node_status == svn_wc_status_deleted);
+ SVN_TEST_ASSERT(status->text_status == svn_wc_status_normal);
+ SVN_TEST_ASSERT(status->prop_status == svn_wc_status_none);
+ SVN_TEST_ASSERT(!status->copied);
+ SVN_TEST_ASSERT(!status->switched);
+ SVN_TEST_ASSERT(!status->file_external);
+ SVN_TEST_ASSERT(status->moved_from_abspath == NULL);
+ SVN_TEST_STRING_ASSERT(status->moved_to_abspath,
+ sbox_wc_path(b, "A/mu-also-moved"));
+
+ /* Ensure that the merged file has the expected status. */
+ opt_rev.kind = svn_opt_revision_working;
+ sb.result_pool = b->pool;
+ SVN_ERR(svn_client_status6(NULL, ctx, sbox_wc_path(b, "A/mu-also-moved"),
+ &opt_rev, svn_depth_unknown, TRUE, TRUE,
+ TRUE, TRUE, FALSE, TRUE, NULL,
+ status_func, &sb, b->pool));
+ status = sb.status;
+ SVN_TEST_ASSERT(status->kind == svn_node_file);
+ SVN_TEST_ASSERT(status->versioned);
+ SVN_TEST_ASSERT(status->conflicted);
+ SVN_TEST_ASSERT(status->node_status == svn_wc_status_conflicted);
+ SVN_TEST_ASSERT(status->text_status == svn_wc_status_conflicted);
+ SVN_TEST_ASSERT(status->prop_status == svn_wc_status_none);
+ SVN_TEST_ASSERT(status->copied);
+ SVN_TEST_ASSERT(!status->switched);
+ SVN_TEST_ASSERT(!status->file_external);
+ SVN_TEST_STRING_ASSERT(status->moved_from_abspath,
+ sbox_wc_path(b, "A/mu-moved"));
+ SVN_TEST_ASSERT(status->moved_to_abspath == NULL);
+
+ /* Ensure that the moved+merged file has the expected content. */
+ SVN_ERR(svn_stringbuf_from_file2(&buf, sbox_wc_path(b, "A/mu-also-moved"),
+ b->pool));
+ conflicted_content = apr_psprintf(b->pool,
+
"<<<<<<< .working\n"
+
"%s"
+
"||||||| .old\n"
+
"This is the file 'mu'.\n"
+
"=======\n"
+
"%s"
+
">>>>>>> .new\n",
+
modified_file_in_working_copy_content,
+
modified_file_content);
+ SVN_TEST_STRING_ASSERT(buf->data, conflicted_content);
+
+ return SVN_NO_ERROR;
+}
+
+/* Same test case as above, but accept the incoming move. */
+static svn_error_t *
+test_update_file_move_vs_file_move_accept_move(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ svn_test__sandbox_t *b = apr_palloc(pool, sizeof(*b));
+ svn_client_ctx_t *ctx;
+ svn_client_conflict_t *conflict;
+ svn_opt_revision_t opt_rev;
+ struct status_baton sb;
+ struct svn_client_status_t *status;
+ svn_stringbuf_t *buf;
+ char *conflicted_content;
+
+ SVN_ERR(svn_test__sandbox_create(b,
+ "update_file_move_vs_file_move_accept_move",
+ opts, pool));
+
+ SVN_ERR(sbox_add_and_commit_greek_tree(b)); /* r1 */
+
+ SVN_ERR(svn_test__create_client_ctx(&ctx, b, b->pool));
+ SVN_ERR(create_file_move_vs_file_move_update_conflict(&conflict, b, ctx));
+
+ SVN_ERR(svn_client_conflict_tree_resolve_by_id(
+ conflict,
+ svn_client_conflict_option_both_moved_file_move_merge,
+ ctx, b->pool));
+
+ /* The node "A/mu" should no longer exist. */
+ SVN_TEST_ASSERT_ERROR(svn_client_conflict_get(
+ &conflict, sbox_wc_path(b, "A/mu"), ctx, pool, pool),
+ SVN_ERR_WC_PATH_NOT_FOUND);
+
+ /* The node "A/mu-also-moved" should not exist. */
+ SVN_TEST_ASSERT_ERROR(svn_client_conflict_get(
+ &conflict, sbox_wc_path(b, "A/mu-also-moved"), ctx,
+ pool, pool),
+ SVN_ERR_WC_PATH_NOT_FOUND);
+
+ /* Ensure that the merged file has the expected status. */
+ opt_rev.kind = svn_opt_revision_working;
+ sb.result_pool = b->pool;
+ SVN_ERR(svn_client_status6(NULL, ctx, sbox_wc_path(b, "A/mu-moved"),
+ &opt_rev, svn_depth_unknown, TRUE, TRUE,
+ TRUE, TRUE, FALSE, TRUE, NULL,
+ status_func, &sb, b->pool));
+ status = sb.status;
+ SVN_TEST_ASSERT(status->kind == svn_node_file);
+ SVN_TEST_ASSERT(status->versioned);
+ SVN_TEST_ASSERT(status->conflicted);
+ SVN_TEST_ASSERT(status->node_status == svn_wc_status_conflicted);
+ SVN_TEST_ASSERT(status->text_status == svn_wc_status_conflicted);
+ SVN_TEST_ASSERT(status->prop_status == svn_wc_status_none);
+ SVN_TEST_ASSERT(!status->copied);
+ SVN_TEST_ASSERT(!status->switched);
+ SVN_TEST_ASSERT(!status->file_external);
+ SVN_TEST_ASSERT(status->moved_from_abspath == NULL);
+ SVN_TEST_ASSERT(status->moved_to_abspath == NULL);
+
+ /* Ensure that the moved+merged file has the expected content. */
+ SVN_ERR(svn_stringbuf_from_file2(&buf, sbox_wc_path(b, "A/mu-moved"),
+ b->pool));
+ conflicted_content = apr_psprintf(b->pool,
+
"<<<<<<< .working\n" /* ### labels need fixing */
+
"%s"
+
"||||||| .old\n"
+
"This is the file 'mu'.\n"
+
"=======\n"
+
"%s"
+
">>>>>>> .new\n",
+
modified_file_content,
+
modified_file_in_working_copy_content);
+ SVN_TEST_STRING_ASSERT(buf->data, conflicted_content);
+
+ return SVN_NO_ERROR;
+}
+
+
/* ==========================================================================
*/
@@ -7321,6 +7583,10 @@ static struct svn_test_descriptor_t test
"dir move vs dir move during merge"),
SVN_TEST_OPTS_PASS(test_merge_dir_move_vs_dir_move_accept_move,
"dir move vs dir move during merge accept move"),
+ SVN_TEST_OPTS_PASS(test_update_file_move_vs_file_move,
+ "file move vs file move during update"),
+ SVN_TEST_OPTS_PASS(test_update_file_move_vs_file_move_accept_move,
+ "file move vs file move during update accept move"),
SVN_TEST_NULL
};
Modified:
subversion/branches/shelving-v3/subversion/tests/libsvn_wc/wc-queries-test.c
URL:
http://svn.apache.org/viewvc/subversion/branches/shelving-v3/subversion/tests/libsvn_wc/wc-queries-test.c?rev=1853900&r1=1853899&r2=1853900&view=diff
==============================================================================
---
subversion/branches/shelving-v3/subversion/tests/libsvn_wc/wc-queries-test.c
(original)
+++
subversion/branches/shelving-v3/subversion/tests/libsvn_wc/wc-queries-test.c
Tue Feb 19 17:10:11 2019
@@ -100,6 +100,7 @@ static const int slow_statements[] =
STMT_SELECT_UPDATE_MOVE_LIST,
STMT_FIND_REPOS_PATH_IN_WC,
STMT_SELECT_PRESENT_HIGHEST_WORKING_NODES_BY_BASENAME_AND_KIND,
+ STMT_SELECT_COPIES_OF_REPOS_RELPATH,
/* Designed as slow to avoid penalty on other queries */
STMT_SELECT_UNREFERENCED_PRISTINES,