You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by da...@apache.org on 2010/04/15 21:48:28 UTC

svn commit: r934569 - in /subversion/trunk/subversion: include/ libsvn_client/ libsvn_diff/ svn/ tests/cmdline/ tests/libsvn_client/ tests/libsvn_diff/

Author: dannas
Date: Thu Apr 15 19:48:28 2010
New Revision: 934569

URL: http://svn.apache.org/viewvc?rev=934569&view=rev
Log:
Fix #3610 - 'svn patch' should be able to ignore whitespace changes.

Mail clients often mess with whitespaces in different ways:
* remove leading whitespaces at the beginning of a line
* convert tabs to spaces
* remove trailing whitespaces at the end of a line

With the --ignore-whitespaces, we allow hunks to be matched without 
taking whitespaces into account. The matching hunks will be applied
as-is without any attempt to guess what the correct whitespaces should
be.

Since this matching is not as restrictive as the usual one, there's a
risk of erroneus behaviour, i.e. matching a patch with all leading
spaces removed makes it impossible to distinguish between a context line
and some other line, intended to be ignored. 

If people don't like the result of patching, they can edit the patch
to their liking and re-apply it (or ask the submitter to resubmit
the patch -- mangled patches are usually the submitter's fault).

* subversion/include/svn_diff.h
  (svn_diff_parse_next_patch): Add IGNORE_WHITESPACES parameter.

* subversion/include/svn_client.h
  (svn_client_patch): Add IGNORE_WHITESPACES parameter.

* subversion/libsvn_client/patch.c
  (apply_patches_baton_t): Add IGNORE_WHITESPACES field.
  (match_hunk): Add IGNORE_WHITESPACES parameter. if ignore_whitespaces
    is set, do a matching with all whitespaces removed.
  (scan_for_match,
   get_hunk_info,
   apply_one_patch): Add IGNORE_WHITESPACES parameter.
  (apply_patches): Pass IGNORE_WHITESPACES parameter from baton to
    svn_diff_parse_next_patch() and apply_one_patch().
  (svn_client_patch): Add IGNORE_WHITESPACES. Pass it on via baton to
    apply_patches.

* subversion/libsvn_diff/parse-diff.c
  (parse_next_hunk): Add IGNORE_WHITESPACES parameter. Treat lines not
    starting with '+' or '-' as context lines if the
    ignore_whitespaces parameter is set.
  (svn_diff_parse_next_patch): Add IGNORE_WHITESPACES parameter.

* subversion/tests/libsvn_diff/parse-diff-test.c
  (test_parse_unidiff): Update callers to use the IGNORE_WHITESPACES
    parameter.

* subversion/tests/libsvn_client/client-test.c
  (test_patch): Update callers to use the IGNORE_WHITESPACES parameter.

* subversion/tests/cmdline/patch_tests.py
  (patch_with_ignore_whitespaces): New.
  (test_list): Add new test.

* subversion/svn/cl.h
  (svn_cl__opt_state_t): Add IGNORE_WHITESPACES field.

* subversion/svn/main.c
  (svn_cl__longopt_t): Add IGNORE_WHITESPACES field.
  (svn_cl__cmd_table): Add --ignore-whitespaces option.
  (main): Handle --ignore-whitespaces option.

Modified:
    subversion/trunk/subversion/include/svn_client.h
    subversion/trunk/subversion/include/svn_diff.h
    subversion/trunk/subversion/libsvn_client/patch.c
    subversion/trunk/subversion/libsvn_diff/parse-diff.c
    subversion/trunk/subversion/svn/cl.h
    subversion/trunk/subversion/svn/main.c
    subversion/trunk/subversion/svn/patch-cmd.c
    subversion/trunk/subversion/tests/cmdline/patch_tests.py
    subversion/trunk/subversion/tests/libsvn_client/client-test.c
    subversion/trunk/subversion/tests/libsvn_diff/parse-diff-test.c

Modified: subversion/trunk/subversion/include/svn_client.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_client.h?rev=934569&r1=934568&r2=934569&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_client.h (original)
+++ subversion/trunk/subversion/include/svn_client.h Thu Apr 15 19:48:28 2010
@@ -4906,6 +4906,7 @@ svn_client_patch(const char *abs_patch_p
                  const apr_array_header_t *exclude_patterns,
                  apr_hash_t **patched_tempfiles,
                  apr_hash_t **reject_tempfiles,
+                 svn_boolean_t ignore_whitespaces,
                  svn_client_ctx_t *ctx,
                  apr_pool_t *result_pool,
                  apr_pool_t *scratch_pool);

Modified: subversion/trunk/subversion/include/svn_diff.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_diff.h?rev=934569&r1=934568&r2=934569&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_diff.h (original)
+++ subversion/trunk/subversion/include/svn_diff.h Thu Apr 15 19:48:28 2010
@@ -866,6 +866,7 @@ svn_error_t *
 svn_diff_parse_next_patch(svn_patch_t **patch,
                           apr_file_t *patch_file,
                           svn_boolean_t reverse,
+                          svn_boolean_t ignore_whitespaces,
                           apr_pool_t *result_pool,
                           apr_pool_t *scratch_pool);
 

Modified: subversion/trunk/subversion/libsvn_client/patch.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/patch.c?rev=934569&r1=934568&r2=934569&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/patch.c (original)
+++ subversion/trunk/subversion/libsvn_client/patch.c Thu Apr 15 19:48:28 2010
@@ -623,7 +623,8 @@ seek_to_line(patch_target_t *target, svn
  * POOL. */
 static svn_error_t *
 match_hunk(svn_boolean_t *matched, patch_target_t *target,
-           const svn_hunk_t *hunk, int fuzz, apr_pool_t *pool)
+           const svn_hunk_t *hunk, int fuzz, 
+           svn_boolean_t ignore_whitespaces, apr_pool_t *pool)
 {
   svn_stringbuf_t *hunk_line;
   const char *target_line;
@@ -668,7 +669,22 @@ match_hunk(svn_boolean_t *matched, patch
                    hunk->trailing_context > fuzz)
             lines_matched = TRUE;
           else
-            lines_matched = ! strcmp(hunk_line_translated, target_line);
+            {
+              if (ignore_whitespaces)
+                {
+                  char *stripped_hunk_line = apr_pstrdup(pool,
+                                                         hunk_line_translated);
+                  char *stripped_target_line = apr_pstrdup(pool, target_line);
+
+                  apr_collapse_spaces(stripped_hunk_line,
+                                      hunk_line_translated);
+                  apr_collapse_spaces(stripped_target_line, target_line);
+                  lines_matched = ! strcmp(stripped_hunk_line,
+                                           stripped_target_line);
+                }
+              else 
+                lines_matched = ! strcmp(hunk_line_translated, target_line);
+            }
         }
     }
   while (lines_matched && ! (hunk_eof || target->eof));
@@ -706,7 +722,9 @@ match_hunk(svn_boolean_t *matched, patch
 static svn_error_t *
 scan_for_match(svn_linenum_t *matched_line, patch_target_t *target,
                const svn_hunk_t *hunk, svn_boolean_t match_first,
-               svn_linenum_t upper_line, int fuzz, apr_pool_t *pool)
+               svn_linenum_t upper_line, int fuzz, 
+               svn_boolean_t ignore_whitespaces,
+               apr_pool_t *pool)
 {
   apr_pool_t *iterpool;
 
@@ -720,7 +738,8 @@ scan_for_match(svn_linenum_t *matched_li
 
       svn_pool_clear(iterpool);
 
-      SVN_ERR(match_hunk(&matched, target, hunk, fuzz, iterpool));
+      SVN_ERR(match_hunk(&matched, target, hunk, fuzz, ignore_whitespaces,
+                         iterpool));
       if (matched)
         {
           svn_boolean_t taken = FALSE;
@@ -764,7 +783,8 @@ scan_for_match(svn_linenum_t *matched_li
  * Do temporary allocations in POOL. */
 static svn_error_t *
 get_hunk_info(hunk_info_t **hi, patch_target_t *target,
-              const svn_hunk_t *hunk, int fuzz, apr_pool_t *result_pool,
+              const svn_hunk_t *hunk, int fuzz, 
+              svn_boolean_t ignore_whitespaces, apr_pool_t *result_pool,
               apr_pool_t *scratch_pool)
 {
   svn_linenum_t matched_line;
@@ -794,7 +814,8 @@ get_hunk_info(hunk_info_t **hi, patch_ta
         }
       else
         SVN_ERR(scan_for_match(&matched_line, target, hunk, TRUE,
-                               hunk->original_start + 1, fuzz, scratch_pool));
+                               hunk->original_start + 1, fuzz,
+                               ignore_whitespaces, scratch_pool));
 
       if (matched_line != hunk->original_start)
         {
@@ -804,7 +825,8 @@ get_hunk_info(hunk_info_t **hi, patch_ta
           /* Scan forward towards the hunk's line and look for a line
            * where the hunk matches. */
           SVN_ERR(scan_for_match(&matched_line, target, hunk, FALSE,
-                                 hunk->original_start, fuzz, scratch_pool));
+                                 hunk->original_start, fuzz,
+                                 ignore_whitespaces, scratch_pool));
 
           /* In tie-break situations, we arbitrarily prefer early matches
            * to save us from scanning the rest of the file. */
@@ -813,7 +835,8 @@ get_hunk_info(hunk_info_t **hi, patch_ta
               /* Scan forward towards the end of the file and look
                * for a line where the hunk matches. */
               SVN_ERR(scan_for_match(&matched_line, target, hunk, TRUE, 0,
-                                     fuzz, scratch_pool));
+                                     fuzz, ignore_whitespaces,
+                                     scratch_pool));
             }
         }
 
@@ -1110,6 +1133,7 @@ apply_one_patch(patch_target_t **patch_t
                 const apr_array_header_t *exclude_patterns,
                 apr_hash_t *patched_tempfiles,
                 apr_hash_t *reject_tempfiles,
+                svn_boolean_t ignore_whitespaces,
                 apr_pool_t *result_pool, apr_pool_t *scratch_pool)
 {
   patch_target_t *target;
@@ -1145,7 +1169,7 @@ apply_one_patch(patch_target_t **patch_t
       do
         {
           SVN_ERR(get_hunk_info(&hi, target, hunk, fuzz,
-                                result_pool, iterpool));
+                                ignore_whitespaces, result_pool, iterpool));
           fuzz++;
         }
       while (hi->rejected && fuzz <= MAX_FUZZ);
@@ -1441,6 +1465,10 @@ typedef struct {
   /* Mapping patch target path -> path to tempfile with rejected hunks. */
   apr_hash_t *reject_tempfiles;
 
+  /* Indicates whether we should ignore whitespaces when matching context
+   * lines */
+  svn_boolean_t ignore_whitespaces;
+
 
   /* The client context. */
   svn_client_ctx_t *ctx;
@@ -1487,7 +1515,8 @@ apply_patches(void *baton,
         SVN_ERR(btn->ctx->cancel_func(btn->ctx->cancel_baton));
 
       SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file,
-                                        btn->reverse, scratch_pool, iterpool));
+                                        btn->reverse, btn->ignore_whitespaces,
+                                        scratch_pool, iterpool));
       if (patch)
         {
           patch_target_t *target;
@@ -1496,6 +1525,7 @@ apply_patches(void *baton,
                                   btn->ctx->wc_ctx, btn->strip_count,
                                   btn->include_patterns, btn->exclude_patterns,
                                   btn->patched_tempfiles, btn->reject_tempfiles,
+                                  btn->ignore_whitespaces,
                                   result_pool, iterpool));
           if (target->filtered)
             SVN_ERR(svn_diff_close_patch(patch));
@@ -1540,6 +1570,7 @@ svn_client_patch(const char *abs_patch_p
                  const apr_array_header_t *exclude_patterns,
                  apr_hash_t **patched_tempfiles,
                  apr_hash_t **reject_tempfiles,
+                 svn_boolean_t ignore_whitespaces,
                  svn_client_ctx_t *ctx,
                  apr_pool_t *result_pool,
                  apr_pool_t *scratch_pool)
@@ -1558,7 +1589,9 @@ svn_client_patch(const char *abs_patch_p
   baton.reverse = reverse;
   baton.include_patterns = include_patterns;
   baton.exclude_patterns = exclude_patterns;
-  if (patched_tempfiles)
+  baton.ignore_whitespaces = ignore_whitespaces;
+
+ if (patched_tempfiles)
     {
       (*patched_tempfiles) = apr_hash_make(result_pool);
       baton.patched_tempfiles = (*patched_tempfiles);

Modified: subversion/trunk/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_diff/parse-diff.c?rev=934569&r1=934568&r2=934569&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/trunk/subversion/libsvn_diff/parse-diff.c Thu Apr 15 19:48:28 2010
@@ -268,6 +268,7 @@ parse_next_hunk(svn_hunk_t **hunk,
                 svn_patch_t *patch,
                 svn_stream_t *stream,
                 svn_boolean_t reverse,
+                svn_boolean_t ignore_whitespaces,
                 apr_pool_t *result_pool,
                 apr_pool_t *scratch_pool)
 {
@@ -355,8 +356,10 @@ parse_next_hunk(svn_hunk_t **hunk,
 
           c = line->data[0];
           /* Tolerate chopped leading spaces on empty lines. */
-          if (original_lines > 0 && modified_lines > 0 &&
-              (c == ' ' || (! eof && line->len == 0)))
+          if (original_lines > 0 && modified_lines > 0 
+              && ((c == ' ')
+              || (! eof && line->len == 0)
+              || (ignore_whitespaces && c != del && c != add)))
             {
               hunk_seen = TRUE;
               original_lines--;
@@ -517,6 +520,7 @@ svn_error_t *
 svn_diff_parse_next_patch(svn_patch_t **patch,
                           apr_file_t *patch_file,
                           svn_boolean_t reverse,
+                          svn_boolean_t ignore_whitespaces,
                           apr_pool_t *result_pool,
                           apr_pool_t *scratch_pool)
 {
@@ -624,7 +628,7 @@ svn_diff_parse_next_patch(svn_patch_t **
           svn_pool_clear(iterpool);
 
           SVN_ERR(parse_next_hunk(&hunk, *patch, stream, reverse,
-                                  result_pool, iterpool));
+                                  ignore_whitespaces, result_pool, iterpool));
           if (hunk)
             APR_ARRAY_PUSH((*patch)->hunks, svn_hunk_t *) = hunk;
         }

Modified: subversion/trunk/subversion/svn/cl.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/cl.h?rev=934569&r1=934568&r2=934569&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/cl.h (original)
+++ subversion/trunk/subversion/svn/cl.h Thu Apr 15 19:48:28 2010
@@ -226,6 +226,8 @@ typedef struct svn_cl__opt_state_t
   svn_boolean_t reverse_diff;     /* reverse a diff (e.g. when patching) */
   apr_array_header_t *include_patterns; /* targets to include in operation */
   apr_array_header_t *exclude_patterns; /* targets to exclude from operation */
+  svn_boolean_t ignore_whitespaces; /* don't account for whitespaces when
+                                       patching */
 } svn_cl__opt_state_t;
 
 

Modified: subversion/trunk/subversion/svn/main.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/main.c?rev=934569&r1=934568&r2=934569&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/main.c (original)
+++ subversion/trunk/subversion/svn/main.c Thu Apr 15 19:48:28 2010
@@ -119,6 +119,7 @@ typedef enum {
   opt_reverse_diff,
   opt_include_pattern,
   opt_exclude_pattern,
+  opt_ignore_whitespaces,
 } svn_cl__longopt_t;
 
 /* Option codes and descriptions for the command line client.
@@ -379,6 +380,10 @@ const apr_getopt_option_t svn_cl__option
                        "See also the --include-pattern option.\n"
                        "                             "
                        "[alias: --ep]")},
+  {"ignore-whitespaces", opt_ignore_whitespaces, 0,
+                       N_("don't take whitespaces into account when,\n"
+                       "                             "
+                       "determining where a patch should be applied")},
   /* Long-opt Aliases
    *
    * These have NULL desriptions, but an option code that matches some
@@ -847,7 +852,7 @@ const svn_opt_subcommand_desc2_t svn_cl_
      "  do not agree with.\n"
      ),
     {'q', opt_dry_run, 'p', opt_reverse_diff, opt_include_pattern,
-     opt_exclude_pattern} },
+     opt_exclude_pattern, opt_ignore_whitespaces} },
 
   { "propdel", svn_cl__propdel, {"pdel", "pd"}, N_
     ("Remove a property from files, dirs, or revisions.\n"
@@ -1774,6 +1779,9 @@ main(int argc, const char *argv[])
                                                       sizeof (const char *));
         APR_ARRAY_PUSH(opt_state.exclude_patterns, const char *) = opt_arg;
         break;
+      case opt_ignore_whitespaces:
+          opt_state.ignore_whitespaces = TRUE;
+          break;
       default:
         /* Hmmm. Perhaps this would be a good place to squirrel away
            opts that commands like svn diff might need. Hmmm indeed. */

Modified: subversion/trunk/subversion/svn/patch-cmd.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/patch-cmd.c?rev=934569&r1=934568&r2=934569&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/patch-cmd.c (original)
+++ subversion/trunk/subversion/svn/patch-cmd.c Thu Apr 15 19:48:28 2010
@@ -81,7 +81,9 @@ svn_cl__patch(apr_getopt_t *os,
                            opt_state->reverse_diff,
                            opt_state->include_patterns,
                            opt_state->exclude_patterns,
-                           NULL, NULL, ctx, pool, pool));
+                           NULL, NULL, 
+                           opt_state->ignore_whitespaces, ctx, pool, pool));
+
 
   if (! opt_state->quiet)
     SVN_ERR(svn_cl__print_conflict_stats(ctx->notify_baton2, pool));

Modified: subversion/trunk/subversion/tests/cmdline/patch_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/patch_tests.py?rev=934569&r1=934568&r2=934569&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/patch_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/patch_tests.py Thu Apr 15 19:48:28 2010
@@ -2251,6 +2251,140 @@ def patch_with_include_exclude_patterns(
                                        "--include-pattern", "*a",
                                        "--exclude-pattern", "A/*/gamma")
 
+def patch_with_ignore_whitespaces(sbox):
+  "ignore whitespaces when patching"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  patch_file_path = tempfile.mkstemp(dir=os.path.abspath(svntest.main.temp_dir))[1]
+  mu_path = os.path.join(wc_dir, 'A', 'mu')
+
+  mu_contents = [
+    "Dear internet user,\n",
+    "\n",
+    "We wish to congratulate you over your email success in our computer\n",
+    "Balloting. This is a Millennium Scientific Electronic Computer Draw\n",
+    "in which email addresses were used. All participants were selected\n",
+    "through a computer ballot system drawn from over 100,000 company \n",
+    "and 50,000,000\t\tindividual email addresses from all over the world. \n",
+    " \n",
+    "Your email address drew and have won the sum of  750,000 Euros\n",
+    "( Seven Hundred and Fifty Thousand Euros) in cash credited to\n",
+    "file with\n",
+    "    REFERENCE NUMBER: ESP/WIN/008/05/10/MA;\n",
+    "    WINNING NUMBER : 14-17-24-34-37-45-16\n",
+    "    BATCH NUMBERS :\n",
+    "    EULO/1007/444/606/08;\n",
+    "    SERIAL NUMBER: 45327\n",
+    "and PROMOTION DATE: 13th June. 2009\n",
+    "\n",
+    "To claim your winning prize, you are to contact the appointed\n",
+    "agent below as soon as possible for the immediate release of your\n",
+    "winnings with the below details.\n",
+    "\n",
+    "Again, we wish to congratulate you over your email success in our\n"
+    "computer Balloting.\n"
+  ]
+
+  # Set mu contents
+  svntest.main.file_write(mu_path, ''.join(mu_contents))
+  expected_output = svntest.wc.State(wc_dir, {
+    'A/mu'       : Item(verb='Sending'),
+    })
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('A/mu', wc_rev=2)
+  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                        expected_status, None, wc_dir)
+
+  # Apply patch with leading and trailing spaces removed and tabs transformed 
+  # to spaces. The patch should match and the hunks should be written to the
+  # target as-is.
+
+  unidiff_patch = [
+    "Index: A/mu\n",
+    "===================================================================\n",
+    "--- A/mu.orig	2009-06-24 15:23:55.000000000 +0100\n",
+    "+++ A/mu	2009-06-24 15:21:23.000000000 +0100\n",
+    "@@ -6,6 +6,9 @@\n",
+    "through a computer ballot system drawn from over 100,000 company\n",
+    "and 50,000,000 individual email addresses from all over the world.\n",
+    "\n",
+    "+It is a promotional program aimed at encouraging internet users;\n",
+    "+therefore you do not need to buy ticket to enter for it.\n",
+    "+\n",
+    "Your email address drew and have won the sum of  750,000 Euros\n",
+    "( Seven Hundred and Fifty Thousand Euros) in cash credited to\n",
+    "file with\n",
+    "@@ -14,11 +17,8 @@\n",
+    "BATCH NUMBERS :\n",
+    "EULO/1007/444/606/08;\n",
+    "SERIAL NUMBER: 45327\n",
+    "-and PROMOTION DATE: 13th June. 2009\n",
+    "+and PROMOTION DATE: 14th June. 2009\n",
+    "\n",
+    "To claim your winning prize, you are to contact the appointed\n",
+    "agent below as soon as possible for the immediate release of your\n",
+    "winnings with the below details.\n",
+    "-\n",
+    "-Again, we wish to congratulate you over your email success in our\n",
+    "-computer Balloting.\n",
+  ]
+
+  svntest.main.file_write(patch_file_path, ''.join(unidiff_patch))
+
+  gamma_contents = "It is the file 'gamma'.\n"
+  iota_contents = "This is the file 'iota'.\nSome more bytes\n"
+  new_contents = "new\n"
+  mu_contents = [
+    "Dear internet user,\n",
+    "\n",
+    "We wish to congratulate you over your email success in our computer\n",
+    "Balloting. This is a Millennium Scientific Electronic Computer Draw\n",
+    "in which email addresses were used. All participants were selected\n",
+    "through a computer ballot system drawn from over 100,000 company\n",
+    "and 50,000,000 individual email addresses from all over the world.\n",
+    "\n",
+    "It is a promotional program aimed at encouraging internet users;\n",
+    "therefore you do not need to buy ticket to enter for it.\n",
+    "\n",
+    "Your email address drew and have won the sum of  750,000 Euros\n",
+    "( Seven Hundred and Fifty Thousand Euros) in cash credited to\n",
+    "file with\n",
+    "    REFERENCE NUMBER: ESP/WIN/008/05/10/MA;\n",
+    "    WINNING NUMBER : 14-17-24-34-37-45-16\n",
+    "BATCH NUMBERS :\n",
+    "EULO/1007/444/606/08;\n",
+    "SERIAL NUMBER: 45327\n",
+    "and PROMOTION DATE: 14th June. 2009\n",
+    "\n",
+    "To claim your winning prize, you are to contact the appointed\n",
+    "agent below as soon as possible for the immediate release of your\n",
+    "winnings with the below details.\n",
+  ]
+
+  expected_output = [
+    'U         %s\n' % os.path.join(wc_dir, 'A', 'mu'),
+  ]
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('A/mu', contents=''.join(mu_contents))
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('A/mu', status='M ', wc_rev=2)
+
+  expected_skip = wc.State('', { })
+
+  svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path),
+                                       expected_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, # expected err
+                                       1, # check-props
+                                       1, # dry-run
+                                       "--ignore-whitespaces",)
+
 ########################################################################
 #Run the tests
 
@@ -2273,6 +2407,7 @@ test_list = [ None,
               patch_with_include_patterns,
               patch_with_exclude_patterns,
               patch_with_include_exclude_patterns,
+              patch_with_ignore_whitespaces,
             ]
 
 if __name__ == '__main__':

Modified: subversion/trunk/subversion/tests/libsvn_client/client-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_client/client-test.c?rev=934569&r1=934568&r2=934569&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_client/client-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_client/client-test.c Thu Apr 15 19:48:28 2010
@@ -350,7 +350,7 @@ test_patch(const svn_test_opts_t *opts,
   /* Apply the patch. */
   SVN_ERR(svn_client_patch(patch_file_path, wc_path, FALSE, 0, FALSE,
                            NULL, NULL, &patched_tempfiles, &reject_tempfiles,
-                           ctx, pool, pool));
+                           FALSE, ctx, pool, pool));
   SVN_ERR(svn_io_file_close(patch_file, pool));
 
   SVN_ERR_ASSERT(apr_hash_count(patched_tempfiles) == 1);

Modified: subversion/trunk/subversion/tests/libsvn_diff/parse-diff-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_diff/parse-diff-test.c?rev=934569&r1=934568&r2=934569&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_diff/parse-diff-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_diff/parse-diff-test.c Thu Apr 15 19:48:28 2010
@@ -64,6 +64,7 @@ test_parse_unidiff(apr_pool_t *pool)
   apr_size_t len;
   const char *fname = "test_parse_unidiff.patch";
   svn_boolean_t reverse;
+  svn_boolean_t ignore_whitespaces;
   int i;
   apr_pool_t *iterpool;
 
@@ -81,6 +82,7 @@ test_parse_unidiff(apr_pool_t *pool)
                              "Cannot write to '%s'", fname);
 
   reverse = FALSE;
+  ignore_whitespaces = FALSE;
   iterpool = svn_pool_create(pool);
   for (i = 0; i < 2; i++)
     {
@@ -101,7 +103,8 @@ test_parse_unidiff(apr_pool_t *pool)
       /* We have two patches with one hunk each.
        * Parse the first patch. */
       SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file, reverse,
-                                        iterpool, iterpool));
+                                        ignore_whitespaces, iterpool, 
+                                        iterpool));
       SVN_ERR_ASSERT(patch);
       SVN_ERR_ASSERT(! strcmp(patch->old_filename, "A/C/gamma"));
       SVN_ERR_ASSERT(! strcmp(patch->new_filename, "A/C/gamma"));
@@ -143,7 +146,8 @@ test_parse_unidiff(apr_pool_t *pool)
       SVN_ERR_ASSERT(buf->len == 0);
 
       /* Parse the second patch. */
-      SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file, reverse, pool, pool));
+      SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file, reverse, 
+                                        ignore_whitespaces, pool, pool));
       SVN_ERR_ASSERT(patch);
       if (reverse)
         {