Skip to content

Commit 6a4d21c

Browse files
committed
Add svn_client_patch2 function that accesses the patch file from an
APR file instead of using a local path. * subversion/include/svn_client.h (svn_client_patch2): New function. (svn_client_patch): Deprecate. * subversion/libsvn_client/deprecated.c (svn_client_patch): Add and implement through svn_client_patch2(). * subversion/libsvn_client/patch.c (apply_patches): Accept a file instead of a path and create a svn_diff_patch_parser_t instead of opening a svn_patch_file_t. (svn_client_patch): Update implementation to svn_client_patch2. * subversion/svn/patch-cmd.c (svn_cl__patch): Check and open the patch file manually, pass to the new function, and close it then. * subversion/tests/libsvn_client/client-test.c (test_patch): Update patch api used. See also a related discussion with myself on dev@ where this was initiated: https://lists.apache.org/thread/p260hdrt5wx0tv6xs9l5nt3pvbzvnrv4 git-svn-id: https://svn.apache.org/repos/asf/subversion/trunk@1925463 13f79535-47bb-0310-9956-ffa450edef68
1 parent ed30630 commit 6a4d21c

5 files changed

Lines changed: 116 additions & 46 deletions

File tree

subversion/include/svn_client.h

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7718,8 +7718,9 @@ typedef svn_error_t *(*svn_client_patch_func_t)(
77187718
apr_pool_t *scratch_pool);
77197719

77207720
/**
7721-
* Apply a unidiff patch that's located at absolute path
7722-
* @a patch_abspath to the working copy directory at @a wc_dir_abspath.
7721+
* Apply a unidiff patch, described in @a apr_file which should have
7722+
* @c APR_READ and @c APR_BUFFERED capabilities to the working copy
7723+
* directory at @a wc_dir_abspath.
77237724
*
77247725
* This function makes a best-effort attempt at applying the patch.
77257726
* It might skip patch targets which cannot be patched (e.g. targets
@@ -7756,7 +7757,26 @@ typedef svn_error_t *(*svn_client_patch_func_t)(
77567757
*
77577758
* Use @a scratch_pool for temporary allocations.
77587759
*
7759-
* @since New in 1.7.
7760+
* @since New in 1.15.
7761+
*/
7762+
svn_error_t *
7763+
svn_client_patch2(apr_file_t *apr_file,
7764+
const char *wc_dir_abspath,
7765+
svn_boolean_t dry_run,
7766+
int strip_count,
7767+
svn_boolean_t reverse,
7768+
svn_boolean_t ignore_whitespace,
7769+
svn_boolean_t remove_tempfiles,
7770+
svn_client_patch_func_t patch_func,
7771+
void *patch_baton,
7772+
svn_client_ctx_t *ctx,
7773+
apr_pool_t *scratch_pool);
7774+
7775+
/**
7776+
* Similar to svn_client_patch2(), but accessing the patch by an absolute
7777+
* path.
7778+
*
7779+
* @deprecated Provided for backward compatibility with the 1.7 API.
77607780
*/
77617781
svn_error_t *
77627782
svn_client_patch(const char *patch_abspath,

subversion/libsvn_client/deprecated.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3290,3 +3290,46 @@ svn_client_upgrade(const char *path,
32903290
return svn_error_trace(svn_client_upgrade2(NULL, path, NULL, ctx,
32913291
NULL, scratch_pool));
32923292
}
3293+
3294+
svn_error_t *
3295+
svn_client_patch(const char *patch_abspath,
3296+
const char *wc_dir_abspath,
3297+
svn_boolean_t dry_run,
3298+
int strip_count,
3299+
svn_boolean_t reverse,
3300+
svn_boolean_t ignore_whitespace,
3301+
svn_boolean_t remove_tempfiles,
3302+
svn_client_patch_func_t patch_func,
3303+
void *patch_baton,
3304+
svn_client_ctx_t *ctx,
3305+
apr_pool_t *scratch_pool)
3306+
{
3307+
svn_node_kind_t kind;
3308+
apr_file_t *apr_file;
3309+
3310+
SVN_ERR(svn_io_check_path(patch_abspath, &kind, scratch_pool));
3311+
if (kind == svn_node_none)
3312+
return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
3313+
_("'%s' does not exist"),
3314+
svn_dirent_local_style(patch_abspath,
3315+
scratch_pool));
3316+
if (kind != svn_node_file)
3317+
return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
3318+
_("'%s' is not a file"),
3319+
svn_dirent_local_style(patch_abspath,
3320+
scratch_pool));
3321+
3322+
SVN_ERR(svn_io_file_open(&apr_file, patch_abspath,
3323+
APR_READ | APR_BUFFERED, APR_OS_DEFAULT,
3324+
scratch_pool));
3325+
3326+
SVN_ERR(svn_client_patch2(apr_file, wc_dir_abspath,
3327+
dry_run, strip_count, reverse,
3328+
ignore_whitespace, remove_tempfiles,
3329+
patch_func, patch_baton,
3330+
ctx, scratch_pool));
3331+
3332+
SVN_ERR(svn_io_file_close(apr_file, scratch_pool));
3333+
3334+
return SVN_NO_ERROR;
3335+
}

subversion/libsvn_client/patch.c

Lines changed: 19 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3613,8 +3613,8 @@ check_ancestor_delete(const char *deleted_target,
36133613

36143614
/* This function is the main entry point into the patch code. */
36153615
static svn_error_t *
3616-
apply_patches(/* The path to the patch file. */
3617-
const char *patch_abspath,
3616+
apply_patches(/* The patch file. */
3617+
apr_file_t *apr_file,
36183618
/* The abspath to the working copy the patch should be applied to. */
36193619
const char *root_abspath,
36203620
/* Indicates whether we're doing a dry run. */
@@ -3636,11 +3636,10 @@ apply_patches(/* The path to the patch file. */
36363636
{
36373637
svn_patch_t *patch;
36383638
apr_pool_t *iterpool;
3639-
svn_patch_file_t *patch_file;
3639+
svn_diff_patch_parser_t *patch_parser;
36403640
apr_array_header_t *targets_info;
36413641

3642-
/* Try to open the patch file. */
3643-
SVN_ERR(svn_diff_open_patch_file(&patch_file, patch_abspath, scratch_pool));
3642+
patch_parser = svn_diff_patch_parser_create(apr_file, scratch_pool);
36443643

36453644
/* Apply patches. */
36463645
targets_info = apr_array_make(scratch_pool, 0,
@@ -3653,9 +3652,9 @@ apply_patches(/* The path to the patch file. */
36533652
if (ctx->cancel_func)
36543653
SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
36553654

3656-
SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file,
3657-
reverse, ignore_whitespace,
3658-
iterpool, iterpool));
3655+
SVN_ERR(svn_diff_patch_parser_next(&patch, patch_parser,
3656+
reverse, ignore_whitespace,
3657+
iterpool, iterpool));
36593658
if (patch)
36603659
{
36613660
patch_target_t *target;
@@ -3720,24 +3719,23 @@ apply_patches(/* The path to the patch file. */
37203719
}
37213720
while (patch);
37223721

3723-
SVN_ERR(svn_diff_close_patch_file(patch_file, iterpool));
37243722
svn_pool_destroy(iterpool);
37253723

37263724
return SVN_NO_ERROR;
37273725
}
37283726

37293727
svn_error_t *
3730-
svn_client_patch(const char *patch_abspath,
3731-
const char *wc_dir_abspath,
3732-
svn_boolean_t dry_run,
3733-
int strip_count,
3734-
svn_boolean_t reverse,
3735-
svn_boolean_t ignore_whitespace,
3736-
svn_boolean_t remove_tempfiles,
3737-
svn_client_patch_func_t patch_func,
3738-
void *patch_baton,
3739-
svn_client_ctx_t *ctx,
3740-
apr_pool_t *scratch_pool)
3728+
svn_client_patch2(apr_file_t *apr_file,
3729+
const char *wc_dir_abspath,
3730+
svn_boolean_t dry_run,
3731+
int strip_count,
3732+
svn_boolean_t reverse,
3733+
svn_boolean_t ignore_whitespace,
3734+
svn_boolean_t remove_tempfiles,
3735+
svn_client_patch_func_t patch_func,
3736+
void *patch_baton,
3737+
svn_client_ctx_t *ctx,
3738+
apr_pool_t *scratch_pool)
37413739
{
37423740
svn_node_kind_t kind;
37433741

@@ -3751,18 +3749,6 @@ svn_client_patch(const char *patch_abspath,
37513749
svn_dirent_local_style(wc_dir_abspath,
37523750
scratch_pool));
37533751

3754-
SVN_ERR(svn_io_check_path(patch_abspath, &kind, scratch_pool));
3755-
if (kind == svn_node_none)
3756-
return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
3757-
_("'%s' does not exist"),
3758-
svn_dirent_local_style(patch_abspath,
3759-
scratch_pool));
3760-
if (kind != svn_node_file)
3761-
return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
3762-
_("'%s' is not a file"),
3763-
svn_dirent_local_style(patch_abspath,
3764-
scratch_pool));
3765-
37663752
SVN_ERR(svn_io_check_path(wc_dir_abspath, &kind, scratch_pool));
37673753
if (kind == svn_node_none)
37683754
return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
@@ -3776,7 +3762,7 @@ svn_client_patch(const char *patch_abspath,
37763762
scratch_pool));
37773763

37783764
SVN_WC__CALL_WITH_WRITE_LOCK(
3779-
apply_patches(patch_abspath, wc_dir_abspath, dry_run, strip_count,
3765+
apply_patches(apr_file, wc_dir_abspath, dry_run, strip_count,
37803766
reverse, ignore_whitespace, remove_tempfiles,
37813767
patch_func, patch_baton, ctx, scratch_pool),
37823768
ctx->wc_ctx, wc_dir_abspath, FALSE /* lock_anchor */, scratch_pool);

subversion/svn/patch-cmd.c

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,10 @@ svn_cl__patch(apr_getopt_t *os,
5151
apr_array_header_t *targets;
5252
const char *abs_patch_path;
5353
const char *patch_path;
54+
apr_file_t *patch_file;
5455
const char *abs_target_path;
5556
const char *target_path;
57+
svn_node_kind_t kind;
5658

5759
opt_state = ((svn_cl__cmd_baton_t *)baton)->opt_state;
5860
ctx = ((svn_cl__cmd_baton_t *)baton)->ctx;
@@ -74,6 +76,19 @@ svn_cl__patch(apr_getopt_t *os,
7476

7577
SVN_ERR(svn_dirent_get_absolute(&abs_patch_path, patch_path, pool));
7678

79+
SVN_ERR(svn_io_check_path(abs_patch_path, &kind, pool));
80+
if (kind == svn_node_none)
81+
return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
82+
_("'%s' does not exist"),
83+
svn_dirent_local_style(abs_patch_path, pool));
84+
if (kind != svn_node_file)
85+
return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
86+
_("'%s' is not a file"),
87+
svn_dirent_local_style(abs_patch_path, pool));
88+
89+
SVN_ERR(svn_io_file_open(&patch_file, abs_patch_path,
90+
APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool));
91+
7792
if (targets->nelts == 1)
7893
target_path = ""; /* "" is the canonical form of "." */
7994
else
@@ -84,12 +99,13 @@ svn_cl__patch(apr_getopt_t *os,
8499
}
85100
SVN_ERR(svn_dirent_get_absolute(&abs_target_path, target_path, pool));
86101

87-
SVN_ERR(svn_client_patch(abs_patch_path, abs_target_path,
88-
opt_state->dry_run, opt_state->strip,
89-
opt_state->reverse_diff,
90-
opt_state->ignore_whitespace,
91-
TRUE, NULL, NULL, ctx, pool));
102+
SVN_ERR(svn_client_patch2(patch_file, abs_target_path,
103+
opt_state->dry_run, opt_state->strip,
104+
opt_state->reverse_diff,
105+
opt_state->ignore_whitespace,
106+
TRUE, NULL, NULL, ctx, pool));
92107

108+
SVN_ERR(svn_io_file_close(patch_file, pool));
93109

94110
if (! opt_state->quiet)
95111
SVN_ERR(svn_cl__notifier_print_conflict_stats(ctx->notify_baton2, pool));

subversion/tests/libsvn_client/client-test.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,8 @@ test_patch(const svn_test_opts_t *opts,
348348
const char *reject_tempfile_path;
349349
const char *key;
350350
int i;
351+
apr_off_t off;
352+
351353
#define NL APR_EOL_STR
352354
#define UNIDIFF_LINES 7
353355
const char *unidiff_patch[UNIDIFF_LINES] = {
@@ -401,8 +403,8 @@ test_patch(const svn_test_opts_t *opts,
401403
pool, svn_test_data_path("test-patch", pool),
402404
"test-patch.diff", SVN_VA_NULL);
403405
SVN_ERR(svn_io_file_open(&patch_file, patch_file_path,
404-
(APR_READ | APR_WRITE | APR_CREATE | APR_TRUNCATE),
405-
APR_OS_DEFAULT, pool));
406+
(APR_READ | APR_WRITE | APR_CREATE | APR_TRUNCATE
407+
| APR_BUFFERED), APR_OS_DEFAULT, pool));
406408
for (i = 0; i < UNIDIFF_LINES; i++)
407409
{
408410
apr_size_t len = strlen(unidiff_patch[i]);
@@ -415,9 +417,12 @@ test_patch(const svn_test_opts_t *opts,
415417
pcb.patched_tempfiles = apr_hash_make(pool);
416418
pcb.reject_tempfiles = apr_hash_make(pool);
417419
pcb.state_pool = pool;
418-
SVN_ERR(svn_client_patch(patch_file_path, wc_path, FALSE, 0, FALSE,
419-
FALSE, FALSE, patch_collection_func, &pcb,
420-
ctx, pool));
420+
421+
off = 0;
422+
SVN_ERR(svn_io_file_seek(patch_file, APR_SET, &off, pool));
423+
SVN_ERR(svn_client_patch2(patch_file, wc_path, FALSE, 0, FALSE,
424+
FALSE, FALSE, patch_collection_func, &pcb,
425+
ctx, pool));
421426
SVN_ERR(svn_io_file_close(patch_file, pool));
422427

423428
SVN_TEST_ASSERT(apr_hash_count(pcb.patched_tempfiles) == 1);

0 commit comments

Comments
 (0)