You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2018/11/07 12:30:11 UTC

svn commit: r1846002 [10/44] - in /subversion/branches/ra-git: ./ build/ build/ac-macros/ build/generator/ build/generator/swig/ build/generator/templates/ build/generator/util/ build/win32/ contrib/client-side/ contrib/client-side/svn_load_dirs/ contr...

Modified: subversion/branches/ra-git/subversion/libsvn_delta/cancel.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_delta/cancel.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_delta/cancel.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_delta/cancel.c Wed Nov  7 12:30:06 2018
@@ -222,6 +222,26 @@ apply_textdelta(void *file_baton,
 }
 
 static svn_error_t *
+apply_textdelta_stream(const svn_delta_editor_t *editor,
+                       void *file_baton,
+                       const char *base_checksum,
+                       svn_txdelta_stream_open_func_t open_func,
+                       void *open_baton,
+                       apr_pool_t *scratch_pool)
+{
+  struct file_baton *fb = file_baton;
+  struct edit_baton *eb = fb->edit_baton;
+
+  SVN_ERR(eb->cancel_func(eb->cancel_baton));
+
+  return eb->wrapped_editor->apply_textdelta_stream(eb->wrapped_editor,
+                                                    fb->wrapped_file_baton,
+                                                    base_checksum,
+                                                    open_func, open_baton,
+                                                    scratch_pool);
+}
+
+static svn_error_t *
 close_file(void *file_baton,
            const char *text_checksum,
            apr_pool_t *pool)
@@ -354,6 +374,7 @@ svn_delta_get_cancellation_editor(svn_ca
       tree_editor->add_file = add_file;
       tree_editor->open_file = open_file;
       tree_editor->apply_textdelta = apply_textdelta;
+      tree_editor->apply_textdelta_stream = apply_textdelta_stream;
       tree_editor->change_file_prop = change_file_prop;
       tree_editor->close_file = close_file;
       tree_editor->absent_file = absent_file;

Modified: subversion/branches/ra-git/subversion/libsvn_delta/debug_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_delta/debug_editor.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_delta/debug_editor.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_delta/debug_editor.c Wed Nov  7 12:30:06 2018
@@ -71,9 +71,11 @@ set_target_revision(void *edit_baton,
   SVN_ERR(svn_stream_printf(eb->out, pool, "set_target_revision : %ld\n",
                             target_revision));
 
-  return eb->wrapped_editor->set_target_revision(eb->wrapped_edit_baton,
-                                                 target_revision,
-                                                 pool);
+  if (eb->wrapped_editor)
+    SVN_ERR(eb->wrapped_editor->set_target_revision(eb->wrapped_edit_baton,
+                                                    target_revision,
+                                                    pool));
+  return SVN_NO_ERROR;
 }
 
 static svn_error_t *
@@ -90,10 +92,11 @@ open_root(void *edit_baton,
                             base_revision));
   eb->indent_level++;
 
-  SVN_ERR(eb->wrapped_editor->open_root(eb->wrapped_edit_baton,
-                                        base_revision,
-                                        pool,
-                                        &dir_baton->wrapped_dir_baton));
+  if (eb->wrapped_editor)
+    SVN_ERR(eb->wrapped_editor->open_root(eb->wrapped_edit_baton,
+                                          base_revision,
+                                          pool,
+                                          &dir_baton->wrapped_dir_baton));
 
   dir_baton->edit_baton = edit_baton;
 
@@ -115,10 +118,12 @@ delete_entry(const char *path,
   SVN_ERR(svn_stream_printf(eb->out, pool, "delete_entry : %s:%ld\n",
                             path, base_revision));
 
-  return eb->wrapped_editor->delete_entry(path,
-                                          base_revision,
-                                          pb->wrapped_dir_baton,
-                                          pool);
+  if (eb->wrapped_editor)
+    SVN_ERR(eb->wrapped_editor->delete_entry(path,
+                                             base_revision,
+                                             pb->wrapped_dir_baton,
+                                             pool));
+  return SVN_NO_ERROR;
 }
 
 static svn_error_t *
@@ -139,12 +144,13 @@ add_directory(const char *path,
                             path, copyfrom_path, copyfrom_revision));
   eb->indent_level++;
 
-  SVN_ERR(eb->wrapped_editor->add_directory(path,
-                                            pb->wrapped_dir_baton,
-                                            copyfrom_path,
-                                            copyfrom_revision,
-                                            pool,
-                                            &b->wrapped_dir_baton));
+  if (eb->wrapped_editor)
+    SVN_ERR(eb->wrapped_editor->add_directory(path,
+                                              pb->wrapped_dir_baton,
+                                              copyfrom_path,
+                                              copyfrom_revision,
+                                              pool,
+                                              &b->wrapped_dir_baton));
 
   b->edit_baton = eb;
   *child_baton = b;
@@ -168,11 +174,12 @@ open_directory(const char *path,
                             path, base_revision));
   eb->indent_level++;
 
-  SVN_ERR(eb->wrapped_editor->open_directory(path,
-                                             pb->wrapped_dir_baton,
-                                             base_revision,
-                                             pool,
-                                             &db->wrapped_dir_baton));
+  if (eb->wrapped_editor)
+    SVN_ERR(eb->wrapped_editor->open_directory(path,
+                                               pb->wrapped_dir_baton,
+                                               base_revision,
+                                               pool,
+                                               &db->wrapped_dir_baton));
 
   db->edit_baton = eb;
   *child_baton = db;
@@ -199,12 +206,13 @@ add_file(const char *path,
 
   eb->indent_level++;
 
-  SVN_ERR(eb->wrapped_editor->add_file(path,
-                                       pb->wrapped_dir_baton,
-                                       copyfrom_path,
-                                       copyfrom_revision,
-                                       pool,
-                                       &fb->wrapped_file_baton));
+  if (eb->wrapped_editor)
+    SVN_ERR(eb->wrapped_editor->add_file(path,
+                                         pb->wrapped_dir_baton,
+                                         copyfrom_path,
+                                         copyfrom_revision,
+                                         pool,
+                                         &fb->wrapped_file_baton));
 
   fb->edit_baton = eb;
   *file_baton = fb;
@@ -229,11 +237,12 @@ open_file(const char *path,
 
   eb->indent_level++;
 
-  SVN_ERR(eb->wrapped_editor->open_file(path,
-                                        pb->wrapped_dir_baton,
-                                        base_revision,
-                                        pool,
-                                        &fb->wrapped_file_baton));
+  if (eb->wrapped_editor)
+    SVN_ERR(eb->wrapped_editor->open_file(path,
+                                          pb->wrapped_dir_baton,
+                                          base_revision,
+                                          pool,
+                                          &fb->wrapped_file_baton));
 
   fb->edit_baton = eb;
   *file_baton = fb;
@@ -255,11 +264,38 @@ apply_textdelta(void *file_baton,
   SVN_ERR(svn_stream_printf(eb->out, pool, "apply_textdelta : %s\n",
                             base_checksum));
 
-  SVN_ERR(eb->wrapped_editor->apply_textdelta(fb->wrapped_file_baton,
-                                              base_checksum,
-                                              pool,
-                                              handler,
-                                              handler_baton));
+  if (eb->wrapped_editor)
+    SVN_ERR(eb->wrapped_editor->apply_textdelta(fb->wrapped_file_baton,
+                                                base_checksum,
+                                                pool,
+                                                handler,
+                                                handler_baton));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+apply_textdelta_stream(const struct svn_delta_editor_t *editor,
+                       void *file_baton,
+                       const char *base_checksum,
+                       svn_txdelta_stream_open_func_t open_func,
+                       void *open_baton,
+                       apr_pool_t *scratch_pool)
+{
+  struct file_baton *fb = file_baton;
+  struct edit_baton *eb = fb->edit_baton;
+
+  SVN_ERR(write_indent(eb, scratch_pool));
+  SVN_ERR(svn_stream_printf(eb->out, scratch_pool,
+                            "apply_textdelta_stream : %s\n",
+                            base_checksum));
+
+  if (eb->wrapped_editor)
+    SVN_ERR(eb->wrapped_editor->apply_textdelta_stream(eb->wrapped_editor,
+                                                       fb->wrapped_file_baton,
+                                                       base_checksum,
+                                                       open_func, open_baton,
+                                                       scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -278,8 +314,9 @@ close_file(void *file_baton,
   SVN_ERR(svn_stream_printf(eb->out, pool, "close_file : %s\n",
                             text_checksum));
 
-  SVN_ERR(eb->wrapped_editor->close_file(fb->wrapped_file_baton,
-                                         text_checksum, pool));
+  if (eb->wrapped_editor)
+    SVN_ERR(eb->wrapped_editor->close_file(fb->wrapped_file_baton,
+                                           text_checksum, pool));
 
   return SVN_NO_ERROR;
 }
@@ -295,8 +332,9 @@ absent_file(const char *path,
   SVN_ERR(write_indent(eb, pool));
   SVN_ERR(svn_stream_printf(eb->out, pool, "absent_file : %s\n", path));
 
-  SVN_ERR(eb->wrapped_editor->absent_file(path, fb->wrapped_file_baton,
-                                          pool));
+  if (eb->wrapped_editor)
+    SVN_ERR(eb->wrapped_editor->absent_file(path, fb->wrapped_file_baton,
+                                            pool));
 
   return SVN_NO_ERROR;
 }
@@ -312,8 +350,9 @@ close_directory(void *dir_baton,
   SVN_ERR(write_indent(eb, pool));
   SVN_ERR(svn_stream_printf(eb->out, pool, "close_directory\n"));
 
-  SVN_ERR(eb->wrapped_editor->close_directory(db->wrapped_dir_baton,
-                                              pool));
+  if (eb->wrapped_editor)
+    SVN_ERR(eb->wrapped_editor->close_directory(db->wrapped_dir_baton,
+                                                pool));
 
   return SVN_NO_ERROR;
 }
@@ -330,8 +369,9 @@ absent_directory(const char *path,
   SVN_ERR(svn_stream_printf(eb->out, pool, "absent_directory : %s\n",
                             path));
 
-  SVN_ERR(eb->wrapped_editor->absent_directory(path, db->wrapped_dir_baton,
-                                               pool));
+  if (eb->wrapped_editor)
+    SVN_ERR(eb->wrapped_editor->absent_directory(path, db->wrapped_dir_baton,
+                                                 pool));
 
   return SVN_NO_ERROR;
 }
@@ -349,10 +389,11 @@ change_file_prop(void *file_baton,
   SVN_ERR(svn_stream_printf(eb->out, pool, "change_file_prop : %s -> %s\n",
                             name, value ? value->data : "<deleted>"));
 
-  SVN_ERR(eb->wrapped_editor->change_file_prop(fb->wrapped_file_baton,
-                                               name,
-                                               value,
-                                               pool));
+  if (eb->wrapped_editor)
+    SVN_ERR(eb->wrapped_editor->change_file_prop(fb->wrapped_file_baton,
+                                                 name,
+                                                 value,
+                                                 pool));
 
   return SVN_NO_ERROR;
 }
@@ -370,10 +411,11 @@ change_dir_prop(void *dir_baton,
   SVN_ERR(svn_stream_printf(eb->out, pool, "change_dir_prop : %s -> %s\n",
                             name, value ? value->data : "<deleted>"));
 
-  SVN_ERR(eb->wrapped_editor->change_dir_prop(db->wrapped_dir_baton,
-                                              name,
-                                              value,
-                                              pool));
+  if (eb->wrapped_editor)
+    SVN_ERR(eb->wrapped_editor->change_dir_prop(db->wrapped_dir_baton,
+                                                name,
+                                                value,
+                                                pool));
 
   return SVN_NO_ERROR;
 }
@@ -387,7 +429,8 @@ close_edit(void *edit_baton,
   SVN_ERR(write_indent(eb, pool));
   SVN_ERR(svn_stream_printf(eb->out, pool, "close_edit\n"));
 
-  SVN_ERR(eb->wrapped_editor->close_edit(eb->wrapped_edit_baton, pool));
+  if (eb->wrapped_editor)
+    SVN_ERR(eb->wrapped_editor->close_edit(eb->wrapped_edit_baton, pool));
 
   return SVN_NO_ERROR;
 }
@@ -401,7 +444,8 @@ abort_edit(void *edit_baton,
   SVN_ERR(write_indent(eb, pool));
   SVN_ERR(svn_stream_printf(eb->out, pool, "abort_edit\n"));
 
-  SVN_ERR(eb->wrapped_editor->abort_edit(eb->wrapped_edit_baton, pool));
+  if (eb->wrapped_editor)
+    SVN_ERR(eb->wrapped_editor->abort_edit(eb->wrapped_edit_baton, pool));
 
   return SVN_NO_ERROR;
 }
@@ -414,7 +458,7 @@ svn_delta__get_debug_editor(const svn_de
                             const char *prefix,
                             apr_pool_t *pool)
 {
-  svn_delta_editor_t *tree_editor = apr_palloc(pool, sizeof(*tree_editor));
+  svn_delta_editor_t *tree_editor = svn_delta_default_editor(pool);
   struct edit_baton *eb = apr_palloc(pool, sizeof(*eb));
   apr_file_t *errfp;
   svn_stream_t *out;
@@ -436,6 +480,7 @@ svn_delta__get_debug_editor(const svn_de
   tree_editor->add_file = add_file;
   tree_editor->open_file = open_file;
   tree_editor->apply_textdelta = apply_textdelta;
+  tree_editor->apply_textdelta_stream = apply_textdelta_stream;
   tree_editor->change_file_prop = change_file_prop;
   tree_editor->close_file = close_file;
   tree_editor->absent_file = absent_file;

Modified: subversion/branches/ra-git/subversion/libsvn_delta/default_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_delta/default_editor.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_delta/default_editor.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_delta/default_editor.c Wed Nov  7 12:30:06 2018
@@ -133,6 +133,33 @@ close_file(void *file_baton,
 }
 
 
+static svn_error_t *
+apply_textdelta_stream(const svn_delta_editor_t *editor,
+                       void *file_baton,
+                       const char *base_checksum,
+                       svn_txdelta_stream_open_func_t open_func,
+                       void *open_baton,
+                       apr_pool_t *scratch_pool)
+{
+  svn_txdelta_window_handler_t handler;
+  void *handler_baton;
+
+  SVN_ERR(editor->apply_textdelta(file_baton, base_checksum,
+                                  scratch_pool, &handler,
+                                  &handler_baton));
+  if (handler != svn_delta_noop_window_handler)
+    {
+      svn_txdelta_stream_t *txdelta_stream;
+
+      SVN_ERR(open_func(&txdelta_stream, open_baton, scratch_pool,
+                        scratch_pool));
+      SVN_ERR(svn_txdelta_send_txstream(txdelta_stream, handler,
+                                        handler_baton, scratch_pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
 
 static const svn_delta_editor_t default_editor =
 {
@@ -151,7 +178,8 @@ static const svn_delta_editor_t default_
   close_file,
   absent_xxx_func,
   single_baton_func,
-  single_baton_func
+  single_baton_func,
+  apply_textdelta_stream
 };
 
 svn_delta_editor_t *

Modified: subversion/branches/ra-git/subversion/libsvn_delta/element.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_delta/element.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_delta/element.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_delta/element.c Wed Nov  7 12:30:06 2018
@@ -375,14 +375,12 @@ svn_element__tree_get(const svn_element_
   return svn_eid__hash_get(tree->e_map, eid);
 }
 
-svn_error_t *
+void
 svn_element__tree_set(svn_element__tree_t *tree,
                       int eid,
                       const svn_element__content_t *element)
 {
   svn_eid__hash_set(tree->e_map, eid, element);
-
-  return SVN_NO_ERROR;
 }
 
 void

Modified: subversion/branches/ra-git/subversion/libsvn_delta/svndiff.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_delta/svndiff.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_delta/svndiff.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_delta/svndiff.c Wed Nov  7 12:30:06 2018
@@ -38,13 +38,16 @@
 
 static const char SVNDIFF_V0[] = { 'S', 'V', 'N', 0 };
 static const char SVNDIFF_V1[] = { 'S', 'V', 'N', 1 };
+static const char SVNDIFF_V2[] = { 'S', 'V', 'N', 2 };
 
 #define SVNDIFF_HEADER_SIZE (sizeof(SVNDIFF_V0))
 
 static const char *
 get_svndiff_header(int version)
 {
-  if (version == 1)
+  if (version == 2)
+    return SVNDIFF_V2;
+  else if (version == 1)
     return SVNDIFF_V1;
   else
     return SVNDIFF_V0;
@@ -148,7 +151,7 @@ send_simple_insertion_window(svn_txdelta
 }
 
 /* Encodes delta window WINDOW to svndiff-format.
-   The svndiff version is VERSION. COMPRESSION_LEVEL is the zlib
+   The svndiff version is VERSION. COMPRESSION_LEVEL is the
    compression level to use.
    Returned values will be allocated in POOL or refer to *WINDOW
    fields. */
@@ -195,21 +198,39 @@ encode_window(svn_stringbuf_t **instruct
   append_encoded_int(header, window->sview_offset);
   append_encoded_int(header, window->sview_len);
   append_encoded_int(header, window->tview_len);
-  if (version == 1)
+  if (version == 2)
     {
       svn_stringbuf_t *compressed_instructions;
       compressed_instructions = svn_stringbuf_create_empty(pool);
-      SVN_ERR(svn__compress(instructions->data, instructions->len,
-                            compressed_instructions, compression_level));
+      SVN_ERR(svn__compress_lz4(instructions->data, instructions->len,
+                                compressed_instructions));
+      instructions = compressed_instructions;
+    }
+  else if (version == 1)
+    {
+      svn_stringbuf_t *compressed_instructions;
+      compressed_instructions = svn_stringbuf_create_empty(pool);
+      SVN_ERR(svn__compress_zlib(instructions->data, instructions->len,
+                                 compressed_instructions, compression_level));
       instructions = compressed_instructions;
     }
   append_encoded_int(header, instructions->len);
-  if (version == 1)
+
+  /* Encode the data. */
+  if (version == 2)
+    {
+      svn_stringbuf_t *compressed = svn_stringbuf_create_empty(pool);
+
+      SVN_ERR(svn__compress_lz4(window->new_data->data, window->new_data->len,
+                                compressed));
+      newdata = svn_stringbuf__morph_into_string(compressed);
+    }
+  else if (version == 1)
     {
       svn_stringbuf_t *compressed = svn_stringbuf_create_empty(pool);
 
-      SVN_ERR(svn__compress(window->new_data->data, window->new_data->len,
-                            compressed, compression_level));
+      SVN_ERR(svn__compress_zlib(window->new_data->data, window->new_data->len,
+                                 compressed, compression_level));
       newdata = svn_stringbuf__morph_into_string(compressed);
     }
   else
@@ -224,6 +245,8 @@ encode_window(svn_stringbuf_t **instruct
   return SVN_NO_ERROR;
 }
 
+/* Note: When changing things here, check the related comment in
+   the svn_txdelta_to_svndiff_stream() function.  */
 static svn_error_t *
 window_handler(svn_txdelta_window_t *window, void *baton)
 {
@@ -542,15 +565,31 @@ decode_window(svn_txdelta_window_t *wind
 
   insend = data + inslen;
 
-  if (version == 1)
+  if (version == 2)
+    {
+      svn_stringbuf_t *instout = svn_stringbuf_create_empty(pool);
+      svn_stringbuf_t *ndout = svn_stringbuf_create_empty(pool);
+
+      SVN_ERR(svn__decompress_lz4(insend, newlen, ndout,
+                                  SVN_DELTA_WINDOW_SIZE));
+      SVN_ERR(svn__decompress_lz4(data, insend - data, instout,
+                                  MAX_INSTRUCTION_SECTION_LEN));
+
+      newlen = ndout->len;
+      data = (unsigned char *)instout->data;
+      insend = (unsigned char *)instout->data + instout->len;
+
+      new_data = svn_stringbuf__morph_into_string(ndout);
+    }
+  else if (version == 1)
     {
       svn_stringbuf_t *instout = svn_stringbuf_create_empty(pool);
       svn_stringbuf_t *ndout = svn_stringbuf_create_empty(pool);
 
-      SVN_ERR(svn__decompress(insend, newlen, ndout,
-                              SVN_DELTA_WINDOW_SIZE));
-      SVN_ERR(svn__decompress(data, insend - data, instout,
-                              MAX_INSTRUCTION_SECTION_LEN));
+      SVN_ERR(svn__decompress_zlib(insend, newlen, ndout,
+                                   SVN_DELTA_WINDOW_SIZE));
+      SVN_ERR(svn__decompress_zlib(data, insend - data, instout,
+                                   MAX_INSTRUCTION_SECTION_LEN));
 
       newlen = ndout->len;
       data = (unsigned char *)instout->data;
@@ -612,6 +651,8 @@ write_handler(void *baton,
         db->version = 0;
       else if (memcmp(buffer, SVNDIFF_V1 + db->header_bytes, nheader) == 0)
         db->version = 1;
+      else if (memcmp(buffer, SVNDIFF_V2 + db->header_bytes, nheader) == 0)
+        db->version = 2;
       else
         return svn_error_create(SVN_ERR_SVNDIFF_INVALID_HEADER, NULL,
                                 _("Svndiff has invalid header"));
@@ -954,3 +995,107 @@ svn_txdelta__read_raw_window_len(apr_siz
   return SVN_NO_ERROR;
 }
 
+typedef struct svndiff_stream_baton_t
+{
+  apr_pool_t *scratch_pool;
+  svn_txdelta_stream_t *txstream;
+  svn_txdelta_window_handler_t handler;
+  void *handler_baton;
+  svn_stringbuf_t *window_buffer;
+  apr_size_t read_pos;
+  svn_boolean_t hit_eof;
+} svndiff_stream_baton_t;
+
+static svn_error_t *
+svndiff_stream_write_fn(void *baton, const char *data, apr_size_t *len)
+{
+  svndiff_stream_baton_t *b = baton;
+
+  /* The memory usage here is limited, as this buffer doesn't grow
+     beyond the (header size + max window size in svndiff format).
+     See the comment in svn_txdelta_to_svndiff_stream().  */
+  svn_stringbuf_appendbytes(b->window_buffer, data, *len);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+svndiff_stream_read_fn(void *baton, char *buffer, apr_size_t *len)
+{
+  svndiff_stream_baton_t *b = baton;
+  apr_size_t left = *len;
+  apr_size_t read = 0;
+
+  while (left)
+    {
+      apr_size_t chunk_size;
+
+      if (b->read_pos == b->window_buffer->len && !b->hit_eof)
+        {
+          svn_txdelta_window_t *window;
+
+          svn_pool_clear(b->scratch_pool);
+          svn_stringbuf_setempty(b->window_buffer);
+          SVN_ERR(svn_txdelta_next_window(&window, b->txstream,
+                                          b->scratch_pool));
+          SVN_ERR(b->handler(window, b->handler_baton));
+          b->read_pos = 0;
+
+          if (!window)
+            b->hit_eof = TRUE;
+        }
+
+      if (left > b->window_buffer->len - b->read_pos)
+        chunk_size = b->window_buffer->len - b->read_pos;
+      else
+        chunk_size = left;
+
+      if (!chunk_size)
+          break;
+
+      memcpy(buffer, b->window_buffer->data + b->read_pos, chunk_size);
+      b->read_pos += chunk_size;
+      buffer += chunk_size;
+      read += chunk_size;
+      left -= chunk_size;
+    }
+
+  *len = read;
+  return SVN_NO_ERROR;
+}
+
+svn_stream_t *
+svn_txdelta_to_svndiff_stream(svn_txdelta_stream_t *txstream,
+                              int svndiff_version,
+                              int compression_level,
+                              apr_pool_t *pool)
+{
+  svndiff_stream_baton_t *baton;
+  svn_stream_t *push_stream;
+  svn_stream_t *pull_stream;
+
+  baton = apr_pcalloc(pool, sizeof(*baton));
+  baton->scratch_pool = svn_pool_create(pool);
+  baton->txstream = txstream;
+  baton->window_buffer = svn_stringbuf_create_empty(pool);
+  baton->hit_eof = FALSE;
+  baton->read_pos = 0;
+
+  push_stream = svn_stream_create(baton, pool);
+  svn_stream_set_write(push_stream, svndiff_stream_write_fn);
+
+  /* We rely on the implementation detail of the svn_txdelta_to_svndiff3()
+     function, namely, on how the window_handler() function behaves.
+     As long as it writes one svndiff window at a time to the target
+     stream, the memory usage of this function (in other words, how
+     much data can be accumulated in the internal 'window_buffer')
+     is limited.  */
+  svn_txdelta_to_svndiff3(&baton->handler, &baton->handler_baton,
+                          push_stream, svndiff_version,
+                          compression_level, pool);
+
+  pull_stream = svn_stream_create(baton, pool);
+  svn_stream_set_read2(pull_stream, NULL, svndiff_stream_read_fn);
+
+  return pull_stream;
+}

Modified: subversion/branches/ra-git/subversion/libsvn_delta/text_delta.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_delta/text_delta.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_delta/text_delta.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_delta/text_delta.c Wed Nov  7 12:30:06 2018
@@ -102,7 +102,7 @@ struct apply_baton {
   char *tbuf;                   /* Target buffer */
   apr_size_t tbuf_size;         /* Allocated target buffer space */
 
-  apr_md5_ctx_t md5_context;    /* Leads to result_digest below. */
+  svn_checksum_ctx_t *md5_context; /* Leads to result_digest below. */
   unsigned char *result_digest; /* MD5 digest of resultant fulltext;
                                    must point to at least APR_MD5_DIGESTSIZE
                                    bytes of storage. */
@@ -720,15 +720,23 @@ apply_window(svn_txdelta_window_t *windo
 {
   struct apply_baton *ab = (struct apply_baton *) baton;
   apr_size_t len;
-  svn_error_t *err;
 
   if (window == NULL)
     {
+      svn_error_t *err = SVN_NO_ERROR;
+
       /* We're done; just clean up.  */
       if (ab->result_digest)
-        apr_md5_final(ab->result_digest, &(ab->md5_context));
+        {
+          svn_checksum_t *md5_checksum;
+
+          err = svn_checksum_final(&md5_checksum, ab->md5_context, ab->pool);
+          if (!err)
+            memcpy(ab->result_digest, md5_checksum->digest,
+                   svn_checksum_size(md5_checksum));
+        }
 
-      err = svn_stream_close(ab->target);
+      err = svn_error_compose_create(err, svn_stream_close(ab->target));
       svn_pool_destroy(ab->pool);
 
       return err;
@@ -772,12 +780,10 @@ apply_window(svn_txdelta_window_t *windo
   if (ab->sbuf_len < window->sview_len)
     {
       len = window->sview_len - ab->sbuf_len;
-      err = svn_stream_read_full(ab->source, ab->sbuf + ab->sbuf_len, &len);
-      if (err == SVN_NO_ERROR && len != window->sview_len - ab->sbuf_len)
-        err = svn_error_create(SVN_ERR_INCOMPLETE_DATA, NULL,
-                               "Delta source ended unexpectedly");
-      if (err != SVN_NO_ERROR)
-        return err;
+      SVN_ERR(svn_stream_read_full(ab->source, ab->sbuf + ab->sbuf_len, &len));
+      if (len != window->sview_len - ab->sbuf_len)
+        return svn_error_create(SVN_ERR_INCOMPLETE_DATA, NULL,
+                                "Delta source ended unexpectedly");
       ab->sbuf_len = window->sview_len;
     }
 
@@ -791,7 +797,7 @@ apply_window(svn_txdelta_window_t *windo
 
   /* Just update the context here. */
   if (ab->result_digest)
-    apr_md5_update(&(ab->md5_context), ab->tbuf, len);
+    SVN_ERR(svn_checksum_update(ab->md5_context, ab->tbuf, len));
 
   return svn_stream_write(ab->target, ab->tbuf, &len);
 }
@@ -822,7 +828,7 @@ svn_txdelta_apply(svn_stream_t *source,
   ab->result_digest = result_digest;
 
   if (result_digest)
-    apr_md5_init(&(ab->md5_context));
+    ab->md5_context = svn_checksum_ctx_create(svn_checksum_md5, subpool);
 
   if (error_info)
     ab->error_info = apr_pstrdup(subpool, error_info);

Modified: subversion/branches/ra-git/subversion/libsvn_diff/diff3.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_diff/diff3.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_diff/diff3.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_diff/diff3.c Wed Nov  7 12:30:06 2018
@@ -325,7 +325,6 @@ svn_diff_diff3_2(svn_diff_t **diff,
   /* Produce a merged diff */
   {
     svn_diff_t **diff_ref = diff;
-    svn_diff_t *diff_last = NULL;
 
     apr_off_t original_start = 1;
     apr_off_t modified_start = 1;
@@ -435,7 +434,6 @@ svn_diff_diff3_2(svn_diff_t **diff,
 
         if (is_modified || is_latest)
           {
-            svn_boolean_t add_diff = TRUE;
             modified_length = modified_sync - modified_start;
             latest_length = latest_sync - latest_start;
 
@@ -456,41 +454,17 @@ svn_diff_diff3_2(svn_diff_t **diff,
                                            &position_list[2],
                                            num_tokens,
                                            pool);
-                /* add_diff = TRUE */
               }
-            else if (is_modified
-                     && (!diff_last
-                         || diff_last->type != svn_diff__type_diff_latest))
+            else if (is_modified)
               {
                 (*diff_ref)->type = svn_diff__type_diff_modified;
-                /* add_diff = TRUE */
-              }
-            else if (is_latest
-                     && (!diff_last
-                         || diff_last->type != svn_diff__type_diff_modified))
-              {
-                (*diff_ref)->type = svn_diff__type_diff_latest;
-                /* add_diff = TRUE */
               }
             else
               {
-                /* We have a latest and a modified region that touch each other,
-                   but not directly change the same location. Create a single
-                   conflict region to properly mark a conflict, and to ease
-                   resolving. */
-                diff_last->type = svn_diff__type_conflict;
-                diff_last->original_length += (*diff_ref)->original_length;
-                diff_last->modified_length += (*diff_ref)->modified_length;
-                diff_last->latest_length += (*diff_ref)->latest_length;
-
-                add_diff = FALSE;
+                (*diff_ref)->type = svn_diff__type_diff_latest;
               }
 
-            if (add_diff)
-              {
-                diff_last = *diff_ref;
-                diff_ref = &(*diff_ref)->next;
-              }
+            diff_ref = &(*diff_ref)->next;
           }
 
         /* Detect EOF */
@@ -516,7 +490,6 @@ svn_diff_diff3_2(svn_diff_t **diff,
             (*diff_ref)->latest_length = common_length;
             (*diff_ref)->resolved_diff = NULL;
 
-            diff_last = *diff_ref;
             diff_ref = &(*diff_ref)->next;
           }
 

Modified: subversion/branches/ra-git/subversion/libsvn_diff/diff_tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_diff/diff_tree.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_diff/diff_tree.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_diff/diff_tree.c Wed Nov  7 12:30:06 2018
@@ -37,14 +37,6 @@
 #include "private/svn_diff_tree.h"
 #include "svn_private_config.h"
 
-typedef struct tree_processor_t
-{
-  svn_diff_tree_processor_t tp;
-
-  /* void *future_extension */
-} tree_processor_t;
-
-
 static svn_error_t *
 default_dir_opened(void **new_dir_baton,
                    svn_boolean_t *skip,
@@ -215,33 +207,30 @@ svn_diff_tree_processor_t *
 svn_diff__tree_processor_create(void *baton,
                                 apr_pool_t *result_pool)
 {
-  tree_processor_t *wrapper;
-  wrapper = apr_pcalloc(result_pool, sizeof(*wrapper));
+  svn_diff_tree_processor_t *tp = apr_pcalloc(result_pool, sizeof(*tp));
 
-  wrapper->tp.baton        = baton;
+  tp->baton        = baton;
 
-  wrapper->tp.dir_opened   = default_dir_opened;
-  wrapper->tp.dir_added    = default_dir_added;
-  wrapper->tp.dir_deleted  = default_dir_deleted;
-  wrapper->tp.dir_changed  = default_dir_changed;
-  wrapper->tp.dir_closed   = default_dir_closed;
+  tp->dir_opened   = default_dir_opened;
+  tp->dir_added    = default_dir_added;
+  tp->dir_deleted  = default_dir_deleted;
+  tp->dir_changed  = default_dir_changed;
+  tp->dir_closed   = default_dir_closed;
 
-  wrapper->tp.file_opened   = default_file_opened;
-  wrapper->tp.file_added    = default_file_added;
-  wrapper->tp.file_deleted  = default_file_deleted;
-  wrapper->tp.file_changed  = default_file_changed;
-  wrapper->tp.file_closed   = default_file_closed;
+  tp->file_opened  = default_file_opened;
+  tp->file_added   = default_file_added;
+  tp->file_deleted = default_file_deleted;
+  tp->file_changed = default_file_changed;
+  tp->file_closed  = default_file_closed;
 
-  wrapper->tp.node_absent   = default_node_absent;
+  tp->node_absent  = default_node_absent;
 
-
-  return &wrapper->tp;
+  return tp;
 }
 
 struct reverse_tree_baton_t
 {
   const svn_diff_tree_processor_t *processor;
-  const char *prefix_relpath;
 };
 
 static svn_error_t *
@@ -259,9 +248,6 @@ reverse_dir_opened(void **new_dir_baton,
 {
   struct reverse_tree_baton_t *rb = processor->baton;
 
-  if (rb->prefix_relpath)
-    relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool);
-
   SVN_ERR(rb->processor->dir_opened(new_dir_baton, skip, skip_children,
                                     relpath,
                                     right_source, left_source,
@@ -284,9 +270,6 @@ reverse_dir_added(const char *relpath,
 {
   struct reverse_tree_baton_t *rb = processor->baton;
 
-  if (rb->prefix_relpath)
-    relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool);
-
   SVN_ERR(rb->processor->dir_deleted(relpath,
                                      right_source,
                                      right_props,
@@ -307,9 +290,6 @@ reverse_dir_deleted(const char *relpath,
 {
   struct reverse_tree_baton_t *rb = processor->baton;
 
-  if (rb->prefix_relpath)
-    relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool);
-
   SVN_ERR(rb->processor->dir_added(relpath,
                                    NULL,
                                    left_source,
@@ -335,9 +315,6 @@ reverse_dir_changed(const char *relpath,
   struct reverse_tree_baton_t *rb = processor->baton;
   apr_array_header_t *reversed_prop_changes = NULL;
 
-  if (rb->prefix_relpath)
-    relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool);
-
   if (prop_changes)
     {
       SVN_ERR_ASSERT(left_props != NULL && right_props != NULL);
@@ -367,9 +344,6 @@ reverse_dir_closed(const char *relpath,
 {
   struct reverse_tree_baton_t *rb = processor->baton;
 
-  if (rb->prefix_relpath)
-    relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool);
-
   SVN_ERR(rb->processor->dir_closed(relpath,
                                     right_source,
                                     left_source,
@@ -393,9 +367,6 @@ reverse_file_opened(void **new_file_bato
 {
   struct reverse_tree_baton_t *rb = processor->baton;
 
-  if (rb->prefix_relpath)
-    relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool);
-
   SVN_ERR(rb->processor->file_opened(new_file_baton,
                                      skip,
                                      relpath,
@@ -423,9 +394,6 @@ reverse_file_added(const char *relpath,
 {
   struct reverse_tree_baton_t *rb = processor->baton;
 
-  if (rb->prefix_relpath)
-    relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool);
-
   SVN_ERR(rb->processor->file_deleted(relpath,
                                       right_source,
                                       right_file,
@@ -447,9 +415,6 @@ reverse_file_deleted(const char *relpath
 {
   struct reverse_tree_baton_t *rb = processor->baton;
 
-  if (rb->prefix_relpath)
-    relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool);
-
   SVN_ERR(rb->processor->file_added(relpath,
                                     NULL /* copyfrom src */,
                                     left_source,
@@ -480,9 +445,6 @@ reverse_file_changed(const char *relpath
   struct reverse_tree_baton_t *rb = processor->baton;
   apr_array_header_t *reversed_prop_changes = NULL;
 
-  if (rb->prefix_relpath)
-    relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool);
-
   if (prop_changes)
     {
       SVN_ERR_ASSERT(left_props != NULL && right_props != NULL);
@@ -515,9 +477,6 @@ reverse_file_closed(const char *relpath,
 {
   struct reverse_tree_baton_t *rb = processor->baton;
 
-  if (rb->prefix_relpath)
-    relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool);
-
   SVN_ERR(rb->processor->file_closed(relpath,
                                      right_source,
                                      left_source,
@@ -536,9 +495,6 @@ reverse_node_absent(const char *relpath,
 {
   struct reverse_tree_baton_t *rb = processor->baton;
 
-  if (rb->prefix_relpath)
-    relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool);
-
   SVN_ERR(rb->processor->node_absent(relpath,
                                     dir_baton,
                                     rb->processor,
@@ -549,7 +505,6 @@ reverse_node_absent(const char *relpath,
 
 const svn_diff_tree_processor_t *
 svn_diff__tree_processor_reverse_create(const svn_diff_tree_processor_t * processor,
-                                        const char *prefix_relpath,
                                         apr_pool_t *result_pool)
 {
   struct reverse_tree_baton_t *rb;
@@ -557,8 +512,6 @@ svn_diff__tree_processor_reverse_create(
 
   rb = apr_pcalloc(result_pool, sizeof(*rb));
   rb->processor = processor;
-  if (prefix_relpath)
-    rb->prefix_relpath = apr_pstrdup(result_pool, prefix_relpath);
 
   reverse = svn_diff__tree_processor_create(rb, result_pool);
 

Modified: subversion/branches/ra-git/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_diff/parse-diff.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_diff/parse-diff.c Wed Nov  7 12:30:06 2018
@@ -69,6 +69,11 @@ struct svn_diff_hunk_t {
   /* APR file handle to the patch file this hunk came from. */
   apr_file_t *apr_file;
 
+  /* Whether the hunk was interpreted as pretty-print mergeinfo. If so,
+     the hunk content is in PATCH and the rest of this hunk object is
+     mostly uninitialized. */
+  svn_boolean_t is_pretty_print_mergeinfo;
+
   /* Ranges used to keep track of this hunk's texts positions within
    * the patch file. */
   struct svn_diff__hunk_range diff_text_range;
@@ -899,10 +904,6 @@ parse_prop_name(const char **prop_name,
  * The hunk header has the following format:
  * ## -0,NUMBER_OF_REVERSE_MERGES +0,NUMBER_OF_FORWARD_MERGES ##
  *
- * At this point, the number of reverse merges has already been
- * parsed into HUNK->ORIGINAL_LENGTH, and the number of forward
- * merges has been parsed into HUNK->MODIFIED_LENGTH.
- *
  * The header is followed by a list of mergeinfo, one path per line.
  * This function parses such lines. Lines describing reverse merges
  * appear first, and then all lines describing forward merges appear.
@@ -914,18 +915,27 @@ parse_prop_name(const char **prop_name,
  * ":r", which in turn is followed by a mergeinfo revision range,
  *  which is terminated by whitespace or end-of-string.
  *
- * If the current line meets the above criteria and we're able
- * to parse valid mergeinfo from it, the resulting mergeinfo
- * is added to patch->mergeinfo or patch->reverse_mergeinfo,
- * and we proceed to the next line.
+ * *NUMBER_OF_REVERSE_MERGES and *NUMBER_OF_FORWARD_MERGES are the
+ * numbers of reverse and forward merges remaining to be read. This
+ * function decrements *NUMBER_OF_REVERSE_MERGES for each LINE
+ * parsed until that is zero, then *NUMBER_OF_FORWARD_MERGES for
+ * each LINE parsed until that is zero. If both are zero, it parses
+ * and discards LINE.
+ *
+ * If LINE is successfully parsed, *FOUND_MERGEINFO is set to TRUE,
+ * otherwise to FALSE.
+ *
+ * If LINE is successfully parsed and counted, the resulting mergeinfo
+ * is added to PATCH->mergeinfo or PATCH->reverse_mergeinfo.
  */
 static svn_error_t *
-parse_mergeinfo(svn_boolean_t *found_mergeinfo,
-                svn_stringbuf_t *line,
-                svn_diff_hunk_t *hunk,
-                svn_patch_t *patch,
-                apr_pool_t *result_pool,
-                apr_pool_t *scratch_pool)
+parse_pretty_mergeinfo_line(svn_boolean_t *found_mergeinfo,
+                            svn_linenum_t *number_of_reverse_merges,
+                            svn_linenum_t *number_of_forward_merges,
+                            svn_stringbuf_t *line,
+                            svn_patch_t *patch,
+                            apr_pool_t *result_pool,
+                            apr_pool_t *scratch_pool)
 {
   char *slash = strchr(line->data, '/');
   char *colon = strrchr(line->data, ':');
@@ -972,7 +982,7 @@ parse_mergeinfo(svn_boolean_t *found_mer
 
       if (mergeinfo)
         {
-          if (hunk->original_length > 0) /* reverse merges */
+          if (*number_of_reverse_merges > 0) /* reverse merges */
             {
               if (patch->reverse)
                 {
@@ -994,9 +1004,9 @@ parse_mergeinfo(svn_boolean_t *found_mer
                                                  result_pool,
                                                  scratch_pool));
                 }
-              hunk->original_length--;
+              (*number_of_reverse_merges)--;
             }
-          else if (hunk->modified_length > 0) /* forward merges */
+          else if (number_of_forward_merges > 0) /* forward merges */
             {
               if (patch->reverse)
                 {
@@ -1018,7 +1028,7 @@ parse_mergeinfo(svn_boolean_t *found_mer
                                                  result_pool,
                                                  scratch_pool));
                 }
-              hunk->modified_length--;
+              (*number_of_forward_merges)--;
             }
 
           *found_mergeinfo = TRUE;
@@ -1165,18 +1175,48 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
       if (in_hunk && *is_property && *prop_name &&
           strcmp(*prop_name, SVN_PROP_MERGEINFO) == 0)
         {
-          svn_boolean_t found_mergeinfo;
+          svn_boolean_t found_pretty_mergeinfo_line;
 
-          SVN_ERR(parse_mergeinfo(&found_mergeinfo, line, *hunk, patch,
-                                  result_pool, iterpool));
-          if (found_mergeinfo)
-            continue; /* Proceed to the next line in the svn:mergeinfo hunk. */
-          else
+          if (! hunk_seen)
+            {
+              /* We're reading the first line of the hunk, so the start
+               * of the line just read is the hunk text's byte offset. */
+              start = last_line;
+            }
+
+          SVN_ERR(parse_pretty_mergeinfo_line(&found_pretty_mergeinfo_line,
+                                              &original_lines, &modified_lines,
+                                              line, patch,
+                                              result_pool, iterpool));
+          if (found_pretty_mergeinfo_line)
             {
-              /* Perhaps we can also use original_lines/modified_lines here */
+              hunk_seen = TRUE;
+              (*hunk)->is_pretty_print_mergeinfo = TRUE;
+              continue; /* Proceed to the next line in the svn:mergeinfo hunk. */
+            }
 
-              in_hunk = FALSE; /* On to next property */
+          if ((*hunk)->is_pretty_print_mergeinfo)
+            {
+              /* We have reached the end of the pretty-print-mergeinfo hunk.
+                 (This format uses only one hunk.) */
+              if (eof)
+                {
+                  /* The hunk ends at EOF. */
+                  end = pos;
+                }
+              else
+                {
+                  /* The start of the current line marks the first byte
+                   * after the hunk text. */
+                  end = last_line;
+                }
+              original_end = end;
+              modified_end = end;
+              break;
             }
+
+          /* Otherwise, this is a property diff in the
+             regular format so fall through to normal processing. */
         }
 
       if (in_hunk)
@@ -1971,10 +2011,10 @@ parse_hunks(svn_patch_t *patch, apr_file
           else
             last_prop_name = prop_name;
 
-          /* Skip svn:mergeinfo properties.
-           * Mergeinfo data cannot be represented as a hunk and
+          /* Skip pretty-printed svn:mergeinfo property hunks.
+           * Pretty-printed mergeinfo data cannot be represented as a hunk and
            * is therefore stored in PATCH itself. */
-          if (strcmp(prop_name, SVN_PROP_MERGEINFO) == 0)
+          if (hunk->is_pretty_print_mergeinfo)
             continue;
 
           SVN_ERR(add_property_hunk(patch, prop_name, hunk, prop_operation,

Modified: subversion/branches/ra-git/subversion/libsvn_fs/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs/deprecated.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_fs/deprecated.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_fs/deprecated.c Wed Nov  7 12:30:06 2018
@@ -28,6 +28,7 @@
 
 #include <apr_md5.h>
 #include "svn_fs.h"
+#include "private/svn_subr_private.h"
 
 
 /*** From fs-loader.c ***/
@@ -130,6 +131,45 @@ svn_fs_node_history(svn_fs_history_t **h
                                               pool, pool));
 }
 
+static svn_error_t *
+mergeinfo_receiver(const char *path,
+                   svn_mergeinfo_t mergeinfo,
+                   void *baton,
+                   apr_pool_t *scratch_pool)
+{
+  svn_mergeinfo_catalog_t catalog = baton;
+  apr_pool_t *result_pool = apr_hash_pool_get(catalog);
+  apr_size_t len = strlen(path);
+
+  apr_hash_set(catalog,
+               apr_pstrmemdup(result_pool, path, len),
+               len,
+               svn_mergeinfo_dup(mergeinfo, result_pool));
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_get_mergeinfo2(svn_mergeinfo_catalog_t *catalog,
+                      svn_fs_root_t *root,
+                      const apr_array_header_t *paths,
+                      svn_mergeinfo_inheritance_t inherit,
+                      svn_boolean_t include_descendants,
+                      svn_boolean_t adjust_inherited_mergeinfo,
+                      apr_pool_t *result_pool,
+                      apr_pool_t *scratch_pool)
+{
+  svn_mergeinfo_catalog_t result_catalog = svn_hash__make(result_pool);
+  SVN_ERR(svn_fs_get_mergeinfo3(root, paths, inherit,
+                                include_descendants,
+                                adjust_inherited_mergeinfo,
+                                mergeinfo_receiver, result_catalog,
+                                scratch_pool));
+  *catalog = result_catalog;
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_fs_get_mergeinfo(svn_mergeinfo_catalog_t *catalog,
                      svn_fs_root_t *root,

Modified: subversion/branches/ra-git/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs/fs-loader.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_fs/fs-loader.c Wed Nov  7 12:30:06 2018
@@ -89,7 +89,7 @@ struct fs_type_defn {
   const char *fs_type;
   const char *fsap_name;
   fs_init_func_t initfunc;
-  fs_library_vtable_t *vtable;
+  void * volatile vtable; /* fs_library_vtable_t */
   struct fs_type_defn *next;
 };
 
@@ -202,7 +202,7 @@ get_library_vtable_direct(fs_library_vta
   const svn_version_t *fs_version;
 
   /* most times, we get lucky */
-  *vtable = apr_atomic_casptr((volatile void **)&fst->vtable, NULL, NULL);
+  *vtable = svn_atomic_casptr(&fst->vtable, NULL, NULL);
   if (*vtable)
     return SVN_NO_ERROR;
 
@@ -245,7 +245,7 @@ get_library_vtable_direct(fs_library_vta
                              fs_version->patch, fs_version->tag);
 
   /* the vtable will not change.  Remember it */
-  apr_atomic_casptr((volatile void **)&fst->vtable, *vtable, NULL);
+  svn_atomic_casptr(&fst->vtable, *vtable, NULL);
 
   return SVN_NO_ERROR;
 }
@@ -1391,18 +1391,38 @@ svn_fs_closest_copy(svn_fs_root_t **root
 }
 
 svn_error_t *
-svn_fs_get_mergeinfo2(svn_mergeinfo_catalog_t *catalog,
-                      svn_fs_root_t *root,
+svn_fs_get_mergeinfo3(svn_fs_root_t *root,
                       const apr_array_header_t *paths,
                       svn_mergeinfo_inheritance_t inherit,
                       svn_boolean_t include_descendants,
                       svn_boolean_t adjust_inherited_mergeinfo,
-                      apr_pool_t *result_pool,
+                      svn_fs_mergeinfo_receiver_t receiver,
+                      void *baton,
                       apr_pool_t *scratch_pool)
 {
   return svn_error_trace(root->vtable->get_mergeinfo(
-    catalog, root, paths, inherit, include_descendants,
-    adjust_inherited_mergeinfo, result_pool, scratch_pool));
+    root, paths, inherit, include_descendants, adjust_inherited_mergeinfo,
+    receiver, baton, scratch_pool));
+}
+
+/* Baton type to be used with mergeinfo_receiver().  It provides some of
+ * the parameters passed to svn_fs__get_mergeinfo_for_path. */
+typedef struct mergeinfo_receiver_baton_t
+{
+  svn_mergeinfo_t *mergeinfo;
+  apr_pool_t *result_pool;
+} mergeinfo_receiver_baton_t;
+
+static svn_error_t *
+mergeinfo_receiver(const char *path,
+                   svn_mergeinfo_t mergeinfo,
+                   void *baton,
+                   apr_pool_t *scratch_pool)
+{
+  mergeinfo_receiver_baton_t *b = baton;
+  *b->mergeinfo = svn_mergeinfo_dup(mergeinfo, b->result_pool);
+
+  return SVN_NO_ERROR;
 }
 
 svn_error_t *
@@ -1416,15 +1436,19 @@ svn_fs__get_mergeinfo_for_path(svn_merge
 {
   apr_array_header_t *paths
     = apr_array_make(scratch_pool, 1, sizeof(const char *));
-  svn_mergeinfo_catalog_t catalog;
+
+  mergeinfo_receiver_baton_t baton;
+  baton.mergeinfo = mergeinfo;
+  baton.result_pool = result_pool;
 
   APR_ARRAY_PUSH(paths, const char *) = path;
 
-  SVN_ERR(svn_fs_get_mergeinfo2(&catalog, root, paths,
+  *mergeinfo = NULL;
+  SVN_ERR(svn_fs_get_mergeinfo3(root, paths,
                                 inherit, FALSE /*include_descendants*/,
                                 adjust_inherited_mergeinfo,
-                                result_pool, scratch_pool));
-  *mergeinfo = svn_hash_gets(catalog, path);
+                                mergeinfo_receiver, &baton,
+                                scratch_pool));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/ra-git/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs/fs-loader.h?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/ra-git/subversion/libsvn_fs/fs-loader.h Wed Nov  7 12:30:06 2018
@@ -420,13 +420,13 @@ typedef struct root_vtable_t
                         const char *ancestor_path,
                         apr_pool_t *pool);
   /* Mergeinfo. */
-  svn_error_t *(*get_mergeinfo)(svn_mergeinfo_catalog_t *catalog,
-                                svn_fs_root_t *root,
+  svn_error_t *(*get_mergeinfo)(svn_fs_root_t *root,
                                 const apr_array_header_t *paths,
                                 svn_mergeinfo_inheritance_t inherit,
                                 svn_boolean_t include_descendants,
                                 svn_boolean_t adjust_inherited_mergeinfo,
-                                apr_pool_t *result_pool,
+                                svn_fs_mergeinfo_receiver_t receiver,
+                                void *baton,
                                 apr_pool_t *scratch_pool);
 } root_vtable_t;
 

Modified: subversion/branches/ra-git/subversion/libsvn_fs_base/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_base/fs.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_fs_base/fs.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_fs_base/fs.c Wed Nov  7 12:30:06 2018
@@ -957,6 +957,7 @@ base_upgrade(svn_fs_t *fs,
       err = SVN_NO_ERROR;
     }
   SVN_ERR(err);
+  SVN_ERR(check_format(old_format_number));
 
   /* Bump the format file's stored version number. */
   SVN_ERR(svn_io_write_version_file(version_file_path,

Modified: subversion/branches/ra-git/subversion/libsvn_fs_base/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_base/tree.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_fs_base/tree.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_fs_base/tree.c Wed Nov  7 12:30:06 2018
@@ -5074,8 +5074,8 @@ base_node_origin_rev(svn_revnum_t *revis
 
 /* Examine directory NODE's immediately children for mergeinfo.
 
-   For those which have explicit mergeinfo, add their mergeinfo to
-   RESULT_CATALOG (allocated in RESULT_CATALOG's pool).
+   For those which have explicit mergeinfo, invoke RECEIVER with
+   RECEIVER_BATON.
 
    For those which don't, but sit atop trees which contain mergeinfo
    somewhere deeper, add them to *CHILDREN_ATOP_MERGEINFO_TREES, a
@@ -5089,10 +5089,11 @@ base_node_origin_rev(svn_revnum_t *revis
 
 struct get_mergeinfo_data_and_entries_baton
 {
-  svn_mergeinfo_catalog_t result_catalog;
   apr_hash_t *children_atop_mergeinfo_trees;
   dag_node_t *node;
   const char *node_path;
+  svn_fs_mergeinfo_receiver_t receiver;
+  void *receiver_baton;
 };
 
 static svn_error_t *
@@ -5103,7 +5104,6 @@ txn_body_get_mergeinfo_data_and_entries(
   apr_hash_t *entries;
   apr_hash_index_t *hi;
   apr_pool_t *iterpool = svn_pool_create(trail->pool);
-  apr_pool_t *result_pool = apr_hash_pool_get(args->result_catalog);
   apr_pool_t *children_pool =
     apr_hash_pool_get(args->children_atop_mergeinfo_trees);
 
@@ -5157,7 +5157,7 @@ txn_body_get_mergeinfo_data_and_entries(
              CHILD_NODE then treat it as if no mergeinfo is present rather
              than raising a parse error. */
           err = svn_mergeinfo_parse(&child_mergeinfo, pval->data,
-                                    result_pool);
+                                    iterpool);
           if (err)
             {
               if (err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR)
@@ -5167,10 +5167,12 @@ txn_body_get_mergeinfo_data_and_entries(
             }
           else
             {
-              svn_hash_sets(args->result_catalog,
-                            svn_fspath__join(args->node_path, dirent->name,
-                                             result_pool),
-                            child_mergeinfo);
+              SVN_ERR(args->receiver(svn_fspath__join(args->node_path,
+                                                      dirent->name,
+                                                      iterpool),
+                                     child_mergeinfo,
+                                     args->receiver_baton,
+                                     iterpool));
             }
         }
 
@@ -5204,7 +5206,8 @@ static svn_error_t *
 crawl_directory_for_mergeinfo(svn_fs_t *fs,
                               dag_node_t *node,
                               const char *node_path,
-                              svn_mergeinfo_catalog_t result_catalog,
+                              svn_fs_mergeinfo_receiver_t receiver,
+                              void *baton,
                               apr_pool_t *pool)
 {
   struct get_mergeinfo_data_and_entries_baton gmdae_args;
@@ -5214,10 +5217,11 @@ crawl_directory_for_mergeinfo(svn_fs_t *
 
   /* Add mergeinfo for immediate children that have it, and fetch
      immediate children that *don't* have it but sit atop trees that do. */
-  gmdae_args.result_catalog = result_catalog;
   gmdae_args.children_atop_mergeinfo_trees = children_atop_mergeinfo_trees;
   gmdae_args.node = node;
   gmdae_args.node_path = node_path;
+  gmdae_args.receiver = receiver;
+  gmdae_args.receiver_baton = baton;
   SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_get_mergeinfo_data_and_entries,
                                  &gmdae_args, FALSE, pool));
 
@@ -5239,7 +5243,7 @@ crawl_directory_for_mergeinfo(svn_fs_t *
       SVN_ERR(crawl_directory_for_mergeinfo(fs, val,
                                             svn_fspath__join(node_path, key,
                                                              iterpool),
-                                            result_catalog, iterpool));
+                                            receiver, baton, iterpool));
     }
   svn_pool_destroy(iterpool);
   return SVN_NO_ERROR;
@@ -5397,20 +5401,21 @@ txn_body_get_node_mergeinfo_stats(void *
 }
 
 
-/* Get the mergeinfo for a set of paths, returned in
-   *MERGEINFO_CATALOG.  Returned values are allocated in POOL, while
-   temporary values are allocated in a sub-pool. */
+/* Find all the mergeinfo for a set of PATHS under ROOT and report it
+   through RECEIVER with BATON.  INHERITED, INCLUDE_DESCENDANTS and
+   ADJUST_INHERITED_MERGEINFO are the same as in the FS API.
+
+   Allocate temporary values are allocated in SCRATCH_POOL. */
 static svn_error_t *
 get_mergeinfos_for_paths(svn_fs_root_t *root,
-                         svn_mergeinfo_catalog_t *mergeinfo_catalog,
                          const apr_array_header_t *paths,
                          svn_mergeinfo_inheritance_t inherit,
                          svn_boolean_t include_descendants,
                          svn_boolean_t adjust_inherited_mergeinfo,
-                         apr_pool_t *result_pool,
+                         svn_fs_mergeinfo_receiver_t receiver,
+                         void *baton,
                          apr_pool_t *scratch_pool)
 {
-  svn_mergeinfo_catalog_t result_catalog = apr_hash_make(result_pool);
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
   int i;
 
@@ -5429,14 +5434,13 @@ get_mergeinfos_for_paths(svn_fs_root_t *
       gmfp_args.root = root;
       gmfp_args.path = path;
       gmfp_args.inherit = inherit;
-      gmfp_args.pool = result_pool;
+      gmfp_args.pool = iterpool;
       gmfp_args.adjust_inherited_mergeinfo = adjust_inherited_mergeinfo;
       SVN_ERR(svn_fs_base__retry_txn(root->fs,
                                      txn_body_get_mergeinfo_for_path,
                                      &gmfp_args, FALSE, iterpool));
       if (path_mergeinfo)
-        svn_hash_sets(result_catalog, apr_pstrdup(result_pool, path),
-                      path_mergeinfo);
+        SVN_ERR(receiver(path, path_mergeinfo, baton, iterpool));
 
       /* If we're including descendants, do so. */
       if (include_descendants)
@@ -5462,26 +5466,25 @@ get_mergeinfos_for_paths(svn_fs_root_t *
           /* If it's worth crawling, crawl. */
           if (do_crawl)
             SVN_ERR(crawl_directory_for_mergeinfo(root->fs, gnms_args.node,
-                                                  path, result_catalog,
+                                                  path, receiver, baton,
                                                   iterpool));
         }
     }
   svn_pool_destroy(iterpool);
 
-  *mergeinfo_catalog = result_catalog;
   return SVN_NO_ERROR;
 }
 
 
 /* Implements svn_fs_get_mergeinfo. */
 static svn_error_t *
-base_get_mergeinfo(svn_mergeinfo_catalog_t *catalog,
-                   svn_fs_root_t *root,
+base_get_mergeinfo(svn_fs_root_t *root,
                    const apr_array_header_t *paths,
                    svn_mergeinfo_inheritance_t inherit,
                    svn_boolean_t include_descendants,
                    svn_boolean_t adjust_inherited_mergeinfo,
-                   apr_pool_t *result_pool,
+                   svn_fs_mergeinfo_receiver_t receiver,
+                   void *baton,
                    apr_pool_t *scratch_pool)
 {
   /* Verify that our filesystem version supports mergeinfo stuff. */
@@ -5493,10 +5496,11 @@ base_get_mergeinfo(svn_mergeinfo_catalog
     return svn_error_create(SVN_ERR_FS_NOT_REVISION_ROOT, NULL, NULL);
 
   /* Retrieve a path -> mergeinfo mapping. */
-  return get_mergeinfos_for_paths(root, catalog, paths,
+  return get_mergeinfos_for_paths(root, paths,
                                   inherit, include_descendants,
                                   adjust_inherited_mergeinfo,
-                                  result_pool, scratch_pool);
+                                  receiver, baton,
+                                  scratch_pool);
 }
 
 

Modified: subversion/branches/ra-git/subversion/libsvn_fs_fs/cached_data.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_fs/cached_data.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_fs_fs/cached_data.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_fs_fs/cached_data.c Wed Nov  7 12:30:06 2018
@@ -866,7 +866,7 @@ create_rep_state_body(rep_state_t **rep_
   rs->size = rep->size;
   rs->revision = rep->revision;
   rs->item_index = rep->item_index;
-  rs->raw_window_cache = ffd->raw_window_cache;
+  rs->raw_window_cache = use_block_read(fs) ? ffd->raw_window_cache : NULL;
   rs->ver = -1;
   rs->start = -1;
 
@@ -1268,7 +1268,7 @@ parse_raw_window(void **out,
   stream = svn_stream_from_string(&raw_window, result_pool);
 
   /* parse it */
-  SVN_ERR(svn_txdelta_read_svndiff_window(&result->window, stream, 1,
+  SVN_ERR(svn_txdelta_read_svndiff_window(&result->window, stream, window->ver,
                                           result_pool));
 
   /* complete the window and return it */
@@ -1462,7 +1462,8 @@ build_rep_list(apr_array_header_t **list
                                  &rep, fs, pool, iterpool));
 
       /* for txn reps, there won't be a cached combined window */
-      if (!svn_fs_fs__id_txn_used(&rep.txn_id))
+      if (   !svn_fs_fs__id_txn_used(&rep.txn_id)
+          && rep.expanded_size < SVN_DELTA_WINDOW_SIZE)
         SVN_ERR(get_cached_combined_window(window_p, rs, &is_cached, pool));
 
       if (is_cached)
@@ -2058,6 +2059,16 @@ skip_contents(struct rep_read_baton *bat
           len -= to_read;
           buffer += to_read;
         }
+
+      /* Make the MD5 calculation catch up with the data delivered
+       * (we did not run MD5 on the data that we took from the cache). */
+      if (!err)
+        {
+          SVN_ERR(svn_checksum_update(baton->md5_checksum_ctx,
+                                      baton->current_fulltext->data,
+                                      baton->current_fulltext->len));
+          baton->off += baton->current_fulltext->len;
+        }
     }
   else if (len > 0)
     {
@@ -2073,6 +2084,15 @@ skip_contents(struct rep_read_baton *bat
 
           err = get_contents_from_windows(baton, buffer, &to_read);
           len -= to_read;
+
+          /* Make the MD5 calculation catch up with the data delivered
+           * (we did not run MD5 on the data that we took from the cache). */
+          if (!err)
+            {
+              SVN_ERR(svn_checksum_update(baton->md5_checksum_ctx,
+                                          buffer, to_read));
+              baton->off += to_read;
+            }
         }
 
       svn_pool_destroy(subpool);
@@ -2083,13 +2103,14 @@ skip_contents(struct rep_read_baton *bat
 
 /* BATON is of type `rep_read_baton'; read the next *LEN bytes of the
    representation and store them in *BUF.  Sum as we read and verify
-   the MD5 sum at the end. */
+   the MD5 sum at the end.  This is a READ_FULL_FN for svn_stream_t. */
 static svn_error_t *
 rep_read_contents(void *baton,
                   char *buf,
                   apr_size_t *len)
 {
   struct rep_read_baton *rb = baton;
+  apr_size_t len_requested = *len;
 
   /* Get data from the fulltext cache for as long as we can. */
   if (rb->fulltext_cache)
@@ -2119,12 +2140,39 @@ rep_read_contents(void *baton,
       SVN_ERR(skip_contents(rb, rb->fulltext_delivered));
     }
 
-  /* Get the next block of data. */
-  SVN_ERR(get_contents_from_windows(rb, buf, len));
+  /* Get the next block of data.
+   * Keep in mind that the representation might be empty and leave us
+   * already positioned at the end of the rep. */
+  if (rb->off == rb->len)
+    *len = 0;
+  else
+    SVN_ERR(get_contents_from_windows(rb, buf, len));
 
   if (rb->current_fulltext)
     svn_stringbuf_appendbytes(rb->current_fulltext, buf, *len);
 
+  /* This is a FULL_READ_FN so a short read implies EOF and we can
+     verify the length. */
+  rb->off += *len;
+  if (*len < len_requested && rb->off != rb->len)
+      {
+        /* A warning rather than an error to allow the data to be
+           retrieved when the length is wrong but the data is
+           present, i.e. if repository corruption has stored the wrong
+           expanded length. */
+        svn_error_t *err = svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+                            _("Length mismatch while reading representation:"
+                              " expected %s,"
+                              " got %s"),
+                            apr_psprintf(rb->pool, "%" SVN_FILESIZE_T_FMT,
+                                         rb->len),
+                            apr_psprintf(rb->pool, "%" SVN_FILESIZE_T_FMT,
+                                         rb->off));
+
+        rb->fs->warning(rb->fs->warning_baton, err);
+        svn_error_clear(err);
+      }
+
   /* Perform checksumming.  We want to check the checksum as soon as
      the last byte of data is read, in case the caller never performs
      a short read, but we don't want to finalize the MD5 context
@@ -2132,7 +2180,6 @@ rep_read_contents(void *baton,
   if (!rb->checksum_finalized)
     {
       SVN_ERR(svn_checksum_update(rb->md5_checksum_ctx, buf, *len));
-      rb->off += *len;
       if (rb->off == rb->len)
         {
           svn_checksum_t *md5_checksum;
@@ -2212,6 +2259,96 @@ svn_fs_fs__get_contents(svn_stream_t **c
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_fs_fs__get_contents_from_file(svn_stream_t **contents_p,
+                                  svn_fs_t *fs,
+                                  representation_t *rep,
+                                  apr_file_t *file,
+                                  apr_off_t offset,
+                                  apr_pool_t *pool)
+{
+  struct rep_read_baton *rb;
+  pair_cache_key_t fulltext_cache_key = { SVN_INVALID_REVNUM, 0 };
+  rep_state_t *rs = apr_pcalloc(pool, sizeof(*rs));
+  svn_fs_fs__rep_header_t *rh;
+
+  /* Initialize the reader baton.  Some members may added lazily
+   * while reading from the stream. */
+  SVN_ERR(rep_read_get_baton(&rb, fs, rep, fulltext_cache_key, pool));
+
+  /* Continue constructing RS. Leave caches as NULL. */
+  rs->size = rep->size;
+  rs->revision = SVN_INVALID_REVNUM;
+  rs->item_index = 0;
+  rs->ver = -1;
+  rs->start = -1;
+
+  /* Provide just enough file access info to allow for a basic read from
+   * FILE but leave all index / footer info with empty values b/c FILE
+   * probably is not a complete revision file. */
+  rs->sfile = apr_pcalloc(pool, sizeof(*rs->sfile));
+  rs->sfile->revision = rep->revision;
+  rs->sfile->pool = pool;
+  rs->sfile->fs = fs;
+  rs->sfile->rfile = apr_pcalloc(pool, sizeof(*rs->sfile->rfile));
+  rs->sfile->rfile->start_revision = SVN_INVALID_REVNUM;
+  rs->sfile->rfile->file = file;
+  rs->sfile->rfile->stream = svn_stream_from_aprfile2(file, TRUE, pool);
+
+  /* Read the rep header. */
+  SVN_ERR(aligned_seek(fs, file, NULL, offset, pool));
+  SVN_ERR(svn_fs_fs__read_rep_header(&rh, rs->sfile->rfile->stream,
+                                     pool, pool));
+  SVN_ERR(get_file_offset(&rs->start, rs, pool));
+  rs->header_size = rh->header_size;
+
+  /* Log the access. */
+  SVN_ERR(dbg_log_access(fs, SVN_INVALID_REVNUM, 0, rh,
+                         SVN_FS_FS__ITEM_TYPE_ANY_REP, pool));
+
+  /* Build the representation list (delta chain). */
+  if (rh->type == svn_fs_fs__rep_plain)
+    {
+      rb->rs_list = apr_array_make(pool, 0, sizeof(rep_state_t *));
+      rb->src_state = rs;
+    }
+  else if (rh->type == svn_fs_fs__rep_self_delta)
+    {
+      rb->rs_list = apr_array_make(pool, 1, sizeof(rep_state_t *));
+      APR_ARRAY_PUSH(rb->rs_list, rep_state_t *) = rs;
+      rb->src_state = NULL;
+    }
+  else
+    {
+      representation_t next_rep = { 0 };
+
+      /* skip "SVNx" diff marker */
+      rs->current = 4;
+
+      /* REP's base rep is inside a proper revision.
+       * It can be reconstructed in the usual way.  */
+      next_rep.revision = rh->base_revision;
+      next_rep.item_index = rh->base_item_index;
+      next_rep.size = rh->base_length;
+      svn_fs_fs__id_txn_reset(&next_rep.txn_id);
+
+      SVN_ERR(build_rep_list(&rb->rs_list, &rb->base_window,
+                             &rb->src_state, rb->fs, &next_rep,
+                             rb->filehandle_pool));
+
+      /* Insert the access to REP as the first element of the delta chain. */
+      svn_sort__array_insert(rb->rs_list, &rs, 0);
+    }
+
+  /* Now, the baton is complete and we can assemble the stream around it. */
+  *contents_p = svn_stream_create(rb, pool);
+  svn_stream_set_read2(*contents_p, NULL /* only full read support */,
+                       rep_read_contents);
+  svn_stream_set_close(*contents_p, rep_read_contents_close);
+
+  return SVN_NO_ERROR;
+}
+
 /* Baton for cache_access_wrapper. Wraps the original parameters of
  * svn_fs_fs__try_process_file_content().
  */
@@ -3091,7 +3228,7 @@ init_rep_state(rep_state_t *rs,
   rs->start = entry->offset + rs->header_size;
   rs->current = rep_header->type == svn_fs_fs__rep_plain ? 0 : 4;
   rs->size = entry->size - rep_header->header_size - 7;
-  rs->ver = 1;
+  rs->ver = -1;
   rs->chunk_index = 0;
   rs->raw_window_cache = ffd->raw_window_cache;
   rs->window_cache = ffd->txdelta_window_cache;
@@ -3149,6 +3286,9 @@ cache_windows(svn_fs_t *fs,
               apr_pool_t *pool)
 {
   apr_pool_t *iterpool = svn_pool_create(pool);
+
+  SVN_ERR(auto_read_diff_version(rs, iterpool));
+
   while (rs->current < rs->size)
     {
       apr_off_t end_offset;
@@ -3209,6 +3349,7 @@ cache_windows(svn_fs_t *fs,
           window.end_offset = rs->current;
           window.window.len = window_len;
           window.window.data = buf;
+          window.ver = rs->ver;
 
           /* cache the window now */
           SVN_ERR(svn_cache__set(rs->raw_window_cache, &key, &window,

Modified: subversion/branches/ra-git/subversion/libsvn_fs_fs/cached_data.h
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_fs/cached_data.h?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_fs_fs/cached_data.h (original)
+++ subversion/branches/ra-git/subversion/libsvn_fs_fs/cached_data.h Wed Nov  7 12:30:06 2018
@@ -81,7 +81,7 @@ svn_fs_fs__rep_chain_length(int *chain_l
                             svn_fs_t *fs,
                             apr_pool_t *scratch_pool);
 
-/* Set *CONTENTS to be a readable svn_stream_t that receives the text
+/* Set *CONTENTS_P to be a readable svn_stream_t that receives the text
    representation REP as seen in filesystem FS.  If CACHE_FULLTEXT is
    not set, bypass fulltext cache lookup for this rep and don't put the
    reconstructed fulltext into cache.
@@ -93,6 +93,18 @@ svn_fs_fs__get_contents(svn_stream_t **c
                         svn_boolean_t cache_fulltext,
                         apr_pool_t *pool);
 
+/* Set *CONTENTS_P to be a readable svn_stream_t that receives the text
+   representation REP as seen in filesystem FS.  Read the latest element
+   of the delta chain from FILE at offset OFFSET.
+   Use POOL for allocations. */
+svn_error_t *
+svn_fs_fs__get_contents_from_file(svn_stream_t **contents_p,
+                                  svn_fs_t *fs,
+                                  representation_t *rep,
+                                  apr_file_t *file,
+                                  apr_off_t offset,
+                                  apr_pool_t *pool);
+
 /* Attempt to fetch the text representation of node-revision NODEREV as
    seen in filesystem FS and pass it along with the BATON to the PROCESSOR.
    Set *SUCCESS only of the data could be provided and the processing
@@ -159,7 +171,7 @@ svn_fs_fs__get_proplist(apr_hash_t **pro
                         apr_pool_t *pool);
 
 /* Create a changes retrieval context object in *RESULT_POOL and return it
- * in *CONTEXT.  It will allow svn_fs_x__get_changes to fetch consecutive
+ * in *CONTEXT.  It will allow svn_fs_fs__get_changes to fetch consecutive
  * blocks (one per invocation) from REV's changed paths list in FS. */
 svn_error_t *
 svn_fs_fs__create_changes_context(svn_fs_fs__changes_context_t **context,

Modified: subversion/branches/ra-git/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_fs/caching.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_fs_fs/caching.c Wed Nov  7 12:30:06 2018
@@ -96,11 +96,8 @@ read_config(const char **cache_namespace
                                                ""),
                          pool);
 
-  /* don't cache text deltas by default.
-   * Once we reconstructed the fulltexts from the deltas,
-   * these deltas are rarely re-used. Therefore, only tools
-   * like svnadmin will activate this to speed up operations
-   * dump and verify.
+  /* Cache text deltas by default.
+   * They tend to be smaller and have finer granularity than fulltexts.
    */
   *cache_txdeltas
     = svn_hash__get_bool(fs->config,
@@ -119,9 +116,9 @@ read_config(const char **cache_namespace
                          SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS,
                          TRUE);
 
-  /* by default, cache nodeprops: this will match pre-1.10
-   * behavior where node properties caching was controlled
-   * by SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS configuration option.
+  /* by default, cache nodeprops.
+   * Pre-1.10, this was controlled by the SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS
+   * configuration option which defaulted to TRUE.
    */
   *cache_nodeprops
     = svn_hash__get_bool(fs->config,
@@ -386,7 +383,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
    *   (e.g. fulltexts etc.)
    * - Index data required to find any of the other data has high prio
    *   (e.g. noderevs, L2P and P2L index pages)
-   * - everthing else should use default prio
+   * - everything else should use default prio
    */
 
 #ifdef SVN_DEBUG_CACHE_DUMP_STATS
@@ -522,7 +519,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
   SVN_ERR(create_cache(&(ffd->revprop_cache),
                        NULL,
                        membuffer,
-                       0, 0, /* Do not use inprocess cache */
+                       8, 20, /* ~400 bytes / entry, capa for ~2 packs */
                        svn_fs_fs__serialize_revprops,
                        svn_fs_fs__deserialize_revprops,
                        sizeof(pair_cache_key_t),

Modified: subversion/branches/ra-git/subversion/libsvn_fs_fs/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_fs/dag.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_fs_fs/dag.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_fs_fs/dag.c Wed Nov  7 12:30:06 2018
@@ -1166,7 +1166,7 @@ svn_fs_fs__dag_serialize(void **data,
                                 (const void * const *)&node->node_pool);
 
   /* serialize other sub-structures */
-  svn_fs_fs__id_serialize(context, (const svn_fs_id_t **)&node->id);
+  svn_fs_fs__id_serialize(context, (const svn_fs_id_t *const *)&node->id);
   svn_fs_fs__id_serialize(context, &node->fresh_root_predecessor_id);
   svn_temp_serializer__add_string(context, &node->created_path);
 

Modified: subversion/branches/ra-git/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_fs/fs.h?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/ra-git/subversion/libsvn_fs_fs/fs.h Wed Nov  7 12:30:06 2018
@@ -117,6 +117,8 @@ extern "C" {
 #define CONFIG_OPTION_P2L_PAGE_SIZE      "p2l-page-size"
 #define CONFIG_SECTION_DEBUG             "debug"
 #define CONFIG_OPTION_PACK_AFTER_COMMIT  "pack-after-commit"
+#define CONFIG_OPTION_VERIFY_BEFORE_COMMIT "verify-before-commit"
+#define CONFIG_OPTION_COMPRESSION        "compression"
 
 /* The format number of this filesystem.
    This is independent of the repository format number, and
@@ -125,7 +127,7 @@ extern "C" {
    Note: If you bump this, please update the switch statement in
          svn_fs_fs__create() as well.
  */
-#define SVN_FS_FS__FORMAT_NUMBER   7
+#define SVN_FS_FS__FORMAT_NUMBER   8
 
 /* The minimum format number that supports svndiff version 1.  */
 #define SVN_FS_FS__MIN_SVNDIFF1_FORMAT 2
@@ -161,6 +163,9 @@ extern "C" {
  * issues with very old servers, restrict those options to the 1.6+ format*/
 #define SVN_FS_FS__MIN_DELTIFICATION_FORMAT 4
 
+/* The minimum format number that supports a configuration file (fsfs.conf) */
+#define SVN_FS_FS__MIN_CONFIG_FILE 4
+
 /* The 1.7-dev format, never released, that packed revprops into SQLite
    revprops.db . */
 #define SVN_FS_FS__PACKED_REVPROP_SQLITE_DEV_FORMAT 5
@@ -180,8 +185,20 @@ extern "C" {
 /* Minimum format number that supports per-instance filesystem IDs. */
 #define SVN_FS_FS__MIN_INSTANCE_ID_FORMAT 7
 
-/* The minimum format number that supports a configuration file (fsfs.conf) */
-#define SVN_FS_FS__MIN_CONFIG_FILE 4
+/* The minimum format number that supports svndiff version 2. */
+#define SVN_FS_FS__MIN_SVNDIFF2_FORMAT 8
+
+/* The minimum format number that supports the special notation ("-")
+   for optional values that are not present in the representation strings,
+   such as SHA1 or the uniquifier.  For example:
+
+     15 0 563 7809 28ef320a82e7bd11eebdf3502d69e608 - 14-g/_5
+ */
+#define SVN_FS_FS__MIN_REP_STRING_OPTIONAL_VALUES_FORMAT 8
+
+ /* The minimum format number that supports V2 schema of the rep-cache.db
+    database. */
+#define SVN_FS_FS__MIN_REP_CACHE_SCHEMA_V2_FORMAT 8
 
 /* On most operating systems apr implements file locks per process, not
    per file.  On Windows apr implements the locking as per file handle
@@ -294,6 +311,13 @@ typedef struct window_cache_key_t
   apr_uint64_t item_index;
 } window_cache_key_t;
 
+typedef enum compression_type_t
+{
+  compression_type_none,
+  compression_type_zlib,
+  compression_type_lz4
+} compression_type_t;
+
 /* Private (non-shared) FSFS-specific data for each svn_fs_t object.
    Any caches in here may be NULL. */
 typedef struct fs_fs_data_t
@@ -469,12 +493,18 @@ typedef struct fs_fs_data_t
    * deltification history after which skip deltas will be used. */
   apr_int64_t max_linear_deltification;
 
-  /* Compression level to use with txdelta storage format in new revs. */
+  /* Compression type to use with txdelta storage format in new revs. */
+  compression_type_t delta_compression_type;
+
+  /* Compression level (currently, only used with compression_type_zlib). */
   int delta_compression_level;
 
   /* Pack after every commit. */
   svn_boolean_t pack_after_commit;
 
+  /* Verify each new revision before commit. */
+  svn_boolean_t verify_before_commit;
+
   /* Per-instance filesystem ID, which provides an additional level of
      uniqueness for filesystems that share the same UUID, but should
      still be distinguishable (e.g. backups produced by svn_fs_hotcopy()