Skip to content

Commit ed30630

Browse files
committed
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() git-svn-id: https://svn.apache.org/repos/asf/subversion/trunk@1925462 13f79535-47bb-0310-9956-ffa450edef68
1 parent 54e2d89 commit ed30630

2 files changed

Lines changed: 114 additions & 32 deletions

File tree

subversion/include/svn_diff.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1370,6 +1370,45 @@ svn_error_t *
13701370
svn_diff_close_patch_file(svn_patch_file_t *patch_file,
13711371
apr_pool_t *scratch_pool);
13721372

1373+
/**
1374+
* Patch file parser.
1375+
*
1376+
* @since New in 1.15
1377+
*/
1378+
typedef struct svn_diff_patch_parser_t svn_diff_patch_parser_t;
1379+
1380+
/**
1381+
* Initialises an instance of @a svn_diff_patch_parser_t from @a patch_file,
1382+
* which may be used in order to parse patch files through svn_diff_parser*
1383+
* routines.
1384+
*
1385+
* @since New in 1.15
1386+
*/
1387+
svn_diff_patch_parser_t *
1388+
svn_diff_patch_parser_create(apr_file_t *patch_file,
1389+
apr_pool_t *result_pool);
1390+
1391+
/**
1392+
* Parses the next @a *patch from @a parser.
1393+
* If no patch can be found, set @a *patch to NULL.
1394+
* If @a reverse is TRUE, invert the patch while parsing it.
1395+
* If @a ignore_whitespace is TRUE, allow patches with no leading
1396+
* whitespace to be parsed.
1397+
* Allocate results in @a result_pool.
1398+
* Use @a scratch_pool for all other allocations.
1399+
*
1400+
* @since New in 1.15.
1401+
* @note Similar to @c svn_diff_parse_next_patch(), but utilizing the parser
1402+
* as its source.
1403+
*/
1404+
svn_error_t *
1405+
svn_diff_patch_parser_next(svn_patch_t **patch,
1406+
svn_diff_patch_parser_t *parser,
1407+
svn_boolean_t reverse,
1408+
svn_boolean_t ignore_whitespace,
1409+
apr_pool_t *result_pool,
1410+
apr_pool_t *scratch_pool);
1411+
13731412
#ifdef __cplusplus
13741413
}
13751414
#endif /* __cplusplus */

subversion/libsvn_diff/parse-diff.c

Lines changed: 75 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1947,32 +1947,6 @@ add_property_hunk(svn_patch_t *patch, const char *prop_name,
19471947
return SVN_NO_ERROR;
19481948
}
19491949

1950-
struct svn_patch_file_t
1951-
{
1952-
/* The APR file handle to the patch file. */
1953-
apr_file_t *apr_file;
1954-
1955-
/* The file offset at which the next patch is expected. */
1956-
apr_off_t next_patch_offset;
1957-
};
1958-
1959-
svn_error_t *
1960-
svn_diff_open_patch_file(svn_patch_file_t **patch_file,
1961-
const char *local_abspath,
1962-
apr_pool_t *result_pool)
1963-
{
1964-
svn_patch_file_t *p;
1965-
1966-
p = apr_palloc(result_pool, sizeof(*p));
1967-
SVN_ERR(svn_io_file_open(&p->apr_file, local_abspath,
1968-
APR_READ | APR_BUFFERED, APR_OS_DEFAULT,
1969-
result_pool));
1970-
p->next_patch_offset = 0;
1971-
*patch_file = p;
1972-
1973-
return SVN_NO_ERROR;
1974-
}
1975-
19761950
/* Parse hunks from APR_FILE and store them in PATCH->HUNKS.
19771951
* Parsing stops if no valid next hunk can be found.
19781952
* If IGNORE_WHITESPACE is TRUE, lines without
@@ -2192,13 +2166,38 @@ static struct transition transitions[] =
21922166
{"GIT binary patch", state_git_mode_seen, binary_patch_start},
21932167
};
21942168

2169+
2170+
/*** svn_diff_patch_parser_t implementation ***/
2171+
2172+
struct svn_diff_patch_parser_t
2173+
{
2174+
/* The APR file handle to the patch file. */
2175+
apr_file_t *apr_file;
2176+
2177+
/* The file offset at which the next patch is expected. */
2178+
apr_off_t next_patch_offset;
2179+
};
2180+
2181+
svn_diff_patch_parser_t *
2182+
svn_diff_patch_parser_create(apr_file_t *patch_file,
2183+
apr_pool_t *result_pool)
2184+
{
2185+
svn_diff_patch_parser_t *result;
2186+
2187+
result = apr_palloc(result_pool, sizeof(*result));
2188+
result->apr_file = patch_file;
2189+
result->next_patch_offset = 0;
2190+
2191+
return result;
2192+
}
2193+
21952194
svn_error_t *
2196-
svn_diff_parse_next_patch(svn_patch_t **patch_p,
2197-
svn_patch_file_t *patch_file,
2198-
svn_boolean_t reverse,
2199-
svn_boolean_t ignore_whitespace,
2200-
apr_pool_t *result_pool,
2201-
apr_pool_t *scratch_pool)
2195+
svn_diff_patch_parser_next(svn_patch_t **patch_p,
2196+
svn_diff_patch_parser_t *patch_file,
2197+
svn_boolean_t reverse,
2198+
svn_boolean_t ignore_whitespace,
2199+
apr_pool_t *result_pool,
2200+
apr_pool_t *scratch_pool)
22022201
{
22032202
apr_off_t pos, last_line;
22042203
svn_boolean_t eof;
@@ -2370,6 +2369,50 @@ svn_diff_parse_next_patch(svn_patch_t **patch_p,
23702369
return SVN_NO_ERROR;
23712370
}
23722371

2372+
2373+
/*** svn_patch_file_t implementation ***/
2374+
2375+
struct svn_patch_file_t
2376+
{
2377+
/* The APR file handle to the patch file. */
2378+
apr_file_t *apr_file;
2379+
2380+
/* Inner parser for svn_diff_patch_parser_next() */
2381+
svn_diff_patch_parser_t *parser;
2382+
};
2383+
2384+
svn_error_t *
2385+
svn_diff_open_patch_file(svn_patch_file_t **patch_file,
2386+
const char *local_abspath,
2387+
apr_pool_t *result_pool)
2388+
{
2389+
svn_patch_file_t *p;
2390+
2391+
p = apr_palloc(result_pool, sizeof(*p));
2392+
SVN_ERR(svn_io_file_open(&p->apr_file, local_abspath,
2393+
APR_READ | APR_BUFFERED, APR_OS_DEFAULT,
2394+
result_pool));
2395+
2396+
p->parser = svn_diff_patch_parser_create(p->apr_file, result_pool);
2397+
2398+
*patch_file = p;
2399+
2400+
return SVN_NO_ERROR;
2401+
}
2402+
2403+
svn_error_t *
2404+
svn_diff_parse_next_patch(svn_patch_t **patch_p,
2405+
svn_patch_file_t *patch_file,
2406+
svn_boolean_t reverse,
2407+
svn_boolean_t ignore_whitespace,
2408+
apr_pool_t *result_pool,
2409+
apr_pool_t *scratch_pool)
2410+
{
2411+
return svn_error_trace(svn_diff_patch_parser_next(patch_p, patch_file->parser,
2412+
reverse, ignore_whitespace,
2413+
result_pool, scratch_pool));
2414+
}
2415+
23732416
svn_error_t *
23742417
svn_diff_close_patch_file(svn_patch_file_t *patch_file,
23752418
apr_pool_t *scratch_pool)

0 commit comments

Comments
 (0)