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

svn commit: r1044548 [9/39] - in /subversion/branches/ignore-mergeinfo: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ contrib/client-side/ contrib/hook-scripts/ contrib/server-side/ notes/api-errata/ notes/api-erra...

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_local/ra_plugin.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_local/ra_plugin.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_local/ra_plugin.c Sat Dec 11 00:15:55 2010
@@ -250,7 +250,6 @@ make_reporter(svn_ra_session_t *session,
 {
   svn_ra_local__session_baton_t *sess = session->priv;
   void *rbaton;
-  size_t repos_url_len;
   const char *other_fs_path = NULL;
   const char *repos_url_decoded;
 
@@ -262,6 +261,8 @@ make_reporter(svn_ra_session_t *session,
      regular filesystem path. */
   if (other_url)
     {
+      size_t repos_url_len;
+
       other_url = svn_path_uri_decode(other_url, pool);
       repos_url_decoded = svn_path_uri_decode(sess->repos_url, pool);
       repos_url_len = strlen(repos_url_decoded);
@@ -504,7 +505,8 @@ svn_ra_local__reparent(svn_ra_session_t 
 
   /* Update our FS_PATH sess member to point to our new
      relative-URL-turned-absolute-filesystem-path. */
-  relpath = apr_pstrcat(pool, "/", svn_path_uri_decode(relpath, pool), NULL);
+  relpath = apr_pstrcat(pool, "/", svn_path_uri_decode(relpath, pool),
+                        (char *)NULL);
   svn_stringbuf_set(sess->fs_path, relpath);
 
   return SVN_NO_ERROR;
@@ -563,14 +565,16 @@ static svn_error_t *
 svn_ra_local__change_rev_prop(svn_ra_session_t *session,
                               svn_revnum_t rev,
                               const char *name,
+                              const svn_string_t *const *old_value_p,
                               const svn_string_t *value,
                               apr_pool_t *pool)
 {
   svn_ra_local__session_baton_t *sess = session->priv;
+
   SVN_ERR(get_username(session, pool));
-  return svn_repos_fs_change_rev_prop3(sess->repos, rev, sess->username,
-                                       name, value, TRUE, TRUE, NULL, NULL,
-                                       pool);
+  return svn_repos_fs_change_rev_prop4(sess->repos, rev, sess->username,
+                                       name, old_value_p, value, TRUE, TRUE,
+                                       NULL, NULL, pool);
 }
 
 static svn_error_t *
@@ -689,6 +693,7 @@ svn_ra_local__get_mergeinfo(svn_ra_sessi
                             const apr_array_header_t *paths,
                             svn_revnum_t revision,
                             svn_mergeinfo_inheritance_t inherit,
+                            svn_boolean_t *validate_inherited_mergeinfo,
                             svn_boolean_t include_descendants,
                             apr_pool_t *pool)
 {
@@ -705,9 +710,11 @@ svn_ra_local__get_mergeinfo(svn_ra_sessi
         svn_dirent_join(sess->fs_path->data, relative_path, pool);
     }
 
-  SVN_ERR(svn_repos_fs_get_mergeinfo(&tmp_catalog, sess->repos, abs_paths,
-                                     revision, inherit, include_descendants,
-                                     NULL, NULL, pool));
+  SVN_ERR(svn_repos_fs_get_mergeinfo2(&tmp_catalog, sess->repos, abs_paths,
+                                      revision, inherit,
+                                      *validate_inherited_mergeinfo,
+                                      include_descendants,
+                                      NULL, NULL, pool));
   if (apr_hash_count(tmp_catalog) > 0)
     SVN_ERR(svn_mergeinfo__remove_prefix_from_catalog(catalog,
                                                       tmp_catalog,
@@ -869,13 +876,14 @@ svn_ra_local__get_log(svn_ra_session_t *
                       apr_pool_t *pool)
 {
   svn_ra_local__session_baton_t *sess = session->priv;
-  int i;
   struct log_baton lb;
   apr_array_header_t *abs_paths =
     apr_array_make(pool, 0, sizeof(const char *));
 
   if (paths)
     {
+      int i;
+
       for (i = 0; i < paths->nelts; i++)
         {
           const char *relative_path = APR_ARRAY_IDX(paths, i, const char *);
@@ -920,7 +928,7 @@ svn_ra_local__do_check_path(svn_ra_sessi
 {
   svn_ra_local__session_baton_t *sess = session->priv;
   svn_fs_root_t *root;
-  const char *abs_path = svn_uri_join(sess->fs_path->data, path, pool);
+  const char *abs_path = svn_fspath__join(sess->fs_path->data, path, pool);
 
   if (! SVN_IS_VALID_REVNUM(revision))
     SVN_ERR(svn_fs_youngest_rev(&revision, sess->fs, pool));
@@ -1389,7 +1397,8 @@ svn_ra_local__has_capability(svn_ra_sess
   if (strcmp(capability, SVN_RA_CAPABILITY_DEPTH) == 0
       || strcmp(capability, SVN_RA_CAPABILITY_LOG_REVPROPS) == 0
       || strcmp(capability, SVN_RA_CAPABILITY_PARTIAL_REPLAY) == 0
-      || strcmp(capability, SVN_RA_CAPABILITY_COMMIT_REVPROPS) == 0)
+      || strcmp(capability, SVN_RA_CAPABILITY_COMMIT_REVPROPS) == 0
+      || strcmp(capability, SVN_RA_CAPABILITY_ATOMIC_REVPROPS) == 0)
     {
       *has = TRUE;
     }

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/commit.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/commit.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/commit.c Sat Dec 11 00:15:55 2010
@@ -49,33 +49,27 @@
 
 
 #define APPLY_TO_VERSION "<D:apply-to-version/>"
+
 /*
-** version_rsrc_t: identify the relevant pieces of a resource on the server
-**
-** REVISION is the resource's revision, or SVN_INVALID_REVNUM if it is
-** new or is the HEAD.
-**
-** URL refers to the public/viewable/original resource.
-** VSN_URL refers to the version resource that we stored locally
-** WR_URL refers to a working resource for this resource
-**
-** Note that VSN_URL is NULL if this resource has just been added, and
-** WR_URL can be NULL if the resource has not (yet) been checked out.
-**
-** LOCAL_PATH is relative to the root of the commit. It will be used
-** for the get_func, push_func, and close_func callbacks.
-**
-** NAME is the name of the resource.
-*/
+ * version_rsrc_t: identify the relevant pieces of a resource on the server
+ *
+ * NOTE:  If you tweak this structure, please update dup_resource() to
+ * ensure that it continues to create complete deep copies!
+ */
 typedef struct
 {
-  svn_revnum_t revision;
-  const char *url;
-  const char *vsn_url;
-  const char *wr_url;
-  const char *local_path;
-  const char *name;
-  apr_pool_t *pool; /* pool in which this resource is allocated. */
+  svn_revnum_t revision;  /* resource's revision, or SVN_INVALID_REVNUM
+                             if it's new or is the HEAD */
+  const char *url;        /* public/viewable/original resource URL */
+  const char *vsn_url;    /* version resource URL that we stored
+                             locally; NULL if this is a just-added resource */
+  const char *wr_url;     /* working resource URL for this resource;
+                             NULL for resources not (yet) checked out */
+  const char *local_path; /* path relative to the root of the commit
+                             (used for get_func, push_func, and
+                             close_func callbacks). */
+  const char *name;       /* basename of the resource */
+  apr_pool_t *pool;       /* pool in which this resource is allocated */
 
 } version_rsrc_t;
 
@@ -141,11 +135,10 @@ static const ne_propname fetch_props[] =
 
 static const ne_propname log_message_prop = { SVN_DAV_PROP_NS_SVN, "log" };
 
-/* perform a deep copy of BASE into POOL, and return the result. */
+/* Return a deep copy of BASE allocated from POOL. */
 static version_rsrc_t * dup_resource(version_rsrc_t *base, apr_pool_t *pool)
 {
   version_rsrc_t *rsrc = apr_pcalloc(pool, sizeof(*rsrc));
-  rsrc->pool = pool;
   rsrc->revision = base->revision;
   rsrc->url = base->url ?
     apr_pstrdup(pool, base->url) : NULL;
@@ -155,6 +148,9 @@ static version_rsrc_t * dup_resource(ver
     apr_pstrdup(pool, base->wr_url) : NULL;
   rsrc->local_path = base->local_path ?
     apr_pstrdup(pool, base->local_path) : NULL;
+  rsrc->name = base->name ?
+    apr_pstrdup(pool, base->name) : NULL;
+  rsrc->pool = pool;
   return rsrc;
 }
 
@@ -616,7 +612,8 @@ static svn_error_t * do_proppatch(svn_ra
     }
 
   return svn_ra_neon__do_proppatch(ras, url, rb->prop_changes,
-                                   rb->prop_deletes, extra_headers, pool);
+                                   rb->prop_deletes, NULL, extra_headers,
+                                   pool);
 }
 
 
@@ -700,7 +697,7 @@ static svn_error_t * commit_delete_entry
                                          apr_pool_t *pool)
 {
   resource_baton_t *parent = parent_baton;
-  const char *name = svn_relpath_basename(path, pool);
+  const char *name = svn_relpath_basename(path, NULL);
   apr_hash_t *extra_headers = NULL;
   const char *child;
   int code;
@@ -1416,7 +1413,7 @@ static svn_error_t * apply_revprops(comm
     return err;
 
   return svn_ra_neon__do_proppatch(cc->ras, vcc_rsrc.wr_url, revprop_table,
-                                   NULL, NULL, pool);
+                                   NULL, NULL, NULL, pool);
 }
 
 svn_error_t * svn_ra_neon__get_commit_editor(svn_ra_session_t *session,

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/fetch.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/fetch.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/fetch.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/fetch.c Sat Dec 11 00:15:55 2010
@@ -56,17 +56,6 @@
 
 
 typedef struct {
-  /* the information for this subdir. if rsrc==NULL, then this is a sentinel
-     record in fetch_ctx_t.subdirs to close the directory implied by the
-     parent_baton member. */
-  svn_ra_neon__resource_t *rsrc;
-
-  /* the directory containing this subdirectory. */
-  void *parent_baton;
-
-} subdir_t;
-
-typedef struct {
   apr_pool_t *pool;
 
   /* these two are the handler that the editor gave us */
@@ -92,9 +81,6 @@ typedef struct {
   void *subctx;
 } custom_get_ctx_t;
 
-#define POP_SUBDIR(sds) (APR_ARRAY_IDX((sds), --(sds)->nelts, subdir_t *))
-#define PUSH_SUBDIR(sds,s) (APR_ARRAY_PUSH((sds), subdir_t *) = (s))
-
 typedef svn_error_t * (*prop_setter_t)(void *baton,
                                        const char *name,
                                        const svn_string_t *value,
@@ -346,7 +332,7 @@ static svn_error_t *add_props(apr_hash_t
              server, or both.  Convert the URI namespace into normal
              'svn:' prefix again before pushing it at the wc. */
           SVN_ERR((*setter)(baton, apr_pstrcat(pool, SVN_PROP_PREFIX,
-                                               key + NSLEN, NULL),
+                                               key + NSLEN, (char *)NULL),
                             val, pool));
         }
 #undef NSLEN
@@ -640,7 +626,8 @@ filter_props(apr_hash_t *props,
       if (strncmp(name, SVN_DAV_PROP_NS_SVN, NSLEN) == 0)
         {
           apr_hash_set(props,
-                       apr_pstrcat(pool, SVN_PROP_PREFIX, name + NSLEN, NULL),
+                       apr_pstrcat(pool, SVN_PROP_PREFIX, name + NSLEN,
+                                   (char *)NULL),
                        APR_HASH_KEY_STRING,
                        value);
           continue;
@@ -1122,6 +1109,7 @@ svn_error_t *svn_ra_neon__get_latest_rev
 svn_error_t *svn_ra_neon__change_rev_prop(svn_ra_session_t *session,
                                           svn_revnum_t rev,
                                           const char *name,
+                                          const svn_string_t *const *old_value_p,
                                           const svn_string_t *value,
                                           apr_pool_t *pool)
 {
@@ -1130,12 +1118,24 @@ svn_error_t *svn_ra_neon__change_rev_pro
   svn_error_t *err;
   apr_hash_t *prop_changes = NULL;
   apr_array_header_t *prop_deletes = NULL;
+  apr_hash_t *prop_old_values = NULL;
   static const ne_propname wanted_props[] =
     {
       { "DAV:", "auto-version" },
       { NULL }
     };
 
+  if (old_value_p)
+    {
+      svn_boolean_t capable;
+      SVN_ERR(svn_ra_neon__has_capability(session, &capable,
+                                          SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+                                          pool));
+
+      /* How did you get past the same check in svn_ra_change_rev_prop2()? */
+      SVN_ERR_ASSERT(capable);
+    }
+
   /* Main objective: do a PROPPATCH (allprops) on a baseline object */
 
   /* ### A Word From Our Sponsor:  see issue #916.
@@ -1165,19 +1165,33 @@ svn_error_t *svn_ra_neon__change_rev_pro
          to attempt the PROPPATCH if the deltaV server is going to do
          auto-versioning and create a new baseline! */
 
-  if (value)
+  if (old_value_p)
     {
-      prop_changes = apr_hash_make(pool);
-      apr_hash_set(prop_changes, name, APR_HASH_KEY_STRING, value);
+      svn_dav__two_props_t *both_values;
+
+      both_values = apr_palloc(pool, sizeof(*both_values));
+      both_values->old_value_p = old_value_p;
+      both_values->new_value = value;
+
+      prop_old_values = apr_hash_make(pool);
+      apr_hash_set(prop_old_values, name, APR_HASH_KEY_STRING, both_values);
     }
   else
     {
-      prop_deletes = apr_array_make(pool, 1, sizeof(const char *));
-      APR_ARRAY_PUSH(prop_deletes, const char *) = name;
+      if (value)
+        {
+          prop_changes = apr_hash_make(pool);
+          apr_hash_set(prop_changes, name, APR_HASH_KEY_STRING, value);
+        }
+      else
+        {
+          prop_deletes = apr_array_make(pool, 1, sizeof(const char *));
+          APR_ARRAY_PUSH(prop_deletes, const char *) = name;
+        }
     }
 
   err = svn_ra_neon__do_proppatch(ras, baseline->url, prop_changes,
-                                  prop_deletes, NULL, pool);
+                                  prop_deletes, prop_old_values, NULL, pool);
   if (err)
     return
       svn_error_create
@@ -2231,7 +2245,8 @@ end_element(void *userdata, int state,
           rb->file_baton ? rb->file_pool : TOP_DIR(rb).pool;
         prop_setter_t setter =
           rb->file_baton ? editor->change_file_prop : editor->change_dir_prop;
-        const char *name = apr_pstrcat(pool, elm->nspace, elm->name, NULL);
+        const char *name = apr_pstrcat(pool, elm->nspace, elm->name,
+                                       (char *)NULL);
         void *baton = rb->file_baton ? rb->file_baton : TOP_DIR(rb).baton;
         svn_string_t valstr;
 

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/get_locks.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/get_locks.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/get_locks.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/get_locks.c Sat Dec 11 00:15:55 2010
@@ -379,7 +379,7 @@ svn_ra_neon__get_locks(svn_ra_session_t 
                                                  url, pool));
 
   baton.lock_hash = apr_hash_make(pool);
-  baton.path = apr_pstrcat(pool, "/", rel_path, NULL);
+  baton.path = apr_pstrcat(pool, "/", rel_path, (char *)NULL);
   baton.requested_depth = depth;
   baton.pool = pool;
   baton.scratchpool = svn_pool_create(pool);

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/lock.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/lock.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/lock.c Sat Dec 11 00:15:55 2010
@@ -282,7 +282,7 @@ do_lock(svn_lock_t **lock,
                            "<D:owner>",
                            apr_xml_quote_string(pool, comment, 0),
                            "</D:owner>",
-                           NULL)
+                           (char *)NULL)
              : "");
 
   extra_headers = apr_hash_make(req->pool);

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/mergeinfo.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/mergeinfo.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/mergeinfo.c Sat Dec 11 00:15:55 2010
@@ -51,6 +51,7 @@ struct mergeinfo_baton
   svn_stringbuf_t *curr_path;
   svn_stringbuf_t *curr_info;
   svn_mergeinfo_catalog_t catalog;
+  svn_boolean_t validated_inherited_mergeinfo;
   svn_error_t *err;
 };
 
@@ -62,6 +63,8 @@ static const svn_ra_neon__xml_elm_t merg
       SVN_RA_NEON__XML_CDATA },
     { SVN_XML_NAMESPACE, SVN_DAV__MERGEINFO_INFO, ELEM_mergeinfo_info,
       SVN_RA_NEON__XML_CDATA },
+    { SVN_XML_NAMESPACE, SVN_DAV__VALIDATE_INHERITED,
+      ELEM_validate_inherited_mergeinfo, SVN_RA_NEON__XML_CDATA },
     { NULL }
   };
 
@@ -93,6 +96,10 @@ start_element(int *elem, void *baton, in
       svn_stringbuf_setempty(mb->curr_info);
       svn_stringbuf_setempty(mb->curr_path);
     }
+  else if (elm->id == ELEM_validate_inherited_mergeinfo)
+    {
+      mb->validated_inherited_mergeinfo = TRUE;
+    }
 
   SVN_ERR(mb->err);
 
@@ -163,10 +170,11 @@ svn_ra_neon__get_mergeinfo(svn_ra_sessio
                            const apr_array_header_t *paths,
                            svn_revnum_t revision,
                            svn_mergeinfo_inheritance_t inherit,
+                           svn_boolean_t *validate_inherited_mergeinfo,
                            svn_boolean_t include_descendants,
                            apr_pool_t *pool)
 {
-  int i, status_code;
+  int status_code;
   svn_ra_neon__session_t *ras = session->priv;
   svn_stringbuf_t *request_body = svn_stringbuf_create("", pool);
   struct mergeinfo_baton mb;
@@ -194,6 +202,14 @@ svn_ra_neon__get_mergeinfo(svn_ra_sessio
                                         "</S:inherit>",
                                         svn_inheritance_to_word(inherit)));
 
+  if (*validate_inherited_mergeinfo)
+    {
+      /* Send it only if true; server will default to "no". */
+      svn_stringbuf_appendcstr(request_body,
+                               "<S:" SVN_DAV__VALIDATE_INHERITED ">yes"
+                               "</S:" SVN_DAV__VALIDATE_INHERITED ">");
+    }
+
   if (include_descendants)
     {
       /* Send it only if true; server will default to "no". */
@@ -204,6 +220,8 @@ svn_ra_neon__get_mergeinfo(svn_ra_sessio
 
   if (paths)
     {
+      int i;
+
       for (i = 0; i < paths->nelts; i++)
         {
           const char *this_path =
@@ -222,6 +240,7 @@ svn_ra_neon__get_mergeinfo(svn_ra_sessio
   mb.curr_path = svn_stringbuf_create("", pool);
   mb.curr_info = svn_stringbuf_create("", pool);
   mb.catalog = apr_hash_make(pool);
+  mb.validated_inherited_mergeinfo = FALSE;
   mb.err = SVN_NO_ERROR;
 
   /* ras's URL may not exist in HEAD, and thus it's not safe to send
@@ -251,5 +270,7 @@ svn_ra_neon__get_mergeinfo(svn_ra_sessio
   if (mb.err == SVN_NO_ERROR && apr_hash_count(mb.catalog))
     *catalog = mb.catalog;
 
+  *validate_inherited_mergeinfo = mb.validated_inherited_mergeinfo;
+
   return mb.err;
 }

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/options.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/options.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/options.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/options.c Sat Dec 11 00:15:55 2010
@@ -152,6 +152,8 @@ parse_capabilities(ne_request *req,
                APR_HASH_KEY_STRING, capability_no);
   apr_hash_set(ras->capabilities, SVN_RA_CAPABILITY_LOG_REVPROPS,
                APR_HASH_KEY_STRING, capability_no);
+  apr_hash_set(ras->capabilities, SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+               APR_HASH_KEY_STRING, capability_no);
 
   /* Then find out which ones are supported. */
   val = ne_get_response_header(req, "dav");
@@ -199,6 +201,10 @@ parse_capabilities(ne_request *req,
         apr_hash_set(ras->capabilities, SVN_RA_CAPABILITY_LOG_REVPROPS,
                      APR_HASH_KEY_STRING, capability_yes);
 
+      if (svn_cstring_match_glob_list(SVN_DAV_NS_DAV_SVN_ATOMIC_REVPROPS, vals))
+        apr_hash_set(ras->capabilities, SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+                     APR_HASH_KEY_STRING, capability_yes);
+
       if (svn_cstring_match_glob_list(SVN_DAV_NS_DAV_SVN_PARTIAL_REPLAY,
                                       vals))
         apr_hash_set(ras->capabilities, SVN_RA_CAPABILITY_PARTIAL_REPLAY,
@@ -389,12 +395,15 @@ svn_ra_neon__has_capability(svn_ra_sessi
              support mergeinfo. */
           svn_mergeinfo_catalog_t ignored;
           svn_error_t *err;
+          svn_boolean_t validate_inherited_mergeinfo = FALSE;
           apr_array_header_t *paths = apr_array_make(pool, 1,
                                                      sizeof(char *));
           APR_ARRAY_PUSH(paths, const char *) = "";
 
           err = svn_ra_neon__get_mergeinfo(session, &ignored, paths, 0,
-                                           FALSE, FALSE, pool);
+                                           FALSE,
+                                           &validate_inherited_mergeinfo,
+                                           FALSE, pool);
 
           if (err)
             {

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/props.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/props.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/props.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/props.c Sat Dec 11 00:15:55 2010
@@ -441,7 +441,7 @@ static svn_error_t * end_element(void *b
 
       if (state == ELEM_unknown)
         {
-          name = apr_pstrcat(pc->pool, nspace, name, NULL);
+          name = apr_pstrcat(pc->pool, nspace, name, (char *)NULL);
         }
       else
         {
@@ -529,7 +529,8 @@ svn_error_t * svn_ra_neon__get_props(apr
           svn_pool_clear(iterpool);
           svn_stringbuf_appendcstr
             (body, apr_pstrcat(iterpool, "<", which_props[n].name, " xmlns=\"",
-                               which_props[n].nspace, "\"/>" DEBUG_CR, NULL));
+                               which_props[n].nspace, "\"/>" DEBUG_CR,
+                               (char *)NULL));
         }
       svn_stringbuf_appendcstr(body, "</prop></propfind>" DEBUG_CR);
       svn_pool_destroy(iterpool);
@@ -626,7 +627,7 @@ svn_error_t * svn_ra_neon__get_one_prop(
   SVN_ERR(svn_ra_neon__get_props_resource(&rsrc, sess, url, label, props,
                                           pool));
 
-  name = apr_pstrcat(pool, propname->nspace, propname->name, NULL);
+  name = apr_pstrcat(pool, propname->nspace, propname->name, (char *)NULL);
   value = apr_hash_get(rsrc->propset, name, APR_HASH_KEY_STRING);
   if (value == NULL)
     {
@@ -1075,30 +1076,66 @@ get_encoding_and_cdata(const char **enco
 static svn_error_t *
 append_setprop(svn_stringbuf_t *body,
                const char *name,
+               const svn_string_t *const *old_value_p,
                const svn_string_t *value,
                apr_pool_t *pool)
 {
   const char *encoding;
   const char *xml_safe;
   const char *xml_tag_name;
+  const char *old_value_tag;
 
   /* Map property names to namespaces */
 #define NSLEN (sizeof(SVN_PROP_PREFIX) - 1)
   if (strncmp(name, SVN_PROP_PREFIX, NSLEN) == 0)
     {
-      xml_tag_name = apr_pstrcat(pool, "S:", name + NSLEN, NULL);
+      xml_tag_name = apr_pstrcat(pool, "S:", name + NSLEN, (char *)NULL);
     }
 #undef NSLEN
   else
     {
-      xml_tag_name = apr_pstrcat(pool, "C:", name, NULL);
+      xml_tag_name = apr_pstrcat(pool, "C:", name, (char *)NULL);
     }
 
-  SVN_ERR(get_encoding_and_cdata(&encoding, &xml_safe, value, pool));
+  if (old_value_p)
+    {
+      if (*old_value_p)
+        {
+          const char *encoding2;
+          const char *xml_safe2;
+          SVN_ERR(get_encoding_and_cdata(&encoding2, &xml_safe2,
+                                         *old_value_p, pool));
+          old_value_tag = apr_psprintf(pool, "<%s %s>%s</%s>",
+                                       "V:" SVN_DAV__OLD_VALUE, encoding2,
+                                       xml_safe2, "V:" SVN_DAV__OLD_VALUE);
+        }
+      else
+        {
+#define OLD_VALUE_ABSENT_TAG \
+          "<" "V:" SVN_DAV__OLD_VALUE \
+              " V:" SVN_DAV__OLD_VALUE__ABSENT "=\"1\" " \
+          "/>"
+          old_value_tag = OLD_VALUE_ABSENT_TAG;
+        }
+    }
+  else
+    {
+      old_value_tag = "";
+    }
+
+  if (old_value_p && !value)
+    {
+      encoding = "V:" SVN_DAV__OLD_VALUE__ABSENT "=\"1\"" ;
+      xml_safe = "";
+    }
+  else
+    {
+      SVN_ERR(get_encoding_and_cdata(&encoding, &xml_safe, value, pool));
+    }
 
   svn_stringbuf_appendcstr(body,
-                           apr_psprintf(pool,"<%s %s>%s</%s>",
-                                        xml_tag_name, encoding,
+                           apr_psprintf(pool,"<%s %s>%s%s</%s>",
+                                        xml_tag_name, encoding, old_value_tag,
                                         xml_safe, xml_tag_name));
   return SVN_NO_ERROR;
 }
@@ -1109,6 +1146,7 @@ svn_ra_neon__do_proppatch(svn_ra_neon__s
                           const char *url,
                           apr_hash_t *prop_changes,
                           const apr_array_header_t *prop_deletes,
+                          apr_hash_t *prop_old_values,
                           apr_hash_t *extra_headers,
                           apr_pool_t *pool)
 {
@@ -1118,7 +1156,8 @@ svn_ra_neon__do_proppatch(svn_ra_neon__s
 
   /* just punt if there are no changes to make. */
   if ((prop_changes == NULL || (! apr_hash_count(prop_changes)))
-      && (prop_deletes == NULL || prop_deletes->nelts == 0))
+      && (prop_deletes == NULL || prop_deletes->nelts == 0)
+      && (prop_old_values == NULL || (! apr_hash_count(prop_old_values))))
     return SVN_NO_ERROR;
 
   /* easier to roll our own PROPPATCH here than use ne_proppatch(), which
@@ -1130,6 +1169,22 @@ svn_ra_neon__do_proppatch(svn_ra_neon__s
      SVN_DAV_PROP_NS_CUSTOM "\" xmlns:S=\""
      SVN_DAV_PROP_NS_SVN "\">" DEBUG_CR, pool);
 
+  /* Handle property changes/deletions with expected old values. */
+  if (prop_old_values)
+    {
+      apr_hash_index_t *hi;
+      svn_stringbuf_appendcstr(body, "<D:set><D:prop>");
+      for (hi = apr_hash_first(pool, prop_old_values); hi; hi = apr_hash_next(hi))
+        {
+          const char *name = svn__apr_hash_index_key(hi);
+          svn_dav__two_props_t *both_values = svn__apr_hash_index_val(hi);
+          svn_pool_clear(subpool);
+          SVN_ERR(append_setprop(body, name, both_values->old_value_p,
+                                 both_values->new_value, subpool));
+        }
+      svn_stringbuf_appendcstr(body, "</D:prop></D:set>");
+    }
+
   /* Handle property changes. */
   if (prop_changes)
     {
@@ -1141,7 +1196,7 @@ svn_ra_neon__do_proppatch(svn_ra_neon__s
           void *val;
           svn_pool_clear(subpool);
           apr_hash_this(hi, &key, NULL, &val);
-          SVN_ERR(append_setprop(body, key, val, subpool));
+          SVN_ERR(append_setprop(body, key, NULL, val, subpool));
         }
       svn_stringbuf_appendcstr(body, "</D:prop></D:set>");
     }
@@ -1155,7 +1210,7 @@ svn_ra_neon__do_proppatch(svn_ra_neon__s
         {
           const char *name = APR_ARRAY_IDX(prop_deletes, n, const char *);
           svn_pool_clear(subpool);
-          SVN_ERR(append_setprop(body, name, NULL, subpool));
+          SVN_ERR(append_setprop(body, name, NULL, NULL, subpool));
         }
       svn_stringbuf_appendcstr(body, "</D:prop></D:remove>");
     }

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/ra_neon.h
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/ra_neon.h?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/ra_neon.h (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/ra_neon.h Sat Dec 11 00:15:55 2010
@@ -254,6 +254,7 @@ svn_error_t *svn_ra_neon__get_dated_revi
 svn_error_t *svn_ra_neon__change_rev_prop(svn_ra_session_t *session,
                                           svn_revnum_t rev,
                                           const char *name,
+                                          const svn_string_t *const *old_value_p,
                                           const svn_string_t *value,
                                           apr_pool_t *pool);
 
@@ -298,13 +299,15 @@ svn_error_t *svn_ra_neon__get_dir(svn_ra
 svn_error_t * svn_ra_neon__abort_commit(void *session_baton,
                                         void *edit_baton);
 
-svn_error_t * svn_ra_neon__get_mergeinfo(svn_ra_session_t *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);
+svn_error_t * svn_ra_neon__get_mergeinfo(
+  svn_ra_session_t *session,
+  apr_hash_t **mergeinfo,
+  const apr_array_header_t *paths,
+  svn_revnum_t revision,
+  svn_mergeinfo_inheritance_t inherit,
+  svn_boolean_t *validate_inherited_mergeinfo,
+  svn_boolean_t include_descendants,
+  apr_pool_t *pool);
 
 svn_error_t * svn_ra_neon__do_update(svn_ra_session_t *session,
                                      const svn_ra_reporter3_t **reporter,
@@ -575,12 +578,15 @@ svn_error_t *svn_ra_neon__get_vcc(const 
 /* Issue a PROPPATCH request on URL, transmitting PROP_CHANGES (a hash
    of const svn_string_t * values keyed on Subversion user-visible
    property names) and PROP_DELETES (an array of property names to
-   delete).  Send any extra request headers in EXTRA_HEADERS. Use POOL
-   for all allocations.  */
+   delete). PROP_OLD_VALUES is a hash of Subversion user-visible property
+   names mapped to svn_dav__two_props_t * values. Send any extra
+   request headers in EXTRA_HEADERS. Use POOL for all allocations.
+ */
 svn_error_t *svn_ra_neon__do_proppatch(svn_ra_neon__session_t *ras,
                                        const char *url,
                                        apr_hash_t *prop_changes,
                                        const apr_array_header_t *prop_deletes,
+                                       apr_hash_t *prop_old_values,
                                        apr_hash_t *extra_headers,
                                        apr_pool_t *pool);
 
@@ -855,7 +861,8 @@ enum {
   ELEM_mergeinfo_info,
   ELEM_has_children,
   ELEM_merged_revision,
-  ELEM_deleted_rev_report
+  ELEM_deleted_rev_report,
+  ELEM_validate_inherited_mergeinfo
 };
 
 /* ### docco */

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/session.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/session.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/session.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/session.c Sat Dec 11 00:15:55 2010
@@ -799,7 +799,8 @@ svn_ra_neon__open(svn_ra_session_t *sess
     callbacks->get_client_string(callback_baton, &client_string, pool);
 
   if (client_string)
-    useragent = apr_pstrcat(pool, "SVN/" SVN_VERSION "/", client_string, NULL);
+    useragent = apr_pstrcat(pool, "SVN/" SVN_VERSION "/", client_string,
+                            (char *)NULL);
   else
     useragent = "SVN/" SVN_VERSION;
 

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/util.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/util.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_neon/util.c Sat Dec 11 00:15:55 2010
@@ -167,6 +167,7 @@ typedef struct
   svn_ra_neon__request_t *req;
   svn_stringbuf_t *description;
   svn_boolean_t contains_error;
+  svn_boolean_t contains_precondition_error;
 } multistatus_baton_t;
 
 /* Implements svn_ra_neon__startelm_cb_t. */
@@ -231,6 +232,9 @@ end_207_element(void *baton, int state,
             return svn_error_create(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
                                     _("The request response contained at least "
                                       "one error"));
+          else if (b->contains_precondition_error) 
+            return svn_error_create(SVN_ERR_FS_PROP_BASEVALUE_MISMATCH, NULL,
+                                    b->description->data);
           else
             return svn_error_create(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
                                     b->description->data);
@@ -260,6 +264,10 @@ end_207_element(void *baton, int state,
             else
               b->propstat_has_error = (status.klass != 2);
 
+            /* Handle "412 Precondition Failed" specially */
+            if (status.code == 412)
+              b->contains_precondition_error = TRUE;
+
             free(status.reason_phrase);
           }
         else

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/commit.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/commit.c Sat Dec 11 00:15:55 2010
@@ -109,6 +109,10 @@ typedef struct {
   apr_hash_t *changed_props;
   apr_hash_t *removed_props;
 
+  /* Same, for the old value (*old_value_p). */
+  apr_hash_t *previous_changed_props;
+  apr_hash_t *previous_removed_props;
+
   /* In HTTP v2, this is the file/directory version we think we're changing. */
   svn_revnum_t base_revision;
 
@@ -376,7 +380,7 @@ checkout_dir(dir_context_t *dir)
           dir->checkout->activity_url_len = dir->commit->activity_url_len;
           dir->checkout->resource_url =
             svn_path_url_add_component2(dir->parent_dir->checkout->resource_url,
-                                        svn_relpath_basename(dir->name, dir->pool),
+                                        svn_relpath_basename(dir->name, NULL),
                                         dir->pool);
 
           apr_hash_set(dir->commit->copied_entries,
@@ -521,9 +525,9 @@ get_version_url(const char **checked_in_
           propfind_url = session->repos_url.path;
         }
 
-      svn_ra_serf__deliver_props(&propfind_ctx, props, session, conn,
-                                 propfind_url, base_revision, "0",
-                                 checked_in_props, FALSE, NULL, pool);
+      SVN_ERR(svn_ra_serf__deliver_props(&propfind_ctx, props, session, conn,
+                                         propfind_url, base_revision, "0",
+                                         checked_in_props, FALSE, NULL, pool));
 
       SVN_ERR(svn_ra_serf__wait_for_props(propfind_ctx, session, pool));
 
@@ -639,16 +643,17 @@ checkout_file(file_context_t *file)
 /* Helper function for proppatch_walker() below. */
 static svn_error_t *
 get_encoding_and_cdata(const char **encoding_p,
-                       serf_bucket_t **cdata_bkt_p,
+                       const svn_string_t **encoded_value_p,
                        serf_bucket_alloc_t *alloc,
                        const svn_string_t *value,
                        apr_pool_t *pool)
 {
-  const char *encoding;
-  const char *cdata;
-  apr_size_t len; /* of cdata */
-
-  SVN_ERR_ASSERT(value);
+  if (value == NULL)
+    {
+      *encoding_p = NULL;
+      *encoded_value_p = NULL;
+      return SVN_NO_ERROR;
+    }
 
   /* If a property is XML-safe, XML-encode it.  Else, base64-encode
      it. */
@@ -656,23 +661,72 @@ get_encoding_and_cdata(const char **enco
     {
       svn_stringbuf_t *xml_esc = NULL;
       svn_xml_escape_cdata_string(&xml_esc, value, pool);
-      encoding = NULL;
-      cdata = xml_esc->data;
-      len = xml_esc->len;
+      *encoding_p = NULL;
+      *encoded_value_p = svn_string_create_from_buf(xml_esc, pool);
     }
   else
     {
-      const svn_string_t *base64ed = svn_base64_encode_string2(value, TRUE,
-                                                               pool);
-      encoding = "base64";
-      cdata = base64ed->data;
-      len = base64ed->len;
+      *encoding_p = "base64";
+      *encoded_value_p = svn_base64_encode_string2(value, TRUE, pool);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+typedef struct walker_baton_t {
+  serf_bucket_t *body_bkt;
+  apr_hash_t *previous_changed_props;
+  apr_hash_t *previous_removed_props;
+  const char *path;
+
+  /* Hack, since change_rev_prop(old_value_p != NULL, value = NULL) uses D:set
+     rather than D:remove...  (see notes/http-and-webdav/webdav-protocol) */
+  enum {
+    filter_all_props,
+    filter_props_with_old_value,
+    filter_props_without_old_value
+  } filter;
+
+  /* Is the property being deleted? */
+  svn_boolean_t deleting;
+} walker_baton_t;
+
+static svn_error_t *
+derive_old_val(const svn_string_t *const *   *old_val_p_p,
+               walker_baton_t *wb,
+               const char *ns,
+               const char *name,
+               apr_pool_t *pool)
+{
+  const svn_string_t *const *old_val_p;
+
+  old_val_p = NULL;
+
+  if (wb->previous_changed_props)
+    {
+      const svn_string_t *old_val;
+      old_val = svn_ra_serf__get_prop_string(wb->previous_changed_props,
+                                             wb->path, ns, name);
+      if (old_val)
+        {
+          old_val_p = apr_pcalloc(pool, sizeof(*old_val_p));
+          *(const svn_string_t **)old_val_p = svn_string_dup(old_val, pool);
+        }
     }
 
-  /* ENCODING, CDATA, and LEN are now set. */
+  if (wb->previous_removed_props)
+    {
+      const svn_string_t *old_val;
+      old_val = svn_ra_serf__get_prop_string(wb->previous_removed_props,
+                                             wb->path, ns, name);
+      if (old_val)
+        {
+          old_val_p = apr_pcalloc(pool, sizeof(*old_val_p));
+          *(const svn_string_t **)old_val_p = NULL;
+        }
+    }
 
-  *encoding_p = encoding;
-  *cdata_bkt_p = SERF_BUCKET_SIMPLE_STRING_LEN(cdata, len, alloc);
+  *old_val_p_p = old_val_p;
   return SVN_NO_ERROR;
 }
 
@@ -683,28 +737,99 @@ proppatch_walker(void *baton,
                  const svn_string_t *val,
                  apr_pool_t *pool)
 {
-  serf_bucket_t *body_bkt = baton;
+  walker_baton_t *wb = baton;
+  serf_bucket_t *body_bkt = wb->body_bkt;
   serf_bucket_t *cdata_bkt;
   serf_bucket_alloc_t *alloc;
   const char *encoding;
+  const svn_string_t *const *old_val_p;
+  const svn_string_t *encoded_value;
   char *prop_name;
 
   /* Use the namespace prefix instead of adding the xmlns attribute to support
      property names containing ':' */
   if (strcmp(ns, SVN_DAV_PROP_NS_SVN) == 0)
-    prop_name = apr_pstrcat(pool, "S:", name, NULL);
+    prop_name = apr_pstrcat(pool, "S:", name, (char *)NULL);
   else if (strcmp(ns, SVN_DAV_PROP_NS_CUSTOM) == 0)
-    prop_name = apr_pstrcat(pool, "C:", name, NULL);
+    prop_name = apr_pstrcat(pool, "C:", name, (char *)NULL);
   name_len = strlen(prop_name);
 
+  SVN_ERR(derive_old_val(&old_val_p, wb, ns, name, pool));
+
+  /* Jump through hoops to work with D:remove and its val = (""-for-NULL)
+   * representation. */
+  if (wb->filter != filter_all_props)
+    {
+      if (wb->filter == filter_props_with_old_value && ! old_val_p)
+      	return SVN_NO_ERROR;
+      if (wb->filter == filter_props_without_old_value && old_val_p)
+      	return SVN_NO_ERROR;
+    }
+  if (wb->deleting)
+    val = NULL;
+
   alloc = body_bkt->allocator;
 
-  SVN_ERR(get_encoding_and_cdata(&encoding, &cdata_bkt, alloc, val, pool));
+  SVN_ERR(get_encoding_and_cdata(&encoding, &encoded_value, alloc, val, pool));
+  if (encoded_value)
+    {
+      cdata_bkt = SERF_BUCKET_SIMPLE_STRING_LEN(encoded_value->data,
+                                                encoded_value->len,
+                                                alloc);
+    }
+  else
+    {
+      cdata_bkt = NULL;
+    }
 
-  svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, prop_name,
-                                    "V:encoding", encoding,
-                                    NULL);
-  serf_bucket_aggregate_append(body_bkt, cdata_bkt);
+  if (cdata_bkt)
+    svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, prop_name,
+                                      "V:encoding", encoding,
+                                      NULL);
+  else
+    svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, prop_name,
+                                      "V:" SVN_DAV__OLD_VALUE__ABSENT, "1",
+                                      NULL);
+
+  if (old_val_p)
+    {
+      const char *encoding2;
+      const svn_string_t *encoded_value2;
+      serf_bucket_t *cdata_bkt2;
+
+      SVN_ERR(get_encoding_and_cdata(&encoding2, &encoded_value2,
+                                     alloc, *old_val_p, pool));
+
+      if (encoded_value2)
+        {
+          cdata_bkt2 = SERF_BUCKET_SIMPLE_STRING_LEN(encoded_value2->data,
+                                                     encoded_value2->len,
+                                                     alloc);
+        }
+      else
+        {
+          cdata_bkt2 = NULL;
+        }
+
+      if (cdata_bkt2)
+        svn_ra_serf__add_open_tag_buckets(body_bkt, alloc,
+                                          "V:" SVN_DAV__OLD_VALUE,
+                                          "V:encoding", encoding2,
+                                          NULL);
+      else
+        svn_ra_serf__add_open_tag_buckets(body_bkt, alloc,
+                                          "V:" SVN_DAV__OLD_VALUE,
+                                          "V:" SVN_DAV__OLD_VALUE__ABSENT, "1",
+                                          NULL);
+
+      if (cdata_bkt2)
+        serf_bucket_aggregate_append(body_bkt, cdata_bkt2);
+
+      svn_ra_serf__add_close_tag_buckets(body_bkt, alloc,
+                                         "V:" SVN_DAV__OLD_VALUE);
+    }
+  if (cdata_bkt)
+    serf_bucket_aggregate_append(body_bkt, cdata_bkt);
   svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, prop_name);
 
   return SVN_NO_ERROR;
@@ -735,7 +860,7 @@ setup_proppatch_headers(serf_bucket_t *h
         {
           const char *token_header;
 
-          token_header = apr_pstrcat(pool, "(<", token, ">)", NULL);
+          token_header = apr_pstrcat(pool, "(<", token, ">)", (char *)NULL);
 
           serf_bucket_headers_set(headers, "If", token_header);
         }
@@ -753,6 +878,7 @@ create_proppatch_body(serf_bucket_t **bk
 {
   proppatch_context_t *ctx = baton;
   serf_bucket_t *body_bkt;
+  walker_baton_t *wb;
 
   body_bkt = serf_bucket_aggregate_create(alloc);
 
@@ -764,14 +890,37 @@ create_proppatch_body(serf_bucket_t **bk
                                     "xmlns:S", SVN_DAV_PROP_NS_SVN,
                                     NULL);
 
+  wb = apr_pcalloc(pool, sizeof(*wb));
+  wb->body_bkt = body_bkt;
+  wb->previous_changed_props = ctx->previous_changed_props;
+  wb->previous_removed_props = ctx->previous_removed_props;
+  wb->path = ctx->path;
+
   if (apr_hash_count(ctx->changed_props) > 0)
     {
       svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "D:set", NULL);
       svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "D:prop", NULL);
 
+      wb->filter = filter_all_props;
+      wb->deleting = FALSE;
       SVN_ERR(svn_ra_serf__walk_all_props(ctx->changed_props, ctx->path,
                                           SVN_INVALID_REVNUM,
-                                          proppatch_walker, body_bkt, pool));
+                                          proppatch_walker, wb, pool));
+
+      svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:prop");
+      svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:set");
+    }
+
+  if (apr_hash_count(ctx->removed_props) > 0)
+    {
+      svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "D:set", NULL);
+      svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "D:prop", NULL);
+
+      wb->filter = filter_props_with_old_value;
+      wb->deleting = TRUE;
+      SVN_ERR(svn_ra_serf__walk_all_props(ctx->removed_props, ctx->path,
+                                          SVN_INVALID_REVNUM,
+                                          proppatch_walker, wb, pool));
 
       svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:prop");
       svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:set");
@@ -782,9 +931,11 @@ create_proppatch_body(serf_bucket_t **bk
       svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "D:remove", NULL);
       svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "D:prop", NULL);
 
+      wb->filter = filter_props_without_old_value;
+      wb->deleting = TRUE;
       SVN_ERR(svn_ra_serf__walk_all_props(ctx->removed_props, ctx->path,
                                           SVN_INVALID_REVNUM,
-                                          proppatch_walker, body_bkt, pool));
+                                          proppatch_walker, wb, pool));
 
       svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:prop");
       svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:remove");
@@ -912,7 +1063,7 @@ setup_put_headers(serf_bucket_t *headers
         {
           const char *token_header;
 
-          token_header = apr_pstrcat(pool, "(<", token, ">)", NULL);
+          token_header = apr_pstrcat(pool, "(<", token, ">)", (char *)NULL);
 
           serf_bucket_headers_set(headers, "If", token_header);
         }
@@ -1007,7 +1158,7 @@ setup_delete_headers(serf_bucket_t *head
           const char *token_header;
 
           token_header = apr_pstrcat(pool, "<", ctx->path, "> (<",
-                                     ctx->lock_token, ">)", NULL);
+                                     ctx->lock_token, ">)", (char *)NULL);
 
           serf_bucket_headers_set(headers, "If", token_header);
 
@@ -2208,6 +2359,7 @@ svn_error_t *
 svn_ra_serf__change_rev_prop(svn_ra_session_t *ra_session,
                              svn_revnum_t rev,
                              const char *name,
+                             const svn_string_t *const *old_value_p,
                              const svn_string_t *value,
                              apr_pool_t *pool)
 {
@@ -2219,6 +2371,17 @@ svn_ra_serf__change_rev_prop(svn_ra_sess
   apr_hash_t *props;
   svn_error_t *err;
 
+  if (old_value_p)
+    {
+      svn_boolean_t capable;
+      SVN_ERR(svn_ra_serf__has_capability(ra_session, &capable,
+                                          SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+                                          pool));
+
+      /* How did you get past the same check in svn_ra_change_rev_prop2()? */
+      SVN_ERR_ASSERT(capable);
+    }
+
   commit = apr_pcalloc(pool, sizeof(*commit));
 
   commit->pool = pool;
@@ -2238,9 +2401,9 @@ svn_ra_serf__change_rev_prop(svn_ra_sess
       props = apr_hash_make(pool);
 
       propfind_ctx = NULL;
-      svn_ra_serf__deliver_props(&propfind_ctx, props, commit->session,
-                                 commit->conn, vcc_url, rev, "0",
-                                 checked_in_props, FALSE, NULL, pool);
+      SVN_ERR(svn_ra_serf__deliver_props(&propfind_ctx, props, commit->session,
+                                         commit->conn, vcc_url, rev, "0",
+                                         checked_in_props, FALSE, NULL, pool));
 
       SVN_ERR(svn_ra_serf__wait_for_props(propfind_ctx, commit->session, pool));
 
@@ -2265,8 +2428,28 @@ svn_ra_serf__change_rev_prop(svn_ra_sess
   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);
+  if (old_value_p)
+    {
+      proppatch_ctx->previous_changed_props = apr_hash_make(proppatch_ctx->pool);
+      proppatch_ctx->previous_removed_props = apr_hash_make(proppatch_ctx->pool);
+    }
   proppatch_ctx->base_revision = SVN_INVALID_REVNUM;
 
+  if (old_value_p && *old_value_p)
+    {
+      svn_ra_serf__set_prop(proppatch_ctx->previous_changed_props,
+                            proppatch_ctx->path,
+                            ns, name, *old_value_p, proppatch_ctx->pool);
+    }
+  else if (old_value_p)
+    {
+      svn_string_t *dummy_value = svn_string_create("", proppatch_ctx->pool);
+
+      svn_ra_serf__set_prop(proppatch_ctx->previous_removed_props,
+                            proppatch_ctx->path,
+                            ns, name, dummy_value, proppatch_ctx->pool);
+    }
+
   if (value)
     {
       svn_ra_serf__set_prop(proppatch_ctx->changed_props, proppatch_ctx->path,

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/getlocks.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/getlocks.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/getlocks.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/getlocks.c Sat Dec 11 00:15:55 2010
@@ -336,7 +336,7 @@ svn_ra_serf__get_locks(svn_ra_session_t 
 
   lock_ctx = apr_pcalloc(pool, sizeof(*lock_ctx));
   lock_ctx->pool = pool;
-  lock_ctx->path = apr_pstrcat(pool, "/", rel_path, NULL);
+  lock_ctx->path = apr_pstrcat(pool, "/", rel_path, (char *)NULL);
   lock_ctx->requested_depth = depth;
   lock_ctx->hash = apr_hash_make(pool);
   lock_ctx->done = FALSE;

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/locks.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/locks.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/locks.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/locks.c Sat Dec 11 00:15:55 2010
@@ -732,7 +732,7 @@ svn_ra_serf__unlock(svn_ra_session_t *ra
         }
 
       unlock_ctx.force = force;
-      unlock_ctx.token = apr_pstrcat(subpool, "<", token, ">", NULL);
+      unlock_ctx.token = apr_pstrcat(subpool, "<", token, ">", (char *)NULL);
 
       req_url = svn_path_url_add_component2(session->repos_url.path, path,
                                             subpool);

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/mergeinfo.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/mergeinfo.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/mergeinfo.c Sat Dec 11 00:15:55 2010
@@ -45,7 +45,8 @@ typedef enum {
   MERGEINFO_REPORT,
   MERGEINFO_ITEM,
   MERGEINFO_PATH,
-  MERGEINFO_INFO
+  MERGEINFO_INFO,
+  MERGEINFO_VALIDATED
 } mergeinfo_state_e;
 
 /* Baton for accumulating mergeinfo.  RESULT_CATALOG stores the final
@@ -62,6 +63,8 @@ typedef struct {
   const apr_array_header_t *paths;
   svn_revnum_t revision;
   svn_mergeinfo_inheritance_t inherit;
+  svn_boolean_t validate_inherited_mergeinfo;
+  svn_boolean_t validated_inherited_mergeinfo;
   svn_boolean_t include_descendants;
 } mergeinfo_context_t;
 
@@ -80,6 +83,11 @@ start_element(svn_ra_serf__xml_parser_t 
       svn_ra_serf__xml_push_state(parser, MERGEINFO_REPORT);
     }
   else if (state == MERGEINFO_REPORT &&
+           strcmp(name.name, SVN_DAV__VALIDATE_INHERITED) == 0)
+    {
+      svn_ra_serf__xml_push_state(parser, MERGEINFO_VALIDATED);
+    }
+  else if (state == MERGEINFO_REPORT &&
            strcmp(name.name, SVN_DAV__MERGEINFO_ITEM) == 0)
     {
       svn_ra_serf__xml_push_state(parser, MERGEINFO_ITEM);
@@ -169,6 +177,11 @@ cdata_handler(svn_ra_serf__xml_parser_t 
         svn_stringbuf_appendbytes(mergeinfo_ctx->curr_info, data, len);
       break;
 
+    case MERGEINFO_VALIDATED:
+      if (strncmp(data, "yes", 3) == 0)
+        mergeinfo_ctx->validated_inherited_mergeinfo = TRUE;
+      break;
+
     default:
       break;
     }
@@ -184,7 +197,6 @@ create_mergeinfo_body(serf_bucket_t **bk
 {
   mergeinfo_context_t *mergeinfo_ctx = baton;
   serf_bucket_t *body_bkt;
-  int i;
 
   body_bkt = serf_bucket_aggregate_create(alloc);
 
@@ -207,8 +219,17 @@ create_mergeinfo_body(serf_bucket_t **bk
                                    "yes", alloc);
     }
 
+  if (mergeinfo_ctx->validate_inherited_mergeinfo)
+    {
+      svn_ra_serf__add_tag_buckets(body_bkt, "S:"
+                                   SVN_DAV__VALIDATE_INHERITED,
+                                   "yes", alloc);
+    }
+
   if (mergeinfo_ctx->paths)
     {
+      int i;
+
       for (i = 0; i < mergeinfo_ctx->paths->nelts; i++)
         {
           const char *this_path = APR_ARRAY_IDX(mergeinfo_ctx->paths,
@@ -234,6 +255,7 @@ svn_ra_serf__get_mergeinfo(svn_ra_sessio
                            const apr_array_header_t *paths,
                            svn_revnum_t revision,
                            svn_mergeinfo_inheritance_t inherit,
+                           svn_boolean_t *validate_inherited_mergeinfo,
                            svn_boolean_t include_descendants,
                            apr_pool_t *pool)
 {
@@ -263,6 +285,8 @@ svn_ra_serf__get_mergeinfo(svn_ra_sessio
   mergeinfo_ctx->paths = paths;
   mergeinfo_ctx->revision = revision;
   mergeinfo_ctx->inherit = inherit;
+  mergeinfo_ctx->validate_inherited_mergeinfo = *validate_inherited_mergeinfo;
+  mergeinfo_ctx->validated_inherited_mergeinfo = FALSE;
   mergeinfo_ctx->include_descendants = include_descendants;
 
   handler = apr_pcalloc(pool, sizeof(*handler));
@@ -302,6 +326,9 @@ svn_ra_serf__get_mergeinfo(svn_ra_sessio
 
   SVN_ERR(err);
 
+  *validate_inherited_mergeinfo =
+    mergeinfo_ctx->validated_inherited_mergeinfo;
+
   if (mergeinfo_ctx->done && apr_hash_count(mergeinfo_ctx->result_catalog))
     *catalog = mergeinfo_ctx->result_catalog;
 

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/options.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/options.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/options.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/options.c Sat Dec 11 00:15:55 2010
@@ -313,6 +313,13 @@ capabilities_headers_iterator_callback(v
                        SVN_RA_CAPABILITY_LOG_REVPROPS,
                        APR_HASH_KEY_STRING, capability_yes);
         }
+      if (svn_cstring_match_glob_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);
+        }
       if (svn_cstring_match_glob_list(SVN_DAV_NS_DAV_SVN_PARTIAL_REPLAY, vals))
         {
           apr_hash_set(orc->session->capabilities,
@@ -404,6 +411,8 @@ options_response_handler(serf_request_t 
                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);
 
   /* Then see which ones we can discover. */
   serf_bucket_headers_do(hdrs, capabilities_headers_iterator_callback, orc);
@@ -485,8 +494,9 @@ svn_ra_serf__exchange_capabilities(svn_r
   svn_error_t *err;
 
   /* This routine automatically fills in serf_sess->capabilities */
-  svn_ra_serf__create_options_req(&opt_ctx, serf_sess, serf_sess->conns[0],
-                                  serf_sess->repos_url.path, pool);
+  SVN_ERR(svn_ra_serf__create_options_req(&opt_ctx, serf_sess,
+                                          serf_sess->conns[0],
+                                          serf_sess->repos_url.path, pool));
 
   err = svn_ra_serf__context_run_wait(
             svn_ra_serf__get_options_done_ptr(opt_ctx), serf_sess, pool);
@@ -557,12 +567,15 @@ svn_ra_serf__has_capability(svn_ra_sessi
              support mergeinfo. */
           svn_mergeinfo_catalog_t ignored;
           svn_error_t *err;
+          svn_boolean_t validate_inherited_mergeinfo = FALSE;
           apr_array_header_t *paths = apr_array_make(pool, 1,
                                                      sizeof(char *));
           APR_ARRAY_PUSH(paths, const char *) = "";
 
           err = svn_ra_serf__get_mergeinfo(ra_session, &ignored, paths, 0,
-                                           FALSE, FALSE, pool);
+                                           FALSE,
+                                           &validate_inherited_mergeinfo,
+                                           FALSE, pool);
 
           if (err)
             {

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/property.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/property.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/property.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/property.c Sat Dec 11 00:15:55 2010
@@ -862,9 +862,9 @@ set_bare_props(svn_ra_serf__prop_set_t s
   if (strcmp(ns, SVN_DAV_PROP_NS_CUSTOM) == 0)
     prop_name = name;
   else if (strcmp(ns, SVN_DAV_PROP_NS_SVN) == 0)
-    prop_name = apr_pstrcat(pool, SVN_PROP_PREFIX, name, NULL);
+    prop_name = apr_pstrcat(pool, SVN_PROP_PREFIX, name, (char *)NULL);
   else if (strcmp(ns, SVN_PROP_PREFIX) == 0)
-    prop_name = apr_pstrcat(pool, SVN_PROP_PREFIX, name, NULL);
+    prop_name = apr_pstrcat(pool, SVN_PROP_PREFIX, name, (char *)NULL);
   else if (strcmp(ns, "") == 0)
     prop_name = name;
   else
@@ -888,9 +888,9 @@ svn_ra_serf__set_baton_props(svn_ra_serf
   if (strcmp(ns, SVN_DAV_PROP_NS_CUSTOM) == 0)
     prop_name = name;
   else if (strcmp(ns, SVN_DAV_PROP_NS_SVN) == 0)
-    prop_name = apr_pstrcat(pool, SVN_PROP_PREFIX, name, NULL);
+    prop_name = apr_pstrcat(pool, SVN_PROP_PREFIX, name, (char *)NULL);
   else if (strcmp(ns, SVN_PROP_PREFIX) == 0)
-    prop_name = apr_pstrcat(pool, SVN_PROP_PREFIX, name, NULL);
+    prop_name = apr_pstrcat(pool, SVN_PROP_PREFIX, name, (char *)NULL);
   else if (strcmp(ns, "") == 0)
     prop_name = name;
   else if (strcmp(name, SVN_DAV__VERSION_NAME) == 0)
@@ -915,7 +915,7 @@ svn_ra_serf__set_baton_props(svn_ra_serf
   else
     {
       /* An unknown namespace, must be a custom property. */
-      prop_name = apr_pstrcat(pool, ns, name, NULL);
+      prop_name = apr_pstrcat(pool, ns, name, (char *)NULL);
     }
 
   return setprop(baton, prop_name, val, pool);
@@ -990,8 +990,9 @@ svn_ra_serf__get_baseline_info(const cha
         {
           svn_ra_serf__options_context_t *opt_ctx;
 
-          svn_ra_serf__create_options_req(&opt_ctx, session, conn,
-                                          session->repos_url.path, pool);
+          SVN_ERR(svn_ra_serf__create_options_req(&opt_ctx, session, conn,
+                                                  session->repos_url.path,
+                                                  pool));
           SVN_ERR(svn_ra_serf__context_run_wait(
             svn_ra_serf__get_options_done_ptr(opt_ctx), session, pool));
 

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/ra_serf.h?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/ra_serf.h Sat Dec 11 00:15:55 2010
@@ -673,6 +673,9 @@ typedef struct svn_ra_serf__server_error
   /* Have we seen an error tag? */
   svn_boolean_t in_error;
 
+  /* Have we seen a HTTP "412 Precondition Failed" error? */
+  svn_boolean_t contains_precondition_error;
+
   /* Should we be collecting the XML cdata? */
   svn_boolean_t collect_cdata;
 
@@ -1322,6 +1325,7 @@ svn_error_t *
 svn_ra_serf__change_rev_prop(svn_ra_session_t *session,
                              svn_revnum_t rev,
                              const char *name,
+                             const svn_string_t *const *old_value_p,
                              const svn_string_t *value,
                              apr_pool_t *pool);
 
@@ -1375,13 +1379,15 @@ 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);
+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 *validate_inherited_mergeinfo,
+  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

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/serf.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/serf.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/serf.c Sat Dec 11 00:15:55 2010
@@ -433,7 +433,7 @@ svn_ra_serf__open(svn_ra_session_t *sess
 
   if (client_string)
     serf_sess->conns[0]->useragent = apr_pstrcat(pool, USER_AGENT, "/",
-                                                 client_string, NULL);
+                                                 client_string, (char *)NULL);
   else
     serf_sess->conns[0]->useragent = USER_AGENT;
 
@@ -600,9 +600,10 @@ fetch_path_props(svn_ra_serf__propfind_c
    */
   if (!SVN_IS_VALID_REVNUM(revision))
     {
-      svn_ra_serf__deliver_props(&prop_ctx, props, session, session->conns[0],
-                                 path, revision, "0", desired_props, TRUE,
-                                 NULL, session->pool);
+      SVN_ERR(svn_ra_serf__deliver_props(&prop_ctx, props, session,
+                                         session->conns[0], path, revision,
+                                         "0", desired_props, TRUE, NULL,
+                                         session->pool));
     }
   else
     {
@@ -619,10 +620,10 @@ fetch_path_props(svn_ra_serf__propfind_c
       prop_ctx = NULL;
       path = svn_path_url_add_component2(basecoll_url, relative_url, pool);
       revision = SVN_INVALID_REVNUM;
-      svn_ra_serf__deliver_props(&prop_ctx, props, session, session->conns[0],
-                                 path, revision, "0",
-                                 desired_props, TRUE,
-                                 NULL, session->pool);
+      SVN_ERR(svn_ra_serf__deliver_props(&prop_ctx, props, session,
+                                         session->conns[0], path, revision,
+                                         "0", desired_props, TRUE, NULL,
+                                         session->pool));
     }
 
   if (prop_ctx)

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/update.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/update.c Sat Dec 11 00:15:55 2010
@@ -1189,10 +1189,11 @@ fetch_file(report_context_t *ctx, report
   info->propfind = NULL;
   if (info->fetch_props)
     {
-      svn_ra_serf__deliver_props(&info->propfind, info->props,
-                                 ctx->sess, conn,
-                                 info->url, info->target_rev, "0", all_props,
-                                 FALSE, &ctx->done_propfinds, info->dir->pool);
+      SVN_ERR(svn_ra_serf__deliver_props(&info->propfind, info->props,
+                                         ctx->sess, conn, info->url,
+                                         info->target_rev, "0", all_props,
+                                         FALSE, &ctx->done_propfinds,
+                                         info->dir->pool));
 
       SVN_ERR_ASSERT(info->propfind);
 
@@ -1743,12 +1744,14 @@ end_report(svn_ra_serf__xml_parser_t *pa
           /* Unconditionally set fetch_props now. */
           info->dir->fetch_props = TRUE;
 
-          svn_ra_serf__deliver_props(&info->dir->propfind, info->dir->props,
-                                     ctx->sess,
-                                     ctx->sess->conns[ctx->sess->cur_conn],
-                                     info->dir->url, info->dir->target_rev,
-                                     "0", all_props, FALSE,
-                                     &ctx->done_propfinds, info->dir->pool);
+          SVN_ERR(svn_ra_serf__deliver_props(&info->dir->propfind,
+                                             info->dir->props, ctx->sess,
+                                             ctx->sess->conns[ctx->sess->cur_conn],
+                                             info->dir->url,
+                                             info->dir->target_rev, "0",
+                                             all_props, FALSE,
+                                             &ctx->done_propfinds,
+                                             info->dir->pool));
 
           SVN_ERR_ASSERT(info->dir->propfind);
 
@@ -2135,7 +2138,7 @@ link_path(void *report_baton,
   SVN_ERR(svn_ra_serf__get_relative_path(&link, uri.path, report->sess,
                                          NULL, pool));
 
-  link = apr_pstrcat(pool, "/", link, NULL);
+  link = apr_pstrcat(pool, "/", link, (char *)NULL);
 
   svn_xml_make_open_tag(&buf, pool, svn_xml_protect_pcdata, "S:entry",
                         "rev", apr_ltoa(pool, revision),

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/util.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_serf/util.c Sat Dec 11 00:15:55 2010
@@ -836,6 +836,7 @@ svn_ra_serf__handle_discard_body(serf_re
             {
               server_err->error = svn_error_create(APR_SUCCESS, NULL, NULL);
               server_err->has_xml_response = TRUE;
+              server_err->contains_precondition_error = FALSE;
               server_err->cdata = svn_stringbuf_create("", pool);
               server_err->collect_cdata = FALSE;
               server_err->parser.pool = server_err->error->pool;
@@ -945,6 +946,34 @@ svn_ra_serf__handle_status_only(serf_req
   return svn_error_return(err);
 }
 
+/* Given a string like "HTTP/1.1 500 (status)" in BUF, parse out the numeric
+   status code into *STATUS_CODE_OUT.  Ignores leading whitespace. */
+static svn_error_t *
+parse_dav_status(int *status_code_out, svn_stringbuf_t *buf,
+                 apr_pool_t *scratch_pool)
+{
+  svn_error_t *err;
+  const char *token;
+  char *tok_status;
+  svn_stringbuf_t *temp_buf = svn_stringbuf_dup(buf, scratch_pool);
+
+  svn_stringbuf_strip_whitespace(temp_buf);
+  token = apr_strtok(temp_buf->data, " \t\r\n", &tok_status);
+  if (token)
+    token = apr_strtok(NULL, " \t\r\n", &tok_status);
+  if (!token)
+    return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
+                             "Malformed DAV:status CDATA '%s'",
+                             buf->data);
+  err = svn_cstring_atoi(status_code_out, token);
+  if (err)
+    return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, err,
+                             "Malformed DAV:status CDATA '%s'",
+                             buf->data);
+
+  return SVN_NO_ERROR;
+}
+
 /*
  * Expat callback invoked on a start element tag for a 207 response.
  */
@@ -968,6 +997,14 @@ start_207(svn_ra_serf__xml_parser_t *par
       svn_stringbuf_setempty(ctx->cdata);
       ctx->collect_cdata = TRUE;
     }
+  else if (ctx->in_error &&
+           strcmp(name.namespace, "DAV:") == 0 &&
+           strcmp(name.name, "status") == 0)
+    {
+      /* Start collecting cdata. */
+      svn_stringbuf_setempty(ctx->cdata);
+      ctx->collect_cdata = TRUE;
+    }
 
   return SVN_NO_ERROR;
 }
@@ -993,7 +1030,22 @@ end_207(svn_ra_serf__xml_parser_t *parse
       ctx->collect_cdata = FALSE;
       ctx->error->message = apr_pstrmemdup(ctx->error->pool, ctx->cdata->data,
                                            ctx->cdata->len);
-      ctx->error->apr_err = SVN_ERR_RA_DAV_REQUEST_FAILED;
+      if (ctx->contains_precondition_error)
+        ctx->error->apr_err = SVN_ERR_FS_PROP_BASEVALUE_MISMATCH;
+      else
+        ctx->error->apr_err = SVN_ERR_RA_DAV_REQUEST_FAILED;
+    }
+  else if (ctx->in_error &&
+           strcmp(name.namespace, "DAV:") == 0 &&
+           strcmp(name.name, "status") == 0)
+    {
+      int status_code;
+
+      ctx->collect_cdata = FALSE;
+
+      SVN_ERR(parse_dav_status(&status_code, ctx->cdata, parser->pool));
+      if (status_code == 412)
+        ctx->contains_precondition_error = TRUE;
     }
 
   return SVN_NO_ERROR;
@@ -1044,6 +1096,7 @@ svn_ra_serf__handle_multistatus_only(ser
         {
           server_err->error = svn_error_create(APR_SUCCESS, NULL, NULL);
           server_err->has_xml_response = TRUE;
+          server_err->contains_precondition_error = FALSE;
           server_err->cdata = svn_stringbuf_create("", pool);
           server_err->collect_cdata = FALSE;
           server_err->parser.pool = server_err->error->pool;

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_svn/client.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_svn/client.c Sat Dec 11 00:15:55 2010
@@ -622,6 +622,7 @@ static svn_error_t *open_session(svn_ra_
   /* In protocol version 2, we send back our protocol version, our
    * capability list, and the URL, and subsequently there is an auth
    * request. */
+  /* Client-side capabilities list: */
   SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "n(wwwwww)cc(?c)",
                                  (apr_uint64_t) 2,
                                  SVN_RA_SVN_CAP_EDIT_PIPELINE,
@@ -813,16 +814,49 @@ static svn_error_t *ra_svn_get_dated_rev
   return SVN_NO_ERROR;
 }
 
+/* Forward declaration. */
+static svn_error_t *ra_svn_has_capability(svn_ra_session_t *session,
+                                          svn_boolean_t *has,
+                                          const char *capability,
+                                          apr_pool_t *pool);
+
 static svn_error_t *ra_svn_change_rev_prop(svn_ra_session_t *session, svn_revnum_t rev,
                                            const char *name,
+                                           const svn_string_t *const *old_value_p,
                                            const svn_string_t *value,
                                            apr_pool_t *pool)
 {
   svn_ra_svn__session_baton_t *sess_baton = session->priv;
   svn_ra_svn_conn_t *conn = sess_baton->conn;
+  svn_boolean_t dont_care;
+  const svn_string_t *old_value;
+  svn_boolean_t has_atomic_revprops;
+
+  SVN_ERR(ra_svn_has_capability(session, &has_atomic_revprops,
+                                SVN_RA_SVN_CAP_ATOMIC_REVPROPS,
+                                pool));
+
+  if (old_value_p)
+    {
+      /* How did you get past the same check in svn_ra_change_rev_prop2()? */
+      SVN_ERR_ASSERT(has_atomic_revprops);
+
+      dont_care = FALSE;
+      old_value = *old_value_p;
+    }
+  else
+    {
+      dont_care = TRUE;
+      old_value = NULL;
+    }
+
+  if (has_atomic_revprops)
+    SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "change-rev-prop2", "rc(?s)(b?s)",
+                                 rev, name, value, dont_care, old_value));
+  else
+    SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "change-rev-prop", "rc?s",
+                                 rev, name, value));
 
-  SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "change-rev-prop", "rc?s",
-                               rev, name, value));
   SVN_ERR(handle_auth_request(sess_baton, pool));
   SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, ""));
   return SVN_NO_ERROR;
@@ -1029,7 +1063,7 @@ static svn_error_t *ra_svn_get_file(svn_
       svn_checksum_t *checksum;
       const char *hex_digest;
 
-      svn_checksum_final(&checksum, checksum_ctx, pool);
+      SVN_ERR(svn_checksum_final(&checksum, checksum_ctx, pool));
       hex_digest = svn_checksum_to_cstring_display(checksum, pool);
       if (strcmp(hex_digest, expected_checksum) != 0)
         return svn_error_createf
@@ -1119,15 +1153,34 @@ static svn_error_t *ra_svn_get_dir(svn_r
   return SVN_NO_ERROR;
 }
 
+/* Converts a apr_uint64_t with values TRUE, FALSE or
+   SVN_RA_SVN_UNSPECIFIED_NUMBER as provided by svn_ra_svn_parse_tuple
+   to a svn_tristate_t */
+static svn_tristate_t
+optbool_to_tristate(apr_uint64_t v)
+{
+  switch (v)
+  {
+    case TRUE:
+      return svn_tristate_true;
+    case FALSE:
+      return svn_tristate_false;
+    default: /* Contains SVN_RA_SVN_UNSPECIFIED_NUMBER */
+      return svn_tristate_unknown;
+  }
+}
+
 /* If REVISION is SVN_INVALID_REVNUM, no value is sent to the
    server, which defaults to youngest. */
-static svn_error_t *ra_svn_get_mergeinfo(svn_ra_session_t *session,
-                                         svn_mergeinfo_catalog_t *catalog,
-                                         const apr_array_header_t *paths,
-                                         svn_revnum_t revision,
-                                         svn_mergeinfo_inheritance_t inherit,
-                                         svn_boolean_t include_descendants,
-                                         apr_pool_t *pool)
+static svn_error_t *ra_svn_get_mergeinfo(
+  svn_ra_session_t *session,
+  svn_mergeinfo_catalog_t *catalog,
+  const apr_array_header_t *paths,
+  svn_revnum_t revision,
+  svn_mergeinfo_inheritance_t inherit,
+  svn_boolean_t *validate_inherited_mergeinfo,
+  svn_boolean_t include_descendants,
+  apr_pool_t *pool)
 {
   svn_ra_svn__session_baton_t *sess_baton = session->priv;
   svn_ra_svn_conn_t *conn = sess_baton->conn;
@@ -1135,6 +1188,7 @@ static svn_error_t *ra_svn_get_mergeinfo
   apr_array_header_t *mergeinfo_tuple;
   svn_ra_svn_item_t *elt;
   const char *path;
+  apr_uint64_t validated_inherited_mergeinfo;
 
   SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w((!", "get-mergeinfo"));
   for (i = 0; i < paths->nelts; i++)
@@ -1142,12 +1196,17 @@ static svn_error_t *ra_svn_get_mergeinfo
       path = APR_ARRAY_IDX(paths, i, const char *);
       SVN_ERR(svn_ra_svn_write_cstring(conn, pool, path));
     }
-  SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!)(?r)wb)", revision,
+  SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!)(?r)wbb)", revision,
                                  svn_inheritance_to_word(inherit),
-                                 include_descendants));
+                                 include_descendants,
+                                 *validate_inherited_mergeinfo));
 
   SVN_ERR(handle_auth_request(sess_baton, pool));
-  SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "l", &mergeinfo_tuple));
+  SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "l?B", &mergeinfo_tuple,
+                                       &validated_inherited_mergeinfo));
+
+  *validate_inherited_mergeinfo =
+    (optbool_to_tristate(validated_inherited_mergeinfo) == svn_tristate_true);
 
   *catalog = NULL;
   if (mergeinfo_tuple->nelts > 0)
@@ -1279,22 +1338,6 @@ static svn_error_t *ra_svn_diff(svn_ra_s
   return SVN_NO_ERROR;
 }
 
-/* Converts a apr_uint64_t with values TRUE, FALSE or
-   SVN_RA_SVN_UNSPECIFIED_NUMBER as provided by svn_ra_svn_parse_tuple
-   to a svn_tristate_t */
-static svn_tristate_t
-optbool_to_tristate(apr_uint64_t v)
-{
-  switch (v)
-  {
-    case TRUE:
-      return svn_tristate_true;
-    case FALSE:
-      return svn_tristate_false;
-    default: /* Contains SVN_RA_SVN_UNSPECIFIED_NUMBER */
-      return svn_tristate_unknown;
-  }
-}
 
 static svn_error_t *ra_svn_log(svn_ra_session_t *session,
                                const apr_array_header_t *paths,
@@ -2257,7 +2300,7 @@ static svn_error_t *ra_svn_get_locks(svn
   /* Figure out the repository abspath from PATH. */
   abs_path = svn_path_url_add_component2(sess->url, path, pool);
   SVN_ERR(path_relative_to_root(session, &abs_path, abs_path, pool));
-  abs_path = apr_pstrcat(pool, "/", abs_path, NULL);
+  abs_path = apr_pstrcat(pool, "/", abs_path, (char *)NULL);
 
   SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "get-locks", "c(w)", path,
                                svn_depth_to_word(depth)));
@@ -2420,6 +2463,9 @@ static svn_error_t *ra_svn_has_capabilit
   else if (strcmp(capability, SVN_RA_CAPABILITY_COMMIT_REVPROPS) == 0)
     *has = svn_ra_svn_has_capability(sess->conn,
                                      SVN_RA_SVN_CAP_COMMIT_REVPROPS);
+  else if (strcmp(capability, SVN_RA_CAPABILITY_ATOMIC_REVPROPS) == 0)
+    *has = svn_ra_svn_has_capability(sess->conn,
+                                     SVN_RA_SVN_CAP_ATOMIC_REVPROPS);
   else  /* Don't know any other capabilities, so error. */
     {
       return svn_error_createf

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_svn/cyrus_auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_svn/cyrus_auth.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_svn/cyrus_auth.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_svn/cyrus_auth.c Sat Dec 11 00:15:55 2010
@@ -410,7 +410,7 @@ static svn_error_t *try_auth(svn_ra_svn_
                                               pmech - mechstring);
               const char *tail = pmech + strlen(mech);
 
-              mechstring = apr_pstrcat(pool, head, tail, NULL);
+              mechstring = apr_pstrcat(pool, head, tail, (char *)NULL);
               again = TRUE;
             }
         }
@@ -632,10 +632,11 @@ svn_error_t *svn_ra_svn__enable_sasl_enc
                                                 apr_pool_t *pool)
 {
   const sasl_ssf_t *ssfp;
-  int result;
 
   if (! conn->encrypted)
     {
+      int result;
+
       /* Get the strength of the security layer. */
       result = sasl_getprop(sasl_ctx, SASL_SSF, (void*) &ssfp);
       if (result != SASL_OK)
@@ -718,9 +719,11 @@ svn_error_t *svn_ra_svn__get_addresses(c
 
       /* Format the IP address and port number like this: a.b.c.d;port */
       *local_addrport = apr_pstrcat(pool, local_addr, ";",
-                                    apr_itoa(pool, (int)local_sa->port), NULL);
+                                    apr_itoa(pool, (int)local_sa->port),
+                                    (char *)NULL);
       *remote_addrport = apr_pstrcat(pool, remote_addr, ";",
-                                     apr_itoa(pool, (int)remote_sa->port), NULL);
+                                     apr_itoa(pool, (int)remote_sa->port),
+                                     (char *)NULL);
     }
   return SVN_NO_ERROR;
 }
@@ -761,7 +764,7 @@ svn_ra_svn__do_cyrus_auth(svn_ra_svn__se
           mechstring = apr_pstrcat(pool,
                                    mechstring,
                                    i == 0 ? "" : " ",
-                                   elt->u.word, NULL);
+                                   elt->u.word, (char *)NULL);
         }
     }
 

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_svn/marshal.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_svn/marshal.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_svn/marshal.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_ra_svn/marshal.c Sat Dec 11 00:15:55 2010
@@ -44,6 +44,12 @@
 
 #define svn_iswhitespace(c) ((c) == ' ' || (c) == '\n')
 
+/* If we receive data that *claims* to be followed by a very long string,
+ * we should not trust that claim right away. But everything up to 1 MB
+ * should be too small to be instrumental for a DOS attack. */
+
+#define SUSPICIOUSLY_HUGE_STRING_SIZE_THRESHOLD (0x100000)
+
 /* --- CONNECTION INITIALIZATION --- */
 
 svn_ra_svn_conn_t *svn_ra_svn_create_conn(apr_socket_t *sock,
@@ -296,8 +302,8 @@ static svn_error_t *readbuf_fill(svn_ra_
   return SVN_NO_ERROR;
 }
 
-static svn_error_t *readbuf_getchar(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
-                                    char *result)
+static APR_INLINE svn_error_t *
+readbuf_getchar(svn_ra_svn_conn_t *conn, apr_pool_t *pool, char *result)
 {
   if (conn->read_ptr == conn->read_end)
     SVN_ERR(readbuf_fill(conn, pool));
@@ -537,15 +543,14 @@ svn_error_t *svn_ra_svn_write_tuple(svn_
 
 /* --- READING DATA ITEMS --- */
 
-/* Read LEN bytes from CONN into already-allocated structure ITEM.
- * Afterwards, *ITEM is of type 'SVN_RA_SVN_STRING', and its string
- * data is allocated in POOL. */
-static svn_error_t *read_string(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
-                                svn_ra_svn_item_t *item, apr_uint64_t len)
+/* Read LEN bytes from CONN into a supposedly empty STRINGBUF.
+ * POOL will be used for temporary allocations. */
+static svn_error_t *
+read_long_string(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
+                 svn_stringbuf_t *stringbuf, apr_uint64_t len)
 {
   char readbuf[4096];
   apr_size_t readbuf_len;
-  svn_stringbuf_t *stringbuf = svn_stringbuf_create("", pool);
 
   /* We can't store strings longer than the maximum size of apr_size_t,
    * so check for wrapping */
@@ -565,6 +570,57 @@ static svn_error_t *read_string(svn_ra_s
       len -= readbuf_len;
     }
 
+  return SVN_NO_ERROR;
+}
+
+/* Read LEN bytes from CONN into already-allocated structure ITEM.
+ * Afterwards, *ITEM is of type 'SVN_RA_SVN_STRING', and its string
+ * data is allocated in POOL. */
+static svn_error_t *read_string(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
+                                svn_ra_svn_item_t *item, apr_uint64_t len)
+{
+  svn_stringbuf_t *stringbuf;
+
+  /* We should not use large strings in our protocol. However, we may
+   * receive a claim that a very long string is going to follow. In that
+   * case, we start small and wait for all that data to actually show up.
+   * This does not fully prevent DOS attacs but makes them harder (you
+   * have to actually send gigabytes of data).
+   */
+  if (len > SUSPICIOUSLY_HUGE_STRING_SIZE_THRESHOLD)
+    {
+      /* This string might take a large amount of memory. Don't allocate
+       * the whole buffer at once, so to prevent OOM issues by corrupted
+       * network data.
+       */
+      stringbuf = svn_stringbuf_create("", pool);
+      SVN_ERR(read_long_string(conn, pool, stringbuf, len));
+    }
+  else
+    {
+      /* This is a reasonably sized string. So, provide a buffer large
+       * enough to prevent re-allocation as long as the data transmission
+       * is not flawed.
+       */
+      stringbuf = svn_stringbuf_create_ensure(len, pool);
+
+      /* Read the string data directly into the string structure.
+       * Do it iteratively, if necessary.
+       */
+      while (len)
+        {
+          apr_size_t readbuf_len = (apr_size_t)len;
+          char *dest = stringbuf->data + stringbuf->len;
+          SVN_ERR(readbuf_read(conn, pool, dest, readbuf_len));
+
+          stringbuf->len += readbuf_len;
+          stringbuf->data[stringbuf->len] = '\0';
+          len -= readbuf_len;
+        }
+    }
+
+  /* Return the string properly wrapped into an RA_SVN item.
+   */
   item->kind = SVN_RA_SVN_STRING;
   item->u.string = apr_palloc(pool, sizeof(*item->u.string));
   item->u.string->data = stringbuf->data;
@@ -582,7 +638,7 @@ static svn_error_t *read_item(svn_ra_svn
                               int level)
 {
   char c = first_char;
-  apr_uint64_t val, prev_val=0;
+  apr_uint64_t val;
   svn_stringbuf_t *str;
   svn_ra_svn_item_t *listitem;
 
@@ -600,7 +656,7 @@ static svn_error_t *read_item(svn_ra_svn
       val = c - '0';
       while (1)
         {
-          prev_val = val;
+          apr_uint64_t prev_val = val;
           SVN_ERR(readbuf_getchar(conn, pool, &c));
           if (!svn_ctype_isdigit(c))
             break;
@@ -625,7 +681,8 @@ static svn_error_t *read_item(svn_ra_svn
   else if (svn_ctype_isalpha(c))
     {
       /* It's a word. */
-      str = svn_stringbuf_ncreate(&c, 1, pool);
+      str = svn_stringbuf_create_ensure(16, pool);
+      svn_stringbuf_appendbyte(str, c);
       while (1)
         {
           SVN_ERR(readbuf_getchar(conn, pool, &c));
@@ -640,7 +697,7 @@ static svn_error_t *read_item(svn_ra_svn
     {
       /* Read in the list items. */
       item->kind = SVN_RA_SVN_LIST;
-      item->u.list = apr_array_make(pool, 0, sizeof(svn_ra_svn_item_t));
+      item->u.list = apr_array_make(pool, 4, sizeof(svn_ra_svn_item_t));
       while (1)
         {
           SVN_ERR(readbuf_getchar_skip_whitespace(conn, pool, &c));