Author: rinrab Date: Thu May 15 16:30:35 2025 New Revision: 1925565 URL: http://svn.apache.org/viewvc?rev=1925565&view=rev Log: Add an svn_client_patch_stream() function that applies patch from a file, instead of a local path, with adding a related test.
* subversion/include/svn_client.h (svn_client_patch_stream): Declare function. * subversion/libsvn_client/patch.c (svn_client_patch_stream): Implement function. * subversion/tests/libsvn_client/client-test.c (test_patch): Also test through the new function. Suggested by: brane See: https://lists.apache.org/thread/rrqn4xqgpdtfld8cxpgclc9gpbhj6cdj Modified: subversion/trunk/subversion/include/svn_client.h subversion/trunk/subversion/libsvn_client/patch.c subversion/trunk/subversion/tests/libsvn_client/client-test.c Modified: subversion/trunk/subversion/include/svn_client.h URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_client.h?rev=1925565&r1=1925564&r2=1925565&view=diff ============================================================================== --- subversion/trunk/subversion/include/svn_client.h (original) +++ subversion/trunk/subversion/include/svn_client.h Thu May 15 16:30:35 2025 @@ -7771,6 +7771,28 @@ svn_client_patch(const char *patch_abspa svn_client_ctx_t *ctx, apr_pool_t *scratch_pool); +/** + * Similar to svn_client_patch(), but the patch is read from a file handle, + * described in @a patch_file. + * + * In feature versions, this function may be used to apply a patch directly + * from an svn_stream_t. + * + * @since New in 1.15. + */ +svn_error_t * +svn_client_patch_stream(apr_file_t *patch_file, + const char *wc_dir_abspath, + svn_boolean_t dry_run, + int strip_count, + svn_boolean_t reverse, + svn_boolean_t ignore_whitespace, + svn_boolean_t remove_tempfiles, + svn_client_patch_func_t patch_func, + void *patch_baton, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool); + /** @} */ /** @} end group: Client working copy management */ Modified: subversion/trunk/subversion/libsvn_client/patch.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/patch.c?rev=1925565&r1=1925564&r2=1925565&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_client/patch.c (original) +++ subversion/trunk/subversion/libsvn_client/patch.c Thu May 15 16:30:35 2025 @@ -3786,3 +3786,52 @@ svn_client_patch(const char *patch_abspa return SVN_NO_ERROR; } + +svn_error_t * +svn_client_patch_stream(apr_file_t *patch_file, + const char *wc_dir_abspath, + svn_boolean_t dry_run, + int strip_count, + svn_boolean_t reverse, + svn_boolean_t ignore_whitespace, + svn_boolean_t remove_tempfiles, + svn_client_patch_func_t patch_func, + void *patch_baton, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + svn_node_kind_t kind; + svn_diff_patch_parser_t *patch_parser; + + if (strip_count < 0) + return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL, + _("strip count must be positive")); + + if (svn_path_is_url(wc_dir_abspath)) + return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, + _("'%s' is not a local path"), + svn_dirent_local_style(wc_dir_abspath, + scratch_pool)); + + SVN_ERR(svn_io_check_path(wc_dir_abspath, &kind, scratch_pool)); + if (kind == svn_node_none) + return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, + _("'%s' does not exist"), + svn_dirent_local_style(wc_dir_abspath, + scratch_pool)); + if (kind != svn_node_dir) + return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, + _("'%s' is not a directory"), + svn_dirent_local_style(wc_dir_abspath, + scratch_pool)); + + patch_parser = svn_diff_patch_parser_create(patch_file, scratch_pool); + + SVN_WC__CALL_WITH_WRITE_LOCK( + apply_patches(patch_parser, wc_dir_abspath, dry_run, strip_count, + reverse, ignore_whitespace, remove_tempfiles, + patch_func, patch_baton, ctx, scratch_pool), + ctx->wc_ctx, wc_dir_abspath, FALSE /* lock_anchor */, scratch_pool); + + return SVN_NO_ERROR; +} Modified: subversion/trunk/subversion/tests/libsvn_client/client-test.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_client/client-test.c?rev=1925565&r1=1925564&r2=1925565&view=diff ============================================================================== --- subversion/trunk/subversion/tests/libsvn_client/client-test.c (original) +++ subversion/trunk/subversion/tests/libsvn_client/client-test.c Thu May 15 16:30:35 2025 @@ -418,7 +418,6 @@ test_patch(const svn_test_opts_t *opts, SVN_ERR(svn_client_patch(patch_file_path, wc_path, FALSE, 0, FALSE, FALSE, FALSE, patch_collection_func, &pcb, ctx, pool)); - SVN_ERR(svn_io_file_close(patch_file, pool)); SVN_TEST_ASSERT(apr_hash_count(pcb.patched_tempfiles) == 1); key = "A/D/gamma"; @@ -433,6 +432,27 @@ test_patch(const svn_test_opts_t *opts, SVN_ERR(check_patch_result(reject_tempfile_path, expected_gamma_reject, APR_EOL_STR, EXPECTED_GAMMA_REJECT_LINES, pool)); + /* svn_client_patch_stream() test */ + apr_hash_clear(pcb.patched_tempfiles); + apr_hash_clear(pcb.reject_tempfiles); + + SVN_ERR(svn_client_patch_stream(patch_file, wc_path, FALSE, 0, FALSE, + FALSE, FALSE, patch_collection_func, &pcb, + ctx, pool)); + + SVN_TEST_ASSERT(apr_hash_count(pcb.patched_tempfiles) == 1); + patched_tempfile_path = apr_hash_get(pcb.patched_tempfiles, key, + APR_HASH_KEY_STRING); + SVN_ERR(check_patch_result(patched_tempfile_path, expected_gamma, "\n", + EXPECTED_GAMMA_LINES, pool)); + SVN_TEST_ASSERT(apr_hash_count(pcb.reject_tempfiles) == 1); + reject_tempfile_path = apr_hash_get(pcb.reject_tempfiles, key, + APR_HASH_KEY_STRING); + SVN_ERR(check_patch_result(reject_tempfile_path, expected_gamma_reject, + APR_EOL_STR, EXPECTED_GAMMA_REJECT_LINES, pool)); + + SVN_ERR(svn_io_file_close(patch_file, pool)); + return SVN_NO_ERROR; }
