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

svn commit: r1373783 [23/50] - in /subversion/branches/compressed-pristines: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ contrib/client-side/emacs/ contrib/client-side/svn-push/ contrib/client-side/svnmerge/ cont...

Modified: subversion/branches/compressed-pristines/subversion/libsvn_ra_svn/marshal.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_ra_svn/marshal.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra_svn/marshal.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra_svn/marshal.c Thu Aug 16 10:17:48 2012
@@ -439,6 +439,8 @@ static svn_error_t *write_number(svn_ra_
 {
   apr_size_t written;
 
+  /* SVN_INT64_BUFFER_SIZE includes space for a terminating NUL that
+   * svn__ui64toa will always append. */
   if (conn->write_pos + SVN_INT64_BUFFER_SIZE >= sizeof(conn->write_buf))
     SVN_ERR(writebuf_flush(conn, pool));
 
@@ -460,11 +462,11 @@ 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
-    write_number(conn, pool, str->len, ':');
+    SVN_ERR(write_number(conn, pool, str->len, ':'));
 
   SVN_ERR(writebuf_write(conn, pool, str->data, str->len));
   SVN_ERR(writebuf_writechar(conn, pool, ' '));
@@ -478,11 +480,11 @@ 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
-    write_number(conn, pool, len, ':');
+    SVN_ERR(write_number(conn, pool, len, ':'));
 
   SVN_ERR(writebuf_write(conn, pool, s, len));
   SVN_ERR(writebuf_writechar(conn, pool, ' '));
@@ -697,7 +699,7 @@ static svn_error_t *read_string(svn_ra_s
               ? len
               : SUSPICIOUSLY_HUGE_STRING_SIZE_THRESHOLD;
 
-      svn_stringbuf_ensure(stringbuf, stringbuf->len + readbuf_len + 1);
+      svn_stringbuf_ensure(stringbuf, stringbuf->len + readbuf_len);
       dest = stringbuf->data + stringbuf->len;
     }
 
@@ -1148,10 +1150,7 @@ svn_error_t *svn_ra_svn_write_cmd(svn_ra
   va_start(ap, fmt);
   err = vwrite_tuple(conn, pool, fmt, ap);
   va_end(ap);
-  if (err)
-    return err;
-  SVN_ERR(svn_ra_svn_end_list(conn, pool));
-  return SVN_NO_ERROR;
+  return err ? svn_error_trace(err) : svn_ra_svn_end_list(conn, pool);
 }
 
 svn_error_t *svn_ra_svn_write_cmd_response(svn_ra_svn_conn_t *conn,
@@ -1161,24 +1160,18 @@ svn_error_t *svn_ra_svn_write_cmd_respon
   va_list ap;
   svn_error_t *err;
 
-  SVN_ERR(svn_ra_svn_start_list(conn, pool));
-  SVN_ERR(svn_ra_svn_write_word(conn, pool, "success"));
+  SVN_ERR(writebuf_write_short_string(conn, pool, "( success ", 10));
   va_start(ap, fmt);
   err = vwrite_tuple(conn, pool, fmt, ap);
   va_end(ap);
-  if (err)
-    return err;
-  SVN_ERR(svn_ra_svn_end_list(conn, pool));
-  return SVN_NO_ERROR;
+  return err ? svn_error_trace(err) : svn_ra_svn_end_list(conn, pool);
 }
 
 svn_error_t *svn_ra_svn_write_cmd_failure(svn_ra_svn_conn_t *conn,
                                           apr_pool_t *pool, svn_error_t *err)
 {
   char buffer[128];
-  SVN_ERR(svn_ra_svn_start_list(conn, pool));
-  SVN_ERR(svn_ra_svn_write_word(conn, pool, "failure"));
-  SVN_ERR(svn_ra_svn_start_list(conn, pool));
+  SVN_ERR(writebuf_write_short_string(conn, pool, "( failure ( ", 12));
   for (; err; err = err->child)
     {
       const char *msg;
@@ -1198,7 +1191,5 @@ svn_error_t *svn_ra_svn_write_cmd_failur
                                      err->file ? err->file : "",
                                      (apr_uint64_t) err->line));
     }
-  SVN_ERR(svn_ra_svn_end_list(conn, pool));
-  SVN_ERR(svn_ra_svn_end_list(conn, pool));
-  return SVN_NO_ERROR;
+  return writebuf_write_short_string(conn, pool, ") ) ", 4);
 }

Modified: subversion/branches/compressed-pristines/subversion/libsvn_ra_svn/ra_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_ra_svn/ra_svn.h?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_ra_svn/ra_svn.h (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_ra_svn/ra_svn.h Thu Aug 16 10:17:48 2012
@@ -57,8 +57,8 @@ typedef svn_error_t *(*ra_svn_block_hand
                                                void *baton);
 
 /* 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__READBUF_SIZE (4*4096)
+#define SVN_RA_SVN__WRITEBUF_SIZE (4*4096)
 
 /* Create forward reference */
 typedef struct svn_ra_svn__session_baton_t svn_ra_svn__session_baton_t;

Modified: subversion/branches/compressed-pristines/subversion/libsvn_repos/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_repos/commit.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_repos/commit.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_repos/commit.c Thu Aug 16 10:17:48 2012
@@ -37,8 +37,11 @@
 #include "svn_checksum.h"
 #include "svn_props.h"
 #include "svn_mergeinfo.h"
-#include "repos.h"
 #include "svn_private_config.h"
+#include "svn_editor.h"
+
+#include "repos.h"
+
 #include "private/svn_fspath.h"
 #include "private/svn_repos_private.h"
 
@@ -128,6 +131,29 @@ struct file_baton
 };
 
 
+struct ev2_baton
+{
+  /* The repository we are editing.  */
+  svn_repos_t *repos;
+
+  /* The authz baton for checks; NULL to skip authz.  */
+  svn_authz_t *authz;
+
+  /* The repository name and user for performing authz checks.  */
+  const char *authz_repos_name;
+  const char *authz_user;
+
+  /* Callback to provide info about the committed revision.  */
+  svn_commit_callback2_t commit_cb;
+  void *commit_baton;
+
+  /* The FS txn editor  */
+  svn_editor_t *inner;
+
+  /* The name of the open transaction (so we know what to commit)  */
+  const char *txn_name;
+};
+
 
 /* Create and return a generic out-of-dateness error. */
 static svn_error_t *
@@ -143,6 +169,40 @@ out_of_date(const char *path, svn_node_k
 }
 
 
+static svn_error_t *
+invoke_commit_cb(svn_commit_callback2_t commit_cb,
+                 void *commit_baton,
+                 svn_fs_t *fs,
+                 svn_revnum_t revision,
+                 const char *post_commit_errstr,
+                 apr_pool_t *scratch_pool)
+{
+  /* FS interface returns non-const values.  */
+  /* const */ svn_string_t *date;
+  /* const */ svn_string_t *author;
+  svn_commit_info_t *commit_info;
+
+  if (commit_cb == NULL)
+    return SVN_NO_ERROR;
+
+  SVN_ERR(svn_fs_revision_prop(&date, fs, revision, SVN_PROP_REVISION_DATE,
+                               scratch_pool));
+  SVN_ERR(svn_fs_revision_prop(&author, fs, revision,
+                               SVN_PROP_REVISION_AUTHOR,
+                               scratch_pool));
+
+  commit_info = svn_create_commit_info(scratch_pool);
+
+  /* fill up the svn_commit_info structure */
+  commit_info->revision = revision;
+  commit_info->date = date ? date->data : NULL;
+  commit_info->author = author ? author->data : NULL;
+  commit_info->post_commit_err = post_commit_errstr;
+
+  return svn_error_trace(commit_cb(commit_info, commit_baton, scratch_pool));
+}
+
+
 
 /* If EDITOR_BATON contains a valid authz callback, verify that the
    REQUIRED access to PATH in ROOT is authorized.  Return an error
@@ -631,7 +691,8 @@ svn_repos__post_commit_error_str(svn_err
   else
     hook_err2 = hook_err1;
 
-  /* This implementation counts on svn_repos_fs_commit_txn() returning
+  /* This implementation counts on svn_repos_fs_commit_txn() and
+     libsvn_repos/commit.c:complete_cb() returning
      svn_fs_commit_txn() as the parent error with a child
      SVN_ERR_REPOS_POST_COMMIT_HOOK_FAILED error.  If the parent error
      is SVN_ERR_REPOS_POST_COMMIT_HOOK_FAILED then there was no error
@@ -703,7 +764,6 @@ close_edit(void *edit_baton,
              display it as a warning) and clear the error. */
           post_commit_err = svn_repos__post_commit_error_str(err, pool);
           svn_error_clear(err);
-          err = SVN_NO_ERROR;
         }
     }
   else
@@ -730,41 +790,19 @@ close_edit(void *edit_baton,
                                          svn_fs_abort_txn(eb->txn, pool)));
     }
 
-  /* Pass new revision information to the caller's callback. */
-  {
-    svn_string_t *date, *author;
-    svn_commit_info_t *commit_info;
-
-    /* Even if there was a post-commit hook failure, it's more serious
-       if one of the calls here fails, so we explicitly check for errors
-       here, while saving the possible post-commit error for later. */
-
-    err = svn_fs_revision_prop(&date, svn_repos_fs(eb->repos),
-                                new_revision, SVN_PROP_REVISION_DATE,
-                                pool);
-    if (! err)
-      {
-        err = svn_fs_revision_prop(&author, svn_repos_fs(eb->repos),
-                                   new_revision, SVN_PROP_REVISION_AUTHOR,
-                                   pool);
-      }
-
-    if ((! err) && eb->commit_callback)
-      {
-        commit_info = svn_create_commit_info(pool);
-
-        /* fill up the svn_commit_info structure */
-        commit_info->revision = new_revision;
-        commit_info->date = date ? date->data : NULL;
-        commit_info->author = author ? author->data : NULL;
-        commit_info->post_commit_err = post_commit_err;
-        err = (*eb->commit_callback)(commit_info,
-                                     eb->commit_callback_baton,
-                                     pool);
-      }
-  }
+  /* At this point, the post-commit error has been converted to a string.
+     That information will be passed to a callback, if provided. If the
+     callback invocation fails in some way, that failure is returned here.
+     IOW, the post-commit error information is low priority compared to
+     other gunk here.  */
 
-  return svn_error_trace(err);
+  /* Pass new revision information to the caller's callback. */
+  return svn_error_trace(invoke_commit_cb(eb->commit_callback,
+                                          eb->commit_callback_baton,
+                                          eb->repos->fs,
+                                          new_revision,
+                                          post_commit_err,
+                                          pool));
 }
 
 
@@ -956,3 +994,373 @@ svn_repos_get_commit_editor5(const svn_d
 
   return SVN_NO_ERROR;
 }
+
+
+#if 0
+static svn_error_t *
+ev2_check_authz(const struct ev2_baton *eb,
+                const char *relpath,
+                svn_repos_authz_access_t required,
+                apr_pool_t *scratch_pool)
+{
+  const char *fspath;
+  svn_boolean_t allowed;
+
+  if (eb->authz == NULL)
+    return SVN_NO_ERROR;
+
+  if (relpath)
+    fspath = apr_pstrcat(scratch_pool, "/", relpath, NULL);
+  else
+    fspath = NULL;
+
+  SVN_ERR(svn_repos_authz_check_access(eb->authz, eb->authz_repos_name, fspath,
+                                       eb->authz_user, required,
+                                       &allowed, scratch_pool));
+  if (!allowed)
+    return svn_error_create(required & svn_authz_write
+                            ? SVN_ERR_AUTHZ_UNWRITABLE
+                            : SVN_ERR_AUTHZ_UNREADABLE,
+                            NULL, "Access denied");
+
+  return SVN_NO_ERROR;
+}
+#endif
+
+
+/* This implements svn_editor_cb_add_directory_t */
+static svn_error_t *
+add_directory_cb(void *baton,
+                 const char *relpath,
+                 const apr_array_header_t *children,
+                 apr_hash_t *props,
+                 svn_revnum_t replaces_rev,
+                 apr_pool_t *scratch_pool)
+{
+  struct ev2_baton *eb = baton;
+
+  SVN_ERR(svn_editor_add_directory(eb->inner, relpath, children, props,
+                                   replaces_rev));
+  return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_add_file_t */
+static svn_error_t *
+add_file_cb(void *baton,
+            const char *relpath,
+            const svn_checksum_t *checksum,
+            svn_stream_t *contents,
+            apr_hash_t *props,
+            svn_revnum_t replaces_rev,
+            apr_pool_t *scratch_pool)
+{
+  struct ev2_baton *eb = baton;
+
+  SVN_ERR(svn_editor_add_file(eb->inner, relpath, checksum, contents, props,
+                              replaces_rev));
+  return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_add_symlink_t */
+static svn_error_t *
+add_symlink_cb(void *baton,
+               const char *relpath,
+               const char *target,
+               apr_hash_t *props,
+               svn_revnum_t replaces_rev,
+               apr_pool_t *scratch_pool)
+{
+  struct ev2_baton *eb = baton;
+
+  SVN_ERR(svn_editor_add_symlink(eb->inner, relpath, target, props,
+                                 replaces_rev));
+  return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_add_absent_t */
+static svn_error_t *
+add_absent_cb(void *baton,
+              const char *relpath,
+              svn_kind_t kind,
+              svn_revnum_t replaces_rev,
+              apr_pool_t *scratch_pool)
+{
+  struct ev2_baton *eb = baton;
+
+  SVN_ERR(svn_editor_add_absent(eb->inner, relpath, kind, replaces_rev));
+  return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_alter_directory_t */
+static svn_error_t *
+alter_directory_cb(void *baton,
+                   const char *relpath,
+                   svn_revnum_t revision,
+                   const apr_array_header_t *children,
+                   apr_hash_t *props,
+                   apr_pool_t *scratch_pool)
+{
+  struct ev2_baton *eb = baton;
+
+  SVN_ERR(svn_editor_alter_directory(eb->inner, relpath, revision,
+                                     children, props));
+  return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_alter_file_t */
+static svn_error_t *
+alter_file_cb(void *baton,
+              const char *relpath,
+              svn_revnum_t revision,
+              apr_hash_t *props,
+              const svn_checksum_t *checksum,
+              svn_stream_t *contents,
+              apr_pool_t *scratch_pool)
+{
+  struct ev2_baton *eb = baton;
+
+  SVN_ERR(svn_editor_alter_file(eb->inner, relpath, revision, props,
+                                checksum, contents));
+  return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_alter_symlink_t */
+static svn_error_t *
+alter_symlink_cb(void *baton,
+                 const char *relpath,
+                 svn_revnum_t revision,
+                 apr_hash_t *props,
+                 const char *target,
+                 apr_pool_t *scratch_pool)
+{
+  struct ev2_baton *eb = baton;
+
+  SVN_ERR(svn_editor_alter_symlink(eb->inner, relpath, revision, props,
+                                   target));
+  return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_delete_t */
+static svn_error_t *
+delete_cb(void *baton,
+          const char *relpath,
+          svn_revnum_t revision,
+          apr_pool_t *scratch_pool)
+{
+  struct ev2_baton *eb = baton;
+
+  SVN_ERR(svn_editor_delete(eb->inner, relpath, revision));
+  return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_copy_t */
+static svn_error_t *
+copy_cb(void *baton,
+        const char *src_relpath,
+        svn_revnum_t src_revision,
+        const char *dst_relpath,
+        svn_revnum_t replaces_rev,
+        apr_pool_t *scratch_pool)
+{
+  struct ev2_baton *eb = baton;
+
+  SVN_ERR(svn_editor_copy(eb->inner, src_relpath, src_revision, dst_relpath,
+                          replaces_rev));
+  return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_move_t */
+static svn_error_t *
+move_cb(void *baton,
+        const char *src_relpath,
+        svn_revnum_t src_revision,
+        const char *dst_relpath,
+        svn_revnum_t replaces_rev,
+        apr_pool_t *scratch_pool)
+{
+  struct ev2_baton *eb = baton;
+
+  SVN_ERR(svn_editor_move(eb->inner, src_relpath, src_revision, dst_relpath,
+                          replaces_rev));
+  return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_rotate_t */
+static svn_error_t *
+rotate_cb(void *baton,
+          const apr_array_header_t *relpaths,
+          const apr_array_header_t *revisions,
+          apr_pool_t *scratch_pool)
+{
+  struct ev2_baton *eb = baton;
+
+  SVN_ERR(svn_editor_rotate(eb->inner, relpaths, revisions));
+  return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_complete_t */
+static svn_error_t *
+complete_cb(void *baton,
+            apr_pool_t *scratch_pool)
+{
+  struct ev2_baton *eb = baton;
+  svn_revnum_t revision;
+  svn_error_t *post_commit_err;
+  const char *conflict_path;
+  svn_error_t *err;
+  const char *post_commit_errstr;
+
+  /* The transaction has been fully edited. Let the pre-commit hook
+     have a look at the thing.  */
+  SVN_ERR(svn_repos__hooks_pre_commit(eb->repos, eb->txn_name, scratch_pool));
+
+  /* Hook is done. Let's do the actual commit.  */
+  SVN_ERR(svn_fs_editor_commit(&revision, &post_commit_err, &conflict_path,
+                               eb->inner, scratch_pool, scratch_pool));
+
+  /* Did a conflict occur during the commit process?  */
+  if (conflict_path != NULL)
+    return svn_error_createf(SVN_ERR_FS_CONFLICT, NULL,
+                             _("Conflict at '%s'"), conflict_path);
+
+  /* Since did not receive an error during the commit process, and no
+     conflict was specified... we committed a revision. Run the hooks.
+     Other errors may have occurred within the FS (specified by the
+     POST_COMMIT_ERR localvar), but we need to run the hooks.  */
+  SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(revision));
+  err = svn_repos__hooks_post_commit(eb->repos, revision, eb->txn_name,
+                                     scratch_pool);
+  if (err)
+    err = svn_error_create(SVN_ERR_REPOS_POST_COMMIT_HOOK_FAILED, err,
+                           _("Commit succeeded, but post-commit hook failed"));
+
+  /* Combine the FS errors with the hook errors, and stringify.  */
+  err = svn_error_compose_create(post_commit_err, err);
+  if (err)
+    {
+      post_commit_errstr = svn_repos__post_commit_error_str(err, scratch_pool);
+      svn_error_clear(err);
+    }
+  else
+    {
+      post_commit_errstr = NULL;
+    }
+
+  return svn_error_trace(invoke_commit_cb(eb->commit_cb, eb->commit_baton,
+                                          eb->repos->fs, revision,
+                                          post_commit_errstr,
+                                          scratch_pool));
+}
+
+
+/* This implements svn_editor_cb_abort_t */
+static svn_error_t *
+abort_cb(void *baton,
+         apr_pool_t *scratch_pool)
+{
+  struct ev2_baton *eb = baton;
+
+  SVN_ERR(svn_editor_abort(eb->inner));
+  return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+apply_revprops(svn_fs_t *fs,
+               const char *txn_name,
+               apr_hash_t *revprops,
+               apr_pool_t *scratch_pool)
+{
+  svn_fs_txn_t *txn;
+  const apr_array_header_t *revprops_array;
+
+  /* The FS editor has a TXN inside it, but we can't access it. Open another
+     based on the TXN_NAME.  */
+  SVN_ERR(svn_fs_open_txn(&txn, fs, txn_name, scratch_pool));
+
+  /* Validate and apply the revision properties.  */
+  revprops_array = svn_prop_hash_to_array(revprops, scratch_pool);
+  SVN_ERR(svn_repos_fs_change_txn_props(txn, revprops_array, scratch_pool));
+
+  /* ### do we need to force the txn to close, or is it enough to wait
+     ### for the pool to be cleared?  */
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_repos__get_commit_ev2(svn_editor_t **editor,
+                          svn_repos_t *repos,
+                          svn_authz_t *authz,
+                          const char *authz_repos_name,
+                          const char *authz_user,
+                          apr_hash_t *revprops,
+                          svn_commit_callback2_t commit_cb,
+                          void *commit_baton,
+                          svn_cancel_func_t cancel_func,
+                          void *cancel_baton,
+                          apr_pool_t *result_pool,
+                          apr_pool_t *scratch_pool)
+{
+  static const svn_editor_cb_many_t editor_cbs = {
+    add_directory_cb,
+    add_file_cb,
+    add_symlink_cb,
+    add_absent_cb,
+    alter_directory_cb,
+    alter_file_cb,
+    alter_symlink_cb,
+    delete_cb,
+    copy_cb,
+    move_cb,
+    rotate_cb,
+    complete_cb,
+    abort_cb
+  };
+  struct ev2_baton *eb;
+  const svn_string_t *author;
+
+  /* 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;
+  eb->authz = authz;
+  eb->authz_repos_name = authz_repos_name;
+  eb->authz_user = authz_user;
+  eb->commit_cb = commit_cb;
+  eb->commit_baton = commit_baton;
+
+  SVN_ERR(svn_fs_editor_create(&eb->inner, &eb->txn_name,
+                               repos->fs, SVN_FS_TXN_CHECK_LOCKS,
+                               cancel_func, cancel_baton,
+                               result_pool, scratch_pool));
+
+  /* The TXN has been created. Go ahead and apply all revision properties.  */
+  SVN_ERR(apply_revprops(repos->fs, eb->txn_name, revprops, scratch_pool));
+
+  /* Wrap the FS editor within our editor.  */
+  SVN_ERR(svn_editor_create(editor, eb, cancel_func, cancel_baton,
+                            result_pool, scratch_pool));
+  SVN_ERR(svn_editor_setcb_many(*editor, &editor_cbs, scratch_pool));
+
+  return SVN_NO_ERROR;
+}

Modified: subversion/branches/compressed-pristines/subversion/libsvn_repos/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_repos/deprecated.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_repos/deprecated.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_repos/deprecated.c Thu Aug 16 10:17:48 2012
@@ -32,6 +32,8 @@
 
 #include "svn_private_config.h"
 
+#include "repos.h"
+
 
 
 
@@ -570,8 +572,7 @@ repos_notify_handler(void *baton,
   switch (notify->action)
   {
     case svn_repos_notify_warning:
-      len = strlen(notify->warning_str);
-      svn_error_clear(svn_stream_write(feedback_stream, notify->warning_str, &len));
+      svn_error_clear(svn_stream_puts(feedback_stream, notify->warning_str));
       return;
 
     case svn_repos_notify_dump_rev_end:
@@ -774,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)
@@ -795,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,
@@ -836,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 *
@@ -878,3 +942,32 @@ svn_repos_get_fs_build_parser(const svn_
   *parser_callbacks = fns_from_fns2(fns2, pool);
   return SVN_NO_ERROR;
 }
+
+
+svn_error_t *
+svn_repos_fs_begin_txn_for_update(svn_fs_txn_t **txn_p,
+                                  svn_repos_t *repos,
+                                  svn_revnum_t rev,
+                                  const char *author,
+                                  apr_pool_t *pool)
+{
+  /* ### someday, we might run a read-hook here. */
+
+  /* Begin the transaction. */
+  SVN_ERR(svn_fs_begin_txn2(txn_p, repos->fs, rev, 0, pool));
+
+  /* We pass the author to the filesystem by adding it as a property
+     on the txn. */
+
+  /* User (author). */
+  if (author)
+    {
+      svn_string_t val;
+      val.data = author;
+      val.len = strlen(author);
+      SVN_ERR(svn_fs_change_txn_prop(*txn_p, SVN_PROP_REVISION_AUTHOR,
+                                     &val, pool));
+    }
+
+  return SVN_NO_ERROR;
+}

Modified: subversion/branches/compressed-pristines/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_repos/dump.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_repos/dump.c Thu Aug 16 10:17:48 2012
@@ -34,6 +34,7 @@
 #include "svn_time.h"
 #include "svn_checksum.h"
 #include "svn_props.h"
+#include "svn_sorts.h"
 
 #include "private/svn_mergeinfo_private.h"
 #include "private/svn_fs_private.h"
@@ -71,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. */
@@ -282,11 +284,11 @@ dump_node(struct edit_baton *eb,
                             SVN_REPOS_DUMPFILE_NODE_PATH ": %s\n",
                             path));
   if (kind == svn_node_file)
-    SVN_ERR(svn_stream_printf(eb->stream, pool,
-                              SVN_REPOS_DUMPFILE_NODE_KIND ": file\n"));
+    SVN_ERR(svn_stream_puts(eb->stream,
+                            SVN_REPOS_DUMPFILE_NODE_KIND ": file\n"));
   else if (kind == svn_node_dir)
-    SVN_ERR(svn_stream_printf(eb->stream, pool,
-                              SVN_REPOS_DUMPFILE_NODE_KIND ": dir\n"));
+    SVN_ERR(svn_stream_puts(eb->stream,
+                            SVN_REPOS_DUMPFILE_NODE_KIND ": dir\n"));
 
   /* Remove leading slashes from copyfrom paths. */
   if (cmp_path)
@@ -301,9 +303,8 @@ dump_node(struct edit_baton *eb,
 
   if (action == svn_node_action_change)
     {
-      SVN_ERR(svn_stream_printf(eb->stream, pool,
-                                SVN_REPOS_DUMPFILE_NODE_ACTION
-                                ": change\n"));
+      SVN_ERR(svn_stream_puts(eb->stream,
+                              SVN_REPOS_DUMPFILE_NODE_ACTION ": change\n"));
 
       /* either the text or props changed, or possibly both. */
       SVN_ERR(svn_fs_revision_root(&compare_root,
@@ -323,9 +324,9 @@ dump_node(struct edit_baton *eb,
       if (! is_copy)
         {
           /* a simple delete+add, implied by a single 'replace' action. */
-          SVN_ERR(svn_stream_printf(eb->stream, pool,
-                                    SVN_REPOS_DUMPFILE_NODE_ACTION
-                                    ": replace\n"));
+          SVN_ERR(svn_stream_puts(eb->stream,
+                                  SVN_REPOS_DUMPFILE_NODE_ACTION
+                                  ": replace\n"));
 
           /* definitely need to dump all content for a replace. */
           if (kind == svn_node_file)
@@ -338,9 +339,9 @@ dump_node(struct edit_baton *eb,
 
           /* the path & kind headers have already been printed;  just
              add a delete action, and end the current record.*/
-          SVN_ERR(svn_stream_printf(eb->stream, pool,
-                                    SVN_REPOS_DUMPFILE_NODE_ACTION
-                                    ": delete\n\n"));
+          SVN_ERR(svn_stream_puts(eb->stream,
+                                  SVN_REPOS_DUMPFILE_NODE_ACTION
+                                  ": delete\n\n"));
 
           /* recurse:  print an additional add-with-history record. */
           SVN_ERR(dump_node(eb, path, kind, svn_node_action_add,
@@ -354,9 +355,8 @@ dump_node(struct edit_baton *eb,
     }
   else if (action == svn_node_action_delete)
     {
-      SVN_ERR(svn_stream_printf(eb->stream, pool,
-                                SVN_REPOS_DUMPFILE_NODE_ACTION
-                                ": delete\n"));
+      SVN_ERR(svn_stream_puts(eb->stream,
+                              SVN_REPOS_DUMPFILE_NODE_ACTION ": delete\n"));
 
       /* we can leave this routine quietly now, don't need to dump
          any content. */
@@ -365,8 +365,8 @@ dump_node(struct edit_baton *eb,
     }
   else if (action == svn_node_action_add)
     {
-      SVN_ERR(svn_stream_printf(eb->stream, pool,
-                                SVN_REPOS_DUMPFILE_NODE_ACTION ": add\n"));
+      SVN_ERR(svn_stream_puts(eb->stream,
+                              SVN_REPOS_DUMPFILE_NODE_ACTION ": add\n"));
 
       if (! is_copy)
         {
@@ -511,9 +511,8 @@ dump_node(struct edit_baton *eb,
              saying that our property contents are a delta. */
           SVN_ERR(svn_fs_node_proplist(&oldhash, compare_root, compare_path,
                                        pool));
-          SVN_ERR(svn_stream_printf(eb->stream, pool,
-                                    SVN_REPOS_DUMPFILE_PROP_DELTA
-                                    ": true\n"));
+          SVN_ERR(svn_stream_puts(eb->stream,
+                                  SVN_REPOS_DUMPFILE_PROP_DELTA ": true\n"));
         }
       else
         oldhash = apr_hash_make(pool);
@@ -544,9 +543,8 @@ dump_node(struct edit_baton *eb,
              saying our text contents are a delta. */
           SVN_ERR(store_delta(&delta_file, &textlen, compare_root,
                               compare_path, eb->fs_root, path, pool));
-          SVN_ERR(svn_stream_printf(eb->stream, pool,
-                                    SVN_REPOS_DUMPFILE_TEXT_DELTA
-                                    ": true\n"));
+          SVN_ERR(svn_stream_puts(eb->stream,
+                                  SVN_REPOS_DUMPFILE_TEXT_DELTA ": true\n"));
 
           if (compare_root)
             {
@@ -738,17 +736,20 @@ close_directory(void *dir_baton,
 {
   struct dir_baton *db = dir_baton;
   struct edit_baton *eb = db->edit_baton;
-  apr_hash_index_t *hi;
   apr_pool_t *subpool = svn_pool_create(pool);
+  int i;
+  apr_array_header_t *sorted_entries;
 
-  for (hi = apr_hash_first(pool, db->deleted_entries);
-       hi;
-       hi = apr_hash_next(hi))
-    {
-      const void *key;
-      const char *path;
-      apr_hash_this(hi, &key, NULL, NULL);
-      path = key;
+  /* Sort entries lexically instead of as paths. Even though the entries
+   * are full paths they're all in the same directory (see comment in struct
+   * dir_baton definition). So we really want to sort by basename, in which
+   * case the lexical sort function is more efficient. */
+  sorted_entries = svn_sort__hash(db->deleted_entries,
+                                  svn_sort_compare_items_lexically, pool);
+  for (i = 0; i < sorted_entries->nelts; i++)
+    {
+      const char *path = APR_ARRAY_IDX(sorted_entries, i,
+                                       svn_sort__item_t).key;
 
       svn_pool_clear(subpool);
 

Modified: subversion/branches/compressed-pristines/subversion/libsvn_repos/fs-wrap.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_repos/fs-wrap.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_repos/fs-wrap.c Thu Aug 16 10:17:48 2012
@@ -124,36 +124,6 @@ svn_repos_fs_begin_txn_for_commit(svn_fs
                                             pool);
 }
 
-
-svn_error_t *
-svn_repos_fs_begin_txn_for_update(svn_fs_txn_t **txn_p,
-                                  svn_repos_t *repos,
-                                  svn_revnum_t rev,
-                                  const char *author,
-                                  apr_pool_t *pool)
-{
-  /* ### someday, we might run a read-hook here. */
-
-  /* Begin the transaction. */
-  SVN_ERR(svn_fs_begin_txn2(txn_p, repos->fs, rev, 0, pool));
-
-  /* We pass the author to the filesystem by adding it as a property
-     on the txn. */
-
-  /* User (author). */
-  if (author)
-    {
-      svn_string_t val;
-      val.data = author;
-      val.len = strlen(author);
-      SVN_ERR(svn_fs_change_txn_prop(*txn_p, SVN_PROP_REVISION_AUTHOR,
-                                     &val, pool));
-    }
-
-  return SVN_NO_ERROR;
-}
-
-
 
 /*** Property wrappers ***/
 
@@ -689,8 +659,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);
 

Modified: subversion/branches/compressed-pristines/subversion/libsvn_repos/hooks.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_repos/hooks.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_repos/hooks.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_repos/hooks.c Thu Aug 16 10:17:48 2012
@@ -30,6 +30,7 @@
 #include "svn_error.h"
 #include "svn_dirent_uri.h"
 #include "svn_path.h"
+#include "svn_pools.h"
 #include "svn_repos.h"
 #include "svn_utf.h"
 #include "repos.h"
@@ -212,7 +213,8 @@ run_hook_cmd(svn_string_t **result,
   apr_file_t *null_handle;
   apr_status_t apr_err;
   svn_error_t *err;
-  apr_proc_t cmd_proc;
+  apr_proc_t cmd_proc = {0};
+  apr_pool_t *cmd_pool;
 
   if (result)
     {
@@ -228,42 +230,39 @@ run_hook_cmd(svn_string_t **result,
             (apr_err, _("Can't create null stdout for hook '%s'"), cmd);
     }
 
+  /* Tie resources allocated for the command to a special pool which we can
+   * destroy in order to clean up the stderr pipe opened for the process. */
+  cmd_pool = svn_pool_create(pool);
+
   err = svn_io_start_cmd3(&cmd_proc, ".", cmd, args,
                           env_from_env_hash(hooks_env, pool, pool),
                           FALSE, FALSE, stdin_handle, result != NULL,
-                          null_handle, TRUE, NULL, pool);
-
-  if (err)
-    {
-      /* CMD_PROC is not safe to use. Bail. */
-      return svn_error_createf
-        (SVN_ERR_REPOS_HOOK_FAILURE, err, _("Failed to start '%s' hook"), cmd);
-    }
+                          null_handle, TRUE, NULL, cmd_pool);
+  if (!err)
+    err = check_hook_result(name, cmd, &cmd_proc, cmd_proc.err, pool);
   else
     {
-      err = check_hook_result(name, cmd, &cmd_proc, cmd_proc.err, pool);
+      /* The command could not be started for some reason. */
+      err = svn_error_createf(SVN_ERR_REPOS_BAD_ARGS, err,
+                              _("Failed to start '%s' hook"), cmd);
     }
 
   /* Hooks are fallible, and so hook failure is "expected" to occur at
      times.  When such a failure happens we still want to close the pipe
      and null file */
-  apr_err = apr_file_close(cmd_proc.err);
-  if (!err && apr_err)
-    return svn_error_wrap_apr
-      (apr_err, _("Error closing read end of stderr pipe"));
-
-  if (result)
+  if (!err && result)
     {
       svn_stringbuf_t *native_stdout;
-      SVN_ERR(svn_stringbuf_from_aprfile(&native_stdout, cmd_proc.out, pool));
-      apr_err = apr_file_close(cmd_proc.out);
-      if (!err && apr_err)
-        return svn_error_wrap_apr
-          (apr_err, _("Error closing read end of stderr pipe"));
-
-      *result = svn_stringbuf__morph_into_string(native_stdout);
+      err = svn_stringbuf_from_aprfile(&native_stdout, cmd_proc.out, pool);
+      if (!err)
+        *result = svn_stringbuf__morph_into_string(native_stdout);
     }
-  else
+
+  /* Close resources allocated by svn_io_start_cmd3(), such as the pipe. */
+  svn_pool_destroy(cmd_pool);
+
+  /* Close the null handle. */
+  if (null_handle)
     {
       apr_err = apr_file_close(null_handle);
       if (!err && apr_err)

Modified: subversion/branches/compressed-pristines/subversion/libsvn_repos/load-fs-vtable.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_repos/load-fs-vtable.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_repos/load-fs-vtable.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_repos/load-fs-vtable.c Thu Aug 16 10:17:48 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;
@@ -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/compressed-pristines/subversion/libsvn_repos/load.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_repos/load.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_repos/load.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_repos/load.c Thu Aug 16 10:17:48 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/compressed-pristines/subversion/libsvn_repos/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_repos/log.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_repos/log.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_repos/log.c Thu Aug 16 10:17:48 2012
@@ -1177,7 +1177,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 +1397,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 +1735,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)
@@ -1807,8 +1807,8 @@ store_search(svn_mergeinfo_t processed,
   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));
 

Modified: subversion/branches/compressed-pristines/subversion/libsvn_repos/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_repos/replay.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_repos/replay.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_repos/replay.c Thu Aug 16 10:17:48 2012
@@ -27,14 +27,18 @@
 
 #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"
 #include "svn_private_config.h"
 #include "private/svn_fspath.h"
+#include "private/svn_repos_private.h"
+#include "private/svn_delta_private.h"
 
 
 /*** Backstory ***/
@@ -99,6 +103,7 @@
    (though not necessarily in the same order in which they
    occurred). */
 
+/* #define USE_EV2_IMPL */
 
 
 /*** Helper functions. ***/
@@ -136,7 +141,6 @@ struct path_driver_cb_baton
   void *authz_read_baton;
 
   const char *base_path; /* relpath */
-  size_t base_path_len;
 
   svn_revnum_t low_water_mark;
   /* Stack of active copy operations. */
@@ -146,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
@@ -337,20 +342,7 @@ add_subdir(svn_fs_root_t *source_root,
 
   return SVN_NO_ERROR;
 }
-
-static svn_boolean_t
-is_within_base_path(const char *path, const char *base_path,
-                    apr_ssize_t base_len)
-{
-  if (base_path[0] == '\0')
-    return TRUE;
-
-  if (strncmp(base_path, path, base_len) == 0
-      && (path[base_len] == '/' || path[base_len] == '\0'))
-    return TRUE;
-
-  return FALSE;
-}
+#endif
 
 /* Given PATH deleted under ROOT, return in READABLE whether the path was
    readable prior to the deletion.  Consult COPIES (a stack of 'struct
@@ -415,7 +407,12 @@ was_readable(svn_boolean_t *readable,
    revision root, fspath, and revnum of the copyfrom of CHANGE, which
    corresponds to PATH under ROOT.  If the copyfrom info is valid
    (i.e., is not (NULL, SVN_INVALID_REVNUM)), then initialize SRC_READABLE
-   too, consulting AUTHZ_READ_FUNC and AUTHZ_READ_BATON if provided. */
+   too, consulting AUTHZ_READ_FUNC and AUTHZ_READ_BATON if provided.
+
+   NOTE: If the copyfrom information in CHANGE is marked as unknown
+   (meaning, its ->copyfrom_rev and ->copyfrom_path cannot be
+   trusted), this function will also update those members of the
+   CHANGE structure to carry accurate copyfrom information.  */
 static svn_error_t *
 fill_copyfrom(svn_fs_root_t **copyfrom_root,
               const char **copyfrom_path,
@@ -462,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,
@@ -481,7 +479,6 @@ path_driver_cb_func(void **dir_baton,
   svn_fs_root_t *source_root = cb->compare_root;
   const char *source_fspath = NULL;
   const char *base_path = cb->base_path;
-  size_t base_path_len = cb->base_path_len;
 
   *dir_baton = NULL;
 
@@ -571,8 +568,7 @@ path_driver_cb_func(void **dir_baton,
          all. */
       if (copyfrom_path
           && ((! src_readable)
-              || (! is_within_base_path(copyfrom_path + 1, base_path,
-                                        base_path_len))
+              || (svn_relpath_skip_ancestor(base_path, copyfrom_path + 1) == NULL)
               || (cb->low_water_mark > copyfrom_rev)))
         {
           copyfrom_path = NULL;
@@ -698,10 +694,18 @@ path_driver_cb_func(void **dir_baton,
         }
     }
 
-  /* Handle property modifications. */
   if (! do_delete || do_add)
     {
-      if (change->prop_mod)
+      /* 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)
         {
           apr_array_header_t *prop_diffs;
           apr_hash_t *old_props;
@@ -731,14 +735,9 @@ path_driver_cb_func(void **dir_baton,
             }
         }
 
-      /* Handle textual modifications.
-
-         Note that this needs to happen in the "copy from a file we
-         aren't allowed to see" case since otherwise the caller will
-         have no way to actually get the new file's contents, which
-         they are apparently allowed to see. */
+      /* Handle textual modifications. */
       if (change->node_kind == svn_node_file
-          && (change->text_mod || (change->copyfrom_path && ! copyfrom_path)))
+          && (change->text_mod || downgraded_copy))
         {
           svn_txdelta_window_handler_t delta_handler;
           void *delta_handler_baton;
@@ -785,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
+
 
 
 
@@ -799,12 +839,12 @@ svn_repos_replay2(svn_fs_root_t *root,
                   void *authz_read_baton,
                   apr_pool_t *pool)
 {
+#ifndef USE_EV2_IMPL
   apr_hash_t *fs_changes;
   apr_hash_t *changed_paths;
   apr_hash_index_t *hi;
   apr_array_header_t *paths;
   struct path_driver_cb_baton cb_baton;
-  size_t base_path_len;
 
   /* Special-case r0, which we know is an empty revision; if we don't
      special-case it we might end up trying to compare it to "r-1". */
@@ -822,8 +862,6 @@ svn_repos_replay2(svn_fs_root_t *root,
   else if (base_path[0] == '/')
     ++base_path;
 
-  base_path_len = strlen(base_path);
-
   /* Make an array from the keys of our CHANGED_PATHS hash, and copy
      the values into a new hash whose keys have no leading slashes. */
   paths = apr_array_make(pool, apr_hash_count(fs_changes),
@@ -856,14 +894,14 @@ svn_repos_replay2(svn_fs_root_t *root,
 
           /* If the base_path doesn't match the top directory of this path
              we don't want anything to do with it... */
-          if (is_within_base_path(path, base_path, base_path_len))
+          if (svn_relpath_skip_ancestor(base_path, path) != NULL)
             {
               APR_ARRAY_PUSH(paths, const char *) = path;
               apr_hash_set(changed_paths, path, keylen, change);
             }
           /* ...unless this was a change to one of the parent directories of
              base_path. */
-          else if (is_within_base_path(base_path, path, keylen))
+          else if (svn_relpath_skip_ancestor(path, base_path) != NULL)
             {
               APR_ARRAY_PUSH(paths, const char *) = path;
               apr_hash_set(changed_paths, path, keylen, change);
@@ -884,7 +922,6 @@ svn_repos_replay2(svn_fs_root_t *root,
   cb_baton.authz_read_func = authz_read_func;
   cb_baton.authz_read_baton = authz_read_baton;
   cb_baton.base_path = base_path;
-  cb_baton.base_path_len = base_path_len;
   cb_baton.low_water_mark = low_water_mark;
   cb_baton.compare_root = NULL;
 
@@ -913,4 +950,634 @@ svn_repos_replay2(svn_fs_root_t *root,
   return svn_delta_path_driver(editor, edit_baton,
                                SVN_INVALID_REVNUM, paths,
                                path_driver_cb_func, &cb_baton, pool);
+#else
+  svn_editor_t *editorv2;
+  struct svn_delta__extra_baton *exb;
+  svn_delta__unlock_func_t unlock_func;
+  svn_boolean_t send_abs_paths;
+  const char *repos_root = "";
+  void *unlock_baton;
+
+  /* Special-case r0, which we know is an empty revision; if we don't
+     special-case it we might end up trying to compare it to "r-1". */
+  if (svn_fs_is_revision_root(root)
+        && svn_fs_revision_root_revision(root) == 0)
+    {
+      SVN_ERR(editor->set_target_revision(edit_baton, 0, pool));
+      return SVN_NO_ERROR;
+    }
+
+  /* Determine the revision to use throughout the edit, and call
+     EDITOR's set_target_revision() function.  */
+  if (svn_fs_is_revision_root(root))
+    {
+      svn_revnum_t revision = svn_fs_revision_root_revision(root);
+      SVN_ERR(editor->set_target_revision(edit_baton, revision, pool));
+    }
+
+  if (! base_path)
+    base_path = "";
+  else if (base_path[0] == '/')
+    ++base_path;
+
+  /* Use the shim to convert our editor to an Ev2 editor, and pass it down
+     the stack. */
+  SVN_ERR(svn_delta__editor_from_delta(&editorv2, &exb,
+                                       &unlock_func, &unlock_baton,
+                                       editor, edit_baton,
+                                       &send_abs_paths,
+                                       repos_root, "",
+                                       NULL, NULL,
+                                       fetch_kind_func, root,
+                                       fetch_props_func, root,
+                                       pool, pool));
+
+  /* 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));
+
+  return SVN_NO_ERROR;
+#endif
+}
+
+
+/*****************************************************************
+ *                      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 *
+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_editor_t *editor,
+                      svn_repos_authz_func_t authz_read_func,
+                      void *authz_read_baton,
+                      apr_pool_t *scratch_pool)
+{
+  apr_hash_t *fs_changes;
+  apr_hash_t *changed_paths;
+  apr_hash_index_t *hi;
+  apr_array_header_t *paths;
+  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));
+
+  /* Special-case r0, which we know is an empty revision; if we don't
+     special-case it we might end up trying to compare it to "r-1". */
+  if (svn_fs_is_revision_root(root)
+        && svn_fs_revision_root_revision(root) == 0)
+    {
+      return SVN_NO_ERROR;
+    }
+
+  /* Fetch the paths changed under ROOT. */
+  SVN_ERR(svn_fs_paths_changed2(&fs_changes, root, scratch_pool));
+
+  /* Make an array from the keys of our CHANGED_PATHS hash, and copy
+     the values into a new hash whose keys have no leading slashes. */
+  paths = apr_array_make(scratch_pool, apr_hash_count(fs_changes),
+                         sizeof(const char *));
+  changed_paths = apr_hash_make(scratch_pool);
+  for (hi = apr_hash_first(scratch_pool, fs_changes); hi;
+        hi = apr_hash_next(hi))
+    {
+      const void *key;
+      void *val;
+      apr_ssize_t keylen;
+      const char *path;
+      svn_fs_path_change2_t *change;
+      svn_boolean_t allowed = TRUE;
+
+      apr_hash_this(hi, &key, &keylen, &val);
+      path = key;
+      change = val;
+
+      if (authz_read_func)
+        SVN_ERR(authz_read_func(&allowed, root, path, authz_read_baton,
+                                scratch_pool));
+
+      if (allowed)
+        {
+          if (path[0] == '/')
+            {
+              path++;
+              keylen--;
+            }
+
+          /* If the base_path doesn't match the top directory of this path
+             we don't want anything to do with it... */
+          if (svn_relpath_skip_ancestor(base_repos_relpath, path) != NULL)
+            {
+              APR_ARRAY_PUSH(paths, const char *) = path;
+              apr_hash_set(changed_paths, path, keylen, change);
+            }
+          /* ...unless this was a change to one of the parent directories of
+             base_path. */
+          else if (svn_relpath_skip_ancestor(path, base_repos_relpath) != NULL)
+            {
+              APR_ARRAY_PUSH(paths, const char *) = path;
+              apr_hash_set(changed_paths, path, keylen, change);
+            }
+        }
+    }
+
+  /* If we were not given a low water mark, assume that everything is there,
+     all the way back to revision 0. */
+  if (! SVN_IS_VALID_REVNUM(low_water_mark))
+    low_water_mark = 0;
+
+  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_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/compressed-pristines/subversion/libsvn_repos/reporter.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_repos/reporter.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_repos/reporter.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_repos/reporter.c Thu Aug 16 10:17:48 2012
@@ -640,14 +640,20 @@ delta_files(report_baton_t *b, void *fil
   /* Send the delta stream if desired, or just a NULL window if not. */
   SVN_ERR(b->editor->apply_textdelta(file_baton, s_hex_digest, pool,
                                      &dhandler, &dbaton));
-  if (b->text_deltas)
+
+  if (dhandler != svn_delta_noop_window_handler)
     {
-      SVN_ERR(svn_fs_get_file_delta_stream(&dstream, s_root, s_path,
-                                           b->t_root, t_path, pool));
-      return svn_txdelta_send_txstream(dstream, dhandler, dbaton, pool);
+      if (b->text_deltas)
+        {
+          SVN_ERR(svn_fs_get_file_delta_stream(&dstream, s_root, s_path,
+                                               b->t_root, t_path, pool));
+          SVN_ERR(svn_txdelta_send_txstream(dstream, dhandler, dbaton, pool));
+        }
+      else
+        SVN_ERR(dhandler(NULL, dbaton));
     }
-  else
-    return dhandler(NULL, dbaton);
+
+  return SVN_NO_ERROR;
 }
 
 /* Determine if the user is authorized to view B->t_root/PATH. */

Modified: subversion/branches/compressed-pristines/subversion/libsvn_repos/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_repos/repos.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_repos/repos.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_repos/repos.c Thu Aug 16 10:17:48 2012
@@ -36,6 +36,7 @@
 #include "svn_version.h"
 
 #include "private/svn_repos_private.h"
+#include "private/svn_subr_private.h"
 #include "svn_private_config.h" /* for SVN_TEMPLATE_ROOT_DIR */
 
 #include "repos.h"
@@ -1017,7 +1018,7 @@ create_conf(svn_repos_t *repos, apr_pool
 "# password-db = passwd"                                                     NL
 "### The authz-db option controls the location of the authorization"         NL
 "### rules for path-based access control.  Unless you specify a path"        NL
-"### starting with a /, the file's location is relative to the the"          NL
+"### starting with a /, the file's location is relative to the"              NL
 "### directory containing this file.  If you don't specify an"               NL
 "### authz-db, no path-based access control is done."                        NL
 "### Uncomment the line below to use the default authorization file."        NL
@@ -1184,9 +1185,9 @@ create_repos_structure(svn_repos_t *repo
   /* Write the top-level README file. */
   {
     const char * const readme_header =
-      "This is a Subversion repository; use the 'svnadmin' tool to examine"  NL
-      "it.  Do not add, delete, or modify files here unless you know how"    NL
-      "to avoid corrupting the repository."                                  NL
+      "This is a Subversion repository; use the 'svnadmin' and 'svnlook' "   NL
+      "tools to examine it.  Do not add, delete, or modify files here "      NL
+      "unless you know how to avoid corrupting the repository."              NL
       ""                                                                     NL;
     const char * const readme_bdb_insert =
       "The directory \"" SVN_REPOS__DB_DIR "\" contains a Berkeley DB environment."  NL
@@ -1563,7 +1564,8 @@ svn_repos_has_capability(svn_repos_t *re
 
       SVN_ERR(svn_fs_revision_root(&root, repos->fs, 0, pool));
       APR_ARRAY_PUSH(paths, const char *) = "";
-      err = svn_fs_get_mergeinfo(&ignored, root, paths, FALSE, FALSE, pool);
+      err = svn_fs_get_mergeinfo2(&ignored, root, paths, FALSE, FALSE,
+                                  TRUE, pool, pool);
 
       if (err)
         {
@@ -1968,3 +1970,17 @@ svn_repos_remember_client_capabilities(s
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_repos__fs_type(const char **fs_type,
+                   const char *repos_path,
+                   apr_pool_t *pool)
+{
+  svn_repos_t repos;
+  repos.path = (char*)repos_path;
+
+  SVN_ERR(check_repos_format(&repos, pool));
+
+  return svn_fs_type(fs_type,
+                     svn_dirent_join(repos_path, SVN_REPOS__DB_DIR, pool),
+                     pool);
+}

Modified: subversion/branches/compressed-pristines/subversion/libsvn_repos/rev_hunt.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_repos/rev_hunt.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_repos/rev_hunt.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_repos/rev_hunt.c Thu Aug 16 10:17:48 2012
@@ -155,7 +155,7 @@ svn_repos_get_committed_info(svn_revnum_
                              apr_pool_t *pool)
 {
   apr_hash_t *revprops;
-  
+
   svn_fs_t *fs = svn_fs_root_fs(root);
 
   /* ### It might be simpler just to declare that revision
@@ -1291,7 +1291,7 @@ find_merged_revisions(apr_array_header_t
                hi = apr_hash_next(hi))
             {
               apr_pool_t *iterpool3;
-              apr_array_header_t *rangelist;
+              svn_rangelist_t *rangelist;
               const char *path;
               int j;
 

Modified: subversion/branches/compressed-pristines/subversion/libsvn_subr/adler32.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_subr/adler32.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_subr/adler32.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_subr/adler32.c Thu Aug 16 10:17:48 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
     {