Karl Fogel <kfogel@newton.ch.collab.net> writes:
> Daniel Rall <dlr@finemaltcoding.com> writes:
> > The output that I'm getting from `svn log` from the latest code seems
> > a bit odd:
> 
> Whups.
> 
> That should be easy to fix (note that -1 is the real value of
> SVN_INVALID_REVNUM).  Can you file a quick issue on it?  I'll bet it
> gets squashed in no time; well, *almost* no time -- I'm going to bed
> now :-).
> 
> You may find it faster to patch than to make an issue, even.
It turned it that no, it was not faster to patch.  But I took a stab
at it anyhow, with some debugging assistence from Ben and a solution
suggestion from Greg.
The log message problem is not reproducable over ra_local (you need at
least 1 revnum to have a shot at it), but is reproducable over ra_dav.
The problem is not in the client library, but on the server-side.
Specifically, the response returned by mod_dav_svn wraps the
SVN_ERR_FS_NOT_FOUND produced when determining the response in a
<S:log-report> element, rather than in the <D:error> element which the
client-side recognizes as an error.
REPORT /repos/svn/trunk HTTP/1.1
Host: 216.127.237.133:81
User-Agent: neon/0.23.5 SVN/0.15.0 (dev build)
Connection: TE
TE: trailers
Content-Length: 142
Content-Type: text/xml
<S:log-report xmlns:S="svn:">
<S:start-revision>3782</S:start-revision><S:end-revision>1</S:end-revision><S:path>asdf</S:path></S:log-report>
HTTP/1.1 200 OK
Date: Thu, 14 Nov 2002 05:44:31 GMT
Server: Apache/2.0.44-dev (Unix) mod_ssl/2.0.44-dev OpenSSL/0.9.6 DAV/2 SVN/0.14.5 (dev build)
Transfer-Encoding: chunked
Content-Type: text/xml; charset="utf-8"
130
<?xml version="1.0" encoding="utf-8"?>
<S:log-report xmlns:S="svn:" xmlns:D="DAV:">
<S:log-item>
<D:version-name>-1</D:version-name>
<D:creator-displayname></D:creator-displayname>
<S:date></S:date>
<D:comment>file not found: revision `3782', path `/trunk/asdf'</D:comment>
</S:log-item>
</S:log-report>
0
Note that the response body actually comes back gzipped.  I used
ethereal to record the transaction (thanks Ben), then used telnet to
reply the response, leaving out the "Accept-Encoding: gzip" HTTP
header (which I assume Neon is generating).  This allowed me to see
the plaintext of the response.
Here's a completely untested patch to mod_dav_svn (having difficulties
getting mod_dav_svn built), approximating the lazy writing of the DAV
XML header fix suggested by gstein.  Even though we should always get
a SVN_ERR_FS_NOT_FOUND, I left in the old error handling for the case
where we've already started writing the response.
Some up for reviewing this/testing it out?  If not, be certain that I
will corner YOU @ ApacheCon. ;-)
* subversion/mod_dav_svn/log.c
  (struct log_receiver_baton): Added a needs_header flag to the
  internal baton to indicate whether we've written the <S:log-report>
  header.  Allows for lazy writes to support mod_dav-based error
  handling.
  (svn_types.h): Imported for svn_boolean_t for needs_header flag.
  (dav_svn__log_report): Initialized the baton's needs_header flag to
  true.  Moved writing of DAV XML header into log_receiver.  Return
  with a dav_error * if an error is detected before we start sending
  the response (e.g. when a we get a SVN_ERR_FS_NOT_FOUND from a
  request for a non-existent resource).
  (log_receiver): Send DAV XML header and <S:log-report> start if we
  still need to send the header (determined by the needs_header flag
  on our baton).
Index: subversion/mod_dav_svn/log.c
===================================================================
--- subversion/mod_dav_svn/log.c	(revision 3793)
+++ subversion/mod_dav_svn/log.c	(working copy)
@@ -26,6 +26,7 @@
 #include "svn_pools.h"
 #include "svn_repos.h"
 #include "svn_fs.h"
+#include "svn_types.h"
 #include "svn_xml.h"
 #include "svn_path.h"
 
@@ -40,6 +41,10 @@
 
   /* where to deliver the output */
   ap_filter_t *output;
+
+  /* Whether we've written the <S:log-report> header.  Allows for lazy
+     writes to support mod_dav-based error handling. */
+  svn_boolean_t needs_header;
 };
 
 
@@ -65,6 +70,16 @@
 {
   struct log_receiver_baton *lrb = baton;
 
+  if (lrb->needs_header)
+    {
+      /* Start the log report. */
+      send_xml(lrb,
+               DAV_XML_HEADER DEBUG_CR
+               "<S:log-report xmlns:S=\"" SVN_XML_NAMESPACE "\" "
+               "xmlns:D=\"DAV:\">" DEBUG_CR);
+      lrb->needs_header = FALSE;
+    }
+
   send_xml(lrb,
            "<S:log-item>" DEBUG_CR
            "<D:version-name>%" SVN_REVNUM_T_FMT "</D:version-name>" DEBUG_CR
@@ -236,12 +251,12 @@
   lrb.bb = apr_brigade_create(resource->pool,  /* not the subpool! */
                               output->c->bucket_alloc);
   lrb.output = output;
+  lrb.needs_header = TRUE;
 
-  /* Start the log report. */
-  send_xml(&lrb,
-           DAV_XML_HEADER DEBUG_CR
-           "<S:log-report xmlns:S=\"" SVN_XML_NAMESPACE "\" "
-           "xmlns:D=\"DAV:\">" DEBUG_CR);
+  /* Our svn_log_message_receiver_t sends the <S:log-report> header in
+     a lazy fashion.  Before writing the first log message, it assures
+     that the header has already been sent (checking the needs_header
+     flag in our log_receiver_baton structure). */
 
   /* Send zero or more log items. */
   serr = svn_repos_get_logs(repos->repos,
@@ -256,27 +271,32 @@
 
   if (serr)
     {
-      /* ### We've definitely generated some content into the output
-         ### filter, which means that we cannot return an error here.
-         ### In the future, mod_dav may specify a way to signal an
-         ### error even after the response stream has begun. 
-         ### 
-         ### So for now, we "return" the error by invoking the
-         ### log_receiver on the error message itself. 
-         ### 
-         ### http://subversion.tigris.org/issues/show_bug.cgi?id=816
-         ### describes a situation where this helps. */
-
-      /* Don't bother to check for error; we can't do anything with it
-         if we get one. */
-      log_receiver(&lrb,
-                   NULL,
-                   SVN_INVALID_REVNUM,
-                   "", "",
-                   serr->message,
-                   resource->pool);
-
-      serr = NULL;
+      /* If we can, report a DAV error. */
+      if (lrb.needs_header)
+        {
+          /* Bail out before writing any of <S:log-report>. */
+          return dav_svn_convert_err(serr, HTTP_BAD_REQUEST, serr->message);
+        }
+      else
+        {
+          /* ### We've sent some content to the output filter, meaning
+             ### that we cannot simply return an error here.  In the
+             ### future, mod_dav may specify a way to signal an error
+             ### even after the response stream has begun.
+
+             ### For now we punt, sending the error message to the
+             ### client as a <S:log-item> (using its <D:version-name>
+             ### and <D:comment> children).
+
+             ### http://subversion.tigris.org/issues/show_bug.cgi?id=816
+             ### describes a situation where this helps.*/
+          log_receiver(&lrb,
+                       NULL,
+                       SVN_INVALID_REVNUM,
+                       "", "",
+                       serr->message,
+                       resource->pool);
+        }
     }
   
   /* End the log report. */
-- 
Daniel Rall <dlr@finemaltcoding.com>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Fri Nov 15 08:21:15 2002