You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2015/10/04 17:52:19 UTC

svn commit: r1706693 - in /subversion/trunk/subversion: libsvn_client/patch.c tests/cmdline/patch_tests.py

Author: rhuijben
Date: Sun Oct  4 15:52:18 2015
New Revision: 1706693

URL: http://svn.apache.org/viewvc?rev=1706693&view=rev
Log:
Make the 'svn patch' notification use 'U' when a patch has been applied,
instead of forcing a 'G' status whenever there were local changes before
applying the patch. Also improve obstruction notifications a bit.

This shows the result of the patch instead of just what running status
might have shown if you didn't apply the patch. (The patch might have
removed the modification).

This patch doesn't affect the patch algorithms.

* subversion/libsvn_client/patch.c
  (patch_target_t): Track skip caused by obstruction. Drop local mods info.
  (resolve_target_path): Update initialization.
  (send_patch_notification): Update notifications.
  (install_patched_target): Handle invalid type obstructions.

* subversion/tests/cmdline/patch_tests.py
  (patch_no_svn_eol_style,
   patch_with_svn_eol_style_uncommitted,
   patch_reverse_revert): Tweak expected output.
  (patch_apply_no_fuz): Use standard patch runner. Tweak expected output.
  (patch_lacking_trailing_eol_on_context,
   patch_binary_file) Tweak expected output.
  (patch_final_eol): Update expected result. Add some comments.
  (patch_add_remove_executable,
   patch_git_symlink,
   patch_like_git_symlink,
   patch_add_one_line): Update expected result.

Modified:
    subversion/trunk/subversion/libsvn_client/patch.c
    subversion/trunk/subversion/tests/cmdline/patch_tests.py

Modified: subversion/trunk/subversion/libsvn_client/patch.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/patch.c?rev=1706693&r1=1706692&r2=1706693&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/patch.c (original)
+++ subversion/trunk/subversion/libsvn_client/patch.c Sun Oct  4 15:52:18 2015
@@ -213,6 +213,9 @@ typedef struct patch_target_t {
   /* True if the target had to be skipped for some reason. */
   svn_boolean_t skipped;
 
+  /* True if the reason for skipping is a local obstruction */
+  svn_boolean_t obstructed;
+
   /* True if the target has been filtered by the patch callback. */
   svn_boolean_t filtered;
 
@@ -228,10 +231,6 @@ typedef struct patch_target_t {
   /* True if at least one property hunk was handled as already applied */
   svn_boolean_t had_prop_already_applied;
 
-  /* True if the target file had local modifications before the
-   * patch was applied to it. */
-  svn_boolean_t local_mods;
-
   /* The operation on the target as set in the patch file */
   svn_diff_operation_kind_t operation;
 
@@ -537,6 +536,7 @@ resolve_target_path(patch_target_t *targ
            status->conflicted)
     {
       target->skipped = TRUE;
+      target->obstructed = TRUE;
       return SVN_NO_ERROR;
     }
   else if (status->node_status == svn_wc_status_deleted)
@@ -544,9 +544,6 @@ resolve_target_path(patch_target_t *targ
       target->locally_deleted = TRUE;
     }
 
-  if (status->text_status != svn_wc_status_normal)
-    target->local_mods = TRUE;
-
   if (status && (status->kind != svn_node_unknown))
     target->db_kind = status->kind;
   else
@@ -2281,15 +2278,16 @@ send_patch_notification(const patch_targ
                                         : target->local_relpath;
 
   notify = svn_wc_create_notify(notify_path, action, scratch_pool);
-  notify->kind = svn_node_file;
+  notify->kind = (target->db_kind == svn_node_dir) ? svn_node_dir
+                                                   : svn_node_file;
 
   if (action == svn_wc_notify_skip)
     {
-      if (target->db_kind == svn_node_none ||
-          target->db_kind == svn_node_unknown)
-        notify->content_state = svn_wc_notify_state_missing;
-      else if (target->db_kind == svn_node_dir)
+      if (target->obstructed)
         notify->content_state = svn_wc_notify_state_obstructed;
+      else if (target->db_kind == svn_node_none ||
+               target->db_kind == svn_node_unknown)
+        notify->content_state = svn_wc_notify_state_missing;
       else
         notify->content_state = svn_wc_notify_state_unknown;
     }
@@ -2297,8 +2295,6 @@ send_patch_notification(const patch_targ
     {
       if (target->had_rejects)
         notify->content_state = svn_wc_notify_state_conflicted;
-      else if (target->local_mods)
-        notify->content_state = svn_wc_notify_state_merged;
       else if (target->has_text_changes)
         notify->content_state = svn_wc_notify_state_changed;
       else if (target->had_already_applied)
@@ -3136,6 +3132,8 @@ install_patched_target(patch_target_t *t
               || wc_kind != target->kind_on_disk)
             {
               target->skipped = TRUE;
+              if (wc_kind != target->kind_on_disk)
+                target->obstructed = TRUE;
             }
         }
 

Modified: subversion/trunk/subversion/tests/cmdline/patch_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/patch_tests.py?rev=1706693&r1=1706692&r2=1706693&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/patch_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/patch_tests.py Sun Oct  4 15:52:18 2015
@@ -1647,9 +1647,9 @@ def patch_no_svn_eol_style(sbox):
 
       svntest.main.file_write(patch_file_path, ''.join(unidiff_patch))
 
-      expected_output = [
-        'G         %s\n' % sbox.ospath('A/mu'),
-      ]
+      expected_output = wc.State(wc_dir, {
+        'A/mu' : Item(status='U '),
+      })
       expected_disk = svntest.main.greek_state.copy()
       expected_disk.tweak('A/mu', contents=''.join(mu_contents))
 
@@ -1664,12 +1664,11 @@ def patch_no_svn_eol_style(sbox):
                                            expected_disk,
                                            expected_status,
                                            expected_skip,
-                                           None, # expected err
-                                           1, # check-props
-                                           1) # dry-run
+                                           [], True, True)
 
       expected_output = ["Reverted '" + mu_path + "'\n"]
-      svntest.actions.run_and_verify_svn(expected_output, [], 'revert', '-R', wc_dir)
+      svntest.actions.run_and_verify_svn(expected_output, [],
+                                         'revert', '-R', wc_dir)
 
 def patch_with_svn_eol_style(sbox):
   "patch target with svn:eol-style"
@@ -1870,9 +1869,9 @@ def patch_with_svn_eol_style_uncommitted
 
       svntest.main.file_write(patch_file_path, ''.join(unidiff_patch))
 
-      expected_output = [
-        'G         %s\n' % sbox.ospath('A/mu'),
-      ]
+      expected_output = wc.State(wc_dir, {
+        'A/mu' : Item(status='U '),
+      })
       expected_disk = svntest.main.greek_state.copy()
       expected_disk.tweak('A/mu', contents=''.join(mu_contents),
                           props={'svn:eol-style' : target_eol_style})
@@ -3370,10 +3369,10 @@ def patch_reverse_revert(sbox):
 
   # Applying the same patch in reverse should undo local mods
   expected_output = wc.State(wc_dir, {
-    'A/D/gamma'   : Item(status='G '),
-    'iota'        : Item(status='G '),
+    'A/D/gamma'   : Item(status='U '),
+    'iota'        : Item(status='U '),
     'new'         : Item(status='D '),
-    'A/mu'        : Item(status='G '),
+    'A/mu'        : Item(status='U '),
     'A/B/E/beta'  : Item(status='A '),
   })
   expected_disk = svntest.main.greek_state.copy()
@@ -4544,7 +4543,7 @@ def patch_apply_no_fuz(sbox):
   sbox.build(read_only=True)
   wc_dir = sbox.wc_dir
 
-  svntest.main.file_write(sbox.ospath('test.txt'), '\n'.join([
+  test1_body = '\n'.join([
       "line_1",
       "line_2",
       "line_3",
@@ -4576,8 +4575,9 @@ def patch_apply_no_fuz(sbox):
       "line_29",
       "line_30",
       ""
-    ]))
-  svntest.main.file_write(sbox.ospath('test_v2.txt'), '\n'.join([
+    ])
+  svntest.main.file_write(sbox.ospath('test.txt'), test1_body, 'wb')
+  test2_body = '\n'.join([
       "line_1a",
       "line_1b",
       "line_1c",
@@ -4620,7 +4620,8 @@ def patch_apply_no_fuz(sbox):
       "line_29",
       "line_30",
       ""
-    ]))
+    ])
+  svntest.main.file_write(sbox.ospath('test_v2.txt'), test2_body, 'wb')
 
   sbox.simple_add('test.txt', 'test_v2.txt')
 
@@ -4631,19 +4632,30 @@ def patch_apply_no_fuz(sbox):
                                                     '--new',
                                                     sbox.ospath('test_v2.txt'))
 
-  patch_path = sbox.ospath('patch.diff')
-  svntest.main.file_write(patch_path, ''.join(out_text))
+  patch_path = sbox.get_tempname('patch.diff')
+  svntest.main.file_write(patch_path, ''.join(out_text), 'wb')
 
-  expected_output = [
-    'G         %s\n' % sbox.ospath('test.txt'),
-  ]
+  expected_output = wc.State(wc_dir, {
+    'test.txt' : Item(status='U '),
+  })
 
-  # Current result: lf.txt patched ok, new created, empty succeeds with offset.
-  svntest.actions.run_and_verify_svn(expected_output, [],
-                                     'patch', patch_path, wc_dir)
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({
+    'test.txt' : Item(contents=test2_body),
+    'test_v2.txt' : Item(contents=test2_body),
+  })
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'test_v2.txt'       : Item(status='A ', wc_rev='-'),
+    'test.txt'          : Item(status='A ', wc_rev='-'),
+  })
 
-  if not filecmp.cmp(sbox.ospath('test.txt'), sbox.ospath('test_v2.txt')):
-    raise svntest.Failure("Patch result not identical")
+  expected_skip = wc.State(wc_dir, {})
+
+  svntest.actions.run_and_verify_patch(wc_dir, patch_path,
+                                       expected_output, expected_disk,
+                                       expected_status, expected_skip,
+                                       [], True, True)
 
 def patch_lacking_trailing_eol_on_context(sbox):
   "patch file lacking trailing eol on context"
@@ -4694,7 +4706,9 @@ def patch_lacking_trailing_eol_on_contex
   sbox.simple_append('iota', "Another line.\n")
   expected_disk.tweak('iota', contents="Some more bytes\n" + iota_contents +
                                        "Another line.\n")
-  expected_output = [ 'G         %s\n' % sbox.ospath('iota') ]
+  expected_output = wc.State(wc_dir, {
+    'iota' : Item(status='U ')
+  })
   svntest.actions.run_and_verify_patch(wc_dir, patch_file_path,
                                        expected_output, expected_disk,
                                        expected_status, expected_skip)
@@ -5766,7 +5780,7 @@ def patch_binary_file(sbox):
                                        [], True, True)
 
   # Ok, now try applying it backwards
-  expected_output.tweak('iota', status='GU')
+  expected_output.tweak('iota', status='UU')
   expected_disk = svntest.main.greek_state.copy()
   expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
   svntest.actions.run_and_verify_patch(wc_dir, tmp,
@@ -5964,14 +5978,15 @@ def patch_final_eol(sbox):
                                        expected_status, expected_skip,
                                        [], False, True)
 
-  # And again
-  expected_output.tweak('iota', 'A/mu', status='G ')
+  # And again - Still U as patch doesn't check final EOL of source
+  expected_output.tweak('iota', 'A/mu', status='U ')
   svntest.actions.run_and_verify_patch(wc_dir, patch,
                                        expected_output, expected_disk,
                                        expected_status, expected_skip,
                                        [], False, True)
 
   # Reverse
+  expected_output.tweak('iota', 'A/mu', status='U ')
   expected_disk.tweak('iota', contents="This is the file 'iota'.\n")
   expected_disk.tweak('A/mu', contents="This is the file 'mu'.\n")
   expected_status.tweak('iota', 'A/mu', status='  ')
@@ -6025,13 +6040,14 @@ def patch_final_eol(sbox):
                                        [], False, True)
 
   # And again
-  expected_output.tweak('iota', 'A/mu', status='G ')
+  expected_output.tweak('iota', 'A/mu', status='U ')
   svntest.actions.run_and_verify_patch(wc_dir, patch,
                                        expected_output, expected_disk,
                                        expected_status, expected_skip,
                                        [], False, True)
 
   # And in reverse
+  expected_output.tweak('iota', 'A/mu', status='U ')
   expected_disk.tweak('iota', contents="This is the file 'iota'.")
   expected_disk.tweak('A/mu', contents="This is the file 'mu'.")
   expected_status.tweak('iota', 'A/mu', status='  ')
@@ -6735,7 +6751,7 @@ def patch_add_remove_executable(sbox):
                                        [], True, True)
 
   # Now apply the edit
-  expected_output.tweak('eicar.com', status='GU')
+  expected_output.tweak('eicar.com', status='UU')
   expected_disk.tweak('eicar.com',
                       props={'svn:mime-type': 'application/octet-stream'},
                       contents=other_data)
@@ -6789,7 +6805,7 @@ def patch_add_remove_executable(sbox):
                                        '--reverse-diff')
 
   # And reverse the edit
-  expected_output.tweak('eicar.com', status='GU')
+  expected_output.tweak('eicar.com', status='UU')
   expected_disk.tweak('eicar.com', contents=eicar_data,
                       props={'svn:mime-type': 'application/octet-stream',
                               'svn:executable': '*'})
@@ -6910,7 +6926,7 @@ def patch_git_symlink(sbox):
                                        [], True, True)
 
   # Now tweak the link
-  expected_output.tweak('link-to-iota', status='G ')
+  expected_output.tweak('link-to-iota', status='U ')
   if svntest.main.is_posix_os():
     expected_disk.tweak('link-to-iota', contents="This is the file 'mu'.\n")
   else:
@@ -6921,6 +6937,7 @@ def patch_git_symlink(sbox):
                                        [], True, True)
 
   # And again
+  expected_output.tweak('link-to-iota', status='G ')
   svntest.actions.run_and_verify_patch(wc_dir, edit_patch,
                                        expected_output, expected_disk,
                                        expected_status, expected_skip,
@@ -7032,6 +7049,7 @@ def patch_like_git_symlink(sbox):
                                        [], True, True)
 
   # Now tweak the link
+  expected_output.tweak('link-to-iota', status='U ')
   expected_disk.tweak('link-to-iota', contents='A/mu')
   svntest.actions.run_and_verify_patch(wc_dir, edit_patch,
                                        expected_output, expected_disk,
@@ -7039,12 +7057,14 @@ def patch_like_git_symlink(sbox):
                                        [], True, True)
 
   # And again
+  expected_output.tweak('link-to-iota', status='G ')
   svntest.actions.run_and_verify_patch(wc_dir, edit_patch,
                                        expected_output, expected_disk,
                                        expected_status, expected_skip,
                                        [], True, True)
 
   # And replace the link with a file
+  expected_output.tweak('link-to-iota', status='U ')
   expected_output.tweak('link-to-iota', status='A ', prev_status='D ')
   expected_disk.tweak('link-to-iota', contents="This is a real file\n")
   svntest.actions.run_and_verify_patch(wc_dir, to_file_patch,
@@ -7284,6 +7304,7 @@ def patch_add_one_line(sbox):
                      "This is the file 'beta'.\n")
 
   # But can we remove the line? - Yes
+  expected_output.tweak(status='U ')
   svntest.actions.run_and_verify_patch(wc_dir, recurse_patch,
                                        expected_output, expected_disk,
                                        expected_status, expected_skip,
@@ -7300,6 +7321,7 @@ def patch_add_one_line(sbox):
                                        '--reverse-diff')
 
   # And the last lines? - No...
+  expected_output.tweak(status='G ')
   svntest.actions.run_and_verify_patch(wc_dir, recurse_patch,
                                        expected_output, expected_disk,
                                        expected_status, expected_skip,