Hi,
my branch has grown into a veritable forest, and so, I thought that
it would be convenient to present the net code changes in a file called
'entire-branch-code' (attached).
This is generated like so:
1) Merge trunk to branch
2) run this bash command:
svn log --stop-on-copy | grep '^*\ subversion' |\
awk '{gsub(/^ +| +$/,"")} {print $0}' | cut -d '*' -f 2 |\
sort --unique | while read line; do echo $line | if [ -a $line ];\
then echo ""; echo \
"================================================================================";\
echo "";\
diff -p --context=0 -b -B -w "$HOME/trunk/$line" "$PWD/$line"; fi;\
done > entire-branch-code
Is this useful? Can this be improved?
thanks,
Gabriela
================================================================================
*** /home/g/trunk/subversion/include/svn_client.h 2013-09-24
21:40:40.306770699 +0100
--- /home/g/branches/invoke-diff-cmd-feature/subversion/include/svn_client.h
2013-09-26 13:50:43.967821533 +0100
*************** svn_client_blame(const char *path_or_url
*** 3023 ****
--- 3024,3028 ----
+ * @a invoke_diff_cmd is used to call an external diff program but may
+ * not be @c NULL. The command line invocation will override the
+ * invoke-diff-cmd invocation entry(if any) in the Subversion
+ * configuration file.
+ *
*************** svn_client_blame(const char *path_or_url
*** 3053 ****
--- 3059,3087 ----
+ * @since New in 1.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,
+ const char *invoke_diff_cmd,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool);
+
+ /** Similar to svn_client_diff7(), but with @a invoke_diff_cmd.
+ *
+ * @deprecated Provided for backward compatibility with the 1.8 API.
*************** svn_client_blame(const char *path_or_url
*** 3055 ****
--- 3090 ----
+ SVN_DEPRECATED
*************** svn_client_diff(const apr_array_header_t
*** 3213 ****
! * identically to svn_client_diff6(), using @a path_or_url for both of that
--- 3248 ----
! * identically to svn_client_diff7(), using @a path_or_url for both of that
*************** svn_client_diff(const apr_array_header_t
*** 3216 ****
! * All other options are handled identically to svn_client_diff6().
--- 3251 ----
! * All other options are handled identically to svn_client_diff7().
*************** svn_client_diff(const apr_array_header_t
*** 3217 ****
--- 3253,3285 ----
+ * @since New in 1.9.
+ */
+ svn_error_t *
+ svn_client_diff_peg7(const apr_array_header_t *diff_options,
+ const char *path_or_url,
+ const svn_opt_revision_t *peg_revision,
+ const svn_opt_revision_t *start_revision,
+ const svn_opt_revision_t *end_revision,
+ 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,
+ const char *invoke_diff_cmd,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool);
+
+
+ /**
+ * Similar to svn_client_peg7(), but with @a no_diff_added set to
+ * FALSE, @a ignore_properties set to FALSE and @a properties_only
+ * set to FALSE.
+ *
+ * @deprecated Provided for backward compatibility with the 1.7 API.
*************** svn_client_diff(const apr_array_header_t
*** 3219 ****
--- 3288 ----
+ SVN_DEPRECATED
*************** svn_client_diff_peg6(const apr_array_hea
*** 3243 ****
! /** Similar to svn_client_diff6_peg6(), but with @a outfile and @a errfile,
--- 3312,3313 ----
! /**
! * Similar to svn_client_diff6_peg6(), but with @a outfile and @a errfile,
================================================================================
*** /home/g/trunk/subversion/include/svn_config.h 2013-08-21
14:38:52.462504050 +0100
--- /home/g/branches/invoke-diff-cmd-feature/subversion/include/svn_config.h
2013-08-21 15:13:02.172668024 +0100
*************** typedef struct svn_config_t svn_config_t
*** 116 ****
--- 117,118 ----
+ /** @since New in 1.9. */
+ #define SVN_CONFIG_OPTION_INVOKE_DIFF_CMD "invoke-diff-cmd"
================================================================================
*** /home/g/trunk/subversion/include/svn_error_codes.h 2013-09-24
21:40:36.710752868 +0100
---
/home/g/branches/invoke-diff-cmd-feature/subversion/include/svn_error_codes.h
2013-09-26 13:50:41.575809672 +0100
*************** SVN_ERROR_START
*** 1206 ****
--- 1207,1211 ----
+ /** @since New in 1.9 */
+ SVN_ERRDEF(SVN_ERR_CLIENT_DIFF_CMD,
+ SVN_ERR_CLIENT_CATEGORY_START + 24,
+ "More than one diff command defined")
+
================================================================================
*** /home/g/trunk/subversion/include/svn_io.h 2013-08-07 20:56:48.269221179
+0100
--- /home/g/branches/invoke-diff-cmd-feature/subversion/include/svn_io.h
2013-10-12 14:15:01.434000142 +0100
*************** svn_io_run_cmd(const char *path,
*** 1824,1825 ****
! * @since New in 1.6.0.
! */
--- 1824 ----
! * @since New in 1.6.0. */
*************** svn_io_file_readline(apr_file_t *file,
*** 2348 ****
--- 2348,2412 ----
+
+ /** Parse a user defined command to contain dynamically created labels
+ * and filenames. This function serves both diff and diff3 parsing
+ * requirements.
+ *
+ * When used in a diff context: (responding parse tokens in braces)
+ *
+ * @a label1 (;l1) refers to the label of @a tmpfile1 (;f1) which is
+ * the pristine copy.
+ *
+ * @a label2 (;l2) refers to the label of @a tmpfile2 (;f2) which
+ * is the altered copy.
+ *
+ * When used in a diff3 context:
+ *
+ * @a label1 refers to the label of @a tmpfile1 which is the 'mine'
+ * copy.
+ *
+ * @a label2 refers to the label of @a tmpfile2 which is the 'older'
+ * copy.
+ *
+ * @a label3 (;l3) refers to the label of @a base (;f3) which is
+ * the 'base' copy.
+ *
+ * A parse token can be escaped by prefixing a ';'. Any other
+ * strings containing ';' are not affected.
+ *
+ * In general:
+ *
+ * @a cmd is a user defined string containing 0 or more parse tokens
+ * which are expanded by the required labels and filenames.
+ *
+ * @a pool is used for temporary allocations.
+ *
+ * @return A NULL-terminated character array.
+ *
+ * @since New in 1.9.
+ */
+ const char **
+ __create_custom_diff_cmd(const char *label1,
+ const char *label2,
+ const char *label3,
+ const char *from,
+ const char *to,
+ const char *base,
+ const char *cmd,
+ apr_pool_t *pool);
+
+
+ /** Run the external diff command defined by the invoke-diff-cmd
+ * option.
+ *
+ * @since New in 1.9.
+ */
+ svn_error_t *
+ svn_io_run_external_diff(const char *dir,
+ const char *label1,
+ const char *label2,
+ const char *tmpfile1,
+ const char *tmpfile2,
+ int *pexitcode,
+ apr_file_t *outfile,
+ apr_file_t *errfile,
+ const char *external_diff_cmd,
+ apr_pool_t *scratch_pool);
================================================================================
*** /home/g/trunk/subversion/libsvn_client/deprecated.c 2013-09-24
21:40:36.722752927 +0100
---
/home/g/branches/invoke-diff-cmd-feature/subversion/libsvn_client/deprecated.c
2013-09-26 13:50:46.983836489 +0100
*************** svn_error_t *
*** 916 ****
--- 917,963 ----
+ svn_client_diff6(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)
+ {
+ return svn_client_diff7(options,
+ path_or_url1,
+ revision1,
+ path_or_url2,
+ revision2,
+ relative_to_dir,
+ depth,
+ ignore_ancestry,
+ no_diff_added,
+ no_diff_deleted,
+ show_copies_as_adds,
+ ignore_content_type,
+ ignore_properties,
+ properties_only,
+ use_git_diff_format,
+ header_encoding,
+ outstream,
+ errstream,
+ changelists,
+ NULL,
+ ctx,
+ pool);
+ }
+
+ svn_error_t *
*************** svn_client_diff(const apr_array_header_t
*** 1035 ****
--- 1083,1129 ----
+ }
+
+ svn_error_t *
+ svn_client_diff_peg6(const apr_array_header_t *options,
+ const char *path_or_url,
+ const svn_opt_revision_t *peg_revision,
+ const svn_opt_revision_t *start_revision,
+ const svn_opt_revision_t *end_revision,
+ 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)
+ {
+ return svn_client_diff_peg7(options,
+ path_or_url,
+ peg_revision,
+ start_revision,
+ end_revision,
+ relative_to_dir,
+ depth,
+ ignore_ancestry,
+ no_diff_added,
+ no_diff_deleted,
+ show_copies_as_adds,
+ ignore_content_type,
+ ignore_properties,
+ properties_only,
+ use_git_diff_format,
+ header_encoding,
+ outstream,
+ errstream,
+ changelists,
+ NULL,
+ ctx,
+ pool);
================================================================================
*** /home/g/trunk/subversion/libsvn_client/diff.c 2013-08-07
20:56:50.881234131 +0100
--- /home/g/branches/invoke-diff-cmd-feature/subversion/libsvn_client/diff.c
2013-08-21 15:18:31.626301687 +0100
*************** print_git_diff_header(svn_stream_t *os,
*** 431 ****
! passed to svn_client_diff6(), which is probably stdout.
--- 431 ----
! passed to svn_client_diff7(), which is probably stdout.
*************** struct diff_cmd_baton {
*** 567 ****
! svn_client_diff6(), either may be SVN_INVALID_REVNUM. We need these
--- 567 ----
! svn_client_diff7(), either may be SVN_INVALID_REVNUM. We need these
*************** struct diff_cmd_baton {
*** 614 ****
--- 615,618 ----
+
+ /* external custom diff command */
+ const char *invoke_diff_cmd;
+
*************** diff_content_changed(svn_boolean_t *wrot
*** 788 ****
--- 793,796 ----
+ if (diff_cmd_baton->diff_cmd && diff_cmd_baton->invoke_diff_cmd)
+ return svn_error_create(SVN_ERR_CLIENT_DIFF_CMD, NULL,
+ _("diff-cmd and invoke-diff-cmd are"
+ "mutually exclusive."));
*************** diff_content_changed(svn_boolean_t *wrot
*** 790 ****
! if (diff_cmd_baton->diff_cmd)
--- 798 ----
! if (diff_cmd_baton->diff_cmd || diff_cmd_baton->invoke_diff_cmd)
*************** diff_content_changed(svn_boolean_t *wrot
*** 828 ****
--- 836,837 ----
+ /* "." is a non-canonical path for the diff process's working
directory. */
+ if (diff_cmd_baton->diff_cmd)
*************** diff_content_changed(svn_boolean_t *wrot
*** 835 ****
--- 845,853 ----
+ else
+ {
+ SVN_ERR(svn_io_run_external_diff(".",
+ label1, label2,
+ tmpfile1, tmpfile2,
+ &exitcode, outfile, errfile,
+ diff_cmd_baton->invoke_diff_cmd,
+ scratch_pool));
+ }
*************** diff_prepare_repos_repos(const char **ur
*** 1537,1538 ****
! This function is really svn_client_diff6(). If you read the public
! API description for svn_client_diff6(), it sounds quite Grand. It
--- 1555,1556 ----
! This function is really svn_client_diff7(). If you read the public
! API description for svn_client_diff7(), it sounds quite Grand. It
*************** diff_prepare_repos_repos(const char **ur
*** 1562 ****
! Perhaps someday a brave soul will truly make svn_client_diff6()
--- 1580 ----
! Perhaps someday a brave soul will truly make svn_client_diff7()
*************** unsupported_diff_error(svn_error_t *chil
*** 1575 ****
! _("Sorry, svn_client_diff6 was called in a way "
--- 1593 ----
! _("Sorry, svn_client_diff7 was called in a way "
*************** unsupported_diff_error(svn_error_t *chil
*** 1584 ****
! All other options are the same as those passed to svn_client_diff6(). */
--- 1602 ----
! All other options are the same as those passed to svn_client_diff7(). */
*************** diff_wc_wc(const char *path1,
*** 1667 ****
! All other options are the same as those passed to svn_client_diff6(). */
--- 1685 ----
! All other options are the same as those passed to svn_client_diff7(). */
*************** diff_repos_repos(const svn_wc_diff_callb
*** 1812 ****
! All other options are the same as those passed to svn_client_diff6(). */
--- 1830 ----
! All other options are the same as those passed to svn_client_diff7(). */
*************** do_diff(const svn_wc_diff_callbacks4_t *
*** 2147 ****
! All other options are the same as those passed to svn_client_diff6(). */
--- 2165 ----
! All other options are the same as those passed to svn_client_diff7(). */
*************** diff_summarize_repos_wc(svn_client_diff_
*** 2191 ****
! All other options are the same as those passed to svn_client_diff6(). */
--- 2209 ----
! All other options are the same as those passed to svn_client_diff7(). */
*************** set_up_diff_cmd_and_options(struct diff_
*** 2466 ****
! /* See if there is a diff command and/or diff arguments. */
--- 2484 ----
! /* old style diff_cmd has precedence in config file */
*************** set_up_diff_cmd_and_options(struct diff_
*** 2469 ****
! svn_config_t *cfg = svn_hash_gets(config, SVN_CONFIG_CATEGORY_CONFIG);
--- 2487,2490 ----
! svn_config_t *cfg;
!
! cfg = svn_hash_gets(config, SVN_CONFIG_CATEGORY_CONFIG);
!
*************** set_up_diff_cmd_and_options(struct diff_
*** 2486,2487 ****
! SVN_ERR(svn_path_cstring_to_utf8(&diff_cmd_baton->diff_cmd, diff_cmd,
! pool));
--- 2507,2508 ----
! SVN_ERR(svn_path_cstring_to_utf8(&diff_cmd_baton->diff_cmd,
! diff_cmd, pool));
*************** set_up_diff_cmd_and_options(struct diff_
*** 2488 ****
--- 2510,2515 ----
+ {
+ if (config) /* check if there is a invoke_diff_cmd in the config file */
+ {
+ svn_config_t *cfg;
+
+ cfg = svn_hash_gets(config, SVN_CONFIG_CATEGORY_CONFIG);
*************** set_up_diff_cmd_and_options(struct diff_
*** 2489 ****
--- 2517,2526 ----
+ svn_config_get(cfg, &diff_cmd, SVN_CONFIG_SECTION_HELPERS,
+ SVN_CONFIG_OPTION_INVOKE_DIFF_CMD, NULL);
+ if (diff_cmd)
+ {
+ SVN_ERR(svn_path_cstring_to_utf8(&diff_cmd_baton->invoke_diff_cmd,
+ diff_cmd, pool));
+ return SVN_NO_ERROR;
+ }
+ }
+ }
*************** set_up_diff_cmd_and_options(struct diff_
*** 2494,2495 ****
! const char **argv = NULL;
! int argc = options->nelts;
--- 2531,2535 ----
! const char **argv;
! int argc;
!
! argc = options->nelts;
! argv = NULL;
*************** set_up_diff_cmd_and_options(struct diff_
*** 2502 ****
! APR_ARRAY_IDX(options, i, const char *), pool));
--- 2543,2545 ----
! APR_ARRAY_IDX(options, i,
! const char *),
! pool));
*************** svn_error_t *
*** 2555 ****
! svn_client_diff6(const apr_array_header_t *options,
--- 2598 ----
! svn_client_diff7(const apr_array_header_t *options,
*************** svn_client_diff6(const apr_array_header_
*** 2573 ****
--- 2617 ----
+ const char *invoke_diff_cmd,
*************** svn_client_diff6(const apr_array_header_
*** 2590 ****
--- 2635 ----
+ diff_cmd_baton.invoke_diff_cmd = invoke_diff_cmd;
*************** svn_error_t *
*** 2622 ****
! svn_client_diff_peg6(const apr_array_header_t *options,
--- 2667 ----
! svn_client_diff_peg7(const apr_array_header_t *options,
*************** svn_client_diff_peg6(const apr_array_hea
*** 2640 ****
--- 2686 ----
+ const char *invoke_diff_cmd,
*************** svn_client_diff_peg6(const apr_array_hea
*** 2653 ****
--- 2700 ----
+ diff_cmd_baton.invoke_diff_cmd = invoke_diff_cmd;
================================================================================
*** /home/g/trunk/subversion/libsvn_subr/config_file.c 2013-07-12
22:06:43.862072458 +0100
---
/home/g/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/config_file.c
2013-08-21 15:12:45.828586973 +0100
*************** svn_config_ensure(const char *config_dir
*** 1120 ****
--- 1121,1125 ----
+ "### 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 = \"diff -y --label ;l1 ;f1 --label ;l2 ;f2\""
NL
================================================================================
================================================================================
*** /home/g/trunk/subversion/libsvn_subr/io.c 2013-10-12 21:38:58.478086111
+0100
--- /home/g/branches/invoke-diff-cmd-feature/subversion/libsvn_subr/io.c
2013-10-12 16:52:34.768876699 +0100
*************** svn_io_run_cmd(const char *path,
*** 3029,3034 ****
!
! svn_error_t *
! svn_io_run_diff2(const char *dir,
! const char *const *user_args,
! int num_user_args,
! const char *label1,
--- 3029,3030 ----
! const char **
! __create_custom_diff_cmd(const char *label1,
*************** svn_io_run_diff2(const char *dir,
*** 3035 ****
--- 3032 ----
+ const char *label3,
*************** svn_io_run_diff2(const char *dir,
*** 3038,3041 ****
! int *pexitcode,
! apr_file_t *outfile,
! apr_file_t *errfile,
! const char *diff_cmd,
--- 3035,3036 ----
! const char *base,
! const char *cmd,
*************** svn_io_run_diff2(const char *dir,
*** 3044,3048 ****
! const char **args;
! int i;
! int exitcode;
! int nargs = 4; /* the diff command itself, two paths, plus a trailing NULL
*/
! apr_pool_t *subpool = svn_pool_create(pool);
--- 3039,3042 ----
! /*
! This function can be tested with:
! /subversion/tests/cmdline/diff_tests.py diff_invoke_external_diffcmd
! */
*************** svn_io_run_diff2(const char *dir,
*** 3050,3051 ****
! if (pexitcode == NULL)
! pexitcode = &exitcode;
--- 3044,3047 ----
! apr_array_header_t *words;
! const char ** result;
! size_t argv, item, i, delimiters = 6;
! apr_pool_t *scratch_pool = svn_pool_create(pool);
*************** svn_io_run_diff2(const char *dir,
*** 3053,3056 ****
! if (user_args != NULL)
! nargs += num_user_args;
! else
! nargs += 1; /* -u */
--- 3049,3061 ----
! struct replace_tokens_tab
! {
! const char *delimiter;
! const char *replace;
! } tokens_tab[] = {
! { ";l1", label1 },
! { ";l2", label2 },
! { ";l3", label3 },
! { ";f1", from },
! { ";f2", to },
! { ";f3", base },
! { NULL, NULL }
! };
*************** svn_io_run_diff2(const char *dir,
*** 3058,3061 ****
! if (label1 != NULL)
! nargs += 2; /* the -L and the label itself */
! if (label2 != NULL)
! nargs += 2; /* the -L and the label itself */
--- 3063 ----
! words = svn_cstring_split(cmd, " ", TRUE, scratch_pool);
*************** svn_io_run_diff2(const char *dir,
*** 3063 ****
! args = apr_palloc(subpool, nargs * sizeof(char *));
--- 3065,3066 ----
! result = apr_palloc(pool,
! (words->nelts+1) * words->elt_size * sizeof(char *) );
*************** svn_io_run_diff2(const char *dir,
*** 3065,3066 ****
! i = 0;
! args[i++] = diff_cmd;
--- 3068,3070 ----
! for (item = 0, argv = 0; item < words->nelts; argv++, item++)
! {
! svn_stringbuf_t *word;
*************** svn_io_run_diff2(const char *dir,
*** 3068 ****
! if (user_args != NULL)
--- 3072,3076 ----
! word = svn_stringbuf_create_empty(scratch_pool);
! svn_stringbuf_appendcstr(word, APR_ARRAY_IDX(words, item, char *));
!
!
! if ( (word->data[0] == '"') && (word->data[word->len-1] != '"') )
*************** svn_io_run_diff2(const char *dir,
*** 3070,3072 ****
! int j;
! for (j = 0; j < num_user_args; ++j)
! args[i++] = user_args[j];
--- 3078,3090 ----
! svn_stringbuf_t * complete =
svn_stringbuf_create_empty(scratch_pool);
! int done = 0;
!
! while( (!done) && item < words->nelts)
! {
! svn_stringbuf_appendcstr(complete,
! APR_ARRAY_IDX(words, item, char *));
!
! if ( (complete->data[complete->len-1] == '"')
! || (item == words->nelts - 1) )
! {
! word->data = complete->data;
! done = 1;
*************** svn_io_run_diff2(const char *dir,
*** 3075,3077 ****
- args[i++] = "-u"; /* assume -u if the user didn't give us any args */
-
- if (label1 != NULL)
--- 3092 ----
*************** svn_io_run_diff2(const char *dir,
*** 3079,3080 ****
! args[i++] = "-L";
! args[i++] = label1;
--- 3094,3095 ----
! svn_stringbuf_appendcstr(complete, " ");
! item++;
*************** svn_io_run_diff2(const char *dir,
*** 3082 ****
! if (label2 != NULL)
--- 3097,3114 ----
! }
! }
!
! for (i = 0; i < delimiters; i++)
! {
! char *found = strstr(word->data, tokens_tab[i].delimiter);
! int len;
!
! if (!found)
! continue;
!
! len = word->len - strlen(found) - 1;
!
! /* if we find a protective semi-colon in front of this, consume it
*/
! if ( (len >= 0)
! && (word->data[len] == ';') )
! svn_stringbuf_remove(word, len, 1);
! else
*************** svn_io_run_diff2(const char *dir,
*** 3084,3085 ****
! args[i++] = "-L";
! args[i++] = label2;
--- 3116,3120 ----
! svn_stringbuf_replace(word, found - word->data,
! strlen(tokens_tab[i].delimiter),
! tokens_tab[i].replace,
! strlen(tokens_tab[i].replace));
! i = delimiters;
*************** svn_io_run_diff2(const char *dir,
*** 3086 ****
--- 3122,3125 ----
+ }
+ result[argv] = word->data;
+ }
+ result[argv] = NULL;
*************** svn_io_run_diff2(const char *dir,
*** 3088,3090 ****
! args[i++] = svn_dirent_local_style(from, subpool);
! args[i++] = svn_dirent_local_style(to, subpool);
! args[i++] = NULL;
--- 3127,3129 ----
! svn_pool_destroy(scratch_pool);
! return result;
! }
*************** svn_io_run_diff2(const char *dir,
*** 3092 ****
! SVN_ERR_ASSERT(i == nargs);
--- 3131,3144 ----
! svn_error_t *
! svn_io_run_external_diff(const char *dir,
! const char *label1,
! const char *label2,
! const char *tmpfile1,
! const char *tmpfile2,
! int *pexitcode,
! apr_file_t *outfile,
! apr_file_t *errfile,
! const char *external_diff_cmd,
! apr_pool_t *pool)
! {
! int exitcode;
! const char ** cmd;
*************** svn_io_run_diff2(const char *dir,
*** 3094,3095 ****
! SVN_ERR(svn_io_run_cmd(dir, diff_cmd, args, pexitcode, NULL, TRUE,
! NULL, outfile, errfile, subpool));
--- 3146,3147 ----
! if (0 == strlen(external_diff_cmd))
! return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, NULL);
*************** svn_io_run_diff2(const char *dir,
*** 3097 ****
! /* The man page for (GNU) diff describes the return value as:
--- 3149,3153 ----
! cmd = __create_custom_diff_cmd(label1, label2, NULL,
! tmpfile1, tmpfile2, NULL,
! external_diff_cmd, pool);
! if (pexitcode == NULL)
! pexitcode = &exitcode;
*************** svn_io_run_diff2(const char *dir,
*** 3099,3100 ****
! "An exit status of 0 means no differences were found, 1 means
! some differences were found, and 2 means trouble."
--- 3155,3156 ----
! SVN_ERR(svn_io_run_cmd(dir, cmd[0], cmd, pexitcode, NULL, TRUE,
! NULL, outfile, errfile, pool));
*************** svn_io_run_diff2(const char *dir,
*** 3102,3106 ****
- A return value of 2 typically occurs when diff cannot read its input
- or write to its output, but in any case we probably ought to return an
- error for anything other than 0 or 1 as the output is likely to be
- corrupt.
- */
--- 3157 ----
*************** svn_io_run_diff2(const char *dir,
*** 3107 ****
--- 3159,3166 ----
+ {
+ int i;
+ const char *failed_command = "";
+
+ for (i = 0; cmd[i]; ++i)
+ failed_command = apr_pstrcat(pool, failed_command,
+ cmd[i], " ", (char*) NULL);
+
*************** svn_io_run_diff2(const char *dir,
*** 3109,3110 ****
! _("'%s' returned %d"),
! svn_dirent_local_style(diff_cmd, pool),
--- 3168,3170 ----
! _("'%s' was expanded to '%s' and returned %d"),
! external_diff_cmd,
! failed_command,
*************** svn_io_run_diff2(const char *dir,
*** 3111 ****
--- 3172,3174 ----
+ }
+ return SVN_NO_ERROR;
+ }
*************** svn_io_run_diff2(const char *dir,
*** 3113 ****
! svn_pool_destroy(subpool);
--- 3176,3197 ----
! svn_error_t *
! svn_io_run_diff2(const char *dir,
! const char *const *user_args,
! int num_user_args,
! const char *label1,
! const char *label2,
! const char *from,
! const char *to,
! int *pexitcode,
! apr_file_t *outfile,
! apr_file_t *errfile,
! const char *diff_cmd,
! apr_pool_t *pool)
! {
! /*
! This function can be tested by using the test
! /subversion/tests/cmdline/diff_tests.py diff_external_diffcmd
! */
! svn_stringbuf_t *com;
! com = svn_stringbuf_create_empty(pool);
! svn_stringbuf_appendcstr(com, diff_cmd);
! svn_stringbuf_appendcstr(com, " ");
*************** svn_io_run_diff2(const char *dir,
*** 3115 ****
! return SVN_NO_ERROR;
--- 3199,3206 ----
! if (user_args != NULL)
! {
! int j;
! for (j = 0; j < num_user_args; ++j)
! {
! svn_stringbuf_appendcstr(com, user_args[j]);
! svn_stringbuf_appendcstr(com, " ");
! }
*************** svn_io_run_diff2(const char *dir,
*** 3116 ****
--- 3208,3209 ----
+ else /* assume -u if the user didn't give us any args */
+ svn_stringbuf_appendcstr(com, "-u ");
*************** svn_io_run_diff2(const char *dir,
*** 3117 ****
--- 3211,3229 ----
+ if (label1 != NULL)
+ svn_stringbuf_appendcstr(com,"-L ;l1 ");
+
+ if (label2 != NULL)
+ svn_stringbuf_appendcstr(com,"-L ;l2 ");
+
+ svn_stringbuf_appendcstr(com,";f1 ;f2 ");
+
+ return svn_io_run_external_diff(dir,
+ label1,
+ label2,
+ from,
+ to,
+ pexitcode,
+ outfile,
+ errfile,
+ com->data,
+ pool);
+ }
================================================================================
*** /home/g/trunk/subversion/svn/cl.h 2013-09-24 21:40:35.782748266 +0100
--- /home/g/branches/invoke-diff-cmd-feature/subversion/svn/cl.h
2013-09-26 13:50:36.815786068 +0100
*************** typedef struct svn_cl__opt_state_t
*** 186 ****
--- 187,188 ----
+ const char *invoke_diff_cmd; /* the format string to specify args */
+ /* for the external diff cmd */
================================================================================
*** /home/g/trunk/subversion/svn/diff-cmd.c 2013-08-07 20:56:48.209220881
+0100
--- /home/g/branches/invoke-diff-cmd-feature/subversion/svn/diff-cmd.c
2013-08-21 15:12:59.268653617 +0100
*************** svn_cl__diff(apr_getopt_t *os,
*** 406 ****
! SVN_ERR(svn_client_diff6(
--- 406 ----
! SVN_ERR(svn_client_diff7(
*************** svn_cl__diff(apr_getopt_t *os,
*** 425 ****
--- 426 ----
+ opt_state->diff.invoke_diff_cmd,
*************** svn_cl__diff(apr_getopt_t *os,
*** 457 ****
! SVN_ERR(svn_client_diff_peg6(
--- 458 ----
! SVN_ERR(svn_client_diff_peg7(
*************** svn_cl__diff(apr_getopt_t *os,
*** 476 ****
--- 478 ----
+ opt_state->diff.invoke_diff_cmd,
================================================================================
*** /home/g/trunk/subversion/svn/log-cmd.c 2013-09-24 21:40:35.658747651
+0100
--- /home/g/branches/invoke-diff-cmd-feature/subversion/svn/log-cmd.c
2013-09-26 13:50:37.027787119 +0100
*************** struct log_receiver_baton
*** 69 ****
--- 70,72 ----
+ /* Custom diff command. */
+ const char *invoke_diff_cmd;
+
*************** display_diff(const svn_log_entry_t *log_
*** 104 ****
--- 108 ----
+ const char *invoke_diff_cmd,
*************** display_diff(const svn_log_entry_t *log_
*** 125 ****
! SVN_ERR(svn_client_diff_peg6(diff_options,
--- 129 ----
! SVN_ERR(svn_client_diff_peg7(diff_options,
*************** display_diff(const svn_log_entry_t *log_
*** 142 ****
--- 147 ----
+ invoke_diff_cmd,
*************** log_entry_receiver(void *baton,
*** 468 ****
--- 474 ----
+ lb->invoke_diff_cmd,
*************** svn_cl__log(apr_getopt_t *os,
*** 710 ****
--- 717,721 ----
+ if (opt_state->diff.diff_cmd && opt_state->diff.diff_cmd)
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("'diff-cmd' and 'invoke-diff-cmd' options are "
+ "mutually exclusive"));
+
*************** svn_cl__log(apr_getopt_t *os,
*** 727 ****
--- 742,746 ----
+ if (opt_state->diff.invoke_diff_cmd && (! opt_state->show_diff))
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("'invoke-diff-cmd' option requires 'diff' "
+ "option"));
+
*************** svn_cl__log(apr_getopt_t *os,
*** 790 ****
--- 810 ----
+ lb.invoke_diff_cmd = opt_state->diff.invoke_diff_cmd;
================================================================================
*** /home/g/trunk/subversion/svnlook/svnlook.c 2013-09-24 21:40:37.690757727
+0100
--- /home/g/branches/invoke-diff-cmd-feature/subversion/svnlook/svnlook.c
2013-09-26 13:50:47.043836786 +0100
*************** enum
*** 102 ****
--- 103 ----
+ svnlook__invoke_diff_cmd,
*************** static const apr_getopt_option_t options
*** 137 ****
--- 139,141 ----
+ {"invoke-diff-cmd", svnlook__invoke_diff_cmd, 1,
+ N_("Customizable diff command (see svn help diff)")},
+
*************** static const svn_opt_subcommand_desc2_t
*** 227 ****
! svnlook__ignore_properties, svnlook__properties_only} },
--- 231,232 ----
! svnlook__ignore_properties, svnlook__properties_only,
! svnlook__invoke_diff_cmd} },
*************** struct svnlook_opt_state
*** 332 ****
--- 338 ----
+ const char *invoke_diff_cmd; /* --invoke-diff-cmd */
*************** typedef struct svnlook_ctxt_t
*** 355 ****
--- 362 ----
+ const char *invoke_diff_cmd;
*************** print_diff_tree(svn_stream_t *out_stream
*** 947 ****
! if (c->diff_cmd)
--- 954 ----
! if (c->diff_cmd || c->invoke_diff_cmd)
*************** print_diff_tree(svn_stream_t *out_stream
*** 1001 ****
--- 1009 ----
+ if (c->diff_cmd)
*************** print_diff_tree(svn_stream_t *out_stream
*** 1009 ****
--- 1018,1033 ----
+ else if (c->invoke_diff_cmd)
+ SVN_ERR(svn_io_run_external_diff(".",
+ orig_label,
+ new_label,
+ orig_path,
+ new_path,
+ &exitcode,
+ outfile,
+ errfile,
+ c->invoke_diff_cmd,
+ pool));
+
+ SVN_ERR(svn_io_file_close(outfile, pool));
+ SVN_ERR(svn_io_file_close(errfile, pool));
+
+
*************** get_ctxt_baton(svnlook_ctxt_t **baton_p,
*** 2093 ****
--- 2118 ----
+ baton->invoke_diff_cmd = opt_state->invoke_diff_cmd;
*************** main(int argc, const char *argv[])
*** 2611 ****
--- 2636,2639 ----
+ case svnlook__invoke_diff_cmd:
+ opt_state.invoke_diff_cmd = opt_arg;
+ break;
+
*************** main(int argc, const char *argv[])
*** 2636 ****
--- 2665,2671 ----
+
+ /* The --diff-cmd and --invoke-diff-cmd options may not co-exist. */
+ if (opt_state.diff_cmd && opt_state.invoke_diff_cmd)
+ SVN_INT_ERR(svn_error_create
+ (SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
+ _("Cannot use the '--diff-cmd' option with the "
+ "'--invoke-diff-cmd' option")));
================================================================================
*** /home/g/trunk/subversion/svn/svn.c 2013-09-24 21:40:35.782748266 +0100
--- /home/g/branches/invoke-diff-cmd-feature/subversion/svn/svn.c
2013-10-12 14:55:38.646085624 +0100
*************** typedef enum svn_cl__longopt_t {
*** 85 ****
--- 86 ----
+ opt_invoke_diff_cmd,
*************** const apr_getopt_option_t svn_cl__option
*** 346 ****
--- 348,374 ----
+ {"invoke-diff-cmd", opt_invoke_diff_cmd, 1,
+ N_("use ARG as format string for external diff command\n"
+ " "
+ "invocation. \n
\n"
+ " "
+ "Substitutions: ;f1 original file
\n"
+ " "
+ " ;f2 changed file
\n"
+ " "
+ " ;l1 label of the original file
\n"
+ " "
+ " ;l2 label of the changed file
\n"
+ " "
+ "Examples: --invoke-diff-cmd=\"diff -y ;f1 ;f2\"
\n"
+ " "
+ " --invoke-diff-cmd=\"kdiff3 -auto -o /home/u/log \\
\n"
+ " "
+ " +;f1 ;l2 --L1 ;l1 --L2 \"Custom Label\" \"
\n"
+ " "
+ "The delimiter ';' can be escaped by adding a ';',
which\n"
+ " "
+ "will be consumed in the process. The delimiter can
\n"
+ " "
+ "appear anywhere in the string, ie, file=;f1 will
expand\n"
+ " "
+ "as expected and file=;;f1 will be rendered as
file=;f1.\n"
+ )},
*************** const svn_opt_subcommand_desc2_t svn_cl_
*** 613 ****
! opt_force, opt_xml, opt_use_git_diff_format, opt_patch_compatible} },
--- 641,642 ----
! opt_force, opt_xml, opt_use_git_diff_format, opt_patch_compatible,
! opt_invoke_diff_cmd} },
*************** sub_main(int argc, const char *argv[], a
*** 2140 ****
--- 2170,2172 ----
+ case opt_invoke_diff_cmd:
+ opt_state.diff.invoke_diff_cmd = apr_pstrdup(pool, opt_arg);
+ break;
*************** sub_main(int argc, const char *argv[], a
*** 2555,2556 ****
! /* Disallow simultaneous use of both --diff-cmd and
! --internal-diff. */
--- 2587,2588 ----
! /* Disallow simultaneous use of both --diff-cmd, --invoke-diff-cmd
! and --internal-diff. */
*************** sub_main(int argc, const char *argv[], a
*** 2564 ****
--- 2597,2612 ----
+ 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 "
+ "are mutually exclusive"));
+ return EXIT_ERROR(err);
+ }
+
+ if ((opt_state.diff.diff_cmd) && (opt_state.diff.invoke_diff_cmd))
+ {
+ err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("--invoke-diff-cmd and --diff-cmd "
+ "are mutually exclusive"));
+ return EXIT_ERROR(err);
+ }
+
*************** sub_main(int argc, const char *argv[], a
*** 2779 ****
--- 2828,2830 ----
+ if (opt_state.diff.invoke_diff_cmd)
+ svn_config_set(cfg_config, SVN_CONFIG_SECTION_HELPERS,
+ SVN_CONFIG_OPTION_INVOKE_DIFF_CMD,
opt_state.diff.invoke_diff_cmd);
================================================================================
*** /home/g/trunk/subversion/tests/cmdline/diff_tests.py 2013-08-21
14:38:53.038506909 +0100
---
/home/g/branches/invoke-diff-cmd-feature/subversion/tests/cmdline/diff_tests.py
2013-10-12 14:34:04.175666692 +0100
*************** def diff_wrong_extension_type(sbox):
*** 3225 ****
--- 3226 ----
+ #----------------------------------------------------------------------
*************** def diff_external_diffcmd(sbox):
*** 3262 ****
--- 3264,3312 ----
+ # Check the correct parsing of arguments for an external diff tool
+ def diff_invoke_external_diffcmd(sbox):
+ "svn diff --invoke-diff-cmd passes correct args"
+
+ diff_script_path = os.path.abspath(".")+"/diff"
+
+ svntest.main.create_python_hook_script(diff_script_path, 'import sys\n'
+ 'for arg in sys.argv[1:]:\n print(arg)\n')
+
+ if sys.platform == 'win32':
+ diff_script_path = "%s.bat" % diff_script_path
+
+ sbox.build(read_only = True)
+ os.chdir(sbox.wc_dir)
+
+ iota_path = 'iota'
+ svntest.main.file_append(iota_path, "new text in iota")
+
+ expected_output = svntest.verify.ExpectedOutput([
+ "Index: iota\n",
+ "===================================================================\n",
+ # correct label ;l1 -> label 1
+ "iota (revision 1)\n",
+
+ # correct file ;f1 -> file1
+ os.path.abspath(svntest.wc.text_base_path("iota")) + "\n",
+
+ # correct label ;l2 -> label 2
+ "iota (working copy)\n",
+
+ # correct file ;f2 -> file2
+ os.path.abspath("iota") + "\n",
+
+ # preservation of quoted string "X Y Z"-> "X Y Z"
+ "\"X Y Z\"\n",
+
+ # correct insertion of filename into string "+;f2+" -> "+" + file2 + "+"
+ "+" + os.path.abspath("iota") + "+\n",
+
+ # removal of protective ';' ";;f1" -> ";f1"
+ ";f1\n",
+ ])
+
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'diff',
+ '--invoke-diff-cmd='+diff_script_path+
+ ' ;l1 ;f1 ;l2 ;f2 \"X Y Z\" +;f2+ ;;f1',
+ iota_path)
+
*************** test_list = [ None,
*** 4690 ****
--- 4741 ----
+ diff_invoke_external_diffcmd,