subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From s...@apache.org
Subject svn commit: r1207663 - in /subversion/trunk/subversion: libsvn_diff/parse-diff.c tests/cmdline/patch_tests.py
Date Mon, 28 Nov 2011 22:34:50 GMT
Author: stsp
Date: Mon Nov 28 22:34:49 2011
New Revision: 1207663

URL: http://svn.apache.org/viewvc?rev=1207663&view=rev
Log:
Make the diff parser handle comment lines indicating missing EOLs if such
comments appear within the diff text of a hunk, not just at the very end
of the hunk's diff text.

Reported by: Peter Balogh
http://svn.haxx.se/users/archive-2011-11/0523.shtml

* subversion/libsvn_diff/parse-diff.c
  (parse_next_hunk): The '\ No newline at end of ...' comments may appear
   not only at the very end of a hunk text, but also at the end of the
   original version (the last line starting with '-') or at the end of the
   modified version (the last line starting with '+') of the hunk text.
   Properly account for this by keeping track of the last byte in the
   original and modified hunk texts independently.

* subversion/tests/cmdline/patch_tests.py
  (patch_target_no_eol_at_eof, test_list): New test.

Modified:
    subversion/trunk/subversion/libsvn_diff/parse-diff.c
    subversion/trunk/subversion/tests/cmdline/patch_tests.py

Modified: subversion/trunk/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_diff/parse-diff.c?rev=1207663&r1=1207662&r2=1207663&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/trunk/subversion/libsvn_diff/parse-diff.c Mon Nov 28 22:34:49 2011
@@ -590,11 +590,19 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
   svn_boolean_t eof, in_hunk, hunk_seen;
   apr_off_t pos, last_line;
   apr_off_t start, end;
+  apr_off_t original_end;
+  apr_off_t modified_end;
   svn_linenum_t original_lines;
   svn_linenum_t modified_lines;
   svn_linenum_t leading_context;
   svn_linenum_t trailing_context;
   svn_boolean_t changed_line_seen;
+  enum {
+    noise_line,
+    original_line,
+    modified_line,
+    context_line
+  } last_line_type;
   apr_pool_t *iterpool;
 
   *prop_operation = svn_diff_op_unchanged;
@@ -615,12 +623,17 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
   leading_context = 0;
   trailing_context = 0;
   changed_line_seen = FALSE;
+  original_end = 0;
+  modified_end = 0;
   *hunk = apr_pcalloc(result_pool, sizeof(**hunk));
 
   /* Get current seek position -- APR has no ftell() :( */
   pos = 0;
   SVN_ERR(svn_io_file_seek(apr_file, APR_CUR, &pos, scratch_pool));
 
+  /* Start out assuming noise. */
+  last_line_type = noise_line;
+
   iterpool = svn_pool_create(scratch_pool);
   do
     {
@@ -649,6 +662,7 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
               char eolbuf[2];
               apr_size_t len;
               apr_off_t off;
+              apr_off_t hunk_text_end;
 
               /* Comment terminates the hunk text and says the hunk text
                * has no trailing EOL. Snip off trailing EOL which is part
@@ -659,14 +673,26 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
               SVN_ERR(svn_io_file_read_full2(apr_file, eolbuf, len, &len,
                                              &eof, iterpool));
               if (eolbuf[0] == '\r' && eolbuf[1] == '\n')
-                end = last_line - 2;
-              else if (eolbuf[1] == '\n')
-                end = last_line - 1;
-              else if (eolbuf[1] == '\r')
-                end = last_line - 1;
+                hunk_text_end = last_line - 2;
+              else if (eolbuf[1] == '\n' || eolbuf[1] == '\r')
+                hunk_text_end = last_line - 1;
               else
-                end = last_line;
-              break;
+                hunk_text_end = last_line;
+
+              if (last_line_type == original_line && original_end == 0)
+                original_end = hunk_text_end;
+              else if (last_line_type == modified_line && modified_end == 0)
+                modified_end = hunk_text_end;
+              else if (last_line_type == context_line)
+                {
+                  if (original_end == 0)
+                    original_end = hunk_text_end;
+                  if (modified_end == 0)
+                    modified_end = hunk_text_end;
+                  break;
+                }
+
+              SVN_ERR(svn_io_file_seek(apr_file, APR_SET, &pos, iterpool));
             }
 
           continue;
@@ -701,6 +727,7 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
                 trailing_context++;
               else
                 leading_context++;
+              last_line_type = context_line;
             }
           else if (original_lines > 0 && c == del)
             {
@@ -714,6 +741,7 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
                 trailing_context = 0;
 
               original_lines--;
+              last_line_type = original_line;
             }
           else if (modified_lines > 0 && c == add)
             {
@@ -727,6 +755,7 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
                 trailing_context = 0;
 
               modified_lines--;
+              last_line_type = modified_line;
             }
           else
             {
@@ -742,6 +771,10 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
                   end = last_line;
                 }
 
+              if (original_end == 0)
+                original_end = end;
+              if (modified_end == 0)
+                modified_end = end;
               break; /* Hunk was empty or has been read. */
             }
         }
@@ -821,10 +854,10 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
       (*hunk)->diff_text_range.end = end;
       (*hunk)->original_text_range.start = start;
       (*hunk)->original_text_range.current = start;
-      (*hunk)->original_text_range.end = end;
+      (*hunk)->original_text_range.end = original_end;
       (*hunk)->modified_text_range.start = start;
       (*hunk)->modified_text_range.current = start;
-      (*hunk)->modified_text_range.end = end;
+      (*hunk)->modified_text_range.end = modified_end;
     }
   else
     /* Something went wrong, just discard the result. */

Modified: subversion/trunk/subversion/tests/cmdline/patch_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/patch_tests.py?rev=1207663&r1=1207662&r2=1207663&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/patch_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/patch_tests.py Mon Nov 28 22:34:49 2011
@@ -3988,6 +3988,63 @@ def patch_delete_and_skip(sbox):
                                        1, # check-props
                                        1) # dry-run
 
+def patch_target_no_eol_at_eof(sbox):
+  "patch target with no eol at eof"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  patch_file_path = make_patch_path(sbox)
+  iota_path = os.path.join(wc_dir, 'iota')
+
+  iota_contents = [
+    "This is the file iota."
+  ]
+
+  svntest.main.file_write(iota_path, ''.join(iota_contents))
+  expected_output = svntest.wc.State(wc_dir, {
+    'iota'  : Item(verb='Sending'),
+    })
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('iota', wc_rev=2)
+  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                        expected_status, None, wc_dir)
+  unidiff_patch = [
+    "--- iota\t(revision 1)\n",
+    "+++ iota\t(working copy)\n",
+    "@@ -1,7 +1,7 @@\n",
+    "-This is the file iota.\n"
+    "\\ No newline at end of file\n",
+    "+It is the file 'iota'.\n",
+    "\\ No newline at end of file\n",
+  ]
+
+  svntest.main.file_write(patch_file_path, ''.join(unidiff_patch))
+
+  iota_contents = [
+    "It is the file 'iota'."
+  ]
+  expected_output = [
+    'U         %s\n' % os.path.join(wc_dir, 'iota'),
+  ]
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('iota', contents=''.join(iota_contents))
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('iota', 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
+
 ########################################################################
 #Run the tests
 
@@ -4030,6 +4087,7 @@ test_list = [ None,
               patch_reversed_add_with_props2,
               patch_dev_null,
               patch_delete_and_skip,
+              patch_target_no_eol_at_eof,
             ]
 
 if __name__ == '__main__':



Mime
View raw message