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")},