[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: [PATCH] - svndumpfilter - add wildcard matchinv

From: Hyrum K. Wright <hyrum_wright_at_mail.utexas.edu>
Date: 2006-10-11 21:52:02 CEST

Andrei wrote:
> Thank you for the feedback. Here is a new version using apr_fnmatch. Based on my tests, it seems to handle escapes ('\') ok and has '[' matching on top of the previous one. I did not see a case which would require me to handle escapes aditionally from apr_fnmatch .. did you
> have any specific functionality in mind that requires this?

Ping...

Has anybody looked at this most recent version of Andrei's patch? If
nothing happens in the next few days, I'll file an issue.

Thanks,
-Hyrum

> On Mon, 2006-10-02 at 09:00 -0400, C. Michael Pilato wrote:
> > Andrei wrote:
> > > This patch adds wildcard matching to the regular "prefix" matching for
> > > svndumpfilter. It is my first patch and feedback would be appreciated.
> > >
> > > There is one place where I am unsure about: the wildcard matching uses
> > > "NXOR", so I am not sure if it was designed to only work with path
> > > prefixes (it seems to go well if I choose "*.txt" as a pattern for
> > > example).
> >
> > Andrei, thanks for the generally good patch. I have a few comments
> > which you can find inline below.
> >
> > > Index: subversion/svndumpfilter/main.c
> > > ===================================================================
> > > --- subversion/svndumpfilter/main.c (revision 21719)
> > > +++ subversion/svndumpfilter/main.c (working copy)
> > > @@ -97,7 +97,118 @@
> > > svn_stringbuf_appendbytes(*strbuf, "\n", 1);
> > > }
> > >
> > > +/* Match a string against a wildcard pattern.
> > > + * @param str - [in] the string to check
> > > + * @param pat - [in] the pattern. '*' and '?' wildcards are accepted,
> > > + * with '\\' as an escape character
> > > + * @return TRUE if pattern match is detected
> > > + */
> > > +static svn_boolean_t
> > > +wildcard_match(const char *str, const char *pat)
> > > +{
> >
> > ...
> >
> > Could not this whole function be written using apr_fnmatch(), the same
> > matching interface we use elsewhere in Subversion? You could do a
> > quicky pass to handle the backslash escape character (a UI quirk I'm not
> > totally sold on), and then hand the result off to apr_fnmatch(). Sure
> > would simplify the code, and keep this behavior consistent with that of
> > other areas of Subversion.
> >
> > > @@ -864,6 +991,23 @@
> > > baton->renumber_history = apr_hash_make(pool);
> > > baton->last_live_revision = SVN_INVALID_REVNUM;
> > >
> > > + if (opt_state->match_type == NULL) { /* just use the default */
> > > + baton->match_function = ary_prefix_match;
> > > + } else if (strcmp(opt_state->match_type, MATCH_TYPE_PREFIX) == 0) {
> > > + baton->match_function = ary_prefix_match;
> > > + } else if (strcmp(opt_state->match_type, MATCH_TYPE_WILDCARD) == 0) {
> > > + svn_error_t *pComplexityCheck;
> > > +
> > > + pComplexityCheck = check_wildcard_complexity(baton->prefixes);
> > > + if (pComplexityCheck)
> > > + return pComplexityCheck;
> >
> > We don't do camel-case. But if you use apr_fnmatch(), you needn't check
> > complexity anyway.
> >
>
>
> ------------------------------------------------------------------------
>
> Index: subversion/svndumpfilter/main.c
> ===================================================================
> --- subversion/svndumpfilter/main.c (revision 21736)
> +++ subversion/svndumpfilter/main.c (working copy)
> @@ -20,6 +20,7 @@
> #include <stdlib.h>
>
> #include <apr_file_io.h>
> +#include <apr_fnmatch.h>
>
> #include "svn_private_config.h"
> #include "svn_cmdline.h"
> @@ -97,7 +98,26 @@
> svn_stringbuf_appendbytes(*strbuf, "\n", 1);
> }
>
> +/* Wildcard matching function to compare a node-path with a
> + * specified set of wildcard patterns
> + */
> +static svn_boolean_t
> +ary_wildcard_match(apr_array_header_t *pfxlist, const char *path)
> +{
> + int i;
> + const char *pattern;
>
> + for (i = 0; i < pfxlist->nelts; i++)
> + {
> + pattern = APR_ARRAY_IDX(pfxlist, i, const char *);
> +
> + if (apr_fnmatch(pattern, path, 0) == APR_SUCCESS)
> + return TRUE;
> + }
> +
> + return FALSE;
> +}
> +
> /* Prefix matching function to compare node-path with set of prefixes. */
> static svn_boolean_t
> ary_prefix_match(apr_array_header_t *pfxlist, const char *path)
> @@ -143,6 +163,8 @@
> svn_boolean_t was_dropped; /* Was this revision dropped? */
> };
>
> +typedef svn_boolean_t (*match_function_t)(apr_array_header_t*, const char *);
> +
> struct parse_baton_t
> {
> /* Command-line options values. */
> @@ -152,6 +174,7 @@
> svn_boolean_t do_renumber_revs;
> svn_boolean_t preserve_revprops;
> apr_array_header_t *prefixes;
> + match_function_t match_function;
>
> /* Input and output streams. */
> svn_stream_t *in_stream;
> @@ -460,7 +483,7 @@
> copyfrom_path = svn_path_join("/", copyfrom_path, pool);
>
> /* Shame, shame, shame ... this is NXOR. */
> - nb->do_skip = (ary_prefix_match(pb->prefixes, node_path)
> + nb->do_skip = (pb->match_function(pb->prefixes, node_path)
> ? pb->do_exclude : (! pb->do_exclude));
>
> /* If we're skipping the node, take note of path, discarding the
> @@ -480,7 +503,7 @@
>
> /* Test if this node was copied from dropped source. */
> if (copyfrom_path &&
> - (ary_prefix_match(pb->prefixes, copyfrom_path)
> + (pb->match_function(pb->prefixes, copyfrom_path)
> ? pb->do_exclude : (! pb->do_exclude)))
> {
> /* This node was copied from dropped source.
> @@ -767,7 +790,8 @@
> svndumpfilter__renumber_revs,
> svndumpfilter__preserve_revprops,
> svndumpfilter__quiet,
> - svndumpfilter__version
> + svndumpfilter__version,
> + svndumpfilter__match_type
> };
>
> /* Option codes and descriptions.
> @@ -792,9 +816,18 @@
> N_("Renumber revisions left after filtering.") },
> {"preserve-revprops", svndumpfilter__preserve_revprops, 0,
> N_("Don't filter revision properties.") },
> + {"match-type", svndumpfilter__match_type, 1,
> + N_("Default: 'prefix'. Defines how the pattern matching is done\n"
> + " "
> + "'prefix' - match nodes with the fiven prefixes from dumpstream.\n"
> + " "
> + "'wildcard' - use '*' and '?' as wildcards (e.g. '*.pdf') .\n"
> + ) },
> {NULL}
> };
>
> +#define MATCH_TYPE_PREFIX "prefix"
> +#define MATCH_TYPE_WILDCARD "wildcard"
>
> /* Array of available subcommands.
> * The entire list must be terminated with an entry of nulls.
> @@ -802,16 +835,18 @@
> static const svn_opt_subcommand_desc_t cmd_table[] =
> {
> {"exclude", subcommand_exclude, {0},
> - N_("Filter out nodes with given prefixes from dumpstream.\n"
> - "usage: svndumpfilter exclude PATH_PREFIX...\n"),
> + N_("Filter out nodes matching a given pattern from the dumpstream.\n"
> + "usage: svndumpfilter exclude PATTERN...\n"),
> {svndumpfilter__drop_empty_revs, svndumpfilter__renumber_revs,
> - svndumpfilter__preserve_revprops, svndumpfilter__quiet} },
> + svndumpfilter__preserve_revprops, svndumpfilter__quiet,
> + svndumpfilter__match_type} },
>
> {"include", subcommand_include, {0},
> - N_("Filter out nodes without given prefixes from dumpstream.\n"
> - "usage: svndumpfilter include PATH_PREFIX...\n"),
> + N_("Filter out nodes matching a given pattern from the dumpstream.\n"
> + "usage: svndumpfilter include PATTERN...\n"),
> {svndumpfilter__drop_empty_revs, svndumpfilter__renumber_revs,
> - svndumpfilter__preserve_revprops, svndumpfilter__quiet} },
> + svndumpfilter__preserve_revprops, svndumpfilter__quiet,
> + svndumpfilter__match_type} },
>
> {"help", subcommand_help, {"?", "h"},
> N_("Describe the usage of this program or its subcommands.\n"
> @@ -833,6 +868,7 @@
> svn_boolean_t help; /* --help or -? */
> svn_boolean_t renumber_revs; /* --renumber-revs */
> svn_boolean_t preserve_revprops; /* --preserve-revprops */
> + const char *match_type; /* --match-type */
> apr_array_header_t *prefixes; /* mainargs. */
> };
>
> @@ -864,6 +900,17 @@
> baton->renumber_history = apr_hash_make(pool);
> baton->last_live_revision = SVN_INVALID_REVNUM;
>
> + if (opt_state->match_type == NULL) { /* just use the default */
> + baton->match_function = ary_prefix_match;
> + } else if (strcmp(opt_state->match_type, MATCH_TYPE_PREFIX) == 0) {
> + baton->match_function = ary_prefix_match;
> + } else if (strcmp(opt_state->match_type, MATCH_TYPE_WILDCARD) == 0) {
> + baton->match_function = ary_wildcard_match;
> + } else {
> + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
> + _("Invalid pattern matching type selected"));
> + }
> +
> /* This is non-ideal: We should pass through the version of the
> * input dumpstream. However, our API currently doesn't allow that.
> * Hardcoding version 2 is acceptable because:
> @@ -1084,7 +1131,6 @@
> apr_array_header_t *received_opts;
> int i;
>
> -
> /* Initialize the app. */
> if (svn_cmdline_init("svndumpfilter", stderr) != EXIT_SUCCESS)
> return EXIT_FAILURE;
> @@ -1168,6 +1214,9 @@
> case svndumpfilter__preserve_revprops:
> opt_state.preserve_revprops = TRUE;
> break;
> + case svndumpfilter__match_type:
> + opt_state.match_type = apr_pstrdup(pool, opt_arg);
> + break;
> default:
> {
> subcommand_help(NULL, NULL, pool);

Received on Wed Oct 11 21:52:19 2006

This is an archived mail posted to the Subversion Dev mailing list.