subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From danie...@apache.org
Subject svn commit: r1692720 - in /subversion/branches/patch-exec/subversion: libsvn_client/patch.c tests/cmdline/patch_tests.py
Date Sun, 26 Jul 2015 12:00:37 GMT
Author: danielsh
Date: Sun Jul 26 12:00:37 2015
New Revision: 1692720

URL: http://svn.apache.org/r1692720
Log:
On the patch-exec branch:
patch: Parse mode changes out of git patches, part 2: high-level client
functionality.

* subversion/libsvn_client/patch.c
  (private/svn_diff_private.h): Include.
  (init_patch_target): Translate executability changes into property changes.
  (apply_one_patch): Add special-case handling for executability propchanges.

* subversion/tests/cmdline/patch_tests.py
  (patch_adds_executability_nocontents,
   patch_adds_executability_yescontents): New tests.

Modified:
    subversion/branches/patch-exec/subversion/libsvn_client/patch.c
    subversion/branches/patch-exec/subversion/tests/cmdline/patch_tests.py

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=1692720&r1=1692719&r2=1692720&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_client/patch.c (original)
+++ subversion/branches/patch-exec/subversion/libsvn_client/patch.c Sun Jul 26 12:00:37 2015
@@ -46,6 +46,7 @@
 #include "private/svn_eol_private.h"
 #include "private/svn_wc_private.h"
 #include "private/svn_dep_compat.h"
+#include "private/svn_diff_private.h"
 #include "private/svn_string_private.h"
 #include "private/svn_subr_private.h"
 #include "private/svn_sorts_private.h"
@@ -1013,6 +1014,9 @@ init_patch_target(patch_target_t **patch
       }
   }
 
+  if (patch->new_executable_p != svn_tristate_unknown)
+    has_prop_changes = TRUE;
+
   prop_changes_only = has_prop_changes && patch->hunks->nelts == 0;
 
   content = apr_pcalloc(result_pool, sizeof(*content));
@@ -1220,6 +1224,56 @@ init_patch_target(patch_target_t **patch
                                        result_pool, scratch_pool));
               svn_hash_sets(target->prop_targets, prop_name, prop_target);
             }
+
+          if (patch->new_executable_p != svn_tristate_unknown
+              && !svn_hash_gets(target->prop_targets, SVN_PROP_EXECUTABLE))
+            {
+              svn_diff_operation_kind_t operation;
+              svn_boolean_t nothing_to_do = FALSE;
+              prop_patch_target_t *prop_target;
+
+              if (patch->old_executable_p == patch->new_executable_p)
+                {
+                    /* Noop change. */
+                    operation = svn_diff_op_unchanged;
+                }
+              else switch (patch->old_executable_p)
+                {
+                  case svn_tristate_false:
+                    /* Made executable. */
+                    operation = svn_diff_op_added;
+                    break;
+
+                  case svn_tristate_true:
+                    /* Made non-executable. */
+                    operation = svn_diff_op_deleted;
+                    break;
+
+                  case svn_tristate_unknown:
+                    if (patch->new_executable_p == svn_tristate_true)
+                      /* New, executable file. */
+                      operation = svn_diff_op_added;
+                    else
+                      /* New, non-executable file. That's not a change. */
+                      nothing_to_do = TRUE;
+                    break;
+
+                  default:
+                    /* NOTREACHED */
+                    abort();
+                }
+
+              if (! nothing_to_do)
+                {
+                  SVN_ERR(init_prop_target(&prop_target,
+                                           SVN_PROP_EXECUTABLE,
+                                           operation,
+                                           wc_ctx, target->local_abspath,
+                                           result_pool, scratch_pool));
+                  svn_hash_sets(target->prop_targets, SVN_PROP_EXECUTABLE,
+                                prop_target);
+                }
+            }
         }
     }
 
@@ -2375,6 +2429,7 @@ 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))
     {
@@ -2422,6 +2477,46 @@ apply_one_patch(patch_target_t **patch_t
         }
     }
 
+  /* Match implied property hunks. */
+  if (patch->new_executable_p != svn_tristate_unknown
+      && svn_hash_gets(target->prop_targets, SVN_PROP_EXECUTABLE))
+    {
+      hunk_info_t *hi;
+      svn_diff_hunk_t *hunk;
+      prop_patch_target_t *prop_target = svn_hash_gets(target->prop_targets,
+                                                       SVN_PROP_EXECUTABLE);
+      const char *const value = SVN_PROP_EXECUTABLE_VALUE;
+
+      switch (prop_target->operation)
+        {
+          case svn_diff_op_added:
+            SVN_ERR(svn_diff_hunk__create_adds_single_line(&hunk, value, patch,
+                                                           result_pool,
+                                                           iterpool));
+            break;
+
+          case svn_diff_op_deleted:
+            SVN__NOT_IMPLEMENTED();
+
+          case svn_diff_op_unchanged:
+            /* ### What to do? */
+            break;
+
+          default:
+            SVN_ERR_MALFUNCTION();
+        }
+
+      /* Derive a hunk_info from hunk. */
+      SVN_ERR(get_hunk_info(&hi, target, prop_target->content,
+                            hunk, 0 /* fuzz */, 0 /* previous_offset */,
+                            ignore_whitespace,
+                            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;
+    }
+
   /* Apply or reject property hunks. */
   for (hash_index = apr_hash_first(scratch_pool, target->prop_targets);
        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=1692720&r1=1692719&r2=1692720&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/tests/cmdline/patch_tests.py (original)
+++ subversion/branches/patch-exec/subversion/tests/cmdline/patch_tests.py Sun Jul 26 12:00:37
2015
@@ -5620,6 +5620,82 @@ def patch_obstructing_symlink_traversal(
                                        expected_output, expected_disk,
                                        expected_status, expected_skip)
 
+def patch_adds_executability_nocontents(sbox):
+  """patch adds svn:executable, without contents"""
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  unidiff_patch = (
+    "diff --git a/iota b/iota\n"
+    "old mode 100644\n"
+    "new mode 100755\n"
+    )
+  patch_file_path = make_patch_path(sbox)
+  svntest.main.file_write(patch_file_path, unidiff_patch)
+
+  ### Patch applies through the unversioned symlink
+  expected_output = [
+    ' U        %s\n' % sbox.ospath('iota'),
+  ]
+  expected_disk = svntest.main.greek_state.copy()
+  # "*" is SVN_PROP_EXECUTABLE_VALUE aka SVN_PROP_BOOLEAN_TRUE
+  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,
+                                       check_props=True)
+
+def patch_adds_executability_yescontents(sbox):
+  """patch adds svn:executable, with contents"""
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  mu_new_contents = (
+    "This is the file 'mu'.\n"
+    "with text mods too\n"
+    )
+
+  unidiff_patch = (
+    "diff --git a/A/mu b/A/mu\n"
+    "old mode 100644\n"
+    "new mode 100755\n"
+    "index 8a0f01c..dfad3ac\n"
+    "--- a/A/mu\n"
+    "+++ b/A/mu\n"
+    "@@ -1 +1,2 @@\n"
+    " This is the file 'mu'.\n"
+    "+with text mods too\n"
+    )
+  patch_file_path = make_patch_path(sbox)
+  svntest.main.file_write(patch_file_path, unidiff_patch)
+
+  ### Patch applies through the unversioned symlink
+  expected_output = [
+    'UU        %s\n' % sbox.ospath('A/mu'),
+  ]
+  expected_disk = svntest.main.greek_state.copy()
+  # "*" is SVN_PROP_EXECUTABLE_VALUE aka SVN_PROP_BOOLEAN_TRUE
+  expected_disk.tweak('A/mu', props={'svn:executable': '*'})
+  expected_disk.tweak('A/mu', contents=mu_new_contents)
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('A/mu', status='MM')
+
+  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,
+                                       check_props=True)
+
 ########################################################################
 #Run the tests
 
@@ -5681,6 +5757,8 @@ test_list = [ None,
               patch_closest,
               patch_symlink_traversal,
               patch_obstructing_symlink_traversal,
+              patch_adds_executability_nocontents,
+              patch_adds_executability_yescontents,
             ]
 
 if __name__ == '__main__':



Mime
View raw message