> However, I noticed a little problem in the implementation of patching; The > svn_client_patch() function accesses the patchfile by an absolute path > instead of a handle to a file. This follows that the file will be opened > twice. Is it possible to modify it, so the svn_client_patch() function > will accept apr_file_t or a svn_stream_t instead of an absolute path to > this file?
Hi, I made a work-in-progress patch in which svn_client_patch [now svn_client_patch2] function will read the patch, which has already been opened at the top of the callstack. Attaching the patch to the email as 'svn-patch-by-file-wip-v1.patch.txt'. What do you think, should I continue this work? PS: this is a patch of svn-patch :-) -- Timofei Zhakov
Index: subversion/include/svn_client.h =================================================================== --- subversion/include/svn_client.h (revision 1922465) +++ subversion/include/svn_client.h (working copy) @@ -7756,9 +7756,29 @@ * * Use @a scratch_pool for temporary allocations. * - * @since New in 1.7. + * @since New in 1.15. */ svn_error_t * +svn_client_patch2(apr_file_t *apr_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); + + +/** + * Similar to svn_client_patch2(), but accessing the patch by an absolute + * path. + * + * @deprecated Provided for backward compatibility with the 1.7 API. + */ +svn_error_t * svn_client_patch(const char *patch_abspath, const char *wc_dir_abspath, svn_boolean_t dry_run, Index: subversion/include/svn_diff.h =================================================================== --- subversion/include/svn_diff.h (revision 1922465) +++ subversion/include/svn_diff.h (working copy) @@ -1333,11 +1333,24 @@ * @since New in 1.7. */ typedef struct svn_patch_file_t svn_patch_file_t; -/** Open @a patch_file at @a local_abspath. +/** + * Open @a patch_file at @a local_abspath. * Allocate @a patch_file in @a result_pool. * - * @since New in 1.7. */ + * @since New in 1.15. + */ svn_error_t * +svn_diff_open_patch_file2(svn_patch_file_t **patch_file, + apr_file_t *file, + apr_pool_t *result_pool); + +/** + * Similar to svn_diff_open_patch_file2(), but accessing the patch by an + * absolute path. + * + * @deprecated Provided for backward compatibility with the 1.7 API. + */ +svn_error_t * svn_diff_open_patch_file(svn_patch_file_t **patch_file, const char *local_abspath, apr_pool_t *result_pool); @@ -1365,7 +1378,9 @@ * Use @a scratch_pool for all temporary allocations. * * @since New in 1.7. + * @deprecated Provided for backward compatibility with the 1.7 API. */ +SVN_DEPRECATED svn_error_t * svn_diff_close_patch_file(svn_patch_file_t *patch_file, apr_pool_t *scratch_pool); Index: subversion/libsvn_client/deprecated.c =================================================================== --- subversion/libsvn_client/deprecated.c (revision 1922465) +++ subversion/libsvn_client/deprecated.c (working copy) @@ -3290,3 +3290,42 @@ return svn_error_trace(svn_client_upgrade2(NULL, path, NULL, ctx, NULL, scratch_pool)); } + +svn_error_t * +svn_client_patch(const char *patch_abspath, + 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; + apr_file_t *apr_file; + + SVN_ERR(svn_io_check_path(patch_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(patch_abspath, + scratch_pool)); + if (kind != svn_node_file) + return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, + _("'%s' is not a file"), + svn_dirent_local_style(patch_abspath, + scratch_pool)); + + SVN_ERR(svn_io_file_open(&apr_file, patch_abspath, + APR_READ | APR_BUFFERED, APR_OS_DEFAULT, + scratch_pool)); + + return svn_error_trace(svn_client_patch2(apr_file, wc_dir_abspath, + dry_run, strip_count, reverse, + ignore_whitespace, remove_tempfiles, + patch_func, patch_baton, + ctx, scratch_pool)); +} Index: subversion/libsvn_client/patch.c =================================================================== --- subversion/libsvn_client/patch.c (revision 1922465) +++ subversion/libsvn_client/patch.c (working copy) @@ -3613,8 +3613,8 @@ /* This function is the main entry point into the patch code. */ static svn_error_t * -apply_patches(/* The path to the patch file. */ - const char *patch_abspath, +apply_patches(/* The patch file. */ + apr_file_t *apr_file, /* The abspath to the working copy the patch should be applied to. */ const char *root_abspath, /* Indicates whether we're doing a dry run. */ @@ -3640,7 +3640,7 @@ apr_array_header_t *targets_info; /* Try to open the patch file. */ - SVN_ERR(svn_diff_open_patch_file(&patch_file, patch_abspath, scratch_pool)); + SVN_ERR(svn_diff_open_patch_file2(&patch_file, apr_file, scratch_pool)); /* Apply patches. */ targets_info = apr_array_make(scratch_pool, 0, @@ -3727,17 +3727,17 @@ } svn_error_t * -svn_client_patch(const char *patch_abspath, - 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_client_patch2(apr_file_t *apr_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; @@ -3751,18 +3751,6 @@ svn_dirent_local_style(wc_dir_abspath, scratch_pool)); - SVN_ERR(svn_io_check_path(patch_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(patch_abspath, - scratch_pool)); - if (kind != svn_node_file) - return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, - _("'%s' is not a file"), - svn_dirent_local_style(patch_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, @@ -3776,7 +3764,7 @@ scratch_pool)); SVN_WC__CALL_WITH_WRITE_LOCK( - apply_patches(patch_abspath, wc_dir_abspath, dry_run, strip_count, + apply_patches(apr_file, 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); Index: subversion/libsvn_diff/deprecated.c =================================================================== --- subversion/libsvn_diff/deprecated.c (revision 1922465) +++ subversion/libsvn_diff/deprecated.c (working copy) @@ -462,3 +462,19 @@ NULL, NULL, pool)); } + +svn_error_t * +svn_diff_open_patch_file(svn_patch_file_t **patch_file, + const char *local_abspath, + apr_pool_t *result_pool) +{ + apr_file_t *file; + + SVN_ERR(svn_io_file_open(&file, local_abspath, + APR_READ | APR_BUFFERED, APR_OS_DEFAULT, + result_pool)); + + return svn_error_trace(svn_diff_open_patch_file2(patch_file, file, + result_pool)); + +} Index: subversion/libsvn_diff/parse-diff.c =================================================================== --- subversion/libsvn_diff/parse-diff.c (revision 1922465) +++ subversion/libsvn_diff/parse-diff.c (working copy) @@ -1957,16 +1957,14 @@ }; svn_error_t * -svn_diff_open_patch_file(svn_patch_file_t **patch_file, - const char *local_abspath, - apr_pool_t *result_pool) +svn_diff_open_patch_file2(svn_patch_file_t **patch_file, + apr_file_t *file, + apr_pool_t *result_pool) { svn_patch_file_t *p; p = apr_palloc(result_pool, sizeof(*p)); - SVN_ERR(svn_io_file_open(&p->apr_file, local_abspath, - APR_READ | APR_BUFFERED, APR_OS_DEFAULT, - result_pool)); + p->apr_file = file; p->next_patch_offset = 0; *patch_file = p;