You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by gb...@apache.org on 2013/10/26 21:02:27 UTC
svn commit: r1536020 - in /subversion/branches/invoke-diff-cmd-feature:
BRANCH-README diff_cmd_config subversion/include/svn_io.h
subversion/libsvn_subr/io.c subversion/svn/svn.c
Author: gbg
Date: Sat Oct 26 19:02:27 2013
New Revision: 1536020
URL: http://svn.apache.org/r1536020
Log:
On the invoke-diff-cmd-feature branch: Add per file diff support which
uses an arbitrary config file.
* BRANCH-README: Update to reflect the latest changes.
* diff_cmd_config: Temporary file for demonstration/testing purposes.
* subversion/include/svn_io.h
(svn_io_parse_diff_cmd_file): New temporary function.
* subversion/libsvn_subr/io.c
(svn_io_run_external_diff): Add selection mechanism.
(svn_io_parse_diff_cmd_file): New temporary function.
* subversion/svn/svn.c
(svn_cl__options[]): Update svn diff help to explain the new
feature.
Added:
subversion/branches/invoke-diff-cmd-feature/diff_cmd_config
Modified:
subversion/branches/invoke-diff-cmd-feature/BRANCH-README
subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_io.h
subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/io.c
subversion/branches/invoke-diff-cmd-feature/subversion/svn/svn.c
Modified: subversion/branches/invoke-diff-cmd-feature/BRANCH-README
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/BRANCH-README?rev=1536020&r1=1536019&r2=1536020&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/BRANCH-README (original)
+++ subversion/branches/invoke-diff-cmd-feature/BRANCH-README Sat Oct 26 19:02:27 2013
@@ -8,7 +8,7 @@ See: http://subversion.tigris.org/issues
original motivation for this project.
--invoke-diff-cmd allows command line selection of an external diff
-program and will be extended to cover the existing diff3 option with a
+program and will be extended to cover the existing diff3 option with
similar --invoke-diff3-cmd option.
Currently this capability is provided by user written shell scripts
@@ -19,28 +19,28 @@ which are passed as the diff program via
What --invoke-diff-cmd and --invoke-diff3-cmd provide
-=====================================================
+------------------------------------------------------
Users can type 'free-style' command lines for their selected
diff/merge program, from 'svn help diff':
--invoke-diff-cmd ARG:
- use ARG as format string for external diff command
- invocation.
-
- Substitutions: %svn_new% new file
- %svn_old% old file
- %svn_new_label% label of the new file
- %svn_old_label% label of the old file
- Examples:
- --invoke-diff-cmd='diff -y %svn_new% %svn_old%'
- --invoke-diff-cmd="kdiff3 -auto -o /home/u/log \
- %svn_new% %svn_old% --L1 %svn_new_label% \
- --L2 "Custom Label" '
- Other constructs possible are:
- +%svn_new%, %svn_new%- and +++%svn_new_label%+++
-
+ use ARG as format string for external diff command
+ invocation.
+
+ Substitutions: ;f1 original file
+ ;f2 changed file
+ ;l1 label of the original file
+ ;l2 label of the changed file
+ Examples: --invoke-diff-cmd="diff -y ;f1 ;f2"
+ --invoke-diff-cmd="kdiff3 -auto -o /home/u/log \
+ +;f1 ;l2 --L1 ;l1 --L2 "Custom Label" "
+
+ The delimiter ';' can be escaped by adding a ';', which will be
+ consumed in the process. The delimiter can appear anywhere in the
+ string, ie, file=;f1 will expand as expected and file=;;f1 will be
+ rendered as file=;f1.
Structure of the feature:
=========================
@@ -51,17 +51,18 @@ API components
./subversion/libsvn_subr/io.c:3030 __create_custom_diff_cmd()
transforms the user input 'invoke-diff-cmd' into a command line
- call by substitution the labels and file names(where defined),
- whilst leaving everything else untouched. This is more of an
- internal routine and probably not well placed in the public API.
- It will be reused for the merge part of this project.
+ call by substitution the file names, whilst leaving everything else
+ untouched. This is more of an internal routine and probably not
+ well placed in the API. It will be reused for the merge part of
+ this project.
+ NOTE:
./subversion/libsvn_subr/io.c:3108 svn_io_run_external_diff()
- calls __create_custom_diff_cmd() and does all the error checking
- required, before routing the result to the actual call to the APR
- routine that makes it.
+ calls svn_io_create_custom_diff_cmd() and does all the error
+ checking required, before routing the result to the actual call to
+ the APR routine that makes it.
UI components
@@ -82,32 +83,34 @@ UI components
one of --invoke-diff-cmd, --diff-cmd or --internal-diff-cmd are
invoked.
-
Changes to the existing code structure:
=======================================
-The original --diff-cmd parsing and routing code has been refactored
+the original --diff-cmd parsing and routing code has been deprecated
and the call to --diff-cmd is now handled by the
-__create_custom_diff_cmd() and svn_io_run_external_diff() routines.
-All the original functionality and user syntax has been retained.
-
+svn_io_create_custom_diff_cmd() and svn_io_run_external_diff()
+routines. All the original functionality and user syntax has been
+retained.
-Tests
+TESTS
=====
-The test for the 'invoke-diff-cmd' feature is
+The test for this feature is
+
+/subversion/tests/cmdline/diff_tests.py diff_invoke_external_diffcmd
- /subversion/tests/cmdline/diff_tests.py diff_invoke_external_diffcmd
The test for the updated --diff-cmd is
- /subversion/tests/cmdline/diff_tests.py diff_external_diffcmd
+/subversion/tests/cmdline/diff_tests.py diff_external_diffcmd
TODO:
====
- * add help info to log, svnlook
+ * add invoke-diff-cmd option to the blame section
+
+ * add help info to log, svnlook, blame
* Adding invoke-diff-cmd to merge:
add --invoke-diff-3-cmd using the svn_io_create_custom_diff_cmd()
@@ -122,170 +125,4 @@ TODO:
http://subversion.tigris.org/issues/show_bug.cgi?id=3836
-Review tools
-============
-
-The entire code of the branch can be obtained thus:
-
-svn diff ^/subversion/trunk@1531612\
- ^/subversion/branches/invoke-diff-cmd-feature
-
-To obtain a visitable list of files with line numbers in the Emacs
-compilation buffer:
-
-M-x cd /branches/invoke-diff-cmd-feature/
-M-x compile
-svn diff ^/subversion/trunk@1531612\
- ^/subversion/branches/invoke-diff-cmd-feature |\
- perl -ne '/Index: (.*)$/ && ($name = $1);
- /^@@.*\+(\d+),/ && print "./$name:$1:diff\n";'
-
-
-Log messages of salient code changes
-====================================
-
-* subversion/include/svn_client.h
-
- (svn_client_diff7, svn_client_diff_peg7): Declare the new API. Like
- svn_client_diff[_peg]6 but with invoke_diff_cmd parameter.
-
- (svn_client_diff6, svn_client_diff_peg_6): Deprecate.
-
-
-* subversion/svn/log-cmd.c
-
- (svn_client_diff_peg7): Update call to svn_client_diff_peg6 to
- svn_client_diff_peg7.
-
- (log_receiver_baton): New struct member invoke_diff_cmd.
-
- (display_diff): New parameter 'invoke_diff_cmd' . Pass
- invoke_diff_cmd parameter into svn_client_diff_peg7().
-
- (log_entry_receiver): Pass invoke_diff_cmd into display_diff().
-
- (svn_cl__log): Ensure mutual exclusions between invoke_diff_cmd and
- quiet and diff-cmd, require 'diff' option. Populate
- log_receiver_baton member invoke_diff_cmd.
-
- (svn_cl__options): Expand help info for invoke-diff-cmd option.
-
-
-* subversion/include/svn_config.h
-
- (SVN_CONFIG_OPTION_INVOKE_DIFF_CMD): New definition.
-
-
-* subversion/include/svn_io.h
-
- (svn_io_create_custom_diff_cmd): New function.
-
- (svn_io_run_external_diff): New function.
-
- (svn_io_run_diff2): Deprecate function.
-
-
-* subversion/libsvn_client/deprecated.c
-
- (svn_client_diff6, svn_client_diff_peg6): New deprecation wrappers.
-
-
-* subversion/libsvn_client/diff.c
-
- (struct diff_cmd_baton): New member: 'invoke_diff_cmd'.
-
- (diff_content_changed): Call svn_io_run_external_diff if
- --invoke-diff-cmd option was specified, otherwise retain previous
- behaviour.
-
- (set_up_diff_cmd_and_options): Apply invoke-diff-cmd option
- preferentially. Old behaviour unchanged.
-
- (svn_client_diff_peg_7): Rename and update from
- svn_client_diff_peg_6. Add new parameter: invoke_diff_cmd.
-
- (svn_client_diff7): Rename and update from svn_client_diff6, add
- new parameter 'invoke_diff_cmd'.
-
- (): Update all comments mentioning 'svn_client_diff6' to
- 'svn_client_diff7'.
-
- (diff_content_changed): Raise an error if both diff_cmd and
- invoke-diff-cmd are set.
-
-
-* subversion/libsvn_subr/config_file.c
-
- (svn_config_ensure): New entry: invoke-diff-cmd.
-
-
-* subversion/libsvn_subr/io.c
-
- (svn_io_create_custom_diff_cmd): New function.
-
- (svn_io_run_external_diff): New function.
-
-
-* subversion/svn/cl.h
-
- (struct svn_cl__opt_state_t.diff): New member: 'invoke_diff_cmd'.
-
-
-* subversion/svn/diff-cmd.c
-
- (svn_cl__diff): Update call to svn_client_diff6 to svn_client_diff7.
-
-
-* subversion/svn/svn.c
-
- (svn_cl__options[]): Add help info and new variable:
- 'opt_invoke_diff_cmd'.
-
- (svn_cl__cmd_table[]): New option: 'invoke-diff-cmd'.
-
- (sub_main): Prohibit simultaneous usage of --invoke-diff-cmd and
- --internal-diff. Add new opt_state.diff.invoke-diff-cmd option
- to the option selector. Add call to svn_config_set.
-
- (svn_cl__cmd_table): Add opt_invoke_diff_cmd to the list of valid
- sub-commands.
-
- (sub_main): Add guard against concurrent usage of incompatible diff
- options. Remove previous guard code.
-
-
-* subversion/tests/cmdline/diff_tests.py
-
- (diff_invoke_external_diffcmd): New function.
-
- (test_list): Add new entry 'diff_invoke_external_diffcmd'.
-
-
-* subversion/include/svn_error_codes.h
-
- (SVN_CLIENT_DIFF_CMD): New macro.
-
-
-* subversion/svnlook/svnlook.c
-
- (enum): New variable svnlook__invoke_diff_cmd.
-
- (options_table[]): New entry 'invoke-diff-cmd'.
-
- (cmd_tablcmd[]): Add svnlook__invoke_diff_cmd to diff cmd table
- entry.
-
- (svnlook_opt_state): New member variable "invoke_diff_cmd".
-
- (svnlook_ctxt_t): New member variable "invoke_diff_cmd".
-
- (print_diff_tree): Modify if condition to include new
- invoke_diff_cmd. Add conditional call to
- /include/svn_io.c:svn_io_run_external_diff().
-
- (get_ctxt_baton): Assign invoke_diff_cmd data.
-
- (main): Assign opt_arg to opt_state.invoke_diff_cmd. Add
- exclusiveness test for invoke_diff_cmd and diff_cmd.
-
Added: subversion/branches/invoke-diff-cmd-feature/diff_cmd_config
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/diff_cmd_config?rev=1536020&view=auto
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/diff_cmd_config (added)
+++ subversion/branches/invoke-diff-cmd-feature/diff_cmd_config Sat Oct 26 19:02:27 2013
@@ -0,0 +1,6 @@
+# this is to demonstrate the --svn-cfg-file feature.
+subversion/svn/svn.c = diff -L "test1" %svn_old% %svn_new%
+#
+subversion/libsvn_subr/io.c = diff -L "test2" %svn_old% %svn_new%
+#
+subversion/include/svn_io.h = diff -u -L "test3" %svn_old% %svn_new%
\ No newline at end of file
Modified: subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_io.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_io.h?rev=1536020&r1=1536019&r2=1536020&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_io.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_io.h Sat Oct 26 19:02:27 2013
@@ -2426,6 +2426,17 @@ svn_io_run_external_diff(const char *dir
const char *external_diff_cmd,
apr_pool_t *scratch_pool);
+
+/** Open the diff_cmd file which contains custom diff commands
+ * pertaining to individual files.
+ *
+ * @since New in 1.9.
+ */
+svn_error_t *
+svn_io_parse_diff_cmd_file(const char *diff_cmd_file,
+ apr_array_header_t *diff_file_data,
+ apr_pool_t *pool);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/io.c?rev=1536020&r1=1536019&r2=1536020&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/io.c Sat Oct 26 19:02:27 2013
@@ -3089,13 +3089,71 @@ __create_custom_diff_cmd(const char *lab
strlen(tokens_tab[i].replace));
i = delimiters;
}
- result[argv] = word->data;
+ result[argv] = apr_pstrdup(scratch_pool, word->data);
}
result[argv] = NULL;
svn_pool_destroy(scratch_pool);
return result;
}
+/* Copy pasta from svn_io_parse_mimetypes_file below. Should really
+refactor this as a generalised wrap that calls any given file and just
+hands back a stuffed array_header_t of the contents and lets the
+caller deal with the result. (but that's for another patch)
+*/
+svn_error_t *
+svn_io_parse_diff_cmd_file(const char *diff_cmd_file,
+ apr_array_header_t *diff_file_data,
+ apr_pool_t *pool)
+{
+ svn_error_t *err = SVN_NO_ERROR;
+ svn_boolean_t eof = FALSE;
+ svn_stringbuf_t *buf;
+ apr_pool_t *subpool = svn_pool_create(pool);
+ apr_file_t *types_file;
+ svn_stream_t *mimetypes_stream;
+
+ SVN_ERR(svn_io_file_open(&types_file, diff_cmd_file,
+ APR_READ, APR_OS_DEFAULT, pool));
+ mimetypes_stream = svn_stream_from_aprfile2(types_file, FALSE, pool);
+
+ while (1)
+ {
+ svn_pool_clear(subpool);
+
+ /* Read a line. */
+ if ((err = svn_stream_readline(mimetypes_stream, &buf,
+ APR_EOL_STR, &eof, subpool)))
+ break;
+
+ /* Only pay attention to non-empty, non-comment lines. */
+ if (buf->len)
+ {
+ if (buf->data[0] == '#')
+ continue;
+
+ APR_ARRAY_PUSH(diff_file_data, char*)
+ = apr_pstrdup(pool, buf->data);
+ }
+ if (eof)
+ break;
+ }
+ svn_pool_destroy(subpool);
+
+ /* If there was an error above, close the file (ignoring any error
+ from *that*) and return the originally error. */
+ if (err)
+ {
+ svn_error_clear(svn_stream_close(mimetypes_stream));
+ return err;
+ }
+
+ /* Close the stream (which closes the underlying file, too). */
+ SVN_ERR(svn_stream_close(mimetypes_stream));
+
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_io_run_external_diff(const char *dir,
const char *label1,
@@ -3108,17 +3166,88 @@ svn_io_run_external_diff(const char *dir
const char *external_diff_cmd,
apr_pool_t *pool)
{
- int exitcode;
+ int exitcode, file_in_list = 0, has_switch = 0;
const char ** cmd;
-
+ char *diff_cmd, *the_config;
+ apr_array_header_t *diff_file_data;
+ svn_stringbuf_t *the_cmd;
+ apr_array_header_t *words;
apr_pool_t *scratch_pool = svn_pool_create(pool);
if (0 == strlen(external_diff_cmd))
return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, NULL);
+ diff_cmd = apr_palloc(pool,
+ ( (sizeof(external_diff_cmd)+1) *sizeof(char *) ) );
+
+ if (strstr(external_diff_cmd, "--svn-cfg-file-query") )
+ has_switch = 2;
+ else if (strstr(external_diff_cmd, "--svn-cfg-file"))
+ has_switch = 1;
+
+ the_cmd = svn_stringbuf_create_empty(scratch_pool);
+
+ if (has_switch)
+ {
+ int i;
+
+ diff_file_data = apr_array_make(scratch_pool, 0, sizeof(char*));
+
+ words = apr_array_make(scratch_pool, 0, sizeof(char **));
+ words = svn_cstring_split(external_diff_cmd, " ", TRUE, scratch_pool);
+
+ the_config = apr_palloc(pool, sizeof(APR_ARRAY_IDX(words, 1, char*)) );
+ the_config = APR_ARRAY_IDX(words, 1, char*);
+
+ SVN_ERR(svn_io_parse_diff_cmd_file(the_config,
+ diff_file_data,
+ scratch_pool));
+
+ for (i = 0; i < diff_file_data->nelts; i++)
+ {
+ apr_array_header_t *tokens;
+
+ tokens = svn_cstring_split(APR_ARRAY_IDX(diff_file_data,
+ i, char *),
+ "=", TRUE, scratch_pool);
+
+ if (strstr(label1, APR_ARRAY_IDX(tokens, 0, char *)) )
+ {
+ diff_cmd = APR_ARRAY_IDX(tokens, 1, char *);
+ i = diff_file_data->nelts; /* found, so we're done here */
+ file_in_list = 1;
+ }
+ }
+
+ if (file_in_list)
+ {
+
+ if (2 == has_switch)
+ {
+ /* here we'd show the user the two different cmds and
+ let them choose which one. Not built yet, b/c I've
+ not worked out yet how to make a hook for a client
+ here.
+ */
+ ;
+ }
+ }
+ else
+ { /* build the command from what's in the external_diff_cmd */
+ for (i = 2; i < words->nelts; i++)
+ {
+ svn_stringbuf_appendcstr(the_cmd, APR_ARRAY_IDX(words, i, char *));
+ svn_stringbuf_appendcstr(the_cmd, " ");
+ }
+ diff_cmd = apr_pstrdup(scratch_pool, the_cmd->data);
+ }
+ } /* close has_switch */
+ else /* no switch found, just a diff cmd */
+ diff_cmd = apr_pstrdup(scratch_pool, external_diff_cmd);
+
cmd = __create_custom_diff_cmd(label1, label2, NULL,
tmpfile1, tmpfile2, NULL,
- external_diff_cmd, scratch_pool);
+ diff_cmd, scratch_pool);
if (pexitcode == NULL)
pexitcode = &exitcode;
Modified: subversion/branches/invoke-diff-cmd-feature/subversion/svn/svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/svn/svn.c?rev=1536020&r1=1536019&r2=1536020&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/svn/svn.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/svn/svn.c Sat Oct 26 19:02:27 2013
@@ -371,6 +371,24 @@ const apr_getopt_option_t svn_cl__option
"Other constructs possible are: \n"
" "
"+%svn_new%, %svn_new%- and +++%svn_new_label%+++ \n"
+ " "
+ "With optional switch given at the start of the command:\n"
+ " "
+ "--svn-cfg-file=/path/to/config-file (automatic) \n"
+ " "
+ "Read config file, apply the diff-cmds stored in there \n"
+ " "
+ "--query-cfg-file=/path/to/config-file (interactive) \n"
+ " "
+ "As above, but query interactively. \n"
+ " "
+ "Example: svn diff --invoke-diff-cmd=\'--svn-cfg-file\\ \n"
+ " "
+ " /home/user/diff_cmds diff -u %svn_new% %svn-old%\' \n"
+ " "
+ "Config file format: (accepts # comments) \n"
+ " "
+ "relative/path/to/file/ = diff %svn_new% ... \n"
)},
{"internal-diff", opt_internal_diff, 0,
N_("override diff-cmd specified in config file")},