Gabriela Gibson wrote on Mon, Apr 29, 2013 at 21:31:09 +0100: > Take two. > > Thanks for looking! > > Gabriela > > [[[ > Add new diff option "--invoke-diff-cmd" which allows the user to > define a custom command line or config file entry for an external > diff program. > > * subversion/include/svn_client.h > (svn_client_diff6): Deprecate. Add new Doxygen comment. > (svn_client_diff7): Add new Doxygen comment. > (svn_client_diff7): New function.
"New doxygen comment" is too low-level; I think what you mean is "Add docstring" (or "Document" (as a verb)), but that's an implicit part of adding a new function; it's not interesting enough for a log message. Counter-suggestion: * foo.h (foo6): Deprecate. (foo7): Declare the new API. Like foo6 but with invoke_diff_cmd parameter. > (svn_client_diff_peg_6): Deprecate. Refresh Doxygen comment. > (svn_client_diff_peg_7): New function. > > * subversion/include/svn_config.h > (SVN_CONFIG_OPTION_INVOKE_DIFF_CMD): New definition. > The '(' should have two, not three, preceding spaces. > * subversion/include/svn_io.h > (svn_io_create_custom_diff_cmd): New function. > (svn_io_run_external_diff): New function. > > * subversion/libsvn_client/deprecated.c > (svn_client_diff6): Deprecate. > (svn_client_diff_peg6): Deprecate. > > * subversion/libsvn_client/diff.c > (struct diff_cmd_baton): New variable. > s/variable/member/, and it would be good to mention it's name. > (diff_content_changed): Call svn_io_run_external_diff if > --invoke-diff-cmd option was specied, otherwise retain previous > behaviour. > "specified". Personally, I normally indent follow-up lines with one or two spaces in addition to the two that precede the '(' (so 3-4 spaces), too. > (set_up_diff_cmd_and_options): Apply invoke-diff-cmd option > preferentially. Old behavior unchanged. Not "behaviour"? > * subversion/svn/diff-cmd.c > (svn_cl__diff): Modify call to deprecated function. > That sentence sounds like you reshuffle the parameters in a call to svn_client_diff6(). What you actually do is call svn_client_diff7() instead. You might want to check svn logs to see what phrasing we normally use? (The most common one is "Update callers", but that one is used primarily changing a function's signature without revving the function.) > * subversion/svn/svn.c > (svn_cl__options[]): New variable and help info. > (svn_cl__cmd_table[]): New variable. > (sub_main): Add exclusiveness condition. Expand if condition. Julian already pointed out the following to you previously: "Expand if condition" describes the shape of the source code change, not the end (difference of functionality) it achieves. > ]]] > Index: subversion/include/svn_client.h > =================================================================== > --- subversion/include/svn_client.h (revision 1475745) > +++ subversion/include/svn_client.h (working copy) > @@ -2986,6 +2986,9 @@ svn_client_blame(const char *path_or_url, > * The above two options are mutually exclusive. It is an error to set > * both to TRUE. > * > + * If @a invoke_diff_cmd is non-null, invoke external diff command > + * with the string it contains. > + * I don't find this sentence clear. The text supports 4 interpretations: c = svn_config_get(..., "external-diff-cmd") subprocess.check_call(invoke_diff_cmd, shell=True) subprocess.check_call(c + ' ' + invoke_diff_cmd, shell=True) subprocess.check_call([c, invoke_diff_cmd]) subprocess.check_call(c, shell=True, stdin=svn_stream_from_stringbuf(invoke_diff_cmd)) Can you please be clearer in the docstring, which one (if any!) it is. > * Generated headers are encoded using @a header_encoding. > * > * Diff output will not be generated for binary files, unless @a > @@ -3015,9 +3018,39 @@ svn_client_blame(const char *path_or_url, > * > * @note @a relative_to_dir doesn't affect the path index generated by > * external diff programs. > + * Indentation > + * @since New in 1.8. s/8/9/ > + */ > +svn_error_t * > +svn_client_diff7(const apr_array_header_t *options, > + const char *path_or_url1, > + const svn_opt_revision_t *revision1, > + const char *path_or_url2, > + const svn_opt_revision_t *revision2, > + const char *relative_to_dir, > + svn_depth_t depth, > + svn_boolean_t ignore_ancestry, > + svn_boolean_t no_diff_added, > + svn_boolean_t no_diff_deleted, > + svn_boolean_t show_copies_as_adds, > + svn_boolean_t ignore_content_type, > + svn_boolean_t ignore_properties, > + svn_boolean_t properties_only, > + svn_boolean_t use_git_diff_format, > + const char *header_encoding, > + svn_stream_t *outstream, > + svn_stream_t *errstream, > + const apr_array_header_t *changelists, > + svn_client_ctx_t *ctx, > + apr_pool_t *pool, > + const char *invoke_diff_cmd); "ctx" and "pool" are always last, I think. So please preserve that convention, add "invoke_diff_cmd" earlier. > Index: subversion/include/svn_config.h > =================================================================== > --- subversion/include/svn_config.h (revision 1475745) > +++ subversion/include/svn_config.h (working copy) > @@ -112,6 +112,7 @@ typedef struct svn_config_t svn_config_t; > #define SVN_CONFIG_OPTION_DIFF_EXTENSIONS "diff-extensions" > #define SVN_CONFIG_OPTION_DIFF3_CMD "diff3-cmd" > #define SVN_CONFIG_OPTION_DIFF3_HAS_PROGRAM_ARG "diff3-has-program-arg" /** @since New in 1.9. */ > +#define SVN_CONFIG_OPTION_INVOKE_DIFF_CMD "invoke-diff-cmd" > #define SVN_CONFIG_OPTION_MERGE_TOOL_CMD "merge-tool-cmd" > #define SVN_CONFIG_SECTION_MISCELLANY "miscellany" > #define SVN_CONFIG_OPTION_GLOBAL_IGNORES "global-ignores" > Index: subversion/include/svn_io.h > =================================================================== > --- subversion/include/svn_io.h (revision 1475745) > +++ subversion/include/svn_io.h (working copy) > @@ -2273,8 +2273,39 @@ svn_io_file_readline(apr_file_t *file, > apr_pool_t *result_pool, > apr_pool_t *scratch_pool); > > +/* Parse a user defined command to contain dynamically > + * created labels and filenames. > + * You need "/**" for doxygen. > + ** @since New in 1.8. (?) > + */ > /** @} */ > +const char ** > +svn_io_create_custom_diff_cmd(const char *label1, > + const char *label2, You haven't addressed my comment about not adding the docstring and declarations on opposite sides of doxygen section-end markers ("@}"). > Index: subversion/libsvn_client/deprecated.c > Index: subversion/libsvn_client/diff.c > Index: subversion/libsvn_subr/io.c I didn't review these parts. > Index: subversion/libsvn_subr/config_file.c > =================================================================== > --- subversion/libsvn_subr/config_file.c (revision 1475745) > +++ subversion/libsvn_subr/config_file.c (working copy) > @@ -1084,6 +1084,12 @@ svn_config_ensure(const char *config_dir, apr_pool > "### Set diff3-has-program-arg to 'yes' if your 'diff3' program" > NL > "### accepts the '--diff-program' option." > NL > "# diff3-has-program-arg = [yes | no]" > NL > + "### Set invoke-diff-cmd to the absolute path of your diff'" > NL > + "### program." > NL > + "### This will override the compile-time default, which is to use" > NL > + "### Subversion's internal diff implementation." > NL > + "### invoke-diff-cmd = " > NL > + "### diff_program (diff, gdiff, etc.) <options> <substitutions>" > NL s/###/#/ for consistency > "### Set merge-tool-cmd to the command used to invoke your external" > NL > "### merging tool of choice. Subversion will pass 5 arguments to" > NL > "### the specified command: base theirs mine merged wcfile" > NL > Index: subversion/svn/cl.h > =================================================================== > --- subversion/svn/cl.h (revision 1475745) > +++ subversion/svn/cl.h (working copy) > @@ -181,6 +181,8 @@ typedef struct svn_cl__opt_state_t > struct > { > const char *diff_cmd; /* the external diff command to use */ > + const char *invoke_diff_cmd; /* the format string to specify args > */ > + /* for the external diff cmd > */ > svn_boolean_t internal_diff; /* override diff_cmd in config file */ > svn_boolean_t no_diff_added; /* do not show diffs for deleted files > */ > svn_boolean_t no_diff_deleted; /* do not show diffs for deleted files > */ > @@ -213,6 +215,7 @@ typedef struct svn_cl__opt_state_t > const char *changelist; /* operate on this changelist > THIS IS TEMPORARY (LAST OF CHANGELISTS) > */ > svn_boolean_t keep_changelists;/* don't remove changelists after commit */ > + const char *invoke_diff_cmd; /* external customizable diff command > */ You didn't address (or disagree with) an earlier review point about not naming a struct member and the same struct's nested struct's member the same. > svn_boolean_t keep_local; /* delete path only from repository */ > svn_boolean_t all_revprops; /* retrieve all revprops */ > svn_boolean_t no_revprops; /* retrieve no revprops */ > Index: subversion/svn/svn.c > =================================================================== > --- subversion/svn/svn.c (revision 1475745) > +++ subversion/svn/svn.c (working copy) > @@ -84,6 +84,7 @@ typedef enum svn_cl__longopt_t { > opt_ignore_properties, > opt_properties_only, > opt_patch_compatible, > + opt_invoke_diff_cmd, > /* end of diff options */ > opt_dry_run, > opt_editor_cmd, > @@ -336,6 +337,55 @@ const apr_getopt_option_t svn_cl__options[] = > {"diff", opt_diff, 0, N_("produce diff output")}, /* maps to show_diff */ > /* diff options */ > {"diff-cmd", opt_diff_cmd, 1, N_("use ARG as diff command")}, > +#ifdef WIN32 > + {"invoke-diff-cmd", opt_invoke_diff_cmd, 1, > + N_("use ARG as format string for external diff command\n" > + " " > + "invocation. \n > \n" > + " " > + "Substitutions: ---f1 ---f2 files to compare > \n" > + " " > + " ---l1 ---l2 user defined labels > \n" > + " " > + "Examples: --invoke-diff-cmd=\"diff -y ---f1 ---f2 > \n" > + " --invoke-diff-cmd=\"kdiff3 -auto -o /home/u/log \\ > \n" > + " " > + " ---f1 ---f2 --L1 ---l1 --L2 \"Custom Label\"\" > \n" > + " " > + "The switch symbol '%' can be modified by defining an > \n" > + " " > + "alternative symbol string, starting with '#', '$' or > '-'\n" > + " " > + "Example: > \n" > + " " > + " --invoke-diff-cmd=\"%% diff -y %%f1 %%f2\" > \n" > + )}, > +#else > + {"invoke-diff-cmd", opt_invoke_diff_cmd, 1, > + N_("use ARG as format string for external diff command\n" > + " " > + "invocation. \n > \n" > + " " > + "Substitutions: %f1 %f2 files to compare > \n" > + " " > + " %l1 %l2 user defined labels > \n" > + " " > + "Examples: --invoke-diff-cmd=\"diff -y %f1 %f2 > \n" > + " " > + " --invoke-diff-cmd=\"kdiff3 -auto -o /home/u/log \\ > \n" > + " " > + " %f1 %f2 --L1 %l1 --L2 \"Custom Label\" \" > \n" > + " " > + "The switch symbol '%' can be modified by defining an > \n" > + " " > + "alternative symbol string, starting with '#','$' or > '-'\n" > + " " > + "Example: > \n" > + " " > + " --invoke-diff-cmd=\"--- diff -y ---f1 ---f2\" > \n" > + )}, > +#endif /* WIN32 */ > + Having a different UI for WIN32 and !WIN32 is a bad idea; uniformity is better. Let's try and agree on a config file syntax first. Requirements for that syntax: - easy to read - easy to parse - allows specifying the replaceable multiple times - allows escaping, i.e., allows specifying the replaceable literally - easy to enter (this is meant to rule out '%' and its double-escaping hell) - (other requirements?) (stopping without suggesting a concrete format, pending an ongoing IRC discussion) > {"internal-diff", opt_internal_diff, 0, > N_("override diff-cmd specified in config file")}, > {"no-diff-added", opt_no_diff_added, 0, > @@ -2497,6 +2551,14 @@ sub_main(int argc, const char *argv[], apr_pool_t > return EXIT_ERROR(err); > } > > + if (opt_state.diff.invoke_diff_cmd && opt_state.diff.internal_diff) > + { > + err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, > + _("--invoke_diff_cmd and --internal-diff " s/_/-/ > + "are mutually exclusive")); > + return EXIT_ERROR(err); > + }