Author: brane
Date: Sun Jan 25 02:17:46 2026
New Revision: 1931527

Log:
On the better-pristines branch: Add an optional callback to spillbufs to
customize how the spill file is created.

* subversion/include/private/svn_subr_private.h
  (svn_spillbuf__create_file_t): New callback type.
  (svn_spillbuf__set_spill_cb): New prototype.
* subversion/libsvn_subr/spillbuf.c: Include svn_error.h.
  (svn_spillbuf_t::create_spill_file): New struct member.
  (svn_spillbuf__create_extended): Initialize this struct member.
  (svn_spillbuf__set_spill_cb): Implement.
  (svn_spillbuf__write): Call the file creation callback.

* subversion/tests/libsvn_subr/spillbuf-test.c: Inlcude svn_io.h.
  (test_spillbuf__file_attrs): Verify that the spill file is deleted
   when it's closed. This is behaviour is specific to the test.
  (create_spillbuf_file): Spillbuf file creation callback.
  (test_spillbuf_file_attrs_spill_callback): New test. Use the callback
   to create a file with delete-on-close behaviour even when the
   spillbuf was created without that flag.
  (test_funcs): Register test_spillbuf_file_attrs_spill_callback.

Modified:
   
subversion/branches/better-pristines/subversion/include/private/svn_subr_private.h
   subversion/branches/better-pristines/subversion/libsvn_subr/spillbuf.c
   
subversion/branches/better-pristines/subversion/tests/libsvn_subr/spillbuf-test.c

Modified: 
subversion/branches/better-pristines/subversion/include/private/svn_subr_private.h
==============================================================================
--- 
subversion/branches/better-pristines/subversion/include/private/svn_subr_private.h
  Sun Jan 25 00:07:00 2026        (r1931526)
+++ 
subversion/branches/better-pristines/subversion/include/private/svn_subr_private.h
  Sun Jan 25 02:17:46 2026        (r1931527)
@@ -118,7 +118,27 @@ svn_spillbuf__create(apr_size_t blocksiz
                      apr_size_t maxsize,
                      apr_pool_t *result_pool);
 
-/* Determine how much content is stored in the spill buffer.  */
+/* Callback for creating the spillbuf's spill file.
+   The prototype is the same as for svn_io_open_unique_file3(). */
+typedef svn_error_t *(*svn_spillbuf__create_file_t)(
+    apr_file_t **file,
+    const char **temp_path,
+    const char *dirpath,
+    svn_io_file_del_t delete_when,
+    apr_pool_t *result_pool,
+    apr_pool_t *scratch_pool);
+
+/* Set a callback that will be called to create the spillbuf's spill file.
+   A default implemntation will be used if this callback is not set.
+   NOTE: Calling this function after the spill file has been created is
+         a programming error and will cause an assertion. It's best to
+         set the callback when the spillbuf is created and before the
+         first write. */
+svn_error_t *
+svn_spillbuf__set_spill_cb(svn_spillbuf_t *buf,
+                           svn_spillbuf__create_file_t create_spill_file);
+
+/* Determine how much content is stored in the spill buffer. */
 svn_filesize_t
 svn_spillbuf__get_size(const svn_spillbuf_t *buf);
 

Modified: subversion/branches/better-pristines/subversion/libsvn_subr/spillbuf.c
==============================================================================
--- subversion/branches/better-pristines/subversion/libsvn_subr/spillbuf.c      
Sun Jan 25 00:07:00 2026        (r1931526)
+++ subversion/branches/better-pristines/subversion/libsvn_subr/spillbuf.c      
Sun Jan 25 02:17:46 2026        (r1931527)
@@ -23,6 +23,7 @@
 
 #include <apr_file_io.h>
 
+#include "svn_error.h"
 #include "svn_io.h"
 #include "svn_pools.h"
 
@@ -80,6 +81,9 @@ struct svn_spillbuf_t {
   /* The name of the temporary spill file. */
   const char *filename;
 
+  /* The callback that creates the spill file, see above. */
+  svn_spillbuf__create_file_t create_spill_file;
+
   /* When false, do not delete the spill file when it is closed. */
   svn_boolean_t delete_on_close;
 
@@ -123,9 +127,10 @@ svn_spillbuf__create_extended(apr_size_t
   buf->pool = result_pool;
   buf->blocksize = blocksize;
   buf->maxsize = maxsize;
+  buf->dirpath = dirpath;
+  buf->create_spill_file = svn_io_open_unique_file3;
   buf->delete_on_close = 0 != (flags & SVN_SPILLBUF__DELETE_ON_CLOSE);
   buf->spill_all_contents = 0 != (flags & SVN_SPILLBUF__SPILL_ALL_CONTENTS);
-  buf->dirpath = dirpath;
   return buf;
 }
 
@@ -141,6 +146,15 @@ svn_spillbuf__create(apr_size_t blocksiz
       result_pool);
 }
 
+svn_error_t *
+svn_spillbuf__set_spill_cb(svn_spillbuf_t *buf,
+                           svn_spillbuf__create_file_t create_spill_file)
+{
+  SVN_ERR_ASSERT(!buf->spill && !buf->filename);
+  buf->create_spill_file = create_spill_file;
+  return SVN_NO_ERROR;
+}
+
 svn_filesize_t
 svn_spillbuf__get_size(const svn_spillbuf_t *buf)
 {
@@ -215,13 +229,13 @@ svn_spillbuf__write(svn_spillbuf_t *buf,
   if (buf->spill == NULL
       && ((buf->maxsize - buf->memory_size) < len))
     {
-      SVN_ERR(svn_io_open_unique_file3(&buf->spill,
-                                       &buf->filename,
-                                       buf->dirpath,
-                                       (buf->delete_on_close
-                                        ? svn_io_file_del_on_close
-                                        : svn_io_file_del_none),
-                                       buf->pool, scratch_pool));
+      SVN_ERR(buf->create_spill_file(&buf->spill,
+                                     &buf->filename,
+                                     buf->dirpath,
+                                     (buf->delete_on_close
+                                      ? svn_io_file_del_on_close
+                                      : svn_io_file_del_none),
+                                     buf->pool, scratch_pool));
 
       /* Optionally write the memory contents into the file. */
       if (buf->spill_all_contents)

Modified: 
subversion/branches/better-pristines/subversion/tests/libsvn_subr/spillbuf-test.c
==============================================================================
--- 
subversion/branches/better-pristines/subversion/tests/libsvn_subr/spillbuf-test.c
   Sun Jan 25 00:07:00 2026        (r1931526)
+++ 
subversion/branches/better-pristines/subversion/tests/libsvn_subr/spillbuf-test.c
   Sun Jan 25 02:17:46 2026        (r1931527)
@@ -21,6 +21,7 @@
  * ====================================================================
  */
 
+#include "svn_io.h"
 #include "svn_types.h"
 
 #include "private/svn_subr_private.h"
@@ -518,6 +519,8 @@ test_spillbuf__file_attrs(apr_pool_t *po
                           svn_spillbuf_t *buf)
 {
   svn_filesize_t filesize;
+  svn_node_kind_t kind;
+  const char *path;
 
   SVN_ERR(svn_spillbuf__write(buf, "abcdef", 6, pool));
   SVN_ERR(svn_spillbuf__write(buf, "ghijkl", 6, pool));
@@ -537,6 +540,15 @@ test_spillbuf__file_attrs(apr_pool_t *po
   else
     SVN_TEST_ASSERT(filesize == (svn_spillbuf__get_size(buf)
                                  - svn_spillbuf__get_memory_size(buf)));
+
+  /* The file must not exist after it is closed. */
+  path = svn_spillbuf__get_filename(buf);
+  SVN_ERR(svn_io_check_path(path, &kind, pool));
+  SVN_TEST_ASSERT(kind == svn_node_file);
+  SVN_ERR(svn_io_file_close(svn_spillbuf__get_file(buf), pool));
+  SVN_ERR(svn_io_check_path(path, &kind, pool));
+  SVN_TEST_ASSERT(kind == svn_node_none);
+
   return SVN_NO_ERROR;
 }
 
@@ -561,6 +573,31 @@ test_spillbuf_file_attrs_spill_all(apr_p
   return test_spillbuf__file_attrs(pool, TRUE, buf);
 }
 
+static svn_error_t *
+create_spillbuf_file(apr_file_t **file,
+                     const char **temp_path,
+                     const char *dirpath,
+                     svn_io_file_del_t delete_when,
+                     apr_pool_t *result_pool,
+                     apr_pool_t *scratch_pool)
+{
+  SVN_TEST_ASSERT(delete_when == svn_io_file_del_none);
+  return svn_io_open_unique_file3(file, temp_path, dirpath,
+                                  svn_io_file_del_on_close,
+                                  result_pool, scratch_pool);
+}
+
+static svn_error_t *
+test_spillbuf_file_attrs_spill_callback(apr_pool_t *pool)
+{
+  svn_spillbuf_t *buf = svn_spillbuf__create_extended(4 /* blocksize */,
+                                                      10 /* maxsize */,
+                                                      0, NULL, pool);
+  svn_spillbuf__set_spill_cb(buf, create_spillbuf_file);
+  return test_spillbuf__file_attrs(pool, FALSE, buf);
+}
+
+
 /* The test table.  */
 
 static int max_threads = 1;
@@ -592,6 +629,8 @@ static struct svn_test_descriptor_t test
     SVN_TEST_PASS2(test_spillbuf_file_attrs, "check spill file properties"),
     SVN_TEST_PASS2(test_spillbuf_file_attrs_spill_all,
                    "check spill file properties (spill-all-data)"),
+    SVN_TEST_PASS2(test_spillbuf_file_attrs_spill_callback,
+                   "check spill file properties (custom file)"),
     SVN_TEST_NULL
   };
 

Reply via email to