OK, so it took me a long time to get back to this, but I'm working on my
'svn log --limit' patch again (aka issue 1992). This lets you run 'svn
log --limit 5' to limit your log output to the last 5 log entries.
Here's the current iteration of the code. It adds a svn_repos_get_logs3
function that adds a limit argument and then bubbles it back up through
the RA layers into the client. Both ra_dav and ra_svn implement this in
such a way that it will 'work' with servers that don't support the
functionality, although for ra_dav it seems to still download all the
log entries, even though I tried to get the XML parser to error out.
The ra_dav code is untested, but looks like it should work. I will of
course test it before committing.
A log message is prepended to the diff.
Please let me know what you think, it's been a while since I looked at
this stuff, so it's quite possible that there's some kind of problem
that I've missed.
-garrett
Implement a '--limit' switch for 'svn log', which allows you to limit
the number of log entries returned.
* subversion/include/svn_repos.h
(svn_repos_get_logs3): new prototype, adds a new 'limit' argument to
svn_repos_get_logs2.
(svn_repos_get_logs2): deprecate.
* subversion/libsvn_repos/log.c
(svn_repos_get_logs3): new, implements limit functionality.
(svn_repos_get_logs2, svn_repos_get_logs): implement in terms of new
svn_repos_get_logs3 function.
* subversion/include/svn_client.h
(svn_client_log2): new prototype, adds a new 'limit' argument to
svn_client_log.
(svn_client_log): deprecate.
* subversion/libsvn_client/log.c
(svn_client_log2): new, like old svn_client_log, but now calls the
get_log2 method of the RA layer.
(svn_client_log): reimplement in terms of svn_client_log2.
* subversion/clients/cmdline/cl.h
(svn_cl__opt_state_t): add limit field.
* subversion/clients/cmdline/log-cmd.c
(svn_cl__log): call svn_client_log2 instead of svn_client_log.
* subversion/clients/cmdline/main.c
(svn_cl__options): add limit option.
(main): handle limit option.
* subversion/tests/clients/cmdline/getopt_tests_data/svn_help_log_switch_stdout
(svn help log): update for new --limit flag.
* subversion/include/svn_ra.h
(svn_ra_plugin_t::get_log2): new, adds a 'limit' argument to get_log.
(svn_ra_plugin_t::get_log): deprecate.
* subversion/libsvn_ra_local/ra_plugin.c
(svn_ra_local__get_log2): new, like svn_ra_local__get_log, but with an
additional 'limit' argument.
(svn_ra_local__get_log): reimplement in terms of svn_ra_local_get_log2.
(ra_local_plugin): add svn_ra_local__get_log2.
* subversion/libsvn_ra_svn/client.c
(ra_svn_log2): add limit functionality, with fallback in case the server
doesn't respect the limit request.
(ra_svn_log): implement in terms of ra_svn_log2.
(ra_svn_plugin): add ra_svn_log2.
* subversion/svnserve/serve.c
(log_cmd): add limit functionality.
* subversion/libsvn_ra_dav/log.c
(log_baton): add limit and count fields for keeping track of logs we
receive versus how many we're willing to display.
(log_end_element): bail out if we go over the limit of entries we're
going to show.
(svn_ra_dav__get_log2): new, adds limit to old svn_ra_dav__get_log impl.
(svn_ra_dav__get_log): reimplement in terms of svn_ra_dav__get_log2.
* subversion/libsvn_ra_dav/ra_dav.h
(svn_ra_dav__get_log2): prototype.
* subversion/libsvn_ra_dav/session.c
(dav_plugin): add svn_ra_dav__get_log2.
* subversion/mod_dav_svn/log.c
(dav_svn__log_report): parse limit out of request and pass it on to
svn_repos_get_logs2.
Index: subversion/include/svn_repos.h
===================================================================
--- subversion/include/svn_repos.h (revision 11128)
+++ subversion/include/svn_repos.h (working copy)
@@ -691,6 +691,8 @@
* "Single repository, multiple projects?" for more. We may simple
* need to offer a few different semantics for @a paths.
*
+ * If @a limit is non-zero then only return the first @a limit logs.
+ *
* If @a discover_changed_paths, then each call to @a receiver passes a
* <tt>const apr_hash_t *</tt> for the receiver's @a changed_paths
* argument; the hash's keys are all the paths committed in that revision.
@@ -718,6 +720,24 @@
* Use @a pool for temporary allocations.
*/
svn_error_t *
+svn_repos_get_logs3 (svn_repos_t *repos,
+ const apr_array_header_t *paths,
+ svn_revnum_t start,
+ svn_revnum_t end,
+ long int limit,
+ svn_boolean_t discover_changed_paths,
+ svn_boolean_t strict_node_history,
+ svn_repos_authz_func_t authz_read_func,
+ void *authz_read_baton,
+ svn_log_message_receiver_t receiver,
+ void *receiver_baton,
+ apr_pool_t *pool);
+
+
+/**
+ * @deprecated Provided for backward compatibility with the 1.1.0 API.
+ */
+svn_error_t *
svn_repos_get_logs2 (svn_repos_t *repos,
const apr_array_header_t *paths,
svn_revnum_t start,
Index: subversion/include/svn_client.h
===================================================================
--- subversion/include/svn_client.h (revision 11128)
+++ subversion/include/svn_client.h (working copy)
@@ -716,6 +716,21 @@
svn_client_ctx_t *ctx,
apr_pool_t *pool);
+/**
+ * @deprecated provided for compatability with the 1.0.0 API
+ *
+ * Similar to svn_client_log2, but with the @a limit parameter set to 0.
+ */
+svn_error_t *
+svn_client_log (const apr_array_header_t *targets,
+ const svn_opt_revision_t *start,
+ const svn_opt_revision_t *end,
+ svn_boolean_t discover_changed_paths,
+ svn_boolean_t strict_node_history,
+ svn_log_message_receiver_t receiver,
+ void *receiver_baton,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool);
/** Invoke @a receiver with @a receiver_baton on each log message from @a
* start to @a end in turn, inclusive (but never invoke @a receiver on a
@@ -729,6 +744,8 @@
*
* ### todo: the above paragraph is not fully implemented yet.
*
+ * If @a limit is non-zero only the first @a limit logs are returned.
+ *
* If @a discover_changed_paths is set, then the `@a changed_paths' argument
* to @a receiver will be passed on each invocation.
*
@@ -759,15 +776,16 @@
*
*/
svn_error_t *
-svn_client_log (const apr_array_header_t *targets,
- const svn_opt_revision_t *start,
- const svn_opt_revision_t *end,
- svn_boolean_t discover_changed_paths,
- svn_boolean_t strict_node_history,
- svn_log_message_receiver_t receiver,
- void *receiver_baton,
- svn_client_ctx_t *ctx,
- apr_pool_t *pool);
+svn_client_log2 (const apr_array_header_t *targets,
+ const svn_opt_revision_t *start,
+ const svn_opt_revision_t *end,
+ long int limit,
+ svn_boolean_t discover_changed_paths,
+ svn_boolean_t strict_node_history,
+ svn_log_message_receiver_t receiver,
+ void *receiver_baton,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool);
/** Invoke @a receiver with @a receiver_baton on each line-blame item
* associated with revision @a end of @a path_or_url, using @a start
Index: subversion/include/svn_ra.h
===================================================================
--- subversion/include/svn_ra.h (revision 11128)
+++ subversion/include/svn_ra.h (working copy)
@@ -646,39 +646,11 @@
void *diff_baton,
apr_pool_t *pool);
- /** Invoke @a receiver with @a receiver_baton on each log message from
- * @a start to @a end. @a start may be greater or less than @a end;
- * this just controls whether the log messages are processed in descending
- * or ascending revision number order.
+ /**
+ * @deprecated provided for compatability with the 1.0.0 API
*
- * If @a start or @a end is @c SVN_INVALID_REVNUM, it defaults to youngest.
- *
- * If @a paths is non-null and has one or more elements, then only show
- * revisions in which at least one of @a paths was changed (i.e., if
- * file, text or props changed; if dir, props changed or an entry
- * was added or deleted). Each path is an <tt>const char *</tt>, relative
- * to the session's common parent.
- *
- * If @a discover_changed_paths, then each call to receiver passes a
- * <tt>const apr_hash_t *</tt> for the receiver's @a changed_paths argument;
- * the hash's keys are all the paths committed in that revision.
- * Otherwise, each call to receiver passes null for @a changed_paths.
- *
- * If @a strict_node_history is set, copy history will not be traversed
- * (if any exists) when harvesting the revision logs for each path.
- *
- * If any invocation of @a receiver returns error, return that error
- * immediately and without wrapping it.
- *
- * If @a start or @a end is a non-existent revision, return the error
- * @c SVN_ERR_FS_NO_SUCH_REVISION, without ever invoking @a receiver.
- *
- * See also the documentation for @c svn_log_message_receiver_t.
- *
- * The caller may not invoke any RA operations using
- * @a session_baton from within @a receiver.
- *
- * Use @a pool for memory allocation.
+ * Similar to get_log2, but with the @a limit parameter always set
+ * to @c 0.
*/
svn_error_t *(*get_log) (void *session_baton,
const apr_array_header_t *paths,
@@ -809,6 +781,53 @@
can't fix this before 2.0, and the fix will cause undetectable
ABI breakage. */
const svn_version_t *(*get_version) (void);
+
+ /** Invoke @a receiver with @a receiver_baton on each log message from
+ * @a start to @a end. @a start may be greater or less than @a end;
+ * this just controls whether the log messages are processed in descending
+ * or ascending revision number order.
+ *
+ * If @a start or @a end is @c SVN_INVALID_REVNUM, it defaults to youngest.
+ *
+ * If @a paths is non-null and has one or more elements, then only show
+ * revisions in which at least one of @a paths was changed (i.e., if
+ * file, text or props changed; if dir, props changed or an entry
+ * was added or deleted). Each path is an <tt>const char *</tt>, relative
+ * to the session's common parent.
+ *
+ * If @a limit is non-zero only return the first @a limit logs.
+ *
+ * If @a discover_changed_paths, then each call to receiver passes a
+ * <tt>const apr_hash_t *</tt> for the receiver's @a changed_paths argument;
+ * the hash's keys are all the paths committed in that revision.
+ * Otherwise, each call to receiver passes null for @a changed_paths.
+ *
+ * If @a strict_node_history is set, copy history will not be traversed
+ * (if any exists) when harvesting the revision logs for each path.
+ *
+ * If any invocation of @a receiver returns error, return that error
+ * immediately and without wrapping it.
+ *
+ * If @a start or @a end is a non-existent revision, return the error
+ * @c SVN_ERR_FS_NO_SUCH_REVISION, without ever invoking @a receiver.
+ *
+ * See also the documentation for @c svn_log_message_receiver_t.
+ *
+ * The caller may not invoke any RA operations using
+ * @a session_baton from within @a receiver.
+ *
+ * Use @a pool for memory allocation.
+ */
+ svn_error_t *(*get_log2) (void *session_baton,
+ const apr_array_header_t *paths,
+ svn_revnum_t start,
+ svn_revnum_t end,
+ long int limit,
+ svn_boolean_t discover_changed_paths,
+ svn_boolean_t strict_node_history,
+ svn_log_message_receiver_t receiver,
+ void *receiver_baton,
+ apr_pool_t *pool);
} svn_ra_plugin_t;
Index: subversion/libsvn_ra_local/ra_plugin.c
===================================================================
--- subversion/libsvn_ra_local/ra_plugin.c (revision 11128)
+++ subversion/libsvn_ra_local/ra_plugin.c (working copy)
@@ -609,15 +609,16 @@
static svn_error_t *
-svn_ra_local__get_log (void *session_baton,
- const apr_array_header_t *paths,
- svn_revnum_t start,
- svn_revnum_t end,
- svn_boolean_t discover_changed_paths,
- svn_boolean_t strict_node_history,
- svn_log_message_receiver_t receiver,
- void *receiver_baton,
- apr_pool_t *pool)
+svn_ra_local__get_log2 (void *session_baton,
+ const apr_array_header_t *paths,
+ svn_revnum_t start,
+ svn_revnum_t end,
+ long int limit,
+ svn_boolean_t discover_changed_paths,
+ svn_boolean_t strict_node_history,
+ svn_log_message_receiver_t receiver,
+ void *receiver_baton,
+ apr_pool_t *pool)
{
svn_ra_local__session_baton_t *sbaton = session_baton;
apr_array_header_t *abs_paths
@@ -635,10 +636,11 @@
(*((const char **)(apr_array_push (abs_paths)))) = abs_path;
}
- return svn_repos_get_logs2 (sbaton->repos,
+ return svn_repos_get_logs3 (sbaton->repos,
abs_paths,
start,
end,
+ limit,
discover_changed_paths,
strict_node_history,
NULL, NULL,
@@ -649,6 +651,30 @@
static svn_error_t *
+svn_ra_local__get_log (void *session_baton,
+ const apr_array_header_t *paths,
+ svn_revnum_t start,
+ svn_revnum_t end,
+ svn_boolean_t discover_changed_paths,
+ svn_boolean_t strict_node_history,
+ svn_log_message_receiver_t receiver,
+ void *receiver_baton,
+ apr_pool_t *pool)
+{
+ return svn_ra_local__get_log2 (session_baton,
+ paths,
+ start,
+ end,
+ 0,
+ discover_changed_paths,
+ strict_node_history,
+ receiver,
+ receiver_baton,
+ pool);
+}
+
+
+static svn_error_t *
svn_ra_local__do_check_path (void *session_baton,
const char *path,
svn_revnum_t revision,
@@ -947,7 +973,8 @@
svn_ra_local__get_repos_root,
svn_ra_local__get_locations,
svn_ra_local__get_file_revs,
- ra_local_version
+ ra_local_version,
+ svn_ra_local__get_log2
};
Index: subversion/libsvn_client/log.c
===================================================================
--- subversion/libsvn_client/log.c (revision 11128)
+++ subversion/libsvn_client/log.c (working copy)
@@ -47,15 +47,16 @@
svn_error_t *
-svn_client_log (const apr_array_header_t *targets,
- const svn_opt_revision_t *start,
- const svn_opt_revision_t *end,
- svn_boolean_t discover_changed_paths,
- svn_boolean_t strict_node_history,
- svn_log_message_receiver_t receiver,
- void *receiver_baton,
- svn_client_ctx_t *ctx,
- apr_pool_t *pool)
+svn_client_log2 (const apr_array_header_t *targets,
+ const svn_opt_revision_t *start,
+ const svn_opt_revision_t *end,
+ long int limit,
+ svn_boolean_t discover_changed_paths,
+ svn_boolean_t strict_node_history,
+ svn_log_message_receiver_t receiver,
+ void *receiver_baton,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
{
svn_ra_plugin_t *ra_lib;
void *ra_baton, *session;
@@ -248,30 +249,32 @@
SVN_ERR (svn_client__get_revision_number
(&end_revnum, ra_lib, session, end, target, pool));
- err = ra_lib->get_log (session,
- condensed_targets,
- start_revnum,
- end_revnum,
- discover_changed_paths,
- strict_node_history,
- receiver,
- receiver_baton,
- pool);
+ err = ra_lib->get_log2 (session,
+ condensed_targets,
+ start_revnum,
+ end_revnum,
+ limit,
+ discover_changed_paths,
+ strict_node_history,
+ receiver,
+ receiver_baton,
+ pool);
if (err)
break;
}
}
else /* both revisions are static, so no loop needed */
{
- err = ra_lib->get_log (session,
- condensed_targets,
- start_revnum,
- end_revnum,
- discover_changed_paths,
- strict_node_history,
- receiver,
- receiver_baton,
- pool);
+ err = ra_lib->get_log2 (session,
+ condensed_targets,
+ start_revnum,
+ end_revnum,
+ limit,
+ discover_changed_paths,
+ strict_node_history,
+ receiver,
+ receiver_baton,
+ pool);
}
/* Special case: If there have been no commits, we'll get an error
@@ -310,3 +313,19 @@
return err;
}
+
+svn_error_t *
+svn_client_log (const apr_array_header_t *targets,
+ const svn_opt_revision_t *start,
+ const svn_opt_revision_t *end,
+ svn_boolean_t discover_changed_paths,
+ svn_boolean_t strict_node_history,
+ svn_log_message_receiver_t receiver,
+ void *receiver_baton,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
+{
+ return svn_client_log2 (targets, start, end, 0, discover_changed_paths,
+ strict_node_history, receiver, receiver_baton, ctx,
+ pool);
+}
Index: subversion/mod_dav_svn/log.c
===================================================================
--- subversion/mod_dav_svn/log.c (revision 11128)
+++ subversion/mod_dav_svn/log.c (working copy)
@@ -208,6 +208,7 @@
dav_svn_authz_read_baton arb;
const dav_svn_repos *repos = resource->info->repos;
const char *target = NULL;
+ long int limit = 0;
int ns;
/* These get determined from the request document. */
@@ -240,6 +241,11 @@
start = SVN_STR_TO_REV(dav_xml_get_cdata(child, resource->pool, 1));
else if (strcmp(child->name, "end-revision") == 0)
end = SVN_STR_TO_REV(dav_xml_get_cdata(child, resource->pool, 1));
+ else if (strcmp(child->name, "limit") == 0)
+ {
+ /* XXX this isn't really a revision, but same difference... */
+ limit = SVN_STR_TO_REV(child->first_cdata.first.text);
+ }
else if (strcmp(child->name, "discover-changed-paths") == 0)
{
/* ### todo: value doesn't matter, presence alone is enough?
@@ -287,10 +293,11 @@
flag in our log_receiver_baton structure). */
/* Send zero or more log items. */
- serr = svn_repos_get_logs2(repos->repos,
+ serr = svn_repos_get_logs3(repos->repos,
paths,
start,
end,
+ limit,
discover_changed_paths,
strict_node_history,
dav_svn_authz_read,
Index: subversion/clients/cmdline/cl.h
===================================================================
--- subversion/clients/cmdline/cl.h (revision 11128)
+++ subversion/clients/cmdline/cl.h (working copy)
@@ -89,6 +89,9 @@
end_revision remains `svn_opt_revision_unspecified'. */
svn_opt_revision_t start_revision, end_revision;
+ /* Max number of log messages to get back from svn_client_log. */
+ long int limit;
+
/* Note: these next two flags only reflect switches given on the
commandline. For example, 'svn up' (with no options) will *not*
set either of these flags, but will be recursive anyway */
Index: subversion/clients/cmdline/log-cmd.c
===================================================================
--- subversion/clients/cmdline/log-cmd.c (revision 11128)
+++ subversion/clients/cmdline/log-cmd.c (working copy)
@@ -500,15 +500,16 @@
SVN_ERR (svn_cmdline_printf (pool, "%s", sb->data));
}
- SVN_ERR (svn_client_log (targets,
- &(opt_state->start_revision),
- &(opt_state->end_revision),
- opt_state->verbose,
- opt_state->stop_on_copy,
- log_message_receiver_xml,
- &lb,
- ctx,
- pool));
+ SVN_ERR (svn_client_log2 (targets,
+ &(opt_state->start_revision),
+ &(opt_state->end_revision),
+ opt_state->limit,
+ opt_state->verbose,
+ opt_state->stop_on_copy,
+ log_message_receiver_xml,
+ &lb,
+ ctx,
+ pool));
if (! opt_state->incremental)
{
@@ -529,15 +530,16 @@
* is concerned, the result of 'svn log --quiet' is the same
* either way.
*/
- SVN_ERR (svn_client_log (targets,
- &(opt_state->start_revision),
- &(opt_state->end_revision),
- opt_state->verbose,
- opt_state->stop_on_copy,
- log_message_receiver,
- &lb,
- ctx,
- pool));
+ SVN_ERR (svn_client_log2 (targets,
+ &(opt_state->start_revision),
+ &(opt_state->end_revision),
+ opt_state->limit,
+ opt_state->verbose,
+ opt_state->stop_on_copy,
+ log_message_receiver,
+ &lb,
+ ctx,
+ pool));
if (! opt_state->incremental)
SVN_ERR (svn_cmdline_printf (pool, SEP_STRING));
Index: subversion/clients/cmdline/main.c
===================================================================
--- subversion/clients/cmdline/main.c (revision 11128)
+++ subversion/clients/cmdline/main.c (working copy)
@@ -144,6 +144,8 @@
"with a native svn:eol-style\n"
" property. ARG may be one "
"of 'LF', 'CR', 'CRLF'")},
+ {"limit", 'l', 1,
+ N_("maximum number of log entries")},
{0, 0, 0, 0}
};
@@ -381,7 +383,7 @@
" svn log foo.c\n"
" svn log http://www.example.com/repo/project/foo.c\n"
" svn log http://www.example.com/repo/project foo.c bar.c\n"),
- {'r', 'q', 'v', svn_cl__targets_opt, svn_cl__stop_on_copy_opt,
+ {'r', 'q', 'v', 'l', svn_cl__targets_opt, svn_cl__stop_on_copy_opt,
svn_cl__incremental_opt, svn_cl__xml_opt, SVN_CL__AUTH_OPTIONS,
svn_cl__config_dir_opt} },
@@ -811,6 +813,9 @@
num_opts++;
switch (opt_id) {
+ case 'l':
+ opt_state.limit = atol (opt_arg);
+ break;
case 'm':
/* Note that there's no way here to detect if the log message
contains a zero byte -- if it does, then opt_arg will just
Index: subversion/tests/clients/cmdline/getopt_tests_data/svn_help_log_switch_stdout
===================================================================
--- subversion/tests/clients/cmdline/getopt_tests_data/svn_help_log_switch_stdout (revision 11128)
+++ subversion/tests/clients/cmdline/getopt_tests_data/svn_help_log_switch_stdout (working copy)
@@ -34,6 +34,7 @@
"PREV" revision just before COMMITTED
-q [--quiet] : print as little as possible
-v [--verbose] : print extra information
+ -l [--limit] arg : maximum number of log entries
--targets arg : pass contents of file ARG as additional args
--stop-on-copy : do not cross copies while traversing history
--incremental : give output suitable for concatenation
Index: subversion/libsvn_repos/log.c
===================================================================
--- subversion/libsvn_repos/log.c (revision 11128)
+++ subversion/libsvn_repos/log.c (working copy)
@@ -199,10 +199,11 @@
svn_error_t *
-svn_repos_get_logs2 (svn_repos_t *repos,
+svn_repos_get_logs3 (svn_repos_t *repos,
const apr_array_header_t *paths,
svn_revnum_t start,
svn_revnum_t end,
+ long int limit,
svn_boolean_t discover_changed_paths,
svn_boolean_t strict_node_history,
svn_repos_authz_func_t authz_read_func,
@@ -328,6 +329,19 @@
return SVN_NO_ERROR;
}
+ if (limit)
+ {
+ if (revs)
+ revs->nelts = limit;
+ else
+ {
+ if (start > end && (start - end) > limit)
+ end = start - (limit - 1);
+ else if (end > start && (end - start) > limit)
+ start = end - (limit - 1);
+ }
+ }
+
for (this_rev = start;
((start >= end) ? (this_rev >= end) : (this_rev <= end));
((start >= end) ? this_rev-- : this_rev++))
@@ -418,7 +432,26 @@
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_repos_get_logs2 (svn_repos_t *repos,
+ const apr_array_header_t *paths,
+ svn_revnum_t start,
+ svn_revnum_t end,
+ svn_boolean_t discover_changed_paths,
+ svn_boolean_t strict_node_history,
+ svn_repos_authz_func_t authz_read_func,
+ void *authz_read_baton,
+ svn_log_message_receiver_t receiver,
+ void *receiver_baton,
+ apr_pool_t *pool)
+{
+ return svn_repos_get_logs3 (repos, paths, start, end, 0,
+ discover_changed_paths, strict_node_history,
+ authz_read_func, authz_read_baton, receiver,
+ receiver_baton, pool);
+}
+
/* The 1.0 version of the function. ### Remove in 2.0. */
svn_error_t *
svn_repos_get_logs (svn_repos_t *repos,
@@ -431,7 +464,7 @@
void *receiver_baton,
apr_pool_t *pool)
{
- return svn_repos_get_logs2 (repos, paths, start, end,
+ return svn_repos_get_logs3 (repos, paths, start, end, 0,
discover_changed_paths, strict_node_history,
NULL, NULL, /* no authz stuff */
receiver, receiver_baton, pool);
Index: subversion/libsvn_ra_svn/client.c
===================================================================
--- subversion/libsvn_ra_svn/client.c (revision 11128)
+++ subversion/libsvn_ra_svn/client.c (working copy)
@@ -1003,12 +1003,13 @@
return SVN_NO_ERROR;
}
-static svn_error_t *ra_svn_log(void *baton, const apr_array_header_t *paths,
- svn_revnum_t start, svn_revnum_t end,
- svn_boolean_t discover_changed_paths,
- svn_boolean_t strict_node_history,
- svn_log_message_receiver_t receiver,
- void *receiver_baton, apr_pool_t *pool)
+static svn_error_t *ra_svn_log2(void *baton, const apr_array_header_t *paths,
+ svn_revnum_t start, svn_revnum_t end,
+ long int limit,
+ svn_boolean_t discover_changed_paths,
+ svn_boolean_t strict_node_history,
+ svn_log_message_receiver_t receiver,
+ void *receiver_baton, apr_pool_t *pool)
{
ra_svn_session_baton_t *sess = baton;
svn_ra_svn_conn_t *conn = sess->conn;
@@ -1020,6 +1021,7 @@
apr_hash_t *cphash;
svn_revnum_t rev, copy_rev;
svn_log_changed_path_t *change;
+ int nreceived = 0;
SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w((!", "log"));
if (paths)
@@ -1030,8 +1032,9 @@
SVN_ERR(svn_ra_svn_write_cstring(conn, pool, path));
}
}
- SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!)(?r)(?r)bb)", start, end,
- discover_changed_paths, strict_node_history));
+ SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!)(?r)(?r)bbr)", start, end,
+ discover_changed_paths, strict_node_history,
+ limit));
SVN_ERR(handle_auth_request(sess, pool));
/* Read the log messages. */
@@ -1069,18 +1072,39 @@
}
else
cphash = NULL;
+
+ if (limit && ++nreceived > limit)
+ break;
+
SVN_ERR(receiver(receiver_baton, cphash, rev, author, date, message,
subpool));
apr_pool_clear(subpool);
}
apr_pool_destroy(subpool);
- /* Read the response. */
- SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, ""));
+ if (nreceived <= limit)
+ {
+ /* Read the response. */
+ SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, ""));
+ }
return SVN_NO_ERROR;
}
+static svn_error_t *ra_svn_log(void *baton,
+ const apr_array_header_t *paths,
+ svn_revnum_t start,
+ svn_revnum_t end,
+ svn_boolean_t discover_changed_paths,
+ svn_boolean_t strict_node_history,
+ svn_log_message_receiver_t receiver,
+ void *receiver_baton, apr_pool_t *pool)
+{
+ return ra_svn_log2(baton, paths, start, end, 0, discover_changed_paths,
+ strict_node_history, receiver, receiver_baton, pool);
+}
+
+
static svn_error_t *ra_svn_check_path(void *baton, const char *path,
svn_revnum_t rev, svn_node_kind_t *kind,
apr_pool_t *pool)
@@ -1288,7 +1312,8 @@
ra_svn_get_repos_root,
ra_svn_get_locations,
ra_svn_get_file_revs,
- svn_ra_svn_version
+ svn_ra_svn_version,
+ ra_svn_log2
};
svn_error_t *svn_ra_svn_init(int abi_version, apr_pool_t *pool,
Index: subversion/libsvn_ra_dav/log.c
===================================================================
--- subversion/libsvn_ra_dav/log.c (revision 11128)
+++ subversion/libsvn_ra_dav/log.c (working copy)
@@ -79,6 +79,9 @@
svn_log_message_receiver_t receiver;
void *receiver_baton;
+ long int limit;
+ long int count;
+
/* If `receiver' returns error, it is stored here. */
svn_error_t *err;
};
@@ -215,6 +218,16 @@
lb->date,
lb->msg,
lb->subpool);
+
+ /* Compatability cruft so that we can provide limit functionality
+ even if the server doesn't support it. I'm not clear why it
+ seems to take so long to bail once this codepath is hit, but
+ whatever... */
+ if (lb->limit && (++lb->count == lb->limit))
+ {
+ lb->err = NULL;
+ return SVN_RA_DAV__XML_INVALID;
+ }
reset_log_item (lb);
@@ -285,15 +298,16 @@
}
-svn_error_t * svn_ra_dav__get_log(void *session_baton,
- const apr_array_header_t *paths,
- svn_revnum_t start,
- svn_revnum_t end,
- svn_boolean_t discover_changed_paths,
- svn_boolean_t strict_node_history,
- svn_log_message_receiver_t receiver,
- void *receiver_baton,
- apr_pool_t *pool)
+svn_error_t * svn_ra_dav__get_log2(void *session_baton,
+ const apr_array_header_t *paths,
+ svn_revnum_t start,
+ svn_revnum_t end,
+ long int limit,
+ svn_boolean_t discover_changed_paths,
+ svn_boolean_t strict_node_history,
+ svn_log_message_receiver_t receiver,
+ void *receiver_baton,
+ apr_pool_t *pool)
{
/* The Plan: Send a request to the server for a log report.
* Somewhere in mod_dav_svn, there will be an implementation, R, of
@@ -356,6 +370,13 @@
apr_psprintf(ras->pool,
"<S:end-revision>%ld"
"</S:end-revision>", end));
+ if (limit)
+ {
+ svn_stringbuf_appendcstr(request_body,
+ apr_psprintf(ras->pool,
+ "<S:limit>%ld</S:limit>", limit));
+ }
+
if (discover_changed_paths)
{
svn_stringbuf_appendcstr(request_body,
@@ -385,6 +406,8 @@
lb.receiver_baton = receiver_baton;
lb.subpool = svn_pool_create (ras->pool);
lb.err = NULL;
+ lb.limit = limit;
+ lb.count = 0;
reset_log_item (&lb);
/* ras's URL may not exist in HEAD, and thus it's not safe to send
@@ -422,3 +445,18 @@
return SVN_NO_ERROR;
}
+
+svn_error_t * svn_ra_dav__get_log(void *session_baton,
+ const apr_array_header_t *paths,
+ svn_revnum_t start,
+ svn_revnum_t end,
+ svn_boolean_t discover_changed_paths,
+ svn_boolean_t strict_node_history,
+ svn_log_message_receiver_t receiver,
+ void *receiver_baton,
+ apr_pool_t *pool)
+{
+ return svn_ra_dav__get_log2(session_baton, paths, start, end, 0,
+ discover_changed_paths, strict_node_history,
+ receiver, receiver_baton, pool);
+}
Index: subversion/libsvn_ra_dav/ra_dav.h
===================================================================
--- subversion/libsvn_ra_dav/ra_dav.h (revision 11128)
+++ subversion/libsvn_ra_dav/ra_dav.h (working copy)
@@ -721,6 +721,18 @@
apr_array_header_t *location_revisions,
apr_pool_t *pool);
+svn_error_t *
+svn_ra_dav__get_log2 (void *session_baton,
+ const apr_array_header_t *paths,
+ svn_revnum_t start,
+ svn_revnum_t end,
+ long int limit,
+ svn_boolean_t discover_changed_paths,
+ svn_boolean_t strict_node_history,
+ svn_log_message_receiver_t receiver,
+ void *receiver_baton,
+ apr_pool_t *pool);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
Index: subversion/libsvn_ra_dav/session.c
===================================================================
--- subversion/libsvn_ra_dav/session.c (revision 11128)
+++ subversion/libsvn_ra_dav/session.c (working copy)
@@ -853,7 +853,8 @@
svn_ra_dav__get_repos_root,
svn_ra_dav__get_locations,
svn_ra_dav__get_file_revs,
- ra_dav_version
+ ra_dav_version,
+ svn_ra_dav__get_log2
};
Index: subversion/svnserve/serve.c
===================================================================
--- subversion/svnserve/serve.c (revision 11128)
+++ subversion/svnserve/serve.c (working copy)
@@ -887,12 +887,16 @@
apr_array_header_t *paths, *full_paths;
svn_ra_svn_item_t *elt;
int i;
+ long int limit = 0;
log_baton_t lb;
/* Parse the arguments. */
- SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "l(?r)(?r)bb", &paths,
+ SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "l(?r)(?r)bb?r", &paths,
&start_rev, &end_rev, &changed_paths,
- &strict_node));
+ &strict_node, &limit));
+ if (limit == -1)
+ limit = 0;
+
full_paths = apr_array_make(pool, paths->nelts, sizeof(const char *));
for (i = 0; i < paths->nelts; i++)
{
@@ -908,7 +912,7 @@
/* Get logs. (Can't report errors back to the client at this point.) */
lb.fs_path = b->fs_path;
lb.conn = conn;
- err = svn_repos_get_logs2(b->repos, full_paths, start_rev, end_rev,
+ err = svn_repos_get_logs3(b->repos, full_paths, start_rev, end_rev, limit,
changed_paths, strict_node, NULL, NULL,
log_receiver, &lb, pool);
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Sat Sep 25 05:18:39 2004