You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by as...@apache.org on 2012/11/24 21:29:48 UTC

svn commit: r1413258 [11/33] - in /subversion/branches/compressed-pristines: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ contrib/client-side/emacs/ contrib/server-side/fsfsfixer/ notes/ notes/directory-index/ subversion/ subv...

Modified: subversion/branches/compressed-pristines/subversion/libsvn_ra_local/split_url.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_ra_local/split_url.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra_local/split_url.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra_local/split_url.c Sat Nov 24 20:29:11 2012
@@ -74,5 +74,8 @@ svn_ra_local__split_URL(svn_repos_t **re
                              - svn_path_component_count(repos_root_dirent));
   *repos_url = urlbuf->data;
 
+  /* Configure hook script environment variables. */
+  SVN_ERR(svn_repos_hooks_setenv(*repos, NULL, pool, pool));
+
   return SVN_NO_ERROR;
 }

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=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/commit.c Sat Nov 24 20:29:11 2012
@@ -38,6 +38,7 @@
 #include "svn_private_config.h"
 #include "private/svn_dep_compat.h"
 #include "private/svn_fspath.h"
+#include "private/svn_skel.h"
 
 #include "ra_serf.h"
 #include "../libsvn_ra/ra_loader.h"
@@ -320,6 +321,49 @@ checkout_node(const char **working_url,
 }
 
 
+/* This is a wrapper around checkout_node() (which see for
+   documentation) which simply retries the CHECKOUT request when it
+   fails due to an SVN_ERR_APMOD_BAD_BASELINE error return from the
+   server.
+
+   See http://subversion.tigris.org/issues/show_bug.cgi?id=4127 for
+   details.
+*/
+static svn_error_t *
+retry_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)
+{
+  svn_error_t *err = SVN_NO_ERROR;
+  int retry_count = 5; /* Magic, arbitrary number. */
+
+  do
+    {
+      svn_error_clear(err);
+
+      err = checkout_node(working_url, commit_ctx, node_url,
+                          result_pool, scratch_pool);
+
+      /* There's a small chance of a race condition here if Apache is
+         experiencing heavy commit concurrency or if the network has
+         long latency.  It's possible that the value of HEAD changed
+         between the time we fetched the latest baseline and the time
+         we try to CHECKOUT that baseline.  If that happens, Apache
+         will throw us a BAD_BASELINE error (deltaV says you can only
+         checkout the latest baseline).  We just ignore that specific
+         error and retry a few times, asking for the latest baseline
+         again. */
+      if (err && (err->apr_err != SVN_ERR_APMOD_BAD_BASELINE))
+        return err;
+    }
+  while (err && retry_count--);
+
+  return err;
+}
+
+
 static svn_error_t *
 checkout_dir(dir_context_t *dir,
              apr_pool_t *scratch_pool)
@@ -365,8 +409,8 @@ checkout_dir(dir_context_t *dir,
     }
 
   /* Checkout our directory into the activity URL now. */
-  err = checkout_node(working, dir->commit, checkout_url,
-                      dir->pool, scratch_pool);
+  err = retry_checkout_node(working, dir->commit, checkout_url,
+                            dir->pool, scratch_pool);
   if (err)
     {
       if (err->apr_err == SVN_ERR_FS_CONFLICT)
@@ -503,8 +547,8 @@ checkout_file(file_context_t *file,
                           NULL, scratch_pool, scratch_pool));
 
   /* Checkout our file into the activity URL now. */
-  err = checkout_node(&file->working_url, file->commit, checkout_url,
-                      file->pool, scratch_pool);
+  err = retry_checkout_node(&file->working_url, file->commit, checkout_url,
+                            file->pool, scratch_pool);
   if (err)
     {
       if (err->apr_err == SVN_ERR_FS_CONFLICT)
@@ -718,36 +762,62 @@ proppatch_walker(void *baton,
   return SVN_NO_ERROR;
 }
 
+/* Possible add the lock-token "If:" precondition header to HEADERS if
+   an examination of COMMIT_CTX and RELPATH indicates that this is the
+   right thing to do.
+
+   Generally speaking, if the client provided a lock token for
+   RELPATH, it's the right thing to do.  There is a notable instance
+   where this is not the case, however.  If the file at RELPATH was
+   explicitly deleted in this commit already, then mod_dav removed its
+   lock token when it fielded the DELETE request, so we don't want to
+   set the lock precondition again.  (See
+   http://subversion.tigris.org/issues/show_bug.cgi?id=3674 for details.)
+*/
 static svn_error_t *
-setup_proppatch_headers(serf_bucket_t *headers,
-                        void *baton,
-                        apr_pool_t *pool)
+maybe_set_lock_token_header(serf_bucket_t *headers,
+                            commit_context_t *commit_ctx,
+                            const char *relpath,
+                            apr_pool_t *pool)
 {
-  proppatch_context_t *proppatch = baton;
+  const char *token;
 
-  if (SVN_IS_VALID_REVNUM(proppatch->base_revision))
-    {
-      serf_bucket_headers_set(headers, SVN_DAV_VERSION_NAME_HEADER,
-                              apr_psprintf(pool, "%ld",
-                                           proppatch->base_revision));
-    }
+  if (! (relpath && commit_ctx->lock_tokens))
+    return SVN_NO_ERROR;
 
-  if (proppatch->relpath && proppatch->commit->lock_tokens)
+  if (! apr_hash_get(commit_ctx->deleted_entries, relpath,
+                     APR_HASH_KEY_STRING))
     {
-      const char *token;
-
-      token = apr_hash_get(proppatch->commit->lock_tokens, proppatch->relpath,
+      token = apr_hash_get(commit_ctx->lock_tokens, relpath,
                            APR_HASH_KEY_STRING);
-
       if (token)
         {
           const char *token_header;
 
           token_header = apr_pstrcat(pool, "(<", token, ">)", (char *)NULL);
-
           serf_bucket_headers_set(headers, "If", token_header);
         }
     }
+  
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+setup_proppatch_headers(serf_bucket_t *headers,
+                        void *baton,
+                        apr_pool_t *pool)
+{
+  proppatch_context_t *proppatch = baton;
+
+  if (SVN_IS_VALID_REVNUM(proppatch->base_revision))
+    {
+      serf_bucket_headers_set(headers, SVN_DAV_VERSION_NAME_HEADER,
+                              apr_psprintf(pool, "%ld",
+                                           proppatch->base_revision));
+    }
+
+  SVN_ERR(maybe_set_lock_token_header(headers, proppatch->commit,
+                                      proppatch->relpath, pool));
 
   return SVN_NO_ERROR;
 }
@@ -950,22 +1020,8 @@ setup_put_headers(serf_bucket_t *headers
                               ctx->result_checksum);
     }
 
-  if (ctx->commit->lock_tokens)
-    {
-      const char *token;
-
-      token = apr_hash_get(ctx->commit->lock_tokens, ctx->relpath,
-                           APR_HASH_KEY_STRING);
-
-      if (token)
-        {
-          const char *token_header;
-
-          token_header = apr_pstrcat(pool, "(<", token, ">)", (char *)NULL);
-
-          serf_bucket_headers_set(headers, "If", token_header);
-        }
-    }
+  SVN_ERR(maybe_set_lock_token_header(headers, ctx->commit,
+                                      ctx->relpath, pool));
 
   return APR_SUCCESS;
 }
@@ -1108,7 +1164,26 @@ create_txn_post_body(serf_bucket_t **bod
                      serf_bucket_alloc_t *alloc,
                      apr_pool_t *pool)
 {
-  *body_bkt = SERF_BUCKET_SIMPLE_STRING("( create-txn )", alloc);
+  apr_hash_t *revprops = baton;
+  svn_skel_t *request_skel;
+  svn_stringbuf_t *skel_str;
+
+  request_skel = svn_skel__make_empty_list(pool);
+  if (revprops)
+    {
+      svn_skel_t *proplist_skel;
+
+      SVN_ERR(svn_skel__unparse_proplist(&proplist_skel, revprops, pool));
+      svn_skel__prepend(proplist_skel, request_skel);
+      svn_skel__prepend_str("create-txn-with-props", request_skel, pool);
+      skel_str = svn_skel__unparse(request_skel, pool);
+      *body_bkt = SERF_BUCKET_SIMPLE_STRING(skel_str->data, alloc);
+    }
+  else
+    {
+      *body_bkt = SERF_BUCKET_SIMPLE_STRING("( create-txn )", alloc);
+    }
+
   return SVN_NO_ERROR;
 }
 
@@ -1213,12 +1288,15 @@ open_root(void *edit_baton,
   proppatch_context_t *proppatch_ctx;
   dir_context_t *dir;
   apr_hash_index_t *hi;
-  const char *proppatch_target;
+  const char *proppatch_target = NULL;
 
   if (SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(ctx->session))
     {
       post_response_ctx_t *prc;
       const char *rel_path;
+      svn_boolean_t post_with_revprops =
+        apr_hash_get(ctx->session->supported_posts, "create-txn-with-props",
+                     APR_HASH_KEY_STRING) ? TRUE : FALSE;
 
       /* Create our activity URL now on the server. */
       handler = apr_pcalloc(ctx->pool, sizeof(*handler));
@@ -1226,7 +1304,8 @@ open_root(void *edit_baton,
       handler->method = "POST";
       handler->body_type = SVN_SKEL_MIME_TYPE;
       handler->body_delegate = create_txn_post_body;
-      handler->body_delegate_baton = NULL;
+      handler->body_delegate_baton =
+        post_with_revprops ? ctx->revprop_table : NULL;
       handler->header_delegate = setup_post_headers;
       handler->header_delegate_baton = NULL;
       handler->path = ctx->session->me_resource;
@@ -1288,7 +1367,9 @@ open_root(void *edit_baton,
       dir->removed_props = apr_hash_make(dir->pool);
       dir->url = apr_pstrdup(dir->pool, ctx->txn_root_url);
 
-      proppatch_target = ctx->txn_url;
+      /* If we included our revprops in the POST, we need not
+         PROPPATCH them. */
+      proppatch_target = post_with_revprops ? NULL : ctx->txn_url;
     }
   else
     {
@@ -1369,45 +1450,50 @@ open_root(void *edit_baton,
       proppatch_target = ctx->baseline_url;
     }
 
+  /* Unless this is NULL -- which means we don't need to PROPPATCH the
+     transaction with our revprops -- then, you know, PROPPATCH the
+     transaction with our revprops.  */
+  if (proppatch_target)
+    {
+      proppatch_ctx = apr_pcalloc(ctx->pool, sizeof(*proppatch_ctx));
+      proppatch_ctx->pool = dir_pool;
+      proppatch_ctx->commit = ctx;
+      proppatch_ctx->path = proppatch_target;
+      proppatch_ctx->changed_props = apr_hash_make(proppatch_ctx->pool);
+      proppatch_ctx->removed_props = apr_hash_make(proppatch_ctx->pool);
+      proppatch_ctx->base_revision = SVN_INVALID_REVNUM;
+
+      for (hi = apr_hash_first(ctx->pool, ctx->revprop_table); hi;
+           hi = apr_hash_next(hi))
+        {
+          const void *key;
+          void *val;
+          const char *name;
+          svn_string_t *value;
+          const char *ns;
+
+          apr_hash_this(hi, &key, NULL, &val);
+          name = key;
+          value = val;
 
-  /* PROPPATCH our revprops and pass them along.  */
-  proppatch_ctx = apr_pcalloc(ctx->pool, sizeof(*proppatch_ctx));
-  proppatch_ctx->pool = dir_pool;
-  proppatch_ctx->commit = ctx;
-  proppatch_ctx->path = proppatch_target;
-  proppatch_ctx->changed_props = apr_hash_make(proppatch_ctx->pool);
-  proppatch_ctx->removed_props = apr_hash_make(proppatch_ctx->pool);
-  proppatch_ctx->base_revision = SVN_INVALID_REVNUM;
-
-  for (hi = apr_hash_first(ctx->pool, ctx->revprop_table); hi;
-       hi = apr_hash_next(hi))
-    {
-      const void *key;
-      void *val;
-      const char *name;
-      svn_string_t *value;
-      const char *ns;
-
-      apr_hash_this(hi, &key, NULL, &val);
-      name = key;
-      value = val;
+          if (strncmp(name, SVN_PROP_PREFIX, sizeof(SVN_PROP_PREFIX) - 1) == 0)
+            {
+              ns = SVN_DAV_PROP_NS_SVN;
+              name += sizeof(SVN_PROP_PREFIX) - 1;
+            }
+          else
+            {
+              ns = SVN_DAV_PROP_NS_CUSTOM;
+            }
 
-      if (strncmp(name, SVN_PROP_PREFIX, sizeof(SVN_PROP_PREFIX) - 1) == 0)
-        {
-          ns = SVN_DAV_PROP_NS_SVN;
-          name += sizeof(SVN_PROP_PREFIX) - 1;
-        }
-      else
-        {
-          ns = SVN_DAV_PROP_NS_CUSTOM;
+          svn_ra_serf__set_prop(proppatch_ctx->changed_props,
+                                proppatch_ctx->path,
+                                ns, name, value, proppatch_ctx->pool);
         }
 
-      svn_ra_serf__set_prop(proppatch_ctx->changed_props, proppatch_ctx->path,
-                            ns, name, value, proppatch_ctx->pool);
+      SVN_ERR(proppatch_resource(proppatch_ctx, dir->commit, ctx->pool));
     }
 
-  SVN_ERR(proppatch_resource(proppatch_ctx, dir->commit, ctx->pool));
-
   *root_baton = dir;
 
   return SVN_NO_ERROR;
@@ -1897,7 +1983,8 @@ apply_textdelta(void *file_baton,
   ctx->stream = svn_stream_create(ctx, pool);
   svn_stream_set_write(ctx->stream, svndiff_stream_write);
 
-  svn_txdelta_to_svndiff2(handler, handler_baton, ctx->stream, 0, pool);
+  svn_txdelta_to_svndiff3(handler, handler_baton, ctx->stream, 0,
+                          SVN_DELTA_COMPRESSION_LEVEL_DEFAULT, pool);
 
   if (base_checksum)
     ctx->base_checksum = apr_pstrdup(ctx->pool, base_checksum);
@@ -2027,7 +2114,7 @@ close_file(void *file_baton,
         {
           handler->body_delegate = create_put_body;
           handler->body_delegate_baton = ctx;
-          handler->body_type = "application/vnd.svn-svndiff";
+          handler->body_type = SVN_SVNDIFF_MIME_TYPE;
         }
 
       handler->header_delegate = setup_put_headers;
@@ -2183,6 +2270,7 @@ svn_ra_serf__get_commit_editor(svn_ra_se
   apr_hash_index_t *hi;
   const char *repos_root;
   const char *base_relpath;
+  svn_boolean_t supports_ephemeral_props;
 
   ctx = apr_pcalloc(pool, sizeof(*ctx));
 
@@ -2203,6 +2291,23 @@ svn_ra_serf__get_commit_editor(svn_ra_se
                    svn_string_dup(val, pool));
     }
 
+  /* If the server supports ephemeral properties, add some carrying
+     interesting version information. */
+  SVN_ERR(svn_ra_serf__has_capability(ra_session, &supports_ephemeral_props,
+                                      SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS,
+                                      pool));
+  if (supports_ephemeral_props)
+    {
+      apr_hash_set(ctx->revprop_table,
+                   apr_pstrdup(pool, SVN_PROP_TXN_CLIENT_COMPAT_VERSION),
+                   APR_HASH_KEY_STRING,
+                   svn_string_create(SVN_VER_NUMBER, pool));
+      apr_hash_set(ctx->revprop_table,
+                   apr_pstrdup(pool, SVN_PROP_TXN_USER_AGENT),
+                   APR_HASH_KEY_STRING,
+                   svn_string_create(session->useragent, pool));
+    }
+
   ctx->callback = callback;
   ctx->callback_baton = callback_baton;
 

Added: subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/inherited_props.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/inherited_props.c?rev=1413258&view=auto
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/inherited_props.c (added)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/inherited_props.c Sat Nov 24 20:29:11 2012
@@ -0,0 +1,351 @@
+/*
+ * inherited_props.c : ra_serf implementation of svn_ra_get_inherited_props
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+
+
+#include <apr_tables.h>
+#include <apr_xml.h>
+
+#include "svn_path.h"
+#include "svn_ra.h"
+#include "svn_string.h"
+#include "svn_xml.h"
+#include "svn_props.h"
+#include "svn_base64.h"
+
+#include "private/svn_dav_protocol.h"
+#include "../libsvn_ra/ra_loader.h"
+#include "svn_private_config.h"
+#include "ra_serf.h"
+
+
+/* The current state of our XML parsing. */
+typedef enum iprops_state_e {
+  NONE = 0,
+  IPROPS_REPORT,
+  IPROPS_ITEM,
+  IPROPS_PATH,
+  IPROPS_PROPNAME,
+  IPROPS_PROPVAL
+} iprops_state_e;
+
+/* Struct for accumulating inherited props. */
+typedef struct iprops_context_t {
+  /* The depth-first ordered array of svn_prop_inherited_item_t *
+     structures we are building. */
+  apr_array_header_t *iprops;
+
+  /* Pool in which to allocate elements of IPROPS. */
+  apr_pool_t *pool;
+
+  /* The repository's root URL. */
+  const char *repos_root_url;
+
+  /* Current CDATA values*/
+  svn_stringbuf_t *curr_path;
+  svn_stringbuf_t *curr_propname;
+  svn_stringbuf_t *curr_propval;
+  const char *curr_prop_val_encoding;
+
+  /* Current element in IPROPS. */
+  svn_prop_inherited_item_t *curr_iprop;
+
+  /* Serf context completion flag for svn_ra_serf__context_run_wait() */
+  svn_boolean_t done;
+
+  /* Path we are finding inherited properties for.  This is relative to
+     the RA session passed to svn_ra_serf__get_inherited_props. */
+  const char *path;
+  /* The revision of PATH*/
+  svn_revnum_t revision;
+} iprops_context_t;
+
+static svn_error_t *
+start_element(svn_ra_serf__xml_parser_t *parser,
+              svn_ra_serf__dav_props_t name,
+              const char **attrs,
+              apr_pool_t *scratch_pool)
+{
+  iprops_context_t *iprops_ctx = parser->user_data;
+  iprops_state_e state;
+
+  state = parser->state->current_state;
+  if (state == NONE
+      && strcmp(name.name, SVN_DAV__INHERITED_PROPS_REPORT) == 0)
+    {
+      svn_ra_serf__xml_push_state(parser, IPROPS_REPORT);
+    }
+  else if (state == IPROPS_REPORT &&
+           strcmp(name.name, SVN_DAV__IPROP_ITEM) == 0)
+    {
+      svn_stringbuf_setempty(iprops_ctx->curr_path);
+      svn_stringbuf_setempty(iprops_ctx->curr_propname);
+      svn_stringbuf_setempty(iprops_ctx->curr_propval);
+      iprops_ctx->curr_prop_val_encoding = NULL;
+      iprops_ctx->curr_iprop = NULL;
+      svn_ra_serf__xml_push_state(parser, IPROPS_ITEM);
+    }
+  else if (state == IPROPS_ITEM &&
+           strcmp(name.name, SVN_DAV__IPROP_PROPVAL) == 0)
+    {
+      const char *prop_val_encoding = svn_xml_get_attr_value("encoding",
+                                                             attrs);
+      iprops_ctx->curr_prop_val_encoding = apr_pstrdup(iprops_ctx->pool,
+                                                       prop_val_encoding);
+      svn_ra_serf__xml_push_state(parser, IPROPS_PROPVAL);
+    }
+  else if (state == IPROPS_ITEM &&
+           strcmp(name.name, SVN_DAV__IPROP_PATH) == 0)
+    {
+      svn_ra_serf__xml_push_state(parser, IPROPS_PATH);
+    }
+  else if (state == IPROPS_ITEM &&
+           strcmp(name.name, SVN_DAV__IPROP_PROPNAME) == 0)
+    {
+      svn_ra_serf__xml_push_state(parser, IPROPS_PROPNAME);
+    }
+  else if (state == IPROPS_ITEM &&
+           strcmp(name.name, SVN_DAV__IPROP_PROPVAL) == 0)
+    {
+      svn_ra_serf__xml_push_state(parser, IPROPS_PROPVAL);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+end_element(svn_ra_serf__xml_parser_t *parser,
+            svn_ra_serf__dav_props_t name,
+            apr_pool_t *scratch_pool)
+{
+  iprops_context_t *iprops_ctx = parser->user_data;
+  iprops_state_e state;
+
+  state = parser->state->current_state;
+
+    if (state == IPROPS_REPORT &&
+      strcmp(name.name, SVN_DAV__INHERITED_PROPS_REPORT) == 0)
+    {
+      svn_ra_serf__xml_pop_state(parser);
+    }
+  else if (state == IPROPS_PATH
+           && strcmp(name.name, SVN_DAV__IPROP_PATH) == 0)
+    {
+      iprops_ctx->curr_iprop = apr_palloc(
+        iprops_ctx->pool, sizeof(svn_prop_inherited_item_t));
+
+      iprops_ctx->curr_iprop->path_or_url =
+        svn_path_url_add_component2(iprops_ctx->repos_root_url,
+                                    iprops_ctx->curr_path->data,
+                                    iprops_ctx->pool);
+      iprops_ctx->curr_iprop->prop_hash = apr_hash_make(iprops_ctx->pool);
+      svn_ra_serf__xml_pop_state(parser);
+    }
+  else if (state == IPROPS_PROPVAL
+           && strcmp(name.name, SVN_DAV__IPROP_PROPVAL) == 0)
+    {
+      const svn_string_t *prop_val;
+
+      if (iprops_ctx->curr_prop_val_encoding)
+        {
+          svn_string_t encoded_prop_val;
+
+          if (strcmp(iprops_ctx->curr_prop_val_encoding, "base64") != 0)
+            return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL);
+
+          encoded_prop_val.data = iprops_ctx->curr_propval->data;
+          encoded_prop_val.len = iprops_ctx->curr_propval->len;
+          prop_val = svn_base64_decode_string(&encoded_prop_val,
+                                              iprops_ctx->pool);
+        }
+      else
+        {
+          prop_val = svn_string_create_from_buf(iprops_ctx->curr_propval,
+                                                iprops_ctx->pool);
+        }
+
+      apr_hash_set(iprops_ctx->curr_iprop->prop_hash,
+                   apr_pstrdup(iprops_ctx->pool,
+                               iprops_ctx->curr_propname->data),
+                   APR_HASH_KEY_STRING,
+                   prop_val);
+      /* Clear current propname and propval in the event there are
+         multiple properties on the current path. */
+      svn_stringbuf_setempty(iprops_ctx->curr_propname);
+      svn_stringbuf_setempty(iprops_ctx->curr_propval);
+      svn_ra_serf__xml_pop_state(parser);
+    }
+  else if (state == IPROPS_PROPNAME
+           && strcmp(name.name, SVN_DAV__IPROP_PROPNAME) == 0)
+    {
+      svn_ra_serf__xml_pop_state(parser);
+    }
+  else if (state == IPROPS_ITEM
+           && strcmp(name.name, SVN_DAV__IPROP_ITEM) == 0)
+    {
+      APR_ARRAY_PUSH(iprops_ctx->iprops, svn_prop_inherited_item_t *) =
+        iprops_ctx->curr_iprop;
+      svn_ra_serf__xml_pop_state(parser);
+    }
+  return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+cdata_handler(svn_ra_serf__xml_parser_t *parser,
+              const char *data,
+              apr_size_t len,
+              apr_pool_t *scratch_pool)
+{
+  iprops_context_t *iprops_ctx = parser->user_data;
+  iprops_state_e state = parser->state->current_state;
+
+  switch (state)
+    {
+    case IPROPS_PATH:
+      svn_stringbuf_appendbytes(iprops_ctx->curr_path, data, len);
+      break;
+
+    case IPROPS_PROPNAME:
+      svn_stringbuf_appendbytes(iprops_ctx->curr_propname, data, len);
+      break;
+
+    case IPROPS_PROPVAL:
+      svn_stringbuf_appendbytes(iprops_ctx->curr_propval, data, len);
+      break;
+
+    default:
+      break;
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+create_iprops_body(serf_bucket_t **bkt,
+                   void *baton,
+                   serf_bucket_alloc_t *alloc,
+                   apr_pool_t *pool)
+{
+  iprops_context_t *iprops_ctx = baton;
+  serf_bucket_t *body_bkt;
+
+  body_bkt = serf_bucket_aggregate_create(alloc);
+
+  svn_ra_serf__add_open_tag_buckets(body_bkt, alloc,
+                                    "S:" SVN_DAV__INHERITED_PROPS_REPORT,
+                                    "xmlns:S", SVN_XML_NAMESPACE,
+                                    NULL);
+  svn_ra_serf__add_tag_buckets(body_bkt,
+                               "S:" SVN_DAV__REVISION,
+                               apr_ltoa(pool, iprops_ctx->revision),
+                               alloc);
+  svn_ra_serf__add_tag_buckets(body_bkt, "S:" SVN_DAV__PATH,
+                               iprops_ctx->path, alloc);
+  svn_ra_serf__add_close_tag_buckets(body_bkt, alloc,
+                                     "S:" SVN_DAV__INHERITED_PROPS_REPORT);
+  *bkt = body_bkt;
+  return SVN_NO_ERROR;
+}
+
+/* Request a inherited-props-report from the URL attached to RA_SESSION,
+   and fill the IPROPS array hash with the results.  */
+svn_error_t *
+svn_ra_serf__get_inherited_props(svn_ra_session_t *ra_session,
+                                 apr_array_header_t **iprops,
+                                 const char *path,
+                                 svn_revnum_t revision,
+                                 apr_pool_t *result_pool,
+                                 apr_pool_t *scratch_pool)
+{
+  svn_error_t *err, *err2;
+
+  iprops_context_t *iprops_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 *req_url;
+
+  SVN_ERR(svn_ra_serf__get_stable_url(&req_url,
+                                      NULL /* latest_revnum */,
+                                      session,
+                                      NULL /* conn */,
+                                      NULL /* url */,
+                                      revision,
+                                      result_pool, scratch_pool));
+
+  iprops_ctx = apr_pcalloc(scratch_pool, sizeof(*iprops_ctx));
+  iprops_ctx->done = FALSE;
+  iprops_ctx->repos_root_url = session->repos_root_str;
+  iprops_ctx->pool = result_pool;
+  iprops_ctx->curr_path = svn_stringbuf_create_empty(scratch_pool);
+  iprops_ctx->curr_propname = svn_stringbuf_create_empty(scratch_pool);
+  iprops_ctx->curr_propval = svn_stringbuf_create_empty(scratch_pool);
+  iprops_ctx->curr_iprop = NULL;
+  iprops_ctx->iprops = apr_array_make(result_pool, 1,
+                                       sizeof(svn_prop_inherited_item_t *));
+  iprops_ctx->path = path;
+  iprops_ctx->revision = revision;
+
+  handler = apr_pcalloc(scratch_pool, sizeof(*handler));
+
+  handler->method = "REPORT";
+  handler->path = req_url;
+  handler->conn = session->conns[0];
+  handler->session = session;
+  handler->body_delegate = create_iprops_body;
+  handler->body_delegate_baton = iprops_ctx;
+  handler->body_type = "text/xml";
+  handler->handler_pool = scratch_pool;
+
+  parser_ctx = apr_pcalloc(scratch_pool, sizeof(*parser_ctx));
+
+  parser_ctx->pool = scratch_pool;
+  parser_ctx->user_data = iprops_ctx;
+  parser_ctx->start = start_element;
+  parser_ctx->end = end_element;
+  parser_ctx->cdata = cdata_handler;
+  parser_ctx->done = &iprops_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(&iprops_ctx->done, session,
+                                      scratch_pool);
+
+  err2 = svn_ra_serf__error_on_status(handler->sline.code, handler->path,
+                                      handler->location);
+  if (err2)
+    {
+      svn_error_clear(err);
+      return err2;
+    }
+
+  SVN_ERR(err);
+
+  if (iprops_ctx->done)
+    *iprops = iprops_ctx->iprops;
+
+  return SVN_NO_ERROR;
+}

Modified: subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/options.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/options.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/options.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/options.c Sat Nov 24 20:29:11 2012
@@ -199,15 +199,38 @@ capabilities_headers_iterator_callback(v
                        SVN_RA_CAPABILITY_PARTIAL_REPLAY, APR_HASH_KEY_STRING,
                        capability_yes);
         }
+      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_INHERITED_PROPS, vals))
+        {
+          apr_hash_set(session->capabilities,
+                       SVN_RA_CAPABILITY_INHERITED_PROPS,
+                       APR_HASH_KEY_STRING, capability_yes);
+        }
+      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_EPHEMERAL_TXNPROPS, vals))
+        {
+          apr_hash_set(session->capabilities,
+                       SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS, APR_HASH_KEY_STRING,
+                       capability_yes);
+        }
     }
 
   /* SVN-specific headers -- if present, server supports HTTP protocol v2 */
   else if (strncmp(key, "SVN", 3) == 0)
     {
+      /* If we've not yet seen any information about supported POST
+         requests, we'll initialize the list/hash with "create-txn"
+         (which we know is supported by virtue of the server speaking
+         HTTPv2 at all. */
+      if (! session->supported_posts)
+        {
+          session->supported_posts = apr_hash_make(session->pool);
+          apr_hash_set(session->supported_posts, "create-txn", 10, (void *)1);
+        }
+
       if (svn_cstring_casecmp(key, SVN_DAV_ROOT_URI_HEADER) == 0)
         {
           session->repos_root = session->session_url;
-          session->repos_root.path = apr_pstrdup(session->pool, val);
+          session->repos_root.path =
+            (char *)svn_fspath__canonicalize(val, session->pool);
           session->repos_root_str =
             svn_urlpath__canonicalize(
                 apr_uri_unparse(session->pool, &session->repos_root, 0),
@@ -257,6 +280,21 @@ capabilities_headers_iterator_callback(v
         {
           opt_ctx->youngest_rev = SVN_STR_TO_REV(val);
         }
+      else if (svn_cstring_casecmp(key, SVN_DAV_SUPPORTED_POSTS_HEADER) == 0)
+        {
+          /* May contain multiple values, separated by commas. */
+          int i;
+          apr_array_header_t *vals = svn_cstring_split(val, ",", TRUE,
+                                                       opt_ctx->pool);
+
+          for (i = 0; i < vals->nelts; i++)
+            {
+              const char *post_val = APR_ARRAY_IDX(vals, i, const char *);
+
+              apr_hash_set(session->supported_posts, post_val,
+                           APR_HASH_KEY_STRING, (void *)1);
+            }
+        }
     }
 
   return 0;
@@ -291,6 +329,10 @@ options_response_handler(serf_request_t 
                    APR_HASH_KEY_STRING, capability_no);
       apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
                    APR_HASH_KEY_STRING, capability_no);
+      apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_INHERITED_PROPS,
+                   APR_HASH_KEY_STRING, capability_no);
+      apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS,
+                   APR_HASH_KEY_STRING, capability_no);
 
       /* Then see which ones we can discover. */
       serf_bucket_headers_do(hdrs, capabilities_headers_iterator_callback,
@@ -299,7 +341,7 @@ options_response_handler(serf_request_t 
       opt_ctx->headers_processed = TRUE;
     }
 
-  /* Execute the 'real' response handler to XML-parse the repsonse body. */
+  /* Execute the 'real' response handler to XML-parse the response body. */
   return opt_ctx->inner_handler(request, response, opt_ctx->inner_baton, pool);
 }
 

Modified: subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/property.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/property.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/property.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/property.c Sat Nov 24 20:29:11 2012
@@ -322,16 +322,11 @@ propfind_closed(svn_ra_serf__xml_estate_
   else
     {
       apr_hash_t *gathered;
-      const char *path;
 
       SVN_ERR_ASSERT(leaving_state == PROPSTAT);
 
       gathered = svn_ra_serf__xml_gather_since(xes, PROPSTAT);
 
-      path = apr_hash_get(gathered, "path", APR_HASH_KEY_STRING);
-      if (path == NULL)
-        path = ctx->path;
-
       /* If we've squirreled away a note that says we want to ignore
          these properties, we'll do so.  Otherwise, we need to copy
          them from the temporary hash into the ctx->ret_props hash. */

Modified: subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/ra_serf.h?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/ra_serf.h Sat Nov 24 20:29:11 2012
@@ -62,6 +62,10 @@ extern "C" {
                    APR_STRINGIFY(SERF_MINOR_VERSION) "." \
                    APR_STRINGIFY(SERF_PATCH_VERSION)
 
+/** Wait duration (in microseconds) used in calls to serf_context_run() */
+#define SVN_RA_SERF__CONTEXT_RUN_DURATION 500000
+
+
 
 /* Forward declarations. */
 typedef struct svn_ra_serf__session_t svn_ra_serf__session_t;
@@ -89,7 +93,9 @@ typedef struct svn_ra_serf__connection_t
 
 } svn_ra_serf__connection_t;
 
-/** Max. number of connctions we'll open to the server. */
+/** Max. number of connctions we'll open to the server. 
+ *  Note: minimum 2 connections are required for ra_serf to function correctly!
+ */
 #define MAX_NR_OF_CONNS 4
 
 /*
@@ -209,6 +215,10 @@ struct svn_ra_serf__session_t {
   const char *vtxn_stub;        /* for accessing transactions (i.e. txnprops) */
   const char *vtxn_root_stub;   /* for accessing TXN/PATH pairs */
 
+  /* Hash mapping const char * server-supported POST types to
+     disinteresting-but-non-null values. */
+  apr_hash_t *supported_posts;
+
   /*** End HTTP v2 stuff ***/
 
   svn_ra_serf__blncache_t *blncache;
@@ -969,12 +979,15 @@ svn_ra_serf__add_xml_header_buckets(serf
                                     serf_bucket_alloc_t *bkt_alloc);
 
 /*
- * Add the appropriate serf buckets to AGG_BUCKET representing xml tag open
- * with name TAG.
+ * Add the appropriate serf buckets to AGG_BUCKET representing the XML
+ * open tag with name TAG.
  *
  * Take the tag's attributes from varargs, a NULL-terminated list of
- * alternating <tt>char *</tt> key and <tt>char *</tt> val.  Do xml-escaping
- * on each val. Attribute will be ignored if it's value is NULL.
+ * alternating <tt>char *</tt> key and <tt>char *</tt> val.  Attribute
+ * will be ignored if it's value is NULL.
+ *
+ * NOTE: Callers are responsible for XML-escaping attribute values as
+ * necessary.
  *
  * The bucket will be allocated from BKT_ALLOC.
  */
@@ -1647,6 +1660,14 @@ svn_ra_serf__get_deleted_rev(svn_ra_sess
                              svn_revnum_t *revision_deleted,
                              apr_pool_t *pool);
 
+/* Implements the get_inherited_props RA layer function. */
+svn_error_t * svn_ra_serf__get_inherited_props(svn_ra_session_t *session,
+                                               apr_array_header_t **iprops,
+                                               const char *path,
+                                               svn_revnum_t revision,
+                                               apr_pool_t *result_pool,
+                                               apr_pool_t *scratch_pool);
+
 /* Implements svn_ra__vtable_t.get_repos_root(). */
 svn_error_t *
 svn_ra_serf__get_repos_root(svn_ra_session_t *ra_session,
@@ -1658,7 +1679,6 @@ svn_error_t *
 svn_ra_serf__register_editor_shim_callbacks(svn_ra_session_t *session,
                                     svn_delta_shim_callbacks_t *callbacks);
 
-
 /*** Authentication handler declarations ***/
 
 /**
@@ -1699,6 +1719,21 @@ svn_ra_serf__create_sb_bucket(svn_spillb
                               apr_pool_t *result_pool,
                               apr_pool_t *scratch_pool);
 
+/** Wrap STATUS from an serf function. If STATUS is not serf error code,
+  * this is equivalent to svn_error_wrap_apr().
+ */
+svn_error_t *
+svn_ra_serf__wrap_err(apr_status_t status,
+                      const char *fmt,
+                      ...);
+
+
+#if defined(SVN_DEBUG)
+/* Wrapper macros to collect file and line information */
+#define svn_ra_serf__wrap_err \
+  (svn_error__locate(__FILE__,__LINE__), (svn_ra_serf__wrap_err))
+
+#endif
 
 #ifdef __cplusplus
 }

Modified: subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/replay.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/replay.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/replay.c Sat Nov 24 20:29:11 2012
@@ -732,6 +732,7 @@ svn_ra_serf__replay_range(svn_ra_session
   svn_revnum_t rev = start_revision;
   const char *report_target;
   int active_reports = 0;
+  apr_short_interval_time_t waittime_left = session->timeout;
 
   SVN_ERR(svn_ra_serf__report_resource(&report_target, session, NULL, pool));
 
@@ -855,18 +856,36 @@ svn_ra_serf__replay_range(svn_ra_session
          ### ahead and apply it here, too, in case serf eventually uses
          ### that parameter.
       */
-      status = serf_context_run(session->context, session->timeout,
+      status = serf_context_run(session->context,
+                                SVN_RA_SERF__CONTEXT_RUN_DURATION,
                                 pool);
 
       err = session->pending_error;
       session->pending_error = NULL;
 
+      /* If the context duration timeout is up, we'll subtract that
+         duration from the total time alloted for such things.  If
+         there's no time left, we fail with a message indicating that
+         the connection timed out.  */
       if (APR_STATUS_IS_TIMEUP(status))
         {
           svn_error_clear(err);
-          return svn_error_create(SVN_ERR_RA_DAV_CONN_TIMEOUT,
-                                  NULL,
-                                  _("Connection timed out"));
+          err = SVN_NO_ERROR;
+          status = 0;
+
+          if (waittime_left > SVN_RA_SERF__CONTEXT_RUN_DURATION)
+            {
+              waittime_left -= SVN_RA_SERF__CONTEXT_RUN_DURATION;
+            }
+          else
+            {
+              return svn_error_create(SVN_ERR_RA_DAV_CONN_TIMEOUT, NULL,
+                                      _("Connection timed out"));
+            }
+        }
+      else
+        {
+          waittime_left = session->timeout;
         }
 
       /* Substract the number of completely handled responses from our
@@ -885,9 +904,8 @@ svn_ra_serf__replay_range(svn_ra_session
       SVN_ERR(err);
       if (status)
         {
-          return svn_error_wrap_apr(status,
-                                    _("Error retrieving replay REPORT (%d)"),
-                                    status);
+          return svn_ra_serf__wrap_err(status,
+                                       _("Error retrieving replay REPORT"));
         }
       done_reports = NULL;
     }

Modified: subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/sb_bucket.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/sb_bucket.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/sb_bucket.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/sb_bucket.c Sat Nov 24 20:29:11 2012
@@ -62,7 +62,7 @@ svn_ra_serf__copy_into_spillbuf(svn_spil
       status = serf_bucket_read(bkt, SERF_READ_ALL_AVAIL, &data, &len);
 
       if (status != APR_SUCCESS && status != APR_EOF)
-        return svn_error_wrap_apr(status, _("Failed to read the request"));
+        return svn_ra_serf__wrap_err(status, _("Failed to read the request"));
 
       SVN_ERR(svn_spillbuf__write(*spillbuf, data, len, scratch_pool));
 

Modified: subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/serf.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/serf.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/serf.c Sat Nov 24 20:29:11 2012
@@ -307,9 +307,9 @@ load_config(svn_ra_serf__session_t *sess
                                      session->pool);
       if (status)
         {
-          return svn_error_wrap_apr(status,
-                                    _("Could not resolve proxy server '%s'"),
-                                    proxy_host);
+          return svn_ra_serf__wrap_err(
+                   status, _("Could not resolve proxy server '%s'"),
+                   proxy_host);
         }
       session->using_proxy = TRUE;
       serf_config_proxy(session->context, proxy_addr);
@@ -381,10 +381,12 @@ svn_ra_serf__open(svn_ra_session_t *sess
                                _("Illegal URL '%s'"),
                                session_URL);
     }
-  /* Contrary to what the comment for apr_uri_t.path says in apr-util 1.2.12 and
-     older, for root paths url.path will be "", where serf requires "/". */
+  /* Depending the version of apr-util in use, for root paths url.path
+     will be NULL or "", where serf requires "/". */
   if (url.path == NULL || url.path[0] == '\0')
-    url.path = apr_pstrdup(serf_sess->pool, "/");
+    {
+      url.path = apr_pstrdup(serf_sess->pool, "/");
+    }
   if (!url.port)
     {
       url.port = apr_uri_port_of_scheme(url.scheme);
@@ -397,8 +399,9 @@ svn_ra_serf__open(svn_ra_session_t *sess
 
   serf_sess->capabilities = apr_hash_make(serf_sess->pool);
 
-  serf_sess->http10 = TRUE;  /* until we confirm HTTP/1.1  */
-  serf_sess->http10 = FALSE; /* ### don't change behavior yet  */
+  /* We have to assume that the server only supports HTTP/1.0. Once it's clear
+     HTTP/1.1 is supported, we can upgrade. */
+  serf_sess->http10 = TRUE;
 
   SVN_ERR(load_config(serf_sess, config, serf_sess->pool));
 
@@ -414,7 +417,7 @@ svn_ra_serf__open(svn_ra_session_t *sess
     callbacks->get_client_string(callback_baton, &client_string, pool);
 
   if (client_string)
-    serf_sess->useragent = apr_pstrcat(pool, USER_AGENT, "/",
+    serf_sess->useragent = apr_pstrcat(pool, USER_AGENT, " ",
                                        client_string, (char *)NULL);
   else
     serf_sess->useragent = USER_AGENT;
@@ -428,7 +431,7 @@ svn_ra_serf__open(svn_ra_session_t *sess
                             svn_ra_serf__conn_closed, serf_sess->conns[0],
                             serf_sess->pool);
   if (status)
-    return svn_error_wrap_apr(status, NULL);
+    return svn_ra_serf__wrap_err(status, NULL);
 
   /* Set the progress callback. */
   serf_context_set_progress_cb(serf_sess->context, svn_ra_serf__progress,
@@ -478,9 +481,18 @@ svn_ra_serf__reparent(svn_ra_session_t *
                                _("Illegal repository URL '%s'"), url);
     }
 
-  /* Maybe we should use a string buffer for these strings so we don't
-     allocate memory in the session on every reparent? */
-  session->session_url.path = apr_pstrdup(session->pool, new_url.path);
+  /* Depending the version of apr-util in use, for root paths url.path
+     will be NULL or "", where serf requires "/". */
+  /* ### Maybe we should use a string buffer for these strings so we
+     ### don't allocate memory in the session on every reparent? */
+  if (new_url.path == NULL || new_url.path[0] == '\0')
+    {
+      session->session_url.path = apr_pstrdup(session->pool, "/");
+    }
+  else
+    {
+      session->session_url.path = apr_pstrdup(session->pool, new_url.path);
+    }
   session->session_url_str = apr_pstrdup(session->pool, url);
 
   return SVN_NO_ERROR;
@@ -1138,7 +1150,8 @@ static const svn_ra__vtable_t serf_vtabl
   svn_ra_serf__has_capability,
   svn_ra_serf__replay_range,
   svn_ra_serf__get_deleted_rev,
-  svn_ra_serf__register_editor_shim_callbacks
+  svn_ra_serf__register_editor_shim_callbacks,
+  svn_ra_serf__get_inherited_props
 };
 
 svn_error_t *

Modified: subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/update.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/update.c Sat Nov 24 20:29:11 2012
@@ -313,6 +313,10 @@ struct report_context_t {
   /* Do we want the server to send copyfrom args or not? */
   svn_boolean_t send_copyfrom_args;
 
+  /* Is the server including properties inline for newly added
+     files/dirs? */
+  svn_boolean_t add_props_included;
+
   /* Path -> lock token mapping. */
   apr_hash_t *lock_path_tokens;
 
@@ -358,6 +362,9 @@ struct report_context_t {
   /* Are we done parsing the REPORT response? */
   svn_boolean_t done;
 
+  /* Did we get a complete (non-truncated) report? */
+  svn_boolean_t report_completed;
+
   /* The XML parser context for the REPORT response.  */
   svn_ra_serf__xml_parser_t *parser_ctx;
 };
@@ -926,12 +933,23 @@ handle_fetch(serf_request_t *request,
           return error_fetch(request, fetch_ctx, err);
         }
 
-      if (val && svn_cstring_casecmp(val, "application/vnd.svn-svndiff") == 0)
+      if (val && svn_cstring_casecmp(val, SVN_SVNDIFF_MIME_TYPE) == 0)
         {
           fetch_ctx->delta_stream =
               svn_txdelta_parse_svndiff(info->textdelta,
                                         info->textdelta_baton,
                                         TRUE, info->editor_pool);
+
+          /* Validate the delta base claimed by the server matches
+             what we asked for! */
+          val = serf_bucket_headers_get(hdrs, SVN_DAV_DELTA_BASE_HEADER);
+          if (val && (strcmp(val, info->delta_base) != 0))
+            {
+              err = svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
+                                      _("GET request returned unexpected "
+                                        "delta base: %s"), val);
+              return error_fetch(request, fetch_ctx, err);
+            }
         }
       else
         {
@@ -961,7 +979,7 @@ handle_fetch(serf_request_t *request,
       status = serf_bucket_read(response, 8000, &data, &len);
       if (SERF_BUCKET_READ_ERROR(status))
         {
-          return svn_error_wrap_apr(status, NULL);
+          return svn_ra_serf__wrap_err(status, NULL);
         }
 
       fetch_ctx->read_size += len;
@@ -981,7 +999,7 @@ handle_fetch(serf_request_t *request,
               /* Skip on to the next iteration of this loop. */
               if (APR_STATUS_IS_EAGAIN(status))
                 {
-                  return svn_error_wrap_apr(status, NULL);
+                  return svn_ra_serf__wrap_err(status, NULL);
                 }
               continue;
             }
@@ -1057,11 +1075,11 @@ handle_fetch(serf_request_t *request,
           svn_pool_destroy(info->pool);
 
           if (status)
-            return svn_error_wrap_apr(status, NULL);
+            return svn_ra_serf__wrap_err(status, NULL);
         }
       if (APR_STATUS_IS_EAGAIN(status))
         {
-          return svn_error_wrap_apr(status, NULL);
+          return svn_ra_serf__wrap_err(status, NULL);
         }
     }
   /* not reached */
@@ -1103,7 +1121,7 @@ handle_stream(serf_request_t *request,
       status = serf_bucket_read(response, 8000, &data, &len);
       if (SERF_BUCKET_READ_ERROR(status))
         {
-          return svn_error_wrap_apr(status, NULL);
+          return svn_ra_serf__wrap_err(status, NULL);
         }
 
       fetch_ctx->read_size += len;
@@ -1122,7 +1140,7 @@ handle_stream(serf_request_t *request,
               /* Skip on to the next iteration of this loop. */
               if (APR_STATUS_IS_EAGAIN(status))
                 {
-                  return svn_error_wrap_apr(status, NULL);
+                  return svn_ra_serf__wrap_err(status, NULL);
                 }
               continue;
             }
@@ -1152,7 +1170,7 @@ handle_stream(serf_request_t *request,
 
       if (status)
         {
-          return svn_error_wrap_apr(status, NULL);
+          return svn_ra_serf__wrap_err(status, NULL);
         }
     }
   /* not reached */
@@ -1216,9 +1234,9 @@ fetch_file(report_context_t *ctx, report
 
   if (!info->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_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
+                              _("The REPORT or PROPFIND response did not "
+                                "include the requested checked-in value"));
     }
 
   /* If needed, create the PROPFIND to retrieve the file's properties. */
@@ -1388,7 +1406,13 @@ start_report(svn_ra_serf__xml_parser_t *
 
   state = parser->state->current_state;
 
-  if (state == NONE && strcmp(name.name, "target-revision") == 0)
+  if (state == NONE && strcmp(name.name, "update-report") == 0)
+    {
+      const char *val = svn_xml_get_attr_value("inline-props", attrs);
+      if (val && (strcmp(val, "true") == 0))
+        ctx->add_props_included = TRUE;
+    }
+  else if (state == NONE && strcmp(name.name, "target-revision") == 0)
     {
       const char *rev;
 
@@ -1528,7 +1552,11 @@ start_report(svn_ra_serf__xml_parser_t *
       /* Mark that we don't have a base. */
       info->base_rev = SVN_INVALID_REVNUM;
       dir->base_rev = info->base_rev;
-      dir->fetch_props = TRUE;
+
+      /* If the server isn't included properties for added items,
+         we'll need to fetch them ourselves. */
+      if (! ctx->add_props_included)
+        dir->fetch_props = TRUE;
 
       dir->repos_relpath = svn_relpath_join(dir->parent_dir->repos_relpath,
                                             dir->base_name, dir->pool);
@@ -1585,9 +1613,13 @@ start_report(svn_ra_serf__xml_parser_t *
       info = push_state(parser, ctx, ADD_FILE);
 
       info->base_rev = SVN_INVALID_REVNUM;
-      info->fetch_props = TRUE;
       info->fetch_file = TRUE;
 
+      /* If the server isn't included properties for added items,
+         we'll need to fetch them ourselves. */
+      if (! ctx->add_props_included)
+        info->fetch_props = TRUE;
+
       info->base_name = apr_pstrdup(info->pool, file_name);
       info->name = NULL;
 
@@ -1862,8 +1894,15 @@ end_report(svn_ra_serf__xml_parser_t *pa
 
   if (state == NONE)
     {
-      /* nothing to close yet. */
-      return SVN_NO_ERROR;
+      if (strcmp(name.name, "update-report") == 0)
+        {
+          ctx->report_completed = TRUE;
+        }
+      else
+        {
+          /* nothing to close yet. */
+          return SVN_NO_ERROR;
+        }
     }
 
   if (((state == OPEN_DIR && (strcmp(name.name, "open-directory") == 0)) ||
@@ -1886,9 +1925,9 @@ end_report(svn_ra_serf__xml_parser_t *pa
       if (!checked_in_url &&
           (!SVN_IS_VALID_REVNUM(info->dir->base_rev) || info->dir->fetch_props))
         {
-          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_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
+                                  _("The REPORT or PROPFIND response did not "
+                                    "include the requested checked-in value"));
         }
 
       info->dir->url = checked_in_url;
@@ -1896,7 +1935,7 @@ end_report(svn_ra_serf__xml_parser_t *pa
       /* At this point, we should have the checked-in href.
        * If needed, create the PROPFIND to retrieve the dir's properties.
        */
-      if (!SVN_IS_VALID_REVNUM(info->dir->base_rev) || info->dir->fetch_props)
+      if (info->dir->fetch_props)
         {
           /* Unconditionally set fetch_props now. */
           info->dir->fetch_props = TRUE;
@@ -2299,7 +2338,7 @@ open_connection_if_needed(svn_ra_serf__s
                                        sess->conns[cur],
                                        sess->pool);
       if (status)
-        return svn_error_wrap_apr(status, NULL);
+        return svn_ra_serf__wrap_err(status, NULL);
 
       sess->num_conns++;
     }
@@ -2353,6 +2392,7 @@ finish_report(void *report_baton,
   svn_stringbuf_t *buf = NULL;
   apr_pool_t *iterpool = svn_pool_create(pool);
   svn_error_t *err;
+  apr_short_interval_time_t waittime_left = sess->timeout;
 
   svn_xml_make_close_tag(&buf, iterpool, "S:update-report");
   SVN_ERR(svn_io_file_write_full(report->body_file, buf->data, buf->len,
@@ -2435,7 +2475,9 @@ finish_report(void *report_baton,
          and what items are allocated within.  */
       iterpool_inner = svn_pool_create(iterpool);
 
-      status = serf_context_run(sess->context, sess->timeout, iterpool_inner);
+      status = serf_context_run(sess->context,
+                                SVN_RA_SERF__CONTEXT_RUN_DURATION,
+                                iterpool_inner);
 
       err = sess->pending_error;
       sess->pending_error = SVN_NO_ERROR;
@@ -2445,19 +2487,35 @@ finish_report(void *report_baton,
           err = handler->server_error->error;
         }
 
+      /* If the context duration timeout is up, we'll subtract that
+         duration from the total time alloted for such things.  If
+         there's no time left, we fail with a message indicating that
+         the connection timed out.  */
       if (APR_STATUS_IS_TIMEUP(status))
         {
           svn_error_clear(err);
-          return svn_error_create(SVN_ERR_RA_DAV_CONN_TIMEOUT,
-                                  NULL,
-                                  _("Connection timed out"));
+          err = SVN_NO_ERROR;
+          status = 0;
+
+          if (waittime_left > SVN_RA_SERF__CONTEXT_RUN_DURATION)
+            {
+              waittime_left -= SVN_RA_SERF__CONTEXT_RUN_DURATION;
+            }
+          else
+            {
+              return svn_error_create(SVN_ERR_RA_DAV_CONN_TIMEOUT, NULL,
+                                      _("Connection timed out"));
+            }
+        }
+      else
+        {
+          waittime_left = sess->timeout;
         }
 
       SVN_ERR(err);
       if (status)
         {
-          return svn_error_wrap_apr(status, _("Error retrieving REPORT (%d)"),
-                                    status);
+          return svn_ra_serf__wrap_err(status, _("Error retrieving REPORT"));
         }
 
       /* Open extra connections if we have enough requests to send. */
@@ -2607,7 +2665,12 @@ finish_report(void *report_baton,
       SVN_ERR(close_all_dirs(report->root_dir));
     }
 
-  err = report->update_editor->close_edit(report->update_baton, iterpool);
+  /* If we got a complete report, close the edit.  Otherwise, abort it. */
+  if (report->report_completed)
+    err = report->update_editor->close_edit(report->update_baton, iterpool);
+  else
+    err = svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
+                           _("Missing update-report close tag"));
 
   svn_pool_destroy(iterpool);
   return svn_error_trace(err);
@@ -2750,6 +2813,10 @@ make_update_reporter(svn_ra_session_t *r
       make_simple_xml_tag(&buf, "S:recursive", "no", scratch_pool);
     }
 
+  /* Subversion 1.8+ servers can be told to send properties for newly
+     added items inline even when doing a skelta response. */
+  make_simple_xml_tag(&buf, "S:include-props", "yes", scratch_pool);
+
   make_simple_xml_tag(&buf, "S:depth", svn_depth_to_word(depth), scratch_pool);
 
   SVN_ERR(svn_io_file_write_full(report->body_file, buf->data, buf->len,

Modified: subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/util.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/util.c Sat Nov 24 20:29:11 2012
@@ -691,6 +691,11 @@ setup_serf_req(serf_request_t *request,
       serf_bucket_headers_setn(*hdrs_bkt, "Content-Type", content_type);
     }
 
+#if SERF_VERSION_AT_LEAST(1, 1, 0)
+  if (session->http10)
+      serf_bucket_headers_setn(*hdrs_bkt, "Connection", "keep-alive");
+#endif
+
   /* These headers need to be sent with every request; see issue #3255
      ("mod_dav_svn does not pass client capabilities to start-commit
      hooks") for why. */
@@ -707,7 +712,8 @@ svn_ra_serf__context_run_wait(svn_boolea
                               apr_pool_t *scratch_pool)
 {
   apr_pool_t *iterpool;
-
+  apr_short_interval_time_t waittime_left = sess->timeout;
+  
   assert(sess->pending_error == SVN_NO_ERROR);
 
   iterpool = svn_pool_create(scratch_pool);
@@ -722,17 +728,36 @@ svn_ra_serf__context_run_wait(svn_boolea
       if (sess->cancel_func)
         SVN_ERR((*sess->cancel_func)(sess->cancel_baton));
 
-      status = serf_context_run(sess->context, sess->timeout, iterpool);
+      status = serf_context_run(sess->context,
+                                SVN_RA_SERF__CONTEXT_RUN_DURATION,
+                                iterpool);
 
       err = sess->pending_error;
       sess->pending_error = SVN_NO_ERROR;
 
+      /* If the context duration timeout is up, we'll subtract that
+         duration from the total time alloted for such things.  If
+         there's no time left, we fail with a message indicating that
+         the connection timed out.  */
       if (APR_STATUS_IS_TIMEUP(status))
         {
           svn_error_clear(err);
-          return svn_error_create(SVN_ERR_RA_DAV_CONN_TIMEOUT,
-                                  NULL,
-                                  _("Connection timed out"));
+          err = SVN_NO_ERROR;
+          status = 0;
+
+          if (waittime_left > SVN_RA_SERF__CONTEXT_RUN_DURATION)
+            {
+              waittime_left -= SVN_RA_SERF__CONTEXT_RUN_DURATION;
+            }
+          else
+            {
+              return svn_error_create(SVN_ERR_RA_DAV_CONN_TIMEOUT, NULL,
+                                      _("Connection timed out"));
+            }
+        }
+      else
+        {
+          waittime_left = sess->timeout;
         }
 
       SVN_ERR(err);
@@ -745,7 +770,7 @@ svn_ra_serf__context_run_wait(svn_boolea
                         _("Error running context"));
             }
 
-          return svn_error_wrap_apr(status, _("Error running context"));
+          return svn_ra_serf__wrap_err(status, _("Error running context"));
         }
 
       /* Debugging purposes only! */
@@ -811,7 +836,12 @@ start_error(svn_ra_serf__xml_parser_t *p
           SVN_ERR(svn_cstring_atoi64(&val, err_code));
           ctx->error->apr_err = (apr_status_t)val;
         }
-      else
+
+      /* If there's no error code provided, or if the provided code is
+         0 (which can happen sometimes depending on how the error is
+         constructed on the server-side), just pick a generic error
+         code to run with. */
+      if (! ctx->error->apr_err)
         {
           ctx->error->apr_err = SVN_ERR_RA_DAV_REQUEST_FAILED;
         }
@@ -928,7 +958,7 @@ svn_ra_serf__handle_discard_body(serf_re
 
   status = drain_bucket(response);
   if (status)
-    return svn_error_wrap_apr(status, NULL);
+    return svn_ra_serf__wrap_err(status, NULL);
 
   return SVN_NO_ERROR;
 }
@@ -1467,7 +1497,7 @@ handle_server_error(serf_request_t *requ
      surface. */
   err = drain_bucket(response);
   if (err && !SERF_BUCKET_READ_ERROR(err))
-    return svn_error_wrap_apr(err, NULL);
+    return svn_ra_serf__wrap_err(err, NULL);
 
   return SVN_NO_ERROR;
 }
@@ -1489,7 +1519,7 @@ svn_ra_serf__handle_xml_parser(serf_requ
   status = serf_bucket_response_status(response, &sl);
   if (SERF_BUCKET_READ_ERROR(status))
     {
-      return svn_error_wrap_apr(status, NULL);
+      return svn_ra_serf__wrap_err(status, NULL);
     }
 
   /* Woo-hoo.  Nothing here to see.  */
@@ -1541,7 +1571,7 @@ svn_ra_serf__handle_xml_parser(serf_requ
 
       if (SERF_BUCKET_READ_ERROR(status))
         {
-          return svn_error_wrap_apr(status, NULL);
+          return svn_ra_serf__wrap_err(status, NULL);
         }
 
       ctx->read_size += len;
@@ -1562,7 +1592,7 @@ svn_ra_serf__handle_xml_parser(serf_requ
               /* Skip on to the next iteration of this loop. */
               if (APR_STATUS_IS_EAGAIN(status))
                 {
-                  return svn_error_wrap_apr(status, NULL);
+                  return svn_ra_serf__wrap_err(status, NULL);
                 }
               continue;
             }
@@ -1606,7 +1636,7 @@ svn_ra_serf__handle_xml_parser(serf_requ
 
       if (APR_STATUS_IS_EAGAIN(status))
         {
-          return svn_error_wrap_apr(status, NULL);
+          return svn_ra_serf__wrap_err(status, NULL);
         }
 
       if (APR_STATUS_IS_EOF(status))
@@ -1627,7 +1657,7 @@ svn_ra_serf__handle_xml_parser(serf_requ
               add_done_item(ctx);
             }
 
-          return svn_error_wrap_apr(status, NULL);
+          return svn_ra_serf__wrap_err(status, NULL);
         }
 
       /* feed me! */
@@ -1817,7 +1847,7 @@ handle_response(serf_request_t *request,
           && handler->sline.code != 304)
         {
           err = svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA,
-                                  svn_error_wrap_apr(status, NULL),
+                                  svn_ra_serf__wrap_err(status, NULL),
                                   _("Premature EOF seen from server"
                                     " (http status=%d)"),
                                   handler->sline.code);
@@ -1966,7 +1996,8 @@ handle_response(serf_request_t *request,
 
   if (err
       && (!SERF_BUCKET_READ_ERROR(err->apr_err)
-          || APR_STATUS_IS_ECONNRESET(err->apr_err)))
+          || APR_STATUS_IS_ECONNRESET(err->apr_err)
+          || APR_STATUS_IS_ECONNABORTED(err->apr_err)))
     {
       /* These errors are special cased in serf
          ### We hope no handler returns these by accident. */
@@ -2212,7 +2243,8 @@ svn_ra_serf__discover_vcc(const char **v
 
       /* Now recreate the root_url. */
       session->repos_root = session->session_url;
-      session->repos_root.path = apr_pstrdup(session->pool, url_buf->data);
+      session->repos_root.path =
+        (char *)svn_fspath__canonicalize(url_buf->data, session->pool);
       session->repos_root_str =
         svn_urlpath__canonicalize(apr_uri_unparse(session->pool,
                                                   &session->repos_root, 0),
@@ -2397,9 +2429,8 @@ expat_response_handler(serf_request_t *r
       XML_SetCharacterDataHandler(ectx->parser, expat_cdata);
     }
 
-  /* ### should we bail on anything < 200 or >= 300 ??
-     ### actually: < 200 should really be handled by the core.  */
-  if (ectx->handler->sline.code == 404)
+  /* ### TODO: sline.code < 200 should really be handled by the core */
+  if ((ectx->handler->sline.code < 200) || (ectx->handler->sline.code >= 300))
     {
       /* By deferring to expect_empty_body(), it will make a choice on
          how to handle the body. Whatever the decision, the core handler
@@ -2418,7 +2449,7 @@ expat_response_handler(serf_request_t *r
 
       status = serf_bucket_read(response, PARSE_CHUNK_SIZE, &data, &len);
       if (SERF_BUCKET_READ_ERROR(status))
-        return svn_error_wrap_apr(status, NULL);
+        return svn_ra_serf__wrap_err(status, NULL);
 
 #if 0
       /* ### move restart/skip into the core handler  */
@@ -2472,7 +2503,7 @@ expat_response_handler(serf_request_t *r
 
       if (status && !SERF_BUCKET_READ_ERROR(status))
         {
-          return svn_error_wrap_apr(status, NULL);
+          return svn_ra_serf__wrap_err(status, NULL);
         }
     }
 

Added: subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/util_error.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/util_error.c?rev=1413258&view=auto
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/util_error.c (added)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/util_error.c Sat Nov 24 20:29:11 2012
@@ -0,0 +1,100 @@
+/*
+ * util_error.c : serf utility routines for wrapping serf status codes
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+#include <serf.h>
+
+#include "svn_utf.h"
+#include "private/svn_error_private.h"
+
+#include "ra_serf.h"
+
+/*
+ * Undefine the helpers for creating errors.
+ *
+ * *NOTE*: Any use of these functions in any other function may need
+ * to call svn_error__locate() because the macro that would otherwise
+ * do this is being undefined and the filename and line number will
+ * not be properly set in the static error_file and error_line
+ * variables.
+ */
+#undef svn_error_create
+#undef svn_error_createf
+#undef svn_error_quick_wrap
+#undef svn_error_wrap_apr
+#undef svn_ra_serf__wrap_err
+
+svn_error_t *
+svn_ra_serf__wrap_err(apr_status_t status,
+                      const char *fmt,
+                      ...)
+{
+  const char *serf_err_msg = serf_error_string(status);
+  svn_error_t *err;
+  va_list ap;
+
+  err = svn_error_create(status, NULL, NULL);
+
+  if (serf_err_msg || fmt)
+    {
+      const char *msg;
+      const char *err_msg;
+      char errbuf[255]; /* Buffer for APR error message. */
+
+      if (serf_err_msg)
+        {
+          err_msg = serf_err_msg;
+        }
+      else
+        {
+          svn_error_t *utf8_err;
+
+          /* Grab the APR error message. */
+          apr_strerror(status, errbuf, sizeof(errbuf));
+          utf8_err = svn_utf_cstring_to_utf8(&err_msg, errbuf, err->pool);
+          if (utf8_err)
+            err_msg = NULL;
+          svn_error_clear(utf8_err);
+        }
+
+      /* Append it to the formatted message. */
+      if (fmt)
+        {
+          va_start(ap, fmt);
+          msg = apr_pvsprintf(err->pool, fmt, ap);
+          va_end(ap);
+        }
+      else
+        {
+          msg = "ra_serf";
+        }
+      if (err_msg)
+        {
+          err->message = apr_pstrcat(err->pool, msg, ": ", err_msg, NULL);
+        }
+      else
+        {
+          err->message = msg;
+        }
+    }
+
+  return err;
+}

Modified: subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/xml.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/xml.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/xml.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra_serf/xml.c Sat Nov 24 20:29:11 2012
@@ -205,9 +205,23 @@ svn_ra_serf__expand_ns(svn_ra_serf__dav_
             }
         }
     }
+  else
+    {
+      const svn_ra_serf__ns_t *ns;
+
+      for (ns = ns_list; ns; ns = ns->next)
+        {
+          if (! ns->namespace[0])
+            {
+              returned_prop_name->namespace = ns->url;
+              returned_prop_name->name = name;
+              return;
+            }
+        }
+    }    
 
-  /* If there is no prefix, or if the prefix is not found, then the
-     name is NOT within a namespace.  */
+  /* If the prefix is not found, then the name is NOT within a
+     namespace.  */
   returned_prop_name->namespace = "";
   returned_prop_name->name = name;
 }