On 12 October 2016 at 15:38, Patrick Steinhardt
<patrick.steinha...@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

Reply via email to