You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2010/04/16 01:37:59 UTC
svn commit: r934645 - /subversion/trunk/subversion/libsvn_client/patch.c
Author: stsp
Date: Thu Apr 15 23:37:58 2010
New Revision: 934645
URL: http://svn.apache.org/viewvc?rev=934645&view=rev
Log:
Allow for more fine-grained cancellation in the svn patch code.
* subversion/libsvn_client/patch.c
(match_hunk, scan_for_match, get_hunk_info, apply_one_patch):
Accept CANCEL_FUNC and CANCEL_BATON parameters, and use them
in strategic places. Hunk matching can take quite a bit of time
for large files but does not modify the working copy, so allowing
cancellation during it makes sense.
(install_patched_target): Allow cancellation in one case, and clearly
document why cancellation is being suppressed in other cases.
(delete_empty_dirs): Allow cancellation while deleting directories.
(apply_patches): Pass cancel_func and cancel_baton to apply_one_patch().
Suggested by: gstein
Modified:
subversion/trunk/subversion/libsvn_client/patch.c
Modified: subversion/trunk/subversion/libsvn_client/patch.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/patch.c?rev=934645&r1=934644&r2=934645&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/patch.c (original)
+++ subversion/trunk/subversion/libsvn_client/patch.c Thu Apr 15 23:37:58 2010
@@ -726,12 +726,14 @@ match_hunk(svn_boolean_t *matched, patch
* If the hunk matched multiple times, and MATCH_FIRST is FALSE,
* return the line number at which the last match occured in *MATCHED_LINE.
* If IGNORE_WHiTESPACES is set, ignore whitespaces during the matching.
+ * Call cancel CANCEL_FUNC with baton CANCEL_BATON to trigger cancellation.
* Do all allocations in POOL. */
static svn_error_t *
scan_for_match(svn_linenum_t *matched_line, patch_target_t *target,
const svn_hunk_t *hunk, svn_boolean_t match_first,
svn_linenum_t upper_line, int fuzz,
svn_boolean_t ignore_whitespaces,
+ svn_cancel_func_t cancel_func, void *cancel_baton,
apr_pool_t *pool)
{
apr_pool_t *iterpool;
@@ -746,6 +748,9 @@ scan_for_match(svn_linenum_t *matched_li
svn_pool_clear(iterpool);
+ if (cancel_func)
+ SVN_ERR((cancel_func)(cancel_baton));
+
SVN_ERR(match_hunk(&matched, target, hunk, fuzz, ignore_whitespaces,
iterpool));
if (matched)
@@ -789,12 +794,14 @@ scan_for_match(svn_linenum_t *matched_li
* IGNORE_WHiTESPACES tells whether whitespaces should be considered when
* matching. When this function returns, neither TARGET->CURRENT_LINE nor
* the file offset in the target file will have changed.
+ * Call cancel CANCEL_FUNC with baton CANCEL_BATON to trigger cancellation.
* Do temporary allocations in POOL. */
static svn_error_t *
get_hunk_info(hunk_info_t **hi, patch_target_t *target,
const svn_hunk_t *hunk, int fuzz,
- svn_boolean_t ignore_whitespaces, apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
+ svn_boolean_t ignore_whitespaces,
+ svn_cancel_func_t cancel_func, void *cancel_baton,
+ apr_pool_t *result_pool, apr_pool_t *scratch_pool)
{
svn_linenum_t matched_line;
@@ -824,7 +831,9 @@ get_hunk_info(hunk_info_t **hi, patch_ta
else
SVN_ERR(scan_for_match(&matched_line, target, hunk, TRUE,
hunk->original_start + 1, fuzz,
- ignore_whitespaces, scratch_pool));
+ ignore_whitespaces,
+ cancel_func, cancel_baton,
+ scratch_pool));
if (matched_line != hunk->original_start)
{
@@ -835,7 +844,9 @@ get_hunk_info(hunk_info_t **hi, patch_ta
* where the hunk matches. */
SVN_ERR(scan_for_match(&matched_line, target, hunk, FALSE,
hunk->original_start, fuzz,
- ignore_whitespaces, scratch_pool));
+ ignore_whitespaces,
+ 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. */
@@ -845,6 +856,7 @@ get_hunk_info(hunk_info_t **hi, patch_ta
* for a line where the hunk matches. */
SVN_ERR(scan_for_match(&matched_line, target, hunk, TRUE, 0,
fuzz, ignore_whitespaces,
+ cancel_func, cancel_baton,
scratch_pool));
}
}
@@ -1135,6 +1147,7 @@ send_patch_notification(const patch_targ
* as parsed from the patch file (after canonicalization).
* IGNORE_WHiTESPACES tells whether whitespaces should be considered when
* doing the matching.
+ * Call cancel CANCEL_FUNC with baton CANCEL_BATON to trigger cancellation.
* Do temporary allocations in SCRATCH_POOL. */
static svn_error_t *
apply_one_patch(patch_target_t **patch_target, svn_patch_t *patch,
@@ -1145,6 +1158,8 @@ apply_one_patch(patch_target_t **patch_t
apr_hash_t *patched_tempfiles,
apr_hash_t *reject_tempfiles,
svn_boolean_t ignore_whitespaces,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
apr_pool_t *result_pool, apr_pool_t *scratch_pool)
{
patch_target_t *target;
@@ -1173,6 +1188,9 @@ apply_one_patch(patch_target_t **patch_t
svn_pool_clear(iterpool);
+ if (cancel_func)
+ SVN_ERR((cancel_func)(cancel_baton));
+
hunk = APR_ARRAY_IDX(patch->hunks, i, svn_hunk_t *);
/* Determine the line the hunk should be applied at.
@@ -1180,7 +1198,9 @@ apply_one_patch(patch_target_t **patch_t
do
{
SVN_ERR(get_hunk_info(&hi, target, hunk, fuzz,
- ignore_whitespaces, result_pool, iterpool));
+ ignore_whitespaces,
+ cancel_func, cancel_baton,
+ result_pool, iterpool));
fuzz++;
}
while (hi->rejected && fuzz <= MAX_FUZZ);
@@ -1282,8 +1302,10 @@ install_patched_target(patch_target_t *t
if (! dry_run && ! target->parent_dir_deleted)
{
/* Schedule the target for deletion. Suppress
- * notification, we'll do it manually in a minute.
- * Also suppress cancellation. */
+ * notification, we'll do it manually in a minute
+ * because we also need to notify during dry-run.
+ * Also suppress cancellation, because we'd rather
+ * notify about what we did before aborting. */
SVN_ERR(svn_wc_delete4(ctx->wc_ctx, target->abs_path,
FALSE /* keep_local */, FALSE,
NULL, NULL, NULL, NULL, pool));
@@ -1394,13 +1416,16 @@ install_patched_target(patch_target_t *t
else
{
/* Create the missing component and add it
- * to version control. Suppress cancellation. */
+ * to version control. Allow cancellation since we
+ * have not modified the working copy yet for this
+ * target. */
SVN_ERR(svn_io_dir_make(abs_path, APR_OS_DEFAULT,
iterpool));
SVN_ERR(svn_wc_add4(ctx->wc_ctx, abs_path,
svn_depth_infinity,
NULL, SVN_INVALID_REVNUM,
- NULL, NULL,
+ ctx->cancel_func,
+ ctx->cancel_baton,
ctx->notify_func2,
ctx->notify_baton2,
iterpool));
@@ -1419,8 +1444,9 @@ install_patched_target(patch_target_t *t
{
/* The target file didn't exist previously,
* so add it to version control.
- * Suppress notification, we'll do that later.
- * Also suppress cancellation. */
+ * Suppress notification, we'll do that later (and also
+ * during dry-run). Also suppress cancellation because
+ * we'd rather notify about what we did before aborting. */
SVN_ERR(svn_wc_add4(ctx->wc_ctx, target->abs_path,
svn_depth_infinity,
NULL, SVN_INVALID_REVNUM,
@@ -1629,6 +1655,9 @@ delete_empty_dirs(apr_array_header_t *ta
svn_pool_clear(iterpool);
+ if (ctx->cancel_func)
+ SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
+
target = APR_ARRAY_IDX(targets, i, patch_target_t *);
parent = svn_dirent_dirname(target->abs_path, iterpool);
SVN_ERR(check_dir_empty(&parent_empty, parent, ctx->wc_ctx,
@@ -1654,6 +1683,9 @@ delete_empty_dirs(apr_array_header_t *ta
svn_pool_clear(iterpool);
+ if (ctx->cancel_func)
+ SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
+
/* Rebuild the empty dirs list, replacing empty dirs which have
* an empty parent with their parent. */
again = FALSE;
@@ -1722,8 +1754,8 @@ delete_empty_dirs(apr_array_header_t *ta
}
if (! dry_run)
SVN_ERR(svn_wc_delete4(ctx->wc_ctx, empty_dir, FALSE, FALSE,
- NULL, NULL, /* suppress cancellation */
- NULL, NULL, /* suppress notification */
+ ctx->cancel_func, ctx->cancel_baton,
+ NULL, NULL, /* no duplicate notification */
iterpool));
}
svn_pool_destroy(iterpool);
@@ -1821,6 +1853,8 @@ apply_patches(void *baton,
btn->include_patterns, btn->exclude_patterns,
btn->patched_tempfiles, btn->reject_tempfiles,
btn->ignore_whitespaces,
+ btn->ctx->cancel_func,
+ btn->ctx->cancel_baton,
result_pool, iterpool));
if (target->filtered)
SVN_ERR(svn_diff_close_patch(patch));