You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2016/10/30 21:42:02 UTC
svn commit: r1767186 - in /subversion/trunk/subversion: include/svn_client.h
libsvn_client/deprecated.c libsvn_client/list.c svn/list-cmd.c svn/svn.c
tests/cmdline/list_tests.py
Author: stefan2
Date: Sun Oct 30 21:42:01 2016
New Revision: 1767186
URL: http://svn.apache.org/viewvc?rev=1767186&view=rev
Log:
Add support for the "--search" option to the 'list' command down to the
svn_client level. Provide a simple test for it.
* subversion/include/svn_client.h
(svn_client_list4): Rev API, adding the PATTERNS parameter.
(svn_client_list3): Deprecate.
* subversion/libsvn_client/deprecated.c
(svn_client_list3): Implement the deprecated API in terms of the new one.
* subversion/libsvn_client/list.c
(match_patterns): New utility function handling the pattern matching.
(get_dir_contents,
list_internal): Add PATTERNS parameter and filter outout accordingly.
(list_external_items,
list_externals): Add PATTERNS parameter and pass it along.
(svn_client_list4): Bump signature and pass parameters on.
* subversion/svn/list-cmd.c
(svn_cl__list): Gather the --search patterns and pass them to the rev'ed
client API.
* subversion/svn/svn.c
(svn_cl__cmd_table): Enabled the '--search' option for 'list'.
* subversion/tests/cmdline/list_tests.py
(list_filtered): New test.
(test_list): Register the new test.
Modified:
subversion/trunk/subversion/include/svn_client.h
subversion/trunk/subversion/libsvn_client/deprecated.c
subversion/trunk/subversion/libsvn_client/list.c
subversion/trunk/subversion/svn/list-cmd.c
subversion/trunk/subversion/svn/svn.c
subversion/trunk/subversion/tests/cmdline/list_tests.py
Modified: subversion/trunk/subversion/include/svn_client.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_client.h?rev=1767186&r1=1767185&r2=1767186&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_client.h (original)
+++ subversion/trunk/subversion/include/svn_client.h Sun Oct 30 21:42:01 2016
@@ -6402,13 +6402,18 @@ typedef svn_error_t *(*svn_client_list_f
* its children. If @a path_or_url is non-existent, return
* #SVN_ERR_FS_NOT_FOUND.
*
+ * If the @a pattern array of <tt>const char *</tt> is not empty, only
+ * report paths whose last segment matches one of the specified glob
+ * patterns. This does not affect the size of the tree nor the number of
+ * externals being covered.
+ *
* If @a fetch_locks is TRUE, include locks when reporting directory entries.
*
* If @a include_externals is TRUE, also list all external items
* reached by recursion. @a depth value passed to the original list target
* applies for the externals also.
*
- * Use @a pool for temporary allocations.
+ * Use @a scratch_pool for temporary allocations.
*
* Use authentication baton cached in @a ctx to authenticate against the
* repository.
@@ -6424,8 +6429,29 @@ typedef svn_error_t *(*svn_client_list_f
* otherwise simply bitwise OR together the combination of @c SVN_DIRENT_
* fields you care about.
*
+ * @since New in 1.10.
+ */
+svn_error_t *
+svn_client_list4(const char *path_or_url,
+ const svn_opt_revision_t *peg_revision,
+ const svn_opt_revision_t *revision,
+ apr_array_header_t *patterns,
+ svn_depth_t depth,
+ apr_uint32_t dirent_fields,
+ svn_boolean_t fetch_locks,
+ svn_boolean_t include_externals,
+ svn_client_list_func2_t list_func,
+ void *baton,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *scratch_pool);
+
+/** Similar to svn_client_list4(), but with @a patterm left empty.
+ *
* @since New in 1.8.
+ *
+ * @deprecated Provided for backwards compatibility with the 1.9 API.
*/
+SVN_DEPRECATED
svn_error_t *
svn_client_list3(const char *path_or_url,
const svn_opt_revision_t *peg_revision,
Modified: subversion/trunk/subversion/libsvn_client/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/deprecated.c?rev=1767186&r1=1767185&r2=1767186&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/deprecated.c (original)
+++ subversion/trunk/subversion/libsvn_client/deprecated.c Sun Oct 30 21:42:01 2016
@@ -1330,6 +1330,27 @@ svn_client_export(svn_revnum_t *result_r
/*** From list.c ***/
+svn_error_t *
+svn_client_list3(const char *path_or_url,
+ const svn_opt_revision_t *peg_revision,
+ const svn_opt_revision_t *revision,
+ svn_depth_t depth,
+ apr_uint32_t dirent_fields,
+ svn_boolean_t fetch_locks,
+ svn_boolean_t include_externals,
+ svn_client_list_func2_t list_func,
+ void *baton,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
+{
+ apr_array_header_t *patterns = apr_array_make(pool, 0, sizeof(const char *));
+ return svn_error_trace(svn_client_list4(path_or_url, peg_revision,
+ revision, patterns, depth,
+ dirent_fields, fetch_locks,
+ include_externals,
+ list_func, baton, ctx, pool));
+}
+
/* Baton for use with wrap_list_func */
struct list_func_wrapper_baton {
void *list_func1_baton;
Modified: subversion/trunk/subversion/libsvn_client/list.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/list.c?rev=1767186&r1=1767185&r2=1767186&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/list.c (original)
+++ subversion/trunk/subversion/libsvn_client/list.c Sun Oct 30 21:42:01 2016
@@ -21,6 +21,8 @@
* ====================================================================
*/
+#include <apr_fnmatch.h>
+
#include "svn_client.h"
#include "svn_dirent_uri.h"
#include "svn_hash.h"
@@ -41,6 +43,7 @@
/* Prototypes for referencing before declaration */
static svn_error_t *
list_externals(apr_hash_t *externals,
+ apr_array_header_t *patterns,
svn_depth_t depth,
apr_uint32_t dirent_fields,
svn_boolean_t fetch_locks,
@@ -53,6 +56,7 @@ static svn_error_t *
list_internal(const char *path_or_url,
const svn_opt_revision_t *peg_revision,
const svn_opt_revision_t *revision,
+ apr_array_header_t *patterns,
svn_depth_t depth,
apr_uint32_t dirent_fields,
svn_boolean_t fetch_locks,
@@ -64,6 +68,25 @@ list_internal(const char *path_or_url,
svn_client_ctx_t *ctx,
apr_pool_t *pool);
+/* Return TRUE if S matches any of the const char * in PATTERNS.
+ * Note that any S will match if PATTERNS is empty. */
+static svn_boolean_t
+match_patterns(const char *s,
+ apr_array_header_t *patterns)
+{
+ int i;
+ if (patterns->nelts == 0)
+ return TRUE;
+
+ for (i = 0; i < patterns->nelts; ++i)
+ {
+ const char *pattern = APR_ARRAY_IDX(patterns, i, const char *);
+ if (apr_fnmatch(pattern, s, APR_FNM_PERIOD) == APR_SUCCESS)
+ return TRUE;
+ }
+
+ return FALSE;
+}
/* Get the directory entries of DIR at REV (relative to the root of
RA_SESSION), getting at least the fields specified by DIRENT_FIELDS.
@@ -75,6 +98,10 @@ list_internal(const char *path_or_url,
if svn_depth_infinity, invoke it on file and directory entries and
recurse into the directory entries with the same depth.
+ If PATTERNS is not empty, the last path segments must match at least
+ one of const char * patterns in it or the respective dirent will not
+ be reported.
+
LOCKS, if non-NULL, is a hash mapping const char * paths to svn_lock_t
objects and FS_PATH is the absolute filesystem path of the RA session.
Use SCRATCH_POOL for temporary allocations.
@@ -94,6 +121,7 @@ get_dir_contents(apr_uint32_t dirent_fie
svn_ra_session_t *ra_session,
apr_hash_t *locks,
const char *fs_path,
+ apr_array_header_t *patterns,
svn_depth_t depth,
svn_client_ctx_t *ctx,
apr_hash_t *externals,
@@ -175,14 +203,15 @@ get_dir_contents(apr_uint32_t dirent_fie
if (the_ent->kind == svn_node_file
|| depth == svn_depth_immediates
|| depth == svn_depth_infinity)
- SVN_ERR(list_func(baton, path, the_ent, lock, fs_path,
- external_parent_url, external_target, iterpool));
+ if (match_patterns(item->key, patterns))
+ SVN_ERR(list_func(baton, path, the_ent, lock, fs_path,
+ external_parent_url, external_target, iterpool));
/* If externals is non-NULL, populate the externals hash table
recursively for all directory entries. */
if (depth == svn_depth_infinity && the_ent->kind == svn_node_dir)
- SVN_ERR(get_dir_contents(dirent_fields, path, rev,
- ra_session, locks, fs_path, depth, ctx,
+ SVN_ERR(get_dir_contents(dirent_fields, path, rev, ra_session,
+ locks, fs_path, patterns, depth, ctx,
externals, external_parent_url,
external_target, list_func, baton,
result_pool, iterpool));
@@ -204,6 +233,10 @@ get_dir_contents(apr_uint32_t dirent_fie
subdirectories (at svn_depth_empty). Else if DEPTH is
svn_depth_empty, just list PATH_OR_URL with none of its entries.
+ If PATTERNS is not empty, the last path segments must match at least
+ one of const char * patterns in it or the respective dirent will not
+ be reported.
+
DIRENT_FIELDS controls which fields in the svn_dirent_t's are
filled in. To have them totally filled in use SVN_DIRENT_ALL,
otherwise simply bitwise OR together the combination of SVN_DIRENT_*
@@ -230,6 +263,7 @@ static svn_error_t *
list_internal(const char *path_or_url,
const svn_opt_revision_t *peg_revision,
const svn_opt_revision_t *revision,
+ apr_array_header_t *patterns,
svn_depth_t depth,
apr_uint32_t dirent_fields,
svn_boolean_t fetch_locks,
@@ -291,17 +325,18 @@ list_internal(const char *path_or_url,
locks = NULL;
/* Report the dirent for the target. */
- SVN_ERR(list_func(baton, "", dirent, locks
- ? (svn_hash_gets(locks, fs_path))
- : NULL, fs_path, external_parent_url,
- external_target, pool));
+ if (match_patterns(svn_dirent_dirname(fs_path, pool), patterns))
+ SVN_ERR(list_func(baton, "", dirent, locks
+ ? (svn_hash_gets(locks, fs_path))
+ : NULL, fs_path, external_parent_url,
+ external_target, pool));
if (dirent->kind == svn_node_dir
&& (depth == svn_depth_files
|| depth == svn_depth_immediates
|| depth == svn_depth_infinity))
SVN_ERR(get_dir_contents(dirent_fields, "", loc->rev, ra_session, locks,
- fs_path, depth, ctx, externals,
+ fs_path, patterns, depth, ctx, externals,
external_parent_url, external_target, list_func,
baton, pool, pool));
@@ -312,7 +347,7 @@ list_internal(const char *path_or_url,
{
/* The 'externals' hash populated by get_dir_contents() is processed
here. */
- SVN_ERR(list_externals(externals, depth, dirent_fields,
+ SVN_ERR(list_externals(externals, patterns, depth, dirent_fields,
fetch_locks, list_func, baton,
ctx, pool));
}
@@ -349,6 +384,7 @@ wrap_list_error(const svn_client_ctx_t *
static svn_error_t *
list_external_items(apr_array_header_t *external_items,
const char *externals_parent_url,
+ apr_array_header_t *patterns,
svn_depth_t depth,
apr_uint32_t dirent_fields,
svn_boolean_t fetch_locks,
@@ -389,6 +425,7 @@ list_external_items(apr_array_header_t *
list_internal(resolved_url,
&item->peg_revision,
&item->revision,
+ patterns,
depth, dirent_fields,
fetch_locks,
TRUE,
@@ -411,6 +448,7 @@ list_external_items(apr_array_header_t *
passed to svn_client_list(). */
static svn_error_t *
list_externals(apr_hash_t *externals,
+ apr_array_header_t *patterns,
svn_depth_t depth,
apr_uint32_t dirent_fields,
svn_boolean_t fetch_locks,
@@ -440,9 +478,10 @@ list_externals(apr_hash_t *externals,
if (! external_items->nelts)
continue;
- SVN_ERR(list_external_items(external_items, externals_parent_url, depth,
- dirent_fields, fetch_locks, list_func,
- baton, ctx, iterpool));
+ SVN_ERR(list_external_items(external_items, externals_parent_url,
+ patterns, depth, dirent_fields,
+ fetch_locks, list_func, baton, ctx,
+ iterpool));
}
svn_pool_destroy(iterpool);
@@ -452,9 +491,10 @@ list_externals(apr_hash_t *externals,
svn_error_t *
-svn_client_list3(const char *path_or_url,
+svn_client_list4(const char *path_or_url,
const svn_opt_revision_t *peg_revision,
const svn_opt_revision_t *revision,
+ apr_array_header_t *patterns,
svn_depth_t depth,
apr_uint32_t dirent_fields,
svn_boolean_t fetch_locks,
@@ -462,14 +502,14 @@ svn_client_list3(const char *path_or_url
svn_client_list_func2_t list_func,
void *baton,
svn_client_ctx_t *ctx,
- apr_pool_t *pool)
+ apr_pool_t *scratch_pool)
{
return svn_error_trace(list_internal(path_or_url, peg_revision,
- revision,
+ revision, patterns,
depth, dirent_fields,
fetch_locks,
include_externals,
NULL, NULL, list_func,
- baton, ctx, pool));
+ baton, ctx, scratch_pool));
}
Modified: subversion/trunk/subversion/svn/list-cmd.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/list-cmd.c?rev=1767186&r1=1767185&r2=1767186&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/list-cmd.c (original)
+++ subversion/trunk/subversion/svn/list-cmd.c Sun Oct 30 21:42:01 2016
@@ -351,6 +351,8 @@ svn_cl__list(apr_getopt_t *os,
const char *target = APR_ARRAY_IDX(targets, i, const char *);
const char *truepath;
svn_opt_revision_t peg_revision;
+ apr_array_header_t *patterns;
+ int k;
/* Initialize the following variables for
every list target. */
@@ -360,6 +362,7 @@ svn_cl__list(apr_getopt_t *os,
svn_pool_clear(subpool);
+ patterns = apr_array_make(subpool, 4, sizeof(const char *));
SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));
/* Get peg revisions. */
@@ -375,8 +378,24 @@ svn_cl__list(apr_getopt_t *os,
SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout));
}
- err = svn_client_list3(truepath, &peg_revision,
- &(opt_state->start_revision),
+ if (opt_state->search_patterns)
+ for (k = 0; k < opt_state->search_patterns->nelts; ++k)
+ {
+ apr_array_header_t *pattern_group
+ = APR_ARRAY_IDX(opt_state->search_patterns, k,
+ apr_array_header_t *);
+
+ /* Should never fail but ... */
+ if (pattern_group->nelts != 1)
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("'search-and' option is not supported"));
+
+ APR_ARRAY_PUSH(patterns, const char *)
+ = APR_ARRAY_IDX(pattern_group, 0, const char *);
+ }
+
+ err = svn_client_list4(truepath, &peg_revision,
+ &(opt_state->start_revision), patterns,
opt_state->depth,
dirent_fields,
(opt_state->xml || opt_state->verbose),
Modified: subversion/trunk/subversion/svn/svn.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/svn.c?rev=1767186&r1=1767185&r2=1767186&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/svn.c (original)
+++ subversion/trunk/subversion/svn/svn.c Sun Oct 30 21:42:01 2016
@@ -798,7 +798,7 @@ const svn_opt_subcommand_desc2_t svn_cl_
" Size (in bytes)\n"
" Date and time of the last commit\n"),
{'r', 'v', 'R', opt_depth, opt_incremental, opt_xml,
- opt_include_externals}, },
+ opt_include_externals, opt_search}, },
{ "lock", svn_cl__lock, {0}, N_
("Lock working copy paths or URLs in the repository, so that\n"
Modified: subversion/trunk/subversion/tests/cmdline/list_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/list_tests.py?rev=1767186&r1=1767185&r2=1767186&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/list_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/list_tests.py Sun Oct 30 21:42:01 2016
@@ -94,6 +94,20 @@ def list_verbose(sbox):
expected, [], 'list', path, '--depth=infinity', "-v")
+def list_filtered(sbox):
+ "filtered list"
+
+ sbox.build(read_only=True)
+ path = sbox.repo_url + "/A/D"
+
+ # check plain info
+ expected = [ "H/omega\n",
+ "gamma\n" ]
+
+ exit_code, output, error = svntest.actions.run_and_verify_svn(
+ None, [], 'list', path, '--depth=infinity', '--search=*a')
+
+
########################################################################
# Run the tests
@@ -101,6 +115,7 @@ def list_verbose(sbox):
test_list = [ None,
list_plain,
list_verbose,
+ list_filtered,
]
if __name__ == '__main__':