You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by cm...@apache.org on 2010/07/30 21:04:17 UTC

svn commit: r980924 - in /subversion/trunk/subversion/libsvn_ra_serf: blame.c commit.c getlocations.c getlocationsegments.c mergeinfo.c options.c property.c ra_serf.h update.c util.c

Author: cmpilato
Date: Fri Jul 30 19:04:17 2010
New Revision: 980924

URL: http://svn.apache.org/viewvc?rev=980924&view=rev
Log:
Finish issue #3685: ra_serf fails to alert users of relocated
repositories (301/302 handling).

* subversion/libsvn_ra_serf/ra_serf.h
  (svn_ra_serf__simple_request_context_t): Add 'location' member.
  (struct svn_ra_serf__xml_parser_t): Add 'location' member.
  (svn_ra_serf__error_on_status): Add 'location' parameter.
  (svn_ra_serf__response_get_location): New function.

* subversion/libsvn_ra_serf/util.c
  (svn_ra_serf__response_get_location): New function.
  (svn_ra_serf__handle_status_only, svn_ra_serf__handle_multistatus_only,
   svn_ra_serf__handle_xml_parser): Use svn_ra_serf__response_get_location()
     to populate the context's
    'location' member.
  (svn_ra_serf__error_on_status): Add 'location' parameter, and use it
    (instead of the 'path' parameter) to report redirect locations.

* subversion/libsvn_ra_serf/blame.c
  (svn_ra_serf__get_file_revs): Update call to svn_ra_serf__error_on_status().

* subversion/libsvn_ra_serf/commit.c
  (return_response_err): Update call to svn_ra_serf__error_on_status(), 
    and give the code some room to breathe.

* subversion/libsvn_ra_serf/getlocations.c
  (svn_ra_serf__get_locations): Update call to svn_ra_serf__error_on_status().

* subversion/libsvn_ra_serf/getlocationsegments.c
  (svn_ra_serf__get_location_segments): Update call to
    svn_ra_serf__error_on_status().  While here, fix an error leak, too.

* subversion/libsvn_ra_serf/mergeinfo.c
  (svn_ra_serf__get_mergeinfo): Update call to svn_ra_serf__error_on_status().

* subversion/libsvn_ra_serf/options.c
  (svn_ra_serf__exchange_capabilities): Use svn_ra_serf__error_on_status() to 
    notice common errors, including the 301/302 redirect variety.

* subversion/libsvn_ra_serf/property.c
  (svn_ra_serf__wait_for_props): Update call to svn_ra_serf__error_on_status().

* subversion/libsvn_ra_serf/update.c
  (handle_stream): Use svn_ra_serf__response_get_location(), and
    update call to svn_ra_serf__error_on_status().

Modified:
    subversion/trunk/subversion/libsvn_ra_serf/blame.c
    subversion/trunk/subversion/libsvn_ra_serf/commit.c
    subversion/trunk/subversion/libsvn_ra_serf/getlocations.c
    subversion/trunk/subversion/libsvn_ra_serf/getlocationsegments.c
    subversion/trunk/subversion/libsvn_ra_serf/mergeinfo.c
    subversion/trunk/subversion/libsvn_ra_serf/options.c
    subversion/trunk/subversion/libsvn_ra_serf/property.c
    subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h
    subversion/trunk/subversion/libsvn_ra_serf/update.c
    subversion/trunk/subversion/libsvn_ra_serf/util.c

Modified: subversion/trunk/subversion/libsvn_ra_serf/blame.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/blame.c?rev=980924&r1=980923&r2=980924&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/blame.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/blame.c Fri Jul 30 19:04:17 2010
@@ -483,8 +483,10 @@ svn_ra_serf__get_file_revs(svn_ra_sessio
   err = svn_ra_serf__context_run_wait(&blame_ctx->done, session, pool);
 
   err = svn_error_compose_create(
-                svn_ra_serf__error_on_status(status_code, handler->path),
-                err);
+            svn_ra_serf__error_on_status(status_code,
+                                         handler->path,
+                                         parser_ctx->location),
+            err);
 
   return svn_error_return(err);
 }

Modified: subversion/trunk/subversion/libsvn_ra_serf/commit.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/commit.c?rev=980924&r1=980923&r2=980924&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/commit.c Fri Jul 30 19:04:17 2010
@@ -220,16 +220,22 @@ static svn_error_t *
 return_response_err(svn_ra_serf__handler_t *handler,
                     svn_ra_serf__simple_request_context_t *ctx)
 {
+  svn_error_t *err;
+
+  /* Ye Olde Fallback Error */
+  err = svn_error_compose_create(
+            ctx->server_error.error,
+            svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
+                              "%s of '%s': %d %s",
+                              handler->method, handler->path,
+                              ctx->status, ctx->reason));
+
   /* Try to return one of the standard errors for 301, 404, etc.,
      then look for an error embedded in the response.  */
-  return svn_error_compose_create(
-    svn_ra_serf__error_on_status(ctx->status, handler->path),
-    svn_error_compose_create(
-      ctx->server_error.error,
-      svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
-                        "%s of '%s': %d %s",
-                        handler->method, handler->path,
-                        ctx->status, ctx->reason)));
+  return svn_error_compose_create(svn_ra_serf__error_on_status(ctx->status,
+                                                               handler->path,
+                                                               ctx->location),
+                                  err);
 }
 
 static serf_bucket_t *

Modified: subversion/trunk/subversion/libsvn_ra_serf/getlocations.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/getlocations.c?rev=980924&r1=980923&r2=980924&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/getlocations.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/getlocations.c Fri Jul 30 19:04:17 2010
@@ -277,7 +277,9 @@ svn_ra_serf__get_locations(svn_ra_sessio
   err = svn_ra_serf__context_run_wait(&loc_ctx->done, session, pool);
 
   SVN_ERR(svn_error_compose_create(
-              svn_ra_serf__error_on_status(loc_ctx->status_code, req_url),
+              svn_ra_serf__error_on_status(loc_ctx->status_code,
+                                           req_url,
+                                           parser_ctx->location),
               err));
 
   return SVN_NO_ERROR;

Modified: subversion/trunk/subversion/libsvn_ra_serf/getlocationsegments.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/getlocationsegments.c?rev=980924&r1=980923&r2=980924&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/getlocationsegments.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/getlocationsegments.c Fri Jul 30 19:04:17 2010
@@ -181,7 +181,7 @@ svn_ra_serf__get_location_segments(svn_r
   svn_ra_serf__handler_t *handler;
   svn_ra_serf__xml_parser_t *parser_ctx;
   const char *relative_url, *basecoll_url, *req_url;
-  svn_error_t *err;
+  svn_error_t *err, *err2;
 
   gls_ctx = apr_pcalloc(pool, sizeof(*gls_ctx));
   gls_ctx->path = path;
@@ -230,8 +230,15 @@ svn_ra_serf__get_location_segments(svn_r
                             _("Location segment report failed on '%s'@'%ld'"),
                               path, peg_revision);
 
-  /* ### Leaks err */
-  SVN_ERR(svn_ra_serf__error_on_status(gls_ctx->status_code, handler->path));
+  err2 = svn_ra_serf__error_on_status(gls_ctx->status_code,
+                                      handler->path,
+                                      parser_ctx->location);
+  if (err2)
+    {
+      /* Prefer err2 to err. */
+      svn_error_clear(err);
+      return err2;
+    }
 
   svn_pool_destroy(gls_ctx->subpool);
 

Modified: subversion/trunk/subversion/libsvn_ra_serf/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/mergeinfo.c?rev=980924&r1=980923&r2=980924&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/mergeinfo.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/mergeinfo.c Fri Jul 30 19:04:17 2010
@@ -290,12 +290,12 @@ svn_ra_serf__get_mergeinfo(svn_ra_sessio
 
   err = svn_ra_serf__context_run_wait(&mergeinfo_ctx->done, session, pool);
 
-  err2 = svn_ra_serf__error_on_status(status_code, handler->path);
-
+  err2 = svn_ra_serf__error_on_status(status_code, handler->path,
+                                      parser_ctx->location);
   if (err2)
     {
       svn_error_clear(err);
-      SVN_ERR(err2);
+      return err2;
     }
 
   SVN_ERR(err);

Modified: subversion/trunk/subversion/libsvn_ra_serf/options.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/options.c?rev=980924&r1=980923&r2=980924&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/options.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/options.c Fri Jul 30 19:04:17 2010
@@ -481,15 +481,20 @@ svn_ra_serf__exchange_capabilities(svn_r
                                    apr_pool_t *pool)
 {
   svn_ra_serf__options_context_t *opt_ctx;
+  svn_error_t *err;
 
   /* This routine automatically fills in serf_sess->capabilities */
   svn_ra_serf__create_options_req(&opt_ctx, serf_sess, serf_sess->conns[0],
                                   serf_sess->repos_url.path, pool);
 
-  SVN_ERR(svn_ra_serf__context_run_wait(
-    svn_ra_serf__get_options_done_ptr(opt_ctx), serf_sess, pool));
+  err = svn_ra_serf__context_run_wait(
+            svn_ra_serf__get_options_done_ptr(opt_ctx), serf_sess, pool);
 
-  return SVN_NO_ERROR;
+  return svn_error_compose_create(
+             svn_ra_serf__error_on_status(opt_ctx->status_code,
+                                          serf_sess->repos_url.path,
+                                          opt_ctx->parser_ctx->location),
+             err);
 }
 
 

Modified: subversion/trunk/subversion/libsvn_ra_serf/property.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/property.c?rev=980924&r1=980923&r2=980924&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/property.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/property.c Fri Jul 30 19:04:17 2010
@@ -700,7 +700,8 @@ svn_ra_serf__wait_for_props(svn_ra_serf_
 
   err = svn_ra_serf__context_run_wait(&prop_ctx->done, sess, pool);
 
-  err2 = svn_ra_serf__error_on_status(prop_ctx->status_code, prop_ctx->path);
+  err2 = svn_ra_serf__error_on_status(prop_ctx->status_code,
+                                      prop_ctx->path, NULL);
   if (err2)
     {
       svn_error_clear(err);

Modified: subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h?rev=980924&r1=980923&r2=980924&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h Fri Jul 30 19:04:17 2010
@@ -623,6 +623,10 @@ struct svn_ra_serf__xml_parser_t {
    */
   int *status_code;
 
+  /* If non-NULL, this is the value of the response's Location header.
+   */
+  const char *location;
+
   /* If non-NULL, this value will be set to TRUE when the response is
    * completed.
    */
@@ -686,6 +690,10 @@ typedef struct svn_ra_serf__simple_reque
   /* The HTTP status line of the response */
   const char *reason;
 
+  /* The Location header value of the response, or NULL if there
+     wasn't one. */
+  const char *location;
+
   /* This value is set to TRUE when the response is completed. */
   svn_boolean_t done;
 
@@ -775,6 +783,13 @@ svn_ra_serf__response_discard_handler(se
                                       void *baton,
                                       apr_pool_t *pool);
 
+/* Return the value of the RESPONSE's Location header if any, or NULL
+ * otherwise.  All allocations will be made in POOL.
+ */
+const char *
+svn_ra_serf__response_get_location(serf_bucket_t *response,
+                                   apr_pool_t *pool);
+
 /** XML helper functions. **/
 
 /*
@@ -1498,11 +1513,14 @@ svn_ra_serf__encode_auth_header(const ch
 /*** General utility functions ***/
 
 /**
- * Convert an HTTP status code resulting from a WebDAV request to the relevant
- * error code.
+ * Convert an HTTP STATUS_CODE resulting from a WebDAV request against
+ * PATH to the relevant error code.  Use the response-supplied LOCATION
+ * where it necessary.
  */
 svn_error_t *
-svn_ra_serf__error_on_status(int status_code, const char *path);
+svn_ra_serf__error_on_status(int status_code,
+                             const char *path,
+                             const char *location);
 
 #ifdef __cplusplus
 }

Modified: subversion/trunk/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/update.c?rev=980924&r1=980923&r2=980924&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/update.c Fri Jul 30 19:04:17 2010
@@ -995,11 +995,15 @@ handle_stream(serf_request_t *request,
 {
   report_fetch_t *fetch_ctx = handler_baton;
   serf_status_line sl;
+  const char *location;
 
   serf_bucket_response_status(response, &sl);
 
   /* Woo-hoo.  Nothing here to see.  */
-  fetch_ctx->err = svn_ra_serf__error_on_status(sl.code, fetch_ctx->info->name);
+  location = svn_ra_serf__response_get_location(response, pool);
+  fetch_ctx->err = svn_ra_serf__error_on_status(sl.code,
+                                                fetch_ctx->info->name,
+                                                location);
   if (fetch_ctx->err)
     {
       fetch_ctx->done = TRUE;

Modified: subversion/trunk/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/util.c?rev=980924&r1=980923&r2=980924&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/util.c Fri Jul 30 19:04:17 2010
@@ -804,6 +804,18 @@ svn_ra_serf__response_discard_handler(se
     }
 }
 
+const char *
+svn_ra_serf__response_get_location(serf_bucket_t *response,
+                                   apr_pool_t *pool)
+{
+  serf_bucket_t *headers;
+  const char *val;
+
+  headers = serf_bucket_response_get_headers(response);
+  val = serf_bucket_headers_get(headers, "Location");
+  return val ? svn_uri_canonicalize(val, pool) : NULL;
+}
+
 /* Implements svn_ra_serf__response_handler_t */
 svn_error_t *
 svn_ra_serf__handle_status_only(serf_request_t *request,
@@ -826,7 +838,7 @@ svn_ra_serf__handle_status_only(serf_req
 
       ctx->status = sl.code;
       ctx->reason = sl.reason;
-
+      ctx->location = svn_ra_serf__response_get_location(response, pool);
       ctx->done = TRUE;
     }
 
@@ -986,6 +998,7 @@ svn_ra_serf__handle_multistatus_only(ser
 
       ctx->status = sl.code;
       ctx->reason = sl.reason;
+      ctx->location = svn_ra_serf__response_get_location(response, pool);
     }
 
   return svn_error_return(err);
@@ -1060,6 +1073,11 @@ svn_ra_serf__handle_xml_parser(serf_requ
       *ctx->status_code = sl.code;
     }
 
+  if (sl.code == 301 || sl.code == 302)
+    {
+      ctx->location = svn_ra_serf__response_get_location(response, pool);
+    }
+
   /* Woo-hoo.  Nothing here to see.  */
   if (sl.code == 404 && ctx->ignore_errors == FALSE)
     {
@@ -1702,18 +1720,20 @@ svn_ra_serf__report_resource(const char 
 }
 
 svn_error_t *
-svn_ra_serf__error_on_status(int status_code, const char *path)
+svn_ra_serf__error_on_status(int status_code,
+                             const char *path,
+                             const char *location)
 {
   switch(status_code)
     {
       case 301:
       case 302:
         return svn_error_createf(SVN_ERR_RA_DAV_RELOCATED, NULL,
-                        (status_code == 301)
-                        ? _("Repository moved permanently to '%s';"
-                            " please relocate")
-                        : _("Repository moved temporarily to '%s';"
-                            " please relocate"), path);
+                                 (status_code == 301)
+                                 ? _("Repository moved permanently to '%s';"
+                                     " please relocate")
+                                 : _("Repository moved temporarily to '%s';"
+                                     " please relocate"), location);
       case 404:
         return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL,
                                  _("'%s' path not found"), path);