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 2015/07/26 14:00:37 UTC
svn commit: r1692720 - in /subversion/branches/patch-exec/subversion:
libsvn_client/patch.c tests/cmdline/patch_tests.py
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__':