Author: stsp
Date: Wed Jun 27 18:53:25 2012
New Revision: 1354666
URL: http://svn.apache.org/viewvc?rev=1354666&view=rev
Log:
Add support for 'svn log --search', which can be used to restrict log output
to entries where the author, log message, or list of changed paths matches
a search pattern. The new --search option works in plain and XML output modes.
Currently, apr_fnmatch() is used for pattern matching, which supports glob
wildcards only. It would be nice to provide full regex support but I'm not
quite sure whether we can use apr_strmatch() without breaking compatibility
with older APR-util versions. So stick with glob patterns for now. Maybe
we can add full regex support later.
(Note: committing from slow laptop on train -- sorry if this breaks any tests)
* subversion/svn/cl.h
(svn_cl__opt_state_t): Add search_pattern.
* subversion/svn/log-cmd.c
(): Include apr_fnmatch.h.
(log_receiver_baton): Add search_pattern.
(match_search_pattern): New helper function that matches elements of a
log entry to a search pattern.
(log_entry_receiver, log_entry_receiver_xml): If a search pattern is provided
only show log entries which match the pattern.
(svn_cl__log): Pass search_pattern from opt_state to the log baton.
* subversion/svn/main.c
(svn_cl__longopt_t): Add opt_search.
(svn_cl__options): Add --search option.
(svn_cl__cmd_table): Add --search option to the log subcommand and extend the
corresponding help text.
(main): Handle --search option.
* subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout: Adjust
for changed output of 'svn help log'.
* subversion/tests/cmdline/log_tests.py
(log_search, test_list): New test for log --search.
Modified:
subversion/trunk/subversion/svn/cl.h
subversion/trunk/subversion/svn/log-cmd.c
subversion/trunk/subversion/svn/main.c
subversion/trunk/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout
subversion/trunk/subversion/tests/cmdline/log_tests.py
Modified: subversion/trunk/subversion/svn/cl.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/cl.h?rev=1354666&r1=1354665&r2=1354666&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/cl.h (original)
+++ subversion/trunk/subversion/svn/cl.h Wed Jun 27 18:53:25 2012
@@ -237,6 +237,7 @@ typedef struct svn_cl__opt_state_t
svn_boolean_t show_diff; /* produce diff output (maps to --diff) */
svn_boolean_t allow_mixed_rev; /* Allow operation on mixed-revision WC */
svn_boolean_t include_externals; /* Recurses (in)to file & dir externals */
+ const char *search_pattern; /* pattern argument for --search */
} svn_cl__opt_state_t;
Modified: subversion/trunk/subversion/svn/log-cmd.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/log-cmd.c?rev=1354666&r1=1354665&r2=1354666&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/log-cmd.c (original)
+++ subversion/trunk/subversion/svn/log-cmd.c Wed Jun 27 18:53:25 2012
@@ -24,6 +24,7 @@
#define APR_WANT_STRFUNC
#define APR_WANT_STDIO
#include <apr_want.h>
+#include <apr_fnmatch.h>
#include "svn_client.h"
#include "svn_compat.h"
@@ -70,6 +71,10 @@ struct log_receiver_baton
/* Stack which keeps track of merge revision nesting, using svn_revnum_t's */
apr_array_header_t *merge_stack;
+ /* Log message search pattern. Log entries will only be shown if the author,
+ * the log message, or a changed path matches this pattern. */
+ const char *search_pattern;
+
/* Pool for persistent allocations. */
apr_pool_t *pool;
};
@@ -141,6 +146,47 @@ display_diff(const svn_log_entry_t *log_
}
+/* Return TRUE if SEARCH_PATTERN matches the AUTHOR, LOG_MESSAGE, or a path
+ * in the set of keys of the CHANGED_PATHS hash. Else, return FALSE.
+ * LOG_MESSAGE and CHANGED_PATHS are allowed to be NULL. */
+static svn_boolean_t
+match_search_pattern(const char *search_pattern,
+ const char *author,
+ const char *log_message,
+ apr_hash_t *changed_paths,
+ apr_pool_t *pool)
+{
+ /* Match any substring containing the pattern, like UNIX 'grep' does. */
+ const char *pattern = apr_psprintf(pool, "*%s*", search_pattern);
+
+ /* Does the author match the search pattern? */
+ if (apr_fnmatch(pattern, author, 0) == APR_SUCCESS)
+ return TRUE;
+
+ /* Does the log message the search pattern? */
+ if (log_message && apr_fnmatch(pattern, log_message, 0) == APR_SUCCESS)
+ return TRUE;
+
+ if (changed_paths)
+ {
+ apr_hash_index_t *hi;
+
+ /* Does a changed path match the search pattern? */
+ for (hi = apr_hash_first(pool, changed_paths);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ const char *path = svn__apr_hash_index_key(hi);
+
+ if (apr_fnmatch(search_pattern, path, 0) == APR_SUCCESS)
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
/* Implement `svn_log_entry_receiver_t', printing the logs in
* a human-readable and machine-parseable format.
*
@@ -257,6 +303,13 @@ log_entry_receiver(void *baton,
if (! lb->omit_log_message && message == NULL)
message = "";
+ if (lb->search_pattern)
+ {
+ if (! match_search_pattern(lb->search_pattern, author, message,
+ log_entry->changed_paths2, pool))
+ return SVN_NO_ERROR;
+ }
+
SVN_ERR(svn_cmdline_printf(pool,
SEP_STRING "r%ld | %s | %s",
log_entry->revision, author, date));
@@ -418,13 +471,6 @@ log_entry_receiver_xml(void *baton,
svn_compat_log_revprops_out(&author, &date, &message, log_entry->revprops);
- if (author)
- author = svn_xml_fuzzy_escape(author, pool);
- if (date)
- date = svn_xml_fuzzy_escape(date, pool);
- if (message)
- message = svn_xml_fuzzy_escape(message, pool);
-
if (log_entry->revision == 0 && message == NULL)
return SVN_NO_ERROR;
@@ -437,6 +483,21 @@ log_entry_receiver_xml(void *baton,
return SVN_NO_ERROR;
}
+ if (lb->search_pattern)
+ {
+ /* Match search pattern before XML-escaping. */
+ if (! match_search_pattern(lb->search_pattern, author, message,
+ log_entry->changed_paths2, pool))
+ return SVN_NO_ERROR;
+ }
+
+ if (author)
+ author = svn_xml_fuzzy_escape(author, pool);
+ if (date)
+ date = svn_xml_fuzzy_escape(date, pool);
+ if (message)
+ message = svn_xml_fuzzy_escape(message, pool);
+
revstr = apr_psprintf(pool, "%ld", log_entry->revision);
/* <logentry revision="xxx"> */
svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "logentry",
@@ -654,6 +715,7 @@ svn_cl__log(apr_getopt_t *os,
: opt_state->depth;
lb.diff_extensions = opt_state->extensions;
lb.merge_stack = apr_array_make(pool, 0, sizeof(svn_revnum_t));
+ lb.search_pattern = opt_state->search_pattern;
lb.pool = pool;
if (opt_state->xml)
Modified: subversion/trunk/subversion/svn/main.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/main.c?rev=1354666&r1=1354665&r2=1354666&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/main.c (original)
+++ subversion/trunk/subversion/svn/main.c Wed Jun 27 18:53:25 2012
@@ -130,6 +130,7 @@ typedef enum svn_cl__longopt_t {
opt_allow_mixed_revisions,
opt_include_externals,
opt_symmetric,
+ opt_search,
} svn_cl__longopt_t;
@@ -375,6 +376,8 @@ const apr_getopt_option_t svn_cl__option
"fixed revision. (See the svn:externals property)")},
{"symmetric", opt_symmetric, 0,
N_("Symmetric merge")},
+ {"search", opt_search, 1,
+ N_("use ARG as search pattern (glob syntax)")},
/* Long-opt Aliases
*
@@ -678,7 +681,17 @@ const svn_opt_subcommand_desc2_t svn_cl_
"\n"
" The --depth option is only valid in combination with the --diff
option\n"
" and limits the scope of the displayed diff to the specified depth.\n"
-
+ "\n"
+ " If the --search option is used, log messages are displayed only if
the\n"
+ " provided search pattern matches the author, log message text, or, if\n"
+ " the --verbose option is also provided, a changed path.\n"
+ " The search pattern may include glob syntax wildcards:\n"
+ " ? matches any single character\n"
+ " * matches a sequence of arbitrary characters\n"
+ " [...] matches any of the characters listed inside the brackets\n"
+ " If --limit is used in combination with --search, --limit restricts
the\n"
+ " number of log messages searched, rather than restricting the output\n"
+ " to a particular number of matching log messages.\n"
"\n"
" Examples:\n"
"\n"
@@ -707,7 +720,7 @@ const svn_opt_subcommand_desc2_t svn_cl_
" svn log --stop-on-copy --limit 1 -r0:HEAD ^/branches/foo\n"),
{'r', 'q', 'v', 'g', 'c', opt_targets, opt_stop_on_copy, opt_incremental,
opt_xml, 'l', opt_with_all_revprops, opt_with_no_revprops,
opt_with_revprop,
- opt_depth, opt_diff, opt_diff_cmd, opt_internal_diff, 'x'},
+ opt_depth, opt_diff, opt_diff_cmd, opt_internal_diff, 'x', opt_search},
{{opt_with_revprop, N_("retrieve revision property ARG")},
{'c', N_("the change made in revision ARG")}} },
@@ -2153,6 +2166,8 @@ main(int argc, const char *argv[])
case opt_properties_only:
opt_state.diff.properties_only = TRUE;
break;
+ case opt_search:
+ opt_state.search_pattern = opt_arg;
default:
/* Hmmm. Perhaps this would be a good place to squirrel away
opts that commands like svn diff might need. Hmmm indeed. */
Modified:
subversion/trunk/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout?rev=1354666&r1=1354665&r2=1354666&view=diff
==============================================================================
---
subversion/trunk/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout
(original)
+++
subversion/trunk/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout
Wed Jun 27 18:53:25 2012
@@ -30,6 +30,17 @@ usage: 1. log [PATH][@REV]
The --depth option is only valid in combination with the --diff option
and limits the scope of the displayed diff to the specified depth.
+ If the --search option is used, log messages are displayed only if the
+ provided search pattern matches the author, log message text, or, if
+ the --verbose option is also provided, a changed path.
+ The search pattern may include glob syntax wildcards:
+ ? matches any single character
+ * matches a sequence of arbitrary characters
+ [...] matches any of the characters listed inside the brackets
+ If --limit is used in combination with --search, --limit restricts the
+ number of log messages searched, rather than restricting the output
+ to a particular number of matching log messages.
+
Examples:
Show the latest 5 log messages for the current working copy
@@ -99,6 +110,7 @@ Valid options:
Ignore changes in EOL style.
-p (--show-c-function):
Show C function name in diff output.
+ --search ARG : use ARG as search pattern (glob syntax)
Global options:
--username ARG : specify a username ARG
Modified: subversion/trunk/subversion/tests/cmdline/log_tests.py
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/log_tests.py?rev=1354666&r1=1354665&r2=1354666&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/log_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/log_tests.py Wed Jun 27 18:53:25
2012
@@ -2280,6 +2280,22 @@ def log_diff_moved(sbox):
compare_diff_output(r2diff, log_chain[1]['diff_lines'])
compare_diff_output(r1diff, log_chain[2]['diff_lines'])
+
+#----------------------------------------------------------------------
+def log_search(sbox):
+ "'svn log --search'"
+
+ guarantee_repos_and_wc(sbox)
+
+ os.chdir(sbox.wc_dir)
+
+ exit_code, output, err = svntest.actions.run_and_verify_svn(
+ None, None, [], 'log', '--search',
+ 'for revision [367]')
+
+ log_chain = parse_log_output(output)
+ check_log_chain(log_chain, [7, 6, 3])
+
########################################################################
# Run the tests
@@ -2323,6 +2339,7 @@ test_list = [ None,
log_diff,
log_xml_old,
log_diff_moved,
+ log_search,
]
if __name__ == '__main__':