You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2010/12/02 21:55:18 UTC

svn commit: r1041580 [8/35] - in /subversion/branches/gpg-agent-password-store: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ contrib/hook-scripts/ contrib/server-side/ notes/http-and-webdav/ notes/wc-ng/ subversio...

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/options.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/options.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/options.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/options.c Thu Dec  2 20:55:08 2010
@@ -566,12 +566,15 @@ svn_ra_serf__has_capability(svn_ra_sessi
              support mergeinfo. */
           svn_mergeinfo_catalog_t ignored;
           svn_error_t *err;
+          svn_boolean_t validate_inherited_mergeinfo = FALSE;
           apr_array_header_t *paths = apr_array_make(pool, 1,
                                                      sizeof(char *));
           APR_ARRAY_PUSH(paths, const char *) = "";
 
           err = svn_ra_serf__get_mergeinfo(ra_session, &ignored, paths, 0,
-                                           FALSE, FALSE, pool);
+                                           FALSE,
+                                           &validate_inherited_mergeinfo,
+                                           FALSE, pool);
 
           if (err)
             {

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/ra_serf.h?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/ra_serf.h Thu Dec  2 20:55:08 2010
@@ -1379,13 +1379,15 @@ svn_ra_serf__get_locks(svn_ra_session_t 
                        svn_depth_t depth,
                        apr_pool_t *pool);
 
-svn_error_t * svn_ra_serf__get_mergeinfo(svn_ra_session_t *ra_session,
-                                         apr_hash_t **mergeinfo,
-                                         const apr_array_header_t *paths,
-                                         svn_revnum_t revision,
-                                         svn_mergeinfo_inheritance_t inherit,
-                                         svn_boolean_t include_descendants,
-                                         apr_pool_t *pool);
+svn_error_t * svn_ra_serf__get_mergeinfo(
+  svn_ra_session_t *ra_session,
+  apr_hash_t **mergeinfo,
+  const apr_array_header_t *paths,
+  svn_revnum_t revision,
+  svn_mergeinfo_inheritance_t inherit,
+  svn_boolean_t *validate_inherited_mergeinfo,
+  svn_boolean_t include_descendants,
+  apr_pool_t *pool);
 
 /* Exchange capabilities with the server, by sending an OPTIONS
  * request announcing the client's capabilities, and by filling

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_svn/client.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_svn/client.c Thu Dec  2 20:55:08 2010
@@ -1153,15 +1153,34 @@ static svn_error_t *ra_svn_get_dir(svn_r
   return SVN_NO_ERROR;
 }
 
+/* Converts a apr_uint64_t with values TRUE, FALSE or
+   SVN_RA_SVN_UNSPECIFIED_NUMBER as provided by svn_ra_svn_parse_tuple
+   to a svn_tristate_t */
+static svn_tristate_t
+optbool_to_tristate(apr_uint64_t v)
+{
+  switch (v)
+  {
+    case TRUE:
+      return svn_tristate_true;
+    case FALSE:
+      return svn_tristate_false;
+    default: /* Contains SVN_RA_SVN_UNSPECIFIED_NUMBER */
+      return svn_tristate_unknown;
+  }
+}
+
 /* If REVISION is SVN_INVALID_REVNUM, no value is sent to the
    server, which defaults to youngest. */
-static svn_error_t *ra_svn_get_mergeinfo(svn_ra_session_t *session,
-                                         svn_mergeinfo_catalog_t *catalog,
-                                         const apr_array_header_t *paths,
-                                         svn_revnum_t revision,
-                                         svn_mergeinfo_inheritance_t inherit,
-                                         svn_boolean_t include_descendants,
-                                         apr_pool_t *pool)
+static svn_error_t *ra_svn_get_mergeinfo(
+  svn_ra_session_t *session,
+  svn_mergeinfo_catalog_t *catalog,
+  const apr_array_header_t *paths,
+  svn_revnum_t revision,
+  svn_mergeinfo_inheritance_t inherit,
+  svn_boolean_t *validate_inherited_mergeinfo,
+  svn_boolean_t include_descendants,
+  apr_pool_t *pool)
 {
   svn_ra_svn__session_baton_t *sess_baton = session->priv;
   svn_ra_svn_conn_t *conn = sess_baton->conn;
@@ -1169,6 +1188,7 @@ static svn_error_t *ra_svn_get_mergeinfo
   apr_array_header_t *mergeinfo_tuple;
   svn_ra_svn_item_t *elt;
   const char *path;
+  apr_uint64_t validated_inherited_mergeinfo;
 
   SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w((!", "get-mergeinfo"));
   for (i = 0; i < paths->nelts; i++)
@@ -1176,12 +1196,17 @@ static svn_error_t *ra_svn_get_mergeinfo
       path = APR_ARRAY_IDX(paths, i, const char *);
       SVN_ERR(svn_ra_svn_write_cstring(conn, pool, path));
     }
-  SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!)(?r)wb)", revision,
+  SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!)(?r)wbb)", revision,
                                  svn_inheritance_to_word(inherit),
-                                 include_descendants));
+                                 include_descendants,
+                                 *validate_inherited_mergeinfo));
 
   SVN_ERR(handle_auth_request(sess_baton, pool));
-  SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "l", &mergeinfo_tuple));
+  SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "l?B", &mergeinfo_tuple,
+                                       &validated_inherited_mergeinfo));
+
+  *validate_inherited_mergeinfo =
+    (optbool_to_tristate(validated_inherited_mergeinfo) == svn_tristate_true);
 
   *catalog = NULL;
   if (mergeinfo_tuple->nelts > 0)
@@ -1313,22 +1338,6 @@ static svn_error_t *ra_svn_diff(svn_ra_s
   return SVN_NO_ERROR;
 }
 
-/* Converts a apr_uint64_t with values TRUE, FALSE or
-   SVN_RA_SVN_UNSPECIFIED_NUMBER as provided by svn_ra_svn_parse_tuple
-   to a svn_tristate_t */
-static svn_tristate_t
-optbool_to_tristate(apr_uint64_t v)
-{
-  switch (v)
-  {
-    case TRUE:
-      return svn_tristate_true;
-    case FALSE:
-      return svn_tristate_false;
-    default: /* Contains SVN_RA_SVN_UNSPECIFIED_NUMBER */
-      return svn_tristate_unknown;
-  }
-}
 
 static svn_error_t *ra_svn_log(svn_ra_session_t *session,
                                const apr_array_header_t *paths,

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

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/dump.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/dump.c Thu Dec  2 20:55:08 2010
@@ -386,7 +386,7 @@ dump_node(struct edit_baton *eb,
 
               SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_md5,
                                            compare_root, compare_path,
-                                           TRUE, pool));
+                                           FALSE, pool));
               hex_digest = svn_checksum_to_cstring(checksum, pool);
               if (hex_digest)
                 SVN_ERR(svn_stream_printf(eb->stream, pool,
@@ -395,7 +395,7 @@ dump_node(struct edit_baton *eb,
 
               SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1,
                                            compare_root, compare_path,
-                                           TRUE, pool));
+                                           FALSE, pool));
               hex_digest = svn_checksum_to_cstring(checksum, pool);
               if (hex_digest)
                 SVN_ERR(svn_stream_printf(eb->stream, pool,
@@ -513,7 +513,7 @@ dump_node(struct edit_baton *eb,
             {
               SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_md5,
                                            compare_root, compare_path,
-                                           TRUE, pool));
+                                           FALSE, pool));
               hex_digest = svn_checksum_to_cstring(checksum, pool);
               if (hex_digest)
                 SVN_ERR(svn_stream_printf(eb->stream, pool,
@@ -522,7 +522,7 @@ dump_node(struct edit_baton *eb,
 
               SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1,
                                            compare_root, compare_path,
-                                           TRUE, pool));
+                                           FALSE, pool));
               hex_digest = svn_checksum_to_cstring(checksum, pool);
               if (hex_digest)
                 SVN_ERR(svn_stream_printf(eb->stream, pool,
@@ -542,7 +542,7 @@ dump_node(struct edit_baton *eb,
                                 ": %" SVN_FILESIZE_T_FMT "\n", textlen));
 
       SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_md5,
-                                   eb->fs_root, path, TRUE, pool));
+                                   eb->fs_root, path, FALSE, pool));
       hex_digest = svn_checksum_to_cstring(checksum, pool);
       if (hex_digest)
         SVN_ERR(svn_stream_printf(eb->stream, pool,
@@ -550,7 +550,7 @@ dump_node(struct edit_baton *eb,
                                   ": %s\n", hex_digest));
 
       SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1,
-                                   eb->fs_root, path, TRUE, pool));
+                                   eb->fs_root, path, FALSE, pool));
       hex_digest = svn_checksum_to_cstring(checksum, pool);
       if (hex_digest)
         SVN_ERR(svn_stream_printf(eb->stream, pool,

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/fs-wrap.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/fs-wrap.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/fs-wrap.c Thu Dec  2 20:55:08 2010
@@ -597,15 +597,16 @@ svn_repos_fs_get_locks2(apr_hash_t **loc
 
 
 svn_error_t *
-svn_repos_fs_get_mergeinfo(svn_mergeinfo_catalog_t *mergeinfo,
-                           svn_repos_t *repos,
-                           const apr_array_header_t *paths,
-                           svn_revnum_t rev,
-                           svn_mergeinfo_inheritance_t inherit,
-                           svn_boolean_t include_descendants,
-                           svn_repos_authz_func_t authz_read_func,
-                           void *authz_read_baton,
-                           apr_pool_t *pool)
+svn_repos_fs_get_mergeinfo2(svn_mergeinfo_catalog_t *mergeinfo,
+                            svn_repos_t *repos,
+                            const apr_array_header_t *paths,
+                            svn_revnum_t rev,
+                            svn_mergeinfo_inheritance_t inherit,
+                            svn_boolean_t validate_inherited_mergeinfo,
+                            svn_boolean_t include_descendants,
+                            svn_repos_authz_func_t authz_read_func,
+                            void *authz_read_baton,
+                            apr_pool_t *pool)
 {
   /* Here we cast away 'const', but won't try to write through this pointer
    * without first allocating a new array. */
@@ -653,8 +654,9 @@ 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,
+                                  validate_inherited_mergeinfo,
+                                  include_descendants, pool));
   else
     *mergeinfo = apr_hash_make(pool);
 
@@ -662,6 +664,26 @@ svn_repos_fs_get_mergeinfo(svn_mergeinfo
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_repos_fs_get_mergeinfo(svn_mergeinfo_catalog_t *mergeinfo,
+                           svn_repos_t *repos,
+                           const apr_array_header_t *paths,
+                           svn_revnum_t rev,
+                           svn_mergeinfo_inheritance_t inherit,
+                           svn_boolean_t include_descendants,
+                           svn_repos_authz_func_t authz_read_func,
+                           void *authz_read_baton,
+                           apr_pool_t *pool)
+{
+  return svn_error_return(svn_repos_fs_get_mergeinfo2(mergeinfo, repos,
+                                                      paths, rev, inherit,
+                                                      FALSE,
+                                                      include_descendants,
+                                                      authz_read_func,
+                                                      authz_read_baton,
+                                                      pool));
+}
+
 struct pack_notify_baton
 {
   svn_repos_notify_func_t notify_func;

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/load.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/load.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/load.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/load.c Thu Dec  2 20:55:08 2010
@@ -43,73 +43,6 @@
 
 /*----------------------------------------------------------------------*/
 
-/** Batons used herein **/
-
-struct parse_baton
-{
-  svn_repos_t *repos;
-  svn_fs_t *fs;
-
-  svn_boolean_t use_history;
-  svn_boolean_t use_pre_commit_hook;
-  svn_boolean_t use_post_commit_hook;
-  enum svn_repos_load_uuid uuid_action;
-  const char *parent_dir;
-  svn_repos_notify_func_t notify_func;
-  void *notify_baton;
-  svn_repos_notify_t *notify;
-  apr_pool_t *pool;
-
-  /* A hash mapping copy-from revisions and mergeinfo range revisions
-     (svn_revnum_t *) in the dump stream to their corresponding revisions
-     (svn_revnum_t *) in the loaded repository.  The hash and its
-     contents are allocated in POOL. */
-  apr_hash_t *rev_map;
-
-  /* The most recent (youngest) revision from the dump stream mapped in
-     REV_MAP.  If no revisions have been mapped yet, this is set to
-     SVN_INVALID_REVNUM. */
-  svn_revnum_t last_rev_mapped;
-
-  /* The oldest old revision loaded from the dump stream.  If no revisions
-     have been loaded yet, this is set to SVN_INVALID_REVNUM. */
-  svn_revnum_t oldest_old_rev;
-};
-
-struct revision_baton
-{
-  svn_revnum_t rev;
-
-  svn_fs_txn_t *txn;
-  svn_fs_root_t *txn_root;
-
-  const svn_string_t *datestamp;
-
-  apr_int32_t rev_offset;
-
-  struct parse_baton *pb;
-  apr_pool_t *pool;
-};
-
-struct node_baton
-{
-  const char *path;
-  svn_node_kind_t kind;
-  enum svn_node_action action;
-  svn_checksum_t *base_checksum;        /* null, if not available */
-  svn_checksum_t *result_checksum;      /* null, if not available */
-  svn_checksum_t *copy_source_checksum; /* null, if not available */
-
-  svn_revnum_t copyfrom_rev;
-  const char *copyfrom_path;
-
-  struct revision_baton *rb;
-  apr_pool_t *pool;
-};
-
-
-/*----------------------------------------------------------------------*/
-
 /** The parser and related helper funcs **/
 
 
@@ -236,170 +169,6 @@ read_key_or_val(char **pbuf,
 }
 
 
-/* Prepend the mergeinfo source paths in MERGEINFO_ORIG with PARENT_DIR, and
-   return it in *MERGEINFO_VAL. */
-static svn_error_t *
-prefix_mergeinfo_paths(svn_string_t **mergeinfo_val,
-                       const svn_string_t *mergeinfo_orig,
-                       const char *parent_dir,
-                       apr_pool_t *pool)
-{
-  apr_hash_t *prefixed_mergeinfo, *mergeinfo;
-  apr_hash_index_t *hi;
-  void *rangelist;
-
-  SVN_ERR(svn_mergeinfo_parse(&mergeinfo, mergeinfo_orig->data, pool));
-  prefixed_mergeinfo = apr_hash_make(pool);
-  for (hi = apr_hash_first(pool, mergeinfo); hi; hi = apr_hash_next(hi))
-    {
-      const void *key;
-      const char *path, *merge_source;
-
-      apr_hash_this(hi, &key, NULL, &rangelist);
-      merge_source = key;
-
-      /* The svn:mergeinfo property syntax demands absolute repository
-         paths, so prepend a leading slash if PARENT_DIR lacks one.  */
-      if (*parent_dir != '/')
-        path = svn_path_join_many(pool, "/", parent_dir,
-                                  merge_source + 1, NULL);
-      else
-        path = svn_path_join(parent_dir, merge_source + 1, pool);
-
-      apr_hash_set(prefixed_mergeinfo, path, APR_HASH_KEY_STRING, rangelist);
-    }
-  return svn_mergeinfo_to_string(mergeinfo_val, prefixed_mergeinfo, pool);
-}
-
-
-/* Examine the mergeinfo in INITIAL_VAL, renumber revisions in rangelists
-   as appropriate, and return the (possibly new) mergeinfo in *FINAL_VAL
-   (allocated from POOL). */
-static svn_error_t *
-renumber_mergeinfo_revs(svn_string_t **final_val,
-                        const svn_string_t *initial_val,
-                        struct revision_baton *rb,
-                        apr_pool_t *pool)
-{
-  apr_pool_t *subpool = svn_pool_create(pool);
-  svn_mergeinfo_t mergeinfo, predates_stream_mergeinfo;
-  svn_mergeinfo_t final_mergeinfo = apr_hash_make(subpool);
-  apr_hash_index_t *hi;
-
-  SVN_ERR(svn_mergeinfo_parse(&mergeinfo, initial_val->data, subpool));
-
-  /* Issue #3020
-     http://subversion.tigris.org/issues/show_bug.cgi?id=3020#desc16
-     Remove mergeinfo older than the oldest revision in the dump stream
-     and adjust its revisions by the difference between the head rev of
-     the target repository and the current dump stream rev. */
-  if (rb->pb->oldest_old_rev > 1)
-    {
-      SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(
-        &predates_stream_mergeinfo, mergeinfo,
-        rb->pb->oldest_old_rev - 1, 0,
-        TRUE, subpool, subpool));
-      SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(
-        &mergeinfo, mergeinfo,
-        rb->pb->oldest_old_rev - 1, 0,
-        FALSE, subpool, subpool));
-      SVN_ERR(svn_mergeinfo__adjust_mergeinfo_rangelists(
-        &predates_stream_mergeinfo, predates_stream_mergeinfo,
-        -rb->rev_offset, subpool, subpool));
-    }
-  else
-    {
-      predates_stream_mergeinfo = NULL;
-    }
-
-  for (hi = apr_hash_first(subpool, mergeinfo); hi; hi = apr_hash_next(hi))
-    {
-      const char *merge_source;
-      apr_array_header_t *rangelist;
-      struct parse_baton *pb = rb->pb;
-      int i;
-      const void *key;
-      void *val;
-
-      apr_hash_this(hi, &key, NULL, &val);
-      merge_source = key;
-      rangelist = val;
-
-      /* Possibly renumber revisions in merge source's rangelist. */
-      for (i = 0; i < rangelist->nelts; i++)
-        {
-          svn_revnum_t *rev_from_map;
-          svn_merge_range_t *range = APR_ARRAY_IDX(rangelist, i,
-                                                   svn_merge_range_t *);
-          rev_from_map = apr_hash_get(pb->rev_map, &range->start,
-                                      sizeof(svn_revnum_t));
-          if (rev_from_map && SVN_IS_VALID_REVNUM(*rev_from_map))
-            {
-              range->start = *rev_from_map;
-            }
-          else if (range->start == pb->oldest_old_rev - 1)
-            {
-              /* Since the start revision of svn_merge_range_t are not
-                 inclusive there is one possible valid start revision that
-                 won't be found in the PB->REV_MAP mapping of load stream
-                 revsions to loaded revisions: The revision immediately
-                 preceeding the oldest revision from the load stream.
-                 This is a valid revision for mergeinfo, but not a valid
-                 copy from revision (which PB->REV_MAP also maps for) so it
-                 will never be in the mapping.
-
-                 If that is what we have here, then find the mapping for the
-                 oldest rev from the load stream and subtract 1 to get the
-                 renumbered, non-inclusive, start revision. */
-              rev_from_map = apr_hash_get(pb->rev_map, &pb->oldest_old_rev,
-                                          sizeof(svn_revnum_t));
-              if (rev_from_map && SVN_IS_VALID_REVNUM(*rev_from_map))
-                range->start = *rev_from_map - 1;
-            }
-          else
-            {
-              /* If we can't remap the start revision then don't even bother
-                 trying to remap the end revision.  It's possible we might
-                 actually succeed at the latter, which can result in invalid
-                 mergeinfo with a start rev > end rev.  If that gets into the
-                 repository then a world of bustage breaks loose anytime that
-                 bogus mergeinfo is parsed.  See
-                 http://subversion.tigris.org/issues/show_bug.cgi?id=3020#desc16.
-                 */
-              continue;
-            }
-
-          rev_from_map = apr_hash_get(pb->rev_map, &range->end,
-                                      sizeof(svn_revnum_t));
-          if (rev_from_map && SVN_IS_VALID_REVNUM(*rev_from_map))
-            range->end = *rev_from_map;
-        }
-      apr_hash_set(final_mergeinfo, merge_source,
-                   APR_HASH_KEY_STRING, rangelist);
-    }
-
-  if (predates_stream_mergeinfo)
-      SVN_ERR(svn_mergeinfo_merge(final_mergeinfo, predates_stream_mergeinfo,
-                                  subpool));
-
-  SVN_ERR(svn_mergeinfo_sort(final_mergeinfo, subpool));
-
-  /* Mergeinfo revision sources for r0 and r1 are invalid; you can't merge r0
-     or r1.  However, svndumpfilter can be abused to produce r1 merge source
-     revs.  So if we encounter any, then strip them out, no need to put them
-     into the load target. */
-  SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(&final_mergeinfo,
-                                                    final_mergeinfo,
-                                                    1, 0, FALSE,
-                                                    subpool, subpool));
-
-  SVN_ERR(svn_mergeinfo_to_string(final_val, final_mergeinfo, pool));
-  svn_pool_destroy(subpool);
-
-  return SVN_NO_ERROR;
-}
-
-
 /* Read CONTENT_LENGTH bytes from STREAM, parsing the bytes as an
    encoded Subversion properties hash, and making multiple calls to
    PARSE_FNS->set_*_property on RECORD_BATON (depending on the value
@@ -480,38 +249,6 @@ parse_property_block(svn_stream_t *strea
               /* Now, send the property pair to the vtable! */
               if (is_node)
                 {
-                  /* svn_mergeinfo_parse() in parse_fns->set_node_property()
-                     will choke on mergeinfo with "\r\n" line endings, but we
-                     might legitimately encounter these in a dump stream.  If
-                     so normalize the line endings to '\n' and make a
-                     notification to PARSE_BATON->FEEDBACK_STREAM that we
-                     have made this correction. */
-                  if (strcmp(keybuf, SVN_PROP_MERGEINFO) == 0
-                      && strstr(propstring.data, "\r"))
-                    {
-                      const char *prop_eol_normalized;
-                      struct parse_baton *pb = parse_baton;
-
-                      SVN_ERR(svn_subst_translate_cstring2(
-                        propstring.data,
-                        &prop_eol_normalized,
-                        "\n",  /* translate to LF */
-                        FALSE, /* no repair */
-                        NULL,  /* no keywords */
-                        FALSE, /* no expansion */
-                        proppool));
-                      propstring.data = prop_eol_normalized;
-                      propstring.len = strlen(prop_eol_normalized);
-
-                      if (pb->notify_func)
-                        {
-                          pb->notify->action = 
-                            svn_repos_notify_load_normalized_mergeinfo;
-                          pb->notify_func(pb->notify_baton, pb->notify,
-                                          proppool);
-                        }
-                    }
-
                   SVN_ERR(parse_fns->set_node_property(record_baton,
                                                        keybuf,
                                                        &propstring));
@@ -663,7 +400,10 @@ parse_format_version(const char *version
 
 
 
-/* The Main Parser Logic */
+/*----------------------------------------------------------------------*/
+
+/** The public routines **/
+
 svn_error_t *
 svn_repos_parse_dumpstream2(svn_stream_t *stream,
                             const svn_repos_parse_fns2_t *parse_fns,
@@ -952,662 +692,3 @@ svn_repos_parse_dumpstream2(svn_stream_t
   svn_pool_destroy(nodepool);
   return SVN_NO_ERROR;
 }
-
-
-/*----------------------------------------------------------------------*/
-
-/** vtable for doing commits to a fs **/
-
-
-static struct node_baton *
-make_node_baton(apr_hash_t *headers,
-                struct revision_baton *rb,
-                apr_pool_t *pool)
-{
-  struct node_baton *nb = apr_pcalloc(pool, sizeof(*nb));
-  const char *val;
-
-  /* Start with sensible defaults. */
-  nb->rb = rb;
-  nb->pool = pool;
-  nb->kind = svn_node_unknown;
-
-  /* Then add info from the headers.  */
-  if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_NODE_PATH,
-                          APR_HASH_KEY_STRING)))
-  {
-    if (rb->pb->parent_dir)
-      nb->path = svn_path_join(rb->pb->parent_dir, val, pool);
-    else
-      nb->path = apr_pstrdup(pool, val);
-  }
-
-  if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_NODE_KIND,
-                          APR_HASH_KEY_STRING)))
-    {
-      if (! strcmp(val, "file"))
-        nb->kind = svn_node_file;
-      else if (! strcmp(val, "dir"))
-        nb->kind = svn_node_dir;
-    }
-
-  nb->action = (enum svn_node_action)(-1);  /* an invalid action code */
-  if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_NODE_ACTION,
-                          APR_HASH_KEY_STRING)))
-    {
-      if (! strcmp(val, "change"))
-        nb->action = svn_node_action_change;
-      else if (! strcmp(val, "add"))
-        nb->action = svn_node_action_add;
-      else if (! strcmp(val, "delete"))
-        nb->action = svn_node_action_delete;
-      else if (! strcmp(val, "replace"))
-        nb->action = svn_node_action_replace;
-    }
-
-  nb->copyfrom_rev = SVN_INVALID_REVNUM;
-  if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_NODE_COPYFROM_REV,
-                          APR_HASH_KEY_STRING)))
-    {
-      nb->copyfrom_rev = SVN_STR_TO_REV(val);
-    }
-  if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_NODE_COPYFROM_PATH,
-                          APR_HASH_KEY_STRING)))
-    {
-      if (rb->pb->parent_dir)
-        nb->copyfrom_path = svn_path_join(rb->pb->parent_dir,
-                                          (*val == '/' ? val + 1 : val), pool);
-      else
-        nb->copyfrom_path = apr_pstrdup(pool, val);
-    }
-
-  if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_TEXT_CONTENT_CHECKSUM,
-                          APR_HASH_KEY_STRING)))
-    {
-      svn_checksum_parse_hex(&nb->result_checksum, svn_checksum_md5, val, pool);
-    }
-
-  if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_TEXT_DELTA_BASE_CHECKSUM,
-                          APR_HASH_KEY_STRING)))
-    {
-      svn_checksum_parse_hex(&nb->base_checksum, svn_checksum_md5, val, pool);
-    }
-
-  if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_TEXT_COPY_SOURCE_CHECKSUM,
-                          APR_HASH_KEY_STRING)))
-    {
-      svn_checksum_parse_hex(&nb->copy_source_checksum, svn_checksum_md5, val,
-                             pool);
-    }
-
-  /* What's cool about this dump format is that the parser just
-     ignores any unrecognized headers.  :-)  */
-
-  return nb;
-}
-
-static struct revision_baton *
-make_revision_baton(apr_hash_t *headers,
-                    struct parse_baton *pb,
-                    apr_pool_t *pool)
-{
-  struct revision_baton *rb = apr_pcalloc(pool, sizeof(*rb));
-  const char *val;
-
-  rb->pb = pb;
-  rb->pool = pool;
-  rb->rev = SVN_INVALID_REVNUM;
-
-  if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_REVISION_NUMBER,
-                          APR_HASH_KEY_STRING)))
-    rb->rev = SVN_STR_TO_REV(val);
-
-  return rb;
-}
-
-
-static svn_error_t *
-new_revision_record(void **revision_baton,
-                    apr_hash_t *headers,
-                    void *parse_baton,
-                    apr_pool_t *pool)
-{
-  struct parse_baton *pb = parse_baton;
-  struct revision_baton *rb;
-  svn_revnum_t head_rev;
-
-  rb = make_revision_baton(headers, pb, pool);
-  SVN_ERR(svn_fs_youngest_rev(&head_rev, pb->fs, pool));
-
-  /* FIXME: This is a lame fallback loading multiple segments of dump in
-     several separate operations. It is highly susceptible to race conditions.
-     Calculate the revision 'offset' for finding copyfrom sources.
-     It might be positive or negative. */
-  rb->rev_offset = (apr_int32_t) (rb->rev) - (head_rev + 1);
-
-  if (rb->rev > 0)
-    {
-      /* Create a new fs txn. */
-      SVN_ERR(svn_fs_begin_txn2(&(rb->txn), pb->fs, head_rev, 0, pool));
-      SVN_ERR(svn_fs_txn_root(&(rb->txn_root), rb->txn, pool));
-
-      if (pb->notify_func)
-        {
-          pb->notify->action = svn_repos_notify_load_txn_start;
-          pb->notify->old_revision = rb->rev;
-          pb->notify_func(pb->notify_baton, pb->notify, rb->pool);
-        }
-
-      /* Stash the oldest "old" revision committed from the load stream. */
-      if (!SVN_IS_VALID_REVNUM(pb->oldest_old_rev))
-        pb->oldest_old_rev = rb->rev;
-    }
-
-  /* If we're parsing revision 0, only the revision are (possibly)
-     interesting to us: when loading the stream into an empty
-     filesystem, then we want new filesystem's revision 0 to have the
-     same props.  Otherwise, we just ignore revision 0 in the stream. */
-
-  *revision_baton = rb;
-  return SVN_NO_ERROR;
-}
-
-
-
-/* Factorized helper func for new_node_record() */
-static svn_error_t *
-maybe_add_with_history(struct node_baton *nb,
-                       struct revision_baton *rb,
-                       apr_pool_t *pool)
-{
-  struct parse_baton *pb = rb->pb;
-
-  if ((nb->copyfrom_path == NULL) || (! pb->use_history))
-    {
-      /* Add empty file or dir, without history. */
-      if (nb->kind == svn_node_file)
-        SVN_ERR(svn_fs_make_file(rb->txn_root, nb->path, pool));
-
-      else if (nb->kind == svn_node_dir)
-        SVN_ERR(svn_fs_make_dir(rb->txn_root, nb->path, pool));
-    }
-  else
-    {
-      /* Hunt down the source revision in this fs. */
-      svn_fs_root_t *copy_root;
-      svn_revnum_t src_rev = nb->copyfrom_rev - rb->rev_offset;
-      svn_revnum_t *src_rev_from_map;
-      if ((src_rev_from_map = apr_hash_get(pb->rev_map, &nb->copyfrom_rev,
-                                           sizeof(nb->copyfrom_rev))))
-        src_rev = *src_rev_from_map;
-
-      if (! SVN_IS_VALID_REVNUM(src_rev))
-        return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
-                                 _("Relative source revision %ld is not"
-                                   " available in current repository"),
-                                 src_rev);
-
-      SVN_ERR(svn_fs_revision_root(&copy_root, pb->fs, src_rev, pool));
-
-      if (nb->copy_source_checksum)
-        {
-          svn_checksum_t *checksum;
-          SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_md5, copy_root,
-                                       nb->copyfrom_path, TRUE, pool));
-          if (!svn_checksum_match(nb->copy_source_checksum, checksum))
-            return svn_error_createf
-              (SVN_ERR_CHECKSUM_MISMATCH,
-               NULL,
-               apr_psprintf(pool, "%s:\n%s\n%s\n",
-                            _("Copy source checksum mismatch on copy from '%s'@%ld\n"
-                              "to '%s' in rev based on r%ld"),
-                            _("   expected:  %s"),
-                            _("     actual:  %s")),
-               nb->copyfrom_path, src_rev,
-               nb->path, rb->rev,
-               svn_checksum_to_cstring_display(nb->copy_source_checksum, pool),
-               svn_checksum_to_cstring_display(checksum, pool));
-        }
-
-      SVN_ERR(svn_fs_copy(copy_root, nb->copyfrom_path,
-                          rb->txn_root, nb->path, pool));
-
-      if (pb->notify_func)
-        {
-          pb->notify->action = svn_repos_notify_load_copied_node;
-          pb->notify_func(pb->notify_baton, pb->notify, rb->pool);
-        }
-    }
-
-  return SVN_NO_ERROR;
-}
-
-
-static svn_error_t *
-uuid_record(const char *uuid,
-            void *parse_baton,
-            apr_pool_t *pool)
-{
-  struct parse_baton *pb = parse_baton;
-  svn_revnum_t youngest_rev;
-
-  if (pb->uuid_action == svn_repos_load_uuid_ignore)
-    return SVN_NO_ERROR;
-
-  if (pb->uuid_action != svn_repos_load_uuid_force)
-    {
-      SVN_ERR(svn_fs_youngest_rev(&youngest_rev, pb->fs, pool));
-      if (youngest_rev != 0)
-        return SVN_NO_ERROR;
-    }
-
-  return svn_fs_set_uuid(pb->fs, uuid, pool);
-}
-
-static svn_error_t *
-new_node_record(void **node_baton,
-                apr_hash_t *headers,
-                void *revision_baton,
-                apr_pool_t *pool)
-{
-  struct revision_baton *rb = revision_baton;
-  struct parse_baton *pb = rb->pb;
-  struct node_baton *nb;
-
-  if (rb->rev == 0)
-    return svn_error_create(SVN_ERR_STREAM_MALFORMED_DATA, NULL,
-                            _("Malformed dumpstream: "
-                              "Revision 0 must not contain node records"));
-
-  nb = make_node_baton(headers, rb, pool);
-
-  /* Make sure we have an action we recognize. */
-  if (nb->action < svn_node_action_change
-        || nb->action > svn_node_action_replace)
-      return svn_error_createf(SVN_ERR_STREAM_UNRECOGNIZED_DATA, NULL,
-                               _("Unrecognized node-action on node '%s'"),
-                               nb->path);
-
-  if (pb->notify_func)
-    {
-      pb->notify->action = svn_repos_notify_load_node_start;
-      pb->notify->node_action = nb->action;
-      pb->notify->path = nb->path;
-      pb->notify_func(pb->notify_baton, pb->notify, rb->pool);
-    }
-
-  switch (nb->action)
-    {
-    case svn_node_action_change:
-      break;
-
-    case svn_node_action_delete:
-      SVN_ERR(svn_fs_delete(rb->txn_root, nb->path, pool));
-      break;
-
-    case svn_node_action_add:
-      SVN_ERR(maybe_add_with_history(nb, rb, pool));
-      break;
-
-    case svn_node_action_replace:
-      SVN_ERR(svn_fs_delete(rb->txn_root, nb->path, pool));
-      SVN_ERR(maybe_add_with_history(nb, rb, pool));
-      break;
-    }
-
-  *node_baton = nb;
-  return SVN_NO_ERROR;
-}
-
-
-static svn_error_t *
-set_revision_property(void *baton,
-                      const char *name,
-                      const svn_string_t *value)
-{
-  struct revision_baton *rb = baton;
-
-  if (rb->rev > 0)
-    {
-      SVN_ERR(svn_fs_change_txn_prop(rb->txn, name, value, rb->pool));
-
-      /* Remember any datestamp that passes through!  (See comment in
-         close_revision() below.) */
-      if (! strcmp(name, SVN_PROP_REVISION_DATE))
-        rb->datestamp = svn_string_dup(value, rb->pool);
-    }
-  else if (rb->rev == 0)
-    {
-      /* Special case: set revision 0 properties when loading into an
-         'empty' filesystem. */
-      struct parse_baton *pb = rb->pb;
-      svn_revnum_t youngest_rev;
-
-      SVN_ERR(svn_fs_youngest_rev(&youngest_rev, pb->fs, rb->pool));
-
-      if (youngest_rev == 0)
-        SVN_ERR(svn_fs_change_rev_prop2(pb->fs, 0, name, NULL, value,
-                                        rb->pool));
-    }
-
-  return SVN_NO_ERROR;
-}
-
-
-static svn_error_t *
-set_node_property(void *baton,
-                  const char *name,
-                  const svn_string_t *value)
-{
-  struct node_baton *nb = baton;
-  struct revision_baton *rb = nb->rb;
-  const char *parent_dir = rb->pb->parent_dir;
-
-  if (strcmp(name, SVN_PROP_MERGEINFO) == 0)
-    {
-      /* Renumber mergeinfo as appropriate. */
-      svn_string_t *renumbered_mergeinfo;
-      SVN_ERR(renumber_mergeinfo_revs(&renumbered_mergeinfo, value, rb,
-                                      nb->pool));
-      value = renumbered_mergeinfo;
-      if (parent_dir)
-        {
-          /* Prefix the merge source paths with PARENT_DIR. */
-          /* ASSUMPTION: All source paths are included in the dump stream. */
-          svn_string_t *mergeinfo_val;
-          SVN_ERR(prefix_mergeinfo_paths(&mergeinfo_val, value, parent_dir,
-                                         nb->pool));
-          value = mergeinfo_val;
-        }
-    }
-
-  return svn_fs_change_node_prop(rb->txn_root, nb->path,
-                                 name, value, nb->pool);
-}
-
-
-static svn_error_t *
-delete_node_property(void *baton,
-                     const char *name)
-{
-  struct node_baton *nb = baton;
-  struct revision_baton *rb = nb->rb;
-
-  return svn_fs_change_node_prop(rb->txn_root, nb->path,
-                                 name, NULL, nb->pool);
-}
-
-
-static svn_error_t *
-remove_node_props(void *baton)
-{
-  struct node_baton *nb = baton;
-  struct revision_baton *rb = nb->rb;
-  apr_hash_t *proplist;
-  apr_hash_index_t *hi;
-
-  SVN_ERR(svn_fs_node_proplist(&proplist,
-                               rb->txn_root, nb->path, nb->pool));
-
-  for (hi = apr_hash_first(nb->pool, proplist); hi; hi = apr_hash_next(hi))
-    {
-      const void *key;
-
-      apr_hash_this(hi, &key, NULL, NULL);
-
-      SVN_ERR(svn_fs_change_node_prop(rb->txn_root, nb->path,
-                                      (const char *) key, NULL,
-                                      nb->pool));
-    }
-
-  return SVN_NO_ERROR;
-}
-
-
-static svn_error_t *
-apply_textdelta(svn_txdelta_window_handler_t *handler,
-                void **handler_baton,
-                void *node_baton)
-{
-  struct node_baton *nb = node_baton;
-  struct revision_baton *rb = nb->rb;
-
-  return svn_fs_apply_textdelta(handler, handler_baton,
-                                rb->txn_root, nb->path,
-                                nb->base_checksum ?
-                                svn_checksum_to_cstring(nb->base_checksum,
-                                                        nb->pool) : NULL,
-                                nb->result_checksum ?
-                                svn_checksum_to_cstring(nb->result_checksum,
-                                                        nb->pool) : NULL,
-                                nb->pool);
-}
-
-
-static svn_error_t *
-set_fulltext(svn_stream_t **stream,
-             void *node_baton)
-{
-  struct node_baton *nb = node_baton;
-  struct revision_baton *rb = nb->rb;
-
-  return svn_fs_apply_text(stream,
-                           rb->txn_root, nb->path,
-                           nb->result_checksum ?
-                           svn_checksum_to_cstring(nb->result_checksum,
-                                                   nb->pool) : NULL,
-                           nb->pool);
-}
-
-
-static svn_error_t *
-close_node(void *baton)
-{
-  struct node_baton *nb = baton;
-  struct revision_baton *rb = nb->rb;
-  struct parse_baton *pb = rb->pb;
-
-  if (pb->notify_func)
-    {
-      pb->notify->action = svn_repos_notify_load_node_done;
-      pb->notify_func(pb->notify_baton, pb->notify, rb->pool);
-    }
-
-  return SVN_NO_ERROR;
-}
-
-
-static svn_error_t *
-close_revision(void *baton)
-{
-  struct revision_baton *rb = baton;
-  struct parse_baton *pb = rb->pb;
-  const char *conflict_msg = NULL;
-  svn_revnum_t *old_rev, *new_rev;
-  svn_error_t *err;
-
-  if (rb->rev <= 0)
-    return SVN_NO_ERROR;
-
-  /* Prepare memory for saving dump-rev -> in-repos-rev mapping. */
-  old_rev = apr_palloc(pb->pool, sizeof(*old_rev) * 2);
-  new_rev = old_rev + 1;
-  *old_rev = rb->rev;
-
-  /* Run the pre-commit hook, if so commanded. */
-  if (pb->use_pre_commit_hook)
-    {
-      const char *txn_name;
-      err = svn_fs_txn_name(&txn_name, rb->txn, rb->pool);
-      if (! err)
-        err = svn_repos__hooks_pre_commit(pb->repos, txn_name, rb->pool);
-      if (err)
-        {
-          svn_error_clear(svn_fs_abort_txn(rb->txn, rb->pool));
-          return svn_error_return(err);
-        }
-    }
-
-  /* Commit. */
-  if ((err = svn_fs_commit_txn(&conflict_msg, new_rev, rb->txn, rb->pool)))
-    {
-      svn_error_clear(svn_fs_abort_txn(rb->txn, rb->pool));
-      if (conflict_msg)
-        return svn_error_quick_wrap(err, conflict_msg);
-      else
-        return svn_error_return(err);
-    }
-
-  /* Run post-commit hook, if so commanded.  */
-  if (pb->use_post_commit_hook)
-    {
-      if ((err = svn_repos__hooks_post_commit(pb->repos, *new_rev, rb->pool)))
-        return svn_error_create
-          (SVN_ERR_REPOS_POST_COMMIT_HOOK_FAILED, err,
-           _("Commit succeeded, but post-commit hook failed"));
-    }
-
-  /* After a successful commit, must record the dump-rev -> in-repos-rev
-     mapping, so that copyfrom instructions in the dump file can look up the
-     correct repository revision to copy from. */
-  apr_hash_set(pb->rev_map, old_rev, sizeof(svn_revnum_t), new_rev);
-
-  /* If the incoming dump stream has non-contiguous revisions (e.g. from
-     using svndumpfilter --drop-empty-revs without --renumber-revs) then
-     we must account for the missing gaps in PB->REV_MAP.  Otherwise we
-     might not be able to map all mergeinfo source revisions to the correct
-     revisions in the target repos. */
-  if (pb->last_rev_mapped != SVN_INVALID_REVNUM
-      && *old_rev != pb->last_rev_mapped + 1)
-    {
-      svn_revnum_t i;
-
-      /* Map all dropped revisions between PB->LAST_REV_MAPPED and OLD_REV. */
-      for (i = pb->last_rev_mapped + 1; i < *old_rev; i++)
-        {
-          svn_revnum_t *gap_rev_old = apr_palloc(pb->pool,
-                                                 sizeof(*gap_rev_old));
-          svn_revnum_t *gap_rev_new = apr_palloc(pb->pool,
-                                                 sizeof(*gap_rev_new));
-          *gap_rev_old = i;
-          *gap_rev_new = pb->last_rev_mapped;
-          apr_hash_set(pb->rev_map, gap_rev_old, sizeof(svn_revnum_t),
-                       gap_rev_new);
-        }
-    }
-  pb->last_rev_mapped = *old_rev;
-
-  /* Deltify the predecessors of paths changed in this revision. */
-  SVN_ERR(svn_fs_deltify_revision(pb->fs, *new_rev, rb->pool));
-
-  /* Grrr, svn_fs_commit_txn rewrites the datestamp property to the
-     current clock-time.  We don't want that, we want to preserve
-     history exactly.  Good thing revision props aren't versioned!
-     Note that if rb->datestamp is NULL, that's fine -- if the dump
-     data doesn't carry a datestamp, we want to preserve that fact in
-     the load. */
-  SVN_ERR(svn_fs_change_rev_prop(pb->fs, *new_rev,
-                                 SVN_PROP_REVISION_DATE, rb->datestamp,
-                                 rb->pool));
-
-  if (pb->notify_func)
-    {
-      pb->notify->action = svn_repos_notify_load_txn_committed;
-      pb->notify->new_revision = *new_rev;
-      pb->notify->old_revision = ((*new_rev == rb->rev)
-                                    ? SVN_INVALID_REVNUM
-                                    : rb->rev);
-      pb->notify_func(pb->notify_baton, pb->notify, rb->pool);
-    }
-
-  return SVN_NO_ERROR;
-}
-
-
-/*----------------------------------------------------------------------*/
-
-/** The public routines **/
-
-
-svn_error_t *
-svn_repos_get_fs_build_parser3(const svn_repos_parse_fns2_t **callbacks,
-                               void **parse_baton,
-                               svn_repos_t *repos,
-                               svn_boolean_t use_history,
-                               enum svn_repos_load_uuid uuid_action,
-                               const char *parent_dir,
-                               svn_repos_notify_func_t notify_func,
-                               void *notify_baton,
-                               apr_pool_t *pool)
-{
-  svn_repos_parse_fns2_t *parser = apr_pcalloc(pool, sizeof(*parser));
-  struct parse_baton *pb = apr_pcalloc(pool, sizeof(*pb));
-
-  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;
-  parser->set_fulltext = set_fulltext;
-  parser->close_node = close_node;
-  parser->close_revision = close_revision;
-  parser->delete_node_property = delete_node_property;
-  parser->apply_textdelta = apply_textdelta;
-
-  pb->repos = repos;
-  pb->fs = svn_repos_fs(repos);
-  pb->use_history = use_history;
-  pb->notify_func = notify_func;
-  pb->notify_baton = notify_baton;
-  pb->notify = svn_repos_notify_create(svn_repos_notify_load_txn_start, pool);
-  pb->uuid_action = uuid_action;
-  pb->parent_dir = parent_dir;
-  pb->pool = pool;
-  pb->rev_map = apr_hash_make(pool);
-  pb->oldest_old_rev = SVN_INVALID_REVNUM;
-  pb->last_rev_mapped = SVN_INVALID_REVNUM;
-
-  *callbacks = parser;
-  *parse_baton = pb;
-  return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
-svn_repos_load_fs3(svn_repos_t *repos,
-                   svn_stream_t *dumpstream,
-                   enum svn_repos_load_uuid uuid_action,
-                   const char *parent_dir,
-                   svn_boolean_t use_pre_commit_hook,
-                   svn_boolean_t use_post_commit_hook,
-                   svn_repos_notify_func_t notify_func,
-                   void *notify_baton,
-                   svn_cancel_func_t cancel_func,
-                   void *cancel_baton,
-                   apr_pool_t *pool)
-{
-  const svn_repos_parse_fns2_t *parser;
-  void *parse_baton;
-  struct parse_baton *pb;
-
-  /* This is really simple. */
-
-  SVN_ERR(svn_repos_get_fs_build_parser3(&parser, &parse_baton,
-                                         repos,
-                                         TRUE, /* look for copyfrom revs */
-                                         uuid_action,
-                                         parent_dir,
-                                         notify_func,
-                                         notify_baton,
-                                         pool));
-
-  /* Heh.  We know this is a parse_baton.  This file made it.  So
-     cast away, and set our hook booleans.  */
-  pb = parse_baton;
-  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,
-                                     cancel_func, cancel_baton, pool);
-}

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/log.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/log.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/log.c Thu Dec  2 20:55:08 2010
@@ -1034,7 +1034,10 @@ send_log(svn_revnum_t rev,
    memory. */
 #define MAX_OPEN_HISTORIES 32
 
-/* Get the histories for PATHS, and store them in *HISTORIES. */
+/* Get the histories for PATHS, and store them in *HISTORIES.
+
+   If IGNORE_MISSING_LOCATIONS is set, don't treat requests for bogus
+   repository locations as fatal -- just ignore them.  */
 static svn_error_t *
 get_path_histories(apr_array_header_t **histories,
                    svn_fs_t *fs,
@@ -1042,6 +1045,7 @@ get_path_histories(apr_array_header_t **
                    svn_revnum_t hist_start,
                    svn_revnum_t hist_end,
                    svn_boolean_t strict_node_history,
+                   svn_boolean_t ignore_missing_locations,
                    svn_repos_authz_func_t authz_read_func,
                    void *authz_read_baton,
                    apr_pool_t *pool)
@@ -1089,7 +1093,18 @@ get_path_histories(apr_array_header_t **
 
       if (i < MAX_OPEN_HISTORIES)
         {
-          SVN_ERR(svn_fs_node_history(&info->hist, root, this_path, pool));
+          svn_error_t *err;
+          err = svn_fs_node_history(&info->hist, root, this_path, pool);
+          if (err
+              && ignore_missing_locations
+              && (err->apr_err == SVN_ERR_FS_NOT_FOUND ||
+                  err->apr_err == SVN_ERR_FS_NOT_DIRECTORY ||
+                  err->apr_err == SVN_ERR_FS_NO_SUCH_REVISION))
+            {
+              svn_error_clear(err);
+              continue;
+            }
+          SVN_ERR(err);
           info->newpool = svn_pool_create(pool);
           info->oldpool = svn_pool_create(pool);
         }
@@ -1336,6 +1351,7 @@ do_logs(svn_fs_t *fs,
         svn_boolean_t discover_changed_paths,
         svn_boolean_t strict_node_history,
         svn_boolean_t include_merged_revisions,
+        svn_boolean_t ignore_missing_locations,
         const apr_array_header_t *revprops,
         svn_boolean_t descending_order,
         svn_log_entry_receiver_t receiver,
@@ -1383,24 +1399,15 @@ handle_merged_revisions(svn_revnum_t rev
   iterpool = svn_pool_create(pool);
   for (i = combined_list->nelts - 1; i >= 0; i--)
     {
-      svn_error_t *err;
       struct path_list_range *pl_range
         = APR_ARRAY_IDX(combined_list, i, struct path_list_range *);
 
       svn_pool_clear(iterpool);
-      err = do_logs(fs, pl_range->paths, pl_range->range.start,
-                    pl_range->range.end, 0, discover_changed_paths,
-                    strict_node_history, TRUE, revprops, TRUE,
-                    receiver, receiver_baton, authz_read_func,
-                    authz_read_baton, iterpool);
-      if (err && (err->apr_err == SVN_ERR_FS_NOT_FOUND ||
-                  err->apr_err == SVN_ERR_FS_NOT_DIRECTORY ||
-                  err->apr_err == SVN_ERR_FS_NO_SUCH_REVISION))
-        {
-          svn_error_clear(err);
-          continue;
-        }
-      SVN_ERR(err);
+      SVN_ERR(do_logs(fs, pl_range->paths, pl_range->range.start,
+                      pl_range->range.end, 0, discover_changed_paths,
+                      strict_node_history, TRUE, TRUE, revprops, TRUE,
+                      receiver, receiver_baton, authz_read_func,
+                      authz_read_baton, iterpool));
     }
   svn_pool_destroy(iterpool);
 
@@ -1415,6 +1422,9 @@ handle_merged_revisions(svn_revnum_t rev
    the logs back as we find them, else buffer the logs and send them back
    in youngest->oldest order.
 
+   If IGNORE_MISSING_LOCATIONS is set, don't treat requests for bogus
+   repository locations as fatal -- just ignore them.
+
    Other parameters are the same as svn_repos_get_logs4().
  */
 static svn_error_t *
@@ -1426,6 +1436,7 @@ do_logs(svn_fs_t *fs,
         svn_boolean_t discover_changed_paths,
         svn_boolean_t strict_node_history,
         svn_boolean_t include_merged_revisions,
+        svn_boolean_t ignore_missing_locations,
         const apr_array_header_t *revprops,
         svn_boolean_t descending_order,
         svn_log_entry_receiver_t receiver,
@@ -1448,8 +1459,8 @@ do_logs(svn_fs_t *fs,
      one of our paths was changed.  So let's go figure out which
      revisions contain real changes to at least one of our paths.  */
   SVN_ERR(get_path_histories(&histories, fs, paths, hist_start, hist_end,
-                             strict_node_history, authz_read_func,
-                             authz_read_baton, pool));
+                             strict_node_history, ignore_missing_locations,
+                             authz_read_func, authz_read_baton, pool));
 
   /* Loop through all the revisions in the range and add any
      where a path was changed to the array, or if they wanted
@@ -1686,7 +1697,7 @@ svn_repos_get_logs4(svn_repos_t *repos,
 
   return do_logs(repos->fs, paths, start, end, limit,
                  discover_changed_paths, strict_node_history,
-                 include_merged_revisions, revprops, descending_order,
-                 receiver, receiver_baton,
+                 include_merged_revisions, FALSE, revprops,
+                 descending_order, receiver, receiver_baton,
                  authz_read_func, authz_read_baton, pool);
 }

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/replay.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/replay.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/replay.c Thu Dec  2 20:55:08 2010
@@ -225,8 +225,13 @@ add_subdir(svn_fs_root_t *source_root,
             continue;
           else if (change->change_kind == svn_fs_path_change_replace)
             {
-              /* ### Can this assert fail? */
-              SVN_ERR_ASSERT(change->copyfrom_known);
+              if (! change->copyfrom_known)
+                {
+                  SVN_ERR(svn_fs_copied_from(&change->copyfrom_rev,
+                                             &change->copyfrom_path,
+                                             target_root, new_path, pool));
+                  change->copyfrom_known = TRUE;
+                }
               copyfrom_path = change->copyfrom_path;
               copyfrom_rev = change->copyfrom_rev;
             }

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/reporter.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/reporter.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/reporter.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/reporter.c Thu Dec  2 20:55:08 2010
@@ -84,6 +84,17 @@ typedef struct path_info_t
   apr_pool_t *pool;            /* Container pool */
 } path_info_t;
 
+/* Describes the standard revision properties that are relevant for
+   reports.  Since a particular revision will often show up more than
+   once in the report, we cache these properties for the time of the
+   report generation. */
+typedef struct revision_info_t
+{
+  svn_revnum_t rev;            /* revision number */
+  svn_string_t* date;          /* revision timestamp */
+  svn_string_t* author;        /* name of the revisions' author */
+} revision_info_t;
+
 /* A structure used by the routines within the `reporter' vtable,
    driven by the client as it describes its working copy revisions. */
 typedef struct report_baton_t
@@ -118,6 +129,11 @@ typedef struct report_baton_t
   path_info_t *lookahead;
   svn_fs_root_t *t_root;
   svn_fs_root_t *s_roots[NUM_CACHED_SOURCE_ROOTS];
+
+  /* Cache for revision properties. This is used to eliminate redundant 
+     revprop fetching. */
+  apr_hash_t* revision_infos;
+
   apr_pool_t *pool;
 } report_baton_t;
 
@@ -428,6 +444,53 @@ change_file_prop(report_baton_t *b, void
   return b->editor->change_file_prop(file_baton, name, value, pool);
 }
 
+/* For the report B, return the relevant revprop data of revision REV in
+   REVISION_INFO. The revision info will be allocated in b->pool.
+   Temporaries get allocated on SCRATCH_POOL. */
+static  svn_error_t *
+get_revision_info(report_baton_t *b,
+                  svn_revnum_t rev,
+                  revision_info_t** revision_info,
+                  apr_pool_t *scratch_pool)
+{
+  apr_hash_t *r_props;
+  svn_string_t *cdate, *author;
+  revision_info_t* info;
+
+  /* Try to find the info in the report's cache */
+  info = apr_hash_get(b->revision_infos, &rev, sizeof(rev));
+  if (!info)
+    {
+      /* Info is not available, yet. 
+         Get all revprops. */
+      SVN_ERR(svn_fs_revision_proplist(&r_props,
+                                       b->repos->fs,
+                                       rev,
+                                       scratch_pool));
+
+      /* Extract the committed-date. */
+      cdate = apr_hash_get(r_props, SVN_PROP_REVISION_DATE,
+                           APR_HASH_KEY_STRING);
+
+      /* Extract the last-author. */
+      author = apr_hash_get(r_props, SVN_PROP_REVISION_AUTHOR,
+                            APR_HASH_KEY_STRING);
+
+      /* Create a result object */
+      info = apr_palloc(b->pool, sizeof(*info));
+      info->rev = rev;
+      info->date = cdate ? svn_string_dup(cdate, b->pool) : NULL;
+      info->author = author ? svn_string_dup(author, b->pool) : NULL;
+
+      /* Cache it */
+      apr_hash_set(b->revision_infos, &rev, sizeof(rev), info);
+    }
+
+  *revision_info = info;
+  return SVN_NO_ERROR;
+}
+
+
 /* Generate the appropriate property editing calls to turn the
    properties of S_REV/S_PATH into those of B->t_root/T_PATH.  If
    S_PATH is NULL, this is an add, so assume the target starts with no
@@ -440,12 +503,13 @@ delta_proplists(report_baton_t *b, svn_r
                 void *object, apr_pool_t *pool)
 {
   svn_fs_root_t *s_root;
-  apr_hash_t *s_props, *t_props, *r_props;
+  apr_hash_t *s_props, *t_props;
   apr_array_header_t *prop_diffs;
   int i;
   svn_revnum_t crev;
   const char *uuid;
-  svn_string_t *cr_str, *cdate, *last_author;
+  svn_string_t *cr_str;
+  revision_info_t* revision_info;
   svn_boolean_t changed;
   const svn_prop_t *pc;
   svn_lock_t *lock;
@@ -459,21 +523,17 @@ delta_proplists(report_baton_t *b, svn_r
       SVN_ERR(change_fn(b, object,
                         SVN_PROP_ENTRY_COMMITTED_REV, cr_str, pool));
 
-      SVN_ERR(svn_fs_revision_proplist(&r_props, b->repos->fs, crev, pool));
+      SVN_ERR(get_revision_info(b, crev, &revision_info, pool));
 
       /* Transmit the committed-date. */
-      cdate = apr_hash_get(r_props, SVN_PROP_REVISION_DATE,
-                           APR_HASH_KEY_STRING);
-      if (cdate || s_path)
+      if (revision_info->date || s_path)
         SVN_ERR(change_fn(b, object, SVN_PROP_ENTRY_COMMITTED_DATE,
-                          cdate, pool));
+                          revision_info->date, pool));
 
       /* Transmit the last-author. */
-      last_author = apr_hash_get(r_props, SVN_PROP_REVISION_AUTHOR,
-                                 APR_HASH_KEY_STRING);
-      if (last_author || s_path)
+      if (revision_info->author || s_path)
         SVN_ERR(change_fn(b, object, SVN_PROP_ENTRY_LAST_AUTHOR,
-                          last_author, pool));
+                          revision_info->author, pool));
 
       /* Transmit the UUID. */
       SVN_ERR(svn_fs_get_uuid(b->repos->fs, &uuid, pool));
@@ -610,7 +670,7 @@ fake_dirent(const svn_fs_dirent_t **entr
       ent = apr_palloc(pool, sizeof(**entry));
       /* ### All callers should be updated to pass just one of these
              formats */
-      ent->name = (*path == '/') ? svn_uri_basename(path, pool)
+      ent->name = (*path == '/') ? svn_fspath__basename(path, pool)
                                  : svn_relpath_basename(path, pool);
       SVN_ERR(svn_fs_node_id(&ent->id, root, path, pool));
       ent->kind = kind;
@@ -1403,6 +1463,8 @@ svn_repos_begin_report2(void **report_ba
   b->edit_baton = edit_baton;
   b->authz_read_func = authz_read_func;
   b->authz_read_baton = authz_read_baton;
+  b->revision_infos = apr_hash_make(pool);
+  b->pool = pool;
 
   SVN_ERR(svn_io_open_unique_file3(&b->tempfile, NULL, NULL,
                                    svn_io_file_del_on_pool_cleanup,

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/repos.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/repos.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/repos.c Thu Dec  2 20:55:08 2010
@@ -1141,6 +1141,13 @@ create_conf(svn_repos_t *repos, apr_pool
 "### have the same password database, and vice versa.  The default realm"    NL
 "### is repository's uuid."                                                  NL
 "# realm = My First Repository"                                              NL
+"### The force-username-case option causes svnserve to case-normalize"       NL
+"### usernames before comparing them against the authorization rules in the" NL
+"### authz-db file configured above.  Valid values are \"upper\" (to upper-" NL
+"### case the usernames), \"lower\" (to lowercase the usernames), and"       NL
+"### \"none\" (to compare usernames as-is without case conversion, which"    NL
+"### is the default behavior)."                                              NL
+"# force-username-case = none"                                               NL
 ""                                                                           NL
 "[sasl]"                                                                     NL
 "### This option specifies whether you want to use the Cyrus SASL"           NL

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/rev_hunt.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/rev_hunt.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/rev_hunt.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/rev_hunt.c Thu Dec  2 20:55:08 2010
@@ -1085,47 +1085,49 @@ find_interesting_revisions(apr_array_hea
                            apr_hash_t *duplicate_path_revs,
                            svn_repos_authz_func_t authz_read_func,
                            void *authz_read_baton,
-                           apr_pool_t *pool)
+                           apr_pool_t *result_pool,
+                           apr_pool_t *scratch_pool)
 {
-  apr_pool_t *iter_pool, *last_pool;
+  apr_pool_t *iterpool, *last_pool;
   svn_fs_history_t *history;
   svn_fs_root_t *root;
   svn_node_kind_t kind;
 
   /* We switch between two pools while looping, since we need information from
      the last iteration to be available. */
-  iter_pool = svn_pool_create(pool);
-  last_pool = svn_pool_create(pool);
+  iterpool = svn_pool_create(scratch_pool);
+  last_pool = svn_pool_create(scratch_pool);
 
   /* The path had better be a file in this revision. */
-  SVN_ERR(svn_fs_revision_root(&root, repos->fs, end, last_pool));
-  SVN_ERR(svn_fs_check_path(&kind, root, path, pool));
+  SVN_ERR(svn_fs_revision_root(&root, repos->fs, end, scratch_pool));
+  SVN_ERR(svn_fs_check_path(&kind, root, path, scratch_pool));
   if (kind != svn_node_file)
     return svn_error_createf
       (SVN_ERR_FS_NOT_FILE, NULL, _("'%s' is not a file in revision %ld"),
        path, end);
 
   /* Open a history object. */
-  SVN_ERR(svn_fs_node_history(&history, root, path, last_pool));
-
+  SVN_ERR(svn_fs_node_history(&history, root, path, scratch_pool));
   while (1)
     {
-      struct path_revision *path_rev = apr_palloc(pool, sizeof(*path_rev));
+      struct path_revision *path_rev;
+      svn_revnum_t tmp_revnum;
+      const char *tmp_path;
       apr_pool_t *tmp_pool;
 
-      svn_pool_clear(iter_pool);
+      svn_pool_clear(iterpool);
 
       /* Fetch the history object to walk through. */
-      SVN_ERR(svn_fs_history_prev(&history, history, TRUE, iter_pool));
+      SVN_ERR(svn_fs_history_prev(&history, history, TRUE, iterpool));
       if (!history)
         break;
-      SVN_ERR(svn_fs_history_location(&path_rev->path, &path_rev->revnum,
-                                      history, iter_pool));
+      SVN_ERR(svn_fs_history_location(&tmp_path, &tmp_revnum,
+                                      history, iterpool));
 
       /* Check to see if we already saw this path (and it's ancestors) */
       if (include_merged_revisions
-          && is_path_in_hash(duplicate_path_revs, path_rev->path,
-                             path_rev->revnum, iter_pool))
+          && is_path_in_hash(duplicate_path_revs, tmp_path,
+                             tmp_revnum, iterpool))
          break;
 
       /* Check authorization. */
@@ -1134,21 +1136,24 @@ find_interesting_revisions(apr_array_hea
           svn_boolean_t readable;
           svn_fs_root_t *tmp_root;
 
-          SVN_ERR(svn_fs_revision_root(&tmp_root, repos->fs, path_rev->revnum,
-                                       iter_pool));
-          SVN_ERR(authz_read_func(&readable, tmp_root, path_rev->path,
-                                  authz_read_baton, iter_pool));
+          SVN_ERR(svn_fs_revision_root(&tmp_root, repos->fs, tmp_revnum,
+                                       iterpool));
+          SVN_ERR(authz_read_func(&readable, tmp_root, tmp_path,
+                                  authz_read_baton, iterpool));
           if (! readable)
             break;
         }
 
-      path_rev->path = apr_pstrdup(pool, path_rev->path);
+      /* We didn't break, so we must really want this path-rev. */
+      path_rev = apr_palloc(result_pool, sizeof(*path_rev));
+      path_rev->path = apr_pstrdup(result_pool, tmp_path);
+      path_rev->revnum = tmp_revnum;
       path_rev->merged = mark_as_merged;
       APR_ARRAY_PUSH(path_revisions, struct path_revision *) = path_rev;
 
       if (include_merged_revisions)
         SVN_ERR(get_merged_mergeinfo(&path_rev->merged_mergeinfo, repos,
-                                     path_rev, pool));
+                                     path_rev, result_pool));
       else
         path_rev->merged_mergeinfo = NULL;
 
@@ -1156,7 +1161,7 @@ find_interesting_revisions(apr_array_hea
          occurrences of it.  We only care about this if including merged
          revisions, 'cause that's the only time we can have duplicates. */
       apr_hash_set(duplicate_path_revs,
-                   apr_psprintf(pool, "%s:%ld", path_rev->path,
+                   apr_psprintf(result_pool, "%s:%ld", path_rev->path,
                                 path_rev->revnum),
                    APR_HASH_KEY_STRING, (void *)0xdeadbeef);
 
@@ -1164,12 +1169,13 @@ find_interesting_revisions(apr_array_hea
         break;
 
       /* Swap pools. */
-      tmp_pool = iter_pool;
-      iter_pool = last_pool;
+      tmp_pool = iterpool;
+      iterpool = last_pool;
       last_pool = tmp_pool;
     }
 
-  svn_pool_destroy(iter_pool);
+  svn_pool_destroy(iterpool);
+  svn_pool_destroy(last_pool);
 
   return SVN_NO_ERROR;
 }
@@ -1198,12 +1204,12 @@ find_merged_revisions(apr_array_header_t
 {
   const apr_array_header_t *old;
   apr_array_header_t *new;
-  apr_pool_t *iter_pool, *last_pool;
+  apr_pool_t *iterpool, *last_pool;
   apr_array_header_t *merged_path_revisions = apr_array_make(pool, 0,
                                                 sizeof(struct path_revision *));
 
   old = mainline_path_revisions;
-  iter_pool = svn_pool_create(pool);
+  iterpool = svn_pool_create(pool);
   last_pool = svn_pool_create(pool);
 
   do
@@ -1211,27 +1217,34 @@ find_merged_revisions(apr_array_header_t
       int i;
       apr_pool_t *temp_pool;
 
-      svn_pool_clear(iter_pool);
-      new = apr_array_make(iter_pool, 0, sizeof(struct path_revision *));
+      svn_pool_clear(iterpool);
+      new = apr_array_make(iterpool, 0, sizeof(struct path_revision *));
 
       /* Iterate over OLD, checking for non-empty mergeinfo.  If found, gather
          path_revisions for any merged revisions, and store those in NEW. */
       for (i = 0; i < old->nelts; i++)
         {
+          apr_pool_t *iterpool2;
           apr_hash_index_t *hi;
           struct path_revision *old_pr = APR_ARRAY_IDX(old, i,
                                                        struct path_revision *);
           if (!old_pr->merged_mergeinfo)
             continue;
 
+          iterpool2 = svn_pool_create(iterpool);
+
           /* Determine and trace the merge sources. */
-          for (hi = apr_hash_first(iter_pool, old_pr->merged_mergeinfo); hi;
+          for (hi = apr_hash_first(iterpool, old_pr->merged_mergeinfo); hi;
                hi = apr_hash_next(hi))
             {
+              apr_pool_t *iterpool3;
               apr_array_header_t *rangelist;
               const char *path;
               int j;
 
+              svn_pool_clear(iterpool2);
+              iterpool3 = svn_pool_create(iterpool2);
+
               apr_hash_this(hi, (void *) &path, NULL, (void *) &rangelist);
 
               for (j = 0; j < rangelist->nelts; j++)
@@ -1241,9 +1254,10 @@ find_merged_revisions(apr_array_header_t
                   svn_node_kind_t kind;
                   svn_fs_root_t *root;
 
+                  svn_pool_clear(iterpool3);
                   SVN_ERR(svn_fs_revision_root(&root, repos->fs, range->end,
-                                               iter_pool));
-                  SVN_ERR(svn_fs_check_path(&kind, root, path, iter_pool));
+                                               iterpool3));
+                  SVN_ERR(svn_fs_check_path(&kind, root, path, iterpool3));
                   if (kind != svn_node_file)
                     continue;
 
@@ -1253,20 +1267,23 @@ find_merged_revisions(apr_array_header_t
                                                      TRUE, TRUE,
                                                      duplicate_path_revs,
                                                      authz_read_func,
-                                                     authz_read_baton, pool));
+                                                     authz_read_baton, pool,
+                                                     iterpool3));
                 }
+              svn_pool_destroy(iterpool3);
             }
+          svn_pool_destroy(iterpool2);
         }
 
       /* Append the newly found path revisions with the old ones. */
-      merged_path_revisions = apr_array_append(iter_pool, merged_path_revisions,
+      merged_path_revisions = apr_array_append(iterpool, merged_path_revisions,
                                                new);
 
       /* Swap data structures */
       old = new;
       temp_pool = last_pool;
-      last_pool = iter_pool;
-      iter_pool = temp_pool;
+      last_pool = iterpool;
+      iterpool = temp_pool;
     }
   while (new->nelts > 0);
 
@@ -1277,7 +1294,7 @@ find_merged_revisions(apr_array_header_t
   /* Copy to the output array. */
   *merged_path_revisions_out = apr_array_copy(pool, merged_path_revisions);
 
-  svn_pool_destroy(iter_pool);
+  svn_pool_destroy(iterpool);
   svn_pool_destroy(last_pool);
 
   return SVN_NO_ERROR;
@@ -1413,7 +1430,8 @@ svn_repos_get_file_revs2(svn_repos_t *re
   SVN_ERR(find_interesting_revisions(mainline_path_revisions, repos, path,
                                      start, end, include_merged_revisions,
                                      FALSE, duplicate_path_revs,
-                                     authz_read_func, authz_read_baton, pool));
+                                     authz_read_func, authz_read_baton, pool,
+                                     pool));
 
   /* If we are including merged revisions, go get those, too. */
   if (include_merged_revisions)

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/checksum.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/checksum.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/checksum.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/checksum.c Thu Dec  2 20:55:08 2010
@@ -135,6 +135,9 @@ const char *
 svn_checksum_to_cstring(const svn_checksum_t *checksum,
                         apr_pool_t *pool)
 {
+  if (checksum == NULL)
+    return NULL;
+
   switch (checksum->kind)
     {
       case svn_checksum_md5:

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/config_file.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/config_file.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/config_file.c Thu Dec  2 20:55:08 2010
@@ -38,6 +38,11 @@
 
 #include "svn_private_config.h"
 
+#ifdef __HAIKU__
+#  include <FindDirectory.h>
+#  include <StorageDefs.h>
+#endif
+
 /* Used to terminate lines in large multi-line string literals. */
 #define NL APR_EOL_STR
 
@@ -331,7 +336,19 @@ svn_config__sys_config_path(const char *
                                    SVN_CONFIG__SUBDIRECTORY, fname, NULL);
   }
 
-#else  /* ! WIN32 */
+#elif defined(__HAIKU__)
+  {
+    char folder[B_PATH_NAME_LENGTH];
+
+    status_t error = find_directory(B_COMMON_SETTINGS_DIRECTORY, -1, false,
+                                    folder, sizeof(folder));
+    if (error)
+      return SVN_NO_ERROR;
+
+    *path_p = svn_dirent_join_many(pool, folder,
+                                   SVN_CONFIG__SYS_DIRECTORY, fname, NULL);
+  }
+#else  /* ! WIN32 && !__HAIKU__ */
 
   *path_p = svn_dirent_join_many(pool, SVN_CONFIG__SYS_DIRECTORY, fname, NULL);
 
@@ -1118,7 +1135,20 @@ svn_config_get_user_config_path(const ch
                                  SVN_CONFIG__SUBDIRECTORY, fname, NULL);
   }
 
-#else  /* ! WIN32 */
+#elif defined(__HAIKU__)
+  {
+    char folder[B_PATH_NAME_LENGTH];
+
+    status_t error = find_directory(B_USER_SETTINGS_DIRECTORY, -1, false,
+                                    folder, sizeof(folder));
+    if (error)
+      return SVN_NO_ERROR;
+
+    *path = svn_dirent_join_many(pool, folder,
+                                 SVN_CONFIG__USR_DIRECTORY, fname, NULL);
+  }
+#else  /* ! WIN32 && !__HAIKU__ */
+
   {
     const char *homedir = svn_user_get_homedir(pool);
     if (! homedir)

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/config_impl.h
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/config_impl.h?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/config_impl.h (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/config_impl.h Thu Dec  2 20:55:08 2010
@@ -114,7 +114,10 @@ svn_error_t *svn_config__parse_registry(
    or svn_config_get_user_config_path() instead. */
 #ifdef WIN32
 #  define SVN_CONFIG__SUBDIRECTORY    "Subversion"
-#else  /* ! WIN32 */
+#elif defined __HAIKU__ /* HAIKU */
+#  define SVN_CONFIG__SYS_DIRECTORY   "subversion"
+#  define SVN_CONFIG__USR_DIRECTORY   "subversion"
+#else  /* ! WIN32 && ! __HAIKU__ */
 #  define SVN_CONFIG__SYS_DIRECTORY   "/etc/subversion"
 #  define SVN_CONFIG__USR_DIRECTORY   ".subversion"
 #endif /* WIN32 */

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/constructors.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/constructors.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/constructors.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/constructors.c Thu Dec  2 20:55:08 2010
@@ -45,7 +45,8 @@ svn_commit_info_t *
 svn_commit_info_dup(const svn_commit_info_t *src_commit_info,
                     apr_pool_t *pool)
 {
-  svn_commit_info_t *dst_commit_info = svn_create_commit_info(pool);
+  svn_commit_info_t *dst_commit_info
+    = apr_palloc(pool, sizeof(*dst_commit_info));
 
   dst_commit_info->date = src_commit_info->date
     ? apr_pstrdup(pool, src_commit_info->date) : NULL;
@@ -66,6 +67,9 @@ svn_log_changed_path2_create(apr_pool_t 
   svn_log_changed_path2_t *new_changed_path
     = apr_pcalloc(pool, sizeof(*new_changed_path));
 
+  new_changed_path->text_modified = svn_tristate_unknown;
+  new_changed_path->props_modified = svn_tristate_unknown;
+
   return new_changed_path;
 }
 
@@ -74,7 +78,7 @@ svn_log_changed_path2_dup(const svn_log_
                           apr_pool_t *pool)
 {
   svn_log_changed_path2_t *new_changed_path
-    = svn_log_changed_path2_create(pool);
+    = apr_palloc(pool, sizeof(*new_changed_path));
 
   *new_changed_path = *changed_path;
 
@@ -190,7 +194,7 @@ svn_log_entry_t *
 svn_log_entry_dup(const svn_log_entry_t *log_entry, apr_pool_t *pool)
 {
   apr_hash_index_t *hi;
-  svn_log_entry_t *new_entry = svn_log_entry_create(pool);
+  svn_log_entry_t *new_entry = apr_palloc(pool, sizeof(*new_entry));
 
   *new_entry = *log_entry;
 
@@ -228,7 +232,8 @@ svn_location_segment_dup(const svn_locat
                          apr_pool_t *pool)
 {
   svn_location_segment_t *new_segment =
-    apr_pcalloc(pool, sizeof(*new_segment));
+    apr_palloc(pool, sizeof(*new_segment));
+
   *new_segment = *segment;
   if (segment->path)
     new_segment->path = apr_pstrdup(pool, segment->path);