[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: [PATCH] Conflict option labels

From: Ivan Zhakov <ivan_at_visualsvn.com>
Date: Wed, 12 Oct 2016 16:44:10 +0200

On 12 October 2016 at 15:38, Patrick Steinhardt
<patrick.steinhardt_at_elegosoft.com> wrote:
> Hi,
>
> please find attached a patch pulling out the short descriptions
> of conflict resolution options from the client and puts them into
> libsvn_client.
>
> [[
> Move conflict resolution options' labels out of the client
>
> * include/svn_client.h:
> - Provide function `svn_client_conflict_option_label`
> * libsvn_client/conflicts.c:
> - Implement function `svn_client_conflict_option_label`
> - Introduce and set label field for svn_conflict_option_t
> * svn/conflict-callbacks.c:
> - Split client-specific and built-in resolver options
> - Implement conversion from built-in resolvers to
> client-specific options
> ]]

Hi Patrick. Thank you for the patch.

See my review inline:
> Index: subversion/include/svn_client.h
> ===================================================================
> --- subversion/include/svn_client.h (revision 1764453)
> +++ subversion/include/svn_client.h (working copy)
> @@ -4718,6 +4718,22 @@
> svn_client_conflict_option_get_id(svn_client_conflict_option_t *option);
>
> /**
> + * Return a textual human-readable label of @a option, allocated in
> + * @a result_pool. The label is encoded in UTF-8 and may contain
> + * up to three words.
May replace 'may contain up to three words' -> 'usually contain up to
three words'?

> + *
> + * Additionally, the label may be localized to the language used
> + * by the current locale.
> + *
> + * @since New in 1.10.
> + */
> +svn_error_t *
> +svn_client_conflict_option_label(const char **label,
> + svn_client_conflict_option_t *option,
> + apr_pool_t *result_pool,
> + apr_pool_t *scratch_pool);
The function name svn_client_conflict_option_label() sounds like an
operation instead of getter. May be
svn_client_conflict_option_get_label() is better name.

Another suggestion: may be return string instead of svn_error_t? I
hardly believe that this function may fail. I.e.:
const char *
svn_client_conflict_option_label(const char **label,
                                 svn_client_conflict_option_t *option,
                                 apr_pool_t *pool);

>
> add_resolution_option(*options, conflict,
> svn_client_conflict_option_postpone,
> + _("postpone"),
> _("skip this conflict and leave it unresolved"),
> resolve_postpone);
>
> @@ -7112,16 +7116,19 @@
> /* Resolver options for a binary file conflict. */
> add_resolution_option(*options, conflict,
> svn_client_conflict_option_base_text,
> + _("accept base"),
> _("discard local and incoming changes for this binary file"),
> resolve_text_conflict);
>
> add_resolution_option(*options, conflict,
> svn_client_conflict_option_incoming_text,
> + _("accept theirs"),
As far I remember we're trying move from term mine/theirs to
incoming/local. What do you think about using 'Accept incoming text'
or 'Use incoming text' label for this option?

> _("accept incoming version of binary file"),
> resolve_text_conflict);
>
> add_resolution_option(*options, conflict,
> svn_client_conflict_option_merged_text,
> + _("accept working copy"),
I suggest use name 'mark as resolved'.

> _("accept binary file as it appears in the working copy"),
> resolve_text_conflict);
> }
> @@ -7130,31 +7137,37 @@
> /* Resolver options for a text file conflict. */
> add_resolution_option(*options, conflict,
> svn_client_conflict_option_base_text,
> + _("accept base"),
I think we need better label for this option, but I don't have good ideas :(

> _("discard local and incoming changes for this file"),
> resolve_text_conflict);
>
> add_resolution_option(*options, conflict,
> svn_client_conflict_option_incoming_text,
> + _("accept theirs"),
> _("accept incoming version of entire file"),
> resolve_text_conflict);
>
> add_resolution_option(*options, conflict,
> svn_client_conflict_option_working_text,
> + _("reject theirs"),
> _("reject all incoming changes for this file"),
> resolve_text_conflict);
>
> add_resolution_option(*options, conflict,
> svn_client_conflict_option_incoming_text_where_conflicted,
> + _("accept conflicts"),
I think we need better label for this option, but I don't have good ideas :(

> _("accept changes only where they conflict"),
> resolve_text_conflict);
>
> add_resolution_option(*options, conflict,
> svn_client_conflict_option_working_text_where_conflicted,
> + _("reject conflicts"),
> _("reject changes which conflict and accept the rest"),
> resolve_text_conflict);
>
> add_resolution_option(*options, conflict,
> svn_client_conflict_option_merged_text,
> + _("accept working copy"),
> _("accept the file as it appears in the working copy"),
> resolve_text_conflict);
> }
> @@ -7176,36 +7189,43 @@
>
> add_resolution_option(*options, conflict,
> svn_client_conflict_option_postpone,
> + _("postpone"),
> _("skip this conflict and leave it unresolved"),
> resolve_postpone);
>
> add_resolution_option(*options, conflict,
> svn_client_conflict_option_base_text,
> + _("accept base"),
> _("discard local and incoming changes for this property"),
> resolve_prop_conflict);
>
> add_resolution_option(*options, conflict,
> svn_client_conflict_option_incoming_text,
> + _("accept theirs"),
> _("accept incoming version of entire property value"),
> resolve_prop_conflict);
>
> add_resolution_option(*options, conflict,
> svn_client_conflict_option_working_text,
> + _("accept working copy"),
'mark as resolved'

> _("accept working copy version of entire property value"),
> resolve_prop_conflict);
>
> add_resolution_option(*options, conflict,
> svn_client_conflict_option_incoming_text_where_conflicted,
> + _("accept conflicts"),
> N_("accept changes only where they conflict"),
> resolve_prop_conflict);
>
> add_resolution_option(*options, conflict,
> svn_client_conflict_option_working_text_where_conflicted,
> + _("reject conflicts"),
> _("reject changes which conflict and accept the rest"),
> resolve_prop_conflict);
>
> add_resolution_option(*options, conflict,
> svn_client_conflict_option_merged_text,
> + _("accept merged"),
> _("accept merged version of property value"),
> resolve_prop_conflict);
>
> @@ -7244,6 +7264,7 @@
>
> add_resolution_option(options, conflict,
> svn_client_conflict_option_accept_current_wc_state,
> + _("accept working copy"),
'mark as resolved'
> _("accept current working copy state"),
> do_resolve_func);
>
[...]

> return SVN_NO_ERROR;
> @@ -7651,8 +7676,8 @@
> add_resolution_option(
> options, conflict,
> svn_client_conflict_option_incoming_added_dir_replace_and_merge,
> - description,
> - resolve_merge_incoming_added_dir_replace_and_merge);
> + N_("replace my directory with incoming directory and merge"),
'replace and merge' ?

> + description, resolve_merge_incoming_added_dir_replace_and_merge);
> }
>
> return SVN_NO_ERROR;
> @@ -7724,7 +7749,7 @@
>
> add_resolution_option(options, conflict,
> svn_client_conflict_option_incoming_delete_ignore,
> - description,
> + N_("ignore incoming deletion"), description,
> resolve_incoming_delete_ignore);
> }
>
> @@ -7783,7 +7808,7 @@
> add_resolution_option(
> options, conflict,
> svn_client_conflict_option_incoming_delete_accept,
> - description,
> + N_("accept incoming deletion"), description,
> resolve_incoming_delete_accept);
> }
> }
> @@ -7960,7 +7985,7 @@
> add_resolution_option(
> options, conflict,
> svn_client_conflict_option_incoming_move_file_text_merge,
> - description,
> + _("move and merge"), description,
> resolve_incoming_move_file_text_merge);
> }
>
> @@ -8078,7 +8103,7 @@
> scratch_pool));
> add_resolution_option(options, conflict,
> svn_client_conflict_option_incoming_move_dir_merge,
> - description,
> + _("move and merge"), description,
> resolve_incoming_move_dir_merge);
> }
>
> @@ -8329,6 +8354,7 @@
> /* Add postpone option. */
> add_resolution_option(*options, conflict,
> svn_client_conflict_option_postpone,
> + _("postpone"),
> _("skip this conflict and leave it unresolved"),
> resolve_postpone);
>
> @@ -8419,6 +8445,17 @@
> }
>
> svn_error_t *
> +svn_client_conflict_option_label(const char **label,
> + svn_client_conflict_option_t *option,
> + apr_pool_t *result_pool,
> + apr_pool_t *scratch_pool)
> +{
> + *label = apr_pstrdup(result_pool, option->label);
> +
> + return SVN_NO_ERROR;
> +}
> +
> +svn_error_t *
> svn_client_conflict_option_describe(const char **description,
> svn_client_conflict_option_t *option,
> apr_pool_t *result_pool,
> Index: subversion/svn/conflict-callbacks.c
> ===================================================================
> --- subversion/svn/conflict-callbacks.c (revision 1764453)
> +++ subversion/svn/conflict-callbacks.c (working copy)
> @@ -374,80 +374,71 @@
> typedef struct resolver_option_t
> {
> const char *code; /* one or two characters */
> - const char *short_desc; /* label in prompt (localized) */
> - const char *long_desc; /* longer description (localized) */
> svn_client_conflict_option_id_t choice;
> /* or ..._undefined if not from libsvn_client */
> const char *accept_arg; /* --accept option argument (NOT localized) */
> } resolver_option_t;
>
> +typedef struct client_option_t
> +{
> + const char *code; /* one or two characters */
> + const char *label; /* label in prompt (localized) */
> + const char *long_desc; /* longer description (localized) */
> + svn_client_conflict_option_id_t choice;
> + /* or ..._undefined if not from libsvn_client */
> + const char *accept_arg; /* --accept option argument (NOT localized) */
> +} client_option_t;
> +
> /* Resolver options for conflict options offered by libsvn_client. */
> static const resolver_option_t builtin_resolver_options[] =
> {
> - { "r", NULL, NULL,
> - svn_client_conflict_option_merged_text,
> - SVN_CL__ACCEPT_WORKING },
> - { "mc", NULL, NULL,
> - svn_client_conflict_option_working_text_where_conflicted,
> - SVN_CL__ACCEPT_MINE_CONFLICT },
> - { "tc", NULL, NULL,
> - svn_client_conflict_option_incoming_text_where_conflicted,
> - SVN_CL__ACCEPT_THEIRS_CONFLICT },
> - { "mf", NULL, NULL,
> - svn_client_conflict_option_working_text,
> - SVN_CL__ACCEPT_MINE_FULL},
> - { "tf", NULL, NULL,
> - svn_client_conflict_option_incoming_text,
> - SVN_CL__ACCEPT_THEIRS_FULL },
> - { "p", N_("postpone"), NULL,
> - svn_client_conflict_option_postpone,
> - SVN_CL__ACCEPT_POSTPONE },
> + { "r", svn_client_conflict_option_merged_text,
> + SVN_CL__ACCEPT_WORKING },
> + { "mc", svn_client_conflict_option_working_text_where_conflicted,
> + SVN_CL__ACCEPT_MINE_CONFLICT },
> + { "tc", svn_client_conflict_option_incoming_text_where_conflicted,
> + SVN_CL__ACCEPT_THEIRS_CONFLICT },
> + { "mf", svn_client_conflict_option_working_text,
> + SVN_CL__ACCEPT_MINE_FULL},
> + { "tf", svn_client_conflict_option_incoming_text,
> + SVN_CL__ACCEPT_THEIRS_FULL },
> + { "p", svn_client_conflict_option_postpone,
> + SVN_CL__ACCEPT_POSTPONE },
>
> /* This option resolves a tree conflict to the current working copy state. */
> - { "r", NULL, NULL,
> - svn_client_conflict_option_accept_current_wc_state,
> - SVN_CL__ACCEPT_WORKING },
> + { "r", svn_client_conflict_option_accept_current_wc_state,
> + SVN_CL__ACCEPT_WORKING },
>
> /* These options use the same code since they only occur in
> * distinct conflict scenarios. */
> - { "u", N_("update move destination"), NULL,
> - svn_client_conflict_option_update_move_destination },
> - { "u", N_("update any moved-away children"), NULL,
> - svn_client_conflict_option_update_any_moved_away_children },
> + { "u", svn_client_conflict_option_update_move_destination },
> + { "u", svn_client_conflict_option_update_any_moved_away_children },
>
> /* Options for incoming add vs local add. */
> - { "i", N_("ignore incoming addition"), NULL,
> - svn_client_conflict_option_incoming_add_ignore },
> + { "i", svn_client_conflict_option_incoming_add_ignore },
>
> /* Options for incoming file add vs local file add upon merge. */
> - { "m", N_("merge the files"), NULL,
> - svn_client_conflict_option_incoming_added_file_text_merge },
> - { "M", N_("replace my file with incoming file and merge the files"), NULL,
> - svn_client_conflict_option_incoming_added_file_replace_and_merge },
> + { "m", svn_client_conflict_option_incoming_added_file_text_merge },
> + { "M", svn_client_conflict_option_incoming_added_file_replace_and_merge },
>
> /* Options for incoming dir add vs local dir add upon merge. */
> - { "m", N_("merge the directories"), NULL,
> - svn_client_conflict_option_incoming_added_dir_merge },
> - { "R", N_("delete my directory and replace it with incoming directory"), NULL,
> - svn_client_conflict_option_incoming_added_dir_replace },
> - { "M", N_("replace my directory with incoming directory and merge"), NULL,
> - svn_client_conflict_option_incoming_added_dir_replace_and_merge },
> + { "m", svn_client_conflict_option_incoming_added_dir_merge },
> + { "R", svn_client_conflict_option_incoming_added_dir_replace },
> + { "M", svn_client_conflict_option_incoming_added_dir_replace_and_merge },
>
> /* Options for incoming delete vs any. */
> - { "i", N_("ignore incoming deletion"), NULL,
> - svn_client_conflict_option_incoming_delete_ignore },
> - { "a", N_("accept incoming deletion"), NULL,
> - svn_client_conflict_option_incoming_delete_accept },
> + { "i", svn_client_conflict_option_incoming_delete_ignore },
> + { "a", svn_client_conflict_option_incoming_delete_accept },
>
> /* Options for incoming move vs local edit. */
> - { "m", NULL, NULL, svn_client_conflict_option_incoming_move_file_text_merge },
> - { "m", NULL, NULL, svn_client_conflict_option_incoming_move_dir_merge },
> + { "m", svn_client_conflict_option_incoming_move_file_text_merge },
> + { "m", svn_client_conflict_option_incoming_move_dir_merge },
>
> { NULL }
> };
>
> /* Extra resolver options offered by 'svn' for any conflict. */
> -static const resolver_option_t extra_resolver_options[] =
> +static const client_option_t extra_resolver_options[] =
> {
> /* Translators: keep long_desc below 70 characters (wrap with a left
> margin of 9 spaces if needed) */
> @@ -458,7 +449,7 @@
>
>
> /* Additional resolver options offered by 'svn' for a text conflict. */
> -static const resolver_option_t extra_resolver_options_text[] =
> +static const client_option_t extra_resolver_options_text[] =
> {
> /* Translators: keep long_desc below 70 characters (wrap with a left
> margin of 9 spaces if needed) */
> @@ -485,7 +476,7 @@
> };
>
> /* Additional resolver options offered by 'svn' for a property conflict. */
> -static const resolver_option_t extra_resolver_options_prop[] =
> +static const client_option_t extra_resolver_options_prop[] =
> {
> /* Translators: keep long_desc below 70 characters (wrap with a left
> margin of 9 spaces if needed) */
> @@ -501,7 +492,7 @@
> };
>
> /* Additional resolver options offered by 'svn' for a tree conflict. */
> -static const resolver_option_t extra_resolver_options_tree[] =
> +static const client_option_t extra_resolver_options_tree[] =
> {
> /* Translators: keep long_desc below 70 characters (wrap with a left
> margin of 9 spaces if needed) */
> @@ -522,11 +513,11 @@
>
> /* Return a pointer to the option description in OPTIONS matching the
> * one- or two-character OPTION_CODE. Return NULL if not found. */
> -static const resolver_option_t *
> -find_option(const resolver_option_t *options,
> +static const client_option_t *
> +find_option(const client_option_t *options,
> const char *option_code)
> {
> - const resolver_option_t *opt;
> + const client_option_t *opt;
>
> for (opt = options; opt->code; opt++)
> {
> @@ -539,24 +530,51 @@
>
> /* Return a pointer to the option description in OPTIONS matching the
> * conflict option ID CHOICE. Return NULL if not found. */
> -static const resolver_option_t *
> -find_option_by_id(const resolver_option_t *options,
> - svn_client_conflict_option_id_t choice)
> +static svn_error_t *
> +find_option_by_builtin(struct client_option_t **out,
> + const resolver_option_t *options,
> + svn_client_conflict_option_t *builtin_option,
> + apr_pool_t *result_pool,
> + apr_pool_t *scratch_pool)
> {
> const resolver_option_t *opt;
> + svn_client_conflict_option_id_t id;
>
> + *out = NULL;
I think it would be more clear to set '*out = NULL' at the end of the
function. But the all code will be simplified if we drop svn_error_t
from svn_client_option_get_label().

> +
> + id = svn_client_conflict_option_get_id(builtin_option);
> +
> for (opt = options; opt->code; opt++)
> {
> - if (opt->choice == choice)
> - return opt;
> + if (opt->choice == id)
> + {
> + client_option_t *client_opt;
> +
> + client_opt = apr_pcalloc(result_pool, sizeof(*client_opt));
> + client_opt->choice = id;
> + client_opt->code = opt->code;
> + SVN_ERR(svn_client_conflict_option_label(&client_opt->label,
> + builtin_option,
> + result_pool,
> + scratch_pool));
Indentation problem: function arguments should be aligned:
[[
          SVN_ERR(svn_client_conflict_option_label(&client_opt->label,
                                                   builtin_option,
                                                   result_pool,
                                                   scratch_pool));
]]

> + SVN_ERR(svn_client_conflict_option_describe(&client_opt->long_desc,
> + builtin_option,
> + result_pool,
> + scratch_pool));
> + client_opt->accept_arg = opt->accept_arg;
> +
> + *out = client_opt;
> +
> + return SVN_NO_ERROR;
> + }
> }
> - return NULL;
> + return SVN_NO_ERROR;
> }
>
[...]

> @@ -693,7 +711,7 @@
>
> /* Set *OPTIONS to an array of resolution options for CONFLICT. */
> static svn_error_t *
> -build_text_conflict_options(resolver_option_t **options,
> +build_text_conflict_options(client_option_t **options,
> svn_client_conflict_t *conflict,
> svn_client_ctx_t *ctx,
> svn_boolean_t is_binary,
> @@ -700,8 +718,8 @@
> apr_pool_t *result_pool,
> apr_pool_t *scratch_pool)
> {
> - resolver_option_t *opt;
> - const resolver_option_t *o;
> + client_option_t *opt;
> + const client_option_t *o;
> apr_array_header_t *builtin_options;
> apr_size_t nopt;
> int i;
> @@ -714,7 +732,7 @@
> nopt = builtin_options->nelts + ARRAY_LEN(extra_resolver_options);
> if (!is_binary)
> nopt += ARRAY_LEN(extra_resolver_options_text);
> - *options = apr_pcalloc(result_pool, sizeof(*opt) * (nopt + 1));
> + *options = apr_pcalloc(result_pool, sizeof(opt) * (nopt + 1));
This change looks suspicions: Are you sure that you passing write size
to apr_pcalloc()?

[...]

svn_client_conflict_option_label

[1] https://subversion.apache.org/docs/community-guide/conventions.html#log-messages

-- 
Ivan Zhakov
Received on 2016-10-12 16:44:44 CEST

This is an archived mail posted to the Subversion Dev mailing list.