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/09/28 19:43:26 UTC

svn commit: r1705733 - in /subversion/trunk/subversion: include/private/svn_diff_private.h libsvn_client/patch.c libsvn_diff/parse-diff.c tests/cmdline/patch_tests.py

Author: rhuijben
Date: Mon Sep 28 17:43:25 2015
New Revision: 1705733

URL: http://svn.apache.org/viewvc?rev=1705733&view=rev
Log:
Stop applying some kinds of property changes during 'svn patch' that should
have been stopped by a conflict.

Properties were deleted even if the original value didn't match. This
catches some hidden bugs in the svn:executable handling.

* subversion/include/private/svn_diff_private.h
  (svn_diff_hunk__create_adds_single_line,
   svn_diff_hunk__create_deletes_single_line): Constify argument.

* subversion/libsvn_client/patch.c
  (prop_patch_target_t): Add boolean.
  (apply_one_patch): Always push diff items to allow notifying conflicts.
    Set skip if nothing changed
  (install_patched_prop_targets): If skipping the property don't change its
    value.

* subversion/libsvn_diff/parse-diff.c
  (svn_diff_hunk_t,
   svn_diff_binary_patch_t): Constify pointer.
  (svn_diff_hunk__create_adds_single_line,
   svn_diff_hunk__create_deletes_single_line): Create reversed hunks, to allow
     reading them back as not reversed.

* subversion/tests/cmdline/patch_tests.py
  (patch_prop_madness): Tweak expectations. Expect conflicts on property
    mismatches, but (currently) not on final EOL only changes.

Modified:
    subversion/trunk/subversion/include/private/svn_diff_private.h
    subversion/trunk/subversion/libsvn_client/patch.c
    subversion/trunk/subversion/libsvn_diff/parse-diff.c
    subversion/trunk/subversion/tests/cmdline/patch_tests.py

Modified: subversion/trunk/subversion/include/private/svn_diff_private.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_diff_private.h?rev=1705733&r1=1705732&r2=1705733&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_diff_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_diff_private.h Mon Sep 28 17:43:25 2015
@@ -123,7 +123,7 @@ svn_diff__display_prop_diffs(svn_stream_
 svn_error_t *
 svn_diff_hunk__create_adds_single_line(svn_diff_hunk_t **hunk,
                                        const char *line,
-                                       svn_patch_t *patch,
+                                       const svn_patch_t *patch,
                                        apr_pool_t *result_pool,
                                        apr_pool_t *scratch_pool);
 
@@ -137,7 +137,7 @@ svn_diff_hunk__create_adds_single_line(s
 svn_error_t *
 svn_diff_hunk__create_deletes_single_line(svn_diff_hunk_t **hunk,
                                           const char *line,
-                                          svn_patch_t *patch,
+                                          const svn_patch_t *patch,
                                           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=1705733&r1=1705732&r2=1705733&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/patch.c (original)
+++ subversion/trunk/subversion/libsvn_client/patch.c Mon Sep 28 17:43:25 2015
@@ -153,6 +153,9 @@ typedef struct prop_patch_target_t {
    * ### Should we use flags instead since we're not using all enum values? */
   svn_diff_operation_kind_t operation;
 
+  /* When true the property change won't be applied */
+  svn_boolean_t skipped;
+
   /* ### Here we'll add flags telling if the prop was added, deleted,
    * ### had_rejects, had_local_mods prior to patching and so on. */
 } prop_patch_target_t;
@@ -2622,8 +2625,7 @@ apply_one_patch(patch_target_t **patch_t
                             TRUE /* is_prop_hunk */,
                             cancel_func, cancel_baton,
                             result_pool, iterpool));
-      if (! hi->already_applied)
-        APR_ARRAY_PUSH(prop_target->content->hunks, hunk_info_t *) = hi;
+      APR_ARRAY_PUSH(prop_target->content->hunks, hunk_info_t *) = hi;
     }
 
   /* Apply or reject property hunks. */
@@ -2632,6 +2634,7 @@ apply_one_patch(patch_target_t **patch_t
        hash_index = apr_hash_next(hash_index))
     {
       prop_patch_target_t *prop_target;
+      svn_boolean_t applied_one = FALSE;
 
       prop_target = apr_hash_this_val(hash_index);
 
@@ -2653,24 +2656,30 @@ apply_one_patch(patch_target_t **patch_t
                                 prop_target->name,
                                 iterpool));
           else
-            SVN_ERR(apply_hunk(target, prop_target->content, hi,
-                               prop_target->name,
-                               iterpool));
+            {
+              SVN_ERR(apply_hunk(target, prop_target->content, hi,
+                                 prop_target->name,
+                                 iterpool));
+              applied_one = TRUE;
+            }
         }
 
-        if (prop_target->content->existed)
-          {
-            /* Copy any remaining lines to target. */
-            SVN_ERR(copy_lines_to_target(prop_target->content, 0,
-                                         scratch_pool));
-            if (! prop_target->content->eof)
-              {
-                /* We could not copy the entire target property to the
-                 * temporary file, and would truncate the target if we
-                 * copied the temporary file on top of it. Skip this target.  */
-                target->skipped = TRUE;
-              }
-          }
+      if (!applied_one)
+        prop_target->skipped = TRUE;
+
+      if (applied_one && prop_target->content->existed)
+        {
+          /* Copy any remaining lines to target. */
+          SVN_ERR(copy_lines_to_target(prop_target->content, 0,
+                                       scratch_pool));
+          if (! prop_target->content->eof)
+            {
+              /* We could not copy the entire target property to the
+               * temporary file, and would truncate the target if we
+               * copied the temporary file on top of it. Skip this target.  */
+              target->skipped = TRUE;
+            }
+        }
       }
 
   svn_pool_destroy(iterpool);
@@ -3102,6 +3111,9 @@ install_patched_prop_targets(patch_targe
       if (ctx->cancel_func)
         SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
 
+      if (prop_target->skipped)
+        continue;
+
       /* For a deleted prop we only set the value to NULL. */
       if (prop_target->operation == svn_diff_op_deleted)
         {

Modified: subversion/trunk/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_diff/parse-diff.c?rev=1705733&r1=1705732&r2=1705733&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/trunk/subversion/libsvn_diff/parse-diff.c Mon Sep 28 17:43:25 2015
@@ -64,7 +64,7 @@ struct svn_diff__hunk_range {
 
 struct svn_diff_hunk_t {
   /* The patch this hunk belongs to. */
-  svn_patch_t *patch;
+  const svn_patch_t *patch;
 
   /* APR file handle to the patch file this hunk came from. */
   apr_file_t *apr_file;
@@ -93,7 +93,7 @@ struct svn_diff_hunk_t {
 
 struct svn_diff_binary_patch_t {
   /* The patch this hunk belongs to. */
-  svn_patch_t *patch;
+  const svn_patch_t *patch;
 
   /* APR file handle to the patch file this hunk came from. */
   apr_file_t *apr_file;
@@ -117,7 +117,7 @@ struct svn_diff_binary_patch_t {
 static svn_error_t *
 add_or_delete_single_line(svn_diff_hunk_t **hunk_out,
                           const char *line,
-                          svn_patch_t *patch,
+                          const svn_patch_t *patch,
                           svn_boolean_t add,
                           apr_pool_t *result_pool,
                           apr_pool_t *scratch_pool)
@@ -202,11 +202,12 @@ add_or_delete_single_line(svn_diff_hunk_
 svn_error_t *
 svn_diff_hunk__create_adds_single_line(svn_diff_hunk_t **hunk_out,
                                        const char *line,
-                                       svn_patch_t *patch,
+                                       const svn_patch_t *patch,
                                        apr_pool_t *result_pool,
                                        apr_pool_t *scratch_pool)
 {
-  SVN_ERR(add_or_delete_single_line(hunk_out, line, patch, TRUE,
+  SVN_ERR(add_or_delete_single_line(hunk_out, line, patch, 
+                                    (!patch->reverse),
                                     result_pool, scratch_pool));
   return SVN_NO_ERROR;
 }
@@ -214,11 +215,12 @@ svn_diff_hunk__create_adds_single_line(s
 svn_error_t *
 svn_diff_hunk__create_deletes_single_line(svn_diff_hunk_t **hunk_out,
                                           const char *line,
-                                          svn_patch_t *patch,
+                                          const svn_patch_t *patch,
                                           apr_pool_t *result_pool,
                                           apr_pool_t *scratch_pool)
 {
-  SVN_ERR(add_or_delete_single_line(hunk_out, line, patch, FALSE,
+  SVN_ERR(add_or_delete_single_line(hunk_out, line, patch,
+                                    patch->reverse,
                                     result_pool, scratch_pool));
   return SVN_NO_ERROR;
 }

Modified: subversion/trunk/subversion/tests/cmdline/patch_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/patch_tests.py?rev=1705733&r1=1705732&r2=1705733&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/patch_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/patch_tests.py Mon Sep 28 17:43:25 2015
@@ -6227,6 +6227,17 @@ def patch_prop_madness(sbox):
 
   sbox.simple_commit()
 
+  r2_props = {
+   'mod_l_n' : 'this\nis\na\nvery\nvery\nlong\nvalue.\nwithout\neol',
+   'mod_l'   : 'this\nis\na\nvery\nvery\nlong\nvalue.\n',
+   'mod_s'   : 'value\n',
+   'mod_s_n' : 'no-eol',
+   'del'     : 'value\n',
+   'del_n'   : 'no-eol',
+  }
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('iota', 'A/mu', props=r2_props)
+
   sbox.simple_propset('mod_s', 'other\n',
                       'iota', 'A/mu')
 
@@ -6259,7 +6270,6 @@ def patch_prop_madness(sbox):
   _, output, _ = svntest.actions.run_and_verify_svn(None, [],
                                                     'diff', wc_dir)
 
-  expected_disk = svntest.main.greek_state.copy()
   expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
 
   new_props = {
@@ -6311,15 +6321,7 @@ def patch_prop_madness(sbox):
 
   # Reverse
   expected_output.tweak('A/mu', 'iota', status=' U')
-  props = {
-   'mod_l_n' : 'this\nis\na\nvery\nvery\nlong\nvalue.\nwithout\neol',
-   'mod_l'   : 'this\nis\na\nvery\nvery\nlong\nvalue.\n',
-   'mod_s'   : 'value\n',
-   'mod_s_n' : 'no-eol',
-   'del'     : 'value\n',
-   'del_n'   : 'no-eol',
-  }
-  expected_disk.tweak('A/mu', 'iota', props=props)
+  expected_disk.tweak('A/mu', 'iota', props=r2_props)
   expected_status.tweak('A/mu', 'iota', status='  ')
   svntest.actions.run_and_verify_patch(wc_dir, patch,
                                        expected_output, expected_disk,
@@ -6340,12 +6342,39 @@ def patch_prop_madness(sbox):
   # Ok, and now introduce some conflicts
 
   sbox.simple_propset('del', 'value', 'iota') # Wrong EOL
-  sbox.simple_propset('del', 'waarde', 'A/mu') # Wrong EOL+value
-
-  sbox.simple_propset('del_n', 'no-eol\n', 'iota') # Wrong EOL
   sbox.simple_propset('del_n', 'regeleinde\n', 'iota') # Wrong EOL+value
 
+  sbox.simple_propset('del', 'waarde', 'A/mu') # Wrong EOL+value
+  sbox.simple_propset('del_n', 'no-eol\n', 'A/mu') # Wrong EOL
+
   expected_output.tweak('A/mu', 'iota', status=' C')
+  expected_status.tweak('iota', 'A/mu', status=' M')
+
+  iota_props = new_props.copy()
+  iota_props['del_n'] = 'regeleinde\n'
+  mu_props = new_props.copy()
+  mu_props['del'] = 'waarde'
+  expected_disk.tweak('iota', props=iota_props)
+  expected_disk.tweak('A/mu', props=mu_props)
+
+  expected_disk.add({
+   'A/mu.svnpatch.rej' : Item(contents="--- %s\n"
+                                       "+++ %s\n"
+                                       "Property: del\n"
+                                       "## -1,1 +0,0 ##\n"
+                                       "-value\n"
+                                       % (sbox.path('A/mu'),
+                                          sbox.path('A/mu'))),
+   'iota.svnpatch.rej' : Item(contents="--- %s\n"
+                                       "+++ %s\n"
+                                       "Property: del_n\n"
+                                       "## -1,1 +0,0 ##\n"
+                                       "-no-eol\n"
+                                       "\ No newline at end of property\n"
+                                       % (sbox.path('iota'),
+                                          sbox.path('iota'))),
+  })
+
   svntest.actions.run_and_verify_patch(wc_dir, patch,
                                        expected_output, expected_disk,
                                        expected_status, expected_skip,