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;
 }
 


Reply via email to