Index: subversion/svnadmin/main.c
===================================================================
--- subversion/svnadmin/main.c	(revision 6839)
+++ subversion/svnadmin/main.c	(working copy)
@@ -66,7 +66,8 @@
   subcommand_list_unused_dblogs,
   subcommand_recover,
   subcommand_rmtxns,
-  subcommand_setlog;
+  subcommand_setlog,
+  subcommand_verify;
 
 enum 
   { 
@@ -223,6 +224,10 @@
      "(Note that revision properties are not historied, so this command\n"
      "will permanently overwrite the previous log message.)\n",
      {'r'} },
+    {"verify", subcommand_verify, {0},
+     "usage: svnadmin verify REPOS_PATH\n\n"
+     "Verifies the data stored in the repository.\n",
+     {0} },
 
     { NULL, NULL, {0}, NULL, {0} }
   };
@@ -246,6 +251,8 @@
   const char *parent_dir;
 
   const char *config_dir;    /* Overriding Configuration Directory */
+
+  svn_boolean_t verify;      /* Verify instead of dumping repository */
 };
 
 /* This implements `svn_opt_subcommand_t'. */
@@ -345,8 +352,13 @@
 
   /* Run the dump to STDOUT.  Let the user redirect output into
      a file if they want.  :-)  */
-  SVN_ERR (create_stdio_stream (&stdout_stream,
-                                apr_file_open_stdout, pool));
+  if (!opt_state->verify)
+    SVN_ERR (create_stdio_stream (&stdout_stream,
+                                  apr_file_open_stdout, pool));
+  else
+    /* If the verify flag was set, we just walk through the repository
+       dumping data without actually writing out any data */
+    stdout_stream = NULL;
 
   /* Progress feedback goes to stderr, unless they asked to suppress
      it. */
@@ -631,6 +643,17 @@
 }
 
 
+/* This implements `svn_opt_subcommand_t'. */
+static svn_error_t *
+subcommand_verify (apr_getopt_t *os, void *baton, apr_pool_t *pool)
+{
+  struct svnadmin_opt_state *opt_state = baton;
+  
+  opt_state->verify = TRUE;
+  opt_state->incremental = TRUE;
+  return subcommand_dump (os, baton, pool);
+}
+
 
 /** Main. **/
 
Index: subversion/include/svn_repos.h
===================================================================
--- subversion/include/svn_repos.h	(revision 6839)
+++ subversion/include/svn_repos.h	(working copy)
@@ -770,7 +770,8 @@
 /** Dump the contents of the filesystem within already-open @a repos into
  * writable @a dumpstream.  Begin at revision @a start_rev, and dump every
  * revision up through @a end_rev.  Use @a pool for all allocation.  If
- * non-@c NULL, send feedback to @a feedback_stream.
+ * non-@c NULL, send feedback to @a feedback_stream. @a dumpstream can be
+ * @c NULL for the purpose of verifying the repository.
  *
  * If @a start_rev is @c SVN_INVALID_REVNUM, then start dumping at revision 
  * 0.  If @a end_rev is @c SVN_INVALID_REVNUM, then dump through the @c HEAD 
Index: subversion/libsvn_repos/dump.c
===================================================================
--- subversion/libsvn_repos/dump.c	(revision 6839)
+++ subversion/libsvn_repos/dump.c	(working copy)
@@ -231,13 +231,14 @@
   svn_revnum_t compare_rev = eb->current_rev - 1;
 
   /* Write out metadata headers for this file node. */
-  SVN_ERR (svn_stream_printf (eb->stream, pool,
-                              SVN_REPOS_DUMPFILE_NODE_PATH ": %s\n", path));
+  if (eb->stream)
+    SVN_ERR (svn_stream_printf (eb->stream, pool,
+                                SVN_REPOS_DUMPFILE_NODE_PATH ": %s\n", path));
   
-  if (kind == svn_node_file)
+  if (kind == svn_node_file && eb->stream)
     SVN_ERR (svn_stream_printf (eb->stream, pool,
                                 SVN_REPOS_DUMPFILE_NODE_KIND ": file\n"));
-  else if (kind == svn_node_dir)
+  else if (kind == svn_node_dir && eb->stream)
     SVN_ERR (svn_stream_printf (eb->stream, pool,
                                 SVN_REPOS_DUMPFILE_NODE_KIND ": dir\n"));
 
@@ -257,9 +258,10 @@
       svn_fs_root_t *compare_root;
       int text_changed = 0, props_changed = 0;
 
-      SVN_ERR (svn_stream_printf (eb->stream, pool,
-                                  SVN_REPOS_DUMPFILE_NODE_ACTION
-                                  ": change\n"));
+      if (eb->stream)
+        SVN_ERR (svn_stream_printf (eb->stream, pool,
+                                    SVN_REPOS_DUMPFILE_NODE_ACTION
+                                    ": change\n"));
 
       /* either the text or props changed, or possibly both. */
       SVN_ERR (svn_fs_revision_root (&compare_root, 
@@ -283,9 +285,10 @@
       if (! is_copy)
         {
           /* a simple delete+add, implied by a single 'replace' action. */
-          SVN_ERR (svn_stream_printf (eb->stream, pool,
-                                      SVN_REPOS_DUMPFILE_NODE_ACTION
-                                      ": replace\n")); 
+          if (eb->stream)
+            SVN_ERR (svn_stream_printf (eb->stream, pool,
+                                        SVN_REPOS_DUMPFILE_NODE_ACTION
+                                        ": replace\n")); 
 
           /* definitely need to dump all content for a replace. */
           if (kind == svn_node_file)
@@ -298,9 +301,10 @@
 
           /* the path & kind headers have already been printed;  just
              add a delete action, and end the current record.*/
-          SVN_ERR (svn_stream_printf (eb->stream, pool,
-                                      SVN_REPOS_DUMPFILE_NODE_ACTION
-                                      ": delete\n\n"));  
+          if (eb->stream)
+            SVN_ERR (svn_stream_printf (eb->stream, pool,
+                                        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,
@@ -314,9 +318,10 @@
     }
   else if (action == svn_node_action_delete)
     {
-      SVN_ERR (svn_stream_printf (eb->stream, pool,
-                                  SVN_REPOS_DUMPFILE_NODE_ACTION
-                                  ": delete\n"));  
+      if (eb->stream)
+        SVN_ERR (svn_stream_printf (eb->stream, pool,
+                                    SVN_REPOS_DUMPFILE_NODE_ACTION
+                                    ": delete\n"));  
 
       /* we can leave this routine quietly now, don't need to dump
          any content. */
@@ -325,8 +330,9 @@
     }
   else if (action == svn_node_action_add)
     {
-      SVN_ERR (svn_stream_printf (eb->stream, pool,
-                                  SVN_REPOS_DUMPFILE_NODE_ACTION ": add\n"));
+      if (eb->stream)
+        SVN_ERR (svn_stream_printf (eb->stream, pool,
+                                    SVN_REPOS_DUMPFILE_NODE_ACTION ": add\n"));
 
       if (! is_copy)
         {
@@ -349,12 +355,13 @@
                "\n... loading this dump into an empty repository will fail.\n",
                cmp_rev, eb->oldest_dumped_rev);
 
-          SVN_ERR (svn_stream_printf (eb->stream, pool,
-                                      SVN_REPOS_DUMPFILE_NODE_COPYFROM_REV 
-                                      ": %" SVN_REVNUM_T_FMT "\n"
-                                      SVN_REPOS_DUMPFILE_NODE_COPYFROM_PATH
-                                      ": %s\n",                  
-                                      cmp_rev, cmp_path));
+          if (eb->stream)
+            SVN_ERR (svn_stream_printf (eb->stream, pool,
+                                        SVN_REPOS_DUMPFILE_NODE_COPYFROM_REV 
+                                        ": %" SVN_REVNUM_T_FMT "\n"
+                                        SVN_REPOS_DUMPFILE_NODE_COPYFROM_PATH
+                                        ": %s\n",
+                                        cmp_rev, cmp_path));
 
           SVN_ERR (svn_fs_revision_root (&src_root, 
                                          svn_fs_root_fs (eb->fs_root),
@@ -385,8 +392,12 @@
          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? */
+      if (eb->stream)
+        {
+          len = 2;
+          return svn_stream_write (eb->stream, "\n\n", &len); /* ### needed? */
+        }
+      return SVN_NO_ERROR;
     }
 
   /*** Start prepping content to dump... ***/
@@ -400,9 +411,10 @@
       write_hash_to_stringbuf (prophash, &propstring, pool);
       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 (eb->stream)
+        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
@@ -414,13 +426,14 @@
 
       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));
+      if (eb->stream)
+        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_md5_checksum (md5_digest, eb->fs_root, path, pool));
       hex_digest = svn_md5_digest_to_cstring (md5_digest, pool);
-      if (hex_digest)
+      if (hex_digest && eb->stream)
         SVN_ERR (svn_stream_printf (eb->stream, pool,
                                     SVN_REPOS_DUMPFILE_TEXT_CONTENT_CHECKSUM 
                                     ": %s\n", hex_digest));
@@ -430,13 +443,14 @@
      and is the summation 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));
+  if (eb->stream)
+    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)
+  if (must_dump_props && eb->stream)
     {
       len = propstring->len;
       SVN_ERR (svn_stream_write (eb->stream, propstring->data, &len));
@@ -459,17 +473,20 @@
           SVN_ERR (svn_stream_read (contents, eb->buffer, &rlen));
           
           /* write however many bytes you read, please. */
-          wlen = rlen;
-          SVN_ERR (svn_stream_write (eb->stream, eb->buffer, &wlen));
-          if (wlen != rlen)
+          if (eb->stream)
             {
-              /* Uh oh, didn't write as many bytes as we read, and no
-                 error was returned.  According to the docstring, this
-                 should never happen. */
-              return 
-                svn_error_createf (SVN_ERR_STREAM_UNEXPECTED_EOF, NULL,
-                                   "Error dumping textual contents of '%s'.",
-                                   path);
+              wlen = rlen;
+              SVN_ERR (svn_stream_write (eb->stream, eb->buffer, &wlen));
+              if (wlen != rlen)
+                {
+                  /* Uh oh, didn't write as many bytes as we read, and no
+                     error was returned.  According to the docstring, this
+                     should never happen. */
+                  return 
+                    svn_error_createf (SVN_ERR_STREAM_UNEXPECTED_EOF, NULL,
+                                       "Error dumping textual contents of '%s'.",
+                                       path);
+                }
             }
         
         if (rlen != eb->bufsize)
@@ -482,8 +499,11 @@
         }
     }
   
-  len = 2;
-  SVN_ERR (svn_stream_write (eb->stream, "\n\n", &len)); /* ### needed? */
+  if (eb->stream)
+    {
+      len = 2;
+      SVN_ERR (svn_stream_write (eb->stream, "\n\n", &len)); /* ### needed? */
+    }
   
   return SVN_NO_ERROR;
 }
@@ -771,52 +791,57 @@
   apr_hash_t *props;
   svn_stringbuf_t *encoded_prophash;
 
+  /* Read the revision props even if we're aren't going to dump
+     them for verification purposes */
   SVN_ERR (svn_fs_revision_proplist (&props, fs, rev, pool));
 
-  {
-    /* Run revision date properties through the time conversion to
-       canonize them. */
-    /* ### Remove this when it is no longer needed for sure. */
-    apr_time_t timetemp;
-    svn_string_t *datevalue = apr_hash_get (props,
-                                            SVN_PROP_REVISION_DATE,
-                                            APR_HASH_KEY_STRING);
-    if (datevalue)
+  if (stream)
+    {
       {
-        SVN_ERR (svn_time_from_cstring (&timetemp, datevalue->data, pool));
-        datevalue = svn_string_create (svn_time_to_cstring (timetemp, pool),
-                                       pool);
-        apr_hash_set (props,
-                      SVN_PROP_REVISION_DATE,
-                      APR_HASH_KEY_STRING,
-                      datevalue);
+        /* Run revision date properties through the time conversion to
+           canonize them. */
+        /* ### Remove this when it is no longer needed for sure. */
+        apr_time_t timetemp;
+        svn_string_t *datevalue = apr_hash_get (props,
+                                                SVN_PROP_REVISION_DATE,
+                                                APR_HASH_KEY_STRING);
+        if (datevalue)
+          {
+            SVN_ERR (svn_time_from_cstring (&timetemp, datevalue->data, pool));
+            datevalue = svn_string_create (svn_time_to_cstring (timetemp, pool),
+                                           pool);
+            apr_hash_set (props,
+                          SVN_PROP_REVISION_DATE,
+                          APR_HASH_KEY_STRING,
+                          datevalue);
+          }
       }
-  }
 
-  write_hash_to_stringbuf (props, &encoded_prophash, pool);
+      write_hash_to_stringbuf (props, &encoded_prophash, pool);
 
-  /* ### someday write a revision-content-checksum */
+      /* ### someday write a revision-content-checksum */
 
-  SVN_ERR (svn_stream_printf (stream, pool,
-                              SVN_REPOS_DUMPFILE_REVISION_NUMBER 
-                              ": %" SVN_REVNUM_T_FMT "\n", rev));
-  SVN_ERR (svn_stream_printf (stream, pool,
-                              SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH
-                              ": %" APR_SIZE_T_FMT "\n",
-                              encoded_prophash->len));
+      SVN_ERR (svn_stream_printf (stream, pool,
+                                  SVN_REPOS_DUMPFILE_REVISION_NUMBER 
+                                  ": %" SVN_REVNUM_T_FMT "\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));
+      /* 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 = 1;
-  SVN_ERR (svn_stream_write (stream, "\n", &len));
+      len = encoded_prophash->len;
+      SVN_ERR (svn_stream_write (stream, encoded_prophash->data, &len));
+
+      len = 1;
+      SVN_ERR (svn_stream_write (stream, "\n", &len));
+    }
   
   return SVN_NO_ERROR;
 }
@@ -868,13 +893,15 @@
 
   /* Write out "general" metadata for the dumpfile.  In this case, a
      magic header followed by a dumpfile format version. */
-  SVN_ERR (svn_stream_printf (stream, pool, SVN_REPOS_DUMPFILE_MAGIC_HEADER
-                              ": %d\n\n", SVN_REPOS_DUMPFILE_FORMAT_VERSION));
+  if (stream)
+    SVN_ERR (svn_stream_printf (stream, pool, SVN_REPOS_DUMPFILE_MAGIC_HEADER
+                                ": %d\n\n", SVN_REPOS_DUMPFILE_FORMAT_VERSION));
   /* Write out the UUID. */
   SVN_ERR (svn_fs_get_uuid(fs, &uuid, pool));
 
-  SVN_ERR (svn_stream_printf (stream, pool, SVN_REPOS_DUMPFILE_UUID
-                              ": %s\n\n", uuid));
+  if (stream)
+    SVN_ERR (svn_stream_printf (stream, pool, SVN_REPOS_DUMPFILE_UUID
+                                ": %s\n\n", uuid));
                    
   /* Main loop:  we're going to dump revision i.  */
   for (i = start_rev; i <= end_rev; i++)
@@ -946,9 +973,14 @@
       /* Reuse all memory consumed by the dump of this one revision. */
       svn_pool_clear (subpool);
       if (feedback_stream)
-        svn_stream_printf (feedback_stream, pool,
-                           "* Dumped revision %" SVN_REVNUM_T_FMT ".\n",
-                           to_rev);
+        if (stream)
+          svn_stream_printf (feedback_stream, pool,
+                             "* Dumped revision %" SVN_REVNUM_T_FMT ".\n",
+                             to_rev);
+        else
+          svn_stream_printf (feedback_stream, pool,
+                             "* Verified revision %" SVN_REVNUM_T_FMT ".\n",
+                             to_rev);
     }
 
   svn_pool_destroy (subpool);
