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/03/30 23:11:15 UTC

svn commit: r929288 - in /subversion/branches/svn-patch-improvements/subversion: libsvn_diff/parse-diff.c tests/cmdline/patch_tests.py

Author: dannas
Date: Tue Mar 30 21:11:15 2010
New Revision: 929288

URL: http://svn.apache.org/viewvc?rev=929288&view=rev
Log:
Fix bug with 'svn patch' not recognizing diff headers when parsing
patches without the 'Index' line and the '======' line. The old code
just assumed that the first line after the hunk would not be a '-'. But
it can be so we must handle it.

* subversion/libsvn_diff/parse-diff.c
  (parse_next_hunk): Check that we have not read all the lines, that the
    hunk header said, the hunk should consist of. We need to check for
    both nr of modified and original lines since we can do a reverse
    parsing. That means treating '+' as '-' and the other way around.

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


Modified:
    subversion/branches/svn-patch-improvements/subversion/libsvn_diff/parse-diff.c
    subversion/branches/svn-patch-improvements/subversion/tests/cmdline/patch_tests.py

Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_diff/parse-diff.c?rev=929288&r1=929287&r2=929288&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_diff/parse-diff.c Tue Mar 30 21:11:15 2010
@@ -281,6 +281,7 @@ parse_next_hunk(svn_hunk_t **hunk,
   svn_stream_t *original_text;
   svn_stream_t *modified_text;
   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;
@@ -358,12 +359,13 @@ parse_next_hunk(svn_hunk_t **hunk,
             {
               hunk_seen = TRUE;
               original_lines--;
+              modified_lines--;
               if (changed_line_seen)
                 trailing_context++;
               else
                 leading_context++;
             }
-          else if (c == add || c == del)
+          else if (original_lines > 0 && c == del)
             {
               hunk_seen = TRUE;
               changed_line_seen = TRUE;
@@ -373,8 +375,19 @@ parse_next_hunk(svn_hunk_t **hunk,
               if (trailing_context > 0)
                 trailing_context = 0;
 
-              if (original_lines > 0 && c == del)
-                original_lines--;
+              original_lines--;
+            }
+          else if (modified_lines > 0 && c == add)
+            {
+              hunk_seen = TRUE;
+              changed_line_seen = TRUE;
+
+              /* A hunk may have context in the middle. We only want the
+                 last lines of context. */
+              if (trailing_context > 0)
+                trailing_context = 0;
+
+              modified_lines--;
             }
           else
             {
@@ -395,7 +408,10 @@ parse_next_hunk(svn_hunk_t **hunk,
               in_hunk = parse_hunk_header(line->data, *hunk, reverse,
                                           iterpool);
               if (in_hunk)
-                original_lines = (*hunk)->original_length;
+                {
+                  original_lines = (*hunk)->original_length;
+                  modified_lines = (*hunk)->modified_length;
+                }
             }
           else if (starts_with(line->data, minus))
             /* This could be a header of another patch. Bail out. */

Modified: subversion/branches/svn-patch-improvements/subversion/tests/cmdline/patch_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/tests/cmdline/patch_tests.py?rev=929288&r1=929287&r2=929288&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/tests/cmdline/patch_tests.py (original)
+++ subversion/branches/svn-patch-improvements/subversion/tests/cmdline/patch_tests.py Tue Mar 30 21:11:15 2010
@@ -836,6 +836,92 @@ def patch_strip1(sbox):
                                        1, # dry-run
                                        '-p1')
 
+def patch_no_index_line(sbox):
+  "patch with no index lines"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  patch_file_path = tempfile.mkstemp(dir=os.path.abspath(svntest.main.temp_dir))[1]
+  gamma_path = os.path.join(wc_dir, 'A', 'D', 'gamma')
+  iota_path = os.path.join(wc_dir, 'iota')
+
+  gamma_contents = [
+    "\n",
+    "Another line before\n",
+    "A third line before\n",
+    "This is the file 'gamma'.\n",
+    "A line after\n",
+    "Another line after\n",
+    "A third line after\n",
+  ]
+
+  svntest.main.file_write(gamma_path, ''.join(gamma_contents))
+  expected_output = svntest.wc.State(wc_dir, {
+    'A/D/gamma'  : Item(verb='Sending'),
+    })
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('A/D/gamma', wc_rev=2)
+  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                        expected_status, None, wc_dir)
+  unidiff_patch = [
+    "--- A/D/gamma\t(revision 1)\n",
+    "+++ A/D/gamma\t(working copy)\n",
+    "@@ -1,7 +1,7 @@\n",
+    " \n",
+    " Another line before\n",
+    " A third line before\n",
+    "-This is the file 'gamma'.\n",
+    "+It is the file 'gamma'.\n",
+    " A line after\n",
+    " Another line after\n",
+    " A third line after\n",
+    "--- iota\t(revision 1)\n",
+    "+++ iota\t(working copy)\n",
+    "@@ -1 +1,2 @@\n",
+    " This is the file 'iota'.\n",
+    "+Some more bytes\n",
+  ]
+
+  svntest.main.file_write(patch_file_path, ''.join(unidiff_patch))
+
+  gamma_contents = [
+    "\n",
+    "Another line before\n",
+    "A third line before\n",
+    "It is the file 'gamma'.\n",
+    "A line after\n",
+    "Another line after\n",
+    "A third line after\n",
+  ]
+  iota_contents = [
+    "This is the file 'iota'.\n",
+    "Some more bytes\n",
+  ]
+  expected_output = [
+    'U         %s\n' % os.path.join(wc_dir, 'A', 'D', 'gamma'),
+    'U         %s\n' % os.path.join(wc_dir, 'iota'),
+  ]
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('A/D/gamma', contents=''.join(gamma_contents))
+  expected_disk.tweak('iota', contents=''.join(iota_contents))
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('A/D/gamma', status='M ', wc_rev=2)
+  expected_status.tweak('iota', status='M ', wc_rev=1)
+
+  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
+
 def patch_add_new_dir(sbox):
   "patch with missing dirs"
 
@@ -2171,6 +2257,7 @@ test_list = [ None,
               patch_offset,
               patch_chopped_leading_spaces,
               patch_strip1,
+              patch_no_index_line,
               patch_add_new_dir,
               patch_reject,
               patch_keywords,