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 2012/07/11 12:26:26 UTC

svn commit: r1360103 [6/18] - in /subversion/branches/ev2-export: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ contrib/server-side/ notes/wc-ng/ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/or...

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c Wed Jul 11 10:26:19 2012
@@ -143,7 +143,7 @@ typedef struct report_dir_t
   apr_hash_t *removed_props;
 
   /* The propfind request for our current directory */
-  svn_ra_serf__propfind_context_t *propfind;
+  svn_ra_serf__handler_t *propfind_handler;
 
   /* Has the server told us to fetch the dir props? */
   svn_boolean_t fetch_props;
@@ -203,7 +203,7 @@ typedef struct report_info_t
   svn_revnum_t copyfrom_rev;
 
   /* The propfind request for our current file (if present) */
-  svn_ra_serf__propfind_context_t *propfind;
+  svn_ra_serf__handler_t *propfind_handler;
 
   /* Has the server told us to fetch the file props? */
   svn_boolean_t fetch_props;
@@ -346,7 +346,7 @@ struct report_context_t {
   /* number of pending PROPFIND requests */
   unsigned int active_propfinds;
 
-  /* completed PROPFIND requests (contains svn_ra_serf__propfind_context_t) */
+  /* completed PROPFIND requests (contains svn_ra_serf__handler_t) */
   svn_ra_serf__list_t *done_propfinds;
 
   /* list of files that only have prop changes (contains report_info_t) */
@@ -464,10 +464,6 @@ set_file_props(void *baton,
   const svn_delta_editor_t *editor = info->dir->report_context->update_editor;
   const char *prop_name;
 
-  if (strcmp(name, "md5-checksum") == 0
-      && strcmp(ns, SVN_DAV_PROP_NS_DAV) == 0)
-    info->final_checksum = apr_pstrdup(info->pool, val->data);
-
   prop_name = svn_ra_serf__svnname_from_wirename(ns, name, scratch_pool);
   if (prop_name != NULL)
     return svn_error_trace(editor->change_file_prop(info->file_baton,
@@ -730,7 +726,7 @@ headers_fetch(serf_bucket_t *headers,
       serf_bucket_headers_setn(headers, "Accept-Encoding",
                                "svndiff1;q=0.9,svndiff;q=0.8");
     }
-  else if (fetch_ctx->conn->using_compression)
+  else if (fetch_ctx->sess->using_compression)
     {
       serf_bucket_headers_setn(headers, "Accept-Encoding", "gzip");
     }
@@ -1079,19 +1075,15 @@ handle_stream(serf_request_t *request,
               apr_pool_t *pool)
 {
   report_fetch_t *fetch_ctx = handler_baton;
-  const char *location;
   svn_error_t *err;
   apr_status_t status;
 
   /* ### new field. make sure we didn't miss some initialization.  */
   SVN_ERR_ASSERT(fetch_ctx->handler != NULL);
 
-  /* Woo-hoo.  Nothing here to see.  */
-  location = svn_ra_serf__response_get_location(response, pool);
-
   err = svn_ra_serf__error_on_status(fetch_ctx->handler->sline.code,
                                      fetch_ctx->info->name,
-                                     location);
+                                     fetch_ctx->handler->location);
   if (err)
     {
       fetch_ctx->handler->done = TRUE;
@@ -1230,15 +1222,18 @@ fetch_file(report_context_t *ctx, report
     }
 
   /* If needed, create the PROPFIND to retrieve the file's properties. */
-  info->propfind = NULL;
+  info->propfind_handler = NULL;
   if (info->fetch_props)
     {
-      SVN_ERR(svn_ra_serf__deliver_props(&info->propfind, info->props,
+      SVN_ERR(svn_ra_serf__deliver_props(&info->propfind_handler, info->props,
                                          ctx->sess, conn, info->url,
                                          ctx->target_rev, "0", all_props,
                                          &ctx->done_propfinds,
                                          info->dir->pool));
-      SVN_ERR_ASSERT(info->propfind);
+      SVN_ERR_ASSERT(info->propfind_handler);
+
+      /* Create a serf request for the PROPFIND.  */
+      svn_ra_serf__request_create(info->propfind_handler);
 
       ctx->active_propfinds++;
     }
@@ -1251,18 +1246,32 @@ fetch_file(report_context_t *ctx, report
       svn_stream_t *contents = NULL;
 
       if (ctx->sess->wc_callbacks->get_wc_contents
-          && info->final_sha1_checksum)
+          && (info->final_sha1_checksum || info->final_checksum))
         {
           svn_error_t *err;
-          svn_checksum_t *sha1_checksum;
+          svn_checksum_t *checksum;
+         
+          /* Parse our checksum, preferring SHA1 to MD5. */
+          if (info->final_sha1_checksum)
+            {
+              err = svn_checksum_parse_hex(&checksum, svn_checksum_sha1,
+                                           info->final_sha1_checksum,
+                                           info->pool);
+            }
+          else if (info->final_checksum)
+            {
+              err = svn_checksum_parse_hex(&checksum, svn_checksum_md5,
+                                           info->final_checksum,
+                                           info->pool);
+            }
 
-          err = svn_checksum_parse_hex(&sha1_checksum, svn_checksum_sha1,
-                                       info->final_sha1_checksum, info->pool);
+          /* Okay so far?  Let's try to get a stream on some readily
+             available matching content. */
           if (!err)
             {
               err = ctx->sess->wc_callbacks->get_wc_contents(
                         ctx->sess->wc_callback_baton, &contents,
-                        sha1_checksum, info->pool);
+                        checksum, info->pool);
             }
 
           if (err)
@@ -1282,7 +1291,7 @@ fetch_file(report_context_t *ctx, report
       if (info->cached_contents)
         {
           /* If we'll be doing a PROPFIND for this file... */
-          if (info->propfind)
+          if (info->propfind_handler)
             { 
               /* ... then we'll just leave ourselves a little "todo"
                  about that fact (and we'll deal with the file content
@@ -1339,7 +1348,7 @@ fetch_file(report_context_t *ctx, report
           ctx->active_fetches++;
         }
     }
-  else if (info->propfind)
+  else if (info->propfind_handler)
     {
       svn_ra_serf__list_t *list_item;
 
@@ -1806,6 +1815,14 @@ start_report(svn_ra_serf__xml_parser_t *
           info->prop_encoding = svn_xml_get_attr_value("encoding", attrs);
           svn_stringbuf_setempty(info->prop_value);
         }
+      else if (strcmp(name.name, "txdelta") == 0)
+        {
+          /* Pre 1.2, mod_dav_svn was using <txdelta> tags (in
+             addition to <fetch-file>s and such) when *not* in
+             "send-all" mode.  As a client, we're smart enough to know
+             that's wrong, so we'll just ignore these tags. */
+          ;
+        }
       else
         {
           return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
@@ -1884,7 +1901,7 @@ end_report(svn_ra_serf__xml_parser_t *pa
           /* Unconditionally set fetch_props now. */
           info->dir->fetch_props = TRUE;
 
-          SVN_ERR(svn_ra_serf__deliver_props(&info->dir->propfind,
+          SVN_ERR(svn_ra_serf__deliver_props(&info->dir->propfind_handler,
                                              info->dir->props, ctx->sess,
                                              ctx->sess->conns[ctx->sess->cur_conn],
                                              info->dir->url,
@@ -1892,7 +1909,10 @@ end_report(svn_ra_serf__xml_parser_t *pa
                                              all_props,
                                              &ctx->done_propfinds,
                                              info->dir->pool));
-          SVN_ERR_ASSERT(info->dir->propfind);
+          SVN_ERR_ASSERT(info->dir->propfind_handler);
+
+          /* Create a serf request for the PROPFIND.  */
+          svn_ra_serf__request_create(info->dir->propfind_handler);
 
           ctx->active_propfinds++;
 
@@ -1902,7 +1922,7 @@ end_report(svn_ra_serf__xml_parser_t *pa
         }
       else
         {
-          info->dir->propfind = NULL;
+          info->dir->propfind_handler = NULL;
         }
 
       svn_ra_serf__xml_pop_state(parser);
@@ -2078,6 +2098,13 @@ end_report(svn_ra_serf__xml_parser_t *pa
 
       svn_ra_serf__set_ver_prop(props, info->base_name, info->base_rev,
                                 ns->namespace, ns->url, set_val_str, pool);
+
+      /* Advance handling:  if we spotted the md5-checksum property on
+         the wire, remember it's value. */
+      if (strcmp(ns->url, "md5-checksum") == 0
+          && strcmp(ns->namespace, SVN_DAV_PROP_NS_DAV) == 0)
+        info->final_checksum = apr_pstrdup(info->pool, set_val_str->data);
+
       svn_ra_serf__xml_pop_state(parser);
     }
   else if (state == IGNORE_PROP_NAME || state == NEED_PROP_NAME)
@@ -2239,8 +2266,6 @@ link_path(void *report_baton,
   return APR_SUCCESS;
 }
 
-/** Max. number of connctions we'll open to the server. */
-#define MAX_NR_OF_CONNS 4
 /** Minimum nr. of outstanding requests needed before a new connection is
  *  opened. */
 #define REQS_PER_CONN 8
@@ -2261,16 +2286,10 @@ open_connection_if_needed(svn_ra_serf__s
       apr_status_t status;
 
       sess->conns[cur] = apr_pcalloc(sess->pool, sizeof(*sess->conns[cur]));
-      sess->conns[cur]->http10 = TRUE;  /* until we confirm HTTP/1.1  */
-      sess->conns[cur]->http10 = FALSE; /* ### don't change behavior yet  */
       sess->conns[cur]->bkt_alloc = serf_bucket_allocator_create(sess->pool,
                                                                  NULL, NULL);
-      sess->conns[cur]->hostname  = sess->conns[0]->hostname;
-      sess->conns[cur]->using_ssl = sess->conns[0]->using_ssl;
-      sess->conns[cur]->using_compression = sess->conns[0]->using_compression;
       sess->conns[cur]->last_status_code = -1;
       sess->conns[cur]->session = sess;
-      sess->conns[cur]->useragent = sess->conns[0]->useragent;
       status = serf_connection_create2(&sess->conns[cur]->conn,
                                        sess->context,
                                        sess->session_url,
@@ -2313,7 +2332,7 @@ headers_report(serf_bucket_t *headers,
 {
   report_context_t *report = baton;
 
-  if (report->conn->using_compression)
+  if (report->sess->using_compression)
     {
       serf_bucket_headers_setn(headers, "Accept-Encoding", "gzip");
     }
@@ -2421,6 +2440,11 @@ finish_report(void *report_baton,
       err = sess->pending_error;
       sess->pending_error = SVN_NO_ERROR;
 
+      if (!err && handler->done && handler->server_error)
+        {
+          err = handler->server_error->error;
+        }
+
       if (APR_STATUS_IS_TIMEUP(status))
         {
           svn_error_clear(err);
@@ -2468,7 +2492,7 @@ finish_report(void *report_baton,
                 {
                   report_info_t *item = cur->data;
 
-                  if (item->propfind == done_list->data)
+                  if (item->propfind_handler == done_list->data)
                     {
                       break;
                     }
@@ -2536,9 +2560,9 @@ finish_report(void *report_baton,
            *   we've already completed the propfind
            * then, we know it's time for us to close this directory.
            */
-          while (cur_dir && !cur_dir->ref_count && cur_dir->tag_closed &&
-                 (!cur_dir->fetch_props ||
-                  svn_ra_serf__propfind_is_done(cur_dir->propfind)))
+          while (cur_dir && !cur_dir->ref_count && cur_dir->tag_closed
+                 && (!cur_dir->fetch_props
+                     || cur_dir->propfind_handler->done))
             {
               report_dir_t *parent = cur_dir->parent_dir;
 
@@ -2821,6 +2845,74 @@ svn_ra_serf__do_switch(svn_ra_session_t 
                               switch_editor, switch_baton, pool);
 }
 
+/* Helper svn_ra_serf__get_file(). Attempts to fetch file contents
+ * using SESSION->wc_callbacks->get_wc_contents() if sha1 property is
+ * present in PROPS.
+ * 
+ * Sets *FOUND_P to TRUE if file contents was successfuly fetched.
+ * 
+ * Performs all temporary allocations in POOL.
+ */
+static svn_error_t *
+try_get_wc_contents(svn_boolean_t *found_p,
+                    svn_ra_serf__session_t *session,
+                    apr_hash_t *props,
+                    svn_stream_t *dst_stream,
+                    apr_pool_t *pool)
+{
+  apr_hash_t *svn_props;
+  const char *sha1_checksum_prop;
+  svn_checksum_t *checksum;
+  svn_stream_t *wc_stream;
+  svn_error_t *err;
+
+  /* No contents found by default. */
+  *found_p = FALSE;
+
+  if (!session->wc_callbacks->get_wc_contents)
+    {
+      /* No callback, nothing to do. */
+      return SVN_NO_ERROR;
+    }
+
+
+  svn_props = apr_hash_get(props, SVN_DAV_PROP_NS_DAV, APR_HASH_KEY_STRING);
+  if (!svn_props)
+    {
+      /* No properties -- therefore no checksum property -- in response. */
+      return SVN_NO_ERROR;
+    }
+
+  sha1_checksum_prop = svn_prop_get_value(svn_props, "sha1-checksum");
+  if (sha1_checksum_prop == NULL)
+    {
+      /* No checksum property in response. */
+      return SVN_NO_ERROR;
+    }
+
+  SVN_ERR(svn_checksum_parse_hex(&checksum, svn_checksum_sha1,
+                                 sha1_checksum_prop, pool));
+
+  err = session->wc_callbacks->get_wc_contents(
+          session->wc_callback_baton, &wc_stream, checksum, pool);
+
+  if (err)
+    {
+      svn_error_clear(err);
+
+      /* Ignore errors for now. */
+      return SVN_NO_ERROR;
+    }
+  
+  if (wc_stream)
+    {
+      SVN_ERR(svn_stream_copy3(wc_stream, dst_stream, NULL, NULL, pool));
+      *found_p = TRUE;
+    }
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_ra_serf__get_file(svn_ra_session_t *ra_session,
                       const char *path,
@@ -2835,6 +2927,7 @@ svn_ra_serf__get_file(svn_ra_session_t *
   const char *fetch_url;
   apr_hash_t *fetch_props;
   svn_kind_t res_kind;
+  const svn_ra_serf__dav_props_t *which_props;
 
   /* What connection should we go on? */
   conn = session->conns[session->cur_conn];
@@ -2859,9 +2952,22 @@ svn_ra_serf__get_file(svn_ra_session_t *
   /* REVISION is always SVN_INVALID_REVNUM  */
   SVN_ERR_ASSERT(!SVN_IS_VALID_REVNUM(revision));
 
+  if (props)
+    {
+      which_props = all_props;
+    }
+  else if (stream && session->wc_callbacks->get_wc_contents)
+    {
+      which_props = type_and_checksum_props;
+    }
+  else
+    {
+      which_props = check_path_props;
+    }
+     
   SVN_ERR(svn_ra_serf__fetch_node_props(&fetch_props, conn, fetch_url,
                                         SVN_INVALID_REVNUM,
-                                        props ? all_props : check_path_props,
+                                        which_props,
                                         pool, pool));
 
   /* Verify that resource type is not collection. */
@@ -2883,39 +2989,46 @@ svn_ra_serf__get_file(svn_ra_session_t *
 
   if (stream)
     {
-      report_fetch_t *stream_ctx;
-      svn_ra_serf__handler_t *handler;
+      svn_boolean_t found;
+      SVN_ERR(try_get_wc_contents(&found, session, fetch_props, stream, pool));
+
+      /* No contents found in the WC, let's fetch from server. */
+      if (!found)
+        {
+          report_fetch_t *stream_ctx;
+          svn_ra_serf__handler_t *handler;
 
-      /* Create the fetch context. */
-      stream_ctx = apr_pcalloc(pool, sizeof(*stream_ctx));
-      stream_ctx->target_stream = stream;
-      stream_ctx->sess = session;
-      stream_ctx->conn = conn;
-      stream_ctx->info = apr_pcalloc(pool, sizeof(*stream_ctx->info));
-      stream_ctx->info->name = fetch_url;
+          /* Create the fetch context. */
+          stream_ctx = apr_pcalloc(pool, sizeof(*stream_ctx));
+          stream_ctx->target_stream = stream;
+          stream_ctx->sess = session;
+          stream_ctx->conn = conn;
+          stream_ctx->info = apr_pcalloc(pool, sizeof(*stream_ctx->info));
+          stream_ctx->info->name = fetch_url;
 
-      handler = apr_pcalloc(pool, sizeof(*handler));
+          handler = apr_pcalloc(pool, sizeof(*handler));
 
-      handler->handler_pool = pool;
-      handler->method = "GET";
-      handler->path = fetch_url;
-      handler->conn = conn;
-      handler->session = session;
+          handler->handler_pool = pool;
+          handler->method = "GET";
+          handler->path = fetch_url;
+          handler->conn = conn;
+          handler->session = session;
 
-      handler->header_delegate = headers_fetch;
-      handler->header_delegate_baton = stream_ctx;
+          handler->header_delegate = headers_fetch;
+          handler->header_delegate_baton = stream_ctx;
 
-      handler->response_handler = handle_stream;
-      handler->response_baton = stream_ctx;
+          handler->response_handler = handle_stream;
+          handler->response_baton = stream_ctx;
 
-      handler->response_error = cancel_fetch;
-      handler->response_error_baton = stream_ctx;
+          handler->response_error = cancel_fetch;
+          handler->response_error_baton = stream_ctx;
 
-      stream_ctx->handler = handler;
+          stream_ctx->handler = handler;
 
-      svn_ra_serf__request_create(handler);
+          svn_ra_serf__request_create(handler);
 
-      SVN_ERR(svn_ra_serf__context_run_wait(&stream_ctx->done, session, pool));
+          SVN_ERR(svn_ra_serf__context_run_wait(&stream_ctx->done, session, pool));
+        }
     }
 
   return SVN_NO_ERROR;

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c Wed Jul 11 10:26:19 2012
@@ -257,7 +257,7 @@ ssl_server_cert(void *baton, int failure
       int i;
       for (i = 0; i < san->nelts; i++) {
           char *s = APR_ARRAY_IDX(san, i, char*);
-          if (apr_fnmatch(s, conn->hostname,
+          if (apr_fnmatch(s, conn->session->session_url.hostname,
                           APR_FNM_PERIOD) == APR_SUCCESS) {
               found_matching_hostname = 1;
               cert_info.hostname = s;
@@ -269,7 +269,7 @@ ssl_server_cert(void *baton, int failure
   /* Match server certificate CN with the hostname of the server */
   if (!found_matching_hostname && cert_info.hostname)
     {
-      if (apr_fnmatch(cert_info.hostname, conn->hostname,
+      if (apr_fnmatch(cert_info.hostname, conn->session->session_url.hostname,
                       APR_FNM_PERIOD) == APR_FNM_NOMATCH)
         {
           svn_failures |= SVN_AUTH_SSL_CNMISMATCH;
@@ -364,7 +364,7 @@ conn_setup(apr_socket_t *sock,
   *read_bkt = serf_context_bucket_socket_create(conn->session->context,
                                                sock, conn->bkt_alloc);
 
-  if (conn->using_ssl)
+  if (conn->session->using_ssl)
     {
       /* input stream */
       *read_bkt = serf_bucket_ssl_decrypt_create(*read_bkt, conn->ssl_context,
@@ -374,7 +374,8 @@ conn_setup(apr_socket_t *sock,
           conn->ssl_context = serf_bucket_ssl_encrypt_context_get(*read_bkt);
 
 #if SERF_VERSION_AT_LEAST(1,0,0)
-          serf_ssl_set_hostname(conn->ssl_context, conn->hostname);
+          serf_ssl_set_hostname(conn->ssl_context,
+                                conn->session->session_url.hostname);
 #endif
 
           serf_ssl_client_cert_provider_set(conn->ssl_context,
@@ -479,7 +480,7 @@ connection_closed(svn_ra_serf__connectio
       SVN_ERR_MALFUNCTION();
     }
 
-  if (conn->using_ssl)
+  if (conn->session->using_ssl)
     conn->ssl_context = NULL;
 
   return SVN_NO_ERROR;
@@ -632,7 +633,7 @@ static svn_error_t *
 setup_serf_req(serf_request_t *request,
                serf_bucket_t **req_bkt,
                serf_bucket_t **hdrs_bkt,
-               svn_ra_serf__connection_t *conn,
+               svn_ra_serf__session_t *session,
                const char *method, const char *url,
                serf_bucket_t *body_bkt, const char *content_type,
                apr_pool_t *request_pool,
@@ -643,7 +644,7 @@ setup_serf_req(serf_request_t *request,
 #if SERF_VERSION_AT_LEAST(1, 1, 0)
   svn_spillbuf_t *buf;
 
-  if (conn->http10 && body_bkt != NULL)
+  if (session->http10 && body_bkt != NULL)
     {
       /* Ugh. Use HTTP/1.0 to talk to the server because we don't know if
          it speaks HTTP/1.1 (and thus, chunked requests), or because the
@@ -669,7 +670,7 @@ setup_serf_req(serf_request_t *request,
   /* Set the Content-Length value. This will also trigger an HTTP/1.0
      request (rather than the default chunked request).  */
 #if SERF_VERSION_AT_LEAST(1, 1, 0)
-  if (conn->http10)
+  if (session->http10)
     {
       if (body_bkt == NULL)
         serf_bucket_request_set_CL(*req_bkt, 0);
@@ -680,10 +681,10 @@ setup_serf_req(serf_request_t *request,
 
   *hdrs_bkt = serf_bucket_request_get_headers(*req_bkt);
 
-  /* We use serf_bucket_headers_setn() because the string below have a
+  /* We use serf_bucket_headers_setn() because the USERAGENT has a
      lifetime longer than this bucket. Thus, there is no need to copy
      the header values.  */
-  serf_bucket_headers_setn(*hdrs_bkt, "User-Agent", conn->useragent);
+  serf_bucket_headers_setn(*hdrs_bkt, "User-Agent", session->useragent);
 
   if (content_type)
     {
@@ -941,16 +942,29 @@ svn_ra_serf__response_discard_handler(se
   return drain_bucket(response);
 }
 
-const char *
-svn_ra_serf__response_get_location(serf_bucket_t *response,
-                                   apr_pool_t *pool)
+
+/* Return the value of the RESPONSE's Location header if any, or NULL
+   otherwise.  All allocations will be made in POOL.  */
+static const char *
+response_get_location(serf_bucket_t *response,
+                      apr_pool_t *pool)
 {
   serf_bucket_t *headers;
-  const char *val;
+  const char *location;
+  apr_status_t status;
+  apr_uri_t uri;
 
   headers = serf_bucket_response_get_headers(response);
-  val = serf_bucket_headers_get(headers, "Location");
-  return val ? svn_urlpath__canonicalize(val, pool) : NULL;
+  location = serf_bucket_headers_get(headers, "Location");
+  if (location == NULL)
+    return NULL;
+
+  /* Ignore the scheme/host/port. Or just return as-is if we can't parse.  */
+  status = apr_uri_parse(pool, location, &uri);
+  if (!status)
+    location = uri.path;
+
+  return svn_urlpath__canonicalize(location, pool);
 }
 
 
@@ -990,11 +1004,6 @@ svn_ra_serf__expect_empty_body(serf_requ
     }
   else
     {
-      /* ### hmm. this is a bit early. we have not seen EOF. if the
-         ### caller thinks we are "done", then it may never call into
-         ### serf_context_run() again to flush the response.  */
-      handler->done = TRUE;
-
       /* The body was not text/xml, so we don't know what to do with it.
          Toss anything that arrives.  */
       handler->discard_body = TRUE;
@@ -1175,11 +1184,6 @@ svn_ra_serf__handle_multistatus_only(ser
         }
       else
         {
-          /* ### hmm. this is a bit early. we have not seen EOF. if the
-             ### caller thinks we are "done", then it may never call into
-             ### serf_context_run() again to flush the response.  */
-          handler->done = TRUE;
-
           /* The body was not text/xml, so we don't know what to do with it.
              Toss anything that arrives.  */
           handler->discard_body = TRUE;
@@ -1419,6 +1423,7 @@ handle_server_error(serf_request_t *requ
   svn_ra_serf__server_error_t server_err = { 0 };
   serf_bucket_t *hdrs;
   const char *val;
+  apr_status_t err;
 
   hdrs = serf_bucket_response_get_headers(response);
   val = serf_bucket_headers_get(hdrs, "Content-Type");
@@ -1458,8 +1463,11 @@ handle_server_error(serf_request_t *requ
     }
 
   /* The only error that we will return is from the XML response body.
-     Otherwise, ignore the entire body and return success.  */
-  (void) drain_bucket(response);
+     Otherwise, ignore the entire body but allow SUCCESS/EOF/EAGAIN to
+     surface. */
+  err = drain_bucket(response);
+  if (err && !SERF_BUCKET_READ_ERROR(err))
+    return svn_error_wrap_apr(err, NULL);
 
   return SVN_NO_ERROR;
 }
@@ -1487,17 +1495,11 @@ svn_ra_serf__handle_xml_parser(serf_requ
   /* Woo-hoo.  Nothing here to see.  */
   if (sl.code == 404 && ctx->ignore_errors == FALSE)
     {
-      add_done_item(ctx);
-
       err = handle_server_error(request, response, pool);
 
-      /* ### the above call should have drained the entire response. this
-         ### call is historical, and probably not required. but during
-         ### the rework of this core handling... let's keep it for now.  */
-      status = drain_bucket(response);
-      if (status)
-        err = svn_error_compose_create(svn_error_wrap_apr(status, NULL),
-                                       err);
+      if (err && APR_STATUS_IS_EOF(err->apr_err))
+        add_done_item(ctx);
+
       return svn_error_trace(err);
     }
 
@@ -1773,6 +1775,10 @@ handle_response(serf_request_t *request,
 
       handler->sline = sl;
       handler->sline.reason = apr_pstrdup(handler->handler_pool, sl.reason);
+
+      /* HTTP/1.1? (or later)  */
+      if (sl.version != SERF_HTTP_10)
+        handler->session->http10 = FALSE;
     }
 
   /* Keep reading from the network until we've read all the headers.  */
@@ -1824,8 +1830,7 @@ handle_response(serf_request_t *request,
     }
 
   /* ... and set up the header fields in HANDLER.  */
-  handler->location = svn_ra_serf__response_get_location(
-                          response, handler->handler_pool);
+  handler->location = response_get_location(response, handler->handler_pool);
 
   /* On the last request, we failed authentication. We succeeded this time,
      so let's save away these credentials.  */
@@ -1845,28 +1850,43 @@ handle_response(serf_request_t *request,
       /* 405 Method Not allowed.
          409 Conflict: can indicate a hook error.
          5xx (Internal) Server error. */
-      /* ### this is completely wrong. it only catches the current network
-         ### packet. we need ongoing parsing. see SERVER_ERROR down below
-         ### in the process_body: area. we'll eventually move to that.  */
-      SVN_ERR(handle_server_error(request, response, scratch_pool));
-
-      if (!handler->session->pending_error)
-        {
-          apr_status_t apr_err = SVN_ERR_RA_DAV_REQUEST_FAILED;
-
-          /* 405 == Method Not Allowed (Occurs when trying to lock a working
-             copy path which no longer exists at HEAD in the repository. */
-          if (handler->sline.code == 405
-              && strcmp(handler->method, "LOCK") == 0)
-            apr_err = SVN_ERR_FS_OUT_OF_DATE;
+      serf_bucket_t *hdrs;
+      const char *val;
 
-          return svn_error_createf(apr_err, NULL,
-                                   _("%s request on '%s' failed: %d %s"),
+      hdrs = serf_bucket_response_get_headers(response);
+      val = serf_bucket_headers_get(hdrs, "Content-Type");
+      if (val && strncasecmp(val, "text/xml", sizeof("text/xml") - 1) == 0)
+        {
+          svn_ra_serf__server_error_t *server_err;
+
+          server_err = begin_error_parsing(start_error, end_error, cdata_error,
+                                           handler->handler_pool);
+          /* Get the parser to set our DONE flag.  */
+          server_err->parser.done = &handler->done;
+
+          handler->server_error = server_err;
+        }
+      else
+        {
+          handler->discard_body = TRUE;
+
+          if (!handler->session->pending_error)
+            {
+              apr_status_t apr_err = SVN_ERR_RA_DAV_REQUEST_FAILED;
+
+              /* 405 == Method Not Allowed (Occurs when trying to lock a working
+                copy path which no longer exists at HEAD in the repository. */
+              if (handler->sline.code == 405
+                  && strcmp(handler->method, "LOCK") == 0)
+                apr_err = SVN_ERR_FS_OUT_OF_DATE;
+
+              handler->session->pending_error =
+                  svn_error_createf(apr_err, NULL,
+                                    _("%s request on '%s' failed: %d %s"),
                                    handler->method, handler->path,
                                    handler->sline.code, handler->sline.reason);
+            }
         }
-
-      return SVN_NO_ERROR; /* Error is set in caller */
     }
 
   /* Stop processing the above, on every packet arrival.  */
@@ -1878,6 +1898,14 @@ handle_response(serf_request_t *request,
   if (handler->discard_body)
     {
       *serf_status = drain_bucket(response);
+
+      /* If the handler hasn't set done (which it shouldn't have) and
+         we now have the EOF, go ahead and set it so that we can stop
+         our context loops.
+       */
+      if (!handler->done && APR_STATUS_IS_EOF(*serf_status))
+          handler->done = TRUE;
+
       return SVN_NO_ERROR;
     }
 
@@ -1889,17 +1917,25 @@ handle_response(serf_request_t *request,
                                            &handler->server_error->parser,
                                            scratch_pool);
 
-      /* APR_EOF will be returned when parsing is complete.  If we see
-         any other error, return it immediately.
+      /* If we do not receive an error or it is a non-transient error, return
+         immediately.
 
-         In practice the only other error we expect to see is APR_EAGAIN,
-         which indicates the network has no more data right now. This
-         svn_error_t will get unwrapped, and that APR_EAGAIN will be
-         returned to serf. We'll get called later, when more network data
-         is available.  */
-      if (!err || !APR_STATUS_IS_EOF(err->apr_err))
+         APR_EOF will be returned when parsing is complete.
+
+         APR_EAGAIN & WAIT_CONN may be intermittently returned as we proceed through
+         parsing and the network has no more data right now.  If we receive that,
+         clear the error and return - allowing serf to wait for more data.
+         */
+      if (!err || SERF_BUCKET_READ_ERROR(err->apr_err))
         return svn_error_trace(err);
 
+      if (!APR_STATUS_IS_EOF(err->apr_err))
+        {
+          *serf_status = err->apr_err;
+          svn_error_clear(err);
+          return SVN_NO_ERROR;
+        }
+
       /* Clear the EOF. We don't need it.  */
       svn_error_clear(err);
 
@@ -1999,7 +2035,7 @@ setup_request(serf_request_t *request,
     }
 
   SVN_ERR(setup_serf_req(request, req_bkt, &headers_bkt,
-                         handler->conn, handler->method, handler->path,
+                         handler->session, handler->method, handler->path,
                          body_bkt, handler->body_type,
                          request_pool, scratch_pool));
 
@@ -2351,7 +2387,15 @@ expat_response_handler(serf_request_t *r
 {
   struct expat_ctx_t *ectx = baton;
 
-  SVN_ERR_ASSERT(ectx->parser != NULL);
+  if (!ectx->parser)
+    {
+      ectx->parser = XML_ParserCreate(NULL);
+      apr_pool_cleanup_register(ectx->cleanup_pool, &ectx->parser,
+                                xml_parser_cleanup, apr_pool_cleanup_null);
+      XML_SetUserData(ectx->parser, ectx);
+      XML_SetElementHandler(ectx->parser, expat_start, expat_end);
+      XML_SetCharacterDataHandler(ectx->parser, expat_cdata);
+    }
 
   /* ### should we bail on anything < 200 or >= 300 ??
      ### actually: < 200 should really be handled by the core.  */
@@ -2387,6 +2431,20 @@ expat_response_handler(serf_request_t *r
       /* ### should we have an IGNORE_ERRORS flag like the v1 parser?  */
 
       expat_status = XML_Parse(ectx->parser, data, (int)len, 0 /* isFinal */);
+
+      /* We need to check INNER_ERROR first. This is an error from the
+         callbacks that has been "dropped off" for us to retrieve. On
+         current Expat parsers, we stop the parser when an error occurs,
+         so we want to ignore EXPAT_STATUS (which reports the stoppage).
+
+         If an error is not present, THEN we go ahead and look for parsing
+         errors.  */
+      if (ectx->inner_error)
+        {
+          apr_pool_cleanup_run(ectx->cleanup_pool, &ectx->parser,
+                               xml_parser_cleanup);
+          return svn_error_trace(ectx->inner_error);
+        }
       if (expat_status == XML_STATUS_ERROR)
         return svn_error_createf(SVN_ERR_XML_MALFORMED,
                                  ectx->inner_error,
@@ -2396,31 +2454,24 @@ expat_response_handler(serf_request_t *r
                                  ectx->handler->sline.code,
                                  ectx->handler->sline.reason);
 
-      /* Was an error dropped off for us?  */
-      if (ectx->inner_error)
-        {
-          apr_pool_cleanup_run(ectx->cleanup_pool, &ectx->parser,
-                               xml_parser_cleanup);
-          return svn_error_trace(ectx->inner_error);
-        }
-
       /* The parsing went fine. What has the bucket told us?  */
 
-      if (APR_STATUS_IS_EAGAIN(status))
-        return svn_error_wrap_apr(status, NULL);
-
       if (APR_STATUS_IS_EOF(status))
         {
           /* Tell expat we've reached the end of the content. Ignore the
              return status. We just don't care.  */
           (void) XML_Parse(ectx->parser, NULL, 0, 1 /* isFinal */);
 
+          svn_ra_serf__xml_context_destroy(ectx->xmlctx);
           apr_pool_cleanup_run(ectx->cleanup_pool, &ectx->parser,
                                xml_parser_cleanup);
 
           /* ### should check XMLCTX to see if it has returned to the
              ### INITIAL state. we may have ended early...  */
+        }
 
+      if (status && !SERF_BUCKET_READ_ERROR(status))
+        {
           return svn_error_wrap_apr(status, NULL);
         }
     }
@@ -2438,12 +2489,8 @@ svn_ra_serf__create_expat_handler(svn_ra
 
   ectx = apr_pcalloc(result_pool, sizeof(*ectx));
   ectx->xmlctx = xmlctx;
-  ectx->parser = XML_ParserCreate(NULL);
-  apr_pool_cleanup_register(result_pool, &ectx->parser,
-                            xml_parser_cleanup, apr_pool_cleanup_null);
-  XML_SetUserData(ectx->parser, ectx);
-  XML_SetElementHandler(ectx->parser, expat_start, expat_end);
-  XML_SetCharacterDataHandler(ectx->parser, expat_cdata);
+  ectx->parser = NULL;
+  ectx->cleanup_pool = result_pool;
 
 
   handler = apr_pcalloc(result_pool, sizeof(*handler));

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/xml.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/xml.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/xml.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/xml.c Wed Jul 11 10:26:19 2012
@@ -443,6 +443,12 @@ lazy_create_pool(void *baton)
   return xes->state_pool;
 }
 
+void
+svn_ra_serf__xml_context_destroy(
+  svn_ra_serf__xml_context_t *xmlctx)
+{
+  svn_pool_destroy(xmlctx->scratch_pool);
+}
 
 svn_ra_serf__xml_context_t *
 svn_ra_serf__xml_context_create(
@@ -483,12 +489,35 @@ svn_ra_serf__xml_gather_since(svn_ra_ser
                               int stop_state)
 {
   apr_hash_t *data;
+  apr_pool_t *pool;
 
   ensure_pool(xes);
+  pool = xes->state_pool;
 
-  data = apr_hash_make(xes->state_pool);
+  data = apr_hash_make(pool);
+
+  for (; xes != NULL; xes = xes->prev)
+    {
+      if (xes->attrs != NULL)
+        {
+          apr_hash_index_t *hi;
 
-  /* ### gather data  */
+          for (hi = apr_hash_first(pool, xes->attrs); hi;
+               hi = apr_hash_next(hi))
+            {
+              const void *key;
+              apr_ssize_t klen;
+              void *val;
+
+              /* Parent name/value lifetimes are at least as long as POOL.  */
+              apr_hash_this(hi, &key, &klen, &val);
+              apr_hash_set(data, key, klen, val);
+            }
+        }
+
+      if (xes->state == stop_state)
+        break;
+    }
 
   return data;
 }
@@ -632,7 +661,8 @@ svn_ra_serf__xml_cb_start(svn_ra_serf__x
                 }
 
               if (value)
-                apr_hash_set(new_xes->attrs, name, APR_HASH_KEY_STRING, value);
+                apr_hash_set(new_xes->attrs, name, APR_HASH_KEY_STRING,
+                             apr_pstrdup(new_pool, value));
             }
         }
     }
@@ -751,11 +781,29 @@ svn_ra_serf__xml_cb_cdata(svn_ra_serf__x
                           const char *data,
                           apr_size_t len)
 {
-  /* If we're collecting cdata, but NOT waiting for a closing tag
-     (ie. not within an unknown tag), then copy the cdata.  */
-  if (xmlctx->current->cdata != NULL
-      && xmlctx->waiting.namespace == NULL)
-    svn_stringbuf_appendbytes(xmlctx->current->cdata, data, len);
+  /* If we are waiting for a closing tag, then we are uninterested in
+     the cdata. Just return.  */
+  if (xmlctx->waiting.namespace != NULL)
+    return SVN_NO_ERROR;
+
+  /* If the current state is collecting cdata, then copy the cdata.  */
+  if (xmlctx->current->cdata != NULL)
+    {
+      svn_stringbuf_appendbytes(xmlctx->current->cdata, data, len);
+    }
+  /* ... else if a CDATA_CB has been supplied, then invoke it for
+     all states.  */
+  else if (xmlctx->cdata_cb != NULL)
+    {
+      START_CALLBACK(xmlctx);
+      SVN_ERR(xmlctx->cdata_cb(xmlctx->current,
+                               xmlctx->baton,
+                               xmlctx->current->state,
+                               data, len,
+                               xmlctx->scratch_pool));
+      END_CALLBACK(xmlctx);
+      svn_pool_clear(xmlctx->scratch_pool);
+    }
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_svn/marshal.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_svn/marshal.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_svn/marshal.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_svn/marshal.c Wed Jul 11 10:26:19 2012
@@ -462,7 +462,7 @@ svn_error_t *svn_ra_svn_write_string(svn
 {
   if (str->len < 10)
     {
-      SVN_ERR(writebuf_writechar(conn, pool, (char)str->len + '0'));
+      SVN_ERR(writebuf_writechar(conn, pool, (char)(str->len + '0')));
       SVN_ERR(writebuf_writechar(conn, pool, ':'));
     }
   else
@@ -480,7 +480,7 @@ svn_error_t *svn_ra_svn_write_cstring(sv
 
   if (len < 10)
     {
-      SVN_ERR(writebuf_writechar(conn, pool, (char)len + '0'));
+      SVN_ERR(writebuf_writechar(conn, pool, (char)(len + '0')));
       SVN_ERR(writebuf_writechar(conn, pool, ':'));
     }
   else

Modified: subversion/branches/ev2-export/subversion/libsvn_repos/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/deprecated.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/deprecated.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/deprecated.c Wed Jul 11 10:26:19 2012
@@ -775,6 +775,27 @@ fns_from_fns2(const svn_repos_parse_fns2
   return fns;
 }
 
+static svn_repos_parser_fns2_t *
+fns2_from_fns3(const svn_repos_parse_fns3_t *fns3,
+              apr_pool_t *pool)
+{
+  svn_repos_parser_fns2_t *fns2;
+
+  fns2 = apr_palloc(pool, sizeof(*fns2));
+  fns2->new_revision_record = fns3->new_revision_record;
+  fns2->uuid_record = fns3->uuid_record;
+  fns2->new_node_record = fns3->new_node_record;
+  fns2->set_revision_property = fns3->set_revision_property;
+  fns2->set_node_property = fns3->set_node_property;
+  fns2->remove_node_props = fns3->remove_node_props;
+  fns2->set_fulltext = fns3->set_fulltext;
+  fns2->close_node = fns3->close_node;
+  fns2->close_revision = fns3->close_revision;
+  fns2->delete_node_property = fns3->delete_node_property;
+  fns2->apply_textdelta = fns3->apply_textdelta;
+  return fns2;
+}
+
 static svn_repos_parse_fns2_t *
 fns2_from_fns(const svn_repos_parser_fns_t *fns,
               apr_pool_t *pool)
@@ -796,6 +817,42 @@ fns2_from_fns(const svn_repos_parser_fns
   return fns2;
 }
 
+static svn_repos_parse_fns3_t *
+fns3_from_fns2(const svn_repos_parser_fns2_t *fns2,
+               apr_pool_t *pool)
+{
+  svn_repos_parse_fns3_t *fns3;
+
+  fns3 = apr_palloc(pool, sizeof(*fns3));
+  fns3->magic_header_record = NULL;
+  fns3->uuid_record = fns2->uuid_record;
+  fns3->new_revision_record = fns2->new_revision_record;
+  fns3->new_node_record = fns2->new_node_record;
+  fns3->set_revision_property = fns2->set_revision_property;
+  fns3->set_node_property = fns2->set_node_property;
+  fns3->remove_node_props = fns2->remove_node_props;
+  fns3->set_fulltext = fns2->set_fulltext;
+  fns3->close_node = fns2->close_node;
+  fns3->close_revision = fns2->close_revision;
+  fns3->delete_node_property = fns2->delete_node_property;
+  fns3->apply_textdelta = fns2->apply_textdelta;
+  return fns3;
+}
+
+svn_error_t *
+svn_repos_parse_dumpstream2(svn_stream_t *stream,
+                            const svn_repos_parser_fns2_t *parse_fns,
+                            void *parse_baton,
+                            svn_cancel_func_t cancel_func,
+                            void *cancel_baton,
+                            apr_pool_t *pool)
+{
+  svn_repos_parse_fns3_t *fns3 = fns3_from_fns2(parse_fns, pool);
+
+  return svn_repos_parse_dumpstream3(stream, fns3, parse_baton, FALSE,
+                                     cancel_func, cancel_baton, pool);
+}
+
 svn_error_t *
 svn_repos_parse_dumpstream(svn_stream_t *stream,
                            const svn_repos_parser_fns_t *parse_fns,
@@ -837,11 +894,17 @@ svn_repos_get_fs_build_parser3(const svn
                                void *notify_baton,
                                apr_pool_t *pool)
 {
-  return svn_repos_get_fs_build_parser4(callbacks, parse_baton, repos,
-                                        SVN_INVALID_REVNUM, SVN_INVALID_REVNUM,
-                                        use_history, validate_props,
-                                        uuid_action, parent_dir,
-                                        notify_func, notify_baton, pool);
+  const svn_repos_parse_fns3_t *fns3;
+
+  SVN_ERR(svn_repos_get_fs_build_parser4(&fns3, parse_baton, repos,
+                                         SVN_INVALID_REVNUM,
+                                         SVN_INVALID_REVNUM,
+                                         use_history, validate_props,
+                                         uuid_action, parent_dir,
+                                         notify_func, notify_baton, pool));
+
+  *callbacks = fns2_from_fns3(fns3, pool);
+  return SVN_NO_ERROR;
 }
 
 svn_error_t *

Modified: subversion/branches/ev2-export/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/dump.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/dump.c Wed Jul 11 10:26:19 2012
@@ -736,7 +736,7 @@ close_directory(void *dir_baton,
   struct dir_baton *db = dir_baton;
   struct edit_baton *eb = db->edit_baton;
   apr_pool_t *subpool = svn_pool_create(pool);
-  unsigned int i;
+  int i;
   apr_array_header_t *sorted_entries;
 
   /* Sort entries lexically instead of as paths. Even though the entries

Modified: subversion/branches/ev2-export/subversion/libsvn_repos/load-fs-vtable.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/load-fs-vtable.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/load-fs-vtable.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/load-fs-vtable.c Wed Jul 11 10:26:19 2012
@@ -589,6 +589,13 @@ maybe_add_with_history(struct node_baton
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+magic_header_record(int version,
+                    void *parse_baton,
+                    apr_pool_t *pool)
+{
+  return SVN_NO_ERROR;
+}
 
 static svn_error_t *
 uuid_record(const char *uuid,
@@ -1016,7 +1023,7 @@ close_revision(void *baton)
 
 
 svn_error_t *
-svn_repos_get_fs_build_parser4(const svn_repos_parse_fns2_t **callbacks,
+svn_repos_get_fs_build_parser4(const svn_repos_parse_fns3_t **callbacks,
                                void **parse_baton,
                                svn_repos_t *repos,
                                svn_revnum_t start_rev,
@@ -1029,7 +1036,7 @@ svn_repos_get_fs_build_parser4(const svn
                                void *notify_baton,
                                apr_pool_t *pool)
 {
-  svn_repos_parse_fns2_t *parser = apr_pcalloc(pool, sizeof(*parser));
+  svn_repos_parse_fns3_t *parser = apr_pcalloc(pool, sizeof(*parser));
   struct parse_baton *pb = apr_pcalloc(pool, sizeof(*pb));
 
   if (parent_dir)
@@ -1042,9 +1049,10 @@ svn_repos_get_fs_build_parser4(const svn
   if (SVN_IS_VALID_REVNUM(start_rev))
     SVN_ERR_ASSERT(start_rev <= end_rev);
 
+  parser->magic_header_record = magic_header_record;
+  parser->uuid_record = uuid_record;
   parser->new_revision_record = new_revision_record;
   parser->new_node_record = new_node_record;
-  parser->uuid_record = uuid_record;
   parser->set_revision_property = set_revision_property;
   parser->set_node_property = set_node_property;
   parser->remove_node_props = remove_node_props;
@@ -1093,7 +1101,7 @@ svn_repos_load_fs4(svn_repos_t *repos,
                    void *cancel_baton,
                    apr_pool_t *pool)
 {
-  const svn_repos_parse_fns2_t *parser;
+  const svn_repos_parse_fns3_t *parser;
   void *parse_baton;
   struct parse_baton *pb;
 
@@ -1116,6 +1124,6 @@ svn_repos_load_fs4(svn_repos_t *repos,
   pb->use_pre_commit_hook = use_pre_commit_hook;
   pb->use_post_commit_hook = use_post_commit_hook;
 
-  return svn_repos_parse_dumpstream2(dumpstream, parser, parse_baton,
+  return svn_repos_parse_dumpstream3(dumpstream, parser, parse_baton, FALSE,
                                      cancel_func, cancel_baton, pool);
 }

Modified: subversion/branches/ev2-export/subversion/libsvn_repos/load.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/load.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/load.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/load.c Wed Jul 11 10:26:19 2012
@@ -181,7 +181,7 @@ read_key_or_val(char **pbuf,
 static svn_error_t *
 parse_property_block(svn_stream_t *stream,
                      svn_filesize_t content_length,
-                     const svn_repos_parse_fns2_t *parse_fns,
+                     const svn_repos_parse_fns3_t *parse_fns,
                      void *record_baton,
                      void *parse_baton,
                      svn_boolean_t is_node,
@@ -299,7 +299,7 @@ static svn_error_t *
 parse_text_block(svn_stream_t *stream,
                  svn_filesize_t content_length,
                  svn_boolean_t is_delta,
-                 const svn_repos_parse_fns2_t *parse_fns,
+                 const svn_repos_parse_fns3_t *parse_fns,
                  void *record_baton,
                  char *buffer,
                  apr_size_t buflen,
@@ -373,7 +373,8 @@ parse_text_block(svn_stream_t *stream,
 /* Parse VERSIONSTRING and verify that we support the dumpfile format
    version number, setting *VERSION appropriately. */
 static svn_error_t *
-parse_format_version(const char *versionstring, int *version)
+parse_format_version(int *version,
+                     const char *versionstring)
 {
   static const int magic_len = sizeof(SVN_REPOS_DUMPFILE_MAGIC_HEADER) - 1;
   const char *p = strchr(versionstring, ':');
@@ -406,9 +407,10 @@ parse_format_version(const char *version
 /** The public routines **/
 
 svn_error_t *
-svn_repos_parse_dumpstream2(svn_stream_t *stream,
-                            const svn_repos_parse_fns2_t *parse_fns,
+svn_repos_parse_dumpstream3(svn_stream_t *stream,
+                            const svn_repos_parse_fns3_t *parse_fns,
                             void *parse_baton,
+                            svn_boolean_t deltas_are_text,
                             svn_cancel_func_t cancel_func,
                             void *cancel_baton,
                             apr_pool_t *pool)
@@ -428,16 +430,11 @@ svn_repos_parse_dumpstream2(svn_stream_t
     return stream_ran_dry();
 
   /* The first two lines of the stream are the dumpfile-format version
-     number, and a blank line. */
-  SVN_ERR(parse_format_version(linebuf->data, &version));
-
-  /* If we were called from svn_repos_parse_dumpstream(), the
-     callbacks to handle delta contents will be NULL, so we have to
-     reject dumpfiles with the current version. */
-  if (version == SVN_REPOS_DUMPFILE_FORMAT_VERSION
-      && (!parse_fns->delete_node_property || !parse_fns->apply_textdelta))
-    return svn_error_createf(SVN_ERR_STREAM_MALFORMED_DATA, NULL,
-                             _("Unsupported dumpfile version: %d"), version);
+     number, and a blank line.  To preserve backward compatibility,
+     don't assume the existence of newer parser-vtable functions. */
+  SVN_ERR(parse_format_version(&version, linebuf->data));
+  if (parse_fns->magic_header_record != NULL)
+    SVN_ERR(parse_fns->magic_header_record(version, parse_baton, pool));
 
   /* A dumpfile "record" is defined to be a header-block of
      rfc822-style headers, possibly followed by a content-block.
@@ -528,6 +525,7 @@ svn_repos_parse_dumpstream2(svn_stream_t
           SVN_ERR(parse_fns->uuid_record(value, parse_baton, pool));
         }
       /* Or perhaps a dumpfile format? */
+      /* ### TODO: use parse_format_version */
       else if ((value = apr_hash_get(headers,
                                      SVN_REPOS_DUMPFILE_MAGIC_HEADER,
                                      APR_HASH_KEY_STRING)))
@@ -591,7 +589,9 @@ svn_repos_parse_dumpstream2(svn_stream_t
           const char *delta = apr_hash_get(headers,
                                            SVN_REPOS_DUMPFILE_TEXT_DELTA,
                                            APR_HASH_KEY_STRING);
-          svn_boolean_t is_delta = (delta && strcmp(delta, "true") == 0);
+          svn_boolean_t is_delta = FALSE;
+          if (! deltas_are_text)
+            is_delta = (delta && strcmp(delta, "true") == 0);
 
           SVN_ERR(parse_text_block(stream,
                                    svn__atoui64(text_cl),

Modified: subversion/branches/ev2-export/subversion/libsvn_repos/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/replay.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/replay.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/replay.c Wed Jul 11 10:26:19 2012
@@ -27,9 +27,11 @@
 
 #include "svn_types.h"
 #include "svn_delta.h"
+#include "svn_hash.h"
 #include "svn_fs.h"
 #include "svn_checksum.h"
 #include "svn_repos.h"
+#include "svn_sorts.h"
 #include "svn_props.h"
 #include "svn_pools.h"
 #include "svn_path.h"
@@ -101,6 +103,7 @@
    (though not necessarily in the same order in which they
    occurred). */
 
+/* #define USE_EV2_IMPL */
 
 
 /*** Helper functions. ***/
@@ -147,6 +150,7 @@ struct path_driver_cb_baton
   apr_pool_t *pool;
 };
 
+#ifndef USE_EV2_IMPL
 /* Recursively traverse EDIT_PATH (as it exists under SOURCE_ROOT) emitting
    the appropriate editor calls to add it and its children without any
    history.  This is meant to be used when either a subset of the tree
@@ -338,6 +342,7 @@ add_subdir(svn_fs_root_t *source_root,
 
   return SVN_NO_ERROR;
 }
+#endif
 
 /* Given PATH deleted under ROOT, return in READABLE whether the path was
    readable prior to the deletion.  Consult COPIES (a stack of 'struct
@@ -454,6 +459,7 @@ fill_copyfrom(svn_fs_root_t **copyfrom_r
   return SVN_NO_ERROR;
 }
 
+#ifndef USE_EV2_IMPL
 static svn_error_t *
 path_driver_cb_func(void **dir_baton,
                     void *parent_baton,
@@ -778,6 +784,47 @@ path_driver_cb_func(void **dir_baton,
   return SVN_NO_ERROR;
 }
 
+#else
+
+static svn_error_t *
+fetch_kind_func(svn_kind_t *kind,
+                void *baton,
+                const char *path,
+                svn_revnum_t base_revision,
+                apr_pool_t *scratch_pool)
+{
+  svn_fs_root_t *root = baton;
+  svn_node_kind_t node_kind;
+
+  SVN_ERR(svn_fs_check_path(&node_kind, root, path, scratch_pool));
+
+  *kind = svn__kind_from_node_kind(node_kind, FALSE);
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+fetch_props_func(apr_hash_t **props,
+                 void *baton,
+                 const char *path,
+                 svn_revnum_t base_revision,
+                 apr_pool_t *result_pool,
+                 apr_pool_t *scratch_pool)
+{
+  svn_fs_root_t *root = baton;
+  svn_fs_root_t *prev_root;
+  svn_fs_t *fs = svn_fs_root_fs(root);
+
+  SVN_ERR(svn_fs_revision_root(&prev_root, fs,
+                               svn_fs_revision_root_revision(root) - 1,
+                               scratch_pool));
+
+  SVN_ERR(svn_fs_node_proplist(props, prev_root, path, result_pool));
+
+  return SVN_NO_ERROR;
+}
+
+#endif
+
 
 
 
@@ -792,7 +839,7 @@ svn_repos_replay2(svn_fs_root_t *root,
                   void *authz_read_baton,
                   apr_pool_t *pool)
 {
-#if 1
+#ifndef USE_EV2_IMPL
   apr_hash_t *fs_changes;
   apr_hash_t *changed_paths;
   apr_hash_index_t *hi;
@@ -941,11 +988,15 @@ svn_repos_replay2(svn_fs_root_t *root,
                                        &send_abs_paths,
                                        repos_root, "",
                                        NULL, NULL,
-                                       NULL, NULL,
-                                       NULL, NULL,
+                                       fetch_kind_func, root,
+                                       fetch_props_func, root,
                                        pool, pool));
 
-  SVN_ERR(svn_repos__replay_ev2(root, base_path, low_water_mark, send_deltas,
+  /* Tell the shim that we're starting the process. */
+  SVN_ERR(exb->start_edit(exb->baton, svn_fs_revision_root_revision(root)));
+
+  /* ### We're ignoring SEND_DELTAS here. */
+  SVN_ERR(svn_repos__replay_ev2(root, base_path, low_water_mark,
                                 editorv2, authz_read_func, authz_read_baton,
                                 pool));
 
@@ -958,19 +1009,468 @@ svn_repos_replay2(svn_fs_root_t *root,
  *                      Ev2 Implementation                       *
  *****************************************************************/
 
+#ifdef USE_EV2_IMPL
+/* Recursively traverse EDIT_PATH (as it exists under SOURCE_ROOT) emitting
+   the appropriate editor calls to add it and its children without any
+   history.  This is meant to be used when either a subset of the tree
+   has been ignored and we need to copy something from that subset to
+   the part of the tree we do care about, or if a subset of the tree is
+   unavailable because of authz and we need to use it as the source of
+   a copy. */
 static svn_error_t *
-replay_node(const char *repos_relpath,
+add_subdir(svn_fs_root_t *source_root,
+           svn_fs_root_t *target_root,
+           svn_editor_t *editor,
+           const char *repos_relpath,
+           const char *source_fspath,
+           svn_repos_authz_func_t authz_read_func,
+           void *authz_read_baton,
+           apr_hash_t *changed_paths,
+           apr_pool_t *result_pool,
+           apr_pool_t *scratch_pool)
+{
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  apr_hash_index_t *hi;
+  apr_hash_t *dirents;
+  apr_hash_t *props = NULL;
+  apr_array_header_t *children = NULL;
+
+  SVN_ERR(svn_fs_node_proplist(&props, target_root, repos_relpath,
+                               scratch_pool));
+
+  SVN_ERR(svn_editor_add_directory(editor, repos_relpath, children,
+                                   props, SVN_INVALID_REVNUM));
+
+  /* We have to get the dirents from the source path, not the target,
+     because we want nested copies from *readable* paths to be handled by
+     path_driver_cb_func, not add_subdir (in order to preserve history). */
+  SVN_ERR(svn_fs_dir_entries(&dirents, source_root, source_fspath,
+                             scratch_pool));
+
+  for (hi = apr_hash_first(scratch_pool, dirents); hi; hi = apr_hash_next(hi))
+    {
+      svn_fs_path_change2_t *change;
+      svn_boolean_t readable = TRUE;
+      svn_fs_dirent_t *dent = svn__apr_hash_index_val(hi);
+      const char *copyfrom_path = NULL;
+      svn_revnum_t copyfrom_rev = SVN_INVALID_REVNUM;
+      const char *child_relpath;
+
+      svn_pool_clear(iterpool);
+
+      child_relpath = svn_relpath_join(repos_relpath, dent->name, iterpool);
+
+      /* If a file or subdirectory of the copied directory is listed as a
+         changed path (because it was modified after the copy but before the
+         commit), we remove it from the changed_paths hash so that future
+         calls to path_driver_cb_func will ignore it. */
+      change = apr_hash_get(changed_paths, child_relpath, APR_HASH_KEY_STRING);
+      if (change)
+        {
+          apr_hash_set(changed_paths, child_relpath, APR_HASH_KEY_STRING,
+                       NULL);
+
+          /* If it's a delete, skip this entry. */
+          if (change->change_kind == svn_fs_path_change_delete)
+            continue;
+
+          /* If it's a replacement, check for copyfrom info (if we
+             don't have it already. */
+          if (change->change_kind == svn_fs_path_change_replace)
+            {
+              if (! change->copyfrom_known)
+                {
+                  SVN_ERR(svn_fs_copied_from(&change->copyfrom_rev,
+                                             &change->copyfrom_path,
+                                             target_root, child_relpath,
+                                             result_pool));
+                  change->copyfrom_known = TRUE;
+                }
+              copyfrom_path = change->copyfrom_path;
+              copyfrom_rev = change->copyfrom_rev;
+            }
+        }
+
+      if (authz_read_func)
+        SVN_ERR(authz_read_func(&readable, target_root, child_relpath,
+                                authz_read_baton, iterpool));
+
+      if (! readable)
+        continue;
+
+      if (dent->kind == svn_node_dir)
+        {
+          svn_fs_root_t *new_source_root;
+          const char *new_source_fspath;
+
+          if (copyfrom_path)
+            {
+              svn_fs_t *fs = svn_fs_root_fs(source_root);
+              SVN_ERR(svn_fs_revision_root(&new_source_root, fs,
+                                           copyfrom_rev, result_pool));
+              new_source_fspath = copyfrom_path;
+            }
+          else
+            {
+              new_source_root = source_root;
+              new_source_fspath = svn_fspath__join(source_fspath, dent->name,
+                                                   iterpool);
+            }
+
+          /* ### authz considerations?
+           *
+           * I think not; when path_driver_cb_func() calls add_subdir(), it
+           * passes SOURCE_ROOT and SOURCE_FSPATH that are unreadable.
+           */
+          if (change && change->change_kind == svn_fs_path_change_replace
+              && copyfrom_path == NULL)
+            {
+              SVN_ERR(svn_editor_add_directory(editor, child_relpath,
+                                               children, props,
+                                               SVN_INVALID_REVNUM));
+            }
+          else
+            {
+              SVN_ERR(add_subdir(new_source_root, target_root,
+                                 editor, child_relpath,
+                                 new_source_fspath,
+                                 authz_read_func, authz_read_baton,
+                                 changed_paths, result_pool, iterpool));
+            }
+        }
+      else if (dent->kind == svn_node_file)
+        {
+          svn_checksum_t *checksum;
+          svn_stream_t *contents;
+
+          SVN_ERR(svn_fs_node_proplist(&props, target_root,
+                                       child_relpath, iterpool));
+
+          SVN_ERR(svn_fs_file_contents(&contents, target_root,
+                                       child_relpath, iterpool));
+
+          SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1,
+                                       target_root,
+                                       child_relpath, TRUE, iterpool));
+
+          SVN_ERR(svn_editor_add_file(editor, child_relpath, checksum,
+                                      contents, props, SVN_INVALID_REVNUM));
+        }
+      else
+        SVN_ERR_MALFUNCTION();
+    }
+
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+#endif
+
+static svn_error_t *
+replay_node(svn_fs_root_t *root,
+            const char *repos_relpath,
             svn_editor_t *editor,
+            svn_revnum_t low_water_mark,
+            const char *base_repos_relpath,
+            apr_array_header_t *copies,
+            apr_hash_t *changed_paths,
+            svn_repos_authz_func_t authz_read_func,
+            void *authz_read_baton,
+            apr_pool_t *result_pool,
             apr_pool_t *scratch_pool)
+#ifndef USE_EV2_IMPL
 {
   SVN__NOT_IMPLEMENTED();
 }
+#else
+{
+  svn_fs_path_change2_t *change;
+  svn_boolean_t do_add = FALSE;
+  svn_boolean_t do_delete = FALSE;
+  svn_revnum_t copyfrom_rev;
+  const char *copyfrom_path;
+  svn_revnum_t replaces_rev;
+
+  /* First, flush the copies stack so it only contains ancestors of path. */
+  while (copies->nelts > 0
+         && (svn_relpath_skip_ancestor(APR_ARRAY_IDX(copies,
+                                                    copies->nelts - 1,
+                                                     struct copy_info *)->path,
+                                       repos_relpath) == NULL) )
+    apr_array_pop(copies);
+
+  change = apr_hash_get(changed_paths, repos_relpath, APR_HASH_KEY_STRING);
+  if (! change)
+    {
+      /* This can only happen if the path was removed from changed_paths
+         by an earlier call to add_subdir, which means the path was already
+         handled and we should simply ignore it. */
+      return SVN_NO_ERROR;
+    }
+  switch (change->change_kind)
+    {
+    case svn_fs_path_change_add:
+      do_add = TRUE;
+      break;
+
+    case svn_fs_path_change_delete:
+      do_delete = TRUE;
+      break;
+
+    case svn_fs_path_change_replace:
+      do_add = TRUE;
+      do_delete = TRUE;
+      break;
+
+    case svn_fs_path_change_modify:
+    default:
+      /* do nothing */
+      break;
+    }
+
+  /* Handle any deletions. */
+  if (do_delete && ! do_add)
+    {
+      svn_boolean_t readable;
+
+      /* Issue #4121: delete under under a copy, of a path that was unreadable
+         at its pre-copy location. */
+      SVN_ERR(was_readable(&readable, root, repos_relpath, copies,
+                            authz_read_func, authz_read_baton,
+                            scratch_pool, scratch_pool));
+      if (readable)
+        SVN_ERR(svn_editor_delete(editor, repos_relpath, SVN_INVALID_REVNUM));
+
+      return SVN_NO_ERROR;
+    }
+
+  /* Handle replacements. */
+  if (do_delete && do_add)
+    replaces_rev = svn_fs_revision_root_revision(root);
+  else
+    replaces_rev = SVN_INVALID_REVNUM;
+
+  /* Fetch the node kind if it makes sense to do so. */
+  if (! do_delete || do_add)
+    {
+      if (change->node_kind == svn_node_unknown)
+        SVN_ERR(svn_fs_check_path(&(change->node_kind), root, repos_relpath,
+                                  scratch_pool));
+      if ((change->node_kind != svn_node_dir) &&
+          (change->node_kind != svn_node_file))
+        return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL,
+                                 _("Filesystem path '%s' is neither a file "
+                                   "nor a directory"), repos_relpath);
+    }
+
+  /* Handle any adds/opens. */
+  if (do_add)
+    {
+      svn_boolean_t src_readable;
+      svn_fs_root_t *copyfrom_root;
+
+      /* Was this node copied? */
+      SVN_ERR(fill_copyfrom(&copyfrom_root, &copyfrom_path, &copyfrom_rev,
+                            &src_readable, root, change,
+                            authz_read_func, authz_read_baton,
+                            repos_relpath, scratch_pool, scratch_pool));
+
+      /* If we have a copyfrom path, and we can't read it or we're just
+         ignoring it, or the copyfrom rev is prior to the low water mark
+         then we just null them out and do a raw add with no history at
+         all. */
+      if (copyfrom_path
+          && ((! src_readable)
+              || (svn_relpath_skip_ancestor(base_repos_relpath,
+                                            copyfrom_path + 1) == NULL)
+              || (low_water_mark > copyfrom_rev)))
+        {
+          copyfrom_path = NULL;
+          copyfrom_rev = SVN_INVALID_REVNUM;
+        }
+
+      /* Do the right thing based on the path KIND. */
+      if (change->node_kind == svn_node_dir)
+        {
+          /* If this is a copy, but we can't represent it as such,
+             then we just do a recursive add of the source path
+             contents. */
+          if (change->copyfrom_path && ! copyfrom_path)
+            {
+              SVN_ERR(add_subdir(copyfrom_root, root, editor,
+                                 repos_relpath, change->copyfrom_path,
+                                 authz_read_func, authz_read_baton,
+                                 changed_paths, result_pool, scratch_pool));
+            }
+          else
+            {
+              if (copyfrom_path)
+                {
+                  if (copyfrom_path[0] == '/')
+                    ++copyfrom_path;
+                  SVN_ERR(svn_editor_copy(editor, copyfrom_path, copyfrom_rev,
+                                          repos_relpath, replaces_rev));
+                }
+              else
+                {
+                  apr_array_header_t *children;
+                  apr_hash_t *props;
+                  apr_hash_t *dirents;
+
+                  SVN_ERR(svn_fs_dir_entries(&dirents, root, repos_relpath,
+                                             scratch_pool));
+                  SVN_ERR(svn_hash_keys(&children, dirents, scratch_pool));
+
+                  SVN_ERR(svn_fs_node_proplist(&props, root, repos_relpath,
+                                               scratch_pool));
+
+                  SVN_ERR(svn_editor_add_directory(editor, repos_relpath,
+                                                   children, props,
+                                                   replaces_rev));
+                }
+            }
+        }
+      else
+        {
+          if (copyfrom_path)
+            {
+              if (copyfrom_path[0] == '/')
+                ++copyfrom_path;
+              SVN_ERR(svn_editor_copy(editor, copyfrom_path, copyfrom_rev,
+                                      repos_relpath, replaces_rev));
+            }
+          else
+            {
+              apr_hash_t *props;
+              svn_checksum_t *checksum;
+              svn_stream_t *contents;
+
+              SVN_ERR(svn_fs_node_proplist(&props, root, repos_relpath,
+                                           scratch_pool));
+
+              SVN_ERR(svn_fs_file_contents(&contents, root, repos_relpath,
+                                           scratch_pool));
+
+              SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1, root,
+                                           repos_relpath, TRUE, scratch_pool));
+
+              SVN_ERR(svn_editor_add_file(editor, repos_relpath, checksum,
+                                          contents, props, replaces_rev));
+            }
+        }
+
+      /* If we represent this as a copy... */
+      if (copyfrom_path)
+        {
+          /* If it is a directory, make sure descendants get the correct
+             delta source by remembering that we are operating inside a
+             (possibly nested) copy operation. */
+          if (change->node_kind == svn_node_dir)
+            {
+              struct copy_info *info = apr_pcalloc(result_pool, sizeof(*info));
+
+              info->path = apr_pstrdup(result_pool, repos_relpath);
+              info->copyfrom_path = apr_pstrdup(result_pool, copyfrom_path);
+              info->copyfrom_rev = copyfrom_rev;
+
+              APR_ARRAY_PUSH(copies, struct copy_info *) = info;
+            }
+        }
+      else
+        /* Else, we are an add without history... */
+        {
+          /* If an ancestor is added with history, we need to forget about
+             that here, go on with life and repeat all the mistakes of our
+             past... */
+          if (change->node_kind == svn_node_dir && copies->nelts > 0)
+            {
+              struct copy_info *info = apr_pcalloc(result_pool, sizeof(*info));
+
+              info->path = apr_pstrdup(result_pool, repos_relpath);
+              info->copyfrom_path = NULL;
+              info->copyfrom_rev = SVN_INVALID_REVNUM;
+
+              APR_ARRAY_PUSH(copies, struct copy_info *) = info;
+            }
+        }
+    }
+  else if (! do_delete)
+    {
+      /* If we are inside an add with history, we need to adjust the
+         delta source. */
+      if (copies->nelts > 0)
+        {
+          struct copy_info *info = APR_ARRAY_IDX(copies,
+                                                 copies->nelts - 1,
+                                                 struct copy_info *);
+          if (info->copyfrom_path)
+            {
+              const char *relpath = svn_relpath_skip_ancestor(info->path,
+                                                              repos_relpath);
+              SVN_ERR_ASSERT(relpath && *relpath);
+              repos_relpath = svn_relpath_join(info->copyfrom_path,
+                                               relpath, scratch_pool);
+            }
+        }
+    }
+
+  if (! do_delete && !do_add)
+    {
+      apr_hash_t *props = NULL;
+
+      /* Is this a copy that was downgraded to a raw add?  (If so,
+         we'll need to transmit properties and file contents and such
+         for it regardless of what the CHANGE structure's text_mod
+         and prop_mod flags say.)  */
+      svn_boolean_t downgraded_copy = (change->copyfrom_known
+                                       && change->copyfrom_path
+                                       && (! copyfrom_path));
+
+      /* Handle property modifications. */
+      if (change->prop_mod || downgraded_copy)
+        {
+          SVN_ERR(svn_fs_node_proplist(&props, root, repos_relpath,
+                                       scratch_pool));
+        }
+
+      /* Handle textual modifications. */
+      if (change->node_kind == svn_node_file
+          && (change->text_mod || change->prop_mod || downgraded_copy))
+        {
+          svn_checksum_t *checksum;
+          svn_stream_t *contents;
+
+          SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1,
+                                       root, repos_relpath, TRUE,
+                                       scratch_pool));
+
+          SVN_ERR(svn_fs_file_contents(&contents, root, repos_relpath,
+                                       scratch_pool));
+
+          SVN_ERR(svn_editor_alter_file(editor, repos_relpath,
+                                        SVN_INVALID_REVNUM, props, checksum,
+                                        contents));
+        }
+
+      if (change->node_kind == svn_node_dir
+          && (change->prop_mod || downgraded_copy))
+        {
+          apr_array_header_t *children = NULL;
+
+          SVN_ERR(svn_editor_alter_directory(editor, repos_relpath,
+                                             SVN_INVALID_REVNUM, children,
+                                             props));
+        }
+    }
+
+  return SVN_NO_ERROR;
+}
+#endif
 
 svn_error_t *
 svn_repos__replay_ev2(svn_fs_root_t *root,
                       const char *base_repos_relpath,
                       svn_revnum_t low_water_mark,
-                      svn_boolean_t send_deltas,
                       svn_editor_t *editor,
                       svn_repos_authz_func_t authz_read_func,
                       void *authz_read_baton,
@@ -980,9 +1480,9 @@ svn_repos__replay_ev2(svn_fs_root_t *roo
   apr_hash_t *changed_paths;
   apr_hash_index_t *hi;
   apr_array_header_t *paths;
-  svn_fs_root_t *compare_root;
   apr_array_header_t *copies;
   apr_pool_t *iterpool;
+  svn_error_t *err = SVN_NO_ERROR;
   int i;
 
   SVN_ERR_ASSERT(!svn_dirent_is_absolute(base_repos_relpath));
@@ -1051,28 +1551,33 @@ svn_repos__replay_ev2(svn_fs_root_t *roo
   if (! SVN_IS_VALID_REVNUM(low_water_mark))
     low_water_mark = 0;
 
-  if (send_deltas)
-    {
-      SVN_ERR(svn_fs_revision_root(&compare_root,
-                                   svn_fs_root_fs(root),
-                                   svn_fs_is_revision_root(root)
-                                     ? svn_fs_revision_root_revision(root) - 1
-                                     : svn_fs_txn_root_base_revision(root),
-                                   scratch_pool));
-    }
-  else
-    compare_root = NULL;
-
   copies = apr_array_make(scratch_pool, 4, sizeof(struct copy_info *));
 
+  /* Sort the paths.  Although not strictly required by the API, this has
+     the pleasant side effect of maintaining a consistent ordering of
+     dumpfile contents. */
+  qsort(paths->elts, paths->nelts, paths->elt_size, svn_sort_compare_paths);
+
   /* Now actually handle the various paths. */
   iterpool = svn_pool_create(scratch_pool);
   for (i = 0; i < paths->nelts; i++)
     {
       const char *repos_relpath = APR_ARRAY_IDX(paths, i, const char *);
-      SVN_ERR(replay_node(repos_relpath, editor, iterpool));
+
+      svn_pool_clear(iterpool);
+      err = replay_node(root, repos_relpath, editor, low_water_mark,
+                        base_repos_relpath, copies, changed_paths,
+                        authz_read_func, authz_read_baton,
+                        scratch_pool, iterpool);
+      if (err)
+        break;
     }
 
+  if (err)
+    return svn_error_compose_create(err, svn_editor_abort(editor));
+  else
+    SVN_ERR(svn_editor_complete(editor));
+
   svn_pool_destroy(iterpool);
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/ev2-export/subversion/libsvn_subr/adler32.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/adler32.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/adler32.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/adler32.c Wed Jul 11 10:26:19 2012
@@ -61,7 +61,9 @@ svn__adler32(apr_uint32_t checksum, cons
        * optimized code. Also, new zlib versions will come with
        * SIMD code for x86 and x64.
        */
-      return adler32(checksum, (const Bytef *)data, len);
+      return (apr_uint32_t)adler32(checksum,
+                                   (const Bytef *)data,
+                                   (uInt)len);
     }
   else
     {

Modified: subversion/branches/ev2-export/subversion/libsvn_subr/auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/auth.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/auth.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/auth.c Wed Jul 11 10:26:19 2012
@@ -441,11 +441,12 @@ svn_auth_get_platform_specific_provider(
             {
               svn_version_func_t version_function
                 = version_function_symbol;
-              const svn_version_checklist_t check_list[] =
-                {
-                  { library_label, version_function },
-                  { NULL, NULL }
-                };
+              svn_version_checklist_t check_list[2];
+
+              check_list[0].label = library_label;
+              check_list[0].version_query = version_function;
+              check_list[1].label = NULL;
+              check_list[1].version_query = NULL;
               SVN_ERR(svn_ver_check_list(svn_subr_version(), check_list));
             }
           if (apr_dso_sym(&provider_function_symbol,

Modified: subversion/branches/ev2-export/subversion/libsvn_subr/base64.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/base64.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/base64.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/base64.c Wed Jul 11 10:26:19 2012
@@ -306,9 +306,9 @@ struct decode_baton {
 static APR_INLINE void
 decode_group(const unsigned char *in, char *out)
 {
-  out[0] = (in[0] << 2) | (in[1] >> 4);
-  out[1] = ((in[1] & 0xf) << 4) | (in[2] >> 2);
-  out[2] = ((in[2] & 0x3) << 6) | in[3];
+  out[0] = (char)((in[0] << 2) | (in[1] >> 4));
+  out[1] = (char)(((in[1] & 0xf) << 4) | (in[2] >> 2));
+  out[2] = (char)(((in[2] & 0x3) << 6) | in[3]);
 }
 
 /* Lookup table for base64 characters; reverse_base64[ch] gives a

Modified: subversion/branches/ev2-export/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/cache-membuffer.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/cache-membuffer.c Wed Jul 11 10:26:19 2012
@@ -700,9 +700,11 @@ let_entry_age(svn_membuffer_t *cache, en
 static APR_INLINE unsigned char
 is_group_initialized(svn_membuffer_t *cache, apr_uint32_t group_index)
 {
-  unsigned char flags = cache->group_initialized
-                          [group_index / (8 * GROUP_INIT_GRANULARITY)];
-  unsigned char bit_mask = 1 << ((group_index / GROUP_INIT_GRANULARITY) % 8);
+  unsigned char flags
+    = cache->group_initialized[group_index / (8 * GROUP_INIT_GRANULARITY)];
+  unsigned char bit_mask
+    = (unsigned char)(1 << ((group_index / GROUP_INIT_GRANULARITY) % 8));
+
   return flags & bit_mask;
 }
 
@@ -726,7 +728,8 @@ initialize_group(svn_membuffer_t *cache,
         cache->directory[i][j].offset = NO_OFFSET;
 
   /* set the "initialized" bit for these groups */
-  bit_mask = 1 << ((group_index / GROUP_INIT_GRANULARITY) % 8);
+  bit_mask
+    = (unsigned char)(1 << ((group_index / GROUP_INIT_GRANULARITY) % 8));
   cache->group_initialized[group_index / (8 * GROUP_INIT_GRANULARITY)]
     |= bit_mask;
 }
@@ -1075,11 +1078,10 @@ svn_cache__membuffer_cache_create(svn_me
    * Note, that this limit could only be exceeded in a very
    * theoretical setup with about 1EB of cache.
    */
-  group_count = directory_size / sizeof(entry_group_t);
-  if (group_count >= (APR_UINT32_MAX / GROUP_SIZE))
-    {
-      group_count = (APR_UINT32_MAX / GROUP_SIZE) - 1;
-    }
+  group_count = directory_size / sizeof(entry_group_t)
+                    >= (APR_UINT32_MAX / GROUP_SIZE)
+              ? (APR_UINT32_MAX / GROUP_SIZE) - 1
+              : (apr_uint32_t)(directory_size / sizeof(entry_group_t));
 
   group_init_size = 1 + group_count / (8 * GROUP_INIT_GRANULARITY);
   for (seg = 0; seg < segment_count; ++seg)

Modified: subversion/branches/ev2-export/subversion/libsvn_subr/cache-memcache.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/cache-memcache.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/cache-memcache.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/cache-memcache.c Wed Jul 11 10:26:19 2012
@@ -29,6 +29,7 @@
 
 #include "svn_private_config.h"
 #include "private/svn_cache.h"
+#include "private/svn_dep_compat.h"
 
 #include "cache.h"
 
@@ -527,7 +528,7 @@ svn_cache__make_memcache_from_config(svn
                                     svn_config_t *config,
                                     apr_pool_t *pool)
 {
-  apr_uint16_t server_count;
+  int server_count;
   apr_pool_t *subpool = svn_pool_create(pool);
 
   server_count =
@@ -542,12 +543,15 @@ svn_cache__make_memcache_from_config(svn
       return SVN_NO_ERROR;
     }
 
+  if (server_count > APR_INT16_MAX)
+    return svn_error_create(SVN_ERR_TOO_MANY_MEMCACHED_SERVERS, NULL, NULL);
+
 #ifdef SVN_HAVE_MEMCACHE
   {
     struct ams_baton b;
     svn_memcache_t *memcache = apr_pcalloc(pool, sizeof(*memcache));
     apr_status_t apr_err = apr_memcache_create(pool,
-                                               server_count,
+                                               (apr_uint16_t)server_count,
                                                0, /* flags */
                                                &(memcache->c));
     if (apr_err != APR_SUCCESS)

Modified: subversion/branches/ev2-export/subversion/libsvn_subr/cache.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/cache.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/cache.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/cache.c Wed Jul 11 10:26:19 2012
@@ -212,14 +212,14 @@ svn_cache__format_info(const svn_cache__
   enum { _1MB = 1024 * 1024 };
 
   apr_uint64_t misses = info->gets - info->hits;
-  double hit_rate = (100.0 * info->hits)
-                  / (info->gets ? info->gets : 1);
-  double write_rate = (100.0 * info->sets)
-                    / (misses ? misses : 1);
-  double data_usage_rate = (100.0 * info->used_size)
-                         / (info->data_size ? info->data_size : 1);
-  double data_entry_rate = (100.0 * info->used_entries)
-                         / (info->total_entries ? info->total_entries : 1);
+  double hit_rate = (100.0 * (double)info->hits)
+                  / (double)(info->gets ? info->gets : 1);
+  double write_rate = (100.0 * (double)info->sets)
+                    / (double)(misses ? misses : 1);
+  double data_usage_rate = (100.0 * (double)info->used_size)
+                         / (double)(info->data_size ? info->data_size : 1);
+  double data_entry_rate = (100.0 * (double)info->used_entries)
+                 / (double)(info->total_entries ? info->total_entries : 1);
 
   return svn_string_createf(result_pool,
 

Modified: subversion/branches/ev2-export/subversion/libsvn_subr/checksum.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/checksum.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/checksum.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/checksum.c Wed Jul 11 10:26:19 2012
@@ -276,8 +276,8 @@ svn_checksum_parse_hex(svn_checksum_t **
       if (x1 == (char)-1 || x2 == (char)-1)
         return svn_error_create(SVN_ERR_BAD_CHECKSUM_PARSE, NULL, NULL);
 
-      digest[i] = (x1 << 4) | x2;
-      is_nonzero |= (x1 << 4) | x2;
+      digest[i] = (char)((x1 << 4) | x2);
+      is_nonzero |= (char)((x1 << 4) | x2);
     }
 
   if (!is_nonzero)

Modified: subversion/branches/ev2-export/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/config_file.c?rev=1360103&r1=1360102&r2=1360103&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/config_file.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/config_file.c Wed Jul 11 10:26:19 2012
@@ -797,9 +797,6 @@ svn_config_ensure(const char *config_dir
                                                                              NL
         "###   http-compression           Whether to compress HTTP requests" NL
         "###   neon-debug-mask            Debug mask for Neon HTTP library"  NL
-#ifdef SVN_NEON_0_26
-        "###   http-auth-types            Auth types to use for HTTP library"NL
-#endif
         "###   ssl-authority-files        List of files, each of a trusted CA"
                                                                              NL
         "###   ssl-trust-default-ca       Trust the system 'default' CAs"    NL
@@ -809,7 +806,7 @@ svn_config_ensure(const char *config_dir
         "###   ssl-pkcs11-provider        Name of PKCS#11 provider to use."  NL
         "###   http-library               Which library to use for http/https"
                                                                              NL
-        "###                              connections (neon or serf)"        NL
+        "###                              connections."                      NL
         "###   store-passwords            Specifies whether passwords used"  NL
         "###                              to authenticate against a"         NL
         "###                              Subversion server may be cached"   NL
@@ -887,6 +884,13 @@ svn_config_ensure(const char *config_dir
         "### HTTP timeouts, if given, are specified in seconds.  A timeout"  NL
         "### of 0, i.e. zero, causes a builtin default to be used."          NL
         "###"                                                                NL
+        "### Most users will not need to explicitly set the http-library"    NL
+        "### option, but valid values for the option include:"               NL
+        "###    'serf': Serf-based module (Subversion 1.5 - present)"        NL
+        "###    'neon': Neon-based module (Subversion 1.0 - 1.7)"            NL
+        "### Availability of these modules may depend on your specific"      NL
+        "### Subversion distribution."                                       NL
+        "###"                                                                NL
         "### The commented-out examples below are intended only to"          NL
         "### demonstrate how to use this file; any resemblance to actual"    NL
         "### servers, living or dead, is entirely coincidental."             NL
@@ -908,9 +912,6 @@ svn_config_ensure(const char *config_dir
         "# http-proxy-username = blah"                                       NL
         "# http-proxy-password = doubleblah"                                 NL
         "# http-timeout = 60"                                                NL
-#ifdef SVN_NEON_0_26
-        "# http-auth-types = basic;digest;negotiate"                         NL
-#endif
         "# neon-debug-mask = 130"                                            NL
 #ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
         "# store-plaintext-passwords = no"                                   NL
@@ -951,9 +952,6 @@ svn_config_ensure(const char *config_dir
         "# http-proxy-username = defaultusername"                            NL
         "# http-proxy-password = defaultpassword"                            NL
         "# http-compression = no"                                            NL
-#ifdef SVN_NEON_0_26
-        "# http-auth-types = basic;digest;negotiate"                         NL
-#endif
         "# No http-timeout, so just use the builtin default."                NL
         "# No neon-debug-mask, so neon debugging is disabled."               NL
         "# ssl-authority-files = /path/to/CAcert.pem;/path/to/CAcert2.pem"   NL