You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2016/02/23 13:10:06 UTC
svn commit: r1731844 - in /subversion/trunk/subversion/libsvn_client:
conflicts.c resolved.c
Author: stsp
Date: Tue Feb 23 12:10:06 2016
New Revision: 1731844
URL: http://svn.apache.org/viewvc?rev=1731844&view=rev
Log:
Split the new libsvn_client conflict resolver code off into a file of its own,
leaving the legacy wc wrapper code in the old resolved.c file.
This draws a clear line between the two conflict resolver implementations,
at least inside libsvn_client (they're still somewhat mixed in libsvn_wc).
The legacy resolver was largely implemented inside libsvn_wc, with a very
thin wrapper at the client layer.
The new resolver still relies on libsvn_wc for working copy manipulation
but takes charge of all other aspects of conflict resolution.
* subversion/libsvn_client/conflicts.c: New, copied from resolved.c with the
legacy conflict code removed.
* subversion/libsvn_client/resolved.c: Keep just the legacy code here.
Added:
subversion/trunk/subversion/libsvn_client/conflicts.c
- copied, changed from r1731843, subversion/trunk/subversion/libsvn_client/resolved.c
Modified:
subversion/trunk/subversion/libsvn_client/resolved.c
Copied: subversion/trunk/subversion/libsvn_client/conflicts.c (from r1731843, subversion/trunk/subversion/libsvn_client/resolved.c)
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/conflicts.c?p2=subversion/trunk/subversion/libsvn_client/conflicts.c&p1=subversion/trunk/subversion/libsvn_client/resolved.c&r1=1731843&r2=1731844&rev=1731844&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/resolved.c (original)
+++ subversion/trunk/subversion/libsvn_client/conflicts.c Tue Feb 23 12:10:06 2016
@@ -1,5 +1,5 @@
/*
- * resolved.c: wrapper around wc resolved functionality.
+ * conflicts.c: conflict resolver implementation
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
@@ -46,110 +46,6 @@
#define ARRAY_LEN(ary) ((sizeof (ary)) / (sizeof ((ary)[0])))
-/*** Code. ***/
-
-svn_error_t *
-svn_client__resolve_conflicts(svn_boolean_t *conflicts_remain,
- apr_hash_t *conflicted_paths,
- svn_client_ctx_t *ctx,
- apr_pool_t *scratch_pool)
-{
- apr_pool_t *iterpool = svn_pool_create(scratch_pool);
- apr_array_header_t *array;
- int i;
-
- if (conflicts_remain)
- *conflicts_remain = FALSE;
-
- SVN_ERR(svn_hash_keys(&array, conflicted_paths, scratch_pool));
- svn_sort__array(array, svn_sort_compare_paths);
-
- for (i = 0; i < array->nelts; i++)
- {
- const char *local_abspath = APR_ARRAY_IDX(array, i, const char *);
-
- svn_pool_clear(iterpool);
- SVN_ERR(svn_wc__resolve_conflicts(ctx->wc_ctx, local_abspath,
- svn_depth_empty,
- TRUE /* resolve_text */,
- "" /* resolve_prop (ALL props) */,
- TRUE /* resolve_tree */,
- svn_wc_conflict_choose_unspecified,
- ctx->conflict_func2,
- ctx->conflict_baton2,
- ctx->cancel_func, ctx->cancel_baton,
- ctx->notify_func2, ctx->notify_baton2,
- iterpool));
-
- if (conflicts_remain && !*conflicts_remain)
- {
- svn_error_t *err;
- svn_boolean_t text_c, prop_c, tree_c;
-
- err = svn_wc_conflicted_p3(&text_c, &prop_c, &tree_c,
- ctx->wc_ctx, local_abspath,
- iterpool);
- if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
- {
- svn_error_clear(err);
- text_c = prop_c = tree_c = FALSE;
- }
- else
- {
- SVN_ERR(err);
- }
- if (text_c || prop_c || tree_c)
- *conflicts_remain = TRUE;
- }
- }
- svn_pool_destroy(iterpool);
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_client_resolve(const char *path,
- svn_depth_t depth,
- svn_wc_conflict_choice_t conflict_choice,
- svn_client_ctx_t *ctx,
- apr_pool_t *pool)
-{
- const char *local_abspath;
- svn_error_t *err;
- const char *lock_abspath;
-
- if (svn_path_is_url(path))
- return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
- _("'%s' is not a local path"), path);
-
- SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
-
- /* Similar to SVN_WC__CALL_WITH_WRITE_LOCK but using a custom
- locking function. */
-
- SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx,
- local_abspath, pool, pool));
- err = svn_wc__resolve_conflicts(ctx->wc_ctx, local_abspath,
- depth,
- TRUE /* resolve_text */,
- "" /* resolve_prop (ALL props) */,
- TRUE /* resolve_tree */,
- conflict_choice,
- ctx->conflict_func2,
- ctx->conflict_baton2,
- ctx->cancel_func, ctx->cancel_baton,
- ctx->notify_func2, ctx->notify_baton2,
- pool);
-
- err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx,
- lock_abspath,
- pool));
- svn_io_sleep_for_timestamps(path, pool);
-
- return svn_error_trace(err);
-}
-
-
/*** Dealing with conflicts. ***/
struct svn_client_conflict_t
Modified: subversion/trunk/subversion/libsvn_client/resolved.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/resolved.c?rev=1731844&r1=1731843&r2=1731844&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/resolved.c (original)
+++ subversion/trunk/subversion/libsvn_client/resolved.c Tue Feb 23 12:10:06 2016
@@ -1,5 +1,5 @@
/*
- * resolved.c: wrapper around wc resolved functionality.
+ * resolved.c: wrapper around Subversion <=1.9 wc resolved functionality
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
@@ -38,13 +38,10 @@
#include "svn_sorts.h"
#include "client.h"
#include "private/svn_sorts_private.h"
-#include "private/svn_token.h"
#include "private/svn_wc_private.h"
#include "svn_private_config.h"
-#define ARRAY_LEN(ary) ((sizeof (ary)) / (sizeof ((ary)[0])))
-
/*** Code. ***/
@@ -148,1673 +145,3 @@ svn_client_resolve(const char *path,
return svn_error_trace(err);
}
-
-
-/*** Dealing with conflicts. ***/
-
-struct svn_client_conflict_t
-{
- const char *local_abspath;
- svn_client_ctx_t *ctx;
- apr_hash_t *prop_conflicts;
-
- /* Indicate which options were chosen to resolve a text or tree conflict
- * on the conflited node. */
- svn_client_conflict_option_id_t resolution_text;
- svn_client_conflict_option_id_t resolution_tree;
-
- /* A mapping from const char* property name to pointers to
- * svn_client_conflict_option_t for all properties which had their
- * conflicts resolved. Indicates which options were chosen to resolve
- * the property conflicts. */
- apr_hash_t *resolved_props;
-
- /* For backwards compat. */
- const svn_wc_conflict_description2_t *legacy_text_conflict;
- const char *legacy_prop_conflict_propname;
- const svn_wc_conflict_description2_t *legacy_tree_conflict;
-};
-
-/* Resolves conflict to OPTION and sets CONFLICT->RESOLUTION accordingly.
- *
- * May raise an error in case the conflict could not be resolved. A common
- * case would be a tree conflict the resolution of which depends on other
- * tree conflicts to be resolved first. */
-typedef svn_error_t *(*conflict_option_resolve_func_t)(
- svn_client_conflict_option_t *option,
- svn_client_conflict_t *conflict,
- apr_pool_t *scratch_pool);
-
-struct svn_client_conflict_option_t
-{
- svn_client_conflict_option_id_t id;
- const char *description;
-
- svn_client_conflict_t *conflict;
- conflict_option_resolve_func_t do_resolve_func;
-
- /* Data which is specific to particular conflicts and options. */
- union {
- struct {
- /* Indicates the property to resolve in case of a property conflict.
- * If set to "", all properties are resolved to this option. */
- const char *propname;
-
- /* A merged property value, if supplied by the API user, else NULL. */
- const svn_string_t *merged_propval;
- } prop;
- } type_data;
-
-};
-
-/*
- * Return a legacy conflict choice corresponding to OPTION_ID.
- * Return svn_wc_conflict_choose_undefined if no corresponding
- * legacy conflict choice exists.
- */
-svn_wc_conflict_choice_t
-svn_client_conflict_option_id_to_wc_conflict_choice(
- svn_client_conflict_option_id_t option_id)
-{
-
- switch (option_id)
- {
- case svn_client_conflict_option_undefined:
- return svn_wc_conflict_choose_undefined;
-
- case svn_client_conflict_option_postpone:
- return svn_wc_conflict_choose_postpone;
-
- case svn_client_conflict_option_base_text:
- return svn_wc_conflict_choose_base;
-
- case svn_client_conflict_option_incoming_text:
- return svn_wc_conflict_choose_theirs_full;
-
- case svn_client_conflict_option_working_text:
- return svn_wc_conflict_choose_mine_full;
-
- case svn_client_conflict_option_incoming_text_where_conflicted:
- return svn_wc_conflict_choose_theirs_conflict;
-
- case svn_client_conflict_option_working_text_where_conflicted:
- return svn_wc_conflict_choose_mine_conflict;
-
- case svn_client_conflict_option_merged_text:
- return svn_wc_conflict_choose_merged;
-
- case svn_client_conflict_option_unspecified:
- return svn_wc_conflict_choose_unspecified;
-
- /* ### These options are mapped to conflict_choice_t for now
- * ### because libsvn_wc does not offer an interface for them. */
- case svn_client_conflict_option_update_move_destination:
- case svn_client_conflict_option_update_any_moved_away_children:
- return svn_wc_conflict_choose_mine_conflict;
-
- default:
- break;
- }
-
- return svn_wc_conflict_choose_undefined;
-}
-
-static void
-add_legacy_desc_to_conflict(const svn_wc_conflict_description2_t *desc,
- svn_client_conflict_t *conflict,
- apr_pool_t *result_pool)
-{
- switch (desc->kind)
- {
- case svn_wc_conflict_kind_text:
- conflict->legacy_text_conflict = desc;
- break;
-
- case svn_wc_conflict_kind_property:
- if (conflict->prop_conflicts == NULL)
- conflict->prop_conflicts = apr_hash_make(result_pool);
- svn_hash_sets(conflict->prop_conflicts, desc->property_name, desc);
- conflict->legacy_prop_conflict_propname = desc->property_name;
- break;
-
- case svn_wc_conflict_kind_tree:
- conflict->legacy_tree_conflict = desc;
- break;
-
- default:
- SVN_ERR_ASSERT_NO_RETURN(FALSE); /* unknown kind of conflict */
- }
-}
-
-/* Set up a conflict object. If legacy conflict descriptor DESC is not NULL,
- * set up the conflict object for backwards compatibility. */
-static svn_error_t *
-conflict_get_internal(svn_client_conflict_t **conflict,
- const char *local_abspath,
- const svn_wc_conflict_description2_t *desc,
- svn_client_ctx_t *ctx,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- const apr_array_header_t *descs;
- int i;
-
- *conflict = apr_pcalloc(result_pool, sizeof(**conflict));
-
- if (desc)
- {
- /* Add a single legacy conflict descriptor. */
- (*conflict)->local_abspath = desc->local_abspath;
- (*conflict)->resolution_text = svn_client_conflict_option_unspecified;
- (*conflict)->resolution_tree = svn_client_conflict_option_unspecified;
- (*conflict)->resolved_props = apr_hash_make(result_pool);
- add_legacy_desc_to_conflict(desc, *conflict, result_pool);
-
- return SVN_NO_ERROR;
- }
-
- (*conflict)->local_abspath = apr_pstrdup(result_pool, local_abspath);
- (*conflict)->resolution_text = svn_client_conflict_option_unspecified;
- (*conflict)->resolution_tree = svn_client_conflict_option_unspecified;
- (*conflict)->resolved_props = apr_hash_make(result_pool);
- (*conflict)->ctx = ctx;
-
- /* Add all legacy conflict descriptors we can find. Eventually, this code
- * path should stop relying on svn_wc_conflict_description2_t entirely. */
- SVN_ERR(svn_wc__read_conflict_descriptions2_t(&descs, ctx->wc_ctx,
- local_abspath,
- result_pool, scratch_pool));
- for (i = 0; i < descs->nelts; i++)
- {
- desc = APR_ARRAY_IDX(descs, i, const svn_wc_conflict_description2_t *);
- add_legacy_desc_to_conflict(desc, *conflict, result_pool);
- }
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_client_conflict_get(svn_client_conflict_t **conflict,
- const char *local_abspath,
- svn_client_ctx_t *ctx,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- return svn_error_trace(conflict_get_internal(conflict, local_abspath, NULL,
- ctx, result_pool, scratch_pool));
-}
-
-svn_error_t *
-svn_client_conflict_from_wc_description2_t(
- svn_client_conflict_t **conflict,
- const svn_wc_conflict_description2_t *desc,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- return svn_error_trace(conflict_get_internal(conflict, NULL, desc, NULL,
- result_pool, scratch_pool));
-}
-
-/* A map for svn_wc_conflict_action_t values to strings */
-static const svn_token_map_t map_conflict_action[] =
-{
- { "edit", svn_wc_conflict_action_edit },
- { "delete", svn_wc_conflict_action_delete },
- { "add", svn_wc_conflict_action_add },
- { "replace", svn_wc_conflict_action_replace },
- { NULL, 0 }
-};
-
-/* A map for svn_wc_conflict_reason_t values to strings */
-static const svn_token_map_t map_conflict_reason[] =
-{
- { "edit", svn_wc_conflict_reason_edited },
- { "delete", svn_wc_conflict_reason_deleted },
- { "missing", svn_wc_conflict_reason_missing },
- { "obstruction", svn_wc_conflict_reason_obstructed },
- { "add", svn_wc_conflict_reason_added },
- { "replace", svn_wc_conflict_reason_replaced },
- { "unversioned", svn_wc_conflict_reason_unversioned },
- { "moved-away", svn_wc_conflict_reason_moved_away },
- { "moved-here", svn_wc_conflict_reason_moved_here },
- { NULL, 0 }
-};
-
-/* Return a localised string representation of the local part of a conflict;
- NULL for non-localised odd cases. */
-static const char *
-local_reason_str(svn_node_kind_t kind, svn_wc_conflict_reason_t reason,
- svn_wc_operation_t operation)
-{
- switch (kind)
- {
- case svn_node_file:
- case svn_node_symlink:
- switch (reason)
- {
- case svn_wc_conflict_reason_edited:
- return _("local file edit");
- case svn_wc_conflict_reason_obstructed:
- return _("local file obstruction");
- case svn_wc_conflict_reason_deleted:
- return _("local file delete");
- case svn_wc_conflict_reason_missing:
- if (operation == svn_wc_operation_merge)
- return _("local file missing or deleted or moved away");
- else
- return _("local file missing");
- case svn_wc_conflict_reason_unversioned:
- return _("local file unversioned");
- case svn_wc_conflict_reason_added:
- return _("local file add");
- case svn_wc_conflict_reason_replaced:
- return _("local file replace");
- case svn_wc_conflict_reason_moved_away:
- return _("local file moved away");
- case svn_wc_conflict_reason_moved_here:
- return _("local file moved here");
- }
- break;
- case svn_node_dir:
- switch (reason)
- {
- case svn_wc_conflict_reason_edited:
- return _("local dir edit");
- case svn_wc_conflict_reason_obstructed:
- return _("local dir obstruction");
- case svn_wc_conflict_reason_deleted:
- return _("local dir delete");
- case svn_wc_conflict_reason_missing:
- if (operation == svn_wc_operation_merge)
- return _("local dir missing or deleted or moved away");
- else
- return _("local dir missing");
- case svn_wc_conflict_reason_unversioned:
- return _("local dir unversioned");
- case svn_wc_conflict_reason_added:
- return _("local dir add");
- case svn_wc_conflict_reason_replaced:
- return _("local dir replace");
- case svn_wc_conflict_reason_moved_away:
- return _("local dir moved away");
- case svn_wc_conflict_reason_moved_here:
- return _("local dir moved here");
- }
- break;
- case svn_node_none:
- case svn_node_unknown:
- switch (reason)
- {
- case svn_wc_conflict_reason_edited:
- return _("local edit");
- case svn_wc_conflict_reason_obstructed:
- return _("local obstruction");
- case svn_wc_conflict_reason_deleted:
- return _("local delete");
- case svn_wc_conflict_reason_missing:
- if (operation == svn_wc_operation_merge)
- return _("local missing or deleted or moved away");
- else
- return _("local missing");
- case svn_wc_conflict_reason_unversioned:
- return _("local unversioned");
- case svn_wc_conflict_reason_added:
- return _("local add");
- case svn_wc_conflict_reason_replaced:
- return _("local replace");
- case svn_wc_conflict_reason_moved_away:
- return _("local moved away");
- case svn_wc_conflict_reason_moved_here:
- return _("local moved here");
- }
- break;
- }
- return NULL;
-}
-
-/* Return a localised string representation of the incoming part of a
- conflict; NULL for non-localised odd cases. */
-static const char *
-incoming_action_str(svn_node_kind_t kind, svn_wc_conflict_action_t action)
-{
- switch (kind)
- {
- case svn_node_file:
- case svn_node_symlink:
- switch (action)
- {
- case svn_wc_conflict_action_edit:
- return _("incoming file edit");
- case svn_wc_conflict_action_add:
- return _("incoming file add");
- case svn_wc_conflict_action_delete:
- return _("incoming file delete or move");
- case svn_wc_conflict_action_replace:
- return _("incoming replace with file");
- }
- break;
- case svn_node_dir:
- switch (action)
- {
- case svn_wc_conflict_action_edit:
- return _("incoming dir edit");
- case svn_wc_conflict_action_add:
- return _("incoming dir add");
- case svn_wc_conflict_action_delete:
- return _("incoming dir delete or move");
- case svn_wc_conflict_action_replace:
- return _("incoming replace with dir");
- }
- break;
- case svn_node_none:
- case svn_node_unknown:
- switch (action)
- {
- case svn_wc_conflict_action_edit:
- return _("incoming edit");
- case svn_wc_conflict_action_add:
- return _("incoming add");
- case svn_wc_conflict_action_delete:
- return _("incoming delete or move");
- case svn_wc_conflict_action_replace:
- return _("incoming replace");
- }
- break;
- }
- return NULL;
-}
-
-/* Return a localised string representation of the operation part of a
- conflict. */
-static const char *
-operation_str(svn_wc_operation_t operation)
-{
- switch (operation)
- {
- case svn_wc_operation_update: return _("upon update");
- case svn_wc_operation_switch: return _("upon switch");
- case svn_wc_operation_merge: return _("upon merge");
- case svn_wc_operation_none: return _("upon none");
- }
- SVN_ERR_MALFUNCTION_NO_RETURN();
- return NULL;
-}
-
-svn_error_t *
-svn_client_conflict_prop_get_description(const char **description,
- svn_client_conflict_t *conflict,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- const char *reason_str, *action_str;
-
- /* We provide separately translatable strings for the values that we
- * know about, and a fall-back in case any other values occur. */
- switch (svn_client_conflict_get_local_change(conflict))
- {
- case svn_wc_conflict_reason_edited:
- reason_str = _("local edit");
- break;
- case svn_wc_conflict_reason_added:
- reason_str = _("local add");
- break;
- case svn_wc_conflict_reason_deleted:
- reason_str = _("local delete");
- break;
- case svn_wc_conflict_reason_obstructed:
- reason_str = _("local obstruction");
- break;
- default:
- reason_str = apr_psprintf(
- scratch_pool, _("local %s"),
- svn_token__to_word(
- map_conflict_reason,
- svn_client_conflict_get_local_change(conflict)));
- break;
- }
- switch (svn_client_conflict_get_incoming_change(conflict))
- {
- case svn_wc_conflict_action_edit:
- action_str = _("incoming edit");
- break;
- case svn_wc_conflict_action_add:
- action_str = _("incoming add");
- break;
- case svn_wc_conflict_action_delete:
- action_str = _("incoming delete");
- break;
- default:
- action_str = apr_psprintf(
- scratch_pool, _("incoming %s"),
- svn_token__to_word(
- map_conflict_action,
- svn_client_conflict_get_incoming_change(conflict)));
- break;
- }
- SVN_ERR_ASSERT(reason_str && action_str);
-
- *description = apr_psprintf(result_pool, _("%s, %s %s"),
- reason_str, action_str,
- operation_str(
- svn_client_conflict_get_operation(conflict)));
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_client_conflict_tree_get_description(const char **description,
- svn_client_conflict_t *conflict,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- const char *action, *reason, *operation;
- svn_node_kind_t incoming_kind;
- svn_wc_conflict_action_t conflict_action;
- svn_wc_conflict_reason_t conflict_reason;
- svn_wc_operation_t conflict_operation;
- svn_node_kind_t conflict_node_kind;
-
- conflict_action = svn_client_conflict_get_incoming_change(conflict);
- conflict_reason = svn_client_conflict_get_local_change(conflict);
- conflict_operation = svn_client_conflict_get_operation(conflict);
- conflict_node_kind = svn_client_conflict_tree_get_victim_node_kind(conflict);
-
- /* Determine the node kind of the incoming change. */
- incoming_kind = svn_node_unknown;
- if (conflict_action == svn_wc_conflict_action_edit ||
- conflict_action == svn_wc_conflict_action_delete)
- {
- /* Change is acting on 'src_left' version of the node. */
- SVN_ERR(svn_client_conflict_get_incoming_old_repos_location(
- NULL, NULL, &incoming_kind, conflict, scratch_pool,
- scratch_pool));
- }
- else if (conflict_action == svn_wc_conflict_action_add ||
- conflict_action == svn_wc_conflict_action_replace)
- {
- /* Change is acting on 'src_right' version of the node.
- *
- * ### For 'replace', the node kind is ambiguous. However, src_left
- * ### is NULL for replace, so we must use src_right. */
- SVN_ERR(svn_client_conflict_get_incoming_new_repos_location(
- NULL, NULL, &incoming_kind, conflict, scratch_pool,
- scratch_pool));
- }
-
- reason = local_reason_str(conflict_node_kind, conflict_reason,
- conflict_operation);
- action = incoming_action_str(incoming_kind, conflict_action);
- operation = operation_str(conflict_operation);
- SVN_ERR_ASSERT(operation);
-
- if (action && reason)
- {
- *description = apr_psprintf(result_pool, _("%s, %s %s"),
- reason, action, operation);
- }
- else
- {
- /* A catch-all message for very rare or nominally impossible cases.
- It will not be pretty, but is closer to an internal error than
- an ordinary user-facing string. */
- *description = apr_psprintf(result_pool,
- _("local: %s %s incoming: %s %s %s"),
- svn_node_kind_to_word(conflict_node_kind),
- svn_token__to_word(map_conflict_reason,
- conflict_reason),
- svn_node_kind_to_word(incoming_kind),
- svn_token__to_word(map_conflict_action,
- conflict_action),
- operation);
- }
- return SVN_NO_ERROR;
-}
-
-void
-svn_client_conflict_option_set_merged_propval(
- svn_client_conflict_option_t *option,
- const svn_string_t *merged_propval)
-{
- option->type_data.prop.merged_propval = merged_propval;
-}
-
-/* Implements conflict_option_resolve_func_t. */
-static svn_error_t *
-resolve_postpone(svn_client_conflict_option_t *option,
- svn_client_conflict_t *conflict,
- apr_pool_t *scratch_pool)
-{
- return SVN_NO_ERROR; /* Nothing to do. */
-}
-
-/* Implements conflict_option_resolve_func_t. */
-static svn_error_t *
-resolve_text_conflict(svn_client_conflict_option_t *option,
- svn_client_conflict_t *conflict,
- apr_pool_t *scratch_pool)
-{
- svn_client_conflict_option_id_t option_id;
- const char *local_abspath;
- const char *lock_abspath;
- svn_wc_conflict_choice_t conflict_choice;
- svn_client_ctx_t *ctx = conflict->ctx;
- svn_error_t *err;
-
- option_id = svn_client_conflict_option_get_id(option);
- conflict_choice =
- svn_client_conflict_option_id_to_wc_conflict_choice(option_id);
- local_abspath = svn_client_conflict_get_local_abspath(conflict);
-
- SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx,
- local_abspath,
- scratch_pool, scratch_pool));
- err = svn_wc__conflict_text_mark_resolved(conflict->ctx->wc_ctx,
- local_abspath,
- conflict_choice,
- conflict->ctx->cancel_func,
- conflict->ctx->cancel_baton,
- conflict->ctx->notify_func2,
- conflict->ctx->notify_baton2,
- scratch_pool);
- err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx,
- lock_abspath,
- scratch_pool));
- svn_io_sleep_for_timestamps(local_abspath, scratch_pool);
- SVN_ERR(err);
-
- conflict->resolution_text = option_id;
-
- return SVN_NO_ERROR;
-}
-
-/* Implements conflict_option_resolve_func_t. */
-static svn_error_t *
-resolve_prop_conflict(svn_client_conflict_option_t *option,
- svn_client_conflict_t *conflict,
- apr_pool_t *scratch_pool)
-{
- svn_client_conflict_option_id_t option_id;
- svn_wc_conflict_choice_t conflict_choice;
- const char *local_abspath;
- const char *lock_abspath;
- const char *propname = option->type_data.prop.propname;
- svn_client_ctx_t *ctx = conflict->ctx;
- svn_error_t *err;
-
- option_id = svn_client_conflict_option_get_id(option);
- conflict_choice =
- svn_client_conflict_option_id_to_wc_conflict_choice(option_id);
- local_abspath = svn_client_conflict_get_local_abspath(conflict);
-
- SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx,
- local_abspath,
- scratch_pool, scratch_pool));
- err = svn_wc__conflict_prop_mark_resolved(ctx->wc_ctx, local_abspath,
- propname, conflict_choice,
- conflict->ctx->notify_func2,
- conflict->ctx->notify_baton2,
- scratch_pool);
- err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx,
- lock_abspath,
- scratch_pool));
- svn_io_sleep_for_timestamps(local_abspath, scratch_pool);
- SVN_ERR(err);
-
- if (propname[0] == '\0')
- {
- apr_hash_index_t *hi;
-
- /* All properties have been resolved to the same option. */
- for (hi = apr_hash_first(scratch_pool, conflict->prop_conflicts);
- hi;
- hi = apr_hash_next(hi))
- {
- const char *this_propname = apr_hash_this_key(hi);
-
- svn_hash_sets(conflict->resolved_props,
- apr_pstrdup(apr_hash_pool_get(conflict->resolved_props),
- this_propname),
- option);
- svn_hash_sets(conflict->prop_conflicts, this_propname, NULL);
- }
-
- conflict->legacy_prop_conflict_propname = NULL;
- }
- else
- {
- svn_hash_sets(conflict->resolved_props,
- apr_pstrdup(apr_hash_pool_get(conflict->resolved_props),
- propname),
- option);
- svn_hash_sets(conflict->prop_conflicts, propname, NULL);
-
- conflict->legacy_prop_conflict_propname =
- apr_hash_this_key(apr_hash_first(scratch_pool,
- conflict->prop_conflicts));
- }
-
- return SVN_NO_ERROR;
-}
-
-/* Implements conflict_option_resolve_func_t. */
-static svn_error_t *
-resolve_accept_current_wc_state(svn_client_conflict_option_t *option,
- svn_client_conflict_t *conflict,
- apr_pool_t *scratch_pool)
-{
- svn_client_conflict_option_id_t option_id;
- const char *local_abspath;
- const char *lock_abspath;
- svn_client_ctx_t *ctx = conflict->ctx;
- svn_error_t *err;
-
- option_id = svn_client_conflict_option_get_id(option);
- local_abspath = svn_client_conflict_get_local_abspath(conflict);
-
- if (option_id != svn_client_conflict_option_accept_current_wc_state)
- return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
- _("Tree conflict on '%s' can only be resolved "
- "to the current working copy state"),
- svn_dirent_local_style(local_abspath,
- scratch_pool));
-
- SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx,
- local_abspath,
- scratch_pool, scratch_pool));
-
- /* Resolve to current working copy state. */
- err = svn_wc__del_tree_conflict(ctx->wc_ctx, local_abspath, scratch_pool);
-
- /* svn_wc__del_tree_conflict doesn't handle notification for us */
- if (ctx->notify_func2)
- ctx->notify_func2(ctx->notify_baton2,
- svn_wc_create_notify(local_abspath,
- svn_wc_notify_resolved,
- scratch_pool),
- scratch_pool);
-
- err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx,
- lock_abspath,
- scratch_pool));
- SVN_ERR(err);
-
- conflict->resolution_tree = option_id;
-
- return SVN_NO_ERROR;
-}
-
-/* Implements conflict_option_resolve_func_t. */
-static svn_error_t *
-resolve_update_break_moved_away(svn_client_conflict_option_t *option,
- svn_client_conflict_t *conflict,
- apr_pool_t *scratch_pool)
-{
- const char *local_abspath;
- const char *lock_abspath;
- svn_client_ctx_t *ctx = conflict->ctx;
- svn_error_t *err;
-
- local_abspath = svn_client_conflict_get_local_abspath(conflict);
-
- SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx,
- local_abspath,
- scratch_pool, scratch_pool));
- err = svn_wc__conflict_tree_update_break_moved_away(ctx->wc_ctx,
- local_abspath,
- ctx->cancel_func,
- ctx->cancel_baton,
- ctx->notify_func2,
- ctx->notify_baton2,
- scratch_pool);
- err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx,
- lock_abspath,
- scratch_pool));
- SVN_ERR(err);
-
- conflict->resolution_tree = svn_client_conflict_option_get_id(option);
-
- return SVN_NO_ERROR;
-}
-
-/* Implements conflict_option_resolve_func_t. */
-static svn_error_t *
-resolve_update_raise_moved_away(svn_client_conflict_option_t *option,
- svn_client_conflict_t *conflict,
- apr_pool_t *scratch_pool)
-{
- const char *local_abspath;
- const char *lock_abspath;
- svn_client_ctx_t *ctx = conflict->ctx;
- svn_error_t *err;
-
- local_abspath = svn_client_conflict_get_local_abspath(conflict);
-
- SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx,
- local_abspath,
- scratch_pool, scratch_pool));
- err = svn_wc__conflict_tree_update_raise_moved_away(ctx->wc_ctx,
- local_abspath,
- ctx->cancel_func,
- ctx->cancel_baton,
- ctx->notify_func2,
- ctx->notify_baton2,
- scratch_pool);
- err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx,
- lock_abspath,
- scratch_pool));
- SVN_ERR(err);
-
- conflict->resolution_tree = svn_client_conflict_option_get_id(option);
-
- return SVN_NO_ERROR;
-}
-
-/* Implements conflict_option_resolve_func_t. */
-static svn_error_t *
-resolve_update_moved_away_node(svn_client_conflict_option_t *option,
- svn_client_conflict_t *conflict,
- apr_pool_t *scratch_pool)
-{
- const char *local_abspath;
- const char *lock_abspath;
- svn_client_ctx_t *ctx = conflict->ctx;
- svn_error_t *err;
-
- local_abspath = svn_client_conflict_get_local_abspath(conflict);
-
- SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx,
- local_abspath,
- scratch_pool, scratch_pool));
- err = svn_wc__conflict_tree_update_moved_away_node(ctx->wc_ctx,
- local_abspath,
- ctx->cancel_func,
- ctx->cancel_baton,
- ctx->notify_func2,
- ctx->notify_baton2,
- scratch_pool);
- err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx,
- lock_abspath,
- scratch_pool));
- svn_io_sleep_for_timestamps(local_abspath, scratch_pool);
- SVN_ERR(err);
-
- conflict->resolution_tree = svn_client_conflict_option_get_id(option);
-
- return SVN_NO_ERROR;
-}
-
-/* Resolver options for a text conflict */
-static const svn_client_conflict_option_t text_conflict_options[] =
-{
- {
- svn_client_conflict_option_postpone,
- N_("skip this conflict and leave it unresolved"),
- NULL,
- resolve_postpone
- },
-
- {
- svn_client_conflict_option_base_text,
- N_("discard local and incoming changes for this file"),
- NULL,
- resolve_text_conflict
- },
-
- {
- svn_client_conflict_option_incoming_text,
- N_("accept incoming version of entire file"),
- NULL,
- resolve_text_conflict
- },
-
- {
- svn_client_conflict_option_working_text,
- N_("reject all incoming changes for this file"),
- NULL,
- resolve_text_conflict
- },
-
- {
- svn_client_conflict_option_incoming_text_where_conflicted,
- N_("accept changes only where they conflict"),
- NULL,
- resolve_text_conflict
- },
-
- {
- svn_client_conflict_option_working_text_where_conflicted,
- N_("reject changes which conflict and accept the rest"),
- NULL,
- resolve_text_conflict
- },
-
- {
- svn_client_conflict_option_merged_text,
- N_("accept the file as it appears in the working copy"),
- NULL,
- resolve_text_conflict
- },
-
-};
-
-/* Resolver options for a binary file conflict */
-static const svn_client_conflict_option_t binary_conflict_options[] =
-{
- {
- svn_client_conflict_option_postpone,
- N_("skip this conflict and leave it unresolved"),
- NULL,
- resolve_postpone,
- },
-
- {
- svn_client_conflict_option_incoming_text,
- N_("accept incoming version of binary file"),
- NULL,
- resolve_text_conflict
- },
-
- {
- svn_client_conflict_option_working_text,
- N_("accept working copy version of binary file"),
- NULL,
- resolve_text_conflict
- },
-
- {
- svn_client_conflict_option_merged_text,
- N_("accept the file as it appears in the working copy"),
- NULL,
- resolve_text_conflict
- },
-
-};
-
-/* Resolver options for a property conflict */
-static const svn_client_conflict_option_t prop_conflict_options[] =
-{
- {
- svn_client_conflict_option_postpone,
- N_("skip this conflict and leave it unresolved"),
- NULL,
- resolve_postpone
- },
-
- {
- svn_client_conflict_option_base_text,
- N_("discard local and incoming changes for this property"),
- NULL,
- resolve_prop_conflict
- },
-
- {
- svn_client_conflict_option_incoming_text,
- N_("accept incoming version of entire property value"),
- NULL,
- resolve_prop_conflict
- },
-
- {
- svn_client_conflict_option_working_text,
- N_("accept working copy version of entire property value"),
- NULL,
- resolve_prop_conflict
- },
-
- {
- svn_client_conflict_option_incoming_text_where_conflicted,
- N_("accept changes only where they conflict"),
- NULL,
- resolve_prop_conflict
- },
-
- {
- svn_client_conflict_option_working_text_where_conflicted,
- N_("reject changes which conflict and accept the rest"),
- NULL,
- resolve_prop_conflict
- },
-
- {
- svn_client_conflict_option_merged_text,
- N_("accept merged version of property value"),
- NULL,
- resolve_prop_conflict
- },
-
-};
-
-static svn_error_t *
-assert_text_conflict(svn_client_conflict_t *conflict, apr_pool_t *scratch_pool)
-{
- svn_boolean_t text_conflicted;
-
- SVN_ERR(svn_client_conflict_get_conflicted(&text_conflicted, NULL, NULL,
- conflict, scratch_pool,
- scratch_pool));
-
- SVN_ERR_ASSERT(text_conflicted); /* ### return proper error? */
-
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-assert_prop_conflict(svn_client_conflict_t *conflict, apr_pool_t *scratch_pool)
-{
- apr_array_header_t *props_conflicted;
-
- SVN_ERR(svn_client_conflict_get_conflicted(NULL, &props_conflicted, NULL,
- conflict, scratch_pool,
- scratch_pool));
-
- /* ### return proper error? */
- SVN_ERR_ASSERT(props_conflicted && props_conflicted->nelts > 0);
-
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-assert_tree_conflict(svn_client_conflict_t *conflict, apr_pool_t *scratch_pool)
-{
- svn_boolean_t tree_conflicted;
-
- SVN_ERR(svn_client_conflict_get_conflicted(NULL, NULL, &tree_conflicted,
- conflict, scratch_pool,
- scratch_pool));
-
- SVN_ERR_ASSERT(tree_conflicted); /* ### return proper error? */
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_client_conflict_text_get_resolution_options(apr_array_header_t **options,
- svn_client_conflict_t *conflict,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- const char *mime_type;
- int i;
-
- SVN_ERR(assert_text_conflict(conflict, scratch_pool));
-
- *options = apr_array_make(result_pool, ARRAY_LEN(text_conflict_options),
- sizeof(svn_client_conflict_option_t *));
-
- mime_type = svn_client_conflict_text_get_mime_type(conflict);
- if (mime_type && svn_mime_type_is_binary(mime_type))
- {
- for (i = 0; i < ARRAY_LEN(binary_conflict_options); i++)
- {
- svn_client_conflict_option_t *option;
-
- /* We must make a copy to make the memory for option->type_data
- * writable and to localize the description. */
- option = apr_pcalloc(result_pool, sizeof(*option));
- *option = binary_conflict_options[i];
- option->description = _(option->description);
- APR_ARRAY_PUSH((*options), const svn_client_conflict_option_t *) =
- option;
- }
- }
- else
- {
- for (i = 0; i < ARRAY_LEN(text_conflict_options); i++)
- {
- svn_client_conflict_option_t *option;
-
- /* We must make a copy to make the memory for option->type_data
- * writable and to localize the description. */
- option = apr_pcalloc(result_pool, sizeof(*option));
- *option = text_conflict_options[i];
- option->description = _(option->description);
- APR_ARRAY_PUSH((*options), const svn_client_conflict_option_t *) =
- option;
- }
- }
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_client_conflict_prop_get_resolution_options(apr_array_header_t **options,
- svn_client_conflict_t *conflict,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- int i;
-
- SVN_ERR(assert_prop_conflict(conflict, scratch_pool));
-
- *options = apr_array_make(result_pool, ARRAY_LEN(prop_conflict_options),
- sizeof(svn_client_conflict_option_t *));
- for (i = 0; i < ARRAY_LEN(prop_conflict_options); i++)
- {
- svn_client_conflict_option_t *option;
-
- /* We must make a copy to make the memory for option->type_data
- * writable and to localize the description. */
- option = apr_pcalloc(result_pool, sizeof(*option));
- *option = prop_conflict_options[i];
- option->description = _(option->description);
- APR_ARRAY_PUSH((*options), const svn_client_conflict_option_t *) = option;
- }
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_client_conflict_tree_get_resolution_options(apr_array_header_t **options,
- svn_client_conflict_t *conflict,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- svn_client_conflict_option_t *option;
- svn_wc_operation_t operation;
- svn_wc_conflict_reason_t local_change;
- svn_wc_conflict_action_t incoming_change;
-
- operation = svn_client_conflict_get_operation(conflict);
- local_change = svn_client_conflict_get_local_change(conflict);
- incoming_change = svn_client_conflict_get_incoming_change(conflict);
-
- SVN_ERR(assert_tree_conflict(conflict, scratch_pool));
-
- *options = apr_array_make(result_pool, 2,
- sizeof(svn_client_conflict_option_t *));
-
- /* Add postpone option. */
- option = apr_pcalloc(result_pool, sizeof(*option));
- option->id = svn_client_conflict_option_postpone;
- option->description = _("skip this conflict and leave it unresolved");
- option->conflict = conflict;
- option->do_resolve_func = resolve_postpone;
- APR_ARRAY_PUSH((*options), const svn_client_conflict_option_t *) = option;
-
- /* Add an option which marks the conflict resolved. */
- option = apr_pcalloc(result_pool, sizeof(*option));
- option->id = svn_client_conflict_option_accept_current_wc_state;
- option->description = _("accept current working copy state");
- option->conflict = conflict;
- if ((operation == svn_wc_operation_update ||
- operation == svn_wc_operation_switch) &&
- (local_change == svn_wc_conflict_reason_moved_away ||
- local_change == svn_wc_conflict_reason_deleted ||
- local_change == svn_wc_conflict_reason_replaced) &&
- incoming_change == svn_wc_conflict_action_edit)
- {
- /* We must break moves if the user accepts the current working copy
- * state instead of updating a moved-away node or updating children
- * moved outside of deleted or replaced directory nodes.
- * Else such moves would be left in an invalid state. */
- option->do_resolve_func = resolve_update_break_moved_away;
- }
- else
- option->do_resolve_func = resolve_accept_current_wc_state;
-
- APR_ARRAY_PUSH((*options), const svn_client_conflict_option_t *) = option;
-
- /* Add options which offer automated resolution: */
- if (svn_client_conflict_get_operation(conflict) == svn_wc_operation_update ||
- svn_client_conflict_get_operation(conflict) == svn_wc_operation_switch)
- {
- svn_wc_conflict_reason_t reason;
-
- reason = svn_client_conflict_get_local_change(conflict);
- if (reason == svn_wc_conflict_reason_moved_away)
- {
- option = apr_pcalloc(result_pool, sizeof(*option));
- option->id =
- svn_client_conflict_option_update_move_destination;
- option->description =
- _("apply incoming changes to move destination");
- option->conflict = conflict;
- option->do_resolve_func = resolve_update_moved_away_node;
- APR_ARRAY_PUSH((*options), const svn_client_conflict_option_t *) =
- option;
- }
- else if (reason == svn_wc_conflict_reason_deleted ||
- reason == svn_wc_conflict_reason_replaced)
- {
- if (svn_client_conflict_get_incoming_change(conflict) ==
- svn_wc_conflict_action_edit &&
- svn_client_conflict_tree_get_victim_node_kind(conflict) ==
- svn_node_dir)
- {
- option = apr_pcalloc(result_pool, sizeof(*option));
- option->id =
- svn_client_conflict_option_update_any_moved_away_children;
- option->description =
- _("prepare for updating moved-away children, if any");
- option->conflict = conflict;
- option->do_resolve_func = resolve_update_raise_moved_away;
- APR_ARRAY_PUSH((*options), const svn_client_conflict_option_t *) =
- option;
- }
- }
- }
-
- return SVN_NO_ERROR;
-}
-
-svn_client_conflict_option_id_t
-svn_client_conflict_option_get_id(svn_client_conflict_option_t *option)
-{
- return option->id;
-}
-
-svn_error_t *
-svn_client_conflict_option_describe(const char **description,
- svn_client_conflict_option_t *option,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- *description = apr_pstrdup(result_pool, option->description);
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_client_conflict_text_resolve(svn_client_conflict_t *conflict,
- svn_client_conflict_option_t *option,
- apr_pool_t *scratch_pool)
-{
- SVN_ERR(assert_text_conflict(conflict, scratch_pool));
- SVN_ERR(option->do_resolve_func(option, conflict, scratch_pool));
-
- return SVN_NO_ERROR;
-}
-
-svn_client_conflict_option_t *
-svn_client_conflict_option_find_by_id(apr_array_header_t *options,
- svn_client_conflict_option_id_t option_id)
-{
- int i;
-
- for (i = 0; i < options->nelts; i++)
- {
- svn_client_conflict_option_t *this_option;
- svn_client_conflict_option_id_t this_option_id;
-
- this_option = APR_ARRAY_IDX(options, i, svn_client_conflict_option_t *);
- this_option_id = svn_client_conflict_option_get_id(this_option);
-
- if (this_option_id == option_id)
- return this_option;
- }
-
- return NULL;
-}
-
-svn_error_t *
-svn_client_conflict_text_resolve_by_id(
- svn_client_conflict_t *conflict,
- svn_client_conflict_option_id_t option_id,
- apr_pool_t *scratch_pool)
-{
- apr_array_header_t *resolution_options;
- svn_client_conflict_option_t *option;
-
- SVN_ERR(svn_client_conflict_text_get_resolution_options(
- &resolution_options, conflict,
- scratch_pool, scratch_pool));
- option = svn_client_conflict_option_find_by_id(resolution_options,
- option_id);
- if (option == NULL)
- return svn_error_createf(SVN_ERR_CLIENT_CONFLICT_OPTION_NOT_APPLICABLE,
- NULL,
- _("Inapplicable conflict resolution option "
- "ID '%d' given for conflicted path '%s'"),
- option_id,
- svn_dirent_local_style(conflict->local_abspath,
- scratch_pool));
- SVN_ERR(svn_client_conflict_text_resolve(conflict, option, scratch_pool));
-
- return SVN_NO_ERROR;
-}
-
-svn_client_conflict_option_id_t
-svn_client_conflict_text_get_resolution(const svn_client_conflict_t *conflict)
-{
- return conflict->resolution_text;
-}
-
-svn_error_t *
-svn_client_conflict_prop_resolve(svn_client_conflict_t *conflict,
- const char *propname,
- svn_client_conflict_option_t *option,
- apr_pool_t *scratch_pool)
-{
- SVN_ERR(assert_prop_conflict(conflict, scratch_pool));
- option->type_data.prop.propname = propname;
- SVN_ERR(option->do_resolve_func(option, conflict, scratch_pool));
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_client_conflict_prop_resolve_by_id(
- svn_client_conflict_t *conflict,
- const char *propname,
- svn_client_conflict_option_id_t option_id,
- apr_pool_t *scratch_pool)
-{
- apr_array_header_t *resolution_options;
- svn_client_conflict_option_t *option;
-
- SVN_ERR(svn_client_conflict_prop_get_resolution_options(
- &resolution_options, conflict,
- scratch_pool, scratch_pool));
- option = svn_client_conflict_option_find_by_id(resolution_options,
- option_id);
- if (option == NULL)
- return svn_error_createf(SVN_ERR_CLIENT_CONFLICT_OPTION_NOT_APPLICABLE,
- NULL,
- _("Inapplicable conflict resolution option "
- "ID '%d' given for conflicted path '%s'"),
- option_id,
- svn_dirent_local_style(conflict->local_abspath,
- scratch_pool));
- SVN_ERR(svn_client_conflict_prop_resolve(conflict, propname, option,
- scratch_pool));
-
- return SVN_NO_ERROR;
-}
-
-svn_client_conflict_option_id_t
-svn_client_conflict_prop_get_resolution(const svn_client_conflict_t *conflict,
- const char *propname)
-{
- svn_client_conflict_option_t *option;
-
- option = svn_hash_gets(conflict->resolved_props, propname);
- if (option == NULL)
- return svn_client_conflict_option_unspecified;
-
- return svn_client_conflict_option_get_id(option);
-}
-
-svn_error_t *
-svn_client_conflict_tree_resolve(svn_client_conflict_t *conflict,
- svn_client_conflict_option_t *option,
- apr_pool_t *scratch_pool)
-{
- SVN_ERR(assert_tree_conflict(conflict, scratch_pool));
- SVN_ERR(option->do_resolve_func(option, conflict, scratch_pool));
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_client_conflict_tree_resolve_by_id(
- svn_client_conflict_t *conflict,
- svn_client_conflict_option_id_t option_id,
- apr_pool_t *scratch_pool)
-{
- apr_array_header_t *resolution_options;
- svn_client_conflict_option_t *option;
-
- /* Backwards compatibility hack: Upper layers may still try to resolve
- * these two tree conflicts as 'mine-conflict' as Subversion 1.9 did.
- * Fix up if necessary... */
- if (option_id == svn_client_conflict_option_working_text_where_conflicted)
- {
- svn_wc_operation_t operation;
-
- operation = svn_client_conflict_get_operation(conflict);
- if (operation == svn_wc_operation_update ||
- operation == svn_wc_operation_switch)
- {
- svn_wc_conflict_reason_t reason;
-
- reason = svn_client_conflict_get_local_change(conflict);
- if (reason == svn_wc_conflict_reason_moved_away)
- {
- /* Map 'mine-conflict' to 'update move destination'. */
- option_id = svn_client_conflict_option_update_move_destination;
- }
- else if (reason == svn_wc_conflict_reason_deleted ||
- reason == svn_wc_conflict_reason_replaced)
- {
- svn_wc_conflict_action_t action;
- svn_node_kind_t node_kind;
-
- action = svn_client_conflict_get_incoming_change(conflict);
- node_kind =
- svn_client_conflict_tree_get_victim_node_kind(conflict);
-
- if (action == svn_wc_conflict_action_edit &&
- node_kind == svn_node_dir)
- {
- /* Map 'mine-conflict' to 'update any moved away children'. */
- option_id =
- svn_client_conflict_option_update_any_moved_away_children;
- }
- }
- }
- }
- else if (option_id == svn_client_conflict_option_merged_text)
- {
- /* Another backwards compatibility hack for 'choose merged'. */
- option_id = svn_client_conflict_option_accept_current_wc_state;
- }
-
- SVN_ERR(svn_client_conflict_tree_get_resolution_options(
- &resolution_options, conflict,
- scratch_pool, scratch_pool));
- option = svn_client_conflict_option_find_by_id(resolution_options,
- option_id);
- if (option == NULL)
- return svn_error_createf(SVN_ERR_CLIENT_CONFLICT_OPTION_NOT_APPLICABLE,
- NULL,
- _("Inapplicable conflict resolution option "
- "ID '%d' given for conflicted path '%s'"),
- option_id,
- svn_dirent_local_style(conflict->local_abspath,
- scratch_pool));
- SVN_ERR(svn_client_conflict_tree_resolve(conflict, option, scratch_pool));
-
- return SVN_NO_ERROR;
-}
-
-svn_client_conflict_option_id_t
-svn_client_conflict_tree_get_resolution(const svn_client_conflict_t *conflict)
-{
- return conflict->resolution_tree;
-}
-
-/* Return the legacy conflict descriptor which is wrapped by CONFLICT. */
-static const svn_wc_conflict_description2_t *
-get_conflict_desc2_t(const svn_client_conflict_t *conflict)
-{
- if (conflict->legacy_text_conflict)
- return conflict->legacy_text_conflict;
-
- if (conflict->legacy_tree_conflict)
- return conflict->legacy_tree_conflict;
-
- if (conflict->prop_conflicts && conflict->legacy_prop_conflict_propname)
- return svn_hash_gets(conflict->prop_conflicts,
- conflict->legacy_prop_conflict_propname);
-
- return NULL;
-}
-
-svn_wc_conflict_kind_t
-svn_client_conflict_get_kind(const svn_client_conflict_t *conflict)
-{
- return get_conflict_desc2_t(conflict)->kind;
-}
-
-svn_error_t *
-svn_client_conflict_get_conflicted(svn_boolean_t *text_conflicted,
- apr_array_header_t **props_conflicted,
- svn_boolean_t *tree_conflicted,
- svn_client_conflict_t *conflict,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- if (text_conflicted)
- *text_conflicted = (conflict->legacy_text_conflict != NULL);
-
- if (props_conflicted)
- {
- if (conflict->prop_conflicts)
- SVN_ERR(svn_hash_keys(props_conflicted, conflict->prop_conflicts,
- result_pool));
- else
- *props_conflicted = apr_array_make(result_pool, 0,
- sizeof(const char*));
- }
-
- if (tree_conflicted)
- *tree_conflicted = (conflict->legacy_tree_conflict != NULL);
-
- return SVN_NO_ERROR;
-}
-
-const char *
-svn_client_conflict_get_local_abspath(const svn_client_conflict_t *conflict)
-{
- return conflict->local_abspath;
-}
-
-svn_wc_operation_t
-svn_client_conflict_get_operation(const svn_client_conflict_t *conflict)
-{
- return get_conflict_desc2_t(conflict)->operation;
-}
-
-svn_wc_conflict_action_t
-svn_client_conflict_get_incoming_change(const svn_client_conflict_t *conflict)
-{
- return get_conflict_desc2_t(conflict)->action;
-}
-
-svn_wc_conflict_reason_t
-svn_client_conflict_get_local_change(const svn_client_conflict_t *conflict)
-{
- return get_conflict_desc2_t(conflict)->reason;
-}
-
-svn_error_t *
-svn_client_conflict_get_repos_info(const char **repos_root_url,
- const char **repos_uuid,
- const svn_client_conflict_t *conflict,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- if (repos_root_url)
- {
- if (get_conflict_desc2_t(conflict)->src_left_version)
- *repos_root_url =
- get_conflict_desc2_t(conflict)->src_left_version->repos_url;
- else if (get_conflict_desc2_t(conflict)->src_right_version)
- *repos_root_url =
- get_conflict_desc2_t(conflict)->src_right_version->repos_url;
- else
- *repos_root_url = NULL;
- }
-
- if (repos_uuid)
- {
- if (get_conflict_desc2_t(conflict)->src_left_version)
- *repos_uuid =
- get_conflict_desc2_t(conflict)->src_left_version->repos_uuid;
- else if (get_conflict_desc2_t(conflict)->src_right_version)
- *repos_uuid =
- get_conflict_desc2_t(conflict)->src_right_version->repos_uuid;
- else
- *repos_uuid = NULL;
- }
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_client_conflict_get_incoming_old_repos_location(
- const char **incoming_old_repos_relpath,
- svn_revnum_t *incoming_old_pegrev,
- svn_node_kind_t *incoming_old_node_kind,
- const svn_client_conflict_t *conflict,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- if (incoming_old_repos_relpath)
- {
- if (get_conflict_desc2_t(conflict)->src_left_version)
- *incoming_old_repos_relpath =
- get_conflict_desc2_t(conflict)->src_left_version->path_in_repos;
- else
- *incoming_old_repos_relpath = NULL;
- }
-
- if (incoming_old_pegrev)
- {
- if (get_conflict_desc2_t(conflict)->src_left_version)
- *incoming_old_pegrev =
- get_conflict_desc2_t(conflict)->src_left_version->peg_rev;
- else
- *incoming_old_pegrev = SVN_INVALID_REVNUM;
- }
-
- if (incoming_old_node_kind)
- {
- if (get_conflict_desc2_t(conflict)->src_left_version)
- *incoming_old_node_kind =
- get_conflict_desc2_t(conflict)->src_left_version->node_kind;
- else
- *incoming_old_node_kind = svn_node_none;
- }
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_client_conflict_get_incoming_new_repos_location(
- const char **incoming_new_repos_relpath,
- svn_revnum_t *incoming_new_pegrev,
- svn_node_kind_t *incoming_new_node_kind,
- const svn_client_conflict_t *conflict,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- if (incoming_new_repos_relpath)
- {
- if (get_conflict_desc2_t(conflict)->src_right_version)
- *incoming_new_repos_relpath =
- get_conflict_desc2_t(conflict)->src_right_version->path_in_repos;
- else
- *incoming_new_repos_relpath = NULL;
- }
-
- if (incoming_new_pegrev)
- {
- if (get_conflict_desc2_t(conflict)->src_right_version)
- *incoming_new_pegrev =
- get_conflict_desc2_t(conflict)->src_right_version->peg_rev;
- else
- *incoming_new_pegrev = SVN_INVALID_REVNUM;
- }
-
- if (incoming_new_node_kind)
- {
- if (get_conflict_desc2_t(conflict)->src_right_version)
- *incoming_new_node_kind =
- get_conflict_desc2_t(conflict)->src_right_version->node_kind;
- else
- *incoming_new_node_kind = svn_node_none;
- }
-
- return SVN_NO_ERROR;
-}
-
-svn_node_kind_t
-svn_client_conflict_tree_get_victim_node_kind(
- const svn_client_conflict_t *conflict)
-{
- SVN_ERR_ASSERT_NO_RETURN(svn_client_conflict_get_kind(conflict)
- == svn_wc_conflict_kind_tree);
-
- return get_conflict_desc2_t(conflict)->node_kind;
-}
-
-const char *
-svn_client_conflict_prop_get_propname(const svn_client_conflict_t *conflict)
-{
- SVN_ERR_ASSERT_NO_RETURN(svn_client_conflict_get_kind(conflict)
- == svn_wc_conflict_kind_property);
-
- return get_conflict_desc2_t(conflict)->property_name;
-}
-
-svn_error_t *
-svn_client_conflict_prop_get_propvals(const svn_string_t **base_propval,
- const svn_string_t **working_propval,
- const svn_string_t **incoming_old_propval,
- const svn_string_t **incoming_new_propval,
- const svn_client_conflict_t *conflict,
- const char *propname,
- apr_pool_t *result_pool)
-{
- const svn_wc_conflict_description2_t *desc;
-
- SVN_ERR_ASSERT(svn_client_conflict_get_kind(conflict) ==
- svn_wc_conflict_kind_property);
-
- desc = svn_hash_gets(conflict->prop_conflicts, propname);
- if (desc == NULL)
- return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
- _("Property '%s' is not in conflict."), propname);
-
- if (base_propval)
- *base_propval =
- svn_string_dup(desc->prop_value_base, result_pool);
-
- if (working_propval)
- *working_propval =
- svn_string_dup(desc->prop_value_working, result_pool);
-
- if (incoming_old_propval)
- *incoming_old_propval =
- svn_string_dup(desc->prop_value_incoming_old, result_pool);
-
- if (incoming_new_propval)
- *incoming_new_propval =
- svn_string_dup(desc->prop_value_incoming_new, result_pool);
-
- return SVN_NO_ERROR;
-}
-
-const char *
-svn_client_conflict_prop_get_reject_abspath(
- const svn_client_conflict_t *conflict)
-{
- SVN_ERR_ASSERT_NO_RETURN(svn_client_conflict_get_kind(conflict)
- == svn_wc_conflict_kind_property);
-
- /* svn_wc_conflict_description2_t stores this path in 'their_abspath' */
- return get_conflict_desc2_t(conflict)->their_abspath;
-}
-
-const char *
-svn_client_conflict_text_get_mime_type(const svn_client_conflict_t *conflict)
-{
- SVN_ERR_ASSERT_NO_RETURN(svn_client_conflict_get_kind(conflict)
- == svn_wc_conflict_kind_text);
-
- return get_conflict_desc2_t(conflict)->mime_type;
-}
-
-svn_error_t *
-svn_client_conflict_text_get_contents(const char **base_abspath,
- const char **working_abspath,
- const char **incoming_old_abspath,
- const char **incoming_new_abspath,
- const svn_client_conflict_t *conflict,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- SVN_ERR_ASSERT(svn_client_conflict_get_kind(conflict)
- == svn_wc_conflict_kind_text);
-
- if (base_abspath)
- {
- if (svn_client_conflict_get_operation(conflict) ==
- svn_wc_operation_merge)
- *base_abspath = NULL; /* ### WC base contents not available yet */
- else /* update/switch */
- *base_abspath = get_conflict_desc2_t(conflict)->base_abspath;
- }
-
- if (working_abspath)
- *working_abspath = get_conflict_desc2_t(conflict)->my_abspath;
-
- if (incoming_old_abspath)
- *incoming_old_abspath = get_conflict_desc2_t(conflict)->base_abspath;
-
- if (incoming_new_abspath)
- *incoming_new_abspath = get_conflict_desc2_t(conflict)->their_abspath;
-
- return SVN_NO_ERROR;
-}