Author: rinrab
Date: Thu May  8 13:51:32 2025
New Revision: 1925462

URL: http://svn.apache.org/viewvc?rev=1925462&view=rev
Log:
Implement a patch file parser in libsvn_diff's level that consumes an
apr_file_t as its source instead of a local_abspath, used in the
svn_patch_file_t interface.

The completely new abstraction is mandatory, because the existing one
(svn_patch_file_t) implements open and close methods which also close
the file, however, if we want to pass it the top, close method will still
affect the file.

The newly introduced in this commit interface (svn_diff_patch_parser_t) can be
initialised from a APR file pointer using the svn_diff_patch_parser_create()
function and used in svn_diff_patch_parser_next().

To maintain svn_patch_file_t related behaviour and prevent code duplication,
it is made up to simply wrap the svn_diff_patch_parser_t interface.

* subversion/include/svn_diff.h
  (svn_diff_patch_parser_t,
   svn_diff_patch_parser_create,
   svn_diff_patch_parser_next): Declare symbols.
* subversion/libsvn_diff/parse-diff.c
  (svn_diff_patch_parser_t): Implement structure.
  (svn_diff_patch_parser_create,
   svn_diff_patch_parser_next): Implement functions.
  (svn_patch_file_t): Replace internal parser information with reference to
     a patch parser; Move to bottom group.
  (svn_diff_open_patch_file): Correctly create the structure and its new
     field; Move to bottom group.
  (svn_diff_parse_next_patch): Implement trough svn_diff_patch_parser_next()

Modified:
    subversion/trunk/subversion/include/svn_diff.h
    subversion/trunk/subversion/libsvn_diff/parse-diff.c

Modified: subversion/trunk/subversion/include/svn_diff.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_diff.h?rev=1925462&r1=1925461&r2=1925462&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_diff.h (original)
+++ subversion/trunk/subversion/include/svn_diff.h Thu May  8 13:51:32 2025
@@ -1370,6 +1370,45 @@ svn_error_t *
 svn_diff_close_patch_file(svn_patch_file_t *patch_file,
                           apr_pool_t *scratch_pool);
 
+/**
+ * Patch file parser.
+ *
+ * @since New in 1.15
+ */
+typedef struct svn_diff_patch_parser_t svn_diff_patch_parser_t;
+
+/**
+ * Initialises an instance of @a svn_diff_patch_parser_t from @a patch_file,
+ * which may be used in order to parse patch files through svn_diff_parser*
+ * routines.
+ *
+ * @since New in 1.15
+ */
+svn_diff_patch_parser_t *
+svn_diff_patch_parser_create(apr_file_t *patch_file,
+                             apr_pool_t *result_pool);
+
+/**
+ * Parses the next @a *patch from @a parser.
+ * If no patch can be found, set @a *patch to NULL.
+ * If @a reverse is TRUE, invert the patch while parsing it.
+ * If @a ignore_whitespace is TRUE, allow patches with no leading
+ * whitespace to be parsed.
+ * Allocate results in @a result_pool.
+ * Use @a scratch_pool for all other allocations.
+ *
+ * @since New in 1.15.
+ * @note Similar to @c svn_diff_parse_next_patch(), but utilizing the parser
+ *       as its source.
+ */
+svn_error_t *
+svn_diff_patch_parser_next(svn_patch_t **patch,
+                           svn_diff_patch_parser_t *parser,
+                           svn_boolean_t reverse,
+                           svn_boolean_t ignore_whitespace,
+                           apr_pool_t *result_pool,
+                           apr_pool_t *scratch_pool);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/trunk/subversion/libsvn_diff/parse-diff.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_diff/parse-diff.c?rev=1925462&r1=1925461&r2=1925462&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/trunk/subversion/libsvn_diff/parse-diff.c Thu May  8 13:51:32 
2025
@@ -1947,32 +1947,6 @@ add_property_hunk(svn_patch_t *patch, co
   return SVN_NO_ERROR;
 }
 
-struct svn_patch_file_t
-{
-  /* The APR file handle to the patch file. */
-  apr_file_t *apr_file;
-
-  /* The file offset at which the next patch is expected. */
-  apr_off_t next_patch_offset;
-};
-
-svn_error_t *
-svn_diff_open_patch_file(svn_patch_file_t **patch_file,
-                         const char *local_abspath,
-                         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->next_patch_offset = 0;
-  *patch_file = p;
-
-  return SVN_NO_ERROR;
-}
-
 /* Parse hunks from APR_FILE and store them in PATCH->HUNKS.
  * Parsing stops if no valid next hunk can be found.
  * If IGNORE_WHITESPACE is TRUE, lines without
@@ -2192,13 +2166,38 @@ static struct transition transitions[] =
   {"GIT binary patch",  state_git_mode_seen,    binary_patch_start},
 };
 
+
+/*** svn_diff_patch_parser_t implementation ***/
+
+struct svn_diff_patch_parser_t
+{
+  /* The APR file handle to the patch file. */
+  apr_file_t *apr_file;
+
+  /* The file offset at which the next patch is expected. */
+  apr_off_t next_patch_offset;
+};
+
+svn_diff_patch_parser_t *
+svn_diff_patch_parser_create(apr_file_t *patch_file,
+                             apr_pool_t *result_pool)
+{
+  svn_diff_patch_parser_t *result;
+
+  result = apr_palloc(result_pool, sizeof(*result));
+  result->apr_file = patch_file;
+  result->next_patch_offset = 0;
+
+  return result;
+}
+
 svn_error_t *
-svn_diff_parse_next_patch(svn_patch_t **patch_p,
-                          svn_patch_file_t *patch_file,
-                          svn_boolean_t reverse,
-                          svn_boolean_t ignore_whitespace,
-                          apr_pool_t *result_pool,
-                          apr_pool_t *scratch_pool)
+svn_diff_patch_parser_next(svn_patch_t **patch_p,
+                           svn_diff_patch_parser_t *patch_file,
+                           svn_boolean_t reverse,
+                           svn_boolean_t ignore_whitespace,
+                           apr_pool_t *result_pool,
+                           apr_pool_t *scratch_pool)
 {
   apr_off_t pos, last_line;
   svn_boolean_t eof;
@@ -2370,6 +2369,50 @@ svn_diff_parse_next_patch(svn_patch_t **
   return SVN_NO_ERROR;
 }
 
+
+/*** svn_patch_file_t implementation ***/
+
+struct svn_patch_file_t
+{
+  /* The APR file handle to the patch file. */
+  apr_file_t *apr_file;
+
+  /* Inner parser for svn_diff_patch_parser_next() */
+  svn_diff_patch_parser_t *parser;
+};
+
+svn_error_t *
+svn_diff_open_patch_file(svn_patch_file_t **patch_file,
+                         const char *local_abspath,
+                         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->parser = svn_diff_patch_parser_create(p->apr_file, result_pool);
+
+  *patch_file = p;
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_diff_parse_next_patch(svn_patch_t **patch_p,
+                          svn_patch_file_t *patch_file,
+                          svn_boolean_t reverse,
+                          svn_boolean_t ignore_whitespace,
+                          apr_pool_t *result_pool,
+                          apr_pool_t *scratch_pool)
+{
+  return svn_error_trace(svn_diff_patch_parser_next(patch_p, 
patch_file->parser,
+                                                    reverse, ignore_whitespace,
+                                                    result_pool, 
scratch_pool));
+}
+
 svn_error_t *
 svn_diff_close_patch_file(svn_patch_file_t *patch_file,
                           apr_pool_t *scratch_pool)


Reply via email to