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

[PATCH] add --limit argument to svn log

From: Garrett Rooney <rooneg_at_electricjellyfish.net>
Date: 2004-09-25 05:18:28 CEST

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

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