summaryrefslogtreecommitdiff
path: root/subversion/libsvn_client/patch.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_client/patch.c')
-rw-r--r--subversion/libsvn_client/patch.c320
1 files changed, 246 insertions, 74 deletions
diff --git a/subversion/libsvn_client/patch.c b/subversion/libsvn_client/patch.c
index b7fbf06..6d8d0a4 100644
--- a/subversion/libsvn_client/patch.c
+++ b/subversion/libsvn_client/patch.c
@@ -48,6 +48,7 @@
#include "private/svn_dep_compat.h"
#include "private/svn_string_private.h"
#include "private/svn_subr_private.h"
+#include "private/svn_sorts_private.h"
typedef struct hunk_info_t {
/* The hunk. */
@@ -208,9 +209,6 @@ typedef struct patch_target_t {
/* True if the target had to be skipped for some reason. */
svn_boolean_t skipped;
- /* True if the target has been filtered by the patch callback. */
- svn_boolean_t filtered;
-
/* True if at least one hunk was rejected. */
svn_boolean_t had_rejects;
@@ -232,6 +230,10 @@ typedef struct patch_target_t {
* (i.e. a new file was added on top locally deleted node). */
svn_boolean_t replaced;
+ /* Set if the target is supposed to be moved by the patch.
+ * This applies to --git diffs which carry "rename from/to" headers. */
+ const char *move_target_abspath;
+
/* True if the target has the executable bit set. */
svn_boolean_t executable;
@@ -321,7 +323,8 @@ obtain_eol_and_keywords_for_file(apr_hash_t **keywords,
const char *rev_str;
const char *author;
const char *url;
- const char *root_url;
+ const char *repos_root_url;
+ const char *repos_relpath;
SVN_ERR(svn_wc__node_get_changed_info(&changed_rev,
&changed_date,
@@ -330,15 +333,17 @@ obtain_eol_and_keywords_for_file(apr_hash_t **keywords,
scratch_pool,
scratch_pool));
rev_str = apr_psprintf(scratch_pool, "%ld", changed_rev);
- SVN_ERR(svn_wc__node_get_url(&url, wc_ctx,
- local_abspath,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_wc__node_get_repos_info(NULL, NULL, &root_url, NULL,
+ SVN_ERR(svn_wc__node_get_repos_info(NULL, &repos_relpath, &repos_root_url,
+ NULL,
wc_ctx, local_abspath,
scratch_pool, scratch_pool));
+ url = svn_path_url_add_component2(repos_root_url, repos_relpath,
+ scratch_pool);
+
SVN_ERR(svn_subst_build_keywords3(keywords,
keywords_val->data,
- rev_str, url, root_url, changed_date,
+ rev_str, url, repos_root_url,
+ changed_date,
author, result_pool));
}
@@ -481,6 +486,8 @@ resolve_target_path(patch_target_t *target,
SVN_ERR(svn_wc__node_was_moved_away(&moved_to_abspath, NULL,
wc_ctx, target->local_abspath,
result_pool, scratch_pool));
+ /* ### BUG: moved_to_abspath contains the target where the op-root was
+ ### moved to... not the target itself! */
if (moved_to_abspath)
{
target->local_abspath = moved_to_abspath;
@@ -942,6 +949,12 @@ choose_target_filename(const svn_patch_t *patch)
if (strcmp(patch->new_filename, "/dev/null") == 0)
return patch->old_filename;
+ /* If the patch renames the target, use the old name while
+ * applying hunks. The target will be renamed to the new name
+ * after hunks have been applied. */
+ if (patch->operation == svn_diff_op_moved)
+ return patch->old_filename;
+
old = svn_path_component_count(patch->old_filename);
new = svn_path_component_count(patch->new_filename);
@@ -991,7 +1004,7 @@ init_patch_target(patch_target_t **patch_target,
hi;
hi = apr_hash_next(hi))
{
- svn_prop_patch_t *prop_patch = svn__apr_hash_index_val(hi);
+ svn_prop_patch_t *prop_patch = apr_hash_this_val(hi);
if (! has_prop_changes)
has_prop_changes = prop_patch->hunks->nelts > 0;
else
@@ -1021,6 +1034,7 @@ init_patch_target(patch_target_t **patch_target,
SVN_ERR(resolve_target_path(target, choose_target_filename(patch),
wcroot_abspath, strip_count, prop_changes_only,
wc_ctx, result_pool, scratch_pool));
+ *patch_target = target;
if (! target->skipped)
{
const char *diff_header;
@@ -1079,6 +1093,64 @@ init_patch_target(patch_target_t **patch_target,
target->added = TRUE;
else if (patch->operation == svn_diff_op_deleted)
target->deleted = TRUE;
+ else if (patch->operation == svn_diff_op_moved)
+ {
+ const char *move_target_path;
+ const char *move_target_relpath;
+ svn_boolean_t under_root;
+ svn_node_kind_t kind_on_disk;
+ svn_node_kind_t wc_kind;
+
+ move_target_path = svn_dirent_internal_style(patch->new_filename,
+ scratch_pool);
+
+ if (strip_count > 0)
+ SVN_ERR(strip_path(&move_target_path, move_target_path,
+ strip_count, scratch_pool, scratch_pool));
+
+ if (svn_dirent_is_absolute(move_target_path))
+ {
+ move_target_relpath = svn_dirent_is_child(wcroot_abspath,
+ move_target_path,
+ scratch_pool);
+ if (! move_target_relpath)
+ {
+ /* The move target path is either outside of the working
+ * copy or it is the working copy itself. Skip it. */
+ target->skipped = TRUE;
+ target->local_abspath = NULL;
+ return SVN_NO_ERROR;
+ }
+ }
+ else
+ move_target_relpath = move_target_path;
+
+ /* Make sure the move target path is secure to use. */
+ SVN_ERR(svn_dirent_is_under_root(&under_root,
+ &target->move_target_abspath,
+ wcroot_abspath,
+ move_target_relpath, result_pool));
+ if (! under_root)
+ {
+ /* The target path is outside of the working copy. Skip it. */
+ target->skipped = TRUE;
+ target->local_abspath = NULL;
+ return SVN_NO_ERROR;
+ }
+
+ SVN_ERR(svn_io_check_path(target->move_target_abspath,
+ &kind_on_disk, scratch_pool));
+ SVN_ERR(svn_wc_read_kind2(&wc_kind, wc_ctx,
+ target->move_target_abspath,
+ FALSE, FALSE, scratch_pool));
+ if (kind_on_disk != svn_node_none || wc_kind != svn_node_none)
+ {
+ /* The move target path already exists on disk. Skip target. */
+ target->skipped = TRUE;
+ target->move_target_abspath = NULL;
+ return SVN_NO_ERROR;
+ }
+ }
if (! target->is_symlink)
{
@@ -1136,8 +1208,8 @@ init_patch_target(patch_target_t **patch_target,
hi;
hi = apr_hash_next(hi))
{
- const char *prop_name = svn__apr_hash_index_key(hi);
- svn_prop_patch_t *prop_patch = svn__apr_hash_index_val(hi);
+ const char *prop_name = apr_hash_this_key(hi);
+ svn_prop_patch_t *prop_patch = apr_hash_this_val(hi);
prop_patch_target_t *prop_target;
SVN_ERR(init_prop_target(&prop_target,
@@ -1150,7 +1222,6 @@ init_patch_target(patch_target_t **patch_target,
}
}
- *patch_target = target;
return SVN_NO_ERROR;
}
@@ -1510,7 +1581,8 @@ match_existing_target(svn_boolean_t *match,
/* Determine the line at which a HUNK applies to CONTENT of the TARGET
* file, and return an appropriate hunk_info object in *HI, allocated from
* RESULT_POOL. Use fuzz factor FUZZ. Set HI->FUZZ to FUZZ. If no correct
- * line can be determined, set HI->REJECTED to TRUE.
+ * line can be determined, set HI->REJECTED to TRUE. PREVIOUS_OFFSET
+ * is the offset at which the previous matching hunk was applied, or zero.
* IGNORE_WHITESPACE tells whether whitespace should be considered when
* matching. IS_PROP_HUNK indicates whether the hunk patches file content
* or a property.
@@ -1522,6 +1594,7 @@ static svn_error_t *
get_hunk_info(hunk_info_t **hi, patch_target_t *target,
target_content_t *content,
svn_diff_hunk_t *hunk, svn_linenum_t fuzz,
+ svn_linenum_t previous_offset,
svn_boolean_t ignore_whitespace,
svn_boolean_t is_prop_hunk,
svn_cancel_func_t cancel_func, void *cancel_baton,
@@ -1531,7 +1604,7 @@ get_hunk_info(hunk_info_t **hi, patch_target_t *target,
svn_linenum_t original_start;
svn_boolean_t already_applied;
- original_start = svn_diff_hunk_get_original_start(hunk);
+ original_start = svn_diff_hunk_get_original_start(hunk) + previous_offset;
already_applied = FALSE;
/* An original offset of zero means that this hunk wants to create
@@ -1639,7 +1712,9 @@ get_hunk_info(hunk_info_t **hi, patch_target_t *target,
modified_start = svn_diff_hunk_get_modified_start(hunk);
if (modified_start == 0)
{
- /* Patch wants to delete the file. */
+ /* Patch wants to delete the file.
+
+ ### locally_deleted is always false here? */
already_applied = target->locally_deleted;
}
else
@@ -1660,27 +1735,85 @@ get_hunk_info(hunk_info_t **hi, patch_target_t *target,
if (! already_applied)
{
- /* Scan the whole file again from the start. */
- SVN_ERR(seek_to_line(content, 1, scratch_pool));
+ int i;
+ svn_linenum_t search_start = 1, search_end = 0;
+ svn_linenum_t matched_line2;
+
+ /* Search for closest match before or after original
+ start. We have no backward search so search forwards
+ from the previous match (or start of file) to the
+ original start looking for the last match. Then
+ search forwards from the original start looking for a
+ better match. Finally search forwards from the start
+ of file to the previous hunk if that could result in
+ a better match. */
+
+ for (i = content->hunks->nelts; i > 0; --i)
+ {
+ const hunk_info_t *prev
+ = APR_ARRAY_IDX(content->hunks, i - 1, const hunk_info_t *);
+ if (!prev->rejected)
+ {
+ svn_linenum_t length;
- /* Scan forward towards the hunk's line and look for a line
- * where the hunk matches. */
+ length = svn_diff_hunk_get_original_length(prev->hunk);
+ search_start = prev->matched_line + length;
+ break;
+ }
+ }
+
+ /* Search from the previous match, or start of file,
+ towards the original location. */
+ SVN_ERR(seek_to_line(content, search_start, scratch_pool));
SVN_ERR(scan_for_match(&matched_line, content, hunk, FALSE,
original_start, fuzz,
ignore_whitespace, FALSE,
cancel_func, cancel_baton,
scratch_pool));
- /* In tie-break situations, we arbitrarily prefer early matches
- * to save us from scanning the rest of the file. */
- if (matched_line == 0)
+ /* If a match we only need to search forwards for a
+ better match, otherwise to the end of the file. */
+ if (matched_line)
+ search_end = original_start + (original_start - matched_line);
+
+ /* Search from original location, towards the end. */
+ SVN_ERR(seek_to_line(content, original_start + 1, scratch_pool));
+ SVN_ERR(scan_for_match(&matched_line2, content, hunk,
+ TRUE, search_end, fuzz, ignore_whitespace,
+ FALSE, cancel_func, cancel_baton,
+ scratch_pool));
+
+ /* Chose the forward match if it is closer than the
+ backward match or if there is no backward match. */
+ if (matched_line2
+ && (!matched_line
+ || (matched_line2 - original_start
+ < original_start - matched_line)))
+ matched_line = matched_line2;
+
+ /* Search from before previous hunk if there could be a
+ better match. */
+ if (search_start > 1
+ && (!matched_line
+ || (matched_line > original_start
+ && (matched_line - original_start
+ > original_start - search_start))))
{
- /* Scan forward towards the end of the file and look
- * for a line where the hunk matches. */
- SVN_ERR(scan_for_match(&matched_line, content, hunk,
- TRUE, 0, fuzz, ignore_whitespace,
- FALSE, cancel_func, cancel_baton,
+ svn_linenum_t search_start2 = 1;
+
+ if (matched_line
+ && matched_line - original_start < original_start)
+ search_start2
+ = original_start - (matched_line - original_start) + 1;
+
+ SVN_ERR(seek_to_line(content, search_start2, scratch_pool));
+ SVN_ERR(scan_for_match(&matched_line2, content, hunk, FALSE,
+ search_start - 1, fuzz,
+ ignore_whitespace, FALSE,
+ cancel_func, cancel_baton,
scratch_pool));
+ if (matched_line2)
+ matched_line = matched_line2;
}
}
}
@@ -1725,7 +1858,7 @@ copy_lines_to_target(target_content_t *content, svn_linenum_t line,
SVN_ERR(readline(content, &target_line, iterpool, iterpool));
if (! content->eof)
target_line = apr_pstrcat(iterpool, target_line, content->eol_str,
- (char *)NULL);
+ SVN_VA_NULL);
len = strlen(target_line);
SVN_ERR(content->write(content->write_baton, target_line,
len, iterpool));
@@ -1949,7 +2082,7 @@ send_hunk_notification(const hunk_info_t *hi,
notify->hunk_fuzz = hi->fuzz;
notify->prop_name = prop_name;
- (*ctx->notify_func2)(ctx->notify_baton2, notify, pool);
+ ctx->notify_func2(ctx->notify_baton2, notify, pool);
return SVN_NO_ERROR;
}
@@ -1963,6 +2096,7 @@ send_patch_notification(const patch_target_t *target,
{
svn_wc_notify_t *notify;
svn_wc_notify_action_t action;
+ const char *notify_path;
if (! ctx->notify_func2)
return SVN_NO_ERROR;
@@ -1971,14 +2105,18 @@ send_patch_notification(const patch_target_t *target,
action = svn_wc_notify_skip;
else if (target->deleted)
action = svn_wc_notify_delete;
- else if (target->added || target->replaced)
+ else if (target->added || target->replaced || target->move_target_abspath)
action = svn_wc_notify_add;
else
action = svn_wc_notify_patch;
- notify = svn_wc_create_notify(target->local_abspath ? target->local_abspath
- : target->local_relpath,
- action, pool);
+ if (target->move_target_abspath)
+ notify_path = target->move_target_abspath;
+ else
+ notify_path = target->local_abspath ? target->local_abspath
+ : target->local_relpath;
+
+ notify = svn_wc_create_notify(notify_path, action, pool);
notify->kind = svn_node_file;
if (action == svn_wc_notify_skip)
@@ -2006,7 +2144,7 @@ send_patch_notification(const patch_target_t *target,
notify->prop_state = svn_wc_notify_state_changed;
}
- (*ctx->notify_func2)(ctx->notify_baton2, notify, pool);
+ ctx->notify_func2(ctx->notify_baton2, notify, pool);
if (action == svn_wc_notify_patch)
{
@@ -2033,7 +2171,7 @@ send_patch_notification(const patch_target_t *target,
{
prop_patch_target_t *prop_target;
- prop_target = svn__apr_hash_index_val(hash_index);
+ prop_target = apr_hash_this_val(hash_index);
for (i = 0; i < prop_target->content->hunks->nelts; i++)
{
@@ -2054,15 +2192,16 @@ send_patch_notification(const patch_target_t *target,
svn_pool_destroy(iterpool);
}
- return SVN_NO_ERROR;
-}
+ if (target->move_target_abspath)
+ {
+ /* Notify about deletion of move source. */
+ notify = svn_wc_create_notify(target->local_abspath,
+ svn_wc_notify_delete, pool);
+ notify->kind = svn_node_file;
+ ctx->notify_func2(ctx->notify_baton2, notify, pool);
+ }
-static void
-svn_sort__array(apr_array_header_t *array,
- int (*comparison_func)(const void *,
- const void *))
-{
- qsort(array->elts, array->nelts, array->elt_size, comparison_func);
+ return SVN_NO_ERROR;
}
/* Implements the callback for svn_sort__array. Puts hunks that match
@@ -2124,8 +2263,6 @@ apply_one_patch(patch_target_t **patch_target, svn_patch_t *patch,
int strip_count,
svn_boolean_t ignore_whitespace,
svn_boolean_t remove_tempfiles,
- svn_client_patch_func_t patch_func,
- void *patch_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *result_pool, apr_pool_t *scratch_pool)
@@ -2135,6 +2272,7 @@ apply_one_patch(patch_target_t **patch_target, svn_patch_t *patch,
int i;
static const svn_linenum_t MAX_FUZZ = 2;
apr_hash_index_t *hash_index;
+ svn_linenum_t previous_offset = 0;
SVN_ERR(init_patch_target(&target, patch, abs_wc_path, wc_ctx, strip_count,
remove_tempfiles, result_pool, scratch_pool));
@@ -2144,19 +2282,6 @@ apply_one_patch(patch_target_t **patch_target, svn_patch_t *patch,
return SVN_NO_ERROR;
}
- if (patch_func)
- {
- SVN_ERR(patch_func(patch_baton, &target->filtered,
- target->canon_path_from_patchfile,
- target->patched_path, target->reject_path,
- scratch_pool));
- if (target->filtered)
- {
- *patch_target = target;
- return SVN_NO_ERROR;
- }
- }
-
iterpool = svn_pool_create(scratch_pool);
/* Match hunks. */
for (i = 0; i < patch->hunks->nelts; i++)
@@ -2177,6 +2302,7 @@ apply_one_patch(patch_target_t **patch_target, svn_patch_t *patch,
do
{
SVN_ERR(get_hunk_info(&hi, target, target->content, hunk, fuzz,
+ previous_offset,
ignore_whitespace,
FALSE /* is_prop_hunk */,
cancel_func, cancel_baton,
@@ -2185,6 +2311,10 @@ apply_one_patch(patch_target_t **patch_target, svn_patch_t *patch,
}
while (hi->rejected && fuzz <= MAX_FUZZ && ! hi->already_applied);
+ if (hi->matched_line)
+ previous_offset
+ = hi->matched_line - svn_diff_hunk_get_original_start(hunk);
+
APR_ARRAY_PUSH(target->content->hunks, hunk_info_t *) = hi;
}
@@ -2236,8 +2366,8 @@ apply_one_patch(patch_target_t **patch_target, svn_patch_t *patch,
const char *prop_name;
prop_patch_target_t *prop_target;
- prop_name = svn__apr_hash_index_key(hash_index);
- prop_patch = svn__apr_hash_index_val(hash_index);
+ prop_name = apr_hash_this_key(hash_index);
+ prop_patch = apr_hash_this_val(hash_index);
if (! strcmp(prop_name, SVN_PROP_SPECIAL))
target->is_special = TRUE;
@@ -2263,7 +2393,7 @@ apply_one_patch(patch_target_t **patch_target, svn_patch_t *patch,
do
{
SVN_ERR(get_hunk_info(&hi, target, prop_target->content,
- hunk, fuzz,
+ hunk, fuzz, 0,
ignore_whitespace,
TRUE /* is_prop_hunk */,
cancel_func, cancel_baton,
@@ -2283,7 +2413,7 @@ apply_one_patch(patch_target_t **patch_target, svn_patch_t *patch,
{
prop_patch_target_t *prop_target;
- prop_target = svn__apr_hash_index_val(hash_index);
+ prop_target = apr_hash_this_val(hash_index);
for (i = 0; i < prop_target->content->hunks->nelts; i++)
{
@@ -2508,8 +2638,9 @@ create_missing_parents(patch_target_t *target,
if (ctx->cancel_func)
SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
- SVN_ERR(svn_wc_add_from_disk2(ctx->wc_ctx, local_abspath,
+ SVN_ERR(svn_wc_add_from_disk3(ctx->wc_ctx, local_abspath,
NULL /*props*/,
+ FALSE /* skip checks */,
ctx->notify_func2, ctx->notify_baton2,
iterpool));
}
@@ -2625,7 +2756,10 @@ install_patched_target(patch_target_t *target, const char *abs_wc_path,
svn_subst_eol_style_native);
SVN_ERR(svn_subst_copy_and_translate4(
- target->patched_path, target->local_abspath,
+ target->patched_path,
+ target->move_target_abspath
+ ? target->move_target_abspath
+ : target->local_abspath,
target->content->eol_str, repair_eol,
target->content->keywords,
TRUE /* expand */, FALSE /* special */,
@@ -2639,15 +2773,39 @@ install_patched_target(patch_target_t *target, const char *abs_wc_path,
* Suppress notification, we'll do that later (and also
* during dry-run). Don't allow cancellation because
* we'd rather notify about what we did before aborting. */
- SVN_ERR(svn_wc_add_from_disk2(ctx->wc_ctx, target->local_abspath,
+ SVN_ERR(svn_wc_add_from_disk3(ctx->wc_ctx, target->local_abspath,
NULL /*props*/,
+ FALSE /* skip checks */,
NULL, NULL, pool));
}
/* Restore the target's executable bit if necessary. */
- SVN_ERR(svn_io_set_file_executable(target->local_abspath,
+ SVN_ERR(svn_io_set_file_executable(target->move_target_abspath
+ ? target->move_target_abspath
+ : target->local_abspath,
target->executable,
FALSE, pool));
+
+ if (target->move_target_abspath)
+ {
+ /* ### Copying the patched content to the move target location,
+ * performing the move in meta-data, and removing the file at
+ * the move source should be one atomic operation. */
+
+ /* ### Create missing parents. */
+
+ /* Perform the move in meta-data. */
+ SVN_ERR(svn_wc__move2(ctx->wc_ctx,
+ target->local_abspath,
+ target->move_target_abspath,
+ TRUE, /* metadata_only */
+ FALSE, /* allow_mixed_revisions */
+ NULL, NULL, NULL, NULL,
+ pool));
+
+ /* Delete the patch target's old location from disk. */
+ SVN_ERR(svn_io_remove_file2(target->local_abspath, FALSE, pool));
+ }
}
}
@@ -2694,7 +2852,7 @@ install_patched_prop_targets(patch_target_t *target,
hi;
hi = apr_hash_next(hi))
{
- prop_patch_target_t *prop_target = svn__apr_hash_index_val(hi);
+ prop_patch_target_t *prop_target = apr_hash_this_val(hi);
const svn_string_t *prop_val;
svn_error_t *err;
@@ -2730,10 +2888,11 @@ install_patched_prop_targets(patch_target_t *target,
{
if (! dry_run)
{
- SVN_ERR(svn_io_file_create(target->local_abspath, "",
- scratch_pool));
- SVN_ERR(svn_wc_add_from_disk2(ctx->wc_ctx, target->local_abspath,
+ SVN_ERR(svn_io_file_create_empty(target->local_abspath,
+ scratch_pool));
+ SVN_ERR(svn_wc_add_from_disk3(ctx->wc_ctx, target->local_abspath,
NULL /*props*/,
+ FALSE /* skip checks */,
/* suppress notification */
NULL, NULL,
iterpool));
@@ -2869,10 +3028,13 @@ check_ancestor_delete(const char *deleted_target,
{
struct can_delete_baton_t cb;
svn_error_t *err;
+ apr_array_header_t *ignores;
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
const char *dir_abspath = svn_dirent_dirname(deleted_target, scratch_pool);
+ SVN_ERR(svn_wc_get_default_ignores(&ignores, ctx->config, scratch_pool));
+
while (svn_dirent_is_child(apply_root, dir_abspath, iterpool))
{
svn_pool_clear(iterpool);
@@ -2882,7 +3044,7 @@ check_ancestor_delete(const char *deleted_target,
cb.targets_info = targets_info;
err = svn_wc_walk_status(ctx->wc_ctx, dir_abspath, svn_depth_infinity,
- TRUE, FALSE, FALSE, NULL,
+ TRUE, FALSE, FALSE, ignores,
can_delete_callback, &cb,
ctx->cancel_func, ctx->cancel_baton,
iterpool);
@@ -2986,14 +3148,23 @@ apply_patches(/* The path to the patch file. */
if (patch)
{
patch_target_t *target;
+ svn_boolean_t filtered = FALSE;
SVN_ERR(apply_one_patch(&target, patch, abs_wc_path,
ctx->wc_ctx, strip_count,
ignore_whitespace, remove_tempfiles,
- patch_func, patch_baton,
ctx->cancel_func, ctx->cancel_baton,
iterpool, iterpool));
- if (! target->filtered)
+
+ if (!target->skipped && patch_func)
+ {
+ SVN_ERR(patch_func(patch_baton, &filtered,
+ target->canon_path_from_patchfile,
+ target->patched_path, target->reject_path,
+ iterpool));
+ }
+
+ if (! filtered)
{
/* Save info we'll still need when we're done patching. */
patch_target_info_t *target_info =
@@ -3009,6 +3180,7 @@ apply_patches(/* The path to the patch file. */
if (target->has_text_changes
|| target->added
+ || target->move_target_abspath
|| target->deleted)
SVN_ERR(install_patched_target(target, abs_wc_path,
ctx, dry_run, iterpool));