subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hwri...@apache.org
Subject svn commit: r1400556 [14/29] - in /subversion/branches/ev2-export: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/hudson/ contrib/client-side/emacs/ contrib/client-side/svn-push/ contrib/client-side/svnmerge/ contrib/hook-...
Date Sun, 21 Oct 2012 02:00:47 GMT
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=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_svn/marshal.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_svn/marshal.c Sun Oct 21 02:00:31 2012
@@ -54,15 +54,34 @@
 
 #define SUSPICIOUSLY_HUGE_STRING_SIZE_THRESHOLD (0x100000)
 
+/* When zero copy has been enabled, don't use blocking writes.  Instead,
+ * time out after this many microseconds. */
+
+#define ZERO_COPY_TIMEOUT 1000000
+
+/* Return the APR socket timeout to be used for the connection depending
+ * on whether there is a blockage handler or zero copy has been activated. */
+static apr_interval_time_t
+get_timeout(svn_ra_svn_conn_t *conn)
+{
+  return conn->block_handler ? 0
+                             : (conn->zero_copy_limit ? ZERO_COPY_TIMEOUT
+                                                      : -1);
+}
+
 /* --- CONNECTION INITIALIZATION --- */
 
-svn_ra_svn_conn_t *svn_ra_svn_create_conn2(apr_socket_t *sock,
+svn_ra_svn_conn_t *svn_ra_svn_create_conn3(apr_socket_t *sock,
                                            apr_file_t *in_file,
                                            apr_file_t *out_file,
                                            int compression_level,
+                                           apr_size_t zero_copy_limit,
+                                           apr_size_t error_check_interval,
                                            apr_pool_t *pool)
 {
-  svn_ra_svn_conn_t *conn = apr_palloc(pool, sizeof(*conn));
+  svn_ra_svn_conn_t *conn;
+  void *mem = apr_palloc(pool, sizeof(*conn) + SVN_RA_SVN__PAGE_SIZE);
+  conn = (void*)APR_ALIGN((apr_uintptr_t)mem, SVN_RA_SVN__PAGE_SIZE);
 
   assert((sock && !in_file && !out_file) || (!sock && in_file && out_file));
 #ifdef SVN_HAVE_SASL
@@ -73,10 +92,14 @@ svn_ra_svn_conn_t *svn_ra_svn_create_con
   conn->read_ptr = conn->read_buf;
   conn->read_end = conn->read_buf;
   conn->write_pos = 0;
+  conn->written_since_error_check = 0;
+  conn->error_check_interval = error_check_interval;
+  conn->may_check_for_error = error_check_interval == 0;
   conn->block_handler = NULL;
   conn->block_baton = NULL;
   conn->capabilities = apr_hash_make(pool);
   conn->compression_level = compression_level;
+  conn->zero_copy_limit = zero_copy_limit;
   conn->pool = pool;
 
   if (sock != NULL)
@@ -86,6 +109,7 @@ svn_ra_svn_conn_t *svn_ra_svn_create_con
       if (!(apr_socket_addr_get(&sa, APR_REMOTE, sock) == APR_SUCCESS
             && apr_sockaddr_ip_get(&conn->remote_ip, sa) == APR_SUCCESS))
         conn->remote_ip = NULL;
+      svn_ra_svn__stream_timeout(conn->stream, get_timeout(conn));
     }
   else
     {
@@ -96,14 +120,25 @@ svn_ra_svn_conn_t *svn_ra_svn_create_con
   return conn;
 }
 
+svn_ra_svn_conn_t *svn_ra_svn_create_conn2(apr_socket_t *sock,
+                                           apr_file_t *in_file,
+                                           apr_file_t *out_file,
+                                           int compression_level,
+                                           apr_pool_t *pool)
+{
+  return svn_ra_svn_create_conn3(sock, in_file, out_file,
+                                 compression_level, 0, 0, pool);
+}
+
 /* backward-compatible implementation using the default compression level */
 svn_ra_svn_conn_t *svn_ra_svn_create_conn(apr_socket_t *sock,
                                           apr_file_t *in_file,
                                           apr_file_t *out_file,
                                           apr_pool_t *pool)
 {
-  return svn_ra_svn_create_conn2(sock, in_file, out_file,
-                                 SVN_DELTA_COMPRESSION_LEVEL_DEFAULT, pool);
+  return svn_ra_svn_create_conn3(sock, in_file, out_file,
+                                 SVN_DELTA_COMPRESSION_LEVEL_DEFAULT, 0, 0,
+                                 pool);
 }
 
 svn_error_t *svn_ra_svn_set_capabilities(svn_ra_svn_conn_t *conn,
@@ -146,6 +181,12 @@ svn_ra_svn_compression_level(svn_ra_svn_
   return conn->compression_level;
 }
 
+apr_size_t
+svn_ra_svn_zero_copy_limit(svn_ra_svn_conn_t *conn)
+{
+  return conn->zero_copy_limit;
+}
+
 const char *svn_ra_svn_conn_remote_host(svn_ra_svn_conn_t *conn)
 {
   return conn->remote_ip;
@@ -156,11 +197,9 @@ svn_ra_svn__set_block_handler(svn_ra_svn
                               ra_svn_block_handler_t handler,
                               void *baton)
 {
-  apr_interval_time_t interval = (handler) ? 0 : -1;
-
   conn->block_handler = handler;
   conn->block_baton = baton;
-  svn_ra_svn__stream_timeout(conn->stream, interval);
+  svn_ra_svn__stream_timeout(conn->stream, get_timeout(conn));
 }
 
 svn_boolean_t svn_ra_svn__input_waiting(svn_ra_svn_conn_t *conn,
@@ -171,20 +210,6 @@ svn_boolean_t svn_ra_svn__input_waiting(
 
 /* --- WRITE BUFFER MANAGEMENT --- */
 
-/* Write bytes into the write buffer until either the write buffer is
- * full or we reach END. */
-static const char *writebuf_push(svn_ra_svn_conn_t *conn, const char *data,
-                                 const char *end)
-{
-  apr_ssize_t buflen, copylen;
-
-  buflen = sizeof(conn->write_buf) - conn->write_pos;
-  copylen = (buflen < end - data) ? buflen : end - data;
-  memcpy(conn->write_buf + conn->write_pos, data, copylen);
-  conn->write_pos += copylen;
-  return data + copylen;
-}
-
 /* Write data to socket or output file as appropriate. */
 static svn_error_t *writebuf_output(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
                                     const char *data, apr_size_t len)
@@ -223,6 +248,10 @@ static svn_error_t *writebuf_output(svn_
         }
     }
 
+  conn->written_since_error_check += len;
+  conn->may_check_for_error
+    = conn->written_since_error_check >= conn->error_check_interval;
+
   if (subpool)
     svn_pool_destroy(subpool);
   return SVN_NO_ERROR;
@@ -242,19 +271,23 @@ static svn_error_t *writebuf_flush(svn_r
 static svn_error_t *writebuf_write(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
                                    const char *data, apr_size_t len)
 {
-  const char *end = data + len;
-
-  if (conn->write_pos > 0 && conn->write_pos + len > sizeof(conn->write_buf))
+  /* data >= 8k is sent immediately */
+  if (len >= sizeof(conn->write_buf) / 2)
     {
-      /* Fill and then empty the write buffer. */
-      data = writebuf_push(conn, data, end);
-      SVN_ERR(writebuf_flush(conn, pool));
+      if (conn->write_pos > 0)
+        SVN_ERR(writebuf_flush(conn, pool));
+      
+      return writebuf_output(conn, pool, data, len);
     }
 
-  if (end - data > (apr_ssize_t)sizeof(conn->write_buf))
-    SVN_ERR(writebuf_output(conn, pool, data, end - data));
-  else
-    writebuf_push(conn, data, end);
+  /* ensure room for the data to add */
+  if (conn->write_pos + len > sizeof(conn->write_buf))
+    SVN_ERR(writebuf_flush(conn, pool));
+
+  /* buffer the new data block as well */
+  memcpy(conn->write_buf + conn->write_pos, data, len);
+  conn->write_pos += len;
+
   return SVN_NO_ERROR;
 }
 
@@ -331,6 +364,31 @@ static svn_error_t *readbuf_input(svn_ra
   return SVN_NO_ERROR;
 }
 
+/* Treat the next LEN input bytes from CONN as "read" */
+static svn_error_t *readbuf_skip(svn_ra_svn_conn_t *conn, apr_uint64_t len)
+{
+  do
+  {
+    apr_size_t buflen = conn->read_end - conn->read_ptr;
+    apr_size_t copylen = (buflen < len) ? buflen : (apr_size_t)len;
+    conn->read_ptr += copylen;
+    len -= copylen;
+    if (len == 0)
+      break;
+
+    buflen = sizeof(conn->read_buf);
+    SVN_ERR(svn_ra_svn__stream_read(conn->stream, conn->read_buf, &buflen));
+    if (buflen == 0)
+      return svn_error_create(SVN_ERR_RA_SVN_CONNECTION_CLOSED, NULL, NULL);
+
+    conn->read_end = conn->read_buf + buflen;
+    conn->read_ptr = conn->read_buf;
+  }
+  while (len > 0);
+
+  return SVN_NO_ERROR;
+}
+
 /* Read data from the socket into the read buffer, which must be empty. */
 static svn_error_t *readbuf_fill(svn_ra_svn_conn_t *conn, apr_pool_t *pool)
 {
@@ -562,13 +620,569 @@ svn_error_t *svn_ra_svn_flush(svn_ra_svn
 
 /* --- WRITING TUPLES --- */
 
+static svn_error_t *
+vwrite_tuple_cstring(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  const char *cstr = va_arg(*ap, const char *);
+  SVN_ERR_ASSERT(cstr);
+  return svn_ra_svn_write_cstring(conn, pool, cstr);
+}
+
+static svn_error_t *
+vwrite_tuple_cstring_opt(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  const char *cstr = va_arg(*ap, const char *);
+  return cstr ? svn_ra_svn_write_cstring(conn, pool, cstr) : SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_tuple_string(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  const svn_string_t *str = va_arg(*ap, const svn_string_t *);
+  SVN_ERR_ASSERT(str);
+  return svn_ra_svn_write_string(conn, pool, str);
+}
+
+static svn_error_t *
+vwrite_tuple_string_opt(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  const svn_string_t *str = va_arg(*ap, const svn_string_t *);
+  return str ? svn_ra_svn_write_string(conn, pool, str) : SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_tuple_start_list(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  return svn_ra_svn_start_list(conn, pool);
+}
+
+static svn_error_t *
+vwrite_tuple_end_list(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  return svn_ra_svn_end_list(conn, pool);
+}
+
+static svn_error_t *
+vwrite_tuple_word(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  const char *cstr = va_arg(*ap, const char *);
+  SVN_ERR_ASSERT(cstr);
+  return svn_ra_svn_write_word(conn, pool, cstr);
+}
+
+static svn_error_t *
+vwrite_tuple_word_opt(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  const char *cstr = va_arg(*ap, const char *);
+  return cstr ? svn_ra_svn_write_word(conn, pool, cstr) : SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_tuple_revision(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  svn_revnum_t rev = va_arg(*ap, svn_revnum_t);
+  SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(rev));
+  return svn_ra_svn_write_number(conn, pool, rev);
+}
+
+static svn_error_t *
+vwrite_tuple_revision_opt(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  svn_revnum_t rev = va_arg(*ap, svn_revnum_t);
+  return SVN_IS_VALID_REVNUM(rev)
+       ? svn_ra_svn_write_number(conn, pool, rev)
+       : SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_tuple_number(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  return svn_ra_svn_write_number(conn, pool, va_arg(*ap, apr_uint64_t));
+}
+
+static svn_error_t *
+vwrite_tuple_boolean(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  const char *cstr = va_arg(*ap, svn_boolean_t) ? "true" : "false";
+  return svn_ra_svn_write_word(conn, pool, cstr);
+}
+
+static svn_error_t *
+vwrite_cmd_open_root(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_revision_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_delete_entry(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_revision_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_add_dir(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_revision_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_open_dir(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_revision_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_change_dir_prop(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_string_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_absent_dir(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_add_file(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_revision_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_open_file(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_revision_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_change_file_prop(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_string_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_close_file(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_absent_file(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_textdelta_chunk(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_string(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_apply_textdelta(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_no_op(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_set_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_revision(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_boolean(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_word(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_link_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_revision(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_boolean(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_word(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_change_rev_prop2(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_revision(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_string_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_boolean(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_string_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_change_rev_prop(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_revision(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_string_opt(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_rev_prop(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_revision(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_get_file(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_revision_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_boolean(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_boolean(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_update(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_revision_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_boolean(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_word(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_boolean(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_switch(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_revision_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_boolean(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_word(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_status(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_boolean(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_revision_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_word(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_diff(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_revision_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_boolean(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_boolean(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_boolean(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_word(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_check_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_revision_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_stat(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_revision_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_get_file_revs(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_revision_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_revision_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_boolean(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_lock(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_boolean(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_revision_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_unlock(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_cstring_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_boolean(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_get_locks(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_word(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_replay(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_revision(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_revision(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_boolean(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_replay_range(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_revision(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_revision(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_revision(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_boolean(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_get_deleted_rev(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_revision(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_revision(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+vwrite_cmd_get_iprops(svn_ra_svn_conn_t *conn, apr_pool_t *pool, va_list *ap)
+{
+  SVN_ERR(vwrite_tuple_cstring(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_revision_opt(conn, pool, ap));
+  SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
+
+  return SVN_NO_ERROR;
+}
+ 
+typedef svn_error_t *
+(*vwrite_tuple_func)(svn_ra_svn_conn_t *, apr_pool_t *, va_list *);
+
+typedef struct cmd_template_t
+{
+  const char *start_sequence;
+  apr_size_t start_sequence_length;
+  vwrite_tuple_func write_ops;
+} cmd_template_t;
+
+static const cmd_template_t cmd_templates[svn_ra_svn_cmd__last]
+    = { {"( target-rev ( "      , 15, vwrite_tuple_revision },
+        {"( open-root ( "       , 14, vwrite_cmd_open_root },
+        {"( delete-entry ( "    , 17, vwrite_cmd_delete_entry },
+        {"( add-dir ( "         , 12, vwrite_cmd_add_dir },
+        {"( open-dir ( "        , 13, vwrite_cmd_open_dir },
+        {"( change-dir-prop ( " , 20, vwrite_cmd_change_dir_prop },
+        {"( close-dir ( "       , 14, vwrite_tuple_cstring },
+        {"( absent-dir ( "      , 15, vwrite_cmd_absent_dir },
+        {"( add-file ( "        , 13, vwrite_cmd_add_file },
+        {"( open-file ( "       , 14, vwrite_cmd_open_file },
+        {"( change-file-prop ( ", 21, vwrite_cmd_change_file_prop },
+        {"( close-file ( "      , 15, vwrite_cmd_close_file },
+        {"( absent-file ( "     , 16, vwrite_cmd_absent_file },
+        {"( textdelta-chunk ( " , 20, vwrite_cmd_textdelta_chunk },
+        {"( textdelta-end ( "   , 18, vwrite_tuple_cstring },
+        {"( apply-textdelta ( " , 20, vwrite_cmd_apply_textdelta },
+        {"( close-edit ( "      , 15, vwrite_cmd_no_op },
+        {"( abort-edit ( "      , 15, vwrite_cmd_no_op },
+
+        {"( set-path ( "        , 13, vwrite_cmd_set_path },
+        {"( delete-path ( "     , 16, vwrite_tuple_cstring },
+        {"( link-path ( "       , 14, vwrite_cmd_link_path },
+        {"( finish-report ( "   , 18, vwrite_cmd_no_op },
+        {"( abort-report ( "    , 17, vwrite_cmd_no_op },
+
+        {"( reparent ( "        , 13, vwrite_tuple_cstring },
+        {"( get-latest-rev ( "  , 19, vwrite_cmd_no_op },
+        {"( get-dated-rev ( "   , 18, vwrite_tuple_cstring },
+        {"( change-rev-prop2 ( ", 21, vwrite_cmd_change_rev_prop2 },
+        {"( change-rev-prop ( " , 20, vwrite_cmd_change_rev_prop },
+        {"( rev-proplist ( "    , 17, vwrite_tuple_revision },
+        {"( rev-prop ( "        , 13, vwrite_cmd_rev_prop },
+        {"( get-file ( "        , 13, vwrite_cmd_get_file },
+        {"( update ( "          , 11, vwrite_cmd_update },
+        {"( switch ( "          , 11, vwrite_cmd_switch },
+        {"( status ( "          , 11, vwrite_cmd_status },
+        {"( diff ( "            ,  9, vwrite_cmd_diff },
+        {"( check-path ( "      , 15, vwrite_cmd_check_path },
+        {"( stat ( "            ,  9, vwrite_cmd_stat },
+        {"( get-file-revs ( "   , 18, vwrite_cmd_get_file_revs },
+        {"( lock ( "            ,  9, vwrite_cmd_lock },
+        {"( unlock ( "          , 11, vwrite_cmd_unlock },
+        {"( get-lock ( "        , 13, vwrite_tuple_cstring },
+        {"( get-locks ( "       , 14, vwrite_cmd_get_locks },
+        {"( replay ( "          , 11, vwrite_cmd_replay },
+        {"( replay-range ( "    , 17, vwrite_cmd_replay_range },
+        {"( get-deleted-rev ( " , 20, vwrite_cmd_get_deleted_rev },
+        {"( get-iprops ( "      , 15, vwrite_cmd_get_iprops },
+        {"( finish-replay ( "   , 18, vwrite_cmd_no_op }
+    };
+
+
+
+
 static svn_error_t *vwrite_tuple(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
-                                 const char *fmt, va_list ap)
+                                 const char *fmt, va_list *ap)
 {
   svn_boolean_t opt = FALSE;
-  svn_revnum_t rev;
-  const char *cstr;
-  const svn_string_t *str;
 
   if (*fmt == '!')
     fmt++;
@@ -577,53 +1191,30 @@ static svn_error_t *vwrite_tuple(svn_ra_
   for (; *fmt; fmt++)
     {
       if (*fmt == 'c')
-        {
-          cstr = va_arg(ap, const char *);
-          if (cstr)
-            SVN_ERR(svn_ra_svn_write_cstring(conn, pool, cstr));
-          else
-            SVN_ERR_ASSERT(opt);
-        }
+        SVN_ERR(opt ? vwrite_tuple_cstring_opt(conn, pool, ap)
+                    : vwrite_tuple_cstring(conn, pool, ap));
       else if (*fmt == 's')
-        {
-          str = va_arg(ap, const svn_string_t *);
-          if (str)
-            SVN_ERR(svn_ra_svn_write_string(conn, pool, str));
-          else
-            SVN_ERR_ASSERT(opt);
-        }
+        SVN_ERR(opt ? vwrite_tuple_string_opt(conn, pool, ap)
+                    : vwrite_tuple_string(conn, pool, ap));
       else if (*fmt == '(' && !opt)
-        SVN_ERR(svn_ra_svn_start_list(conn, pool));
+        SVN_ERR(vwrite_tuple_start_list(conn, pool, ap));
       else if (*fmt == ')')
         {
-          SVN_ERR(svn_ra_svn_end_list(conn, pool));
+          SVN_ERR(vwrite_tuple_end_list(conn, pool, ap));
           opt = FALSE;
         }
       else if (*fmt == '?')
         opt = TRUE;
       else if (*fmt == 'w')
-        {
-          cstr = va_arg(ap, const char *);
-          if (cstr)
-            SVN_ERR(svn_ra_svn_write_word(conn, pool, cstr));
-          else
-            SVN_ERR_ASSERT(opt);
-        }
+        SVN_ERR(opt ? vwrite_tuple_word_opt(conn, pool, ap)
+                    : vwrite_tuple_word(conn, pool, ap));
       else if (*fmt == 'r')
-        {
-          rev = va_arg(ap, svn_revnum_t);
-          if (SVN_IS_VALID_REVNUM(rev))
-            SVN_ERR(svn_ra_svn_write_number(conn, pool, rev));
-          else
-            SVN_ERR_ASSERT(opt);
-        }
+        SVN_ERR(opt ? vwrite_tuple_revision_opt(conn, pool, ap)
+                    : vwrite_tuple_revision(conn, pool, ap));
       else if (*fmt == 'n' && !opt)
-        SVN_ERR(svn_ra_svn_write_number(conn, pool, va_arg(ap, apr_uint64_t)));
+        SVN_ERR(vwrite_tuple_number(conn, pool, ap));
       else if (*fmt == 'b' && !opt)
-        {
-          cstr = va_arg(ap, svn_boolean_t) ? "true" : "false";
-          SVN_ERR(svn_ra_svn_write_word(conn, pool, cstr));
-        }
+        SVN_ERR(vwrite_tuple_boolean(conn, pool, ap));
       else if (*fmt == '!' && !*(fmt + 1))
         return SVN_NO_ERROR;
       else
@@ -640,7 +1231,7 @@ svn_error_t *svn_ra_svn_write_tuple(svn_
   va_list ap;
 
   va_start(ap, fmt);
-  err = vwrite_tuple(conn, pool, fmt, ap);
+  err = vwrite_tuple(conn, pool, fmt, &ap);
   va_end(ap);
   return err;
 }
@@ -800,6 +1391,95 @@ static svn_error_t *read_item(svn_ra_svn
   return SVN_NO_ERROR;
 }
 
+/* Given the first non-whitespace character FIRST_CHAR, read the first
+ * command (word) encountered in CONN into *ITEM.  If ITEM is NULL, skip
+ * to the end of the current list.  Use POOL for allocations. */
+static svn_error_t *
+read_command_only(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
+                  const char **item, char first_char)
+{
+  char c = first_char;
+
+  /* Determine the item type and read it in.  Make sure that c is the
+  * first character at the end of the item so we can test to make
+  * sure it's whitespace. */
+  if (svn_ctype_isdigit(c))
+    {
+      /* It's a number or a string.  Read the number part, either way. */
+      apr_uint64_t val, prev_val=0;
+      val = c - '0';
+      while (1)
+        {
+          prev_val = val;
+          SVN_ERR(readbuf_getchar(conn, pool, &c));
+          if (!svn_ctype_isdigit(c))
+            break;
+          val = val * 10 + (c - '0');
+          if (prev_val >= (APR_UINT64_MAX / 10)) /* > maximum value? */
+            return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
+                                    _("Number is larger than maximum"));
+        }
+      if (c == ':')
+        {
+          /* It's a string. */
+          SVN_ERR(readbuf_skip(conn, val));
+          SVN_ERR(readbuf_getchar(conn, pool, &c));
+        }
+    }
+  else if (svn_ctype_isalpha(c))
+    {
+      /* It's a word. */
+      if (item)
+        {
+          /* This is the word we want to read */
+          
+          char *buf = apr_palloc(pool, 32);
+          apr_size_t len = 1;
+          buf[0] = c;
+
+          while (1)
+            {
+              SVN_ERR(readbuf_getchar(conn, pool, &c));
+              if (!svn_ctype_isalnum(c) && c != '-')
+                break;
+              buf[len] = c;
+              if (++len == 32)
+                return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
+                                        _("Word too long"));
+            }
+          buf[len] = 0;
+          *item = buf;
+        }
+      else
+        {
+          /* we don't need the actual word, just skip it */
+          do
+          {
+            SVN_ERR(readbuf_getchar(conn, pool, &c));
+          }
+          while (svn_ctype_isalnum(c) || c == '-');
+        }
+    }
+  else if (c == '(')
+    {
+      /* Read in the list items. */
+      while (1)
+        {
+          SVN_ERR(readbuf_getchar_skip_whitespace(conn, pool, &c));
+          if (c == ')')
+            break;
+
+          if (item && *item == NULL)
+            SVN_ERR(read_command_only(conn, pool, item, c));
+          else
+            SVN_ERR(read_command_only(conn, pool, NULL, c));
+        }
+      SVN_ERR(readbuf_getchar(conn, pool, &c));
+    }
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *svn_ra_svn_read_item(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
                                   svn_ra_svn_item_t **item)
 {
@@ -948,6 +1628,18 @@ svn_error_t *svn_ra_svn_read_tuple(svn_r
   return err;
 }
 
+svn_error_t *svn_ra_svn__read_command_only(svn_ra_svn_conn_t *conn,
+                                           apr_pool_t *pool,
+                                           const char **command)
+{
+  char c;
+  SVN_ERR(readbuf_getchar_skip_whitespace(conn, pool, &c));
+
+  *command = NULL;
+  return read_command_only(conn, pool, command, c);
+}
+
+
 svn_error_t *svn_ra_svn_parse_proplist(const apr_array_header_t *list,
                                        apr_pool_t *pool,
                                        apr_hash_t **props)
@@ -1148,11 +1840,28 @@ svn_error_t *svn_ra_svn_write_cmd(svn_ra
   SVN_ERR(svn_ra_svn_start_list(conn, pool));
   SVN_ERR(svn_ra_svn_write_word(conn, pool, cmdname));
   va_start(ap, fmt);
-  err = vwrite_tuple(conn, pool, fmt, ap);
+  err = vwrite_tuple(conn, pool, fmt, &ap);
   va_end(ap);
   return err ? svn_error_trace(err) : svn_ra_svn_end_list(conn, pool);
 }
 
+svn_error_t *svn_ra_svn_write_templated_cmd(svn_ra_svn_conn_t *conn,
+                                            apr_pool_t *pool,
+                                            svn_ra_svn_cmd_t cmd, ...)
+{
+  va_list ap;
+  svn_error_t *err;
+
+  SVN_ERR(writebuf_write_short_string(conn, pool,
+                                      cmd_templates[cmd].start_sequence,
+                                      cmd_templates[cmd].start_sequence_length));
+  va_start(ap, cmd);
+  err = cmd_templates[cmd].write_ops(conn, pool, &ap);
+  va_end(ap);
+
+  return err ? err : writebuf_write_short_string(conn, pool, ") ) ", 4);
+}
+
 svn_error_t *svn_ra_svn_write_cmd_response(svn_ra_svn_conn_t *conn,
                                            apr_pool_t *pool,
                                            const char *fmt, ...)
@@ -1162,7 +1871,7 @@ svn_error_t *svn_ra_svn_write_cmd_respon
 
   SVN_ERR(writebuf_write_short_string(conn, pool, "( success ", 10));
   va_start(ap, fmt);
-  err = vwrite_tuple(conn, pool, fmt, ap);
+  err = vwrite_tuple(conn, pool, fmt, &ap);
   va_end(ap);
   return err ? svn_error_trace(err) : svn_ra_svn_end_list(conn, pool);
 }

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_svn/protocol
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_svn/protocol?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_svn/protocol (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_svn/protocol Sun Oct 21 02:00:31 2012
@@ -202,6 +202,10 @@ capability and C indicates a client capa
 [S]  atomic-revprops   If the server presents this capability, it
                        supports the change-rev-prop2 command.
                        See section 3.1.1.
+[S]  inherited-props   If the server presents this capability, it supports the
+                       retrieval of inherited properties via the get-dir and
+                       get-file commands and also supports the get-iprops
+                       command (see section 3.1.1).
 
 3. Commands
 -----------
@@ -222,6 +226,7 @@ responds.
 Here are some miscellaneous prototypes used by the command sets:
 
   proplist:  ( ( name:string value:string ) ... )
+  iproplist: ( ( name:string proplist ) ... )
   propdelta: ( ( name:string [ value:string ] ) ... )
   node-kind: none|file|dir|unknown
   bool:      true|false
@@ -293,8 +298,10 @@ second place for auth-request point as n
                    ? ( post-commit-err:string ) )
 
   get-file
-    params:   ( path:string [ rev:number ] want-props:bool want-contents:bool )
-    response: ( [ checksum:string ] rev:number props:proplist )
+    params:   ( path:string [ rev:number ] want-props:bool want-contents:bool
+                [ want-iprops:bool ] )
+    response: ( [ checksum:string ] rev:number props:proplist
+                [ inherited-props:iproplist ] )
     If want-contents is specified, then after sending response, server
      sends file contents as a series of strings, terminated by the empty
      string, followed by a second empty command response to indicate
@@ -302,8 +309,9 @@ second place for auth-request point as n
 
   get-dir
     params:   ( path:string [ rev:number ] want-props:bool want-contents:bool
-                ? ( field:dirent-field ... ) )
-    response: ( rev:number props:proplist ( entry:dirent ... ) )]
+                ? ( field:dirent-field ... ) [ want-iprops:bool ] )
+    response: ( rev:number props:proplist ( entry:dirent ... )
+                [ inherited-props:iproplist ] )]
     dirent:   ( name:string kind:node-kind size:number has-props:bool
                 created-rev:number [ created-date:string ]
                 [ last-author:string ] )
@@ -464,6 +472,11 @@ second place for auth-request point as n
     params:   ( path:string peg-rev:number end-rev:number )
     response: ( deleted-rev:number )
 
+  get-iprops
+    params:   ( path:string [ rev:number ] )
+    response: ( inherited-props:iproplist )
+    New in svn 1.8.  If rev is not specified, the youngest revision is used.
+
 3.1.2. Editor Command Set
 
 An edit operation produces only one response, at close-edit or

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_svn/ra_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_svn/ra_svn.h?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_svn/ra_svn.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_svn/ra_svn.h Sun Oct 21 02:00:31 2012
@@ -56,9 +56,13 @@ typedef svn_error_t *(*ra_svn_block_hand
                                                apr_pool_t *pool,
                                                void *baton);
 
+/* The default "user agent". */
+#define SVN_RA_SVN__DEFAULT_USERAGENT  "SVN/" SVN_VER_NUMBER
+
 /* The size of our per-connection read and write buffers. */
-#define SVN_RA_SVN__READBUF_SIZE (4*4096)
-#define SVN_RA_SVN__WRITEBUF_SIZE (4*4096)
+#define SVN_RA_SVN__PAGE_SIZE 4096
+#define SVN_RA_SVN__READBUF_SIZE (4 * SVN_RA_SVN__PAGE_SIZE)
+#define SVN_RA_SVN__WRITEBUF_SIZE (4 * SVN_RA_SVN__PAGE_SIZE)
 
 /* Create forward reference */
 typedef struct svn_ra_svn__session_baton_t svn_ra_svn__session_baton_t;
@@ -66,6 +70,14 @@ typedef struct svn_ra_svn__session_baton
 /* This structure is opaque to the server.  The client pokes at the
  * first few fields during setup and cleanup. */
 struct svn_ra_svn_conn_st {
+
+  /* I/O buffers */
+  char write_buf[SVN_RA_SVN__WRITEBUF_SIZE];
+  char read_buf[SVN_RA_SVN__READBUF_SIZE];
+  char *read_ptr;
+  char *read_end;
+  apr_size_t write_pos;
+
   svn_ra_svn__stream_t *stream;
   svn_ra_svn__session_baton_t *session;
 #ifdef SVN_HAVE_SASL
@@ -75,19 +87,32 @@ struct svn_ra_svn_conn_st {
   apr_socket_t *sock;
   svn_boolean_t encrypted;
 #endif
-  char read_buf[SVN_RA_SVN__READBUF_SIZE];
-  char *read_ptr;
-  char *read_end;
-  char write_buf[SVN_RA_SVN__WRITEBUF_SIZE];
-  apr_size_t write_pos;
+
+  /* abortion check control */
+  apr_size_t written_since_error_check;
+  apr_size_t error_check_interval;
+  svn_boolean_t may_check_for_error;
+
+  /* repository info */
   const char *uuid;
   const char *repos_root;
+
+  /* TX block notification target */
   ra_svn_block_handler_t block_handler;
   void *block_baton;
+
+  /* server settings */
   apr_hash_t *capabilities;
   int compression_level;
+  apr_size_t zero_copy_limit;
+
+  /* who's on the other side of the connection? */
   char *remote_ip;
+
+  /* EV2 support*/
   svn_delta_shim_callbacks_t *shim_callbacks;
+
+  /* our pool */
   apr_pool_t *pool;
 };
 
@@ -104,6 +129,7 @@ struct svn_ra_svn__session_baton_t {
   void *callbacks_baton;
   apr_off_t bytes_read, bytes_written; /* apr_off_t's because that's what
                                           the callback interface uses */
+  const char *useragent;
 };
 
 /* Set a callback for blocked writes on conn.  This handler may
@@ -167,6 +193,13 @@ svn_error_t *svn_ra_svn__stream_write(sv
 svn_error_t *svn_ra_svn__stream_read(svn_ra_svn__stream_t *stream,
                                      char *data, apr_size_t *len);
 
+/* Read the command word from CONN, return it in *COMMAND and skip to the
+ * end of the command.  Allocate data in POOL.
+ */
+svn_error_t *svn_ra_svn__read_command_only(svn_ra_svn_conn_t *conn,
+                                           apr_pool_t *pool,
+                                           const char **command);
+
 /* Set the timeout for operations on STREAM to INTERVAL. */
 void svn_ra_svn__stream_timeout(svn_ra_svn__stream_t *stream,
                                 apr_interval_time_t interval);

Modified: subversion/branches/ev2-export/subversion/libsvn_repos/authz.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/authz.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/authz.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/authz.c Sun Oct 21 02:00:31 2012
@@ -714,14 +714,15 @@ static svn_boolean_t authz_validate_sect
 {
   struct authz_validate_baton *b = baton;
 
-  /* If the section is the groups definition, use the group checking
-     callback. Otherwise, use the rule checking callback. */
-  if (strncmp(name, "groups", 6) == 0)
+  /* Use the group checking callback for the "groups" section... */
+  if (strcmp(name, "groups") == 0)
     svn_config_enumerate2(b->config, name, authz_validate_group,
                           baton, pool);
-  else if (strncmp(name, "aliases", 7) == 0)
+  /* ...and the alias checking callback for "aliases"... */
+  else if (strcmp(name, "aliases") == 0)
     svn_config_enumerate2(b->config, name, authz_validate_alias,
                           baton, pool);
+  /* ...but for everything else use the rule checking callback. */
   else
     {
       /* Validate the section's name. Skip the optional REPOS_NAME. */

Modified: subversion/branches/ev2-export/subversion/libsvn_repos/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/commit.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/commit.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/commit.c Sun Oct 21 02:00:31 2012
@@ -921,8 +921,8 @@ svn_repos_get_commit_editor5(const svn_d
                              const char *repos_url,
                              const char *base_path,
                              apr_hash_t *revprop_table,
-                             svn_commit_callback2_t callback,
-                             void *callback_baton,
+                             svn_commit_callback2_t commit_callback,
+                             void *commit_baton,
                              svn_repos_authz_callback_t authz_callback,
                              void *authz_baton,
                              apr_pool_t *pool)
@@ -967,8 +967,8 @@ svn_repos_get_commit_editor5(const svn_d
   /* Set up the edit baton. */
   eb->pool = subpool;
   eb->revprop_table = svn_prop_hash_dup(revprop_table, subpool);
-  eb->commit_callback = callback;
-  eb->commit_callback_baton = callback_baton;
+  eb->commit_callback = commit_callback;
+  eb->commit_callback_baton = commit_baton;
   eb->authz_callback = authz_callback;
   eb->authz_baton = authz_baton;
   eb->base_path = svn_fspath__canonicalize(base_path, subpool);
@@ -1334,12 +1334,8 @@ svn_repos__get_commit_ev2(svn_editor_t *
   /* Can the user modify the repository at all?  */
   /* ### check against AUTHZ.  */
 
-  /* Okay... some access is allowed. Let's run the start-commit hook.  */
   author = apr_hash_get(revprops, SVN_PROP_REVISION_AUTHOR,
                         APR_HASH_KEY_STRING);
-  SVN_ERR(svn_repos__hooks_start_commit(repos, author ? author->data : NULL,
-                                        repos->client_capabilities,
-                                        scratch_pool));
 
   eb = apr_palloc(result_pool, sizeof(*eb));
   eb->repos = repos;
@@ -1357,6 +1353,11 @@ svn_repos__get_commit_ev2(svn_editor_t *
   /* The TXN has been created. Go ahead and apply all revision properties.  */
   SVN_ERR(apply_revprops(repos->fs, eb->txn_name, revprops, scratch_pool));
 
+  /* Okay... some access is allowed. Let's run the start-commit hook.  */
+  SVN_ERR(svn_repos__hooks_start_commit(repos, author ? author->data : NULL,
+                                        repos->client_capabilities,
+                                        eb->txn_name, scratch_pool));
+
   /* Wrap the FS editor within our editor.  */
   SVN_ERR(svn_editor_create(editor, eb, cancel_func, cancel_baton,
                             result_pool, scratch_pool));

Modified: subversion/branches/ev2-export/subversion/libsvn_repos/delta.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/delta.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/delta.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/delta.c Sun Oct 21 02:00:31 2012
@@ -629,12 +629,23 @@ svn_repos__compare_files(svn_boolean_t *
   if (!*changed_p)
     return SVN_NO_ERROR;
 
-  /* From this point on, assume things haven't changed. */
+  /* If the SHA1 checksums match for these things, we'll claim they
+     have the same contents.  (We don't give quite as much weight to
+     MD5 checksums.)  */
+  SVN_ERR(svn_fs_file_checksum(&checksum1, svn_checksum_sha1,
+                               root1, path1, FALSE, pool));
+  SVN_ERR(svn_fs_file_checksum(&checksum2, svn_checksum_sha1,
+                               root2, path2, FALSE, pool));
+  if (checksum1 && checksum2)
+    {
+      *changed_p = !svn_checksum_match(checksum1, checksum2);
+      return SVN_NO_ERROR;
+    }
+
+  /* From this point on, our default answer is "Nothing's changed". */
   *changed_p = FALSE;
 
-  /* So, things have changed.  But we need to know if the two sets of
-     file contents are actually different.  If they have differing
-     sizes, then we know they differ. */
+  /* Different filesizes means the contents are different. */
   SVN_ERR(svn_fs_file_length(&size1, root1, path1, pool));
   SVN_ERR(svn_fs_file_length(&size2, root2, path2, pool));
   if (size1 != size2)
@@ -643,8 +654,7 @@ svn_repos__compare_files(svn_boolean_t *
       return SVN_NO_ERROR;
     }
 
-  /* Same sizes, huh?  Well, if their checksums differ, we know they
-     differ. */
+  /* Different MD5 checksums means the contents are different. */
   SVN_ERR(svn_fs_file_checksum(&checksum1, svn_checksum_md5, root1, path1,
                                FALSE, pool));
   SVN_ERR(svn_fs_file_checksum(&checksum2, svn_checksum_md5, root2, path2,
@@ -655,13 +665,11 @@ svn_repos__compare_files(svn_boolean_t *
       return SVN_NO_ERROR;
     }
 
-  /* Same sizes, same checksums.  Chances are reallllly good that they
-     don't differ, but to be absolute sure, we need to compare bytes. */
+  /* And finally, different contents means the ... uh ... contents are
+     different. */
   SVN_ERR(svn_fs_file_contents(&stream1, root1, path1, pool));
   SVN_ERR(svn_fs_file_contents(&stream2, root2, path2, pool));
-
   SVN_ERR(svn_stream_contents_same2(&same, stream1, stream2, pool));
-
   *changed_p = !same;
 
   return SVN_NO_ERROR;

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=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/deprecated.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/deprecated.c Sun Oct 21 02:00:31 2012
@@ -48,8 +48,8 @@ svn_repos_get_commit_editor4(const svn_d
                              const char *base_path,
                              const char *user,
                              const char *log_msg,
-                             svn_commit_callback2_t callback,
-                             void *callback_baton,
+                             svn_commit_callback2_t commit_callback,
+                             void *commit_baton,
                              svn_repos_authz_callback_t authz_callback,
                              void *authz_baton,
                              apr_pool_t *pool)
@@ -65,7 +65,7 @@ svn_repos_get_commit_editor4(const svn_d
                  svn_string_create(log_msg, pool));
   return svn_repos_get_commit_editor5(editor, edit_baton, repos, txn,
                                       repos_url, base_path, revprop_table,
-                                      callback, callback_baton,
+                                      commit_callback, commit_baton,
                                       authz_callback, authz_baton, pool);
 }
 
@@ -254,6 +254,41 @@ svn_repos_begin_report(void **report_bat
 }
 
 svn_error_t *
+svn_repos_begin_report2(void **report_baton,
+                        svn_revnum_t revnum,
+                        svn_repos_t *repos,
+                        const char *fs_base,
+                        const char *target,
+                        const char *tgt_path,
+                        svn_boolean_t text_deltas,
+                        svn_depth_t depth,
+                        svn_boolean_t ignore_ancestry,
+                        svn_boolean_t send_copyfrom_args,
+                        const svn_delta_editor_t *editor,
+                        void *edit_baton,
+                        svn_repos_authz_func_t authz_read_func,
+                        void *authz_read_baton,
+                        apr_pool_t *pool)
+{
+  return svn_repos_begin_report3(report_baton,
+                                 revnum,
+                                 repos,
+                                 fs_base,
+                                 target,
+                                 tgt_path,
+                                 text_deltas,
+                                 depth,
+                                 ignore_ancestry,
+                                 send_copyfrom_args,
+                                 editor,
+                                 edit_baton,
+                                 authz_read_func,
+                                 authz_read_baton,
+                                 0,     /* disable zero-copy code path */
+                                 pool);
+}
+
+svn_error_t *
 svn_repos_set_path2(void *baton, const char *path, svn_revnum_t rev,
                     svn_boolean_t start_empty, const char *lock_token,
                     apr_pool_t *pool)

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=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/dump.c Sun Oct 21 02:00:31 2012
@@ -72,7 +72,8 @@ store_delta(apr_file_t **tempfile, svn_f
   /* Compute the delta and send it to the temporary file. */
   SVN_ERR(svn_fs_get_file_delta_stream(&delta_stream, oldroot, oldpath,
                                        newroot, newpath, pool));
-  svn_txdelta_to_svndiff2(&wh, &whb, temp_stream, 0, pool);
+  svn_txdelta_to_svndiff3(&wh, &whb, temp_stream, 0,
+                          SVN_DELTA_COMPRESSION_LEVEL_DEFAULT, pool);
   SVN_ERR(svn_txdelta_send_txstream(delta_stream, wh, whb, pool));
 
   /* Get the length of the temporary file and rewind it. */

Modified: subversion/branches/ev2-export/subversion/libsvn_repos/fs-wrap.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/fs-wrap.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/fs-wrap.c Sun Oct 21 02:00:31 2012
@@ -31,10 +31,12 @@
 #include "svn_props.h"
 #include "svn_repos.h"
 #include "svn_time.h"
+#include "svn_sorts.h"
 #include "repos.h"
 #include "svn_private_config.h"
 #include "private/svn_repos_private.h"
 #include "private/svn_utf_private.h"
+#include "private/svn_fspath.h"
 
 
 /*** Commit wrappers ***/
@@ -48,6 +50,9 @@ svn_repos_fs_commit_txn(const char **con
 {
   svn_error_t *err, *err2;
   const char *txn_name;
+  apr_hash_t *props;
+  apr_pool_t *iterpool;
+  apr_hash_index_t *hi;
 
   *new_rev = SVN_INVALID_REVNUM;
 
@@ -55,6 +60,24 @@ svn_repos_fs_commit_txn(const char **con
   SVN_ERR(svn_fs_txn_name(&txn_name, txn, pool));
   SVN_ERR(svn_repos__hooks_pre_commit(repos, txn_name, pool));
 
+  /* Remove any ephemeral transaction properties. */
+  SVN_ERR(svn_fs_txn_proplist(&props, txn, pool));
+  iterpool = svn_pool_create(pool);
+  for (hi = apr_hash_first(pool, props); hi; hi = apr_hash_next(hi))
+    {
+      const void *key;
+      apr_hash_this(hi, &key, NULL, NULL);
+
+      svn_pool_clear(iterpool);
+
+      if (strncmp(key, SVN_PROP_TXN_PREFIX,
+                  (sizeof(SVN_PROP_TXN_PREFIX) - 1)) == 0)
+        {
+          SVN_ERR(svn_fs_change_txn_prop(txn, key, NULL, iterpool));
+        }
+    }
+  svn_pool_destroy(iterpool);
+  
   /* Commit. */
   err = svn_fs_commit_txn(conflict_p, new_rev, txn, pool);
   if (! SVN_IS_VALID_REVNUM(*new_rev))
@@ -83,23 +106,29 @@ svn_repos_fs_begin_txn_for_commit2(svn_f
                                    apr_hash_t *revprop_table,
                                    apr_pool_t *pool)
 {
-  svn_string_t *author = apr_hash_get(revprop_table, SVN_PROP_REVISION_AUTHOR,
-                                      APR_HASH_KEY_STRING);
   apr_array_header_t *revprops;
+  const char *txn_name;
+  svn_string_t *author = apr_hash_get(revprop_table,
+                                      SVN_PROP_REVISION_AUTHOR,
+                                      APR_HASH_KEY_STRING);
 
-  /* Run start-commit hooks. */
-  SVN_ERR(svn_repos__hooks_start_commit(repos, author ? author->data : NULL,
-                                        repos->client_capabilities, pool));
-
-  /* Begin the transaction, ask for the fs to do on-the-fly lock checks. */
+  /* Begin the transaction, ask for the fs to do on-the-fly lock checks.
+     We fetch its name, too, so the start-commit hook can use it.  */
   SVN_ERR(svn_fs_begin_txn2(txn_p, repos->fs, rev,
                             SVN_FS_TXN_CHECK_LOCKS, pool));
+  SVN_ERR(svn_fs_txn_name(&txn_name, *txn_p, pool));
 
   /* We pass the revision properties to the filesystem by adding them
      as properties on the txn.  Later, when we commit the txn, these
      properties will be copied into the newly created revision. */
   revprops = svn_prop_hash_to_array(revprop_table, pool);
-  return svn_repos_fs_change_txn_props(*txn_p, revprops, pool);
+  SVN_ERR(svn_repos_fs_change_txn_props(*txn_p, revprops, pool));
+
+  /* Run start-commit hooks. */
+  SVN_ERR(svn_repos__hooks_start_commit(repos, author ? author->data : NULL,
+                                        repos->client_capabilities, txn_name,
+                                        pool));
+  return SVN_NO_ERROR;
 }
 
 
@@ -364,9 +393,9 @@ svn_repos_fs_revision_prop(svn_string_t 
     {
       /* Only svn:author and svn:date are fetchable. */
       if ((strncmp(propname, SVN_PROP_REVISION_AUTHOR,
-                   strlen(SVN_PROP_REVISION_AUTHOR)) != 0)
+                   sizeof(SVN_PROP_REVISION_AUTHOR)-1) != 0)
           && (strncmp(propname, SVN_PROP_REVISION_DATE,
-                      strlen(SVN_PROP_REVISION_DATE)) != 0))
+                      sizeof(SVN_PROP_REVISION_DATE)-1) != 0))
         *value_p = NULL;
 
       else
@@ -659,8 +688,8 @@ svn_repos_fs_get_mergeinfo(svn_mergeinfo
      the change itself. */
   /* ### TODO(reint): ... but how about descendant merged-to paths? */
   if (readable_paths->nelts > 0)
-    SVN_ERR(svn_fs_get_mergeinfo(mergeinfo, root, readable_paths, inherit,
-                                 include_descendants, pool));
+    SVN_ERR(svn_fs_get_mergeinfo2(mergeinfo, root, readable_paths, inherit,
+                                  include_descendants, TRUE, pool, pool));
   else
     *mergeinfo = apr_hash_make(pool);
 
@@ -710,7 +739,54 @@ svn_repos_fs_pack2(svn_repos_t *repos,
                      cancel_func, cancel_baton, pool);
 }
 
+svn_error_t *
+svn_repos_fs_get_inherited_props(apr_array_header_t **inherited_props_p,
+                                 svn_fs_root_t *root,
+                                 const char *path,
+                                 svn_repos_authz_func_t authz_read_func,
+                                 void *authz_read_baton,
+                                 apr_pool_t *result_pool,
+                                 apr_pool_t *scratch_pool)
+{
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  apr_array_header_t *inherited_props;
+  const char *parent_path = path;
+
+  inherited_props = apr_array_make(result_pool, 1,
+                                   sizeof(svn_prop_inherited_item_t *));
+  while (!(parent_path[0] == '/' && parent_path[1] == '\0'))
+    {
+      svn_boolean_t allowed = TRUE;
+      apr_hash_t *parent_properties;
+
+      svn_pool_clear(iterpool);
+      parent_path = svn_fspath__dirname(parent_path, iterpool);
+
+      if (authz_read_func)
+        SVN_ERR(authz_read_func(&allowed, root, parent_path,
+                                authz_read_baton, iterpool));
+      if (allowed)
+        {
+          SVN_ERR(svn_fs_node_proplist(&parent_properties, root,
+                                       parent_path, result_pool));
+          if (parent_properties && apr_hash_count(parent_properties))
+            {
+              svn_prop_inherited_item_t *i_props =
+                apr_pcalloc(result_pool, sizeof(*i_props));
+              i_props->path_or_url =
+                apr_pstrdup(result_pool, parent_path + 1);
+              i_props->prop_hash = parent_properties;
+              /* Build the output array in depth-first order. */
+              svn_sort__array_insert(&i_props, inherited_props, 0);
+            }
+        }
+    }
+
+  svn_pool_destroy(iterpool);
 
+  *inherited_props_p = inherited_props;
+  return SVN_NO_ERROR;
+}
 
 /*
  * vim:ts=4:sw=2:expandtab:tw=80:fo=tcroq

Modified: subversion/branches/ev2-export/subversion/libsvn_repos/hooks.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/hooks.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/hooks.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/hooks.c Sun Oct 21 02:00:31 2012
@@ -215,6 +215,7 @@ run_hook_cmd(svn_string_t **result,
   svn_error_t *err;
   apr_proc_t cmd_proc = {0};
   apr_pool_t *cmd_pool;
+  apr_hash_t *hook_env = NULL;
 
   if (result)
     {
@@ -234,8 +235,19 @@ run_hook_cmd(svn_string_t **result,
    * destroy in order to clean up the stderr pipe opened for the process. */
   cmd_pool = svn_pool_create(pool);
 
+  /* Check if a custom environment is defined for this hook, or else
+   * whether a default environment is defined. */
+  if (hooks_env)
+    {
+      hook_env = apr_hash_get(hooks_env, name, APR_HASH_KEY_STRING);
+      if (hook_env == NULL)
+        hook_env = apr_hash_get(hooks_env,
+                                SVN_REPOS__HOOKS_ENV_DEFAULT_SECTION,
+                                APR_HASH_KEY_STRING);
+    }
+    
   err = svn_io_start_cmd3(&cmd_proc, ".", cmd, args,
-                          env_from_env_hash(hooks_env, pool, pool),
+                          env_from_env_hash(hook_env, pool, pool),
                           FALSE, FALSE, stdin_handle, result != NULL,
                           null_handle, TRUE, NULL, cmd_pool);
   if (!err)
@@ -357,6 +369,7 @@ svn_error_t *
 svn_repos__hooks_start_commit(svn_repos_t *repos,
                               const char *user,
                               const apr_array_header_t *capabilities,
+                              const char *txn_name,
                               apr_pool_t *pool)
 {
   const char *hook = svn_repos_start_commit_hook(repos, pool);
@@ -368,7 +381,7 @@ svn_repos__hooks_start_commit(svn_repos_
     }
   else if (hook)
     {
-      const char *args[5];
+      const char *args[6];
       char *capabilities_string;
 
       if (capabilities)
@@ -388,7 +401,8 @@ svn_repos__hooks_start_commit(svn_repos_
       args[1] = svn_dirent_local_style(svn_repos_path(repos, pool), pool);
       args[2] = user ? user : "";
       args[3] = capabilities_string;
-      args[4] = NULL;
+      args[4] = txn_name;
+      args[5] = NULL;
 
       SVN_ERR(run_hook_cmd(NULL, SVN_REPOS__HOOK_START_COMMIT, hook, args,
                            repos->hooks_env, NULL, pool));

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=1400556&r1=1400555&r2=1400556&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 Sun Oct 21 02:00:31 2012
@@ -264,7 +264,7 @@ renumber_mergeinfo_revs(svn_string_t **f
   for (hi = apr_hash_first(subpool, mergeinfo); hi; hi = apr_hash_next(hi))
     {
       const char *merge_source;
-      apr_array_header_t *rangelist;
+      svn_rangelist_t *rangelist;
       struct parse_baton *pb = rb->pb;
       int i;
       const void *key;

Modified: subversion/branches/ev2-export/subversion/libsvn_repos/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/log.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/log.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/log.c Sun Oct 21 02:00:31 2012
@@ -39,6 +39,7 @@
 #include "repos.h"
 #include "private/svn_fspath.h"
 #include "private/svn_mergeinfo_private.h"
+#include "private/svn_subr_private.h"
 
 
 
@@ -159,6 +160,10 @@ svn_repos_check_revision_access(svn_repo
  * The CHANGED hash set and its keys and values are allocated in POOL;
  * keys are const char * paths and values are svn_log_changed_path_t.
  *
+ * To prevent changes from being processed over and over again, the
+ * changed paths for ROOT may be passed in PREFETCHED_CHANGES.  If the
+ * latter is NULL, we will request the list inside this function.
+ *
  * If optional AUTHZ_READ_FUNC is non-NULL, then use it (with
  * AUTHZ_READ_BATON and FS) to check whether each changed-path (and
  * copyfrom_path) is readable:
@@ -177,18 +182,20 @@ static svn_error_t *
 detect_changed(apr_hash_t **changed,
                svn_fs_root_t *root,
                svn_fs_t *fs,
+               apr_hash_t *prefetched_changes,
                svn_repos_authz_func_t authz_read_func,
                void *authz_read_baton,
                apr_pool_t *pool)
 {
-  apr_hash_t *changes;
+  apr_hash_t *changes = prefetched_changes;
   apr_hash_index_t *hi;
   apr_pool_t *subpool;
   svn_boolean_t found_readable = FALSE;
   svn_boolean_t found_unreadable = FALSE;
 
-  *changed = apr_hash_make(pool);
-  SVN_ERR(svn_fs_paths_changed2(&changes, root, pool));
+  *changed = svn_hash__make(pool);
+  if (changes == NULL)
+    SVN_ERR(svn_fs_paths_changed2(&changes, root, pool));
 
   if (apr_hash_count(changes) == 0)
     /* No paths changed in this revision?  Uh, sure, I guess the
@@ -551,26 +558,28 @@ next_history_rev(const apr_array_header_
 
 /* Set *DELETED_MERGEINFO_CATALOG and *ADDED_MERGEINFO_CATALOG to
    catalogs describing how mergeinfo values on paths (which are the
-   keys of those catalogs) were changed in REV. */
+   keys of those catalogs) were changed in REV.  If *PREFETCHED_CAHNGES
+   already contains the changed paths for REV, use that.  Otherwise,
+   request that data and return it in *PREFETCHED_CHANGES. */
 /* ### TODO: This would make a *great*, useful public function,
    ### svn_repos_fs_mergeinfo_changed()!  -- cmpilato  */
 static svn_error_t *
 fs_mergeinfo_changed(svn_mergeinfo_catalog_t *deleted_mergeinfo_catalog,
                      svn_mergeinfo_catalog_t *added_mergeinfo_catalog,
+                     apr_hash_t **prefetched_changes,
                      svn_fs_t *fs,
                      svn_revnum_t rev,
                      apr_pool_t *result_pool,
                      apr_pool_t *scratch_pool)
 
 {
-  apr_hash_t *changes;
   svn_fs_root_t *root;
   apr_pool_t *iterpool;
   apr_hash_index_t *hi;
 
   /* Initialize return variables. */
-  *deleted_mergeinfo_catalog = apr_hash_make(result_pool);
-  *added_mergeinfo_catalog = apr_hash_make(result_pool);
+  *deleted_mergeinfo_catalog = svn_hash__make(result_pool);
+  *added_mergeinfo_catalog = svn_hash__make(result_pool);
 
   /* Revision 0 has no mergeinfo and no mergeinfo changes. */
   if (rev == 0)
@@ -579,17 +588,20 @@ fs_mergeinfo_changed(svn_mergeinfo_catal
   /* We're going to use the changed-paths information for REV to
      narrow down our search. */
   SVN_ERR(svn_fs_revision_root(&root, fs, rev, scratch_pool));
-  SVN_ERR(svn_fs_paths_changed2(&changes, root, scratch_pool));
+  if (*prefetched_changes == NULL)
+    SVN_ERR(svn_fs_paths_changed2(prefetched_changes, root, scratch_pool));
 
   /* No changed paths?  We're done. */
-  if (apr_hash_count(changes) == 0)
+  if (apr_hash_count(*prefetched_changes) == 0)
     return SVN_NO_ERROR;
 
   /* Loop over changes, looking for anything that might carry an
      svn:mergeinfo change and is one of our paths of interest, or a
      child or [grand]parent directory thereof. */
   iterpool = svn_pool_create(scratch_pool);
-  for (hi = apr_hash_first(scratch_pool, changes); hi; hi = apr_hash_next(hi))
+  for (hi = apr_hash_first(scratch_pool, *prefetched_changes); 
+       hi;
+       hi = apr_hash_next(hi))
     {
       const void *key;
       void *val;
@@ -769,10 +781,14 @@ fs_mergeinfo_changed(svn_mergeinfo_catal
 /* Determine what (if any) mergeinfo for PATHS was modified in
    revision REV, returning the differences for added mergeinfo in
    *ADDED_MERGEINFO and deleted mergeinfo in *DELETED_MERGEINFO.
+   If *PREFETCHED_CAHNGES already contains the changed paths for
+   REV, use that.  Otherwise, request that data and return it in
+   *PREFETCHED_CHANGES.
    Use POOL for all allocations. */
 static svn_error_t *
 get_combined_mergeinfo_changes(svn_mergeinfo_t *added_mergeinfo,
                                svn_mergeinfo_t *deleted_mergeinfo,
+                               apr_hash_t **prefetched_changes,
                                svn_fs_t *fs,
                                const apr_array_header_t *paths,
                                svn_revnum_t rev,
@@ -787,8 +803,8 @@ get_combined_mergeinfo_changes(svn_merge
   svn_error_t *err;
 
   /* Initialize return value. */
-  *added_mergeinfo = apr_hash_make(result_pool);
-  *deleted_mergeinfo = apr_hash_make(result_pool);
+  *added_mergeinfo = svn_hash__make(result_pool);
+  *deleted_mergeinfo = svn_hash__make(result_pool);
 
   /* If we're asking about revision 0, there's no mergeinfo to be found. */
   if (rev == 0)
@@ -804,6 +820,7 @@ get_combined_mergeinfo_changes(svn_merge
   /* Fetch the mergeinfo changes for REV. */
   err = fs_mergeinfo_changed(&deleted_mergeinfo_catalog,
                              &added_mergeinfo_catalog,
+                             prefetched_changes,
                              fs, rev, scratch_pool, scratch_pool);
   if (err)
     {
@@ -829,6 +846,7 @@ get_combined_mergeinfo_changes(svn_merge
     {
       const char *path = APR_ARRAY_IDX(paths, i, const char *);
       const char *prev_path;
+      apr_ssize_t klen;
       svn_revnum_t appeared_rev, prev_rev;
       svn_fs_root_t *prev_root;
       svn_mergeinfo_catalog_t catalog, inherited_catalog;
@@ -899,8 +917,9 @@ get_combined_mergeinfo_changes(svn_merge
                                     FALSE, /* adjust_inherited_mergeinfo */
                                     iterpool, iterpool));
 
-      prev_mergeinfo = apr_hash_get(catalog, prev_path, APR_HASH_KEY_STRING);
-      prev_inherited_mergeinfo = apr_hash_get(inherited_catalog, prev_path, APR_HASH_KEY_STRING);
+      klen = strlen(prev_path);
+      prev_mergeinfo = apr_hash_get(catalog, prev_path, klen);
+      prev_inherited_mergeinfo = apr_hash_get(inherited_catalog, prev_path, klen);
 
       /* Fetch the current mergeinfo (as of REV, and including
          inherited stuff) for this path. */
@@ -915,8 +934,9 @@ get_combined_mergeinfo_changes(svn_merge
                                     FALSE, /* adjust_inherited_mergeinfo */
                                     iterpool, iterpool));
 
-      mergeinfo = apr_hash_get(catalog, path, APR_HASH_KEY_STRING);
-      inherited_mergeinfo = apr_hash_get(inherited_catalog, path, APR_HASH_KEY_STRING);
+      klen = strlen(path);
+      mergeinfo = apr_hash_get(catalog, path, klen);
+      inherited_mergeinfo = apr_hash_get(inherited_catalog, path, klen);
 
       if (!prev_mergeinfo && !mergeinfo)
         continue;
@@ -935,6 +955,16 @@ get_combined_mergeinfo_changes(svn_merge
           if (inherits_same_mergeinfo)
             continue;
         }
+      else
+        {
+          svn_boolean_t same_mergeinfo;
+          SVN_ERR(svn_mergeinfo__equals(&same_mergeinfo,
+                                        prev_inherited_mergeinfo,
+                                        FALSE,
+                                        TRUE, iterpool));
+          if (same_mergeinfo)
+            continue;
+        }
 
       /* Compare, constrast, and combine the results. */
       SVN_ERR(svn_mergeinfo_diff2(&deleted, &added, prev_mergeinfo,
@@ -989,6 +1019,7 @@ static svn_error_t *
 fill_log_entry(svn_log_entry_t *log_entry,
                svn_revnum_t rev,
                svn_fs_t *fs,
+               apr_hash_t *prefetched_changes,
                svn_boolean_t discover_changed_paths,
                const apr_array_header_t *revprops,
                svn_repos_authz_func_t authz_read_func,
@@ -1008,7 +1039,7 @@ fill_log_entry(svn_log_entry_t *log_entr
 
       SVN_ERR(svn_fs_revision_root(&newroot, fs, rev, pool));
       patherr = detect_changed(&changed_paths,
-                               newroot, fs,
+                               newroot, fs, prefetched_changes,
                                authz_read_func, authz_read_baton,
                                pool);
 
@@ -1048,7 +1079,7 @@ fill_log_entry(svn_log_entry_t *log_entr
           if (censor_revprops)
             {
               /* ... but we can only return author/date. */
-              log_entry->revprops = apr_hash_make(pool);
+              log_entry->revprops = svn_hash__make(pool);
               apr_hash_set(log_entry->revprops, SVN_PROP_REVISION_AUTHOR,
                            APR_HASH_KEY_STRING,
                            apr_hash_get(r_props, SVN_PROP_REVISION_AUTHOR,
@@ -1077,7 +1108,7 @@ fill_log_entry(svn_log_entry_t *log_entr
                 /* ... but we can only return author/date. */
                 continue;
               if (log_entry->revprops == NULL)
-                log_entry->revprops = apr_hash_make(pool);
+                log_entry->revprops = svn_hash__make(pool);
               apr_hash_set(log_entry->revprops, name,
                            APR_HASH_KEY_STRING, value);
             }
@@ -1119,6 +1150,7 @@ fill_log_entry(svn_log_entry_t *log_entr
 static svn_error_t *
 send_log(svn_revnum_t rev,
          svn_fs_t *fs,
+         apr_hash_t *prefetched_changes,
          svn_mergeinfo_t log_target_history_as_mergeinfo,
          apr_hash_t *nested_merges,
          svn_boolean_t discover_changed_paths,
@@ -1137,7 +1169,7 @@ send_log(svn_revnum_t rev,
   svn_boolean_t found_rev_of_interest = TRUE;
 
   log_entry = svn_log_entry_create(pool);
-  SVN_ERR(fill_log_entry(log_entry, rev, fs,
+  SVN_ERR(fill_log_entry(log_entry, rev, fs, prefetched_changes,
                          discover_changed_paths || handling_merged_revision,
                          revprops, authz_read_func, authz_read_baton,
                          pool));
@@ -1177,7 +1209,7 @@ send_log(svn_revnum_t rev,
             {
               const char *mergeinfo_path =
                 svn__apr_hash_index_key(hi2);
-              apr_array_header_t *rangelist =
+              svn_rangelist_t *rangelist =
                 svn__apr_hash_index_val(hi2);
 
               /* Check whether CHANGED_PATH at revision REV is a child of
@@ -1397,7 +1429,7 @@ struct path_list_range
    the paths can be accessed by revision. */
 struct rangelist_path
 {
-  apr_array_header_t *rangelist;
+  svn_rangelist_t *rangelist;
   const char *path;
 };
 
@@ -1735,8 +1767,8 @@ reduce_search(apr_array_header_t *paths,
   for (i = 0; i < paths->nelts; ++i)
     {
       const char *path = APR_ARRAY_IDX(paths, i, const char *);
-      apr_array_header_t *ranges = apr_hash_get(processed, path,
-                                                APR_HASH_KEY_STRING);
+      svn_rangelist_t *ranges = apr_hash_get(processed, path,
+                                             APR_HASH_KEY_STRING);
       int j;
 
       if (!ranges)
@@ -1800,15 +1832,15 @@ store_search(svn_mergeinfo_t processed,
      singe revisions where HIST_START is equal to HIST_END. */
   svn_revnum_t start = hist_start <= hist_end ? hist_start : hist_end;
   svn_revnum_t end = hist_start <= hist_end ? hist_end + 1 : hist_start + 1;
-  svn_mergeinfo_t mergeinfo = apr_hash_make(scratch_pool);
+  svn_mergeinfo_t mergeinfo = svn_hash__make(scratch_pool);
   apr_pool_t *processed_pool = apr_hash_pool_get(processed);
   int i;
 
   for (i = 0; i < paths->nelts; ++i)
     {
       const char *path = APR_ARRAY_IDX(paths, i, const char *);
-      apr_array_header_t *ranges = apr_array_make(processed_pool, 1,
-                                                  sizeof(svn_merge_range_t*));
+      svn_rangelist_t *ranges = apr_array_make(processed_pool, 1,
+                                               sizeof(svn_merge_range_t*));
       svn_merge_range_t *range = apr_palloc(processed_pool,
                                             sizeof(svn_merge_range_t));
 
@@ -1941,6 +1973,7 @@ do_logs(svn_fs_t *fs,
           svn_mergeinfo_t added_mergeinfo = NULL;
           svn_mergeinfo_t deleted_mergeinfo = NULL;
           svn_boolean_t has_children = FALSE;
+          apr_hash_t *changes = NULL;
 
           /* If we're including merged revisions, we need to calculate
              the mergeinfo deltas committed in this revision to our
@@ -1961,6 +1994,7 @@ do_logs(svn_fs_t *fs,
                 }
               SVN_ERR(get_combined_mergeinfo_changes(&added_mergeinfo,
                                                      &deleted_mergeinfo,
+                                                     &changes,
                                                      fs, cur_paths,
                                                      current, iterpool,
                                                      iterpool));
@@ -1973,7 +2007,7 @@ do_logs(svn_fs_t *fs,
              in anyway). */
           if (descending_order)
             {
-              SVN_ERR(send_log(current, fs,
+              SVN_ERR(send_log(current, fs, changes,
                                log_target_history_as_mergeinfo, nested_merges,
                                discover_changed_paths,
                                subtractive_merge, handling_merged_revisions,
@@ -1989,8 +2023,8 @@ do_logs(svn_fs_t *fs,
                          single hash to be shared across all of the merged
                          recursions so we can track and squelch duplicates. */
                       subpool = svn_pool_create(pool);
-                      nested_merges = apr_hash_make(subpool);
-                      processed = apr_hash_make(subpool);
+                      nested_merges = svn_hash__make(subpool);
+                      processed = svn_hash__make(subpool);
                     }
 
                   SVN_ERR(handle_merged_revisions(
@@ -2035,7 +2069,7 @@ do_logs(svn_fs_t *fs,
 
                   *cur_rev = current;
                   if (! rev_mergeinfo)
-                    rev_mergeinfo = apr_hash_make(pool);
+                    rev_mergeinfo = svn_hash__make(pool);
                   apr_hash_set(rev_mergeinfo, cur_rev, sizeof(*cur_rev),
                                add_and_del_mergeinfo);
                 }
@@ -2078,8 +2112,8 @@ do_logs(svn_fs_t *fs,
                               || apr_hash_count(deleted_mergeinfo) > 0);
             }
 
-          SVN_ERR(send_log(current, fs, log_target_history_as_mergeinfo,
-                           nested_merges,
+          SVN_ERR(send_log(current, fs, NULL,
+                           log_target_history_as_mergeinfo, nested_merges,
                            discover_changed_paths, subtractive_merge,
                            handling_merged_revisions, revprops, has_children,
                            receiver, receiver_baton, authz_read_func,
@@ -2089,7 +2123,7 @@ do_logs(svn_fs_t *fs,
               if (!nested_merges)
                 {
                   subpool = svn_pool_create(pool);
-                  nested_merges = apr_hash_make(subpool);
+                  nested_merges = svn_hash__make(subpool);
                 }
 
               SVN_ERR(handle_merged_revisions(current, fs,
@@ -2169,7 +2203,7 @@ get_paths_history_as_mergeinfo(svn_merge
       end_rev = tmp_rev;
     }
 
-  *paths_history_mergeinfo = apr_hash_make(result_pool);
+  *paths_history_mergeinfo = svn_hash__make(result_pool);
 
   for (i = 0; i < paths->nelts; i++)
     {
@@ -2302,7 +2336,8 @@ svn_repos_get_logs4(svn_repos_t *repos,
             rev = end - i;
           else
             rev = start + i;
-          SVN_ERR(send_log(rev, fs, NULL, NULL, discover_changed_paths, FALSE,
+          SVN_ERR(send_log(rev, fs, NULL, NULL, NULL,
+                           discover_changed_paths, FALSE,
                            FALSE, revprops, FALSE, receiver,
                            receiver_baton, authz_read_func,
                            authz_read_baton, iterpool));

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=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/replay.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/replay.c Sun Oct 21 02:00:31 2012
@@ -150,7 +150,6 @@ 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
@@ -342,7 +341,6 @@ 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
@@ -459,7 +457,6 @@ 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,
@@ -784,8 +781,6 @@ 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,
@@ -795,8 +790,14 @@ fetch_kind_func(svn_kind_t *kind,
 {
   svn_fs_root_t *root = baton;
   svn_node_kind_t node_kind;
+  svn_fs_root_t *prev_root;
+  svn_fs_t *fs = svn_fs_root_fs(root);
 
-  SVN_ERR(svn_fs_check_path(&node_kind, root, path, scratch_pool));
+  if (!SVN_IS_VALID_REVNUM(base_revision))
+    base_revision = svn_fs_revision_root_revision(root) - 1;
+
+  SVN_ERR(svn_fs_revision_root(&prev_root, fs, base_revision, scratch_pool));
+  SVN_ERR(svn_fs_check_path(&node_kind, prev_root, path, scratch_pool));
 
   *kind = svn__kind_from_node_kind(node_kind, FALSE);
   return SVN_NO_ERROR;
@@ -814,17 +815,15 @@ fetch_props_func(apr_hash_t **props,
   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));
+  if (!SVN_IS_VALID_REVNUM(base_revision))
+    base_revision = svn_fs_revision_root_revision(root) - 1;
 
+  SVN_ERR(svn_fs_revision_root(&prev_root, fs, base_revision, scratch_pool));
   SVN_ERR(svn_fs_node_proplist(props, prev_root, path, result_pool));
 
   return SVN_NO_ERROR;
 }
 
-#endif
-
 
 
 
@@ -1009,7 +1008,6 @@ 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
@@ -1018,16 +1016,16 @@ svn_repos_replay2(svn_fs_root_t *root,
    unavailable because of authz and we need to use it as the source of
    a copy. */
 static svn_error_t *
-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)
+add_subdir_ev2(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;
@@ -1131,11 +1129,11 @@ add_subdir(svn_fs_root_t *source_root,
             }
           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));
+              SVN_ERR(add_subdir_ev2(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)
@@ -1164,7 +1162,6 @@ add_subdir(svn_fs_root_t *source_root,
 
   return SVN_NO_ERROR;
 }
-#endif
 
 static svn_error_t *
 replay_node(svn_fs_root_t *root,
@@ -1178,11 +1175,6 @@ replay_node(svn_fs_root_t *root,
             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;
@@ -1297,10 +1289,11 @@ replay_node(svn_fs_root_t *root,
              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));
+              SVN_ERR(add_subdir_ev2(copyfrom_root, root, editor,
+                                     repos_relpath, change->copyfrom_path,
+                                     authz_read_func, authz_read_baton,
+                                     changed_paths, result_pool,
+                                     scratch_pool));
             }
           else
             {
@@ -1437,15 +1430,18 @@ replay_node(svn_fs_root_t *root,
       if (change->node_kind == svn_node_file
           && (change->text_mod || change->prop_mod || downgraded_copy))
         {
-          svn_checksum_t *checksum;
-          svn_stream_t *contents;
+          svn_checksum_t *checksum = NULL;
+          svn_stream_t *contents = NULL;
 
-          SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1,
-                                       root, repos_relpath, TRUE,
-                                       scratch_pool));
+          if (change->text_mod)
+            {
+              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_fs_file_contents(&contents, root, repos_relpath,
+                                           scratch_pool));
+            }
 
           SVN_ERR(svn_editor_alter_file(editor, repos_relpath,
                                         SVN_INVALID_REVNUM, props, checksum,
@@ -1465,7 +1461,6 @@ replay_node(svn_fs_root_t *root,
 
   return SVN_NO_ERROR;
 }
-#endif
 
 svn_error_t *
 svn_repos__replay_ev2(svn_fs_root_t *root,



Mime
View raw message