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 2015/01/28 00:27:46 UTC

svn commit: r1655189 [7/9] - in /subversion/branches/svn-auth-x509: ./ build/ build/generator/ subversion/bindings/javahl/native/ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_fs_base/ subversion/libsvn_fs_...

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_repos/dump.c?rev=1655189&r1=1655188&r2=1655189&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_repos/dump.c Tue Jan 27 23:27:44 2015
@@ -38,6 +38,7 @@
 #include "svn_props.h"
 #include "svn_sorts.h"
 
+#include "private/svn_repos_private.h"
 #include "private/svn_mergeinfo_private.h"
 #include "private/svn_fs_private.h"
 #include "private/svn_sorts_private.h"
@@ -356,6 +357,7 @@ store_delta(apr_file_t **tempfile, svn_f
    with message WARNING_FMT formatted with the remaining variable arguments.
    Send it by calling NOTIFY_FUNC (if not null) with NOTIFY_BATON.
  */
+__attribute__((format(printf, 5, 6)))
 static void
 notify_warning(apr_pool_t *scratch_pool,
                svn_repos_notify_func_t notify_func,
@@ -382,6 +384,231 @@ notify_warning(apr_pool_t *scratch_pool,
 
 /*----------------------------------------------------------------------*/
 
+/* Write to STREAM the header in HEADERS named KEY, if present.
+ */
+static svn_error_t *
+write_header(svn_stream_t *stream,
+             apr_hash_t *headers,
+             const char *key,
+             apr_pool_t *scratch_pool)
+{
+  const char *val = svn_hash_gets(headers, key);
+
+  if (val)
+    {
+      SVN_ERR(svn_stream_printf(stream, scratch_pool,
+                                "%s: %s\n", key, val));
+    }
+  return SVN_NO_ERROR;
+}
+
+/* Write headers, in arbitrary order.
+ * ### TODO: use a stable order
+ * ### Modifies HEADERS.
+ */
+static svn_error_t *
+write_revision_headers(svn_stream_t *stream,
+                       apr_hash_t *headers,
+                       apr_pool_t *scratch_pool)
+{
+  const char **h;
+  apr_hash_index_t *hi;
+
+  static const char *revision_headers_order[] =
+  {
+    SVN_REPOS_DUMPFILE_REVISION_NUMBER,  /* must be first */
+    NULL
+  };
+
+  /* Write some headers in a given order */
+  for (h = revision_headers_order; *h; h++)
+    {
+      SVN_ERR(write_header(stream, headers, *h, scratch_pool));
+      svn_hash_sets(headers, *h, NULL);
+    }
+
+  /* Write any and all remaining headers except Content-length.
+   * ### TODO: use a stable order
+   */
+  for (hi = apr_hash_first(scratch_pool, headers); hi; hi = apr_hash_next(hi))
+    {
+      const char *key = apr_hash_this_key(hi);
+
+      if (strcmp(key, SVN_REPOS_DUMPFILE_CONTENT_LENGTH) != 0)
+        SVN_ERR(write_header(stream, headers, key, scratch_pool));
+    }
+
+  /* Content-length must be last */
+  SVN_ERR(write_header(stream, headers, SVN_REPOS_DUMPFILE_CONTENT_LENGTH,
+                       scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+apr_array_header_t *
+svn_repos__dumpfile_headers_create(apr_pool_t *pool)
+{
+  apr_array_header_t *headers
+    = apr_array_make(pool, 5, sizeof(svn_repos__dumpfile_header_entry_t));
+
+  return headers;
+}
+
+void
+svn_repos__dumpfile_header_push(apr_array_header_t *headers,
+                                const char *key,
+                                const char *val)
+{
+  svn_repos__dumpfile_header_entry_t *h
+    = &APR_ARRAY_PUSH(headers, svn_repos__dumpfile_header_entry_t);
+
+  h->key = apr_pstrdup(headers->pool, key);
+  h->val = apr_pstrdup(headers->pool, val);
+}
+
+void
+svn_repos__dumpfile_header_pushf(apr_array_header_t *headers,
+                                 const char *key,
+                                 const char *val_fmt,
+                                 ...)
+{
+  va_list ap;
+  svn_repos__dumpfile_header_entry_t *h
+    = &APR_ARRAY_PUSH(headers, svn_repos__dumpfile_header_entry_t);
+
+  h->key = apr_pstrdup(headers->pool, key);
+  va_start(ap, val_fmt);
+  h->val = apr_pvsprintf(headers->pool, val_fmt, ap);
+  va_end(ap);
+}
+
+svn_error_t *
+svn_repos__dump_headers(svn_stream_t *stream,
+                        apr_array_header_t *headers,
+                        svn_boolean_t terminate,
+                        apr_pool_t *scratch_pool)
+{
+  int i;
+
+  for (i = 0; i < headers->nelts; i++)
+    {
+      svn_repos__dumpfile_header_entry_t *h
+        = &APR_ARRAY_IDX(headers, i, svn_repos__dumpfile_header_entry_t);
+
+      SVN_ERR(svn_stream_printf(stream, scratch_pool,
+                                "%s: %s\n", h->key, h->val));
+    }
+
+  /* End of headers */
+  if (terminate)
+    SVN_ERR(svn_stream_puts(stream, "\n"));
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_repos__dump_revision_record(svn_stream_t *dump_stream,
+                                svn_revnum_t revision,
+                                apr_hash_t *extra_headers,
+                                apr_hash_t *revprops,
+                                svn_boolean_t props_section_always,
+                                apr_pool_t *scratch_pool)
+{
+  svn_stringbuf_t *propstring = NULL;
+  apr_hash_t *headers;
+
+  if (extra_headers)
+    headers = apr_hash_copy(scratch_pool, extra_headers);
+  else
+    headers = apr_hash_make(scratch_pool);
+
+  /* ### someday write a revision-content-checksum */
+
+  svn_hash_sets(headers, SVN_REPOS_DUMPFILE_REVISION_NUMBER,
+                apr_psprintf(scratch_pool, "%ld", revision));
+
+  if (apr_hash_count(revprops) || props_section_always)
+    {
+      svn_stream_t *propstream;
+
+      propstring = svn_stringbuf_create_empty(scratch_pool);
+      propstream = svn_stream_from_stringbuf(propstring, scratch_pool);
+      SVN_ERR(svn_hash_write2(revprops, propstream, "PROPS-END", scratch_pool));
+      SVN_ERR(svn_stream_close(propstream));
+
+      svn_hash_sets(headers, SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH,
+                    apr_psprintf(scratch_pool,
+                                 "%" APR_SIZE_T_FMT, propstring->len));
+    }
+
+  /* Write out a regular Content-length header for the benefit of
+     non-Subversion RFC-822 parsers. */
+  svn_hash_sets(headers, SVN_REPOS_DUMPFILE_CONTENT_LENGTH,
+                apr_psprintf(scratch_pool,
+                             "%" APR_SIZE_T_FMT, propstring->len));
+  SVN_ERR(write_revision_headers(dump_stream, headers, scratch_pool));
+
+  /* End of headers */
+  SVN_ERR(svn_stream_puts(dump_stream, "\n"));
+
+  /* Property data. */
+  if (propstring)
+    {
+      SVN_ERR(svn_stream_write(dump_stream, propstring->data, &propstring->len));
+    }
+
+  /* put an end to revision */
+  SVN_ERR(svn_stream_puts(dump_stream, "\n"));
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_repos__dump_node_record(svn_stream_t *dump_stream,
+                            apr_array_header_t *headers,
+                            svn_stringbuf_t *props_str,
+                            svn_boolean_t has_text,
+                            svn_filesize_t text_content_length,
+                            svn_boolean_t content_length_always,
+                            apr_pool_t *scratch_pool)
+{
+  svn_filesize_t content_length = 0;
+
+  /* add content-length headers */
+  if (props_str)
+    {
+      svn_repos__dumpfile_header_pushf(
+        headers, SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH,
+        "%" APR_SIZE_T_FMT, props_str->len);
+      content_length += props_str->len;
+    }
+  if (has_text)
+    {
+      svn_repos__dumpfile_header_pushf(
+        headers, SVN_REPOS_DUMPFILE_TEXT_CONTENT_LENGTH,
+        "%" SVN_FILESIZE_T_FMT, text_content_length);
+      content_length += text_content_length;
+    }
+  if (content_length_always || props_str || has_text)
+    {
+      svn_repos__dumpfile_header_pushf(
+        headers, SVN_REPOS_DUMPFILE_CONTENT_LENGTH,
+        "%" SVN_FILESIZE_T_FMT, content_length);
+    }
+
+  /* write the headers */
+  SVN_ERR(svn_repos__dump_headers(dump_stream, headers, TRUE, scratch_pool));
+
+  /* write the props */
+  if (props_str)
+    {
+      SVN_ERR(svn_stream_write(dump_stream, props_str->data, &props_str->len));
+    }
+  return SVN_NO_ERROR;
+}
+
+/*----------------------------------------------------------------------*/
+
 /** An editor which dumps node-data in 'dumpfile format' to a file. **/
 
 /* Look, mom!  No file batons! */
@@ -434,10 +661,6 @@ struct edit_baton
 struct dir_baton
 {
   struct edit_baton *edit_baton;
-  struct dir_baton *parent_dir_baton;
-
-  /* is this directory a new addition to this revision? */
-  svn_boolean_t added;
 
   /* has this directory been written to the output stream? */
   svn_boolean_t written_out;
@@ -477,21 +700,19 @@ struct dir_baton
    path, SVN_INVALID_REVNUM for the rev), just compare this directory
    PATH against itself in the previous revision.
 
-   PARENT_DIR_BATON is the directory baton of this directory's parent,
-   or NULL if this is the top-level directory of the edit.  ADDED
-   indicated if this directory is newly added in this revision.
+   PB is the directory baton of this directory's parent,
+   or NULL if this is the top-level directory of the edit.
+
    Perform all allocations in POOL.  */
 static struct dir_baton *
 make_dir_baton(const char *path,
                const char *cmp_path,
                svn_revnum_t cmp_rev,
                void *edit_baton,
-               void *parent_dir_baton,
-               svn_boolean_t added,
+               struct dir_baton *pb,
                apr_pool_t *pool)
 {
   struct edit_baton *eb = edit_baton;
-  struct dir_baton *pb = parent_dir_baton;
   struct dir_baton *new_db = apr_pcalloc(pool, sizeof(*new_db));
   const char *full_path;
 
@@ -509,11 +730,9 @@ make_dir_baton(const char *path,
     cmp_path = svn_relpath_canonicalize(cmp_path, pool);
 
   new_db->edit_baton = eb;
-  new_db->parent_dir_baton = pb;
   new_db->path = full_path;
   new_db->cmp_path = cmp_path;
   new_db->cmp_rev = cmp_rev;
-  new_db->added = added;
   new_db->written_out = FALSE;
   new_db->deleted_entries = apr_hash_make(pool);
   new_db->check_name_collision = FALSE;
@@ -815,6 +1034,34 @@ check_mergeinfo_normalization(const char
 }
 
 
+/* A special case of dump_node(), for a delete record.
+ *
+ * The only thing special about this version is it only writes one blank
+ * line, not two, after the headers. Why? Historical precedent for the
+ * case where a delete record is used as part of a (delete + add-with-history)
+ * in implementing a replacement.
+ *
+ * Also it doesn't do a path-tracker check.
+ */
+static svn_error_t *
+dump_node_delete(svn_stream_t *stream,
+                 const char *node_relpath,
+                 apr_pool_t *pool)
+{
+  apr_array_header_t *headers = svn_repos__dumpfile_headers_create(pool);
+
+  /* Node-path: ... */
+  svn_repos__dumpfile_header_push(
+    headers, SVN_REPOS_DUMPFILE_NODE_PATH, node_relpath);
+
+  /* Node-action: delete */
+  svn_repos__dumpfile_header_push(
+    headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "delete");
+
+  SVN_ERR(svn_repos__dump_headers(stream, headers, TRUE, pool));
+  return SVN_NO_ERROR;
+}
+
 /* This helper is the main "meat" of the editor -- it does all the
    work of writing a node record.
 
@@ -838,13 +1085,14 @@ dump_node(struct edit_baton *eb,
           apr_pool_t *pool)
 {
   svn_stringbuf_t *propstring;
-  svn_filesize_t content_length = 0;
   apr_size_t len;
   svn_boolean_t must_dump_text = FALSE, must_dump_props = FALSE;
   const char *compare_path = path;
   svn_revnum_t compare_rev = eb->current_rev - 1;
   svn_fs_root_t *compare_root = NULL;
   apr_file_t *delta_file = NULL;
+  apr_array_header_t *headers = svn_repos__dumpfile_headers_create(pool);
+  svn_filesize_t textlen;
 
   /* Maybe validate the path. */
   if (eb->verify || eb->notify_func)
@@ -873,15 +1121,14 @@ dump_node(struct edit_baton *eb,
     }
 
   /* Write out metadata headers for this file node. */
-  SVN_ERR(svn_stream_printf(eb->stream, pool,
-                            SVN_REPOS_DUMPFILE_NODE_PATH ": %s\n",
-                            path));
+  svn_repos__dumpfile_header_push(
+    headers, SVN_REPOS_DUMPFILE_NODE_PATH, path);
   if (kind == svn_node_file)
-    SVN_ERR(svn_stream_puts(eb->stream,
-                            SVN_REPOS_DUMPFILE_NODE_KIND ": file\n"));
+    svn_repos__dumpfile_header_push(
+      headers, SVN_REPOS_DUMPFILE_NODE_KIND, "file");
   else if (kind == svn_node_dir)
-    SVN_ERR(svn_stream_puts(eb->stream,
-                            SVN_REPOS_DUMPFILE_NODE_KIND ": dir\n"));
+    svn_repos__dumpfile_header_push(
+      headers, SVN_REPOS_DUMPFILE_NODE_KIND, "dir");
 
   /* Remove leading slashes from copyfrom paths. */
   if (cmp_path)
@@ -894,15 +1141,16 @@ dump_node(struct edit_baton *eb,
       compare_rev = cmp_rev;
     }
 
-  if (action == svn_node_action_change)
+  switch (action)
     {
+    case svn_node_action_change:
       if (eb->path_tracker)
         SVN_ERR_W(node_must_exist(eb, path, eb->current_rev, kind, pool),
                   apr_psprintf(pool, _("Change invalid path '%s' in r%ld"),
                                path, eb->current_rev));
 
-      SVN_ERR(svn_stream_puts(eb->stream,
-                              SVN_REPOS_DUMPFILE_NODE_ACTION ": change\n"));
+      svn_repos__dumpfile_header_push(
+        headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "change");
 
       /* either the text or props changed, or possibly both. */
       SVN_ERR(svn_fs_revision_root(&compare_root,
@@ -916,9 +1164,27 @@ dump_node(struct edit_baton *eb,
         SVN_ERR(svn_fs_contents_different(&must_dump_text,
                                           compare_root, compare_path,
                                           eb->fs_root, path, pool));
-    }
-  else if (action == svn_node_action_replace)
-    {
+      break;
+
+    case svn_node_action_delete:
+      if (eb->path_tracker)
+        {
+          SVN_ERR_W(node_must_exist(eb, path, eb->current_rev, kind, pool),
+                    apr_psprintf(pool, _("Deleting invalid path '%s' in r%ld"),
+                                 path, eb->current_rev));
+          tracker_path_delete(eb->path_tracker, path);
+        }
+
+      svn_repos__dumpfile_header_push(
+        headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "delete");
+
+      /* we can leave this routine quietly now, don't need to dump
+         any content. */
+      must_dump_text = FALSE;
+      must_dump_props = FALSE;
+      break;
+
+    case svn_node_action_replace:
       if (eb->path_tracker)
         SVN_ERR_W(node_must_exist(eb, path, eb->current_rev,
                                   svn_node_unknown, pool),
@@ -932,77 +1198,43 @@ dump_node(struct edit_baton *eb,
             tracker_path_replace(eb->path_tracker, path);
 
           /* a simple delete+add, implied by a single 'replace' action. */
-          SVN_ERR(svn_stream_puts(eb->stream,
-                                  SVN_REPOS_DUMPFILE_NODE_ACTION
-                                  ": replace\n"));
+          svn_repos__dumpfile_header_push(
+            headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "replace");
 
           /* definitely need to dump all content for a replace. */
           if (kind == svn_node_file)
             must_dump_text = TRUE;
           must_dump_props = TRUE;
+          break;
         }
       else
         {
+          /* more complex:  delete original, then add-with-history.  */
+          /* ### Why not write a 'replace' record? Don't know. */
+
           if (eb->path_tracker)
             {
-              SVN_ERR_W(node_must_exist(eb, compare_path, compare_rev,
-                                        kind, pool),
-                        apr_psprintf(pool,
-                                     _("Replacing path '%s' in r%ld "
-                                       "with invalid path"),
-                                     path, eb->current_rev));
-
-              /* we will call dump_node again with an addition further
-                 down the road */
               tracker_path_delete(eb->path_tracker, path);
             }
 
-          /* more complex:  delete original, then add-with-history.  */
+          /* ### Unusually, we end this 'delete' node record with only a single
+                 blank line after the header block -- no extra blank line. */
+          SVN_ERR(dump_node_delete(eb->stream, path, pool));
 
-          /* the path & kind headers have already been printed;  just
-             add a delete action, and end the current record.*/
-          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,
-                            is_copy, compare_path, compare_rev, pool));
-
-          /* we can leave this routine quietly now, don't need to dump
-             any content;  that was already done in the second record. */
-          must_dump_text = FALSE;
-          must_dump_props = FALSE;
-        }
-    }
-  else if (action == svn_node_action_delete)
-    {
-      if (eb->path_tracker)
-        {
-          SVN_ERR_W(node_must_exist(eb, path, eb->current_rev, kind, pool),
-                    apr_psprintf(pool, _("Deleting invalid path '%s' in r%ld"),
-                                 path, eb->current_rev));
-          tracker_path_delete(eb->path_tracker, path);
+          /* The remaining action is a non-replacing add-with-history */
+          /* action = svn_node_action_add; */
         }
+      /* FALL THROUGH to 'add' */
 
-      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. */
-      must_dump_text = FALSE;
-      must_dump_props = FALSE;
-    }
-  else if (action == svn_node_action_add)
-    {
+    case svn_node_action_add:
       if (eb->path_tracker)
         SVN_ERR_W(node_must_not_exist(eb, path, eb->current_rev, pool),
                   apr_psprintf(pool,
                                _("Adding already existing path '%s' in r%ld"),
                                path, eb->current_rev));
 
-      SVN_ERR(svn_stream_puts(eb->stream,
-                              SVN_REPOS_DUMPFILE_NODE_ACTION ": add\n"));
+      svn_repos__dumpfile_header_push(
+        headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "add");
 
       if (! is_copy)
         {
@@ -1043,12 +1275,10 @@ dump_node(struct edit_baton *eb,
                 *eb->found_old_reference = TRUE;
             }
 
-          SVN_ERR(svn_stream_printf(eb->stream, pool,
-                                    SVN_REPOS_DUMPFILE_NODE_COPYFROM_REV
-                                    ": %ld\n"
-                                    SVN_REPOS_DUMPFILE_NODE_COPYFROM_PATH
-                                    ": %s\n",
-                                    cmp_rev, cmp_path));
+          svn_repos__dumpfile_header_pushf(
+            headers, SVN_REPOS_DUMPFILE_NODE_COPYFROM_REV, "%ld", cmp_rev);
+          svn_repos__dumpfile_header_push(
+            headers, SVN_REPOS_DUMPFILE_NODE_COPYFROM_PATH, cmp_path);
 
           SVN_ERR(svn_fs_revision_root(&compare_root,
                                        svn_fs_root_fs(eb->fs_root),
@@ -1072,20 +1302,19 @@ dump_node(struct edit_baton *eb,
                                            FALSE, pool));
               hex_digest = svn_checksum_to_cstring(checksum, pool);
               if (hex_digest)
-                SVN_ERR(svn_stream_printf(eb->stream, pool,
-                                      SVN_REPOS_DUMPFILE_TEXT_COPY_SOURCE_MD5
-                                      ": %s\n", hex_digest));
+                svn_repos__dumpfile_header_push(
+                  headers, SVN_REPOS_DUMPFILE_TEXT_COPY_SOURCE_MD5, hex_digest);
 
               SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1,
                                            compare_root, compare_path,
                                            FALSE, pool));
               hex_digest = svn_checksum_to_cstring(checksum, pool);
               if (hex_digest)
-                SVN_ERR(svn_stream_printf(eb->stream, pool,
-                                      SVN_REPOS_DUMPFILE_TEXT_COPY_SOURCE_SHA1
-                                      ": %s\n", hex_digest));
+                svn_repos__dumpfile_header_push(
+                  headers, SVN_REPOS_DUMPFILE_TEXT_COPY_SOURCE_SHA1, hex_digest);
             }
         }
+      break;
     }
 
   if ((! must_dump_text) && (! must_dump_props))
@@ -1095,8 +1324,9 @@ dump_node(struct edit_baton *eb,
          then our dumpstream format demands that at a *minimum*, we
          see a lone "PROPS-END" as a divider between text and props
          content within the content-block. */
-      len = 2;
-      return svn_stream_write(eb->stream, "\n\n", &len); /* ### needed? */
+      SVN_ERR(svn_repos__dump_headers(eb->stream, headers, TRUE, pool));
+      len = 1;
+      return svn_stream_write(eb->stream, "\n", &len); /* ### needed? */
     }
 
   /*** Start prepping content to dump... ***/
@@ -1107,7 +1337,6 @@ dump_node(struct edit_baton *eb,
   if (must_dump_props)
     {
       apr_hash_t *prophash, *oldhash = NULL;
-      apr_size_t proplen;
       svn_stream_t *propstream;
 
       SVN_ERR(svn_fs_node_proplist(&prophash, eb->fs_root, path, pool));
@@ -1165,8 +1394,8 @@ dump_node(struct edit_baton *eb,
           if (!oldhash)         /* May have been set for normalization check */
             SVN_ERR(svn_fs_node_proplist(&oldhash, compare_root, compare_path,
                                          pool));
-          SVN_ERR(svn_stream_puts(eb->stream,
-                                  SVN_REPOS_DUMPFILE_PROP_DELTA ": true\n"));
+          svn_repos__dumpfile_header_push(
+            headers, SVN_REPOS_DUMPFILE_PROP_DELTA, "true");
         }
       else
         oldhash = apr_hash_make(pool);
@@ -1175,11 +1404,6 @@ dump_node(struct edit_baton *eb,
       SVN_ERR(svn_hash_write_incremental(prophash, oldhash, propstream,
                                          "PROPS-END", pool));
       SVN_ERR(svn_stream_close(propstream));
-      proplen = propstring->len;
-      content_length += proplen;
-      SVN_ERR(svn_stream_printf(eb->stream, pool,
-                                SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH
-                                ": %" APR_SIZE_T_FMT "\n", proplen));
     }
 
   /* If we are supposed to dump text, write out a text length header
@@ -1188,7 +1412,6 @@ dump_node(struct edit_baton *eb,
     {
       svn_checksum_t *checksum;
       const char *hex_digest;
-      svn_filesize_t textlen;
 
       if (eb->use_deltas)
         {
@@ -1197,8 +1420,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_puts(eb->stream,
-                                  SVN_REPOS_DUMPFILE_TEXT_DELTA ": true\n"));
+          svn_repos__dumpfile_header_push(
+            headers, SVN_REPOS_DUMPFILE_TEXT_DELTA, "true");
 
           if (compare_root)
             {
@@ -1207,18 +1430,16 @@ dump_node(struct edit_baton *eb,
                                            FALSE, pool));
               hex_digest = svn_checksum_to_cstring(checksum, pool);
               if (hex_digest)
-                SVN_ERR(svn_stream_printf(eb->stream, pool,
-                                          SVN_REPOS_DUMPFILE_TEXT_DELTA_BASE_MD5
-                                          ": %s\n", hex_digest));
+                svn_repos__dumpfile_header_push(
+                  headers, SVN_REPOS_DUMPFILE_TEXT_DELTA_BASE_MD5, hex_digest);
 
               SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1,
                                            compare_root, compare_path,
                                            FALSE, pool));
               hex_digest = svn_checksum_to_cstring(checksum, pool);
               if (hex_digest)
-                SVN_ERR(svn_stream_printf(eb->stream, pool,
-                                      SVN_REPOS_DUMPFILE_TEXT_DELTA_BASE_SHA1
-                                      ": %s\n", hex_digest));
+                svn_repos__dumpfile_header_push(
+                  headers, SVN_REPOS_DUMPFILE_TEXT_DELTA_BASE_SHA1, hex_digest);
             }
         }
       else
@@ -1227,42 +1448,30 @@ dump_node(struct edit_baton *eb,
           SVN_ERR(svn_fs_file_length(&textlen, eb->fs_root, path, pool));
         }
 
-      content_length += textlen;
-      SVN_ERR(svn_stream_printf(eb->stream, pool,
-                                SVN_REPOS_DUMPFILE_TEXT_CONTENT_LENGTH
-                                ": %" SVN_FILESIZE_T_FMT "\n", textlen));
-
       SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_md5,
                                    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,
-                                  SVN_REPOS_DUMPFILE_TEXT_CONTENT_MD5
-                                  ": %s\n", hex_digest));
+        svn_repos__dumpfile_header_push(
+          headers, SVN_REPOS_DUMPFILE_TEXT_CONTENT_MD5, hex_digest);
 
       SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1,
                                    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,
-                                  SVN_REPOS_DUMPFILE_TEXT_CONTENT_SHA1
-                                  ": %s\n", hex_digest));
+        svn_repos__dumpfile_header_push(
+          headers, SVN_REPOS_DUMPFILE_TEXT_CONTENT_SHA1, hex_digest);
     }
 
   /* 'Content-length:' is the last header before we dump the content,
      and is the sum of the text and prop contents lengths.  We write
      this only for the benefit of non-Subversion RFC-822 parsers. */
-  SVN_ERR(svn_stream_printf(eb->stream, pool,
-                            SVN_REPOS_DUMPFILE_CONTENT_LENGTH
-                            ": %" SVN_FILESIZE_T_FMT "\n\n",
-                            content_length));
-
-  /* Dump property content if we're supposed to do so. */
-  if (must_dump_props)
-    {
-      len = propstring->len;
-      SVN_ERR(svn_stream_write(eb->stream, propstring->data, &len));
-    }
+  SVN_ERR(svn_repos__dump_node_record(eb->stream, headers,
+                                      must_dump_props ? propstring : NULL,
+                                      must_dump_text,
+                                      must_dump_text ? textlen : 0,
+                                      TRUE /*content_length_always*/,
+                                      pool));
 
   /* Dump text content */
   if (must_dump_text && (kind == svn_node_file))
@@ -1294,7 +1503,7 @@ open_root(void *edit_baton,
           void **root_baton)
 {
   *root_baton = make_dir_baton(NULL, NULL, SVN_INVALID_REVNUM,
-                               edit_baton, NULL, FALSE, pool);
+                               edit_baton, NULL, pool);
   return SVN_NO_ERROR;
 }
 
@@ -1325,13 +1534,13 @@ add_directory(const char *path,
 {
   struct dir_baton *pb = parent_baton;
   struct edit_baton *eb = pb->edit_baton;
-  void *val;
+  void *was_deleted;
   svn_boolean_t is_copy = FALSE;
   struct dir_baton *new_db
-    = make_dir_baton(path, copyfrom_path, copyfrom_rev, eb, pb, TRUE, pool);
+    = make_dir_baton(path, copyfrom_path, copyfrom_rev, eb, pb, pool);
 
   /* This might be a replacement -- is the path already deleted? */
-  val = svn_hash_gets(pb->deleted_entries, path);
+  was_deleted = svn_hash_gets(pb->deleted_entries, path);
 
   /* Detect an add-with-history. */
   is_copy = ARE_VALID_COPY_ARGS(copyfrom_path, copyfrom_rev);
@@ -1339,19 +1548,19 @@ add_directory(const char *path,
   /* Dump the node. */
   SVN_ERR(dump_node(eb, path,
                     svn_node_dir,
-                    val ? svn_node_action_replace : svn_node_action_add,
+                    was_deleted ? svn_node_action_replace : svn_node_action_add,
                     is_copy,
                     is_copy ? copyfrom_path : NULL,
                     is_copy ? copyfrom_rev : SVN_INVALID_REVNUM,
                     pool));
 
-  if (val)
+  if (was_deleted)
     /* Delete the path, it's now been dumped. */
     svn_hash_sets(pb->deleted_entries, path, NULL);
 
   /* Check for normalized name clashes, but only if this is actually a
      new name in the parent, not a replacement. */
-  if (!val && eb->verify && eb->check_normalization && eb->notify_func)
+  if (!was_deleted && eb->verify && eb->check_normalization && eb->notify_func)
     {
       pb->check_name_collision = TRUE;
     }
@@ -1385,7 +1594,7 @@ open_directory(const char *path,
       cmp_rev = pb->cmp_rev;
     }
 
-  new_db = make_dir_baton(path, cmp_path, cmp_rev, eb, pb, FALSE, pool);
+  new_db = make_dir_baton(path, cmp_path, cmp_rev, eb, pb, pool);
   *child_baton = new_db;
   return SVN_NO_ERROR;
 }
@@ -1437,11 +1646,11 @@ add_file(const char *path,
 {
   struct dir_baton *pb = parent_baton;
   struct edit_baton *eb = pb->edit_baton;
-  void *val;
+  void *was_deleted;
   svn_boolean_t is_copy = FALSE;
 
   /* This might be a replacement -- is the path already deleted? */
-  val = svn_hash_gets(pb->deleted_entries, path);
+  was_deleted = svn_hash_gets(pb->deleted_entries, path);
 
   /* Detect add-with-history. */
   is_copy = ARE_VALID_COPY_ARGS(copyfrom_path, copyfrom_rev);
@@ -1449,19 +1658,19 @@ add_file(const char *path,
   /* Dump the node. */
   SVN_ERR(dump_node(eb, path,
                     svn_node_file,
-                    val ? svn_node_action_replace : svn_node_action_add,
+                    was_deleted ? svn_node_action_replace : svn_node_action_add,
                     is_copy,
                     is_copy ? copyfrom_path : NULL,
                     is_copy ? copyfrom_rev : SVN_INVALID_REVNUM,
                     pool));
 
-  if (val)
+  if (was_deleted)
     /* delete the path, it's now been dumped. */
     svn_hash_sets(pb->deleted_entries, path, NULL);
 
   /* Check for normalized name clashes, but only if this is actually a
      new name in the parent, not a replacement. */
-  if (!val && eb->verify && eb->check_normalization && eb->notify_func)
+  if (!was_deleted && eb->verify && eb->check_normalization && eb->notify_func)
     {
       pb->check_name_collision = TRUE;
     }
@@ -1512,11 +1721,16 @@ change_dir_prop(void *parent_baton,
 
   /* This function is what distinguishes between a directory that is
      opened to merely get somewhere, vs. one that is opened because it
-     *actually* changed by itself.  */
+     *actually* changed by itself.
+
+     Instead of recording the prop changes here, we just use this method
+     to trigger writing the node; dump_node() finds all the changes. */
   if (! db->written_out)
     {
       SVN_ERR(dump_node(eb, db->path,
                         svn_node_dir, svn_node_action_change,
+                        /* ### We pass is_copy=FALSE; this might be wrong
+                           but the parameter isn't used when action=change. */
                         FALSE, db->cmp_path, db->cmp_rev, pool));
       db->written_out = TRUE;
     }
@@ -1705,12 +1919,9 @@ write_revision_record(svn_stream_t *stre
                       svn_revnum_t rev,
                       apr_pool_t *pool)
 {
-  apr_size_t len;
   apr_hash_t *props;
-  svn_stringbuf_t *encoded_prophash;
   apr_time_t timetemp;
   svn_string_t *datevalue;
-  svn_stream_t *propstream;
 
   SVN_ERR(svn_fs_revision_proplist(&props, fs, rev, pool));
 
@@ -1726,33 +1937,10 @@ write_revision_record(svn_stream_t *stre
       svn_hash_sets(props, SVN_PROP_REVISION_DATE, datevalue);
     }
 
-  encoded_prophash = svn_stringbuf_create_ensure(0, pool);
-  propstream = svn_stream_from_stringbuf(encoded_prophash, pool);
-  SVN_ERR(svn_hash_write2(props, propstream, "PROPS-END", pool));
-  SVN_ERR(svn_stream_close(propstream));
-
-  /* ### someday write a revision-content-checksum */
-
-  SVN_ERR(svn_stream_printf(stream, pool,
-                            SVN_REPOS_DUMPFILE_REVISION_NUMBER
-                            ": %ld\n", rev));
-  SVN_ERR(svn_stream_printf(stream, pool,
-                            SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH
-                            ": %" APR_SIZE_T_FMT "\n",
-                            encoded_prophash->len));
-
-  /* Write out a regular Content-length header for the benefit of
-     non-Subversion RFC-822 parsers. */
-  SVN_ERR(svn_stream_printf(stream, pool,
-                            SVN_REPOS_DUMPFILE_CONTENT_LENGTH
-                            ": %" APR_SIZE_T_FMT "\n\n",
-                            encoded_prophash->len));
-
-  len = encoded_prophash->len;
-  SVN_ERR(svn_stream_write(stream, encoded_prophash->data, &len));
-
-  len = 1;
-  return svn_stream_write(stream, "\n", &len);
+  SVN_ERR(svn_repos__dump_revision_record(stream, rev, NULL, props,
+                                          TRUE /*props_section_always*/,
+                                          pool));
+  return SVN_NO_ERROR;
 }
 
 

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_repos/load-fs-vtable.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_repos/load-fs-vtable.c?rev=1655189&r1=1655188&r2=1655189&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_repos/load-fs-vtable.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_repos/load-fs-vtable.c Tue Jan 27 23:27:44 2015
@@ -41,6 +41,7 @@
 #include "private/svn_fspath.h"
 #include "private/svn_dep_compat.h"
 #include "private/svn_mergeinfo_private.h"
+#include "private/svn_repos_private.h"
 
 /*----------------------------------------------------------------------*/
 
@@ -192,8 +193,6 @@ change_node_prop(svn_fs_root_t *txn_root
 
 /* Prepend the mergeinfo source paths in MERGEINFO_ORIG with PARENT_DIR, and
    return it in *MERGEINFO_VAL. */
-/* ### FIXME:  Consider somehow sharing code with
-   ### svnrdump/load_editor.c:prefix_mergeinfo_paths() */
 static svn_error_t *
 prefix_mergeinfo_paths(svn_string_t **mergeinfo_val,
                        const svn_string_t *mergeinfo_orig,
@@ -225,13 +224,20 @@ prefix_mergeinfo_paths(svn_string_t **me
 
 /* Examine the mergeinfo in INITIAL_VAL, renumber revisions in rangelists
    as appropriate, and return the (possibly new) mergeinfo in *FINAL_VAL
-   (allocated from POOL). */
-/* ### FIXME:  Consider somehow sharing code with
-   ### svnrdump/load_editor.c:renumber_mergeinfo_revs() */
+   (allocated from POOL).
+
+   Adjust any mergeinfo revisions not older than OLDEST_DUMPSTREAM_REV by
+   using REV_MAP which maps (svn_revnum_t) old rev to (svn_revnum_t) new rev.
+
+   Adjust any mergeinfo revisions older than OLDEST_DUMPSTREAM_REV by
+   (-OLDER_REVS_OFFSET), dropping any that become <= 0.
+ */
 static svn_error_t *
 renumber_mergeinfo_revs(svn_string_t **final_val,
                         const svn_string_t *initial_val,
-                        struct revision_baton *rb,
+                        apr_hash_t *rev_map,
+                        svn_revnum_t oldest_dumpstream_rev,
+                        apr_int32_t older_revs_offset,
                         apr_pool_t *pool)
 {
   apr_pool_t *subpool = svn_pool_create(pool);
@@ -246,19 +252,22 @@ renumber_mergeinfo_revs(svn_string_t **f
      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_dumpstream_rev > 1)
+  if (oldest_dumpstream_rev > 1)
     {
+      /* predates_stream_mergeinfo := mergeinfo that refers to revs before
+         oldest_dumpstream_rev */
       SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(
         &predates_stream_mergeinfo, mergeinfo,
-        rb->pb->oldest_dumpstream_rev - 1, 0,
+        oldest_dumpstream_rev - 1, 0,
         TRUE, subpool, subpool));
+      /* mergeinfo := mergeinfo that refers to revs >= oldest_dumpstream_rev */
       SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(
         &mergeinfo, mergeinfo,
-        rb->pb->oldest_dumpstream_rev - 1, 0,
+        oldest_dumpstream_rev - 1, 0,
         FALSE, subpool, subpool));
       SVN_ERR(svn_mergeinfo__adjust_mergeinfo_rangelists(
         &predates_stream_mergeinfo, predates_stream_mergeinfo,
-        -rb->rev_offset, subpool, subpool));
+        -older_revs_offset, subpool, subpool));
     }
   else
     {
@@ -269,7 +278,6 @@ renumber_mergeinfo_revs(svn_string_t **f
     {
       const char *merge_source = apr_hash_this_key(hi);
       svn_rangelist_t *rangelist = apr_hash_this_val(hi);
-      struct parse_baton *pb = rb->pb;
       int i;
 
       /* Possibly renumber revisions in merge source's rangelist. */
@@ -278,27 +286,27 @@ renumber_mergeinfo_revs(svn_string_t **f
           svn_revnum_t rev_from_map;
           svn_merge_range_t *range = APR_ARRAY_IDX(rangelist, i,
                                                    svn_merge_range_t *);
-          rev_from_map = get_revision_mapping(pb->rev_map, range->start);
+          rev_from_map = get_revision_mapping(rev_map, range->start);
           if (SVN_IS_VALID_REVNUM(rev_from_map))
             {
               range->start = rev_from_map;
             }
-          else if (range->start == pb->oldest_dumpstream_rev - 1)
+          else if (range->start == oldest_dumpstream_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
+                 won't be found in the REV_MAP mapping of load stream
                  revsions to loaded revisions: The revision immediately
                  preceding 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
+                 copy from revision (which 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 = get_revision_mapping(pb->rev_map,
-                                                  pb->oldest_dumpstream_rev);
+              rev_from_map = get_revision_mapping(rev_map,
+                                                  oldest_dumpstream_rev);
               if (SVN_IS_VALID_REVNUM(rev_from_map))
                 range->start = rev_from_map - 1;
             }
@@ -315,7 +323,7 @@ renumber_mergeinfo_revs(svn_string_t **f
               continue;
             }
 
-          rev_from_map = get_revision_mapping(pb->rev_map, range->end);
+          rev_from_map = get_revision_mapping(rev_map, range->end);
           if (SVN_IS_VALID_REVNUM(rev_from_map))
             range->end = rev_from_map;
         }
@@ -758,18 +766,18 @@ set_revision_property(void *baton,
 }
 
 
-/* Adjust mergeinfo:
- *   - normalize line endings (if all CRLF, change to LF; but error if mixed);
- *   - adjust revision numbers (see renumber_mergeinfo_revs());
- *   - adjust paths (see prefix_mergeinfo_paths()).
- */
-static svn_error_t *
-adjust_mergeinfo_property(struct revision_baton *rb,
-                          svn_string_t **new_value_p,
-                          const svn_string_t *old_value,
-                          apr_pool_t *result_pool)
+svn_error_t *
+svn_repos__adjust_mergeinfo_property(svn_string_t **new_value_p,
+                                     const svn_string_t *old_value,
+                                     const char *parent_dir,
+                                     apr_hash_t *rev_map,
+                                     svn_revnum_t oldest_dumpstream_rev,
+                                     apr_int32_t older_revs_offset,
+                                     svn_repos_notify_func_t notify_func,
+                                     void *notify_baton,
+                                     apr_pool_t *result_pool,
+                                     apr_pool_t *scratch_pool)
 {
-  struct parse_baton *pb = rb->pb;
   svn_string_t prop_val = *old_value;
 
   /* Tolerate mergeinfo with "\r\n" line endings because some
@@ -790,29 +798,29 @@ adjust_mergeinfo_property(struct revisio
       prop_val.data = prop_eol_normalized;
       prop_val.len = strlen(prop_eol_normalized);
 
-      if (pb->notify_func)
+      if (notify_func)
         {
-          /* ### TODO: Use proper scratch pool instead of pb->notify_pool */
           svn_repos_notify_t *notify
                   = svn_repos_notify_create(
                                 svn_repos_notify_load_normalized_mergeinfo,
-                                pb->notify_pool);
+                                scratch_pool);
 
-          pb->notify_func(pb->notify_baton, notify, pb->notify_pool);
-          svn_pool_clear(pb->notify_pool);
+          notify_func(notify_baton, notify, scratch_pool);
         }
     }
 
   /* Renumber mergeinfo as appropriate. */
-  SVN_ERR(renumber_mergeinfo_revs(new_value_p, &prop_val, rb,
+  SVN_ERR(renumber_mergeinfo_revs(new_value_p, &prop_val,
+                                  rev_map, oldest_dumpstream_rev,
+                                  older_revs_offset,
                                   result_pool));
 
-  if (pb->parent_dir)
+  if (parent_dir)
     {
-      /* Prefix the merge source paths with PB->parent_dir. */
+      /* Prefix the merge source paths with PARENT_DIR. */
       /* ASSUMPTION: All source paths are included in the dump stream. */
       SVN_ERR(prefix_mergeinfo_paths(new_value_p, *new_value_p,
-                                     pb->parent_dir, result_pool));
+                                     parent_dir, result_pool));
     }
 
   return SVN_NO_ERROR;
@@ -842,7 +850,14 @@ set_node_property(void *baton,
       svn_string_t *new_value;
       svn_error_t *err;
 
-      err = adjust_mergeinfo_property(rb, &new_value, value, nb->pool);
+      err = svn_repos__adjust_mergeinfo_property(&new_value, value,
+                                                 pb->parent_dir,
+                                                 pb->rev_map,
+                                                 pb->oldest_dumpstream_rev,
+                                                 rb->rev_offset,
+                                                 pb->notify_func, pb->notify_baton,
+                                                 nb->pool, pb->notify_pool);
+      svn_pool_clear(pb->notify_pool);
       if (err)
         {
           if (pb->validate_props)

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_subr/checksum.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_subr/checksum.c?rev=1655189&r1=1655188&r2=1655189&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_subr/checksum.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_subr/checksum.c Tue Jan 27 23:27:44 2015
@@ -165,12 +165,15 @@ checksum_create_without_digest(svn_check
   return checksum;
 }
 
+/* Return a checksum object, allocated in POOL.  The checksum will be of
+ * type KIND and contain the given DIGEST.
+ */
 static svn_checksum_t *
 checksum_create(svn_checksum_kind_t kind,
-                apr_size_t digest_size,
                 const unsigned char *digest,
                 apr_pool_t *pool)
 {
+  apr_size_t digest_size = DIGESTSIZE(kind);
   svn_checksum_t *checksum = checksum_create_without_digest(kind, digest_size,
                                                             pool);
   memcpy((unsigned char *)checksum->digest, digest, digest_size);
@@ -206,32 +209,28 @@ svn_checksum_t *
 svn_checksum__from_digest_md5(const unsigned char *digest,
                               apr_pool_t *result_pool)
 {
-  return checksum_create(svn_checksum_md5, APR_MD5_DIGESTSIZE, digest,
-                         result_pool);
+  return checksum_create(svn_checksum_md5, digest, result_pool);
 }
 
 svn_checksum_t *
 svn_checksum__from_digest_sha1(const unsigned char *digest,
                                apr_pool_t *result_pool)
 {
-  return checksum_create(svn_checksum_sha1, APR_SHA1_DIGESTSIZE, digest,
-                         result_pool);
+  return checksum_create(svn_checksum_sha1, digest, result_pool);
 }
 
 svn_checksum_t *
 svn_checksum__from_digest_fnv1a_32(const unsigned char *digest,
                                    apr_pool_t *result_pool)
 {
-  return checksum_create(svn_checksum_fnv1a_32, sizeof(digest), digest,
-                         result_pool);
+  return checksum_create(svn_checksum_fnv1a_32, digest, result_pool);
 }
 
 svn_checksum_t *
 svn_checksum__from_digest_fnv1a_32x4(const unsigned char *digest,
                                      apr_pool_t *result_pool)
 {
-  return checksum_create(svn_checksum_fnv1a_32x4, sizeof(digest), digest,
-                         result_pool);
+  return checksum_create(svn_checksum_fnv1a_32x4, digest, result_pool);
 }
 
 svn_error_t *
@@ -428,10 +427,7 @@ svn_checksum_dup(const svn_checksum_t *c
       case svn_checksum_sha1:
       case svn_checksum_fnv1a_32:
       case svn_checksum_fnv1a_32x4:
-        return checksum_create(checksum->kind,
-                               digest_sizes[checksum->kind],
-                               checksum->digest,
-                               pool);
+        return checksum_create(checksum->kind, checksum->digest, pool);
 
       default:
         SVN_ERR_MALFUNCTION_NO_RETURN();
@@ -492,10 +488,7 @@ svn_checksum_empty_checksum(svn_checksum
       case svn_checksum_sha1:
       case svn_checksum_fnv1a_32:
       case svn_checksum_fnv1a_32x4:
-        return checksum_create(kind,
-                               digest_sizes[kind],
-                               empty_string_digests[kind],
-                               pool);
+        return checksum_create(kind, empty_string_digests[kind], pool);
 
       default:
         /* We really shouldn't get here, but if we do... */

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_subr/io.c?rev=1655189&r1=1655188&r2=1655189&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_subr/io.c Tue Jan 27 23:27:44 2015
@@ -1590,7 +1590,8 @@ io_set_file_perms(const char *path,
   status = apr_stat(&finfo, path_apr, APR_FINFO_PROT | APR_FINFO_LINK, pool);
   if (status)
     {
-      if (ignore_enoent && APR_STATUS_IS_ENOENT(status))
+      if (ignore_enoent && (APR_STATUS_IS_ENOENT(status)
+                            || SVN__APR_STATUS_IS_ENOTDIR(status)))
         return SVN_NO_ERROR;
       else if (status != APR_ENOTIMPL)
         return svn_error_wrap_apr(status,
@@ -1951,7 +1952,8 @@ svn_io_set_file_read_only(const char *pa
                               pool);
 
   if (status && status != APR_ENOTIMPL)
-    if (!ignore_enoent || !APR_STATUS_IS_ENOENT(status))
+    if (!(ignore_enoent && (APR_STATUS_IS_ENOENT(status)
+                            || SVN__APR_STATUS_IS_ENOTDIR(status))))
       return svn_error_wrap_apr(status,
                                 _("Can't set file '%s' read-only"),
                                 svn_dirent_local_style(path, pool));
@@ -2454,11 +2456,6 @@ svn_io_remove_file2(const char *path,
   SVN_ERR(cstring_from_utf8(&path_apr, path, scratch_pool));
 
   apr_err = apr_file_remove(path_apr, scratch_pool);
-  if (!apr_err
-      || (ignore_enoent
-          && (APR_STATUS_IS_ENOENT(apr_err)
-              || SVN__APR_STATUS_IS_ENOTDIR(apr_err))))
-    return SVN_NO_ERROR;
 
 #ifdef WIN32
   /* If the target is read only NTFS reports EACCESS and FAT/FAT32
@@ -2474,30 +2471,36 @@ svn_io_remove_file2(const char *path,
         return SVN_NO_ERROR;
     }
 
+  /* Check to make sure we aren't trying to delete a directory */
+  if (apr_err == APR_FROM_OS_ERROR(ERROR_ACCESS_DENIED)
+      || apr_err == APR_FROM_OS_ERROR(ERROR_SHARING_VIOLATION))
     {
-      apr_status_t os_err = APR_TO_OS_ERROR(apr_err);
-      /* Check to make sure we aren't trying to delete a directory */
-      if (os_err == ERROR_ACCESS_DENIED || os_err == ERROR_SHARING_VIOLATION)
-        {
-          apr_finfo_t finfo;
+      apr_finfo_t finfo;
 
-          if (!apr_stat(&finfo, path_apr, APR_FINFO_TYPE, scratch_pool)
-              && finfo.filetype == APR_REG)
-            {
-              WIN32_RETRY_LOOP(apr_err, apr_file_remove(path_apr,
-                                                        scratch_pool));
-            }
+      if (!apr_stat(&finfo, path_apr, APR_FINFO_TYPE, scratch_pool)
+          && finfo.filetype == APR_REG)
+        {
+          WIN32_RETRY_LOOP(apr_err, apr_file_remove(path_apr, scratch_pool));
         }
-
-      /* Just return the delete error */
     }
-#endif
 
-  if (apr_err)
-    return svn_error_wrap_apr(apr_err, _("Can't remove file '%s'"),
-                              svn_dirent_local_style(path, scratch_pool));
+  /* Just return the delete error */
+#endif
 
-  return SVN_NO_ERROR;
+  if (!apr_err)
+    {
+      return SVN_NO_ERROR;
+    }
+  else if (ignore_enoent && (APR_STATUS_IS_ENOENT(apr_err)
+                             || SVN__APR_STATUS_IS_ENOTDIR(apr_err)))
+    {
+      return SVN_NO_ERROR;
+    }
+  else
+    {
+      return svn_error_wrap_apr(apr_err, _("Can't remove file '%s'"),
+                                svn_dirent_local_style(path, scratch_pool));
+    }
 }
 
 
@@ -2552,7 +2555,8 @@ svn_io_remove_dir2(const char *path, svn
   if (err)
     {
       /* if the directory doesn't exist, our mission is accomplished */
-      if (ignore_enoent && APR_STATUS_IS_ENOENT(err->apr_err))
+      if (ignore_enoent && (APR_STATUS_IS_ENOENT(err->apr_err)
+                            || SVN__APR_STATUS_IS_ENOTDIR(err->apr_err)))
         {
           svn_error_clear(err);
           return SVN_NO_ERROR;

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_subr/prefix_string.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_subr/prefix_string.c?rev=1655189&r1=1655188&r2=1655189&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_subr/prefix_string.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_subr/prefix_string.c Tue Jan 27 23:27:44 2015
@@ -267,7 +267,7 @@ svn_prefix_string__expand(const svn_pref
   apr_size_t len = s->prefix->length + s_len;
   char *buffer = apr_palloc(pool, len + 1);
 
-  svn_string_t *result = apr_pcalloc(pool, sizeof(result));
+  svn_string_t *result = apr_pcalloc(pool, sizeof(*result));
   result->data = buffer;
   result->len = len;
   buffer[len] = '\0';

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_subr/sqlite.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_subr/sqlite.c?rev=1655189&r1=1655188&r2=1655189&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_subr/sqlite.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_subr/sqlite.c Tue Jan 27 23:27:44 2015
@@ -189,6 +189,21 @@ struct svn_sqlite__value_t
                              sqlite3_errmsg((db)->db3));          \
 } while (0)
 
+#define SQLITE_ERR_CLOSE(x, db, pool) do                          \
+{                                                                 \
+  int sqlite_err__temp = (x);                                     \
+  if (sqlite_err__temp != SQLITE_OK)                              \
+    {                                                             \
+      const char *sqlite_err__msg                                 \
+        = apr_pstrdup(pool, sqlite3_errmsg((db)->db3));           \
+      return svn_error_compose_create(                            \
+           svn_error_createf(SQLITE_ERROR_CODE(sqlite_err__temp), \
+                             NULL, "sqlite[S%d]: %s",             \
+                             sqlite_err__temp, sqlite_err__msg),  \
+           svn_sqlite__close(db));                                \
+    }                                                             \
+} while (0)
+
 #define SQLITE_ERR_MSG(x, msg) do                                \
 {                                                                \
   int sqlite_err__temp = (x);                                    \
@@ -198,6 +213,13 @@ struct svn_sqlite__value_t
                              sqlite_err__temp, msg);             \
 } while (0)
 
+#define SVN_ERR_CLOSE(x, db) do                                       \
+{                                                                     \
+  svn_error_t *svn__err = (x);                                        \
+  if (svn__err)                                                       \
+    return svn_error_compose_create(svn__err, svn_sqlite__close(db)); \
+} while (0)
+
 
 /* Time (in milliseconds) to wait for sqlite locks before giving up. */
 #define BUSY_TIMEOUT 10000
@@ -809,7 +831,7 @@ init_sqlite(void *baton, apr_pool_t *poo
 }
 
 static svn_error_t *
-internal_open(sqlite3 **db3, const char *path, svn_sqlite__mode_t mode,
+internal_open(svn_sqlite__db_t *db, const char *path, svn_sqlite__mode_t mode,
               apr_int32_t timeout, apr_pool_t *scratch_pool)
 {
   {
@@ -856,13 +878,13 @@ internal_open(sqlite3 **db3, const char
 
     /* Open the database. Note that a handle is returned, even when an error
        occurs (except for out-of-memory); thus, we can safely use it to
-       extract an error message and construct an svn_error_t. */
+       extract an error message and construct an svn_error_t.  SQLite always
+       requires sqlite3_close() after sqlite3_open_v2() while Subversion 
+       typically does not require close() after an open() that returns an
+       error.  So we must ensure we close the handle if this function, or
+       the caller svn_sqlite__open, returns an error to the application. */
     {
       const char *vFs = NULL;
-      int err_code;
-      /* We'd like to use SQLITE_ERR here, but we can't since it would
-         just return an error and leave the database open.  So, we need to
-         do this manually. */
 
 #if defined(WIN32) && SQLITE_VERSION_AT_LEAST(3, 8, 1)
       if (strlen(path) > 248)
@@ -886,18 +908,8 @@ internal_open(sqlite3 **db3, const char
 #endif
 
       /* ### SQLITE_CANTOPEN */
-      err_code = sqlite3_open_v2(path, db3, flags, vFs);
-      if (err_code != SQLITE_OK)
-        {
-          /* Save the error message before closing the SQLite handle. */
-          char *msg = apr_pstrdup(scratch_pool, sqlite3_errmsg(*db3));
-
-          /* We don't catch the error here, since we care more about the open
-             error than the close error at this point. */
-          sqlite3_close(*db3);
-
-          SQLITE_ERR_MSG(err_code, msg);
-        }
+      SQLITE_ERR_CLOSE(sqlite3_open_v2(path, &db->db3, flags, vFs),
+                       db, scratch_pool);
     }
   }
 
@@ -905,7 +917,8 @@ internal_open(sqlite3 **db3, const char
     timeout = BUSY_TIMEOUT;
 
   /* Retry until timeout when database is busy. */
-  SQLITE_ERR_MSG(sqlite3_busy_timeout(*db3, timeout), sqlite3_errmsg(*db3));
+  SQLITE_ERR_CLOSE(sqlite3_busy_timeout(db->db3, timeout),
+                   db, scratch_pool);
 
   return SVN_NO_ERROR;
 }
@@ -925,35 +938,29 @@ close_apr(void *data)
   if (db->db3 == NULL)
     return APR_SUCCESS;
 
-  /* Finalize any existing prepared statements. */
-  for (i = 0; i < db->nbr_statements; i++)
+  /* Finalize any prepared statements. */
+  if (db->prepared_stmts)
     {
-      if (db->prepared_stmts[i])
+      for (i = 0; i < db->nbr_statements + STMT_INTERNAL_LAST; i++)
         {
-          if (db->prepared_stmts[i]->needs_reset)
+          if (db->prepared_stmts[i])
             {
+              if (i < db->nbr_statements
+                  && db->prepared_stmts[i]->needs_reset)
+                {
 #ifdef SVN_DEBUG
-              const char *stmt_text = db->statement_strings[i];
-              SVN_UNUSED(stmt_text);
+                  const char *stmt_text = db->statement_strings[i];
+                  SVN_UNUSED(stmt_text);
 
-              SVN_ERR_MALFUNCTION_NO_RETURN();
+                  SVN_ERR_MALFUNCTION_NO_RETURN();
 #else
-              err = svn_error_compose_create(
-                            err,
+                  err = svn_error_compose_create(err,
                             svn_sqlite__reset(db->prepared_stmts[i]));
 #endif
-            }
-          err = svn_error_compose_create(
-                        svn_sqlite__finalize(db->prepared_stmts[i]), err);
-        }
-    }
-  /* And finalize any used internal statements */
-  for (; i < db->nbr_statements + STMT_INTERNAL_LAST; i++)
-    {
-      if (db->prepared_stmts[i])
-        {
-          err = svn_error_compose_create(
+                }
+              err = svn_error_compose_create(
                         svn_sqlite__finalize(db->prepared_stmts[i]), err);
+            }
         }
     }
 
@@ -1081,7 +1088,7 @@ svn_sqlite__open(svn_sqlite__db_t **db,
 
   *db = apr_pcalloc(result_pool, sizeof(**db));
 
-  SVN_ERR(internal_open(&(*db)->db3, path, mode, timeout, scratch_pool));
+  SVN_ERR(internal_open(*db, path, mode, timeout, scratch_pool));
 
 #if SQLITE_VERSION_NUMBER >= 3008000 && SQLITE_VERSION_NUMBER < 3009000
   /* disable SQLITE_ENABLE_STAT3/4 from 3.8.1 - 3.8.3 (but not 3.8.3.1+)
@@ -1102,10 +1109,10 @@ svn_sqlite__open(svn_sqlite__db_t **db,
   svn_membuf__create(&(*db)->sqlext_buf3, 800, result_pool);
 
   /* Register collation and LIKE and GLOB operator replacements. */
-  SQLITE_ERR(sqlite3_create_collation((*db)->db3,
-                                      "svn-ucs-nfd", SQLITE_UTF8,
-                                      *db, collate_ucs_nfd),
-             *db);
+  SQLITE_ERR_CLOSE(sqlite3_create_collation((*db)->db3,
+                                            "svn-ucs-nfd", SQLITE_UTF8,
+                                            *db, collate_ucs_nfd),
+                   db, scratch_pool);
   /* ### Is it really necessary to override these functions?
          I would assume the default implementation to be collation agnostic?
          And otherwise our implementation should be...
@@ -1113,18 +1120,18 @@ svn_sqlite__open(svn_sqlite__db_t **db,
          The default implementation is in some cases index backed, while our
          implementation can't be. With an index based on the collation it could
          be. */
-  SQLITE_ERR(sqlite3_create_function((*db)->db3, "glob", 2,
-                                     SQLITE_UTF8 | SQLITE_DETERMINISTIC,
-                                     *db, glob_ucs_nfd, NULL, NULL),
-             *db);
-  SQLITE_ERR(sqlite3_create_function((*db)->db3, "like", 2,
-                                     SQLITE_UTF8 | SQLITE_DETERMINISTIC,
-                                     *db, like_ucs_nfd, NULL, NULL),
-             *db);
-  SQLITE_ERR(sqlite3_create_function((*db)->db3, "like", 3,
-                                     SQLITE_UTF8 | SQLITE_DETERMINISTIC,
-                                     *db, like_ucs_nfd, NULL, NULL),
-             *db);
+  SQLITE_ERR_CLOSE(sqlite3_create_function((*db)->db3, "glob", 2,
+                                           SQLITE_UTF8 | SQLITE_DETERMINISTIC,
+                                           *db, glob_ucs_nfd, NULL, NULL),
+                   db, scratch_pool);
+  SQLITE_ERR_CLOSE(sqlite3_create_function((*db)->db3, "like", 2,
+                                           SQLITE_UTF8 | SQLITE_DETERMINISTIC,
+                                           *db, like_ucs_nfd, NULL, NULL),
+                   db, scratch_pool);
+  SQLITE_ERR_CLOSE(sqlite3_create_function((*db)->db3, "like", 3,
+                                           SQLITE_UTF8 | SQLITE_DETERMINISTIC,
+                                           *db, like_ucs_nfd, NULL, NULL),
+                   db, scratch_pool);
 #endif /* SVN_UNICODE_NORMALIZATION_FIXES */
 
 #ifdef SQLITE3_DEBUG
@@ -1134,7 +1141,7 @@ svn_sqlite__open(svn_sqlite__db_t **db,
   sqlite3_profile((*db)->db3, sqlite_profiler, (*db)->db3);
 #endif
 
-  SVN_ERR(exec_sql(*db,
+  SVN_ERR_CLOSE(exec_sql(*db,
               /* The default behavior of the LIKE operator is to ignore case
                  for ASCII characters. Hence, by default 'a' LIKE 'A' is true.
                  The case_sensitive_like pragma installs a new application-
@@ -1164,13 +1171,15 @@ svn_sqlite__open(svn_sqlite__db_t **db,
                  affects application(read: Subversion) performance/behavior. */
               "PRAGMA foreign_keys=OFF;"      /* SQLITE_DEFAULT_FOREIGN_KEYS*/
               "PRAGMA locking_mode = NORMAL;" /* SQLITE_DEFAULT_LOCKING_MODE */
-              ));
+                            ),
+                *db);
 
 #if defined(SVN_DEBUG)
   /* When running in debug mode, enable the checking of foreign key
      constraints.  This has possible performance implications, so we don't
      bother to do it for production...for now. */
-  SVN_ERR(exec_sql(*db, "PRAGMA foreign_keys=ON;"));
+  SVN_ERR_CLOSE(exec_sql(*db, "PRAGMA foreign_keys=ON;"),
+                *db);
 #endif
 
 #ifdef SVN_SQLITE_REVERSE_UNORDERED_SELECTS
@@ -1178,7 +1187,8 @@ svn_sqlite__open(svn_sqlite__db_t **db,
      clause to emit their results in the reverse order of what they normally
      would.  This can help detecting invalid assumptions about the result
      order.*/
-  SVN_ERR(exec_sql(*db, "PRAGMA reverse_unordered_selects=ON;"));
+  SVN_ERR_CLOSE(exec_sql(*db, "PRAGMA reverse_unordered_selects=ON;"),
+                *db);
 #endif
 
   /* Store temporary tables in RAM instead of in temporary files, but don't

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_subr/stream.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_subr/stream.c?rev=1655189&r1=1655188&r2=1655189&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_subr/stream.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_subr/stream.c Tue Jan 27 23:27:44 2015
@@ -2071,7 +2071,7 @@ create_tempfile(HANDLE *hFile,
 
       if (h == INVALID_HANDLE_VALUE)
         {
-          apr_status_t status = apr_get_os_error();;
+          apr_status_t status = apr_get_os_error();
           if (i > 1000)
             return svn_error_createf(SVN_ERR_IO_UNIQUE_NAMES_EXHAUSTED,
                            svn_error_wrap_apr(status, NULL),

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_wc/conflicts.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_wc/conflicts.c?rev=1655189&r1=1655188&r2=1655189&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_wc/conflicts.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_wc/conflicts.c Tue Jan 27 23:27:44 2015
@@ -2240,7 +2240,7 @@ svn_wc__read_conflicts(const apr_array_h
     {
       /* Some callers expect not NULL */
       *conflicts = apr_array_make(result_pool, 0,
-                                  sizeof(svn_wc_conflict_description2_t *));;
+                                  sizeof(svn_wc_conflict_description2_t *));
       return SVN_NO_ERROR;
     }
 

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_wc/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_wc/merge.c?rev=1655189&r1=1655188&r2=1655189&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_wc/merge.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_wc/merge.c Tue Jan 27 23:27:44 2015
@@ -180,7 +180,7 @@ detranslate_wc_file(const char **detrans
       = prop ? (prop->value ? prop->value->data : NULL) : old_mime_value;
 
     old_is_binary = old_mime_value && svn_mime_type_is_binary(old_mime_value);
-    new_is_binary = new_mime_value && svn_mime_type_is_binary(new_mime_value);;
+    new_is_binary = new_mime_value && svn_mime_type_is_binary(new_mime_value);
   }
 
   /* See what translations we want to do */

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc_db.c?rev=1655189&r1=1655188&r2=1655189&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc_db.c Tue Jan 27 23:27:44 2015
@@ -1591,19 +1591,32 @@ svn_wc__db_init(svn_wc__db_t *db,
                         FALSE /* auto-upgrade */,
                         db->state_pool, scratch_pool));
 
-  /* The WCROOT is complete. Stash it into DB.  */
-  svn_hash_sets(db->dir_data, wcroot->abspath, wcroot);
+  /* Any previously cached children may now have a new WCROOT, most likely that
+     of the new WCROOT, but there might be descendant directories that are their
+     own working copy, in which case setting WCROOT to our new WCROOT might
+     actually break things for those.
+
+     Clearing is the safest thing we can do in this case, as a test would lead
+     to unnecessary probing, while the standard code probes later anyway. So we
+     only lose a bit of memory
 
-  /* Any previously cached children now have a new WCROOT. */
+     ### Perhaps we could check wcroot->abspath to detect which case we have
+         where, but currently it is already very hard to trigger this from
+         the short living 'svn' client. (GUI clients like TortoiseSVN are far
+         more likely to get in these cases)
+     */
   for (hi = apr_hash_first(scratch_pool, db->dir_data);
        hi;
        hi = apr_hash_next(hi))
     {
       const char *abspath = apr_hash_this_key(hi);
       if (svn_dirent_is_ancestor(wcroot->abspath, abspath))
-        svn_hash_sets(db->dir_data, abspath, wcroot);
+        svn_hash_sets(db->dir_data, abspath, NULL);
     }
 
+  /* The WCROOT is complete. Stash it into DB.  */
+  svn_hash_sets(db->dir_data, wcroot->abspath, wcroot);
+
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc_db_update_move.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc_db_update_move.c?rev=1655189&r1=1655188&r2=1655189&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc_db_update_move.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc_db_update_move.c Tue Jan 27 23:27:44 2015
@@ -2230,6 +2230,19 @@ bump_moved_layer(svn_boolean_t *recurse,
        always have sufficient depth to bump subtree moves. */
     can_bump = TRUE;
 
+  /* Are we allowed to bump */
+  if (can_bump)
+    {
+      svn_boolean_t locked;
+
+      SVN_ERR(svn_wc__db_wclock_owns_lock_internal(&locked, wcroot,
+                                                   dst_relpath,
+                                                   FALSE, scratch_pool));
+
+      if (!locked)
+        can_bump = FALSE;
+    }
+
   if (!can_bump)
     {
       SVN_ERR(bump_mark_tree_conflict(wcroot, src_relpath,

Modified: subversion/branches/svn-auth-x509/subversion/mod_authz_svn/mod_authz_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/mod_authz_svn/mod_authz_svn.c?rev=1655189&r1=1655188&r2=1655189&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/mod_authz_svn/mod_authz_svn.c (original)
+++ subversion/branches/svn-auth-x509/subversion/mod_authz_svn/mod_authz_svn.c Tue Jan 27 23:27:44 2015
@@ -244,15 +244,26 @@ static const command_rec authz_svn_cmds[
  * per-module loglevel configuration.  It expands to FILE and LINE
  * in older server versions.  ALLOWED is boolean.
  * REPOS_PATH and DEST_REPOS_PATH are information
- * about the request.  DEST_REPOS_PATH may be NULL. */
+ * about the request.  DEST_REPOS_PATH may be NULL.
+ * Non-zero IS_SUBREQ_BYPASS means that this authorization check was
+ * implicitly requested using 'subrequest bypass' callback from
+ * mod_dav_svn.
+ */
 static void
 log_access_verdict(LOG_ARGS_SIGNATURE,
-                   const request_rec *r, int allowed,
+                   const request_rec *r, int allowed, int is_subreq_bypass,
                    const char *repos_path, const char *dest_repos_path)
 {
-  int level = allowed ? APLOG_INFO : APLOG_WARNING;
+  int level = allowed ? APLOG_INFO : APLOG_ERR;
   const char *verdict = allowed ? "granted" : "denied";
 
+  /* Use less important log level for implicit sub-request authorization
+     checks. */
+  if (is_subreq_bypass)
+    level = APLOG_INFO;
+  else if (r->main && r->method_number == M_GET)
+    level = APLOG_INFO;
+
   if (r->user)
     {
       if (dest_repos_path)
@@ -749,7 +760,7 @@ subreq_bypass2(request_rec *r,
   if (!conf->anonymous
       || (! (conf->access_file || conf->repo_relative_access_file)))
     {
-      log_access_verdict(APLOG_MARK, r, 0, repos_path, NULL);
+      log_access_verdict(APLOG_MARK, r, 0, TRUE, repos_path, NULL);
       return HTTP_FORBIDDEN;
     }
 
@@ -778,12 +789,12 @@ subreq_bypass2(request_rec *r,
         }
       if (!authz_access_granted)
         {
-          log_access_verdict(APLOG_MARK, r, 0, repos_path, NULL);
+          log_access_verdict(APLOG_MARK, r, 0, TRUE, repos_path, NULL);
           return HTTP_FORBIDDEN;
         }
     }
 
-  log_access_verdict(APLOG_MARK, r, 1, repos_path, NULL);
+  log_access_verdict(APLOG_MARK, r, 1, TRUE, repos_path, NULL);
 
   return OK;
 }
@@ -858,7 +869,7 @@ access_checker(request_rec *r)
         return DECLINED;
 
       if (!authn_required)
-        log_access_verdict(APLOG_MARK, r, 0, repos_path, dest_repos_path);
+        log_access_verdict(APLOG_MARK, r, 0, FALSE, repos_path, dest_repos_path);
 
       return HTTP_FORBIDDEN;
     }
@@ -866,7 +877,7 @@ access_checker(request_rec *r)
   if (status != OK)
     return status;
 
-  log_access_verdict(APLOG_MARK, r, 1, repos_path, dest_repos_path);
+  log_access_verdict(APLOG_MARK, r, 1, FALSE, repos_path, dest_repos_path);
 
   return OK;
 }
@@ -893,7 +904,7 @@ check_user_id(request_rec *r)
   if (status == OK)
     {
       apr_table_setn(r->notes, "authz_svn-anon-ok", (const char*)1);
-      log_access_verdict(APLOG_MARK, r, 1, repos_path, dest_repos_path);
+      log_access_verdict(APLOG_MARK, r, 1, FALSE, repos_path, dest_repos_path);
       return OK;
     }
 
@@ -923,7 +934,7 @@ auth_checker(request_rec *r)
     {
       if (conf->authoritative)
         {
-          log_access_verdict(APLOG_MARK, r, 0, repos_path, dest_repos_path);
+          log_access_verdict(APLOG_MARK, r, 0, FALSE, repos_path, dest_repos_path);
           ap_note_auth_failure(r);
           return HTTP_FORBIDDEN;
         }
@@ -933,7 +944,7 @@ auth_checker(request_rec *r)
   if (status != OK)
     return status;
 
-  log_access_verdict(APLOG_MARK, r, 1, repos_path, dest_repos_path);
+  log_access_verdict(APLOG_MARK, r, 1, FALSE, repos_path, dest_repos_path);
 
   return OK;
 }

Modified: subversion/branches/svn-auth-x509/subversion/mod_dav_svn/liveprops.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/mod_dav_svn/liveprops.c?rev=1655189&r1=1655188&r2=1655189&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/mod_dav_svn/liveprops.c (original)
+++ subversion/branches/svn-auth-x509/subversion/mod_dav_svn/liveprops.c Tue Jan 27 23:27:44 2015
@@ -36,6 +36,7 @@
 #include "svn_time.h"
 #include "svn_dav.h"
 #include "svn_props.h"
+#include "svn_ctype.h"
 
 #include "private/svn_dav_protocol.h"
 
@@ -422,7 +423,43 @@ insert_prop_internal(const dav_resource
         if (last_author == NULL)
           return DAV_PROP_INSERT_NOTDEF;
 
-        value = apr_xml_quote_string(scratch_pool, last_author->data, 1);
+        if (svn_xml_is_xml_safe(last_author->data, last_author->len)
+            || !resource->info->repos->is_svn_client)
+          value = apr_xml_quote_string(scratch_pool, last_author->data, 1);
+        else
+          {
+            /* We are talking to a Subversion client, which will (like any proper
+               xml parser) error out if we produce control characters in XML.
+
+               However Subversion clients process both the generic
+               <creator-displayname /> as the custom element for svn:author.
+
+               Let's skip outputting the invalid characters here to make the XML
+               valid, so clients can see the custom element.
+
+               Subversion Clients will then either use a slightly invalid
+               author (unlikely) or more likely use the second result, which
+               will be transferred with full escaping capabilities.
+
+               We have tests in place to assert proper behavior over the RA layer.
+             */
+            apr_size_t i;
+            svn_stringbuf_t *buf;
+
+            buf = svn_stringbuf_create_from_string(last_author, scratch_pool);
+
+            for (i = 0; i < buf->len; i++)
+              {
+                char c = buf->data[i];
+
+                if (svn_ctype_iscntrl(c))
+                  {
+                    svn_stringbuf_remove(buf, i--, 1);
+                  }
+              }
+
+            value = apr_xml_quote_string(scratch_pool, buf->data, 1);
+          }
         break;
       }
 

Modified: subversion/branches/svn-auth-x509/subversion/mod_dav_svn/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/mod_dav_svn/merge.c?rev=1655189&r1=1655188&r2=1655189&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/mod_dav_svn/merge.c (original)
+++ subversion/branches/svn-auth-x509/subversion/mod_dav_svn/merge.c Tue Jan 27 23:27:44 2015
@@ -136,12 +136,13 @@ do_resources(const dav_svn_repos *repos,
       const void *key;
       void *val;
       const char *path;
+      apr_ssize_t path_len;
       svn_fs_path_change2_t *change;
       svn_boolean_t send_self;
       svn_boolean_t send_parent;
 
       svn_pool_clear(subpool);
-      apr_hash_this(hi, &key, NULL, &val);
+      apr_hash_this(hi, &key, &path_len, &val);
       path = key;
       change = val;
 
@@ -170,14 +171,14 @@ do_resources(const dav_svn_repos *repos,
         {
           /* If we haven't already sent this path, send it (and then
              remember that we sent it). */
-          if (! svn_hash_gets(sent, path))
+          if (! apr_hash_get(sent, path, path_len))
             {
               svn_node_kind_t kind;
               SVN_ERR(svn_fs_check_path(&kind, root, path, subpool));
               SVN_ERR(send_response(repos, root, path,
                                     kind == svn_node_dir,
                                     output, bb, subpool));
-              svn_hash_sets(sent, path, (void *)1);
+              apr_hash_set(sent, path, path_len, (void *)1);
             }
         }
       if (send_parent)

Modified: subversion/branches/svn-auth-x509/subversion/svnadmin/svnadmin.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/svnadmin/svnadmin.c?rev=1655189&r1=1655188&r2=1655189&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/svnadmin/svnadmin.c (original)
+++ subversion/branches/svn-auth-x509/subversion/svnadmin/svnadmin.c Tue Jan 27 23:27:44 2015
@@ -1271,7 +1271,7 @@ subcommand_freeze(apr_getopt_t *os, void
     }
 
   b.command = APR_ARRAY_IDX(args, 0, const char *);
-  b.args = apr_palloc(pool, sizeof(char *) * args->nelts + 1);
+  b.args = apr_palloc(pool, sizeof(char *) * (args->nelts + 1));
   for (i = 0; i < args->nelts; ++i)
     b.args[i] = APR_ARRAY_IDX(args, i, const char *);
   b.args[args->nelts] = NULL;