subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From danie...@apache.org
Subject svn commit: r1694569 - in /subversion/branches/patch-exec: BRANCH-README subversion/include/svn_diff.h subversion/libsvn_client/patch.c subversion/tests/cmdline/patch_tests.py
Date Thu, 06 Aug 2015 20:33:44 GMT
Author: danielsh
Date: Thu Aug  6 20:33:44 2015
New Revision: 1694569

URL: http://svn.apache.org/r1694569
Log:
On the patch-exec branch, reject self-contradictory patches.

* subversion/libsvn_client/patch.c
  (contradictory_executability): New helper function.
  (init_patch_target): Reject patches that specify the executability state in
     two different, contradictory ways.
  (apply_one_patch): Remove outdated comment.

* subversion/tests/cmdline/patch_tests.py
  (patch_ambiguous_executability_consistent,
   patch_ambiguous_executability_contradiction): New test.

* BRANCH-README: Mark this task done.

Modified:
    subversion/branches/patch-exec/BRANCH-README
    subversion/branches/patch-exec/subversion/include/svn_diff.h
    subversion/branches/patch-exec/subversion/libsvn_client/patch.c
    subversion/branches/patch-exec/subversion/tests/cmdline/patch_tests.py

Modified: subversion/branches/patch-exec/BRANCH-README
URL: http://svn.apache.org/viewvc/subversion/branches/patch-exec/BRANCH-README?rev=1694569&r1=1694568&r2=1694569&view=diff
==============================================================================
--- subversion/branches/patch-exec/BRANCH-README (original)
+++ subversion/branches/patch-exec/BRANCH-README Thu Aug  6 20:33:44 2015
@@ -8,8 +8,7 @@ Steps:
 - [DONE] Implement parse-diff.c support
 - [DONE] Implement "make it executable" support, with tests
 - [DONE] Implement "make it non-executable" support, with tests
-- [TODO] Write tests for adding/remove svn:executable using the normal
-         'svn diff' property add/removal syntax
+- [DONE] Handle svn:executable and 'new mode' lines both present
 - [TODO] parser: Review handling of modes other than 0644/0755
                  Consider checking "mode & 0111"
 

Modified: subversion/branches/patch-exec/subversion/include/svn_diff.h
URL: http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/include/svn_diff.h?rev=1694569&r1=1694568&r2=1694569&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/include/svn_diff.h (original)
+++ subversion/branches/patch-exec/subversion/include/svn_diff.h Thu Aug  6 20:33:44 2015
@@ -1252,6 +1252,11 @@ typedef struct svn_patch_t {
 
   /** The old and new executability bits, as retrieved from the patch file.
    *
+   * A patch may specify an executability change via @a old_executable_p and
+   * / @a new_executable_p, via a #SVN_PROP_EXECUTABLE propchange hunk, or both
+   * ways; however, if both ways are used, they must specify the same semantic
+   * change.
+   *
    * #svn_tristate_unknown indicates the patch does not specify the
    * corresponding bit.
    *

Modified: subversion/branches/patch-exec/subversion/libsvn_client/patch.c
URL: http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_client/patch.c?rev=1694569&r1=1694568&r2=1694569&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_client/patch.c (original)
+++ subversion/branches/patch-exec/subversion/libsvn_client/patch.c Thu Aug  6 20:33:44 2015
@@ -959,6 +959,39 @@ choose_target_filename(const svn_patch_t
   return (old < new) ? patch->old_filename : patch->new_filename;
 }
 
+/* Return whether the svn:executable proppatch and the out-of-band
+ * executability metadata contradict each other, assuming both are present.
+ */
+svn_boolean_t
+contradictory_executability(const svn_patch_t *patch,
+                            const prop_patch_target_t *target)
+{
+  switch (target->operation)
+    {
+      case svn_diff_op_added:
+        return patch->new_executable_p == svn_tristate_false;
+
+      case svn_diff_op_deleted:
+        return patch->new_executable_p == svn_tristate_true;
+
+      case svn_diff_op_unchanged:
+        /* ### Can this happen? */
+        return (patch->old_executable_p != svn_tristate_unknown
+                && patch->new_executable_p != svn_tristate_unknown
+                && patch->old_executable_p == patch->new_executable_p);
+
+      case svn_diff_op_modified:
+        return (patch->old_executable_p != svn_tristate_unknown
+                && patch->new_executable_p != svn_tristate_unknown
+                && patch->old_executable_p != patch->new_executable_p);
+
+      default:
+        /* Can't happen: the proppatch parser never generates other values. */
+        SVN_ERR_MALFUNCTION_NO_RETURN();
+    }
+}
+
+
 /* Attempt to initialize a *PATCH_TARGET structure for a target file
  * described by PATCH. Use working copy context WC_CTX.
  * STRIP_COUNT specifies the number of leading path components
@@ -1192,6 +1225,7 @@ init_patch_target(patch_target_t **patch
       if (! target->skipped)
         {
           apr_hash_index_t *hi;
+          prop_patch_target_t *prop_executable_target;
 
           for (hi = apr_hash_first(result_pool, patch->prop_patches);
                hi;
@@ -1209,8 +1243,29 @@ init_patch_target(patch_target_t **patch
               svn_hash_sets(target->prop_targets, prop_name, prop_target);
             }
 
+          /* Now, check for an out-of-band mode change and convert it to
+           * an svn:executable property patch. */
+          prop_executable_target = svn_hash_gets(target->prop_targets,
+                                                 SVN_PROP_EXECUTABLE);
           if (patch->new_executable_p != svn_tristate_unknown
-              && !svn_hash_gets(target->prop_targets, SVN_PROP_EXECUTABLE))
+              && prop_executable_target)
+            {
+              if (contradictory_executability(patch, prop_executable_target))
+                /* Invalid input: specifies both git-like "new mode" lines and
+                 * svn-like addition/removal of svn:executable.
+                 *
+                 * If this were merely a hunk that didn't apply, we'd reject it
+                 * and move on.  However, this is a self-contradictory hunk;
+                 * it has no unambiguous interpretation.  Therefore: */
+                return svn_error_createf(SVN_ERR_INVALID_INPUT, NULL,
+                                         _("Invalid patch: specifies "
+                                           "contradicting mode changes and "
+                                           "%s changes (for '%s')"),
+                                         SVN_PROP_EXECUTABLE,
+                                         target->local_abspath);
+            }
+          else if (patch->new_executable_p != svn_tristate_unknown
+                   && !prop_executable_target)
             {
               svn_diff_operation_kind_t operation;
               svn_boolean_t nothing_to_do = FALSE;
@@ -2413,7 +2468,6 @@ apply_one_patch(patch_target_t **patch_t
 
   /* Match property hunks. */
   for (hash_index = apr_hash_first(scratch_pool, patch->prop_patches);
-       /* ### will be skipped for SVN_PROP_EXECUTABLE; okay? */
        hash_index;
        hash_index = apr_hash_next(hash_index))
     {

Modified: subversion/branches/patch-exec/subversion/tests/cmdline/patch_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/tests/cmdline/patch_tests.py?rev=1694569&r1=1694568&r2=1694569&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/tests/cmdline/patch_tests.py (original)
+++ subversion/branches/patch-exec/subversion/tests/cmdline/patch_tests.py Thu Aug  6 20:33:44
2015
@@ -5728,6 +5728,81 @@ def patch_deletes_executability(sbox):
                                        expected_status, expected_skip,
                                        check_props=True)
 
+def patch_ambiguous_executability_contradiction(sbox):
+  """patch ambiguous svn:executable, bad"""
+
+  sbox.build(read_only=True)
+  wc_dir = sbox.wc_dir
+
+  unidiff_patch = (
+    "Index: iota\n"
+    "===================================================================\n"
+    "diff --git a/iota b/iota\n"
+    "old mode 100755\n"
+    "new mode 100644\n"
+    "Property changes on: iota\n"
+    "-------------------------------------------------------------------\n"
+    "Added: svn:executable\n"
+    "## -0,0 +1 ##\n"
+    "+*\n"
+    )
+  patch_file_path = make_patch_path(sbox)
+  svntest.main.file_write(patch_file_path, unidiff_patch)
+
+  expected_output = []
+
+  expected_disk = svntest.main.greek_state.copy()
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+
+  expected_skip = wc.State('', { })
+
+  error_re_string = r'.*Invalid patch:.*contradicting.*mode.*svn:executable'
+  svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path),
+                                       expected_output, expected_disk,
+                                       expected_status, expected_skip,
+                                       error_re_string=error_re_string,
+                                       check_props=True)
+
+def patch_ambiguous_executability_consistent(sbox):
+  """patch ambiguous svn:executable, good"""
+
+  sbox.build(read_only=True)
+  wc_dir = sbox.wc_dir
+
+  unidiff_patch = (
+    "Index: iota\n"
+    "===================================================================\n"
+    "diff --git a/iota b/iota\n"
+    "old mode 100644\n"
+    "new mode 100755\n"
+    "Property changes on: iota\n"
+    "-------------------------------------------------------------------\n"
+    "Added: svn:executable\n"
+    "## -0,0 +1 ##\n"
+    "+*\n"
+    )
+  patch_file_path = make_patch_path(sbox)
+  svntest.main.file_write(patch_file_path, unidiff_patch)
+
+  expected_output = [
+    ' U        %s\n' % sbox.ospath('iota'),
+  ]
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('iota', props={'svn:executable': '*'})
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('iota', status=' M')
+
+  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,
+                                       error_re_string=None,
+                                       check_props=True)
+
 ########################################################################
 #Run the tests
 
@@ -5792,6 +5867,8 @@ test_list = [ None,
               patch_adds_executability_nocontents,
               patch_adds_executability_yescontents,
               patch_deletes_executability,
+              patch_ambiguous_executability_contradiction,
+              patch_ambiguous_executability_consistent,
             ]
 
 if __name__ == '__main__':



Mime
View raw message