You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2015/01/27 13:39:15 UTC

svn commit: r1655026 - in /subversion/trunk/subversion: include/private/svn_repos_private.h libsvn_repos/dump.c svndumpfilter/svndumpfilter.c svnrdump/dump_editor.c

Author: julianfoad
Date: Tue Jan 27 12:39:14 2015
New Revision: 1655026

URL: http://svn.apache.org/r1655026
Log:
Factor out writing a dumpfile node record, from 'svnadmin dump', 'svnrdump
dump' and 'svndumpfilter'.

No functional change.

* subversion/include/private/svn_repos_private.h
  (svn_repos__dump_node_record): New function.

* subversion/libsvn_repos/dump.c
  (svn_repos__dump_node_record): New, moved from output_node_record in
    svndumpfilter.c. Make the content-length header optional when there are
    no properties or text, so we can preserve exact behaviour.
  (dump_node): Use it.

* subversion/svndumpfilter/svndumpfilter.c
  (output_node_record): Delete; move to svn_repos__dump_node_record.
  (set_fulltext,
   close_node): Adjust callers.

* subversion/svnrdump/dump_editor.c
  (dir_baton): Add a 'headers' field in which to accumulate headers.
  (make_dir_baton): Initialize the 'headers' field.
  (get_props_content): Don't add a Prop-content-length header here.
  (dump_node): Return headers instead of writing them.
  (dump_mkdir,
   dump_pending_dir): Simplify by using svn_repos__dump_node_record().
  (open_root,
   add_directory): Adjust a call to dump_node() to store the headers in the
    node baton instead of writing them out straight away.
  (close_directory): The same, and instead of adjusting the second dump_node
    call and then dumping the resulting headers, use dump_node_delete().
  (close_file): Adjust the call to dump_node() and use the headers returned
    from it as the starting point for creating the rest of the headers.

Modified:
    subversion/trunk/subversion/include/private/svn_repos_private.h
    subversion/trunk/subversion/libsvn_repos/dump.c
    subversion/trunk/subversion/svndumpfilter/svndumpfilter.c
    subversion/trunk/subversion/svnrdump/dump_editor.c

Modified: subversion/trunk/subversion/include/private/svn_repos_private.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_repos_private.h?rev=1655026&r1=1655025&r2=1655026&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_repos_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_repos_private.h Tue Jan 27 12:39:14 2015
@@ -363,6 +363,34 @@ svn_repos__dump_revision_record(svn_stre
                                 svn_boolean_t props_section_always,
                                 apr_pool_t *scratch_pool);
 
+/* Output node headers and props.
+ *
+ * Output HEADERS, content length headers, blank line, and
+ * then PROPS_STR (if non-null) to DUMP_STREAM.
+ *
+ * HEADERS is an array of headers as struct {const char *key, *val;}.
+ * Write them all in the given order.
+ *
+ * PROPS_STR is the property content block, including a terminating
+ * 'PROPS_END\n' line. Iff PROPS_STR is non-null, write a
+ * Prop-content-length header and the prop content block.
+ *
+ * Iff HAS_TEXT is true, write a Text-content length, using the value
+ * TEXT_CONTENT_LENGTH.
+ *
+ * Write a Content-length header, its value being the sum of the
+ * Prop- and Text- content length headers, if props and/or text are present
+ * or if CONTENT_LENGTH_ALWAYS is true.
+ */
+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);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/trunk/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_repos/dump.c?rev=1655026&r1=1655025&r2=1655026&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_repos/dump.c (original)
+++ subversion/trunk/subversion/libsvn_repos/dump.c Tue Jan 27 12:39:14 2015
@@ -563,6 +563,50 @@ svn_repos__dump_revision_record(svn_stre
   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. **/
@@ -1041,7 +1085,6 @@ 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;
@@ -1049,6 +1092,7 @@ dump_node(struct edit_baton *eb,
   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)
@@ -1293,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));
@@ -1361,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_repos__dumpfile_header_pushf(
-        headers, SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH,
-        "%" APR_SIZE_T_FMT, proplen);
     }
 
   /* If we are supposed to dump text, write out a text length header
@@ -1374,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)
         {
@@ -1411,11 +1448,6 @@ dump_node(struct edit_baton *eb,
           SVN_ERR(svn_fs_file_length(&textlen, eb->fs_root, path, pool));
         }
 
-      content_length += textlen;
-      svn_repos__dumpfile_header_pushf(
-        headers, SVN_REPOS_DUMPFILE_TEXT_CONTENT_LENGTH,
-        "%" SVN_FILESIZE_T_FMT, 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);
@@ -1434,18 +1466,12 @@ dump_node(struct edit_baton *eb,
   /* '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_repos__dumpfile_header_pushf(
-    headers, SVN_REPOS_DUMPFILE_CONTENT_LENGTH,
-    "%" SVN_FILESIZE_T_FMT, content_length);
-
-  SVN_ERR(svn_repos__dump_headers(eb->stream, headers, TRUE, pool));
-
-  /* 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))

Modified: subversion/trunk/subversion/svndumpfilter/svndumpfilter.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svndumpfilter/svndumpfilter.c?rev=1655026&r1=1655025&r2=1655026&view=diff
==============================================================================
--- subversion/trunk/subversion/svndumpfilter/svndumpfilter.c (original)
+++ subversion/trunk/subversion/svndumpfilter/svndumpfilter.c Tue Jan 27 12:39:14 2015
@@ -660,66 +660,6 @@ new_node_record(void **node_baton,
 }
 
 
-/* Output node headers and props.
- *
- * Write HEADERS, content length headers, a blank line, and the properties
- * content section PROPS_STR (if non-null) to DUMP_STREAM.
- *
- * HEADERS is an array of headers as struct {const char *key, *val;}.
- * Write them all in the given order.
- *
- * PROPS_STR is the property content block, including a terminating
- * 'PROPS_END\n' line. Iff PROPS_STR is non-null, write a
- * Prop-content-length header and the prop content block.
- *
- * Iff HAS_TEXT is true, write a Text-content length, using the value
- * TEXT_CONTENT_LENGTH.
- *
- * Always write a Content-length header, its value being the sum of the
- * Prop- and Text- content length headers.
- * ### TODO: Make it optional (only written if props and/or text present).
- */
-static svn_error_t *
-output_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,
-                   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;
-    }
-  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;
-}
-
-
 /* Examine the mergeinfo in INITIAL_VAL, omitting missing merge
    sources or renumbering revisions in rangelists as appropriate, and
    return the (possibly new) mergeinfo in *FINAL_VAL (allocated from
@@ -924,12 +864,13 @@ set_fulltext(svn_stream_t **stream, void
             {
               svn_stringbuf_appendcstr(nb->props, "PROPS-END\n");
             }
-          SVN_ERR(output_node_record(nb->rb->pb->out_stream,
-                                     nb->headers,
-                                     nb->has_props ? nb->props : NULL,
-                                     nb->has_text,
-                                     nb->tcl,
-                                     nb->node_pool));
+          SVN_ERR(svn_repos__dump_node_record(nb->rb->pb->out_stream,
+                                              nb->headers,
+                                              nb->has_props ? nb->props : NULL,
+                                              nb->has_text,
+                                              nb->tcl,
+                                              TRUE /*content_length_always*/,
+                                              nb->node_pool));
         }
       *stream = nb->rb->pb->out_stream;
     }
@@ -957,12 +898,13 @@ close_node(void *node_baton)
         {
           svn_stringbuf_appendcstr(nb->props, "PROPS-END\n");
         }
-      SVN_ERR(output_node_record(nb->rb->pb->out_stream,
-                                 nb->headers,
-                                 nb->has_props ? nb->props : NULL,
-                                 nb->has_text,
-                                 nb->tcl,
-                                 nb->node_pool));
+      SVN_ERR(svn_repos__dump_node_record(nb->rb->pb->out_stream,
+                                          nb->headers,
+                                          nb->has_props ? nb->props : NULL,
+                                          nb->has_text,
+                                          nb->tcl,
+                                          TRUE /*content_length_always*/,
+                                          nb->node_pool));
     }
 
   /* put an end to node. */

Modified: subversion/trunk/subversion/svnrdump/dump_editor.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svnrdump/dump_editor.c?rev=1655026&r1=1655025&r2=1655026&view=diff
==============================================================================
--- subversion/trunk/subversion/svnrdump/dump_editor.c (original)
+++ subversion/trunk/subversion/svnrdump/dump_editor.c Tue Jan 27 12:39:14 2015
@@ -57,6 +57,9 @@ struct dir_baton
   const char *copyfrom_path; /* a relpath */
   svn_revnum_t copyfrom_rev;
 
+  /* Headers accumulated so far for this directory */
+  apr_array_header_t *headers;
+
   /* Properties which were modified during change_dir_prop. */
   apr_hash_t *props;
 
@@ -184,6 +187,7 @@ make_dir_baton(const char *path,
                             ? svn_relpath_canonicalize(copyfrom_path, pool)
                             : NULL;
   new_db->copyfrom_rev = copyfrom_rev;
+  new_db->headers = NULL;
   new_db->props = apr_hash_make(pool);
   new_db->deleted_props = apr_hash_make(pool);
   new_db->deleted_entries = apr_hash_make(pool);
@@ -243,11 +247,6 @@ get_props_content(apr_array_header_t *he
   svn_repos__dumpfile_header_push(
     headers, SVN_REPOS_DUMPFILE_PROP_DELTA, "true");
 
-  /* Prop-content-length: 193 */
-  svn_repos__dumpfile_header_pushf(
-    headers, SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH,
-    "%" APR_SIZE_T_FMT, (*content)->len);
-
   return SVN_NO_ERROR;
 }
 
@@ -279,21 +278,26 @@ dump_node_delete(svn_stream_t *stream,
   return SVN_NO_ERROR;
 }
 
-/*
- * Write out a partial node record for PATH of type KIND.
+/* Set *HEADERS_P to contain some headers for the node at PATH of type KIND.
+ *
  * ACTION describes what is happening to the node (see enum
- * svn_node_action). Write record to writable EB->STREAM.
+ * svn_node_action).
  *
  * If the node was itself copied, IS_COPY is TRUE and the
  * path/revision of the copy source are in COPYFROM_PATH/COPYFROM_REV.
  * If IS_COPY is FALSE, yet COPYFROM_PATH/COPYFROM_REV are valid, this
  * node is part of a copied subtree.
-
- * Note: only when ACTION=delete, write a complete dumpfile record
- * terminated with blank lines.
+ *
+ * Iff ACTION is svn_node_action_replace and IS_COPY, then first write a
+ * complete deletion record to the dump stream.
+ *
+ * If ACTION is svn_node_action_delete, then the node record will be
+ * complete. (The caller may want to write two blank lines after the
+ * header block.)
  */
 static svn_error_t *
-dump_node(struct dump_edit_baton *eb,
+dump_node(apr_array_header_t **headers_p,
+          struct dump_edit_baton *eb,
           const char *repos_relpath,
           struct dir_baton *db,
           struct file_baton *fb,
@@ -345,13 +349,7 @@ dump_node(struct dump_edit_baton *eb,
       /* Node-action: delete */
       svn_repos__dumpfile_header_push(
         headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "delete");
-
-      /* We can leave this routine quietly now. Nothing more to do-
-         print the headers terminated by one blank line, and an extra
-         blank line because we're not dumping props or text. */
-      SVN_ERR(svn_repos__dump_headers(eb->stream, headers, TRUE, pool));
-      SVN_ERR(svn_stream_puts(eb->stream, "\n"));
-      return SVN_NO_ERROR;
+      break;
 
     case svn_node_action_replace:
       if (! is_copy)
@@ -434,10 +432,10 @@ dump_node(struct dump_edit_baton *eb,
       break;
     }
 
-  /* Write the headers so far. We don't necessarily have all the headers
+  /* Return the headers so far. We don't necessarily have all the headers
      yet -- there may be property-related and content length headers to
-     come -- so don't write a terminating blank line. */
-  SVN_ERR(svn_repos__dump_headers(eb->stream, headers, FALSE, pool));
+     come, if this was not a 'delete' record. */
+  *headers_p = headers;
   return SVN_NO_ERROR;
 }
 
@@ -447,7 +445,6 @@ dump_mkdir(struct dump_edit_baton *eb,
            apr_pool_t *pool)
 {
   svn_stringbuf_t *prop_content;
-  apr_size_t len;
   apr_array_header_t *headers = svn_repos__dumpfile_headers_create(pool);
 
   /* Node-path: ... */
@@ -466,11 +463,9 @@ dump_mkdir(struct dump_edit_baton *eb,
   SVN_ERR(get_props_content(headers, &prop_content,
                             apr_hash_make(pool), apr_hash_make(pool),
                             pool, pool));
-  len = prop_content->len;
-  svn_repos__dumpfile_header_pushf(headers, SVN_REPOS_DUMPFILE_CONTENT_LENGTH,
-                                   "%" APR_SIZE_T_FMT, len);
-  SVN_ERR(svn_repos__dump_headers(eb->stream, headers, TRUE, pool));
-  SVN_ERR(svn_stream_write(eb->stream, prop_content->data, &len));
+  SVN_ERR(svn_repos__dump_node_record(eb->stream, headers, prop_content,
+                                      FALSE, 0, FALSE /*content_length_always*/,
+                                      pool));
 
   /* Newlines to tie it all off. */
   SVN_ERR(svn_stream_puts(eb->stream, "\n\n"));
@@ -485,6 +480,7 @@ dump_pending_dir(struct dump_edit_baton
                  apr_pool_t *scratch_pool)
 {
   struct dir_baton *db = eb->pending_db;
+  svn_stringbuf_t *prop_content = NULL;
 
   if (! db)
     return SVN_NO_ERROR;
@@ -492,25 +488,16 @@ dump_pending_dir(struct dump_edit_baton
   /* Some pending properties to dump? */
   if (db->dump_props)
     {
-      apr_array_header_t *headers
-        = svn_repos__dumpfile_headers_create(scratch_pool);
-      svn_stringbuf_t *content;
-      apr_size_t len;
-
-      SVN_ERR(get_props_content(headers, &content, db->props, db->deleted_props,
+      SVN_ERR(get_props_content(db->headers, &prop_content,
+                                db->props, db->deleted_props,
                                 scratch_pool, scratch_pool));
-
-      /* Content-length: 14 */
-      svn_repos__dumpfile_header_pushf(
-        headers, SVN_REPOS_DUMPFILE_CONTENT_LENGTH,
-        "%" APR_SIZE_T_FMT, content->len);
-
-      SVN_ERR(svn_repos__dump_headers(eb->stream, headers, TRUE,
+    }
+  SVN_ERR(svn_repos__dump_node_record(eb->stream, db->headers, prop_content,
+                                      FALSE, 0, FALSE /*content_length_always*/,
                                       scratch_pool));
 
-      len = content->len;
-      SVN_ERR(svn_stream_write(eb->stream, content->data, &len));
-
+  if (db->dump_props)
+    {
       /* No text is going to be dumped. Write a couple of newlines and
          wait for the next node/ revision. */
       SVN_ERR(svn_stream_puts(eb->stream, "\n\n"));
@@ -583,7 +570,8 @@ open_root(void *edit_baton,
                  to letting the typical plumbing handle this task. */
               new_db = make_dir_baton(NULL, NULL, SVN_INVALID_REVNUM,
                                       edit_baton, NULL, pool);
-              SVN_ERR(dump_node(eb, new_db->repos_relpath, new_db,
+              SVN_ERR(dump_node(&new_db->headers,
+                                eb, new_db->repos_relpath, new_db,
                                 NULL, svn_node_action_add, FALSE,
                                 NULL, SVN_INVALID_REVNUM, pool));
 
@@ -649,7 +637,8 @@ add_directory(const char *path,
   is_copy = ARE_VALID_COPY_ARGS(copyfrom_path, copyfrom_rev);
 
   /* Dump the node */
-  SVN_ERR(dump_node(pb->eb, new_db->repos_relpath, new_db, NULL,
+  SVN_ERR(dump_node(&new_db->headers,
+                    pb->eb, new_db->repos_relpath, new_db, NULL,
                     was_deleted ? svn_node_action_replace : svn_node_action_add,
                     is_copy,
                     is_copy ? new_db->copyfrom_path : NULL,
@@ -723,7 +712,8 @@ close_directory(void *dir_baton,
      directory. */
   if ((! this_pending) && (db->dump_props))
     {
-      SVN_ERR(dump_node(db->eb, db->repos_relpath, db, NULL,
+      SVN_ERR(dump_node(&db->headers,
+                        db->eb, db->repos_relpath, db, NULL,
                         svn_node_action_change, FALSE,
                         NULL, SVN_INVALID_REVNUM, pool));
       db->eb->pending_db = db;
@@ -736,8 +726,9 @@ close_directory(void *dir_baton,
     {
       const char *path = apr_hash_this_key(hi);
 
-      SVN_ERR(dump_node(db->eb, path, NULL, NULL, svn_node_action_delete,
-                        FALSE, NULL, SVN_INVALID_REVNUM, pool));
+      SVN_ERR(dump_node_delete(db->eb->stream, path, pool));
+      /* This deletion record is complete -- write an extra newline */
+      SVN_ERR(svn_stream_puts(db->eb->stream, "\n"));
     }
 
   /* ### should be unnecessary */
@@ -904,13 +895,13 @@ close_file(void *file_baton,
   struct file_baton *fb = file_baton;
   struct dump_edit_baton *eb = fb->eb;
   apr_finfo_t *info = apr_pcalloc(pool, sizeof(apr_finfo_t));
-  svn_stringbuf_t *propstring;
-  apr_array_header_t *headers = svn_repos__dumpfile_headers_create(pool);
+  svn_stringbuf_t *propstring = NULL;
+  apr_array_header_t *headers;
 
   SVN_ERR(dump_pending_dir(eb, pool));
 
-  /* Dump the node. */
-  SVN_ERR(dump_node(eb, fb->repos_relpath, NULL, fb,
+  /* Start dumping this node, by collecting some basic headers for it. */
+  SVN_ERR(dump_node(&headers, eb, fb->repos_relpath, NULL, fb,
                     fb->action, fb->is_copy, fb->copyfrom_path,
                     fb->copyfrom_rev, pool));
 
@@ -942,35 +933,19 @@ close_file(void *file_baton,
         svn_repos__dumpfile_header_push(
           headers, SVN_REPOS_DUMPFILE_TEXT_DELTA_BASE_MD5, fb->base_checksum);
 
-      /* Text-content-length: 39 */
-      svn_repos__dumpfile_header_pushf(
-        headers, SVN_REPOS_DUMPFILE_TEXT_CONTENT_LENGTH,
-        "%lu", (unsigned long)info->size);
-
       /* Text-content-md5: 82705804337e04dcd0e586bfa2389a7f */
       svn_repos__dumpfile_header_push(
         headers, SVN_REPOS_DUMPFILE_TEXT_CONTENT_MD5, text_checksum);
     }
 
-  /* Content-length: 1549 */
-  /* If both text and props are absent, skip this header */
-  if (fb->dump_props)
-    svn_repos__dumpfile_header_pushf(
-      headers, SVN_REPOS_DUMPFILE_CONTENT_LENGTH,
-      "%lu", (unsigned long)(info->size + propstring->len));
-  else if (fb->dump_text)
-    svn_repos__dumpfile_header_pushf(
-      headers, SVN_REPOS_DUMPFILE_CONTENT_LENGTH,
-      "%lu", (unsigned long)info->size);
+  /* Dump the headers and props now */
+  SVN_ERR(svn_repos__dump_node_record(eb->stream, headers, propstring,
+                                      fb->dump_text, info->size,
+                                      FALSE /*content_length_always*/,
+                                      pool));
 
-  SVN_ERR(svn_repos__dump_headers(eb->stream, headers, TRUE, pool));
-
-  /* Dump the props now */
   if (fb->dump_props)
     {
-      SVN_ERR(svn_stream_write(eb->stream, propstring->data,
-                               &(propstring->len)));
-
       /* Cleanup */
       fb->dump_props = FALSE;
       apr_hash_clear(fb->props);