You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by vm...@apache.org on 2012/05/29 03:39:49 UTC

svn commit: r1343447 [11/27] - in /subversion/branches/javahl-ra: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ contrib/client-side/emacs/ contrib/server-side/ notes/ notes/api-errata/1.8/ notes/merge-tracking/ sub...

Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_serf/options.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_serf/options.c?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_serf/options.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_serf/options.c Tue May 29 01:39:41 2012
@@ -48,165 +48,68 @@
 /*
  * This enum represents the current state of our XML parsing for an OPTIONS.
  */
-typedef enum options_state_e {
+enum options_state_e {
+  INITIAL = 0,
   OPTIONS,
   ACTIVITY_COLLECTION,
   HREF
-} options_state_e;
-
-typedef struct options_state_list_t {
-  /* The current state that we are in now. */
-  options_state_e state;
-
-  /* The previous state we were in. */
-  struct options_state_list_t *prev;
-} options_state_list_t;
+};
 
-struct svn_ra_serf__options_context_t {
+typedef struct options_context_t {
   /* pool to allocate memory from */
   apr_pool_t *pool;
 
-  /* Buffer for the activity-collection  */
-  svn_stringbuf_t *acbuf;
-  svn_boolean_t collect_cdata;
-
-  /* Current state we're in */
-  options_state_list_t *state;
-  options_state_list_t *free_state;
-
-  /* HTTP Status code */
-  int status_code;
-
-  /* are we done? */
-  svn_boolean_t done;
+  /* Have we extracted options values from the headers already?  */
+  svn_boolean_t headers_processed;
 
   svn_ra_serf__session_t *session;
   svn_ra_serf__connection_t *conn;
+  svn_ra_serf__handler_t *handler;
 
-  const char *path;
+  svn_ra_serf__response_handler_t inner_handler;
+  void *inner_baton;
 
   const char *activity_collection;
   svn_revnum_t youngest_rev;
 
-  serf_response_acceptor_t acceptor;
-  serf_response_handler_t handler;
-  svn_ra_serf__xml_parser_t *parser_ctx;
+} options_context_t;
 
-};
+#define D_ "DAV:"
+#define S_ SVN_XML_NAMESPACE
+static const svn_ra_serf__xml_transition_t options_ttable[] = {
+  { INITIAL, D_, "options-response", OPTIONS,
+    FALSE, { NULL }, FALSE, FALSE },
 
-static void
-push_state(svn_ra_serf__options_context_t *options_ctx, options_state_e state)
-{
-  options_state_list_t *new_state;
+  { OPTIONS, D_, "activity-collection-set", ACTIVITY_COLLECTION,
+    FALSE, { NULL }, FALSE, FALSE },
 
-  if (!options_ctx->free_state)
-    {
-      new_state = apr_palloc(options_ctx->pool, sizeof(*options_ctx->state));
-    }
-  else
-    {
-      new_state = options_ctx->free_state;
-      options_ctx->free_state = options_ctx->free_state->prev;
-    }
-  new_state->state = state;
+  { ACTIVITY_COLLECTION, D_, "href", HREF,
+    TRUE, { NULL }, FALSE, TRUE },
 
-  /* Add it to the state chain. */
-  new_state->prev = options_ctx->state;
-  options_ctx->state = new_state;
-}
-
-static void pop_state(svn_ra_serf__options_context_t *options_ctx)
-{
-  options_state_list_t *free_state;
-  free_state = options_ctx->state;
-  /* advance the current state */
-  options_ctx->state = options_ctx->state->prev;
-  free_state->prev = options_ctx->free_state;
-  options_ctx->free_state = free_state;
-}
-
-static svn_error_t *
-start_options(svn_ra_serf__xml_parser_t *parser,
-              svn_ra_serf__dav_props_t name,
-              const char **attrs,
-              apr_pool_t *scratch_pool)
-{
-  svn_ra_serf__options_context_t *options_ctx = parser->user_data;
-
-  if (!options_ctx->state && strcmp(name.name, "options-response") == 0)
-    {
-      push_state(options_ctx, OPTIONS);
-    }
-  else if (!options_ctx->state)
-    {
-      /* Nothing to do. */
-      return SVN_NO_ERROR;
-    }
-  else if (options_ctx->state->state == OPTIONS &&
-           strcmp(name.name, "activity-collection-set") == 0)
-    {
-      push_state(options_ctx, ACTIVITY_COLLECTION);
-    }
-  else if (options_ctx->state->state == ACTIVITY_COLLECTION &&
-           strcmp(name.name, "href") == 0)
-    {
-      options_ctx->collect_cdata = TRUE;
-      push_state(options_ctx, HREF);
-    }
+  { 0 }
+};
 
-  return SVN_NO_ERROR;
-}
 
+/* Conforms to svn_ra_serf__xml_closed_t  */
 static svn_error_t *
-end_options(svn_ra_serf__xml_parser_t *parser,
-            svn_ra_serf__dav_props_t name,
-            apr_pool_t *scratch_pool)
+options_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)
 {
-  svn_ra_serf__options_context_t *options_ctx = parser->user_data;
-  options_state_list_t *cur_state;
-
-  if (!options_ctx->state)
-    {
-      return SVN_NO_ERROR;
-    }
+  options_context_t *opt_ctx = baton;
 
-  cur_state = options_ctx->state;
+  SVN_ERR_ASSERT(leaving_state == HREF);
+  SVN_ERR_ASSERT(cdata != NULL);
 
-  if (cur_state->state == OPTIONS &&
-      strcmp(name.name, "options-response") == 0)
-    {
-      pop_state(options_ctx);
-    }
-  else if (cur_state->state == ACTIVITY_COLLECTION &&
-           strcmp(name.name, "activity-collection-set") == 0)
-    {
-      pop_state(options_ctx);
-    }
-  else if (cur_state->state == HREF &&
-           strcmp(name.name, "href") == 0)
-    {
-      options_ctx->collect_cdata = FALSE;
-      options_ctx->activity_collection =
-        svn_urlpath__canonicalize(options_ctx->acbuf->data, options_ctx->pool);
-      pop_state(options_ctx);
-    }
+  opt_ctx->activity_collection = svn_urlpath__canonicalize(cdata->data,
+                                                           opt_ctx->pool);
 
   return SVN_NO_ERROR;
 }
 
-static svn_error_t *
-cdata_options(svn_ra_serf__xml_parser_t *parser,
-              const char *data,
-              apr_size_t len,
-              apr_pool_t *scratch_pool)
-{
-  svn_ra_serf__options_context_t *ctx = parser->user_data;
-
-  if (ctx->collect_cdata)
-    svn_stringbuf_appendbytes(ctx->acbuf, data, len);
-
-  return SVN_NO_ERROR;
-}
 
 static svn_error_t *
 create_options_body(serf_bucket_t **body_bkt,
@@ -227,47 +130,17 @@ create_options_body(serf_bucket_t **body
   return SVN_NO_ERROR;
 }
 
-svn_boolean_t*
-svn_ra_serf__get_options_done_ptr(svn_ra_serf__options_context_t *ctx)
-{
-  return &ctx->done;
-}
-
-const char *
-svn_ra_serf__options_get_activity_collection(svn_ra_serf__options_context_t *ctx)
-{
-  return ctx->activity_collection;
-}
-
-svn_revnum_t
-svn_ra_serf__options_get_youngest_rev(svn_ra_serf__options_context_t *ctx)
-{
-  return ctx->youngest_rev;
-}
-
-/* Context for both options_response_handler() and capabilities callback. */
-struct options_response_ctx_t {
-  /* Baton for __handle_xml_parser() */
-  svn_ra_serf__xml_parser_t *parser_ctx;
-
-  /* Session into which we'll store server capabilities */
-  svn_ra_serf__session_t *session;
-
-  /* For temporary work only. */
-  apr_pool_t *pool;
-};
-
 
 /* We use these static pointers so we can employ pointer comparison
  * of our capabilities hash members instead of strcmp()ing all over
  * the place.
  */
 /* Both server and repository support the capability. */
-static const char *capability_yes = "yes";
+static const char *const capability_yes = "yes";
 /* Either server or repository does not support the capability. */
-static const char *capability_no = "no";
+static const char *const capability_no = "no";
 /* Server supports the capability, but don't yet know if repository does. */
-static const char *capability_server_yes = "server-yes";
+static const char *const capability_server_yes = "server-yes";
 
 
 /* This implements serf_bucket_headers_do_callback_fn_t.
@@ -277,7 +150,8 @@ capabilities_headers_iterator_callback(v
                                        const char *key,
                                        const char *val)
 {
-  struct options_response_ctx_t *orc = baton;
+  options_context_t *opt_ctx = baton;
+  svn_ra_serf__session_t *session = opt_ctx->session;
 
   if (svn_cstring_casecmp(key, "dav") == 0)
     {
@@ -285,7 +159,8 @@ capabilities_headers_iterator_callback(v
            DAV: version-control,checkout,working-resource
            DAV: merge,baseline,activity,version-controlled-collection
            DAV: http://subversion.tigris.org/xmlns/dav/svn/depth */
-      apr_array_header_t *vals = svn_cstring_split(val, ",", TRUE, orc->pool);
+      apr_array_header_t *vals = svn_cstring_split(val, ",", TRUE,
+                                                   opt_ctx->pool);
 
       /* Right now we only have a few capabilities to detect, so just
          seek for them directly.  This could be written slightly more
@@ -294,33 +169,35 @@ capabilities_headers_iterator_callback(v
 
       if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_DEPTH, vals))
         {
-          apr_hash_set(orc->session->capabilities, SVN_RA_CAPABILITY_DEPTH,
-                       APR_HASH_KEY_STRING, capability_yes);
+          apr_hash_set(session->capabilities,
+                       SVN_RA_CAPABILITY_DEPTH, APR_HASH_KEY_STRING,
+                       capability_yes);
         }
       if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_MERGEINFO, vals))
         {
           /* The server doesn't know what repository we're referring
              to, so it can't just say capability_yes. */
-          apr_hash_set(orc->session->capabilities, SVN_RA_CAPABILITY_MERGEINFO,
-                       APR_HASH_KEY_STRING, capability_server_yes);
+          apr_hash_set(session->capabilities,
+                       SVN_RA_CAPABILITY_MERGEINFO, APR_HASH_KEY_STRING,
+                       capability_server_yes);
         }
       if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_LOG_REVPROPS, vals))
         {
-          apr_hash_set(orc->session->capabilities,
-                       SVN_RA_CAPABILITY_LOG_REVPROPS,
-                       APR_HASH_KEY_STRING, capability_yes);
+          apr_hash_set(session->capabilities,
+                       SVN_RA_CAPABILITY_LOG_REVPROPS, APR_HASH_KEY_STRING,
+                       capability_yes);
         }
       if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_ATOMIC_REVPROPS, vals))
         {
-          apr_hash_set(orc->session->capabilities,
-                       SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
-                       APR_HASH_KEY_STRING, capability_yes);
+          apr_hash_set(session->capabilities,
+                       SVN_RA_CAPABILITY_ATOMIC_REVPROPS, APR_HASH_KEY_STRING,
+                       capability_yes);
         }
       if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_PARTIAL_REPLAY, vals))
         {
-          apr_hash_set(orc->session->capabilities,
-                       SVN_RA_CAPABILITY_PARTIAL_REPLAY,
-                       APR_HASH_KEY_STRING, capability_yes);
+          apr_hash_set(session->capabilities,
+                       SVN_RA_CAPABILITY_PARTIAL_REPLAY, APR_HASH_KEY_STRING,
+                       capability_yes);
         }
     }
 
@@ -329,14 +206,12 @@ capabilities_headers_iterator_callback(v
     {
       if (svn_cstring_casecmp(key, SVN_DAV_ROOT_URI_HEADER) == 0)
         {
-          orc->session->repos_root = orc->session->session_url;
-          orc->session->repos_root.path = apr_pstrdup(orc->session->pool, val);
-          orc->session->repos_root_str =
+          session->repos_root = session->session_url;
+          session->repos_root.path = apr_pstrdup(session->pool, val);
+          session->repos_root_str =
             svn_urlpath__canonicalize(
-                apr_uri_unparse(orc->session->pool,
-                                &orc->session->repos_root,
-                                0),
-                orc->session->pool);
+                apr_uri_unparse(session->pool, &session->repos_root, 0),
+                session->pool);
         }
       else if (svn_cstring_casecmp(key, SVN_DAV_ME_RESOURCE_HEADER) == 0)
         {
@@ -345,44 +220,42 @@ capabilities_headers_iterator_callback(v
 
           if (!(ignore_v2_env_var
                 && apr_strnatcasecmp(ignore_v2_env_var, "yes") == 0))
-            orc->session->me_resource = apr_pstrdup(orc->session->pool, val);
+            session->me_resource = apr_pstrdup(session->pool, val);
 #else
-          orc->session->me_resource = apr_pstrdup(orc->session->pool, val);
+          session->me_resource = apr_pstrdup(session->pool, val);
 #endif
         }
       else if (svn_cstring_casecmp(key, SVN_DAV_REV_STUB_HEADER) == 0)
         {
-          orc->session->rev_stub = apr_pstrdup(orc->session->pool, val);
+          session->rev_stub = apr_pstrdup(session->pool, val);
         }
       else if (svn_cstring_casecmp(key, SVN_DAV_REV_ROOT_STUB_HEADER) == 0)
         {
-          orc->session->rev_root_stub = apr_pstrdup(orc->session->pool, val);
+          session->rev_root_stub = apr_pstrdup(session->pool, val);
         }
       else if (svn_cstring_casecmp(key, SVN_DAV_TXN_STUB_HEADER) == 0)
         {
-          orc->session->txn_stub = apr_pstrdup(orc->session->pool, val);
+          session->txn_stub = apr_pstrdup(session->pool, val);
         }
       else if (svn_cstring_casecmp(key, SVN_DAV_TXN_ROOT_STUB_HEADER) == 0)
         {
-          orc->session->txn_root_stub = apr_pstrdup(orc->session->pool, val);
+          session->txn_root_stub = apr_pstrdup(session->pool, val);
         }
       else if (svn_cstring_casecmp(key, SVN_DAV_VTXN_STUB_HEADER) == 0)
         {
-          orc->session->vtxn_stub = apr_pstrdup(orc->session->pool, val);
+          session->vtxn_stub = apr_pstrdup(session->pool, val);
         }
       else if (svn_cstring_casecmp(key, SVN_DAV_VTXN_ROOT_STUB_HEADER) == 0)
         {
-          orc->session->vtxn_root_stub = apr_pstrdup(orc->session->pool, val);
+          session->vtxn_root_stub = apr_pstrdup(session->pool, val);
         }
       else if (svn_cstring_casecmp(key, SVN_DAV_REPOS_UUID_HEADER) == 0)
         {
-          orc->session->uuid = apr_pstrdup(orc->session->pool, val);
+          session->uuid = apr_pstrdup(session->pool, val);
         }
       else if (svn_cstring_casecmp(key, SVN_DAV_YOUNGEST_REV_HEADER) == 0)
         {
-          struct svn_ra_serf__options_context_t *user_data =
-            orc->parser_ctx->user_data;
-          user_data->youngest_rev = SVN_STR_TO_REV(val);
+          opt_ctx->youngest_rev = SVN_STR_TO_REV(val);
         }
     }
 
@@ -400,88 +273,116 @@ options_response_handler(serf_request_t 
                          void *baton,
                          apr_pool_t *pool)
 {
-  struct options_response_ctx_t *orc = baton;
-  serf_bucket_t *hdrs = serf_bucket_response_get_headers(response);
+  options_context_t *opt_ctx = baton;
+
+  if (!opt_ctx->headers_processed)
+    {
+      svn_ra_serf__session_t *session = opt_ctx->session;
+      serf_bucket_t *hdrs = serf_bucket_response_get_headers(response);
 
-  /* Start out assuming all capabilities are unsupported. */
-  apr_hash_set(orc->session->capabilities, SVN_RA_CAPABILITY_PARTIAL_REPLAY,
-               APR_HASH_KEY_STRING, capability_no);
-  apr_hash_set(orc->session->capabilities, SVN_RA_CAPABILITY_DEPTH,
-               APR_HASH_KEY_STRING, capability_no);
-  apr_hash_set(orc->session->capabilities, SVN_RA_CAPABILITY_MERGEINFO,
-               APR_HASH_KEY_STRING, capability_no);
-  apr_hash_set(orc->session->capabilities, SVN_RA_CAPABILITY_LOG_REVPROPS,
-               APR_HASH_KEY_STRING, capability_no);
-  apr_hash_set(orc->session->capabilities, SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
-               APR_HASH_KEY_STRING, capability_no);
+      /* Start out assuming all capabilities are unsupported. */
+      apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_PARTIAL_REPLAY,
+                   APR_HASH_KEY_STRING, capability_no);
+      apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_DEPTH,
+                   APR_HASH_KEY_STRING, capability_no);
+      apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO,
+                   APR_HASH_KEY_STRING, capability_no);
+      apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_LOG_REVPROPS,
+                   APR_HASH_KEY_STRING, capability_no);
+      apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+                   APR_HASH_KEY_STRING, capability_no);
+
+      /* Then see which ones we can discover. */
+      serf_bucket_headers_do(hdrs, capabilities_headers_iterator_callback,
+                             opt_ctx);
 
-  /* Then see which ones we can discover. */
-  serf_bucket_headers_do(hdrs, capabilities_headers_iterator_callback, orc);
+      opt_ctx->headers_processed = TRUE;
+    }
 
   /* Execute the 'real' response handler to XML-parse the repsonse body. */
-  return svn_ra_serf__handle_xml_parser(request, response,
-                                        orc->parser_ctx, pool);
+  return opt_ctx->inner_handler(request, response, opt_ctx->inner_baton, pool);
 }
 
 
-svn_error_t *
-svn_ra_serf__create_options_req(svn_ra_serf__options_context_t **opt_ctx,
-                                svn_ra_serf__session_t *session,
-                                svn_ra_serf__connection_t *conn,
-                                const char *path,
-                                apr_pool_t *pool)
+static svn_error_t *
+create_options_req(options_context_t **opt_ctx,
+                   svn_ra_serf__session_t *session,
+                   svn_ra_serf__connection_t *conn,
+                   apr_pool_t *pool)
 {
-  svn_ra_serf__options_context_t *new_ctx;
+  options_context_t *new_ctx;
+  svn_ra_serf__xml_context_t *xmlctx;
   svn_ra_serf__handler_t *handler;
-  svn_ra_serf__xml_parser_t *parser_ctx;
-  struct options_response_ctx_t *options_response_ctx;
 
   new_ctx = apr_pcalloc(pool, sizeof(*new_ctx));
-
   new_ctx->pool = pool;
-
-  new_ctx->acbuf = svn_stringbuf_create_empty(pool);
-
-  new_ctx->path = path;
-  new_ctx->youngest_rev = SVN_INVALID_REVNUM;
-
   new_ctx->session = session;
   new_ctx->conn = conn;
 
-  handler = apr_pcalloc(pool, sizeof(*handler));
+  new_ctx->youngest_rev = SVN_INVALID_REVNUM;
+
+  xmlctx = svn_ra_serf__xml_context_create(options_ttable,
+                                           NULL, options_closed, new_ctx,
+                                           pool);
+  handler = svn_ra_serf__create_expat_handler(xmlctx, pool);
 
   handler->method = "OPTIONS";
-  handler->path = path;
+  handler->path = session->session_url.path;
   handler->body_delegate = create_options_body;
   handler->body_type = "text/xml";
   handler->conn = conn;
   handler->session = session;
 
-  parser_ctx = apr_pcalloc(pool, sizeof(*parser_ctx));
-
-  parser_ctx->pool = pool;
-  parser_ctx->user_data = new_ctx;
-  parser_ctx->start = start_options;
-  parser_ctx->end = end_options;
-  parser_ctx->cdata = cdata_options;
-  parser_ctx->done = &new_ctx->done;
-  parser_ctx->status_code = &new_ctx->status_code;
-
-  options_response_ctx = apr_pcalloc(pool, sizeof(*options_response_ctx));
-  options_response_ctx->parser_ctx = parser_ctx;
-  options_response_ctx->session = session;
-  options_response_ctx->pool = pool;
+  new_ctx->handler = handler;
 
+  new_ctx->inner_handler = handler->response_handler;
+  new_ctx->inner_baton = handler->response_baton;
   handler->response_handler = options_response_handler;
-  handler->response_baton = options_response_ctx;
+  handler->response_baton = new_ctx;
+
+  *opt_ctx = new_ctx;
+
+  return SVN_NO_ERROR;
+}
+
 
-  svn_ra_serf__request_create(handler);
+svn_error_t *
+svn_ra_serf__v2_get_youngest_revnum(svn_revnum_t *youngest,
+                                    svn_ra_serf__connection_t *conn,
+                                    apr_pool_t *scratch_pool)
+{
+  svn_ra_serf__session_t *session = conn->session;
+  options_context_t *opt_ctx;
 
-  new_ctx->parser_ctx = parser_ctx;
+  SVN_ERR_ASSERT(SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(session));
 
-  *opt_ctx = new_ctx;
+  SVN_ERR(create_options_req(&opt_ctx, session, conn, scratch_pool));
+  SVN_ERR(svn_ra_serf__context_run_one(opt_ctx->handler, scratch_pool));
+
+  *youngest = opt_ctx->youngest_rev;
+
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_ra_serf__v1_get_activity_collection(const char **activity_url,
+                                        svn_ra_serf__connection_t *conn,
+                                        apr_pool_t *result_pool,
+                                        apr_pool_t *scratch_pool)
+{
+  svn_ra_serf__session_t *session = conn->session;
+  options_context_t *opt_ctx;
+
+  SVN_ERR_ASSERT(!SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(session));
+
+  SVN_ERR(create_options_req(&opt_ctx, session, conn, scratch_pool));
+  SVN_ERR(svn_ra_serf__context_run_one(opt_ctx->handler, scratch_pool));
+
+  *activity_url = apr_pstrdup(result_pool, opt_ctx->activity_collection);
 
   return SVN_NO_ERROR;
+
 }
 
 
@@ -493,32 +394,29 @@ svn_ra_serf__exchange_capabilities(svn_r
                                    const char **corrected_url,
                                    apr_pool_t *pool)
 {
-  svn_ra_serf__options_context_t *opt_ctx;
+  options_context_t *opt_ctx;
   svn_error_t *err;
 
   /* This routine automatically fills in serf_sess->capabilities */
-  SVN_ERR(svn_ra_serf__create_options_req(&opt_ctx, serf_sess,
-                                          serf_sess->conns[0],
-                                          serf_sess->session_url.path, pool));
+  SVN_ERR(create_options_req(&opt_ctx, serf_sess, serf_sess->conns[0], pool));
 
-  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_one(opt_ctx->handler, pool);
 
   /* If our caller cares about server redirections, and our response
      carries such a thing, report as much.  We'll disregard ERR --
      it's most likely just a complaint about the response body not
      successfully parsing as XML or somesuch. */
-  if (corrected_url && (opt_ctx->status_code == 301))
+  if (corrected_url && (opt_ctx->handler->sline.code == 301))
     {
       svn_error_clear(err);
-      *corrected_url = opt_ctx->parser_ctx->location;
+      *corrected_url = opt_ctx->handler->location;
       return SVN_NO_ERROR;
     }
 
   return svn_error_compose_create(
-             svn_ra_serf__error_on_status(opt_ctx->status_code,
+             svn_ra_serf__error_on_status(opt_ctx->handler->sline.code,
                                           serf_sess->session_url.path,
-                                          opt_ctx->parser_ctx->location),
+                                          opt_ctx->handler->location),
              err);
 }
 

Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_serf/property.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_serf/property.c?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_serf/property.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_serf/property.c Tue May 29 01:39:41 2012
@@ -97,9 +97,6 @@ struct svn_ra_serf__propfind_context_t {
    */
   const char *current_path;
 
-  /* Returned status code. */
-  int status_code;
-
   /* Are we done issuing the PROPFIND? */
   svn_boolean_t done;
 
@@ -112,6 +109,7 @@ struct svn_ra_serf__propfind_context_t {
   svn_ra_serf__list_t done_item;
 };
 
+
 const svn_string_t *
 svn_ra_serf__get_ver_prop_string(apr_hash_t *props,
                                  const char *path,
@@ -552,6 +550,7 @@ svn_ra_serf__deliver_props(svn_ra_serf__
 
   handler = apr_pcalloc(pool, sizeof(*handler));
 
+  handler->handler_pool = pool;
   handler->method = "PROPFIND";
   handler->path = path;
   handler->body_delegate = create_propfind_body;
@@ -571,7 +570,6 @@ svn_ra_serf__deliver_props(svn_ra_serf__
   parser_ctx->start = start_propfind;
   parser_ctx->end = end_propfind;
   parser_ctx->cdata = cdata_propfind;
-  parser_ctx->status_code = &new_prop_ctx->status_code;
   parser_ctx->done = &new_prop_ctx->done;
   parser_ctx->done_list = new_prop_ctx->done_list;
   parser_ctx->done_item = &new_prop_ctx->done_item;
@@ -595,11 +593,6 @@ svn_ra_serf__propfind_is_done(svn_ra_ser
   return ctx->done;
 }
 
-int
-svn_ra_serf__propfind_status_code(svn_ra_serf__propfind_context_t *ctx)
-{
-  return ctx->status_code;
-}
 
 /*
  * This helper function will block until the PROP_CTX indicates that is done
@@ -614,7 +607,7 @@ 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,
+  err2 = svn_ra_serf__error_on_status(prop_ctx->handler->sline.code,
                                       prop_ctx->path, NULL);
   if (err2)
     {
@@ -652,32 +645,50 @@ svn_ra_serf__retrieve_props(apr_hash_t *
 
 
 svn_error_t *
-svn_ra_serf__walk_all_props(apr_hash_t *props,
-                            const char *name,
-                            svn_revnum_t rev,
-                            svn_ra_serf__walker_visitor_t walker,
-                            void *baton,
-                            apr_pool_t *scratch_pool)
+svn_ra_serf__fetch_node_props(apr_hash_t **results,
+                              svn_ra_serf__connection_t *conn,
+                              const char *url,
+                              svn_revnum_t revision,
+                              const svn_ra_serf__dav_props_t *which_props,
+                              apr_pool_t *result_pool,
+                              apr_pool_t *scratch_pool)
 {
-  apr_hash_index_t *ns_hi;
+  apr_hash_t *multiprops;
   apr_hash_t *ver_props;
-  apr_hash_t *path_props;
-  apr_pool_t *iterpool;
 
-  ver_props = apr_hash_get(props, &rev, sizeof(rev));
-  if (!ver_props)
-    {
-      return SVN_NO_ERROR;
-    }
+  /* Note: a couple extra hash tables and whatnot get into RESULT_POOL.
+     Not a big deal at this point. Theoretically, we could fetch all
+     props into SCRATCH_POOL, then copy just the REVISION/URL props
+     into RESULT_POOL. Too much work for too little gain...  */
+  SVN_ERR(svn_ra_serf__retrieve_props(&multiprops, conn->session, conn,
+                                      url, revision, "0", which_props,
+                                      result_pool, scratch_pool));
+
+  ver_props = apr_hash_get(multiprops, &revision, sizeof(revision));
+  if (ver_props != NULL)
+    {
+      *results = apr_hash_get(ver_props, url, APR_HASH_KEY_STRING);
+      if (*results != NULL)
+        return SVN_NO_ERROR;
+    }
+
+  return svn_error_create(SVN_ERR_RA_DAV_PROPS_NOT_FOUND, NULL,
+                          _("The PROPFIND response did not include "
+                            "the requested properties"));
+}
 
-  path_props = apr_hash_get(ver_props, name, APR_HASH_KEY_STRING);
-  if (!path_props)
-    {
-      return SVN_NO_ERROR;
-    }
+
+svn_error_t *
+svn_ra_serf__walk_node_props(apr_hash_t *props,
+                             svn_ra_serf__walker_visitor_t walker,
+                             void *baton,
+                             apr_pool_t *scratch_pool)
+{
+  apr_pool_t *iterpool;
+  apr_hash_index_t *ns_hi;
 
   iterpool = svn_pool_create(scratch_pool);
-  for (ns_hi = apr_hash_first(scratch_pool, path_props); ns_hi;
+  for (ns_hi = apr_hash_first(scratch_pool, props); ns_hi;
        ns_hi = apr_hash_next(ns_hi))
     {
       void *ns_val;
@@ -711,6 +722,31 @@ svn_ra_serf__walk_all_props(apr_hash_t *
 
 
 svn_error_t *
+svn_ra_serf__walk_all_props(apr_hash_t *props,
+                            const char *name,
+                            svn_revnum_t rev,
+                            svn_ra_serf__walker_visitor_t walker,
+                            void *baton,
+                            apr_pool_t *scratch_pool)
+{
+  apr_hash_t *ver_props;
+  apr_hash_t *path_props;
+
+  ver_props = apr_hash_get(props, &rev, sizeof(rev));
+  if (!ver_props)
+    return SVN_NO_ERROR;
+
+  path_props = apr_hash_get(ver_props, name, APR_HASH_KEY_STRING);
+  if (!path_props)
+    return SVN_NO_ERROR;
+
+  return svn_error_trace(svn_ra_serf__walk_node_props(path_props,
+                                                      walker, baton,
+                                                      scratch_pool));
+}
+
+
+svn_error_t *
 svn_ra_serf__walk_all_paths(apr_hash_t *props,
                             svn_revnum_t rev,
                             svn_ra_serf__path_rev_walker_t walker,
@@ -832,15 +868,13 @@ set_flat_props(void *baton,
 svn_error_t *
 svn_ra_serf__flatten_props(apr_hash_t **flat_props,
                            apr_hash_t *props,
-                           const char *path,
-                           svn_revnum_t revision,
                            apr_pool_t *result_pool,
                            apr_pool_t *scratch_pool)
 {
   *flat_props = apr_hash_make(result_pool);
 
-  return svn_error_trace(svn_ra_serf__walk_all_props(
-                            props, path, revision,
+  return svn_error_trace(svn_ra_serf__walk_node_props(
+                            props,
                             set_flat_props,
                             *flat_props /* baton */,
                             scratch_pool));
@@ -899,7 +933,7 @@ svn_ra_serf__select_revprops(apr_hash_t 
 
 
 /*
- * Contact the server (using SESSION and CONN) to calculate baseline
+ * Contact the server (using CONN) to calculate baseline
  * information for BASELINE_URL at REVISION (which may be
  * SVN_INVALID_REVNUM to query the HEAD revision).
  *
@@ -911,209 +945,295 @@ svn_ra_serf__select_revprops(apr_hash_t 
 static svn_error_t *
 retrieve_baseline_info(svn_revnum_t *actual_revision,
                        const char **basecoll_url_p,
-                       svn_ra_serf__session_t *session,
                        svn_ra_serf__connection_t *conn,
                        const char *baseline_url,
                        svn_revnum_t revision,
-                       apr_pool_t *pool)
+                       apr_pool_t *result_pool,
+                       apr_pool_t *scratch_pool)
 {
   apr_hash_t *props;
+  apr_hash_t *dav_props;
   const char *basecoll_url;
-  const char *version_name;
-
-  SVN_ERR(svn_ra_serf__retrieve_props(&props, session, conn,
-                                      baseline_url, revision, "0",
-                                      baseline_props,
-                                      pool, pool));
 
-  basecoll_url = svn_ra_serf__get_ver_prop(props, baseline_url, revision,
-                                           "DAV:", "baseline-collection");
+  SVN_ERR(svn_ra_serf__fetch_node_props(&props, conn,
+                                        baseline_url, revision,
+                                        baseline_props,
+                                        scratch_pool, scratch_pool));
+  dav_props = apr_hash_get(props, "DAV:", 4);
+  /* If DAV_PROPS is NULL, then svn_prop_get_value() will return NULL.  */
 
+  basecoll_url = svn_prop_get_value(dav_props, "baseline-collection");
   if (!basecoll_url)
     {
       return svn_error_create(SVN_ERR_RA_DAV_PROPS_NOT_FOUND, NULL,
                               _("The PROPFIND response did not include "
                                 "the requested baseline-collection value"));
     }
-
-  *basecoll_url_p = svn_urlpath__canonicalize(basecoll_url, pool);
-
-  version_name = svn_ra_serf__get_ver_prop(props, baseline_url, revision,
-                                           "DAV:", SVN_DAV__VERSION_NAME);
-  if (!version_name)
-    {
-      return svn_error_create(SVN_ERR_RA_DAV_PROPS_NOT_FOUND, NULL,
-                              _("The PROPFIND response did not include "
-                                "the requested version-name value"));
-    }
+  *basecoll_url_p = svn_urlpath__canonicalize(basecoll_url, result_pool);
 
   if (actual_revision)
     {
+      const char *version_name;
+
+      version_name = svn_prop_get_value(dav_props, SVN_DAV__VERSION_NAME);
+      if (!version_name)
+        return svn_error_create(SVN_ERR_RA_DAV_PROPS_NOT_FOUND, NULL,
+                                _("The PROPFIND response did not include "
+                                  "the requested version-name value"));
+
       *actual_revision = SVN_STR_TO_REV(version_name);
     }
 
   return SVN_NO_ERROR;
 }
 
+
+/* For HTTPv1 servers, do a PROPFIND dance on the VCC to fetch the youngest
+   revnum. If BASECOLL_URL is non-NULL, then the corresponding baseline
+   collection URL is also returned.
+
+   Do the work over CONN.
+
+   *BASECOLL_URL (if requested) will be allocated in RESULT_POOL. All
+   temporary allocations will be made in SCRATCH_POOL.  */
+static svn_error_t *
+v1_get_youngest_revnum(svn_revnum_t *youngest,
+                       const char **basecoll_url,
+                       svn_ra_serf__connection_t *conn,
+                       const char *vcc_url,
+                       apr_pool_t *result_pool,
+                       apr_pool_t *scratch_pool)
+{
+  const char *baseline_url;
+  const char *bc_url;
+
+  /* Fetching DAV:checked-in from the VCC (with no Label: to specify a
+     revision) will return the latest Baseline resource's URL.  */
+  SVN_ERR(svn_ra_serf__fetch_dav_prop(&baseline_url, conn, vcc_url,
+                                      SVN_INVALID_REVNUM,
+                                      "checked-in",
+                                      scratch_pool, scratch_pool));
+  if (!baseline_url)
+    {
+      return svn_error_create(SVN_ERR_RA_DAV_OPTIONS_REQ_FAILED, NULL,
+                              _("The OPTIONS response did not include "
+                                "the requested checked-in value"));
+    }
+  baseline_url = svn_urlpath__canonicalize(baseline_url, scratch_pool);
+
+  /* From the Baseline resource, we can fetch the DAV:baseline-collection
+     and DAV:version-name properties. The latter is the revision number,
+     which is formally the name used in Label: headers.  */
+
+  /* First check baseline information cache. */
+  SVN_ERR(svn_ra_serf__blncache_get_baseline_info(&bc_url,
+                                                  youngest,
+                                                  conn->session->blncache,
+                                                  baseline_url,
+                                                  scratch_pool));
+  if (!bc_url)
+    {
+      SVN_ERR(retrieve_baseline_info(youngest, &bc_url, conn,
+                                     baseline_url, SVN_INVALID_REVNUM,
+                                     scratch_pool, scratch_pool));
+      SVN_ERR(svn_ra_serf__blncache_set(conn->session->blncache,
+                                        baseline_url, *youngest,
+                                        bc_url, scratch_pool));
+    }
+
+  if (basecoll_url != NULL)
+    *basecoll_url = apr_pstrdup(result_pool, bc_url);
+
+  return SVN_NO_ERROR;
+}
+
+
 svn_error_t *
-svn_ra_serf__get_baseline_info(const char **bc_url,
-                               const char **bc_relative,
-                               svn_ra_serf__session_t *session,
-                               svn_ra_serf__connection_t *conn,
-                               const char *url,
-                               svn_revnum_t revision,
-                               svn_revnum_t *latest_revnum,
-                               apr_pool_t *pool)
+svn_ra_serf__get_youngest_revnum(svn_revnum_t *youngest,
+                                 svn_ra_serf__session_t *session,
+                                 apr_pool_t *scratch_pool)
 {
-  const char *vcc_url, *relative_url, *basecoll_url, *baseline_url;
+  const char *vcc_url;
 
-  /* No URL?  No sweat.  We'll use the session URL. */
-  if (! url)
-    url = session->session_url.path;
+  if (SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(session))
+    return svn_error_trace(svn_ra_serf__v2_get_youngest_revnum(
+                             youngest, session->conns[0], scratch_pool));
 
-  /* If the caller didn't provide a specific connection for us to use,
-     we'll use the default one.  */
-  if (! conn)
-    conn = session->conns[0];
+  SVN_ERR(svn_ra_serf__discover_vcc(&vcc_url, session, NULL, scratch_pool));
+
+  return svn_error_trace(v1_get_youngest_revnum(youngest, NULL,
+                                                session->conns[0], vcc_url,
+                                                scratch_pool, scratch_pool));
+}
+
+
+/* Set *BC_URL to the baseline collection url for REVISION. If REVISION
+   is SVN_INVALID_REVNUM, then the youngest revnum ("HEAD") is used.
+
+   *REVNUM_USED will be set to the revision used.
+
+   Uses the specified CONN, which is part of SESSION.
 
+   All allocations (results and temporary) are performed in POOL.  */
+static svn_error_t *
+get_baseline_info(const char **bc_url,
+                  svn_revnum_t *revnum_used,
+                  svn_ra_serf__session_t *session,
+                  svn_ra_serf__connection_t *conn,
+                  svn_revnum_t revision,
+                  apr_pool_t *pool)
+{
   /* If we detected HTTP v2 support on the server, we can construct
      the baseline collection URL ourselves, and fetch the latest
      revision (if needed) with an OPTIONS request.  */
   if (SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(session))
     {
-      svn_revnum_t actual_revision;
-
       if (SVN_IS_VALID_REVNUM(revision))
         {
-          actual_revision = revision;
+          *revnum_used = revision;
         }
       else
         {
-          svn_ra_serf__options_context_t *opt_ctx;
-
-          SVN_ERR(svn_ra_serf__create_options_req(&opt_ctx, session, conn,
-                                                  session->session_url.path,
-                                                  pool));
-          SVN_ERR(svn_ra_serf__context_run_wait(
-                svn_ra_serf__get_options_done_ptr(opt_ctx), session, pool));
-
-          actual_revision = svn_ra_serf__options_get_youngest_rev(opt_ctx);
-          if (! SVN_IS_VALID_REVNUM(actual_revision))
+          SVN_ERR(svn_ra_serf__v2_get_youngest_revnum(
+                    revnum_used, conn, pool));
+          if (! SVN_IS_VALID_REVNUM(*revnum_used))
             return svn_error_create(SVN_ERR_RA_DAV_OPTIONS_REQ_FAILED, NULL,
                                     _("The OPTIONS response did not include "
                                       "the youngest revision"));
         }
 
-      basecoll_url = apr_psprintf(pool, "%s/%ld",
-                                  session->rev_root_stub, actual_revision);
-      if (latest_revnum)
-        *latest_revnum = actual_revision;
+      *bc_url = apr_psprintf(pool, "%s/%ld",
+                             session->rev_root_stub, *revnum_used);
     }
 
   /* Otherwise, we fall back to the old VCC_URL PROPFIND hunt.  */
   else
     {
+      const char *vcc_url;
+
       SVN_ERR(svn_ra_serf__discover_vcc(&vcc_url, session, conn, pool));
 
       if (SVN_IS_VALID_REVNUM(revision))
         {
           /* First check baseline information cache. */
-          SVN_ERR(svn_ra_serf__blncache_get_bc_url(&basecoll_url,
+          SVN_ERR(svn_ra_serf__blncache_get_bc_url(bc_url,
                                                    session->blncache,
                                                    revision, pool));
-
-          if (!basecoll_url)
+          if (!*bc_url)
             {
-              SVN_ERR(retrieve_baseline_info(NULL, &basecoll_url, session,
-                                             conn, vcc_url, revision, pool));
+              SVN_ERR(retrieve_baseline_info(NULL, bc_url, conn,
+                                             vcc_url, revision, pool, pool));
               SVN_ERR(svn_ra_serf__blncache_set(session->blncache, NULL,
-                                                revision, basecoll_url, pool));
+                                                revision, *bc_url, pool));
             }
 
-          if (latest_revnum)
-            {
-              *latest_revnum = revision;
-            }
+          *revnum_used = revision;
         }
       else
         {
-          apr_hash_t *props;
-          svn_revnum_t actual_revision;
+          SVN_ERR(v1_get_youngest_revnum(revnum_used, bc_url,
+                                         conn, vcc_url,
+                                         pool, pool));
+        }
+    }
 
-          SVN_ERR(svn_ra_serf__retrieve_props(&props, session, conn,
-                                              vcc_url, revision, "0",
-                                              checked_in_props,
-                                              pool, pool));
-          baseline_url = svn_ra_serf__get_ver_prop(props, vcc_url, revision,
-                                                   "DAV:", "checked-in");
-          if (!baseline_url)
-            {
-              return svn_error_create(SVN_ERR_RA_DAV_OPTIONS_REQ_FAILED, NULL,
-                                      _("The OPTIONS response did not include "
-                                        "the requested checked-in value"));
-            }
+  return SVN_NO_ERROR;
+}
 
-          baseline_url = svn_urlpath__canonicalize(baseline_url, pool);
 
-          /* First check baseline information cache. */
-          SVN_ERR(svn_ra_serf__blncache_get_baseline_info(&basecoll_url,
-                                                          &actual_revision,
-                                                          session->blncache,
-                                                          baseline_url,
-                                                          pool));
-          if (!basecoll_url)
-            {
-              SVN_ERR(retrieve_baseline_info(&actual_revision, &basecoll_url,
-                                             session, conn,
-                                             baseline_url, revision, pool));
-              SVN_ERR(svn_ra_serf__blncache_set(session->blncache,
-                                                baseline_url, actual_revision,
-                                                basecoll_url, pool));
-            }
+svn_error_t *
+svn_ra_serf__get_stable_url(const char **stable_url,
+                            svn_revnum_t *latest_revnum,
+                            svn_ra_serf__session_t *session,
+                            svn_ra_serf__connection_t *conn,
+                            const char *url,
+                            svn_revnum_t revision,
+                            apr_pool_t *result_pool,
+                            apr_pool_t *scratch_pool)
+{
+  const char *basecoll_url;
+  const char *repos_relpath;
+  svn_revnum_t revnum_used;
 
-          if (latest_revnum)
-            {
-              *latest_revnum = actual_revision;
-            }
-        }
-    }
+  /* No URL? No sweat. We'll use the session URL.  */
+  if (! url)
+    url = session->session_url.path;
 
-  /* And let's not forget to calculate our relative path. */
-  SVN_ERR(svn_ra_serf__get_relative_path(&relative_url, url, session,
-                                         conn, pool));
+  /* If the caller didn't provide a specific connection for us to use,
+     we'll use the default connection.  */
+  if (! conn)
+    conn = session->conns[0];
+
+  SVN_ERR(get_baseline_info(&basecoll_url, &revnum_used,
+                            session, conn, revision, scratch_pool));
+  SVN_ERR(svn_ra_serf__get_relative_path(&repos_relpath, url,
+                                         session, conn, scratch_pool));
+
+  *stable_url = svn_path_url_add_component2(basecoll_url, repos_relpath,
+                                            result_pool);
+  if (latest_revnum)
+    *latest_revnum = revnum_used;
 
-  *bc_url = basecoll_url;
-  *bc_relative = relative_url;
   return SVN_NO_ERROR;
 }
 
 
 svn_error_t *
-svn_ra_serf__get_resource_type(svn_node_kind_t *kind,
-                               apr_hash_t *props,
-                               const char *url,
-                               svn_revnum_t revision)
+svn_ra_serf__get_resource_type(svn_kind_t *kind,
+                               apr_hash_t *props)
 {
+  apr_hash_t *dav_props;
   const char *res_type;
 
-  res_type = svn_ra_serf__get_ver_prop(props, url, revision,
-                                       "DAV:", "resourcetype");
+  dav_props = apr_hash_get(props, "DAV:", 4);
+  res_type = svn_prop_get_value(dav_props, "resourcetype");
   if (!res_type)
     {
       /* How did this happen? */
       return svn_error_create(SVN_ERR_RA_DAV_PROPS_NOT_FOUND, NULL,
                               _("The PROPFIND response did not include the "
-                              "requested resourcetype value"));
+                                "requested resourcetype value"));
     }
 
   if (strcmp(res_type, "collection") == 0)
     {
-      *kind = svn_node_dir;
+      *kind = svn_kind_dir;
     }
   else
     {
-      *kind = svn_node_file;
+      *kind = svn_kind_file;
     }
 
   return SVN_NO_ERROR;
 }
+
+
+svn_error_t *
+svn_ra_serf__fetch_dav_prop(const char **value,
+                            svn_ra_serf__connection_t *conn,
+                            const char *url,
+                            svn_revnum_t revision,
+                            const char *propname,
+                            apr_pool_t *result_pool,
+                            apr_pool_t *scratch_pool)
+{
+  apr_hash_t *props;
+  apr_hash_t *dav_props;
+
+  SVN_ERR(svn_ra_serf__fetch_node_props(&props, conn, url, revision,
+                                        checked_in_props,
+                                        scratch_pool, scratch_pool));
+  dav_props = apr_hash_get(props, "DAV:", 4);
+  if (dav_props == NULL)
+    return svn_error_create(SVN_ERR_RA_DAV_PROPS_NOT_FOUND, NULL,
+                            _("The PROPFIND response did not include "
+                              "the requested 'DAV:' properties"));
+
+  /* We wouldn't get here if the resource was not found (404), so the
+     property should be present.
+
+     Note: it is okay to call apr_pstrdup() with NULL.  */
+  *value = apr_pstrdup(result_pool, svn_prop_get_value(dav_props, propname));
+
+  return SVN_NO_ERROR;
+}

Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_serf/ra_serf.h?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_serf/ra_serf.h Tue May 29 01:39:41 2012
@@ -26,7 +26,7 @@
 
 
 #include <serf.h>
-#include <expat.h>
+#include <expat.h>  /* for XML_Parser  */
 #include <apr_uri.h>
 
 #include "svn_types.h"
@@ -280,40 +280,14 @@ static const svn_ra_serf__dav_props_t al
   { NULL }
 };
 
-static const svn_ra_serf__dav_props_t vcc_props[] =
-{
-  { "DAV:", "version-controlled-configuration" },
-  { NULL }
-};
-
 static const svn_ra_serf__dav_props_t check_path_props[] =
 {
   { "DAV:", "resourcetype" },
   { NULL }
 };
 
-static const svn_ra_serf__dav_props_t uuid_props[] =
-{
-  { SVN_DAV_PROP_NS_DAV, "repository-uuid" },
-  { NULL }
-};
-
-static const svn_ra_serf__dav_props_t repos_root_props[] =
-{
-  { SVN_DAV_PROP_NS_DAV, "baseline-relative-path" },
-  { NULL }
-};
-
-static const svn_ra_serf__dav_props_t href_props[] =
-{
-  { "DAV:", "href" },
-  { NULL }
-};
-
 /* WC props compatibility with ra_neon. */
-#define SVN_RA_SERF__WC_NAMESPACE SVN_PROP_WC_PREFIX "ra_dav:"
-#define SVN_RA_SERF__WC_ACTIVITY_URL SVN_RA_SERF__WC_NAMESPACE "activity-url"
-#define SVN_RA_SERF__WC_CHECKED_IN_URL SVN_RA_SERF__WC_NAMESPACE "version-url"
+#define SVN_RA_SERF__WC_CHECKED_IN_URL SVN_PROP_WC_PREFIX "ra_dav:version-url"
 
 /** Serf utility functions **/
 
@@ -364,7 +338,7 @@ typedef svn_error_t *
 (*svn_ra_serf__response_handler_t)(serf_request_t *request,
                                    serf_bucket_t *response,
                                    void *handler_baton,
-                                   apr_pool_t *pool);
+                                   apr_pool_t *scratch_pool);
 
 /* Callback for when a request body is needed. */
 /* ### should pass a scratch_pool  */
@@ -388,6 +362,9 @@ typedef svn_error_t *
                                  int status_code,
                                  void *baton);
 
+/* ### we should reorder the types in this file.  */
+typedef struct svn_ra_serf__server_error_t svn_ra_serf__server_error_t;
+
 /*
  * Structure that can be passed to our default handler to guide the
  * execution of the request through its lifecycle.
@@ -402,10 +379,24 @@ typedef struct svn_ra_serf__handler_t {
   /* The content-type of the request body. */
   const char *body_type;
 
+  /* Has the request/response been completed?  */
+  svn_boolean_t done;
+
+  /* If we captured an error from the server, then this will be non-NULL.
+     It will be allocated from HANDLER_POOL.  */
+  svn_ra_serf__server_error_t *server_error;
+
   /* The handler and baton pair for our handler. */
   svn_ra_serf__response_handler_t response_handler;
   void *response_baton;
 
+  /* When REPONSE_HANDLER is invoked, the following fields will be set
+     based on the response header. HANDLER_POOL must be non-NULL for these
+     values to be filled in. SLINE.REASON and LOCATION will be allocated
+     within HANDLER_POOL.  */
+  serf_status_line sline;  /* The parsed Status-Line  */
+  const char *location;  /* The Location: header, if any  */
+
   /* The handler and baton pair to be executed when a non-recoverable error
    * is detected.  If it is NULL in the presence of an error, an abort() may
    * be triggered.
@@ -437,8 +428,34 @@ typedef struct svn_ra_serf__handler_t {
   /* The connection and session to be used for this request. */
   svn_ra_serf__connection_t *conn;
   svn_ra_serf__session_t *session;
+
+  /* Internal flag to indicate we've parsed the headers.  */
+  svn_boolean_t reading_body;
+
+  /* When this flag will be set, the core handler will discard any unread
+     portion of the response body. The registered response handler will
+     no longer be called.  */
+  svn_boolean_t discard_body;
+
+  /* Pool for allocating SLINE.REASON and LOCATION. If this pool is NULL,
+     then the requestor does not care about SLINE and LOCATION.  */
+  apr_pool_t *handler_pool;
+
 } svn_ra_serf__handler_t;
 
+
+/* Run one request and process the response.
+
+   Similar to context_run_wait(), but this creates the request for HANDLER
+   and then waits for it to complete.
+
+   WARNING: context_run_wait() does NOT create a request, whereas this
+   function DOES. Avoid a double-create.  */
+svn_error_t *
+svn_ra_serf__context_run_one(svn_ra_serf__handler_t *handler,
+                             apr_pool_t *scratch_pool);
+
+
 /*
  * Helper function to queue a request in the @a handler's connection.
  */
@@ -532,16 +549,6 @@ struct svn_ra_serf__xml_parser_t {
   /* Our previously used states (will be reused). */
   svn_ra_serf__xml_state_t *free_state;
 
-  /* If non-NULL, the status code of the response will be stored here.
-   *
-   * If this is NULL and an error is received, an abort will be triggered.
-   */
-  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.
    */
@@ -601,10 +608,164 @@ struct svn_ra_serf__xml_parser_t {
   apr_off_t read_size; /* Number of bytes read from response */
 };
 
+
+/* v2 of the XML parsing functions  */
+
+/* The XML parsing context.  */
+typedef struct svn_ra_serf__xml_context_t svn_ra_serf__xml_context_t;
+
+
+/* An opaque structure for the XML parse element/state.  */
+typedef struct svn_ra_serf__xml_estate_t svn_ra_serf__xml_estate_t;
+
+/* Called just after the parser moves into ENTERED_STATE.  */
+typedef svn_error_t *
+(*svn_ra_serf__xml_opened_t)(svn_ra_serf__xml_estate_t *xes,
+                             void *baton,
+                             int entered_state,
+                             apr_pool_t *scratch_pool);
+
+
+/* Called just before the parser leaves LEAVING_STATE.
+
+   If cdata collection was enabled for this state, then CDATA will be
+   non-NULL and contain the collected cdata.
+
+   If attribute collection was enabled for this state, then ATTRS will
+   contain the attributes collected for this element only. Use
+   svn_ra_serf__xml_gather_since() to gather up data from outer states.
+   ATTRS is char* -> char*.
+
+   Temporary allocations may be made in SCRATCH_POOL.  */
+typedef svn_error_t *
+(*svn_ra_serf__xml_closed_t)(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);
+
+
+/* State transition table.
+
+   When the XML Context is constructed, it is in state 0. User states are
+   positive integers.
+
+   In a list of transitions, use { 0 } to indicate the end. Specifically,
+   the code looks for NS == NULL.
+
+   ### more docco
+*/
+typedef struct svn_ra_serf__xml_transition_t {
+  /* This transition applies when in this state  */
+  int from_state;
+
+  /* And when this tag is observed  */
+  const char *ns;
+  const char *name;
+
+  /* Moving to this state  */
+  int to_state;
+
+  /* Should the cdata of NAME be collected?  */
+  svn_boolean_t collect_cdata;
+
+  /* Which attributes of NAME should be collected? Terminate with NULL.
+     Maximum of 10 attributes may be collected. Note that attribute
+     namespaces are ignored at this time.
+
+     Attribute names beginning with "?" are optional. Other names must
+     exist on the element, or SVN_ERR_XML_ATTRIB_NOT_FOUND will be raised.  */
+  const char *collect_attrs[11];
+
+  /* When NAME is opened, should the callback be invoked?  */
+  svn_boolean_t custom_open;
+
+  /* When NAME is closed, should the callback be invoked?  */
+  svn_boolean_t custom_close;
+
+} svn_ra_serf__xml_transition_t;
+
+
+svn_ra_serf__xml_context_t *
+svn_ra_serf__xml_context_create(
+  const svn_ra_serf__xml_transition_t *ttable,
+  svn_ra_serf__xml_opened_t opened_cb,
+  svn_ra_serf__xml_closed_t closed_cb,
+  void *baton,
+  apr_pool_t *result_pool);
+
+
+/* Construct a handler with the response function/baton set up to parse
+   a response body using the given XML context. The handler and its
+   internal structures are allocated in RESULT_POOL.
+
+   This also initializes HANDLER_POOL to the given RESULT_POOL.  */
+svn_ra_serf__handler_t *
+svn_ra_serf__create_expat_handler(svn_ra_serf__xml_context_t *xmlctx,
+                                  apr_pool_t *result_pool);
+
+
+/* Allocated within XES->STATE_POOL. Changes are not allowd. Make a deep
+   copy, as appropriate.
+
+   The resulting hash maps char* names to char* values.  */
+apr_hash_t *
+svn_ra_serf__xml_gather_since(svn_ra_serf__xml_estate_t *xes,
+                              int stop_state);
+
+
+/* Attach the NAME/VALUE pair onto this/parent state identified by STATE.
+   The name and value will be copied into the target state's pool.
+
+   These values will be available to the CLOSED_CB for the target state,
+   or part of the gathered state via xml_gather_since().
+
+   Typically, this function is used by a child state's close callback,
+   or within an opening callback to store additional data.
+
+   Note: if the state is not found, then a programmer error has occurred,
+   so the function will invoke SVN_ERR_MALFUNCTION().  */
+void
+svn_ra_serf__xml_note(svn_ra_serf__xml_estate_t *xes,
+                      int state,
+                      const char *name,
+                      const char *value);
+
+
+/* Returns XES->STATE_POOL for allocating structures that should live
+   as long as the state identified by XES.  */
+apr_pool_t *
+svn_ra_serf__xml_state_pool(svn_ra_serf__xml_estate_t *xes);
+
+
+/* Any XML parser may be used. When an opening tag is seen, call this
+   function to feed the information into XMLCTX.  */
+svn_error_t *
+svn_ra_serf__xml_cb_start(svn_ra_serf__xml_context_t *xmlctx,
+                          const char *raw_name,
+                          const char *const *attrs);
+
+
+/* When a close tag is seen, call this function to feed the information
+   into XMLCTX.  */
+svn_error_t *
+svn_ra_serf__xml_cb_end(svn_ra_serf__xml_context_t *xmlctx,
+                        const char *raw_name);
+
+
+/* When cdata is parsed by the wrapping XML parser, call this function to
+   feed the cdata into the XMLCTX.  */
+svn_error_t *
+svn_ra_serf__xml_cb_cdata(svn_ra_serf__xml_context_t *xmlctx,
+                          const char *data,
+                          apr_size_t len);
+
+
 /*
  * Parses a server-side error message into a local Subversion error.
  */
-typedef struct svn_ra_serf__server_error_t {
+struct svn_ra_serf__server_error_t {
   /* Our local representation of the error. */
   svn_error_t *error;
 
@@ -631,41 +792,8 @@ typedef struct svn_ra_serf__server_error
 
   /* XML parser and namespace used to parse the remote response */
   svn_ra_serf__xml_parser_t parser;
-} svn_ra_serf__server_error_t;
-
-/* A simple request context that can be passed to handle_status_only. */
-typedef struct svn_ra_serf__simple_request_context_t {
-  apr_pool_t *pool;
-
-  /* The HTTP status code of the response */
-  int status;
-
-  /* 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;
-
-  /* If an error occurred, this value will be initialized. */
-  svn_ra_serf__server_error_t server_error;
-} svn_ra_serf__simple_request_context_t;
+};
 
-/*
- * Serf handler for @a request / @a response pair that takes in a
- * @a baton (@see svn_ra_serf__simple_request_context_t).
- * Implements svn_ra_serf__response_handler_t.
- *
- * Temporary allocations are made in @a pool.
- */
-svn_error_t *
-svn_ra_serf__handle_status_only(serf_request_t *request,
-                                serf_bucket_t *response,
-                                void *baton,
-                                apr_pool_t *pool);
 
 /*
  * Handler that discards the entire @a response body associated with a
@@ -682,32 +810,45 @@ svn_ra_serf__handle_discard_body(serf_re
                                  void *baton,
                                  apr_pool_t *pool);
 
-/*
- * Handler that retrieves the embedded XML error response from the
- * the @a response body associated with a @a request.
- * Implements svn_ra_serf__response_handler_t.
- *
- * All temporary allocations will be made in a @a pool.
- */
-svn_error_t *
-svn_ra_serf__handle_server_error(serf_request_t *request,
-                                 serf_bucket_t *response,
-                                 apr_pool_t *pool);
 
 /*
  * Handler that retrieves the embedded XML multistatus response from the
- * the @a RESPONSE body associated with a @a REQUEST. *DONE is set to TRUE.
+ * the @a RESPONSE body associated with a @a REQUEST.
+ *
  * Implements svn_ra_serf__response_handler_t.
  *
- * The @a BATON should be of type svn_ra_serf__simple_request_context_t.
+ * The @a BATON should be of type svn_ra_serf__handler_t. When the request
+ * is complete, the handler's DONE flag will be set to TRUE.
  *
- * All temporary allocations will be made in a @a pool.
+ * All temporary allocations will be made in a @a scratch_pool.
  */
 svn_error_t *
 svn_ra_serf__handle_multistatus_only(serf_request_t *request,
                                      serf_bucket_t *response,
                                      void *baton,
-                                     apr_pool_t *pool);
+                                     apr_pool_t *scratch_pool);
+
+
+/* Handler that expects an empty body.
+
+   If a body IS present, and it is text/xml, then it will be parsed for
+   a server-side error.
+
+   BATON should be the svn_ra_serf__handler_t running REQUEST.
+
+   Status line information will be in HANDLER->SLINE.
+
+   Any parsed errors will be left in HANDLER->SERVER_ERROR. That member
+   may be NULL if no body was present, or a problem occurred trying to
+   parse the body.
+
+   All temporary allocations will be made in SCRATCH_POOL.  */
+svn_error_t *
+svn_ra_serf__expect_empty_body(serf_request_t *request,
+                               serf_bucket_t *response,
+                               void *baton,
+                               apr_pool_t *scratch_pool);
+
 
 /*
  * This function will feed the RESPONSE body into XMLP.  When parsing is
@@ -827,12 +968,12 @@ svn_ra_serf__add_cdata_len_buckets(serf_
  * Look up the @a attrs array for namespace definitions and add each one
  * to the @a ns_list of namespaces.
  *
- * New namespaces will be allocated in @a pool.
+ * New namespaces will be allocated in RESULT_POOL.
  */
 void
 svn_ra_serf__define_ns(svn_ra_serf__ns_t **ns_list,
-                       const char **attrs,
-                       apr_pool_t *pool);
+                       const char *const *attrs,
+                       apr_pool_t *result_pool);
 
 /*
  * Look up @a name in the @a ns_list list for previously declared namespace
@@ -843,7 +984,7 @@ svn_ra_serf__define_ns(svn_ra_serf__ns_t
  */
 void
 svn_ra_serf__expand_ns(svn_ra_serf__dav_props_t *returned_prop_name,
-                       svn_ra_serf__ns_t *ns_list,
+                       const svn_ra_serf__ns_t *ns_list,
                        const char *name);
 
 
@@ -858,11 +999,6 @@ typedef struct svn_ra_serf__propfind_con
 svn_boolean_t
 svn_ra_serf__propfind_is_done(svn_ra_serf__propfind_context_t *ctx);
 
-/*
- * Returns the response status code of the PROPFIND @a ctx.
- */
-int
-svn_ra_serf__propfind_status_code(svn_ra_serf__propfind_context_t *ctx);
 
 /*
  * This function will deliver a PROP_CTX PROPFIND request in the SESS
@@ -913,6 +1049,50 @@ svn_ra_serf__retrieve_props(apr_hash_t *
                             apr_pool_t *result_pool,
                             apr_pool_t *scratch_pool);
 
+
+/* Using CONN, fetch the properties specified by WHICH_PROPS using CONN
+   for URL at REVISION. The resulting properties are placed into a 2-level
+   hash in RESULTS, mapping NAMESPACE -> hash<PROPNAME, PROPVALUE>, which
+   is allocated in RESULT_POOL.
+
+   If REVISION is SVN_INVALID_REVNUM, then the properties are fetched
+   from HEAD for URL.
+
+   This function performs the request synchronously.
+
+   Temporary allocations are made in SCRATCH_POOL.  */
+svn_error_t *
+svn_ra_serf__fetch_node_props(apr_hash_t **results,
+                              svn_ra_serf__connection_t *conn,
+                              const char *url,
+                              svn_revnum_t revision,
+                              const svn_ra_serf__dav_props_t *which_props,
+                              apr_pool_t *result_pool,
+                              apr_pool_t *scratch_pool);
+
+
+/* Using CONN, fetch a DAV: property from the resource identified by URL
+   within REVISION. The PROPNAME may be one of:
+
+     "checked-in"
+     "href"
+
+   The resulting value will be allocated in RESULT_POOL, and may be NULL
+   if the property does not exist (note: "href" always exists).
+
+   This function performs the request synchronously.
+
+   Temporary allocations are made in SCRATCH_POOL.  */
+svn_error_t *
+svn_ra_serf__fetch_dav_prop(const char **value,
+                            svn_ra_serf__connection_t *conn,
+                            const char *url,
+                            svn_revnum_t revision,
+                            const char *propname,
+                            apr_pool_t *result_pool,
+                            apr_pool_t *scratch_pool);
+
+
 /* Set PROPS for PATH at REV revision with a NS:NAME VAL.
  *
  * The POOL governs allocation.
@@ -941,6 +1121,15 @@ svn_ra_serf__walk_all_props(apr_hash_t *
                             void *baton,
                             apr_pool_t *pool);
 
+
+/* Like walk_all_props(), but a 2-level hash.  */
+svn_error_t *
+svn_ra_serf__walk_node_props(apr_hash_t *props,
+                             svn_ra_serf__walker_visitor_t walker,
+                             void *baton,
+                             apr_pool_t *scratch_pool);
+
+
 typedef svn_error_t *
 (*svn_ra_serf__path_rev_walker_t)(void *baton,
                                   const char *path, apr_ssize_t path_len,
@@ -979,9 +1168,8 @@ svn_ra_serf__select_revprops(apr_hash_t 
                              apr_pool_t *scratch_pool);
 
 
-/* PROPS is nested hash tables mapping REV -> PATH -> NS -> NAME -> VALUE.
-   This function takes the tree of tables identified by PATH and REVISION
-   (resulting in NS:NAME:VALUE hashes) and flattens them into a set of
+/* PROPS is nested hash tables mapping NS -> NAME -> VALUE.
+   This function takes the NS:NAME:VALUE hashes and flattens them into a set of
    names to VALUE. The names are composed of NS:NAME, with specific
    rewrite from wire names (DAV) to SVN names. This mapping is managed
    by the svn_ra_serf__set_baton_props() function.
@@ -994,8 +1182,6 @@ svn_ra_serf__select_revprops(apr_hash_t 
 svn_error_t *
 svn_ra_serf__flatten_props(apr_hash_t **flat_props,
                            apr_hash_t *props,
-                           const char *path,
-                           svn_revnum_t revision,
                            apr_pool_t *result_pool,
                            apr_pool_t *scratch_pool);
 
@@ -1035,10 +1221,8 @@ svn_ra_serf__set_prop(apr_hash_t *props,
                       const svn_string_t *val, apr_pool_t *pool);
 
 svn_error_t *
-svn_ra_serf__get_resource_type(svn_node_kind_t *kind,
-                               apr_hash_t *props,
-                               const char *url,
-                               svn_revnum_t revision);
+svn_ra_serf__get_resource_type(svn_kind_t *kind,
+                               apr_hash_t *props);
 
 
 /** MERGE-related functions **/
@@ -1077,28 +1261,35 @@ svn_ra_serf__merge_create_req(svn_ra_ser
 
 /** OPTIONS-related functions **/
 
-typedef struct svn_ra_serf__options_context_t svn_ra_serf__options_context_t;
+/* On HTTPv2 connections, run an OPTIONS request over CONN to fetch the
+   current youngest revnum, returning it in *YOUNGEST.
 
-/* Is this OPTIONS-request done yet? */
-svn_boolean_t*
-svn_ra_serf__get_options_done_ptr(svn_ra_serf__options_context_t *ctx);
+   (the revnum is headers of the OPTIONS response)
 
-const char *
-svn_ra_serf__options_get_activity_collection(svn_ra_serf__options_context_t *ctx);
+   This function performs the request synchronously.
 
-svn_revnum_t
-svn_ra_serf__options_get_youngest_rev(svn_ra_serf__options_context_t *ctx);
+   All temporary allocations will be made in SCRATCH_POOL.  */
+svn_error_t *
+svn_ra_serf__v2_get_youngest_revnum(svn_revnum_t *youngest,
+                                    svn_ra_serf__connection_t *conn,
+                                    apr_pool_t *scratch_pool);
+
+
+/* On HTTPv1 connections, run an OPTIONS request over CONN to fetch the
+   activity collection set and return it in *ACTIVITY_URL, allocated
+   from RESULT_POOL.
+
+   (the activity-collection-set is in the body of the OPTIONS response)
+
+   This function performs the request synchronously.
+
+   All temporary allocations will be made in SCRATCH_POOL.  */
+svn_error_t *
+svn_ra_serf__v1_get_activity_collection(const char **activity_url,
+                                        svn_ra_serf__connection_t *conn,
+                                        apr_pool_t *result_pool,
+                                        apr_pool_t *scratch_pool);
 
-/* Create an OPTIONS request.  When run, ask for an
-   activity-collection-set in the request body (retrievable via
-   accessor above) and also parse the server's capability headers into
-   the SESSION->capabilites hash. */
-svn_error_t *
-svn_ra_serf__create_options_req(svn_ra_serf__options_context_t **opt_ctx,
-                                svn_ra_serf__session_t *session,
-                                svn_ra_serf__connection_t *conn,
-                                const char *path,
-                                apr_pool_t *pool);
 
 /* Set @a VCC_URL to the default VCC for our repository based on @a
  * ORIG_PATH for the session @a SESSION, ensuring that the VCC URL and
@@ -1138,34 +1329,63 @@ svn_ra_serf__get_relative_path(const cha
                                svn_ra_serf__connection_t *conn,
                                apr_pool_t *pool);
 
-/* Set *BC_URL to the baseline collection url, and set *BC_RELATIVE to
- * the path relative to that url for URL in REVISION using SESSION.
- * BC_RELATIVE will be URI decoded.
- *
- * REVISION may be SVN_INVALID_REVNUM (to mean "the current HEAD
- * revision").  If URL is NULL, use SESSION's session url.
- *
- * If LATEST_REVNUM is not NULL, set it to the baseline revision. If
- * REVISION was set to SVN_INVALID_REVNUM, this will return the current
- * HEAD revision.
- *
- * If non-NULL, use CONN for communications with the server;
- * otherwise, use the default connection.
- *
- * Use POOL for all allocations.
- */
+
+/* Using the default connection in SESSION (conns[0]), get the youngest
+   revnum from the server, returning it in *YOUNGEST.
+
+   This function operates synchronously.
+
+   All temporary allocations are performed in SCRATCH_POOL.  */
 svn_error_t *
-svn_ra_serf__get_baseline_info(const char **bc_url,
-                               const char **bc_relative,
-                               svn_ra_serf__session_t *session,
-                               svn_ra_serf__connection_t *conn,
-                               const char *url,
-                               svn_revnum_t revision,
-                               svn_revnum_t *latest_revnum,
-                               apr_pool_t *pool);
+svn_ra_serf__get_youngest_revnum(svn_revnum_t *youngest,
+                                 svn_ra_serf__session_t *session,
+                                 apr_pool_t *scratch_pool);
+
+
+/* Generate a revision-stable URL.
+
+   The RA APIs all refer to user/public URLs that float along with the
+   youngest revision. In many cases, we do NOT want to work with that URL
+   since it can change from one moment to the next. Especially if we
+   attempt to operation against multiple floating URLs -- we could end up
+   referring to two separate revisions.
+
+   The DAV RA provider(s) solve this by generating a URL that is specific
+   to a revision by using a URL into a "baseline collection".
+
+   For a specified SESSION, with an optional CONN (if NULL, then the
+   session's default connection will be used; specifically SESSION->conns[0]),
+   generate a revision-stable URL for URL at REVISION. If REVISION is
+   SVN_INVALID_REVNUM, then the stable URL will refer to the youngest
+   revision at the time this function was called.
+
+   If URL is NULL, then the session root will be used.
+
+   The stable URL will be placed into *STABLE_URL, allocated from RESULT_POOL.
+
+   If LATEST_REVNUM is not NULL, then the revision used will be placed into
+   *LATEST_REVNUM. That will be equal to youngest, or the given REVISION.
+
+   This function operates synchronously, if any communication to the server
+   is required. Communication is needed if REVISION is SVN_INVALID_REVNUM
+   (to get the current youngest revnum), or if the specified REVISION is not
+   (yet) in our cache of baseline collections.
+
+   All temporary allocations are performed in SCRATCH_POOL.  */
+svn_error_t *
+svn_ra_serf__get_stable_url(const char **stable_url,
+                            svn_revnum_t *latest_revnum,
+                            svn_ra_serf__session_t *session,
+                            svn_ra_serf__connection_t *conn,
+                            const char *url,
+                            svn_revnum_t revision,
+                            apr_pool_t *result_pool,
+                            apr_pool_t *scratch_pool);
+
 
 /** RA functions **/
 
+/* Implements svn_ra__vtable_t.get_log(). */
 svn_error_t *
 svn_ra_serf__get_log(svn_ra_session_t *session,
                      const apr_array_header_t *paths,
@@ -1180,6 +1400,7 @@ svn_ra_serf__get_log(svn_ra_session_t *s
                      void *receiver_baton,
                      apr_pool_t *pool);
 
+/* Implements svn_ra__vtable_t.get_locations(). */
 svn_error_t *
 svn_ra_serf__get_locations(svn_ra_session_t *session,
                            apr_hash_t **locations,
@@ -1188,6 +1409,7 @@ svn_ra_serf__get_locations(svn_ra_sessio
                            const apr_array_header_t *location_revisions,
                            apr_pool_t *pool);
 
+/* Implements svn_ra__vtable_t.get_location_segments(). */
 svn_error_t *
 svn_ra_serf__get_location_segments(svn_ra_session_t *session,
                                    const char *path,
@@ -1198,6 +1420,7 @@ svn_ra_serf__get_location_segments(svn_r
                                    void *receiver_baton,
                                    apr_pool_t *pool);
 
+/* Implements svn_ra__vtable_t.do_diff(). */
 svn_error_t *
 svn_ra_serf__do_diff(svn_ra_session_t *session,
                      const svn_ra_reporter3_t **reporter,
@@ -1212,6 +1435,7 @@ svn_ra_serf__do_diff(svn_ra_session_t *s
                      void *diff_baton,
                      apr_pool_t *pool);
 
+/* Implements svn_ra__vtable_t.do_status(). */
 svn_error_t *
 svn_ra_serf__do_status(svn_ra_session_t *ra_session,
                        const svn_ra_reporter3_t **reporter,
@@ -1223,6 +1447,7 @@ svn_ra_serf__do_status(svn_ra_session_t 
                        void *status_baton,
                        apr_pool_t *pool);
 
+/* Implements svn_ra__vtable_t.do_update(). */
 svn_error_t *
 svn_ra_serf__do_update(svn_ra_session_t *ra_session,
                        const svn_ra_reporter3_t **reporter,
@@ -1235,6 +1460,7 @@ svn_ra_serf__do_update(svn_ra_session_t 
                        void *update_baton,
                        apr_pool_t *pool);
 
+/* Implements svn_ra__vtable_t.do_switch(). */
 svn_error_t *
 svn_ra_serf__do_switch(svn_ra_session_t *ra_session,
                        const svn_ra_reporter3_t **reporter,
@@ -1247,6 +1473,7 @@ svn_ra_serf__do_switch(svn_ra_session_t 
                        void *switch_baton,
                        apr_pool_t *pool);
 
+/* Implements svn_ra__vtable_t.get_file_revs(). */
 svn_error_t *
 svn_ra_serf__get_file_revs(svn_ra_session_t *session,
                            const char *path,
@@ -1257,12 +1484,14 @@ svn_ra_serf__get_file_revs(svn_ra_sessio
                            void *handler_baton,
                            apr_pool_t *pool);
 
+/* Implements svn_ra__vtable_t.get_dated_revision(). */
 svn_error_t *
 svn_ra_serf__get_dated_revision(svn_ra_session_t *session,
                                 svn_revnum_t *revision,
                                 apr_time_t tm,
                                 apr_pool_t *pool);
 
+/* Implements svn_ra__vtable_t.get_commit_editor(). */
 svn_error_t *
 svn_ra_serf__get_commit_editor(svn_ra_session_t *session,
                                const svn_delta_editor_t **editor,
@@ -1274,6 +1503,7 @@ svn_ra_serf__get_commit_editor(svn_ra_se
                                svn_boolean_t keep_locks,
                                apr_pool_t *pool);
 
+/* Implements svn_ra__vtable_t.get_file(). */
 svn_error_t *
 svn_ra_serf__get_file(svn_ra_session_t *session,
                       const char *path,
@@ -1283,6 +1513,7 @@ svn_ra_serf__get_file(svn_ra_session_t *
                       apr_hash_t **props,
                       apr_pool_t *pool);
 
+/* Implements svn_ra__vtable_t.change_rev_prop(). */
 svn_error_t *
 svn_ra_serf__change_rev_prop(svn_ra_session_t *session,
                              svn_revnum_t rev,
@@ -1291,6 +1522,7 @@ svn_ra_serf__change_rev_prop(svn_ra_sess
                              const svn_string_t *value,
                              apr_pool_t *pool);
 
+/* Implements svn_ra__vtable_t.replay(). */
 svn_error_t *
 svn_ra_serf__replay(svn_ra_session_t *ra_session,
                     svn_revnum_t revision,
@@ -1300,6 +1532,7 @@ svn_ra_serf__replay(svn_ra_session_t *ra
                     void *edit_baton,
                     apr_pool_t *pool);
 
+/* Implements svn_ra__vtable_t.replay_range(). */
 svn_error_t *
 svn_ra_serf__replay_range(svn_ra_session_t *ra_session,
                           svn_revnum_t start_revision,
@@ -1311,6 +1544,7 @@ svn_ra_serf__replay_range(svn_ra_session
                           void *replay_baton,
                           apr_pool_t *pool);
 
+/* Implements svn_ra__vtable_t.lock(). */
 svn_error_t *
 svn_ra_serf__lock(svn_ra_session_t *ra_session,
                   apr_hash_t *path_revs,
@@ -1320,6 +1554,7 @@ svn_ra_serf__lock(svn_ra_session_t *ra_s
                   void *lock_baton,
                   apr_pool_t *pool);
 
+/* Implements svn_ra__vtable_t.unlock(). */
 svn_error_t *
 svn_ra_serf__unlock(svn_ra_session_t *ra_session,
                     apr_hash_t *path_tokens,
@@ -1328,12 +1563,14 @@ svn_ra_serf__unlock(svn_ra_session_t *ra
                     void *lock_baton,
                     apr_pool_t *pool);
 
+/* Implements svn_ra__vtable_t.get_lock(). */
 svn_error_t *
 svn_ra_serf__get_lock(svn_ra_session_t *ra_session,
                       svn_lock_t **lock,
                       const char *path,
                       apr_pool_t *pool);
 
+/* Implements svn_ra__vtable_t.get_locks(). */
 svn_error_t *
 svn_ra_serf__get_locks(svn_ra_session_t *ra_session,
                        apr_hash_t **locks,
@@ -1341,13 +1578,19 @@ svn_ra_serf__get_locks(svn_ra_session_t 
                        svn_depth_t depth,
                        apr_pool_t *pool);
 
-svn_error_t * svn_ra_serf__get_mergeinfo(svn_ra_session_t *ra_session,
-                                         apr_hash_t **mergeinfo,
-                                         const apr_array_header_t *paths,
-                                         svn_revnum_t revision,
-                                         svn_mergeinfo_inheritance_t inherit,
-                                         svn_boolean_t include_descendants,
-                                         apr_pool_t *pool);
+/* Request a mergeinfo-report from the URL attached to SESSION,
+   and fill in the MERGEINFO hash with the results.
+
+   Implements svn_ra__vtable_t.get_mergeinfo().
+ */
+svn_error_t *
+svn_ra_serf__get_mergeinfo(svn_ra_session_t *ra_session,
+                           apr_hash_t **mergeinfo,
+                           const apr_array_header_t *paths,
+                           svn_revnum_t revision,
+                           svn_mergeinfo_inheritance_t inherit,
+                           svn_boolean_t include_descendants,
+                           apr_pool_t *pool);
 
 /* Exchange capabilities with the server, by sending an OPTIONS
  * request announcing the client's capabilities, and by filling
@@ -1366,14 +1609,14 @@ svn_ra_serf__exchange_capabilities(svn_r
                                    const char **corrected_url,
                                    apr_pool_t *pool);
 
-/* Implements the has_capability RA layer function. */
+/* Implements svn_ra__vtable_t.has_capability(). */
 svn_error_t *
 svn_ra_serf__has_capability(svn_ra_session_t *ra_session,
                             svn_boolean_t *has,
                             const char *capability,
                             apr_pool_t *pool);
 
-/* Implements the get_deleted_rev RA layer function. */
+/* Implements svn_ra__vtable_t.get_deleted_rev(). */
 svn_error_t *
 svn_ra_serf__get_deleted_rev(svn_ra_session_t *session,
                              const char *path,
@@ -1382,6 +1625,18 @@ svn_ra_serf__get_deleted_rev(svn_ra_sess
                              svn_revnum_t *revision_deleted,
                              apr_pool_t *pool);
 
+/* Implements svn_ra__vtable_t.get_repos_root(). */
+svn_error_t *
+svn_ra_serf__get_repos_root(svn_ra_session_t *ra_session,
+                            const char **url,
+                            apr_pool_t *pool);
+
+/* Implements svn_ra__vtable_t.register_editor_shim_callbacks(). */
+svn_error_t *
+svn_ra_serf__register_editor_shim_callbacks(svn_ra_session_t *session,
+                                    svn_delta_shim_callbacks_t *callbacks);
+
+
 /*** Authentication handler declarations ***/
 
 /**
@@ -1408,16 +1663,14 @@ svn_ra_serf__error_on_status(int status_
                              const char *path,
                              const char *location);
 
-svn_error_t *
-svn_ra_serf__register_editor_shim_callbacks(svn_ra_session_t *session,
-                                    svn_delta_shim_callbacks_t *callbacks);
-
-
+/* ###? */
 svn_error_t *
 svn_ra_serf__copy_into_spillbuf(svn_spillbuf_t **spillbuf,
                                 serf_bucket_t *bkt,
                                 apr_pool_t *result_pool,
                                 apr_pool_t *scratch_pool);
+
+/* ###? */
 serf_bucket_t *
 svn_ra_serf__create_sb_bucket(svn_spillbuf_t *spillbuf,
                               serf_bucket_alloc_t *allocator,
@@ -1425,12 +1678,6 @@ svn_ra_serf__create_sb_bucket(svn_spillb
                               apr_pool_t *scratch_pool);
 
 
-svn_error_t *
-svn_ra_serf__get_repos_root(svn_ra_session_t *ra_session,
-                            const char **url,
-                            apr_pool_t *pool);
-
-
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_serf/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_serf/replay.c?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_serf/replay.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_serf/replay.c Tue May 29 01:39:41 2012
@@ -24,9 +24,6 @@
 
 
 #include <apr_uri.h>
-
-#include <expat.h>
-
 #include <serf.h>
 
 #include "svn_pools.h"
@@ -198,13 +195,12 @@ start_replay(svn_ra_serf__xml_parser_t *
       ctx->dst_rev_pool = svn_pool_create(ctx->src_rev_pool);
       ctx->file_pool = svn_pool_create(ctx->dst_rev_pool);
 
-      /* ### it would be nice to have a proper scratch_pool.  */
       SVN_ERR(svn_ra_serf__select_revprops(&ctx->props,
                                            ctx->revprop_target,
                                            ctx->revprop_rev,
                                            ctx->revs_props,
                                            ctx->dst_rev_pool,
-                                           ctx->dst_rev_pool));
+                                           scratch_pool));
 
       if (ctx->revstart_func)
         {
@@ -228,7 +224,7 @@ start_replay(svn_ra_serf__xml_parser_t *
 
       SVN_ERR(ctx->editor->set_target_revision(ctx->editor_baton,
                                                SVN_STR_TO_REV(rev),
-                                               ctx->dst_rev_pool));
+                                               scratch_pool));
     }
   else if (state == REPORT &&
            strcmp(name.name, "open-root") == 0)
@@ -273,7 +269,7 @@ start_replay(svn_ra_serf__xml_parser_t *
       info = push_state(parser, ctx, DELETE_ENTRY);
 
       SVN_ERR(ctx->editor->delete_entry(file_name, SVN_STR_TO_REV(rev),
-                                        info->baton, ctx->dst_rev_pool));
+                                        info->baton, scratch_pool));
 
       svn_ra_serf__xml_pop_state(parser);
     }
@@ -334,7 +330,7 @@ start_replay(svn_ra_serf__xml_parser_t *
     {
       replay_info_t *info = parser->state->private;
 
-      SVN_ERR(ctx->editor->close_directory(info->baton, ctx->dst_rev_pool));
+      SVN_ERR(ctx->editor->close_directory(info->baton, scratch_pool));
 
       svn_ra_serf__xml_pop_state(parser);
     }
@@ -426,8 +422,7 @@ start_replay(svn_ra_serf__xml_parser_t *
 
       checksum = svn_xml_get_attr_value("checksum", attrs);
 
-      SVN_ERR(ctx->editor->close_file(info->baton, checksum,
-                                      ctx->file_pool));
+      SVN_ERR(ctx->editor->close_file(info->baton, checksum, scratch_pool));
 
       svn_ra_serf__xml_pop_state(parser);
     }
@@ -643,10 +638,6 @@ svn_ra_serf__replay(svn_ra_session_t *ra
   svn_ra_serf__xml_parser_t *parser_ctx;
   svn_error_t *err;
   const char *report_target;
-  /* We're not really interested in the status code here in replay, but
-     the XML parsing code will abort on error if it doesn't have a place
-     to store the response status code. */
-  int status_code;
 
   SVN_ERR(svn_ra_serf__report_resource(&report_target, session, NULL, pool));
 
@@ -663,6 +654,7 @@ svn_ra_serf__replay(svn_ra_session_t *ra
 
   handler = apr_pcalloc(pool, sizeof(*handler));
 
+  handler->handler_pool = pool;
   handler->method = "REPORT";
   handler->path = session->session_url_str;
   handler->body_delegate = create_replay_body;
@@ -678,7 +670,6 @@ svn_ra_serf__replay(svn_ra_session_t *ra
   parser_ctx->start = start_replay;
   parser_ctx->end = end_replay;
   parser_ctx->cdata = cdata_replay;
-  parser_ctx->status_code = &status_code;
   parser_ctx->done = &replay_ctx->done;
 
   handler->response_handler = svn_ra_serf__handle_xml_parser;
@@ -752,10 +743,6 @@ svn_ra_serf__replay_range(svn_ra_session
       svn_ra_serf__list_t *done_list;
       svn_ra_serf__list_t *done_reports = NULL;
       replay_context_t *replay_ctx;
-      /* We're not really interested in the status code here in replay, but
-         the XML parsing code will abort on error if it doesn't have a place
-         to store the response status code. */
-      int status_code;
 
       if (session->cancel_func)
         SVN_ERR(session->cancel_func(session->cancel_baton));
@@ -806,6 +793,7 @@ svn_ra_serf__replay_range(svn_ra_session
           /* Send the replay report request. */
           handler = apr_pcalloc(replay_ctx->src_rev_pool, sizeof(*handler));
 
+          handler->handler_pool = replay_ctx->src_rev_pool;
           handler->method = "REPORT";
           handler->path = session->session_url_str;
           handler->body_delegate = create_replay_body;
@@ -828,7 +816,6 @@ svn_ra_serf__replay_range(svn_ra_session
           parser_ctx->start = start_replay;
           parser_ctx->end = end_replay;
           parser_ctx->cdata = cdata_replay;
-          parser_ctx->status_code = &status_code;
           parser_ctx->done = &replay_ctx->done;
           parser_ctx->done_list = &done_reports;
           parser_ctx->done_item = &replay_ctx->done_item;