You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2012/08/16 12:18:03 UTC

svn commit: r1373783 [17/50] - in /subversion/branches/compressed-pristines: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ contrib/client-side/emacs/ contrib/client-side/svn-push/ contrib/client-side/svnmerge/ cont...

Modified: subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/commit.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/commit.c Thu Aug 16 10:17:48 2012
@@ -22,9 +22,6 @@
  */
 
 #include <apr_uri.h>
-
-#include <expat.h>
-
 #include <serf.h>
 
 #include "svn_pools.h"
@@ -45,19 +42,6 @@
 #include "ra_serf.h"
 #include "../libsvn_ra/ra_loader.h"
 
-
-/* Structure associated with a CHECKOUT request. */
-typedef struct checkout_context_t {
-
-  apr_pool_t *pool;
-
-  const char *activity_url;
-  const char *checkout_url;
-  const char *resource_url;
-
-  svn_ra_serf__simple_request_context_t progress;
-
-} checkout_context_t;
 
 /* Baton passed back with the commit editor. */
 typedef struct commit_context_t {
@@ -82,7 +66,7 @@ typedef struct commit_context_t {
 
   /* HTTP v1 stuff (only valid when 'txn_url' is NULL) */
   const char *activity_url;      /* activity base URL... */
-  checkout_context_t *baseline;  /* checkout for the baseline */
+  const char *baseline_url;      /* the working-baseline resource */
   const char *checked_in_url;    /* checked-in root to base CHECKOUTs from */
   const char *vcc_url;           /* vcc url */
 
@@ -110,7 +94,6 @@ typedef struct proppatch_context_t {
   /* In HTTP v2, this is the file/directory version we think we're changing. */
   svn_revnum_t base_revision;
 
-  svn_ra_serf__simple_request_context_t progress;
 } proppatch_context_t;
 
 typedef struct delete_context_t {
@@ -122,7 +105,6 @@ typedef struct delete_context_t {
   apr_hash_t *lock_token_hash;
   svn_boolean_t keep_locks;
 
-  svn_ra_serf__simple_request_context_t progress;
 } delete_context_t;
 
 /* Represents a directory. */
@@ -162,9 +144,9 @@ typedef struct dir_context_t {
   apr_hash_t *changed_props;
   apr_hash_t *removed_props;
 
-  /* The checked out context for this directory.  May be NULL; if so
+  /* The checked-out working resource for this directory.  May be NULL; if so
      call checkout_dir() first.  */
-  checkout_context_t *checkout;
+  const char *working_url;
 
 } dir_context_t;
 
@@ -184,8 +166,8 @@ typedef struct file_context_t {
   const char *relpath;
   const char *name;
 
-  /* The checked out context for this file. */
-  checkout_context_t *checkout;
+  /* The checked-out working resource for this file. */
+  const char *working_url;
 
   /* The base revision of the file. */
   svn_revnum_t base_revision;
@@ -219,24 +201,29 @@ typedef struct file_context_t {
 /* Setup routines and handlers for various requests we'll invoke. */
 
 static svn_error_t *
-return_response_err(svn_ra_serf__handler_t *handler,
-                    svn_ra_serf__simple_request_context_t *ctx)
+return_response_err(svn_ra_serf__handler_t *handler)
 {
   svn_error_t *err;
 
+  /* We should have captured SLINE and LOCATION in the HANDLER.  */
+  SVN_ERR_ASSERT(handler->handler_pool != NULL);
+
   /* Ye Olde Fallback Error */
   err = svn_error_compose_create(
-            ctx->server_error.error,
+            handler->server_error != NULL
+              ? handler->server_error->error
+              : SVN_NO_ERROR,
             svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
                               _("%s of '%s': %d %s"),
                               handler->method, handler->path,
-                              ctx->status, ctx->reason));
+                              handler->sline.code, handler->sline.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,
-                                                               ctx->location),
+  return svn_error_compose_create(svn_ra_serf__error_on_status(
+                                    handler->sline.code,
+                                    handler->path,
+                                    handler->location),
                                   err);
 }
 
@@ -247,7 +234,7 @@ create_checkout_body(serf_bucket_t **bkt
                      serf_bucket_alloc_t *alloc,
                      apr_pool_t *pool)
 {
-  checkout_context_t *ctx = baton;
+  const char *activity_url = baton;
   serf_bucket_t *body_bkt;
 
   body_bkt = serf_bucket_aggregate_create(alloc);
@@ -259,8 +246,10 @@ create_checkout_body(serf_bucket_t **bkt
   svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "D:activity-set", NULL);
   svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "D:href", NULL);
 
+  SVN_ERR_ASSERT(activity_url != NULL);
   svn_ra_serf__add_cdata_len_buckets(body_bkt, alloc,
-                                     ctx->activity_url, strlen(ctx->activity_url));
+                                     activity_url,
+                                     strlen(activity_url));
 
   svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:href");
   svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:activity-set");
@@ -271,59 +260,76 @@ create_checkout_body(serf_bucket_t **bkt
   return SVN_NO_ERROR;
 }
 
-/* Implements svn_ra_serf__response_handler_t */
+
+/* Using the HTTPv1 protocol, perform a CHECKOUT of NODE_URL within the
+   given COMMIT_CTX. The resulting working resource will be returned in
+   *WORKING_URL, allocated from RESULT_POOL. All temporary allocations
+   are performed in SCRATCH_POOL.
+
+   ### are these URLs actually repos relpath values? or fspath? or maybe
+   ### the abspath portion of the full URL.
+
+   This function operates synchronously.
+
+   Strictly speaking, we could perform "all" of the CHECKOUT requests
+   when the commit starts, and only block when we need a specific
+   answer. Or, at a minimum, send off these individual requests async
+   and block when we need the answer (eg PUT or PROPPATCH).
+
+   However: the investment to speed this up is not worthwhile, given
+   that CHECKOUT (and the related round trip) is completely obviated
+   in HTTPv2.
+*/
 static svn_error_t *
-handle_checkout(serf_request_t *request,
-                serf_bucket_t *response,
-                void *handler_baton,
-                apr_pool_t *pool)
+checkout_node(const char **working_url,
+              const commit_context_t *commit_ctx,
+              const char *node_url,
+              apr_pool_t *result_pool,
+              apr_pool_t *scratch_pool)
 {
-  checkout_context_t *ctx = handler_baton;
+  svn_ra_serf__handler_t handler = { 0 };
 
-  svn_error_t *err = svn_ra_serf__handle_status_only(request, response,
-                                                     &ctx->progress, pool);
+  /* HANDLER_POOL is the scratch pool since we don't need to remember
+     anything from the handler. We just want the working resource.  */
+  handler.handler_pool = scratch_pool;
+  handler.session = commit_ctx->session;
+  handler.conn = commit_ctx->conn;
 
-  /* These handler functions are supposed to return an APR_EOF status
-     wrapped in a svn_error_t to indicate to serf that the response was
-     completely read. While we have to return this status code to our
-     caller, we should treat it as the normal case for now. */
-  if (err && ! APR_STATUS_IS_EOF(err->apr_err))
-    return err;
+  handler.body_delegate = create_checkout_body;
+  handler.body_delegate_baton = (/* const */ void *)commit_ctx->activity_url;
+  handler.body_type = "text/xml";
 
-  /* Get the resulting location. */
-  if (ctx->progress.done && ctx->progress.status == 201)
-    {
-      serf_bucket_t *hdrs;
-      apr_uri_t uri;
-      const char *location;
-      apr_status_t status;
+  handler.response_handler = svn_ra_serf__expect_empty_body;
+  handler.response_baton = &handler;
 
-      hdrs = serf_bucket_response_get_headers(response);
-      location = serf_bucket_headers_get(hdrs, "Location");
-      if (!location)
-        return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, err,
-                                _("No Location header received"));
+  handler.method = "CHECKOUT";
+  handler.path = node_url;
 
-      status = apr_uri_parse(pool, location, &uri);
+  SVN_ERR(svn_ra_serf__context_run_one(&handler, scratch_pool));
 
-      if (status)
-        err = svn_error_compose_create(svn_error_wrap_apr(status, NULL), err);
+  if (handler.sline.code != 201)
+    return svn_error_trace(return_response_err(&handler));
 
-      ctx->resource_url = svn_urlpath__canonicalize(uri.path, ctx->pool);
-    }
+  if (handler.location == NULL)
+    return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
+                            _("No Location header received"));
+
+  *working_url = apr_pstrdup(result_pool, handler.location);
 
-  return err;
+  return SVN_NO_ERROR;
 }
 
+
 static svn_error_t *
-checkout_dir(dir_context_t *dir)
+checkout_dir(dir_context_t *dir,
+             apr_pool_t *scratch_pool)
 {
-  checkout_context_t *checkout_ctx;
-  svn_ra_serf__handler_t *handler;
   svn_error_t *err;
   dir_context_t *p_dir = dir;
+  const char *checkout_url;
+  const char **working;
 
-  if (dir->checkout)
+  if (dir->working_url)
     {
       return SVN_NO_ERROR;
     }
@@ -335,73 +341,41 @@ checkout_dir(dir_context_t *dir)
       if (p_dir->added)
         {
           /* Implicitly checkout this dir now. */
-          dir->checkout = apr_pcalloc(dir->pool, sizeof(*dir->checkout));
-          dir->checkout->pool = dir->pool;
-          dir->checkout->progress.pool = dir->pool;
-          dir->checkout->activity_url = dir->commit->activity_url;
-          dir->checkout->resource_url =
-            svn_path_url_add_component2(dir->parent_dir->checkout->resource_url,
-                                        dir->name, dir->pool);
-
+          dir->working_url = svn_path_url_add_component2(
+                                   dir->parent_dir->working_url,
+                                   dir->name, dir->pool);
           return SVN_NO_ERROR;
         }
       p_dir = p_dir->parent_dir;
     }
 
-  /* Checkout our directory into the activity URL now. */
-  handler = apr_pcalloc(dir->pool, sizeof(*handler));
-  handler->session = dir->commit->session;
-  handler->conn = dir->commit->conn;
-
-  checkout_ctx = apr_pcalloc(dir->pool, sizeof(*checkout_ctx));
-  checkout_ctx->pool = dir->pool;
-  checkout_ctx->progress.pool = dir->pool;
-
-  checkout_ctx->activity_url = dir->commit->activity_url;
-
   /* We could be called twice for the root: once to checkout the baseline;
    * once to checkout the directory itself if we need to do so.
+   * Note: CHECKOUT_URL should live longer than HANDLER.
    */
-  if (!dir->parent_dir && !dir->commit->baseline)
+  if (!dir->parent_dir && !dir->commit->baseline_url)
     {
-      checkout_ctx->checkout_url = dir->commit->vcc_url;
-      dir->commit->baseline = checkout_ctx;
+      checkout_url = dir->commit->vcc_url;
+      working = &dir->commit->baseline_url;
     }
   else
     {
-      checkout_ctx->checkout_url = dir->url;
-      dir->checkout = checkout_ctx;
+      checkout_url = dir->url;
+      working = &dir->working_url;
     }
 
-  handler->body_delegate = create_checkout_body;
-  handler->body_delegate_baton = checkout_ctx;
-  handler->body_type = "text/xml";
-
-  handler->response_handler = handle_checkout;
-  handler->response_baton = checkout_ctx;
-
-  handler->method = "CHECKOUT";
-  handler->path = checkout_ctx->checkout_url;
-
-  svn_ra_serf__request_create(handler);
-
-  err = svn_ra_serf__context_run_wait(&checkout_ctx->progress.done,
-                                      dir->commit->session,
-                                      dir->pool);
+  /* Checkout our directory into the activity URL now. */
+  err = checkout_node(working, dir->commit, checkout_url,
+                      dir->pool, scratch_pool);
   if (err)
     {
       if (err->apr_err == SVN_ERR_FS_CONFLICT)
-        SVN_ERR_W(err, apr_psprintf(dir->pool,
+        SVN_ERR_W(err, apr_psprintf(scratch_pool,
                   _("Directory '%s' is out of date; try updating"),
-                  svn_dirent_local_style(dir->relpath, dir->pool)));
+                  svn_dirent_local_style(dir->relpath, scratch_pool)));
       return err;
     }
 
-  if (checkout_ctx->progress.status != 201)
-    {
-      return return_response_err(handler, &checkout_ctx->progress);
-    }
-
   return SVN_NO_ERROR;
 }
 
@@ -419,16 +393,17 @@ checkout_dir(dir_context_t *dir)
  * BASE_REVISION, and set *CHECKED_IN_URL to the concatenation of that
  * with RELPATH.
  *
- * Allocate the result in POOL, and use POOL for temporary allocation.
+ * Allocate the result in RESULT_POOL, and use SCRATCH_POOL for
+ * temporary allocation.
  */
 static svn_error_t *
 get_version_url(const char **checked_in_url,
                 svn_ra_serf__session_t *session,
-                svn_ra_serf__connection_t *conn,
                 const char *relpath,
                 svn_revnum_t base_revision,
                 const char *parent_vsn_url,
-                apr_pool_t *pool)
+                apr_pool_t *result_pool,
+                apr_pool_t *scratch_pool)
 {
   const char *root_checkout;
 
@@ -436,15 +411,16 @@ get_version_url(const char **checked_in_
     {
       const svn_string_t *current_version;
 
-      SVN_ERR(session->wc_callbacks->get_wc_prop(session->wc_callback_baton,
-                                                 relpath,
-                                                 SVN_RA_SERF__WC_CHECKED_IN_URL,
-                                                 &current_version, pool));
+      SVN_ERR(session->wc_callbacks->get_wc_prop(
+                session->wc_callback_baton,
+                relpath,
+                SVN_RA_SERF__WC_CHECKED_IN_URL,
+                &current_version, scratch_pool));
 
       if (current_version)
         {
           *checked_in_url =
-            svn_urlpath__canonicalize(current_version->data, pool);
+            svn_urlpath__canonicalize(current_version->data, result_pool);
           return SVN_NO_ERROR;
         }
     }
@@ -455,63 +431,53 @@ get_version_url(const char **checked_in_
     }
   else
     {
-      svn_ra_serf__propfind_context_t *propfind_ctx;
-      apr_hash_t *props;
       const char *propfind_url;
-
-      props = apr_hash_make(pool);
+      svn_ra_serf__connection_t *conn = session->conns[0];
 
       if (SVN_IS_VALID_REVNUM(base_revision))
         {
-          const char *bc_url, *bc_relpath;
-
           /* mod_dav_svn can't handle the "Label:" header that
              svn_ra_serf__deliver_props() is going to try to use for
              this lookup, so we'll do things the hard(er) way, by
              looking up the version URL from a resource in the
              baseline collection. */
-          SVN_ERR(svn_ra_serf__get_baseline_info(&bc_url, &bc_relpath,
-                                                 session, conn,
-                                                 session->session_url.path,
-                                                 base_revision, NULL, pool));
-          propfind_url = svn_path_url_add_component2(bc_url, bc_relpath, pool);
+          /* ### conn==NULL for session->conns[0]. same as CONN.  */
+          SVN_ERR(svn_ra_serf__get_stable_url(&propfind_url,
+                                              NULL /* latest_revnum */,
+                                              session, NULL /* conn */,
+                                              NULL /* url */, base_revision,
+                                              scratch_pool, scratch_pool));
         }
       else
         {
           propfind_url = session->session_url.path;
         }
 
-      /* ### switch to svn_ra_serf__retrieve_props  */
-      SVN_ERR(svn_ra_serf__deliver_props(&propfind_ctx, props, session, conn,
-                                         propfind_url, base_revision, "0",
-                                         checked_in_props, NULL, pool));
-      SVN_ERR(svn_ra_serf__wait_for_props(propfind_ctx, session, pool));
-
-      /* We wouldn't get here if the url wasn't found (404), so the checked-in
-         property should have been set. */
-      root_checkout =
-          svn_ra_serf__get_ver_prop(props, propfind_url,
-                                    base_revision, "DAV:", "checked-in");
-
+      SVN_ERR(svn_ra_serf__fetch_dav_prop(&root_checkout,
+                                          conn, propfind_url, base_revision,
+                                          "checked-in",
+                                          scratch_pool, scratch_pool));
       if (!root_checkout)
         return svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
                                  _("Path '%s' not present"),
                                  session->session_url.path);
 
-      root_checkout = svn_urlpath__canonicalize(root_checkout, pool);
+      root_checkout = svn_urlpath__canonicalize(root_checkout, scratch_pool);
     }
 
-  *checked_in_url = svn_path_url_add_component2(root_checkout, relpath, pool);
+  *checked_in_url = svn_path_url_add_component2(root_checkout, relpath,
+                                                result_pool);
 
   return SVN_NO_ERROR;
 }
 
 static svn_error_t *
-checkout_file(file_context_t *file)
+checkout_file(file_context_t *file,
+              apr_pool_t *scratch_pool)
 {
-  svn_ra_serf__handler_t *handler;
   svn_error_t *err;
   dir_context_t *parent_dir = file->parent_dir;
+  const char *checkout_url;
 
   /* Is one of our parent dirs newly added?  If so, we're already
    * implicitly checked out.
@@ -521,68 +487,33 @@ checkout_file(file_context_t *file)
       if (parent_dir->added)
         {
           /* Implicitly checkout this file now. */
-          file->checkout = apr_pcalloc(file->pool, sizeof(*file->checkout));
-          file->checkout->pool = file->pool;
-          file->checkout->progress.pool = file->pool;
-          file->checkout->activity_url = file->commit->activity_url;
-          file->checkout->resource_url =
-            svn_path_url_add_component2(parent_dir->checkout->resource_url,
-                                        svn_relpath_skip_ancestor(
-                                          parent_dir->relpath, file->relpath),
-                                        file->pool);
+          file->working_url = svn_path_url_add_component2(
+                                    parent_dir->working_url,
+                                    svn_relpath_skip_ancestor(
+                                      parent_dir->relpath, file->relpath),
+                                    file->pool);
           return SVN_NO_ERROR;
         }
       parent_dir = parent_dir->parent_dir;
     }
 
-  /* Checkout our file into the activity URL now. */
-  handler = apr_pcalloc(file->pool, sizeof(*handler));
-  handler->session = file->commit->session;
-  handler->conn = file->commit->conn;
-
-  file->checkout = apr_pcalloc(file->pool, sizeof(*file->checkout));
-  file->checkout->pool = file->pool;
-  file->checkout->progress.pool = file->pool;
-
-  file->checkout->activity_url = file->commit->activity_url;
-
-  SVN_ERR(get_version_url(&(file->checkout->checkout_url),
-                          file->commit->session, file->commit->conn,
+  SVN_ERR(get_version_url(&checkout_url,
+                          file->commit->session,
                           file->relpath, file->base_revision,
-                          NULL, file->pool));
+                          NULL, scratch_pool, scratch_pool));
 
-  handler->body_delegate = create_checkout_body;
-  handler->body_delegate_baton = file->checkout;
-  handler->body_type = "text/xml";
-
-  handler->response_handler = handle_checkout;
-  handler->response_baton = file->checkout;
-
-  handler->method = "CHECKOUT";
-  handler->path = file->checkout->checkout_url;
-
-  svn_ra_serf__request_create(handler);
-
-  /* There's no need to wait here as we only need this when we start the
-   * PROPPATCH or PUT of the file.
-   */
-  err = svn_ra_serf__context_run_wait(&file->checkout->progress.done,
-                                      file->commit->session,
-                                      file->pool);
+  /* Checkout our file into the activity URL now. */
+  err = checkout_node(&file->working_url, file->commit, checkout_url,
+                      file->pool, scratch_pool);
   if (err)
     {
       if (err->apr_err == SVN_ERR_FS_CONFLICT)
-        SVN_ERR_W(err, apr_psprintf(file->pool,
+        SVN_ERR_W(err, apr_psprintf(scratch_pool,
                   _("File '%s' is out of date; try updating"),
-                  svn_dirent_local_style(file->relpath, file->pool)));
+                  svn_dirent_local_style(file->relpath, scratch_pool)));
       return err;
     }
 
-  if (file->checkout->progress.status != 201)
-    {
-      return return_response_err(handler, &file->checkout->progress);
-    }
-
   return SVN_NO_ERROR;
 }
 
@@ -920,6 +851,7 @@ proppatch_resource(proppatch_context_t *
   struct proppatch_body_baton_t pbb;
 
   handler = apr_pcalloc(pool, sizeof(*handler));
+  handler->handler_pool = pool;
   handler->method = "PROPPATCH";
   handler->path = proppatch->path;
   handler->conn = commit->conn;
@@ -934,20 +866,19 @@ proppatch_resource(proppatch_context_t *
   handler->body_delegate_baton = &pbb;
 
   handler->response_handler = svn_ra_serf__handle_multistatus_only;
-  handler->response_baton = &proppatch->progress;
-
-  svn_ra_serf__request_create(handler);
+  handler->response_baton = handler;
 
-  /* If we don't wait for the response, our pool will be gone! */
-  SVN_ERR(svn_ra_serf__context_run_wait(&proppatch->progress.done,
-                                        commit->session, pool));
+  SVN_ERR(svn_ra_serf__context_run_one(handler, pool));
 
-  if (proppatch->progress.status != 207 ||
-      proppatch->progress.server_error.error)
-    {
-      return svn_error_create(SVN_ERR_RA_DAV_PROPPATCH_FAILED,
-        return_response_err(handler, &proppatch->progress),
-        _("At least one property change failed; repository is unchanged"));
+  if (handler->sline.code != 207
+      || (handler->server_error != NULL
+          && handler->server_error->error != NULL))
+    {
+      return svn_error_create(
+               SVN_ERR_RA_DAV_PROPPATCH_FAILED,
+               return_response_err(handler),
+               _("At least one property change failed; repository"
+                 " is unchanged"));
     }
 
   return SVN_NO_ERROR;
@@ -1055,8 +986,8 @@ setup_copy_file_headers(serf_bucket_t *h
 
   serf_bucket_headers_set(headers, "Destination", absolute_uri);
 
-  serf_bucket_headers_set(headers, "Depth", "0");
-  serf_bucket_headers_set(headers, "Overwrite", "T");
+  serf_bucket_headers_setn(headers, "Depth", "0");
+  serf_bucket_headers_setn(headers, "Overwrite", "T");
 
   return SVN_NO_ERROR;
 }
@@ -1080,22 +1011,18 @@ setup_copy_dir_headers(serf_bucket_t *he
   else
     {
       uri.path = (char *)svn_path_url_add_component2(
-                                    dir->parent_dir->checkout->resource_url,
+                                    dir->parent_dir->working_url,
                                     dir->name, pool);
     }
   absolute_uri = apr_uri_unparse(pool, &uri, 0);
 
   serf_bucket_headers_set(headers, "Destination", absolute_uri);
 
-  serf_bucket_headers_set(headers, "Depth", "infinity");
-  serf_bucket_headers_set(headers, "Overwrite", "T");
+  serf_bucket_headers_setn(headers, "Depth", "infinity");
+  serf_bucket_headers_setn(headers, "Overwrite", "T");
 
   /* Implicitly checkout this dir now. */
-  dir->checkout = apr_pcalloc(dir->pool, sizeof(*dir->checkout));
-  dir->checkout->pool = dir->pool;
-  dir->checkout->progress.pool = dir->pool;
-  dir->checkout->activity_url = dir->commit->activity_url;
-  dir->checkout->resource_url = apr_pstrdup(dir->checkout->pool, uri.path);
+  dir->working_url = apr_pstrdup(dir->pool, uri.path);
 
   return SVN_NO_ERROR;
 }
@@ -1125,8 +1052,8 @@ setup_delete_headers(serf_bucket_t *head
           serf_bucket_headers_set(headers, "If", token_header);
 
           if (ctx->keep_locks)
-            serf_bucket_headers_set(headers, SVN_DAV_OPTIONS_HEADER,
-                                    SVN_DAV_OPTION_KEEP_LOCKS);
+            serf_bucket_headers_setn(headers, SVN_DAV_OPTIONS_HEADER,
+                                     SVN_DAV_OPTION_KEEP_LOCKS);
         }
     }
 
@@ -1205,7 +1132,7 @@ setup_post_headers(serf_bucket_t *header
 /* Handler baton for POST request. */
 typedef struct post_response_ctx_t
 {
-  svn_ra_serf__simple_request_context_t *request_ctx;
+  svn_ra_serf__handler_t *handler;
   commit_context_t *commit_ctx;
 } post_response_ctx_t;
 
@@ -1250,14 +1177,15 @@ post_headers_iterator_callback(void *bat
 
 
 /* A custom serf_response_handler_t which is mostly a wrapper around
-   svn_ra_serf__handle_status_only -- it just notices POST response
+   svn_ra_serf__expect_empty_body -- it just notices POST response
    headers, too.
+
    Implements svn_ra_serf__response_handler_t */
 static svn_error_t *
 post_response_handler(serf_request_t *request,
                       serf_bucket_t *response,
                       void *baton,
-                      apr_pool_t *pool)
+                      apr_pool_t *scratch_pool)
 {
   post_response_ctx_t *prc = baton;
   serf_bucket_t *hdrs = serf_bucket_response_get_headers(response);
@@ -1266,8 +1194,8 @@ post_response_handler(serf_request_t *re
   serf_bucket_headers_do(hdrs, post_headers_iterator_callback, prc);
 
   /* Execute the 'real' response handler to XML-parse the repsonse body. */
-  return svn_ra_serf__handle_status_only(request, response,
-                                         prc->request_ctx, pool);
+  return svn_ra_serf__expect_empty_body(request, response,
+                                        prc->handler, scratch_pool);
 }
 
 
@@ -1289,12 +1217,12 @@ open_root(void *edit_baton,
 
   if (SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(ctx->session))
     {
-      svn_ra_serf__simple_request_context_t *post_ctx;
       post_response_ctx_t *prc;
       const char *rel_path;
 
       /* Create our activity URL now on the server. */
       handler = apr_pcalloc(ctx->pool, sizeof(*handler));
+      handler->handler_pool = ctx->pool;
       handler->method = "POST";
       handler->body_type = SVN_SKEL_MIME_TYPE;
       handler->body_delegate = create_txn_post_body;
@@ -1305,25 +1233,20 @@ open_root(void *edit_baton,
       handler->conn = ctx->session->conns[0];
       handler->session = ctx->session;
 
-      post_ctx = apr_pcalloc(ctx->pool, sizeof(*post_ctx));
-      post_ctx->pool = ctx->pool;
-
       prc = apr_pcalloc(ctx->pool, sizeof(*prc));
-      prc->request_ctx = post_ctx;
+      prc->handler = handler;
       prc->commit_ctx = ctx;
 
       handler->response_handler = post_response_handler;
       handler->response_baton = prc;
 
-      svn_ra_serf__request_create(handler);
+      SVN_ERR(svn_ra_serf__context_run_one(handler, ctx->pool));
 
-      SVN_ERR(svn_ra_serf__context_run_wait(&post_ctx->done, ctx->session,
-                                            ctx->pool));
-
-      if (post_ctx->status != 201)
+      if (handler->sline.code != 201)
         {
           apr_status_t status = SVN_ERR_RA_DAV_REQUEST_FAILED;
-          switch(post_ctx->status)
+
+          switch (handler->sline.code)
             {
               case 403:
                 status = SVN_ERR_RA_DAV_FORBIDDEN;
@@ -1336,7 +1259,7 @@ open_root(void *edit_baton,
           return svn_error_createf(status, NULL,
                                    _("%s of '%s': %d %s (%s://%s)"),
                                    handler->method, handler->path,
-                                   post_ctx->status, post_ctx->reason,
+                                   handler->sline.code, handler->sline.reason,
                                    ctx->session->session_url.scheme,
                                    ctx->session->session_url.hostinfo);
         }
@@ -1369,20 +1292,12 @@ open_root(void *edit_baton,
     }
   else
     {
-      svn_ra_serf__options_context_t *opt_ctx;
-      svn_ra_serf__simple_request_context_t *mkact_ctx;
       const char *activity_str;
 
-      SVN_ERR(svn_ra_serf__create_options_req(&opt_ctx, ctx->session,
-                                              ctx->session->conns[0],
-                                              ctx->session->session_url.path,
-                                              ctx->pool));
-
-      SVN_ERR(svn_ra_serf__context_run_wait(
-        svn_ra_serf__get_options_done_ptr(opt_ctx),
-        ctx->session, ctx->pool));
-
-      activity_str = svn_ra_serf__options_get_activity_collection(opt_ctx);
+      SVN_ERR(svn_ra_serf__v1_get_activity_collection(&activity_str,
+                                                      ctx->session->conns[0],
+                                                      ctx->pool,
+                                                      ctx->pool));
       if (!activity_str)
         return svn_error_create(SVN_ERR_RA_DAV_OPTIONS_REQ_FAILED, NULL,
                                 _("The OPTIONS response did not include the "
@@ -1394,26 +1309,22 @@ open_root(void *edit_baton,
 
       /* Create our activity URL now on the server. */
       handler = apr_pcalloc(ctx->pool, sizeof(*handler));
+      handler->handler_pool = ctx->pool;
       handler->method = "MKACTIVITY";
       handler->path = ctx->activity_url;
       handler->conn = ctx->session->conns[0];
       handler->session = ctx->session;
 
-      mkact_ctx = apr_pcalloc(ctx->pool, sizeof(*mkact_ctx));
-      mkact_ctx->pool = ctx->pool;
+      handler->response_handler = svn_ra_serf__expect_empty_body;
+      handler->response_baton = handler;
 
-      handler->response_handler = svn_ra_serf__handle_status_only;
-      handler->response_baton = mkact_ctx;
+      SVN_ERR(svn_ra_serf__context_run_one(handler, ctx->pool));
 
-      svn_ra_serf__request_create(handler);
-
-      SVN_ERR(svn_ra_serf__context_run_wait(&mkact_ctx->done, ctx->session,
-                                            ctx->pool));
-
-      if (mkact_ctx->status != 201)
+      if (handler->sline.code != 201)
         {
           apr_status_t status = SVN_ERR_RA_DAV_REQUEST_FAILED;
-          switch(mkact_ctx->status)
+
+          switch (handler->sline.code)
             {
               case 403:
                 status = SVN_ERR_RA_DAV_FORBIDDEN;
@@ -1426,7 +1337,7 @@ open_root(void *edit_baton,
           return svn_error_createf(status, NULL,
                                    _("%s of '%s': %d %s (%s://%s)"),
                                    handler->method, handler->path,
-                                   mkact_ctx->status, mkact_ctx->reason,
+                                   handler->sline.code, handler->sline.reason,
                                    ctx->session->session_url.scheme,
                                    ctx->session->session_url.hostinfo);
         }
@@ -1447,22 +1358,21 @@ open_root(void *edit_baton,
       dir->removed_props = apr_hash_make(dir->pool);
 
       SVN_ERR(get_version_url(&dir->url, dir->commit->session,
-                              dir->commit->conn, dir->relpath,
+                              dir->relpath,
                               dir->base_revision, ctx->checked_in_url,
-                              dir->pool));
+                              dir->pool, dir->pool /* scratch_pool */));
       ctx->checked_in_url = dir->url;
 
       /* Checkout our root dir */
-      SVN_ERR(checkout_dir(dir));
+      SVN_ERR(checkout_dir(dir, dir->pool /* scratch_pool */));
 
-      proppatch_target = ctx->baseline->resource_url;
+      proppatch_target = ctx->baseline_url;
     }
 
 
   /* PROPPATCH our revprops and pass them along.  */
   proppatch_ctx = apr_pcalloc(ctx->pool, sizeof(*proppatch_ctx));
   proppatch_ctx->pool = dir_pool;
-  proppatch_ctx->progress.pool = dir_pool;
   proppatch_ctx->commit = ctx;
   proppatch_ctx->path = proppatch_target;
   proppatch_ctx->changed_props = apr_hash_make(proppatch_ctx->pool);
@@ -1523,8 +1433,8 @@ delete_entry(const char *path,
   else
     {
       /* Ensure our directory has been checked out */
-      SVN_ERR(checkout_dir(dir));
-      delete_target = svn_path_url_add_component2(dir->checkout->resource_url,
+      SVN_ERR(checkout_dir(dir, pool /* scratch_pool */));
+      delete_target = svn_path_url_add_component2(dir->working_url,
                                                   svn_relpath_basename(path,
                                                                        NULL),
                                                   pool);
@@ -1532,18 +1442,18 @@ delete_entry(const char *path,
 
   /* DELETE our entry */
   delete_ctx = apr_pcalloc(pool, sizeof(*delete_ctx));
-  delete_ctx->progress.pool = pool;
   delete_ctx->path = apr_pstrdup(pool, path);
   delete_ctx->revision = revision;
   delete_ctx->lock_token_hash = dir->commit->lock_tokens;
   delete_ctx->keep_locks = dir->commit->keep_locks;
 
   handler = apr_pcalloc(pool, sizeof(*handler));
+  handler->handler_pool = pool;
   handler->session = dir->commit->session;
   handler->conn = dir->commit->conn;
 
-  handler->response_handler = svn_ra_serf__handle_status_only;
-  handler->response_baton = &delete_ctx->progress;
+  handler->response_handler = svn_ra_serf__expect_empty_body;
+  handler->response_baton = handler;
 
   handler->header_delegate = setup_delete_headers;
   handler->header_delegate_baton = delete_ctx;
@@ -1551,10 +1461,7 @@ delete_entry(const char *path,
   handler->method = "DELETE";
   handler->path = delete_target;
 
-  svn_ra_serf__request_create(handler);
-
-  err = svn_ra_serf__context_run_wait(&delete_ctx->progress.done,
-                                      dir->commit->session, pool);
+  err = svn_ra_serf__context_run_one(handler, pool);
 
   if (err &&
       (err->apr_err == SVN_ERR_FS_BAD_LOCK_TOKEN ||
@@ -1572,12 +1479,7 @@ delete_entry(const char *path,
       handler->body_delegate_baton = delete_ctx;
       handler->body_type = "text/xml";
 
-      svn_ra_serf__request_create(handler);
-
-      delete_ctx->progress.done = 0;
-
-      SVN_ERR(svn_ra_serf__context_run_wait(&delete_ctx->progress.done,
-                                            dir->commit->session, pool));
+      SVN_ERR(svn_ra_serf__context_run_one(handler, pool));
     }
   else if (err)
     {
@@ -1585,9 +1487,9 @@ delete_entry(const char *path,
     }
 
   /* 204 No Content: item successfully deleted */
-  if (delete_ctx->progress.status != 204)
+  if (handler->sline.code != 204)
     {
-      return return_response_err(handler, &delete_ctx->progress);
+      return svn_error_trace(return_response_err(handler));
     }
 
   apr_hash_set(dir->commit->deleted_entries,
@@ -1608,7 +1510,6 @@ add_directory(const char *path,
   dir_context_t *parent = parent_baton;
   dir_context_t *dir;
   svn_ra_serf__handler_t *handler;
-  svn_ra_serf__simple_request_context_t *add_dir_ctx;
   apr_status_t status;
   const char *mkcol_target;
 
@@ -1635,24 +1536,22 @@ add_directory(const char *path,
   else
     {
       /* Ensure our parent is checked out. */
-      SVN_ERR(checkout_dir(parent));
+      SVN_ERR(checkout_dir(parent, dir->pool /* scratch_pool */));
 
       dir->url = svn_path_url_add_component2(parent->commit->checked_in_url,
                                              dir->name, dir->pool);
       mkcol_target = svn_path_url_add_component2(
-                               parent->checkout->resource_url,
+                               parent->working_url,
                                dir->name, dir->pool);
     }
 
   handler = apr_pcalloc(dir->pool, sizeof(*handler));
+  handler->handler_pool = dir->pool;
   handler->conn = dir->commit->conn;
   handler->session = dir->commit->session;
 
-  add_dir_ctx = apr_pcalloc(dir->pool, sizeof(*add_dir_ctx));
-  add_dir_ctx->pool = dir->pool;
-
-  handler->response_handler = svn_ra_serf__handle_status_only;
-  handler->response_baton = add_dir_ctx;
+  handler->response_handler = svn_ra_serf__expect_empty_body;
+  handler->response_baton = handler;
   if (!dir->copy_path)
     {
       handler->method = "MKCOL";
@@ -1661,7 +1560,7 @@ add_directory(const char *path,
   else
     {
       apr_uri_t uri;
-      const char *rel_copy_path, *basecoll_url, *req_url;
+      const char *req_url;
 
       status = apr_uri_parse(dir->pool, dir->copy_path, &uri);
       if (status)
@@ -1671,13 +1570,12 @@ add_directory(const char *path,
                                    dir->copy_path);
         }
 
-      SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &rel_copy_path,
-                                             dir->commit->session,
-                                             dir->commit->conn,
-                                             uri.path, dir->copy_revision,
-                                             NULL, dir_pool));
-      req_url = svn_path_url_add_component2(basecoll_url, rel_copy_path,
-                                            dir->pool);
+      /* ### conn==NULL for session->conns[0]. same as commit->conn.  */
+      SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */,
+                                          dir->commit->session,
+                                          NULL /* conn */,
+                                          uri.path, dir->copy_revision,
+                                          dir_pool, dir_pool));
 
       handler->method = "COPY";
       handler->path = req_url;
@@ -1686,29 +1584,24 @@ add_directory(const char *path,
       handler->header_delegate_baton = dir;
     }
 
-  svn_ra_serf__request_create(handler);
-
-  SVN_ERR(svn_ra_serf__context_run_wait(&add_dir_ctx->done,
-                                        dir->commit->session, dir->pool));
+  SVN_ERR(svn_ra_serf__context_run_one(handler, dir->pool));
 
-  switch (add_dir_ctx->status)
+  switch (handler->sline.code)
     {
       case 201: /* Created:    item was successfully copied */
       case 204: /* No Content: item successfully replaced an existing target */
         break;
 
       case 403:
-        SVN_ERR(add_dir_ctx->server_error.error);
         return svn_error_createf(SVN_ERR_RA_DAV_FORBIDDEN, NULL,
                                 _("Access to '%s' forbidden"),
                                  handler->path);
       default:
-        SVN_ERR(add_dir_ctx->server_error.error);
         return svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
                                  _("Adding directory failed: %s on %s "
                                    "(%d %s)"),
                                  handler->method, handler->path,
-                                 add_dir_ctx->status, add_dir_ctx->reason);
+                                 handler->sline.code, handler->sline.reason);
     }
 
   *child_baton = dir;
@@ -1748,9 +1641,10 @@ open_directory(const char *path,
   else
     {
       SVN_ERR(get_version_url(&dir->url,
-                              dir->commit->session, dir->commit->conn,
+                              dir->commit->session,
                               dir->relpath, dir->base_revision,
-                              dir->commit->checked_in_url, dir->pool));
+                              dir->commit->checked_in_url,
+                              dir->pool, dir->pool /* scratch_pool */));
     }
   *child_baton = dir;
 
@@ -1775,9 +1669,9 @@ change_dir_prop(void *dir_baton,
   else
     {
       /* Ensure we have a checked out dir. */
-      SVN_ERR(checkout_dir(dir));
+      SVN_ERR(checkout_dir(dir, pool /* scratch_pool */));
 
-      proppatch_target = dir->checkout->resource_url;
+      proppatch_target = dir->working_url;
     }
 
   name = apr_pstrdup(dir->pool, name);
@@ -1825,7 +1719,6 @@ close_directory(void *dir_baton,
 
       proppatch_ctx = apr_pcalloc(pool, sizeof(*proppatch_ctx));
       proppatch_ctx->pool = pool;
-      proppatch_ctx->progress.pool = pool;
       proppatch_ctx->commit = dir->commit;
       proppatch_ctx->relpath = dir->relpath;
       proppatch_ctx->changed_props = dir->changed_props;
@@ -1838,7 +1731,7 @@ close_directory(void *dir_baton,
         }
       else
         {
-          proppatch_ctx->path = dir->checkout->resource_url;
+          proppatch_ctx->path = dir->working_url;
         }
 
       SVN_ERR(proppatch_resource(proppatch_ctx, dir->commit, dir->pool));
@@ -1886,10 +1779,10 @@ add_file(const char *path,
   else
     {
       /* Ensure our parent directory has been checked out */
-      SVN_ERR(checkout_dir(dir));
+      SVN_ERR(checkout_dir(dir, new_file->pool /* scratch_pool */));
 
       new_file->url =
-        svn_path_url_add_component2(dir->checkout->resource_url,
+        svn_path_url_add_component2(dir->working_url,
                                     new_file->name, new_file->pool);
     }
 
@@ -1906,28 +1799,22 @@ add_file(const char *path,
   if (! ((dir->added && !dir->copy_path) ||
          (deleted_parent && deleted_parent[0] != '\0')))
     {
-      svn_ra_serf__simple_request_context_t *head_ctx;
       svn_ra_serf__handler_t *handler;
 
-      head_ctx = apr_pcalloc(new_file->pool, sizeof(*head_ctx));
-      head_ctx->pool = new_file->pool;
-
       handler = apr_pcalloc(new_file->pool, sizeof(*handler));
+      handler->handler_pool = new_file->pool;
       handler->session = new_file->commit->session;
       handler->conn = new_file->commit->conn;
       handler->method = "HEAD";
       handler->path = svn_path_url_add_component2(
         dir->commit->session->session_url.path,
         path, new_file->pool);
-      handler->response_handler = svn_ra_serf__handle_status_only;
-      handler->response_baton = head_ctx;
-      svn_ra_serf__request_create(handler);
-
-      SVN_ERR(svn_ra_serf__context_run_wait(&head_ctx->done,
-                                            new_file->commit->session,
-                                            new_file->pool));
+      handler->response_handler = svn_ra_serf__expect_empty_body;
+      handler->response_baton = handler;
+
+      SVN_ERR(svn_ra_serf__context_run_one(handler, new_file->pool));
 
-      if (head_ctx->status != 404)
+      if (handler->sline.code != 404)
         {
           return svn_error_createf(SVN_ERR_RA_DAV_ALREADY_EXISTS, NULL,
                                    _("File '%s' already exists"), path);
@@ -1971,9 +1858,9 @@ open_file(const char *path,
   else
     {
       /* CHECKOUT the file into our activity. */
-      SVN_ERR(checkout_file(new_file));
+      SVN_ERR(checkout_file(new_file, new_file->pool /* scratch_pool */));
 
-      new_file->url = new_file->checkout->resource_url;
+      new_file->url = new_file->working_url;
     }
 
   *file_baton = new_file;
@@ -2059,7 +1946,7 @@ change_file_prop(void *file_baton,
 static svn_error_t *
 close_file(void *file_baton,
            const char *text_checksum,
-           apr_pool_t *pool)
+           apr_pool_t *scratch_pool)
 {
   file_context_t *ctx = file_baton;
   svn_boolean_t put_empty_file = FALSE;
@@ -2070,11 +1957,10 @@ close_file(void *file_baton,
   if (ctx->copy_path)
     {
       svn_ra_serf__handler_t *handler;
-      svn_ra_serf__simple_request_context_t *copy_ctx;
       apr_uri_t uri;
-      const char *rel_copy_path, *basecoll_url, *req_url;
+      const char *req_url;
 
-      status = apr_uri_parse(pool, ctx->copy_path, &uri);
+      status = apr_uri_parse(scratch_pool, ctx->copy_path, &uri);
       if (status)
         {
           return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
@@ -2082,36 +1968,31 @@ close_file(void *file_baton,
                                    ctx->copy_path);
         }
 
-      SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &rel_copy_path,
-                                             ctx->commit->session,
-                                             ctx->commit->conn,
-                                             uri.path, ctx->copy_revision,
-                                             NULL, pool));
-      req_url = svn_path_url_add_component2(basecoll_url, rel_copy_path, pool);
+      /* ### conn==NULL for session->conns[0]. same as commit->conn.  */
+      SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */,
+                                          ctx->commit->session,
+                                          NULL /* conn */,
+                                          uri.path, ctx->copy_revision,
+                                          scratch_pool, scratch_pool));
 
-      handler = apr_pcalloc(pool, sizeof(*handler));
+      handler = apr_pcalloc(scratch_pool, sizeof(*handler));
+      handler->handler_pool = scratch_pool;
       handler->method = "COPY";
       handler->path = req_url;
       handler->conn = ctx->commit->conn;
       handler->session = ctx->commit->session;
 
-      copy_ctx = apr_pcalloc(pool, sizeof(*copy_ctx));
-      copy_ctx->pool = pool;
-
-      handler->response_handler = svn_ra_serf__handle_status_only;
-      handler->response_baton = copy_ctx;
+      handler->response_handler = svn_ra_serf__expect_empty_body;
+      handler->response_baton = handler;
 
       handler->header_delegate = setup_copy_file_headers;
       handler->header_delegate_baton = ctx;
 
-      svn_ra_serf__request_create(handler);
+      SVN_ERR(svn_ra_serf__context_run_one(handler, scratch_pool));
 
-      SVN_ERR(svn_ra_serf__context_run_wait(&copy_ctx->done,
-                                            ctx->commit->session, pool));
-
-      if (copy_ctx->status != 201 && copy_ctx->status != 204)
+      if (handler->sline.code != 201 && handler->sline.code != 204)
         {
-          return return_response_err(handler, copy_ctx);
+          return svn_error_trace(return_response_err(handler));
         }
     }
 
@@ -2125,19 +2006,16 @@ close_file(void *file_baton,
   if (ctx->stream || put_empty_file)
     {
       svn_ra_serf__handler_t *handler;
-      svn_ra_serf__simple_request_context_t *put_ctx;
 
-      handler = apr_pcalloc(pool, sizeof(*handler));
+      handler = apr_pcalloc(scratch_pool, sizeof(*handler));
+      handler->handler_pool = scratch_pool;
       handler->method = "PUT";
       handler->path = ctx->url;
       handler->conn = ctx->commit->conn;
       handler->session = ctx->commit->session;
 
-      put_ctx = apr_pcalloc(pool, sizeof(*put_ctx));
-      put_ctx->pool = pool;
-
-      handler->response_handler = svn_ra_serf__handle_status_only;
-      handler->response_baton = put_ctx;
+      handler->response_handler = svn_ra_serf__expect_empty_body;
+      handler->response_baton = handler;
 
       if (put_empty_file)
         {
@@ -2155,19 +2033,16 @@ close_file(void *file_baton,
       handler->header_delegate = setup_put_headers;
       handler->header_delegate_baton = ctx;
 
-      svn_ra_serf__request_create(handler);
+      SVN_ERR(svn_ra_serf__context_run_one(handler, scratch_pool));
 
-      SVN_ERR(svn_ra_serf__context_run_wait(&put_ctx->done,
-                                            ctx->commit->session, pool));
-
-      if (put_ctx->status != 204 && put_ctx->status != 201)
+      if (handler->sline.code != 204 && handler->sline.code != 201)
         {
-          return return_response_err(handler, put_ctx);
+          return svn_error_trace(return_response_err(handler));
         }
     }
 
   if (ctx->svndiff)
-    SVN_ERR(svn_io_file_close(ctx->svndiff, pool));
+    SVN_ERR(svn_io_file_close(ctx->svndiff, scratch_pool));
 
   /* If we had any prop changes, push them via PROPPATCH. */
   if (apr_hash_count(ctx->changed_props) ||
@@ -2177,7 +2052,6 @@ close_file(void *file_baton,
 
       proppatch = apr_pcalloc(ctx->pool, sizeof(*proppatch));
       proppatch->pool = ctx->pool;
-      proppatch->progress.pool = pool;
       proppatch->relpath = ctx->relpath;
       proppatch->path = ctx->url;
       proppatch->commit = ctx->commit;
@@ -2196,59 +2070,50 @@ close_edit(void *edit_baton,
            apr_pool_t *pool)
 {
   commit_context_t *ctx = edit_baton;
-  svn_ra_serf__merge_context_t *merge_ctx;
-  svn_ra_serf__simple_request_context_t *delete_ctx;
-  svn_ra_serf__handler_t *handler;
-  svn_boolean_t *merge_done;
   const char *merge_target =
     ctx->activity_url ? ctx->activity_url : ctx->txn_url;
+  const svn_commit_info_t *commit_info;
+  int response_code;
 
   /* MERGE our activity */
-  SVN_ERR(svn_ra_serf__merge_create_req(&merge_ctx, ctx->session,
-                                        ctx->session->conns[0],
-                                        merge_target,
-                                        ctx->lock_tokens,
-                                        ctx->keep_locks,
-                                        pool));
-
-  merge_done = svn_ra_serf__merge_get_done_ptr(merge_ctx);
+  SVN_ERR(svn_ra_serf__run_merge(&commit_info, &response_code,
+                                 ctx->session,
+                                 ctx->session->conns[0],
+                                 merge_target,
+                                 ctx->lock_tokens,
+                                 ctx->keep_locks,
+                                 pool, pool));
 
-  SVN_ERR(svn_ra_serf__context_run_wait(merge_done, ctx->session, pool));
-
-  if (svn_ra_serf__merge_get_status(merge_ctx) != 200)
+  if (response_code != 200)
     {
       return svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
                                _("MERGE request failed: returned %d "
                                  "(during commit)"),
-                               svn_ra_serf__merge_get_status(merge_ctx));
+                               response_code);
     }
 
   /* Inform the WC that we did a commit.  */
   if (ctx->callback)
-    SVN_ERR(ctx->callback(svn_ra_serf__merge_get_commit_info(merge_ctx),
-                          ctx->callback_baton, pool));
+    SVN_ERR(ctx->callback(commit_info, ctx->callback_baton, pool));
 
   /* If we're using activities, DELETE our completed activity.  */
   if (ctx->activity_url)
     {
+      svn_ra_serf__handler_t *handler;
+
       handler = apr_pcalloc(pool, sizeof(*handler));
+      handler->handler_pool = pool;
       handler->method = "DELETE";
       handler->path = ctx->activity_url;
       handler->conn = ctx->conn;
       handler->session = ctx->session;
 
-      delete_ctx = apr_pcalloc(pool, sizeof(*delete_ctx));
-      delete_ctx->pool = pool;
+      handler->response_handler = svn_ra_serf__expect_empty_body;
+      handler->response_baton = handler;
 
-      handler->response_handler = svn_ra_serf__handle_status_only;
-      handler->response_baton = delete_ctx;
+      SVN_ERR(svn_ra_serf__context_run_one(handler, pool));
 
-      svn_ra_serf__request_create(handler);
-
-      SVN_ERR(svn_ra_serf__context_run_wait(&delete_ctx->done, ctx->session,
-                                            pool));
-
-      SVN_ERR_ASSERT(delete_ctx->status == 204);
+      SVN_ERR_ASSERT(handler->sline.code == 204);
     }
 
   return SVN_NO_ERROR;
@@ -2260,7 +2125,6 @@ abort_edit(void *edit_baton,
 {
   commit_context_t *ctx = edit_baton;
   svn_ra_serf__handler_t *handler;
-  svn_ra_serf__simple_request_context_t *delete_ctx;
 
   /* If an activity or transaction wasn't even created, don't bother
      trying to delete it. */
@@ -2273,32 +2137,27 @@ abort_edit(void *edit_baton,
 
   /* DELETE our aborted activity */
   handler = apr_pcalloc(pool, sizeof(*handler));
+  handler->handler_pool = pool;
   handler->method = "DELETE";
   handler->conn = ctx->session->conns[0];
   handler->session = ctx->session;
 
-  delete_ctx = apr_pcalloc(pool, sizeof(*delete_ctx));
-  delete_ctx->pool = pool;
-
-  handler->response_handler = svn_ra_serf__handle_status_only;
-  handler->response_baton = delete_ctx;
+  handler->response_handler = svn_ra_serf__expect_empty_body;
+  handler->response_baton = handler;
 
   if (USING_HTTPV2_COMMIT_SUPPORT(ctx)) /* HTTP v2 */
     handler->path = ctx->txn_url;
   else
     handler->path = ctx->activity_url;
 
-  svn_ra_serf__request_create(handler);
-
-  SVN_ERR(svn_ra_serf__context_run_wait(&delete_ctx->done, ctx->session,
-                                        pool));
+  SVN_ERR(svn_ra_serf__context_run_one(handler, pool));
 
   /* 204 if deleted,
      403 if DELETE was forbidden (indicates MKACTIVITY was forbidden too),
      404 if the activity wasn't found. */
-  if (delete_ctx->status != 204 &&
-      delete_ctx->status != 403 &&
-      delete_ctx->status != 404
+  if (handler->sline.code != 204
+      && handler->sline.code != 403
+      && handler->sline.code != 404
       )
     {
       SVN_ERR_MALFUNCTION();
@@ -2323,6 +2182,7 @@ svn_ra_serf__get_commit_editor(svn_ra_se
   commit_context_t *ctx;
   apr_hash_index_t *hi;
   const char *repos_root;
+  const char *base_relpath;
 
   ctx = apr_pcalloc(pool, sizeof(*ctx));
 
@@ -2370,9 +2230,11 @@ svn_ra_serf__get_commit_editor(svn_ra_se
   *edit_baton = ctx;
 
   SVN_ERR(svn_ra_serf__get_repos_root(ra_session, &repos_root, pool));
+  base_relpath = svn_uri_skip_ancestor(repos_root, session->session_url_str,
+                                       pool);
 
   SVN_ERR(svn_editor__insert_shims(ret_editor, edit_baton, *ret_editor,
-                                   *edit_baton, repos_root, NULL,
+                                   *edit_baton, repos_root, base_relpath,
                                    session->shim_callbacks, pool, pool));
 
   return SVN_NO_ERROR;
@@ -2389,8 +2251,8 @@ svn_ra_serf__change_rev_prop(svn_ra_sess
   svn_ra_serf__session_t *session = ra_session->priv;
   proppatch_context_t *proppatch_ctx;
   commit_context_t *commit;
-  const char *vcc_url, *proppatch_target, *ns;
-  apr_hash_t *props;
+  const char *proppatch_target;
+  const char *ns;
   svn_error_t *err;
 
   if (old_value_p)
@@ -2417,21 +2279,15 @@ svn_ra_serf__change_rev_prop(svn_ra_sess
     }
   else
     {
-      svn_ra_serf__propfind_context_t *propfind_ctx;
+      const char *vcc_url;
 
       SVN_ERR(svn_ra_serf__discover_vcc(&vcc_url, commit->session,
                                         commit->conn, pool));
 
-      props = apr_hash_make(pool);
-
-      /* ### switch to svn_ra_serf__retrieve_props  */
-      SVN_ERR(svn_ra_serf__deliver_props(&propfind_ctx, props, commit->session,
-                                         commit->conn, vcc_url, rev, "0",
-                                         checked_in_props, NULL, pool));
-      SVN_ERR(svn_ra_serf__wait_for_props(propfind_ctx, commit->session, pool));
-
-      proppatch_target = svn_ra_serf__get_ver_prop(props, vcc_url, rev,
-                                                   "DAV:", "href");
+      SVN_ERR(svn_ra_serf__fetch_dav_prop(&proppatch_target,
+                                          commit->conn, vcc_url, rev,
+                                          "href",
+                                          pool, pool));
     }
 
   if (strncmp(name, SVN_PROP_PREFIX, sizeof(SVN_PROP_PREFIX) - 1) == 0)
@@ -2447,7 +2303,6 @@ svn_ra_serf__change_rev_prop(svn_ra_sess
   /* PROPPATCH our log message and pass it along.  */
   proppatch_ctx = apr_pcalloc(pool, sizeof(*proppatch_ctx));
   proppatch_ctx->pool = pool;
-  proppatch_ctx->progress.pool = pool;
   proppatch_ctx->commit = commit;
   proppatch_ctx->path = proppatch_target;
   proppatch_ctx->changed_props = apr_hash_make(proppatch_ctx->pool);

Modified: subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/get_deleted_rev.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/get_deleted_rev.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/get_deleted_rev.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/get_deleted_rev.c Thu Aug 16 10:17:48 2012
@@ -35,14 +35,13 @@
 /*
  * This enum represents the current state of our XML parsing for a REPORT.
  */
-typedef enum drev_state_e {
-  NONE = 0,
+enum drev_state_e {
+  INITIAL = 0,
+  REPORT,
   VERSION_NAME
-} drev_state_e;
+};
 
 typedef struct drev_context_t {
-  apr_pool_t *pool;
-
   const char *path;
   svn_revnum_t peg_revision;
   svn_revnum_t end_revision;
@@ -51,91 +50,41 @@ typedef struct drev_context_t {
      the range PEG_REVISION-END-END_REVISION? */
   svn_revnum_t *revision_deleted;
 
-  /* are we done? */
-  svn_boolean_t done;
-
 } drev_context_t;
 
-
-static void
-push_state(svn_ra_serf__xml_parser_t *parser,
-           drev_context_t *drev_ctx,
-           drev_state_e state)
-{
-  svn_ra_serf__xml_push_state(parser, state);
-
-  if (state == VERSION_NAME)
-    parser->state->private = NULL;
-}
-
-static svn_error_t *
-start_getdrev(svn_ra_serf__xml_parser_t *parser,
-              svn_ra_serf__dav_props_t name,
-              const char **attrs,
-              apr_pool_t *scratch_pool)
-{
-  drev_context_t *drev_ctx = parser->user_data;
-  drev_state_e state;
-
-  state = parser->state->current_state;
+#define D_ "DAV:"
+#define S_ SVN_XML_NAMESPACE
+static const svn_ra_serf__xml_transition_t getdrev_ttable[] = {
+  { INITIAL, S_, "get-deleted-rev-report", REPORT,
+    FALSE, { NULL }, FALSE },
 
-  if (state == NONE &&
-      strcmp(name.name, SVN_DAV__VERSION_NAME) == 0)
-    {
-      push_state(parser, drev_ctx, VERSION_NAME);
-    }
+  { REPORT, D_, SVN_DAV__VERSION_NAME, VERSION_NAME,
+    TRUE, { NULL }, TRUE },
 
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-end_getdrev(svn_ra_serf__xml_parser_t *parser,
-            svn_ra_serf__dav_props_t name,
-            apr_pool_t *scratch_pool)
-{
-  drev_context_t *drev_ctx = parser->user_data;
-  drev_state_e state;
-  svn_string_t *info;
-
-  state = parser->state->current_state;
-  info = parser->state->private;
-
-  if (state == VERSION_NAME &&
-      strcmp(name.name, SVN_DAV__VERSION_NAME) == 0 &&
-      info)
-    {
-      *drev_ctx->revision_deleted = SVN_STR_TO_REV(info->data);
-      svn_ra_serf__xml_pop_state(parser);
-    }
-
-  return SVN_NO_ERROR;
-}
+  { 0 }
+};
 
+
+/* Conforms to svn_ra_serf__xml_closed_t  */
 static svn_error_t *
-cdata_getdrev(svn_ra_serf__xml_parser_t *parser,
-              const char *data,
-              apr_size_t len,
-              apr_pool_t *scratch_pool)
+getdrev_closed(svn_ra_serf__xml_estate_t *xes,
+               void *baton,
+               int leaving_state,
+               const svn_string_t *cdata,
+               apr_hash_t *attrs,
+               apr_pool_t *scratch_pool)
 {
-  drev_context_t *drev_ctx = parser->user_data;
-  drev_state_e state;
+  drev_context_t *drev_ctx = baton;
 
-  UNUSED_CTX(drev_ctx);
+  SVN_ERR_ASSERT(leaving_state == VERSION_NAME);
+  SVN_ERR_ASSERT(cdata != NULL);
 
-  state = parser->state->current_state;
-  switch (state)
-    {
-    case VERSION_NAME:
-        parser->state->private = svn_string_ncreate(data, len,
-                                                    parser->state->pool);
-        break;
-    default:
-        break;
-    }
+  *drev_ctx->revision_deleted = SVN_STR_TO_REV(cdata->data);
 
   return SVN_NO_ERROR;
 }
 
+
 /* Implements svn_ra_serf__request_body_delegate_t */
 static svn_error_t *
 create_getdrev_body(serf_bucket_t **body_bkt,
@@ -186,54 +135,44 @@ svn_ra_serf__get_deleted_rev(svn_ra_sess
   drev_context_t *drev_ctx;
   svn_ra_serf__session_t *ras = session->priv;
   svn_ra_serf__handler_t *handler;
-  svn_ra_serf__xml_parser_t *parser_ctx;
-  const char *relative_url, *basecoll_url, *req_url;
-  int status_code = 0;
+  svn_ra_serf__xml_context_t *xmlctx;
+  const char *req_url;
   svn_error_t *err;
 
   drev_ctx = apr_pcalloc(pool, sizeof(*drev_ctx));
   drev_ctx->path = path;
   drev_ctx->peg_revision = peg_revision;
   drev_ctx->end_revision = end_revision;
-  drev_ctx->pool = pool;
   drev_ctx->revision_deleted = revision_deleted;
-  drev_ctx->done = FALSE;
 
-  SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url,
-                                         ras, NULL, NULL, peg_revision, NULL,
-                                         pool));
-
-  req_url = svn_path_url_add_component2(basecoll_url, relative_url, pool);
-
-  parser_ctx = apr_pcalloc(pool, sizeof(*parser_ctx));
-  parser_ctx->pool = pool;
-  parser_ctx->user_data = drev_ctx;
-  parser_ctx->start = start_getdrev;
-  parser_ctx->end = end_getdrev;
-  parser_ctx->cdata = cdata_getdrev;
-  parser_ctx->done = &drev_ctx->done;
-  parser_ctx->status_code = &status_code;
+  SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */,
+                                      ras, NULL /* conn */,
+                                      NULL /* url */, peg_revision,
+                                      pool, pool));
+
+  xmlctx = svn_ra_serf__xml_context_create(getdrev_ttable,
+                                           NULL, getdrev_closed, NULL,
+                                           drev_ctx,
+                                           pool);
+  handler = svn_ra_serf__create_expat_handler(xmlctx, pool);
 
-  handler = apr_pcalloc(pool, sizeof(*handler));
   handler->method = "REPORT";
   handler->path = req_url;
   handler->body_type = "text/xml";
-  handler->response_handler = svn_ra_serf__handle_xml_parser;
   handler->body_delegate = create_getdrev_body;
   handler->body_delegate_baton = drev_ctx;
   handler->conn = ras->conns[0];
   handler->session = ras;
-  handler->response_baton = parser_ctx;
 
-  svn_ra_serf__request_create(handler);
-
-  err = svn_ra_serf__context_run_wait(&drev_ctx->done, ras, pool);
+  err = svn_ra_serf__context_run_one(handler, pool);
 
   /* Map status 501: Method Not Implemented to our not implemented error.
      1.5.x servers and older don't support this report. */
-  if (status_code == 501)
+  if (handler->sline.code == 501)
     return svn_error_createf(SVN_ERR_RA_NOT_IMPLEMENTED, err,
-                             _("'%s' REPORT not implemented"), "get-deleted-rev");
+                             _("'%s' REPORT not implemented"),
+                             "get-deleted-rev");
   SVN_ERR(err);
+
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/getdate.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/getdate.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/getdate.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/getdate.c Thu Aug 16 10:17:48 2012
@@ -24,9 +24,6 @@
 
 
 #include <apr_uri.h>
-
-#include <expat.h>
-
 #include <serf.h>
 
 #include "svn_pools.h"
@@ -46,10 +43,11 @@
 /*
  * This enum represents the current state of our XML parsing for a REPORT.
  */
-typedef enum date_state_e {
-  NONE = 0,
+enum date_state_e {
+  INITIAL = 0,
+  REPORT,
   VERSION_NAME
-} date_state_e;
+};
 
 
 typedef struct date_context_t {
@@ -59,79 +57,41 @@ typedef struct date_context_t {
   /* What was the youngest revision at that time? */
   svn_revnum_t *revision;
 
-  /* are we done? */
-  svn_boolean_t done;
-
 } date_context_t;
 
+#define D_ "DAV:"
+#define S_ SVN_XML_NAMESPACE
+static const svn_ra_serf__xml_transition_t date_ttable[] = {
+  { INITIAL, S_, "dated-rev-report", REPORT,
+    FALSE, { NULL }, FALSE },
 
-static svn_error_t *
-start_getdate(svn_ra_serf__xml_parser_t *parser,
-              svn_ra_serf__dav_props_t name,
-              const char **attrs,
-              apr_pool_t *scratch_pool)
-{
-  date_context_t *date_ctx = parser->user_data;
-  date_state_e state = parser->state->current_state;
-
-  UNUSED_CTX(date_ctx);
+  { REPORT, D_, SVN_DAV__VERSION_NAME, VERSION_NAME,
+    TRUE, { NULL }, TRUE },
 
-  if (state == NONE &&
-      strcmp(name.name, SVN_DAV__VERSION_NAME) == 0)
-    {
-      svn_ra_serf__xml_push_state(parser, VERSION_NAME);
+  { 0 }
+};
 
-      parser->state->private = svn_stringbuf_create_empty(parser->state->pool);
-    }
-
-  return SVN_NO_ERROR;
-}
 
+/* Conforms to svn_ra_serf__xml_closed_t  */
 static svn_error_t *
-end_getdate(svn_ra_serf__xml_parser_t *parser,
-            svn_ra_serf__dav_props_t name,
+date_closed(svn_ra_serf__xml_estate_t *xes,
+            void *baton,
+            int leaving_state,
+            const svn_string_t *cdata,
+            apr_hash_t *attrs,
             apr_pool_t *scratch_pool)
 {
-  date_context_t *date_ctx = parser->user_data;
-  date_state_e state = parser->state->current_state;
+  date_context_t *date_ctx = baton;
 
-  if (state == VERSION_NAME &&
-      strcmp(name.name, SVN_DAV__VERSION_NAME) == 0)
-    {
-      const svn_stringbuf_t *datebuf = parser->state->private;
-
-      *date_ctx->revision = SVN_STR_TO_REV(datebuf->data);
-      svn_ra_serf__xml_pop_state(parser);
-    }
+  SVN_ERR_ASSERT(leaving_state == VERSION_NAME);
+  SVN_ERR_ASSERT(cdata != NULL);
 
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-cdata_getdate(svn_ra_serf__xml_parser_t *parser,
-              const char *data,
-              apr_size_t len,
-              apr_pool_t *scratch_pool)
-{
-  date_context_t *date_ctx = parser->user_data;
-  date_state_e state = parser->state->current_state;
-  svn_stringbuf_t *datebuf;
-
-  UNUSED_CTX(date_ctx);
-
-  switch (state)
-    {
-    case VERSION_NAME:
-        datebuf = parser->state->private;
-        svn_stringbuf_appendbytes(datebuf, data, len);
-        break;
-    default:
-        break;
-    }
+  *date_ctx->revision = SVN_STR_TO_REV(cdata->data);
 
   return SVN_NO_ERROR;
 }
 
+
 /* Implements svn_ra_serf__request_body_delegate_t */
 static svn_error_t *
 create_getdate_body(serf_bucket_t **body_bkt,
@@ -169,18 +129,20 @@ svn_ra_serf__get_dated_revision(svn_ra_s
   date_context_t *date_ctx;
   svn_ra_serf__session_t *session = ra_session->priv;
   svn_ra_serf__handler_t *handler;
-  svn_ra_serf__xml_parser_t *parser_ctx;
+  svn_ra_serf__xml_context_t *xmlctx;
   const char *report_target;
-  int status_code;
 
   date_ctx = apr_palloc(pool, sizeof(*date_ctx));
   date_ctx->time = tm;
   date_ctx->revision = revision;
-  date_ctx->done = FALSE;
 
   SVN_ERR(svn_ra_serf__report_resource(&report_target, session, NULL, pool));
 
-  handler = apr_pcalloc(pool, sizeof(*handler));
+  xmlctx = svn_ra_serf__xml_context_create(date_ttable,
+                                           NULL, date_closed, NULL,
+                                           date_ctx,
+                                           pool);
+  handler = svn_ra_serf__create_expat_handler(xmlctx, pool);
 
   handler->method = "REPORT";
   handler->path = report_target;
@@ -188,25 +150,12 @@ svn_ra_serf__get_dated_revision(svn_ra_s
   handler->conn = session->conns[0];
   handler->session = session;
 
-  parser_ctx = apr_pcalloc(pool, sizeof(*parser_ctx));
-
-  parser_ctx->pool = pool;
-  parser_ctx->user_data = date_ctx;
-  parser_ctx->start = start_getdate;
-  parser_ctx->end = end_getdate;
-  parser_ctx->cdata = cdata_getdate;
-  parser_ctx->done = &date_ctx->done;
-  parser_ctx->status_code = &status_code;
-
   handler->body_delegate = create_getdate_body;
   handler->body_delegate_baton = date_ctx;
 
-  handler->response_handler = svn_ra_serf__handle_xml_parser;
-  handler->response_baton = parser_ctx;
-
-  svn_ra_serf__request_create(handler);
-
   *date_ctx->revision = SVN_INVALID_REVNUM;
 
-  return svn_ra_serf__context_run_wait(&date_ctx->done, session, pool);
+  /* ### use svn_ra_serf__error_on_status() ?  */
+
+  return svn_error_trace(svn_ra_serf__context_run_one(handler, pool));
 }

Modified: subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/getlocations.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/getlocations.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/getlocations.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/getlocations.c Thu Aug 16 10:17:48 2012
@@ -41,18 +41,11 @@
 /*
  * This enum represents the current state of our XML parsing for a REPORT.
  */
-typedef enum loc_state_e {
+enum loc_state_e {
+  INITIAL = 0,
   REPORT,
   LOCATION
-} loc_state_e;
-
-typedef struct loc_state_list_t {
-  /* The current state that we are in now. */
-  loc_state_e state;
-
-  /* The previous state we were in. */
-  struct loc_state_list_t *prev;
-} loc_state_list_t;
+};
 
 typedef struct loc_context_t {
   /* pool to allocate memory from */
@@ -66,114 +59,49 @@ typedef struct loc_context_t {
   /* Returned location hash */
   apr_hash_t *paths;
 
-  /* Current state we're in */
-  loc_state_list_t *state;
-  loc_state_list_t *free_state;
-
-  int status_code;
-
-  svn_boolean_t done;
 } loc_context_t;
 
-
-static void
-push_state(loc_context_t *loc_ctx, loc_state_e state)
-{
-  loc_state_list_t *new_state;
-
-  if (!loc_ctx->free_state)
-    {
-      new_state = apr_palloc(loc_ctx->pool, sizeof(*loc_ctx->state));
-    }
-  else
-    {
-      new_state = loc_ctx->free_state;
-      loc_ctx->free_state = loc_ctx->free_state->prev;
-    }
-  new_state->state = state;
+#define D_ "DAV:"
+#define S_ SVN_XML_NAMESPACE
+static const svn_ra_serf__xml_transition_t getloc_ttable[] = {
+  { INITIAL, S_, "get-locations-report", REPORT,
+    FALSE, { NULL }, FALSE },
 
-  /* Add it to the state chain. */
-  new_state->prev = loc_ctx->state;
-  loc_ctx->state = new_state;
-}
+  { REPORT, S_, "location", LOCATION,
+    FALSE, { "?rev", "?path", NULL }, TRUE },
 
-static void pop_state(loc_context_t *loc_ctx)
-{
-  loc_state_list_t *free_state;
-  free_state = loc_ctx->state;
-  /* advance the current state */
-  loc_ctx->state = loc_ctx->state->prev;
-  free_state->prev = loc_ctx->free_state;
-  loc_ctx->free_state = free_state;
-}
+  { 0 }
+};
 
+
+/* Conforms to svn_ra_serf__xml_closed_t  */
 static svn_error_t *
-start_getloc(svn_ra_serf__xml_parser_t *parser,
-             svn_ra_serf__dav_props_t name,
-             const char **attrs,
-             apr_pool_t *scratch_pool)
+getloc_closed(svn_ra_serf__xml_estate_t *xes,
+              void *baton,
+              int leaving_state,
+              const svn_string_t *cdata,
+              apr_hash_t *attrs,
+              apr_pool_t *scratch_pool)
 {
-  loc_context_t *loc_ctx = parser->user_data;
+  loc_context_t *loc_ctx = baton;
+  const char *revstr;
+  const char *path;
 
-  if (!loc_ctx->state && strcmp(name.name, "get-locations-report") == 0)
-    {
-      push_state(loc_ctx, REPORT);
-    }
-  else if (loc_ctx->state &&
-           loc_ctx->state->state == REPORT &&
-           strcmp(name.name, "location") == 0)
-    {
-      svn_revnum_t rev = SVN_INVALID_REVNUM;
-      const char *revstr, *path;
+  SVN_ERR_ASSERT(leaving_state == LOCATION);
 
-      revstr = svn_xml_get_attr_value("rev", attrs);
-      if (revstr)
-        {
-          rev = SVN_STR_TO_REV(revstr);
-        }
-
-      path = svn_xml_get_attr_value("path", attrs);
-
-      if (SVN_IS_VALID_REVNUM(rev) && path)
-        {
-          apr_hash_set(loc_ctx->paths,
-                       apr_pmemdup(loc_ctx->pool, &rev, sizeof(rev)),
-                       sizeof(rev),
-                       apr_pstrdup(loc_ctx->pool, path));
-        }
+  revstr = apr_hash_get(attrs, "rev", APR_HASH_KEY_STRING);
+  path = apr_hash_get(attrs, "path", APR_HASH_KEY_STRING);
+  if (revstr != NULL && path != NULL)
+    {
+      svn_revnum_t rev = SVN_STR_TO_REV(revstr);
+      apr_hash_set(loc_ctx->paths,
+                   apr_pmemdup(loc_ctx->pool, &rev, sizeof(rev)), sizeof(rev),
+                   apr_pstrdup(loc_ctx->pool, path));
     }
 
   return SVN_NO_ERROR;
 }
 
-static svn_error_t *
-end_getloc(svn_ra_serf__xml_parser_t *parser,
-           svn_ra_serf__dav_props_t name,
-           apr_pool_t *scratch_pool)
-{
-  loc_context_t *loc_ctx = parser->user_data;
-  loc_state_list_t *cur_state;
-
-  if (!loc_ctx->state)
-    {
-      return SVN_NO_ERROR;
-    }
-
-  cur_state = loc_ctx->state;
-
-  if (cur_state->state == REPORT &&
-      strcmp(name.name, "get-locations-report") == 0)
-    {
-      pop_state(loc_ctx);
-    }
-  else if (cur_state->state == LOCATION &&
-           strcmp(name.name, "location") == 0)
-    {
-      pop_state(loc_ctx);
-    }
-
-  return SVN_NO_ERROR;
-}
 
 /* Implements svn_ra_serf__request_body_delegate_t */
 static svn_error_t *
@@ -228,8 +156,8 @@ svn_ra_serf__get_locations(svn_ra_sessio
   loc_context_t *loc_ctx;
   svn_ra_serf__session_t *session = ra_session->priv;
   svn_ra_serf__handler_t *handler;
-  svn_ra_serf__xml_parser_t *parser_ctx;
-  const char *relative_url, *basecoll_url, *req_url;
+  svn_ra_serf__xml_context_t *xmlctx;
+  const char *req_url;
   svn_error_t *err;
 
   loc_ctx = apr_pcalloc(pool, sizeof(*loc_ctx));
@@ -237,18 +165,20 @@ svn_ra_serf__get_locations(svn_ra_sessio
   loc_ctx->path = path;
   loc_ctx->peg_revision = peg_revision;
   loc_ctx->location_revisions = location_revisions;
-  loc_ctx->done = FALSE;
   loc_ctx->paths = apr_hash_make(loc_ctx->pool);
 
   *locations = loc_ctx->paths;
 
-  SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url, session,
-                                         NULL, NULL, peg_revision, NULL,
-                                         pool));
-
-  req_url = svn_path_url_add_component2(basecoll_url, relative_url, pool);
-
-  handler = apr_pcalloc(pool, sizeof(*handler));
+  SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */,
+                                      session, NULL /* conn */,
+                                      NULL /* url */, peg_revision,
+                                      pool, pool));
+
+  xmlctx = svn_ra_serf__xml_context_create(getloc_ttable,
+                                           NULL, getloc_closed, NULL,
+                                           loc_ctx,
+                                           pool);
+  handler = svn_ra_serf__create_expat_handler(xmlctx, pool);
 
   handler->method = "REPORT";
   handler->path = req_url;
@@ -258,26 +188,12 @@ svn_ra_serf__get_locations(svn_ra_sessio
   handler->conn = session->conns[0];
   handler->session = session;
 
-  parser_ctx = apr_pcalloc(pool, sizeof(*parser_ctx));
-
-  parser_ctx->pool = pool;
-  parser_ctx->user_data = loc_ctx;
-  parser_ctx->start = start_getloc;
-  parser_ctx->end = end_getloc;
-  parser_ctx->status_code = &loc_ctx->status_code;
-  parser_ctx->done = &loc_ctx->done;
-
-  handler->response_handler = svn_ra_serf__handle_xml_parser;
-  handler->response_baton = parser_ctx;
-
-  svn_ra_serf__request_create(handler);
-
-  err = svn_ra_serf__context_run_wait(&loc_ctx->done, session, pool);
+  err = svn_ra_serf__context_run_one(handler, pool);
 
   SVN_ERR(svn_error_compose_create(
-              svn_ra_serf__error_on_status(loc_ctx->status_code,
+              svn_ra_serf__error_on_status(handler->sline.code,
                                            req_url,
-                                           parser_ctx->location),
+                                           handler->location),
               err));
 
   return SVN_NO_ERROR;

Modified: subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/getlocationsegments.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/getlocationsegments.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/getlocationsegments.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/getlocationsegments.c Thu Aug 16 10:17:48 2012
@@ -25,7 +25,6 @@
 
 
 #include <apr_uri.h>
-#include <expat.h>
 #include <serf.h>
 
 #include "svn_pools.h"
@@ -50,82 +49,60 @@ typedef struct gls_context_t {
   svn_location_segment_receiver_t receiver;
   void *receiver_baton;
 
-  /* subpool used only as long as a single receiver invocation */
-  apr_pool_t *subpool;
-
-  /* True iff we're looking at a child of the outer report tag */
-  svn_boolean_t inside_report;
-
-  int status_code;
-
-  svn_boolean_t done;
 } gls_context_t;
 
+enum {
+  INITIAL = 0,
+  REPORT,
+  SEGMENT
+};
+
+#define D_ "DAV:"
+#define S_ SVN_XML_NAMESPACE
+static const svn_ra_serf__xml_transition_t gls_ttable[] = {
+  { INITIAL, S_, "get-location-segments-report", REPORT,
+    FALSE, { NULL }, FALSE },
 
-static svn_error_t *
-start_gls(svn_ra_serf__xml_parser_t *parser,
-          svn_ra_serf__dav_props_t name,
-          const char **attrs,
-          apr_pool_t *scratch_pool)
-{
-  gls_context_t *gls_ctx = parser->user_data;
+  { REPORT, S_, "location-segment", SEGMENT,
+    FALSE, { "?path", "range-start", "range-end", NULL }, TRUE },
 
-  if ((! gls_ctx->inside_report)
-      && strcmp(name.name, "get-location-segments-report") == 0)
-    {
-      gls_ctx->inside_report = TRUE;
-    }
-  else if (gls_ctx->inside_report
-           && strcmp(name.name, "location-segment") == 0)
-    {
-      const char *rev_str;
-      svn_revnum_t range_start = SVN_INVALID_REVNUM;
-      svn_revnum_t range_end = SVN_INVALID_REVNUM;
-      const char *path = NULL;
-
-      path = svn_xml_get_attr_value("path", attrs);
-      rev_str = svn_xml_get_attr_value("range-start", attrs);
-      if (rev_str)
-        range_start = SVN_STR_TO_REV(rev_str);
-      rev_str = svn_xml_get_attr_value("range-end", attrs);
-      if (rev_str)
-        range_end = SVN_STR_TO_REV(rev_str);
-
-      if (SVN_IS_VALID_REVNUM(range_start) && SVN_IS_VALID_REVNUM(range_end))
-        {
-          svn_location_segment_t *segment = apr_pcalloc(gls_ctx->subpool,
-                                                        sizeof(*segment));
-          segment->path = path;
-          segment->range_start = range_start;
-          segment->range_end = range_end;
-          SVN_ERR(gls_ctx->receiver(segment,
-                                    gls_ctx->receiver_baton,
-                                    gls_ctx->subpool));
-          svn_pool_clear(gls_ctx->subpool);
-        }
-      else
-        {
-          return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
-                                  _("Expected valid revision range"));
-        }
-    }
+  { 0 }
+};
 
-  return SVN_NO_ERROR;
-}
 
+/* Conforms to svn_ra_serf__xml_closed_t  */
 static svn_error_t *
-end_gls(svn_ra_serf__xml_parser_t *parser,
-        svn_ra_serf__dav_props_t name,
-        apr_pool_t *scratch_pool)
+gls_closed(svn_ra_serf__xml_estate_t *xes,
+           void *baton,
+           int leaving_state,
+           const svn_string_t *cdata,
+           apr_hash_t *attrs,
+           apr_pool_t *scratch_pool)
 {
-  gls_context_t *gls_ctx = parser->user_data;
-
-  if (strcmp(name.name, "get-location-segments-report") == 0)
-    gls_ctx->inside_report = FALSE;
+  gls_context_t *gls_ctx = baton;
+  const char *path;
+  const char *start_str;
+  const char *end_str;
+  svn_location_segment_t segment;
+
+  SVN_ERR_ASSERT(leaving_state == SEGMENT);
+
+  path = apr_hash_get(attrs, "path", APR_HASH_KEY_STRING);
+  start_str = apr_hash_get(attrs, "range-start", APR_HASH_KEY_STRING);
+  end_str = apr_hash_get(attrs, "range-end", APR_HASH_KEY_STRING);
+
+  /* The transition table said these must exist.  */
+  SVN_ERR_ASSERT(start_str && end_str);
+
+  segment.path = path;  /* may be NULL  */
+  segment.range_start = SVN_STR_TO_REV(start_str);
+  segment.range_end = SVN_STR_TO_REV(end_str);
+  SVN_ERR(gls_ctx->receiver(&segment, gls_ctx->receiver_baton, scratch_pool));
 
   return SVN_NO_ERROR;
 }
 
+
 /* Implements svn_ra_serf__request_body_delegate_t */
 static svn_error_t *
 create_gls_body(serf_bucket_t **body_bkt,
@@ -182,8 +159,8 @@ svn_ra_serf__get_location_segments(svn_r
   gls_context_t *gls_ctx;
   svn_ra_serf__session_t *session = ra_session->priv;
   svn_ra_serf__handler_t *handler;
-  svn_ra_serf__xml_parser_t *parser_ctx;
-  const char *relative_url, *basecoll_url, *req_url;
+  svn_ra_serf__xml_context_t *xmlctx;
+  const char *req_url;
   svn_error_t *err;
 
   gls_ctx = apr_pcalloc(pool, sizeof(*gls_ctx));
@@ -193,16 +170,17 @@ svn_ra_serf__get_location_segments(svn_r
   gls_ctx->end_rev = end_rev;
   gls_ctx->receiver = receiver;
   gls_ctx->receiver_baton = receiver_baton;
-  gls_ctx->subpool = svn_pool_create(pool);
-  gls_ctx->inside_report = FALSE;
-  gls_ctx->done = FALSE;
-
-  SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url, session,
-                                         NULL, NULL, peg_revision, NULL, pool));
 
-  req_url = svn_path_url_add_component2(basecoll_url, relative_url, pool);
-
-  handler = apr_pcalloc(pool, sizeof(*handler));
+  SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */,
+                                      session, NULL /* conn */,
+                                      NULL /* url */, peg_revision,
+                                      pool, pool));
+
+  xmlctx = svn_ra_serf__xml_context_create(gls_ttable,
+                                           NULL, gls_closed, NULL,
+                                           gls_ctx,
+                                           pool);
+  handler = svn_ra_serf__create_expat_handler(xmlctx, pool);
 
   handler->method = "REPORT";
   handler->path = req_url;
@@ -212,34 +190,13 @@ svn_ra_serf__get_location_segments(svn_r
   handler->conn = session->conns[0];
   handler->session = session;
 
-  parser_ctx = apr_pcalloc(pool, sizeof(*parser_ctx));
-
-  parser_ctx->pool = pool;
-  parser_ctx->user_data = gls_ctx;
-  parser_ctx->start = start_gls;
-  parser_ctx->end = end_gls;
-  parser_ctx->status_code = &gls_ctx->status_code;
-  parser_ctx->done = &gls_ctx->done;
-
-  handler->response_handler = svn_ra_serf__handle_xml_parser;
-  handler->response_baton = parser_ctx;
-
-  svn_ra_serf__request_create(handler);
-
-  err = svn_ra_serf__context_run_wait(&gls_ctx->done, session, pool);
-
-  if (gls_ctx->inside_report)
-    err = svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, err,
-                            _("Location segment report failed on '%s'@'%ld'"),
-                              path, peg_revision);
+  err = svn_ra_serf__context_run_one(handler, pool);
 
   err = svn_error_compose_create(
-         svn_ra_serf__error_on_status(gls_ctx->status_code,
+         svn_ra_serf__error_on_status(handler->sline.code,
                                       handler->path,
-                                      parser_ctx->location),
-         err);;
-
-  svn_pool_destroy(gls_ctx->subpool);
+                                      handler->location),
+         err);
 
   if (err && (err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE))
     return svn_error_create(SVN_ERR_RA_NOT_IMPLEMENTED, err, NULL);