You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ar...@apache.org on 2012/07/30 08:39:38 UTC

svn commit: r1367002 [8/21] - in /subversion/branches/svn-bisect: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ contrib/client-side/emacs/ contrib/server-side/mod_dontdothat/ notes/ notes/api-errata/1.7/ notes/http-and-webdav/ ...

Modified: subversion/branches/svn-bisect/subversion/libsvn_delta/editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_delta/editor.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_delta/editor.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_delta/editor.c Mon Jul 30 06:39:28 2012
@@ -57,13 +57,129 @@ struct svn_editor_t
 #ifdef ENABLE_ORDERING_CHECK
   apr_hash_t *pending_incomplete_children;
   apr_hash_t *completed_nodes;
-  apr_hash_t *needs_text_or_target;
   svn_boolean_t finished;
 
   apr_pool_t *result_pool;
 #endif
 };
 
+#ifdef ENABLE_ORDERING_CHECK
+
+/* Marker to indicate no further changes are allowed on this node.  */
+static const int marker_done;
+#define MARKER_DONE (&marker_done)
+
+/* Marker indicating that add_* may be called for this path, or that it
+   can be the destination of a copy or move. For copy/move, the path
+   will switch to MARKER_ALLOW_ALTER, to enable further tweaks.  */
+static const int marker_allow_add;
+#define MARKER_ALLOW_ADD (&marker_allow_add)
+
+/* Marker indicating that alter_* may be called for this path.  */
+static const int marker_allow_alter;
+#define MARKER_ALLOW_ALTER (&marker_allow_alter)
+
+/* Just like MARKER_DONE, but also indicates that the node was created
+   via add_directory(). This allows us to verify that the CHILDREN param
+   was comprehensive.  */
+static const int marker_added_dir;
+#define MARKER_ADDED_DIR (&marker_added_dir)
+
+#define MARK_FINISHED(editor) ((editor)->finished = TRUE)
+#define SHOULD_NOT_BE_FINISHED(editor)  SVN_ERR_ASSERT(!(editor)->finished)
+
+#define CLEAR_INCOMPLETE(editor, relpath) \
+  apr_hash_set((editor)->pending_incomplete_children, relpath,  \
+               APR_HASH_KEY_STRING, NULL);
+
+#define MARK_RELPATH(editor, relpath, value) \
+  apr_hash_set((editor)->completed_nodes, \
+               apr_pstrdup((editor)->result_pool, relpath), \
+               APR_HASH_KEY_STRING, value)
+
+#define MARK_COMPLETED(editor, relpath) \
+  MARK_RELPATH(editor, relpath, MARKER_DONE)
+#define SHOULD_NOT_BE_COMPLETED(editor, relpath) \
+  SVN_ERR_ASSERT(apr_hash_get((editor)->completed_nodes, relpath, \
+                              APR_HASH_KEY_STRING) == NULL)
+
+#define MARK_ALLOW_ADD(editor, relpath) \
+  MARK_RELPATH(editor, relpath, MARKER_ALLOW_ADD)
+#define SHOULD_ALLOW_ADD(editor, relpath) \
+  SVN_ERR_ASSERT(allow_either(editor, relpath, MARKER_ALLOW_ADD, NULL))
+
+#define MARK_ALLOW_ALTER(editor, relpath) \
+  MARK_RELPATH(editor, relpath, MARKER_ALLOW_ALTER)
+#define SHOULD_ALLOW_ALTER(editor, relpath) \
+  SVN_ERR_ASSERT(allow_either(editor, relpath, MARKER_ALLOW_ALTER, NULL))
+
+#define MARK_ADDED_DIR(editor, relpath) \
+  MARK_RELPATH(editor, relpath, MARKER_ADDED_DIR)
+#define CHECK_UNKNOWN_CHILD(editor, relpath) \
+  SVN_ERR_ASSERT(check_unknown_child(editor, relpath))
+
+static svn_boolean_t
+allow_either(const svn_editor_t *editor,
+             const char *relpath,
+             const void *marker1,
+             const void *marker2)
+{
+  void *value = apr_hash_get(editor->completed_nodes, relpath,
+                             APR_HASH_KEY_STRING);
+  return value == marker1 || value == marker2;
+}
+
+static svn_boolean_t
+check_unknown_child(const svn_editor_t *editor,
+                    const char *relpath)
+{
+  const char *parent;
+
+  /* If we already know about the new child, then exit early.  */
+  if (apr_hash_get(editor->pending_incomplete_children, relpath,
+                   APR_HASH_KEY_STRING) != NULL)
+    return TRUE;
+
+  parent = svn_relpath_dirname(relpath, editor->scratch_pool);
+
+  /* Was this parent created via svn_editor_add_directory() ?  */
+  if (apr_hash_get(editor->completed_nodes, parent, APR_HASH_KEY_STRING)
+      == MARKER_ADDED_DIR)
+    {
+      /* Whoops. This child should have been listed in that add call,
+         and placed into ->pending_incomplete_children.  */
+      return FALSE;
+    }
+
+  /* The parent was not added in this drive.  */
+  return TRUE;
+}
+
+#else
+
+/* Be wary with the definition of these macros so that we don't
+   end up with "statement with no effect" warnings. Obviously, this
+   depends upon particular usage, which is easy to verify.  */
+
+#define MARK_FINISHED(editor)  /* empty */
+#define SHOULD_NOT_BE_FINISHED(editor)  /* empty */
+
+#define CLEAR_INCOMPLETE(editor, relpath)  /* empty */
+
+#define MARK_COMPLETED(editor, relpath)  /* empty */
+#define SHOULD_NOT_BE_COMPLETED(editor, relpath)  /* empty */
+
+#define MARK_ALLOW_ADD(editor, relpath)  /* empty */
+#define SHOULD_ALLOW_ADD(editor, relpath)  /* empty */
+
+#define MARK_ALLOW_ALTER(editor, relpath)  /* empty */
+#define SHOULD_ALLOW_ALTER(editor, relpath)  /* empty */
+
+#define MARK_ADDED_DIR(editor, relpath)  /* empty */
+#define CHECK_UNKNOWN_CHILD(editor, relpath)  /* empty */
+
+#endif /* ENABLE_ORDERING_CHECK */
+
 
 svn_error_t *
 svn_editor_create(svn_editor_t **editor,
@@ -79,10 +195,10 @@ svn_editor_create(svn_editor_t **editor,
   (*editor)->cancel_func = cancel_func;
   (*editor)->cancel_baton = cancel_baton;
   (*editor)->scratch_pool = svn_pool_create(result_pool);
+
 #ifdef ENABLE_ORDERING_CHECK
   (*editor)->pending_incomplete_children = apr_hash_make(result_pool);
   (*editor)->completed_nodes = apr_hash_make(result_pool);
-  (*editor)->needs_text_or_target = apr_hash_make(result_pool);
   (*editor)->finished = FALSE;
   (*editor)->result_pool = result_pool;
 #endif
@@ -132,31 +248,31 @@ svn_editor_setcb_add_absent(svn_editor_t
 
 
 svn_error_t *
-svn_editor_setcb_set_props(svn_editor_t *editor,
-                           svn_editor_cb_set_props_t callback,
-                           apr_pool_t *scratch_pool)
+svn_editor_setcb_alter_directory(svn_editor_t *editor,
+                                 svn_editor_cb_alter_directory_t callback,
+                                 apr_pool_t *scratch_pool)
 {
-  editor->funcs.cb_set_props = callback;
+  editor->funcs.cb_alter_directory = callback;
   return SVN_NO_ERROR;
 }
 
 
 svn_error_t *
-svn_editor_setcb_set_text(svn_editor_t *editor,
-                          svn_editor_cb_set_text_t callback,
-                          apr_pool_t *scratch_pool)
+svn_editor_setcb_alter_file(svn_editor_t *editor,
+                            svn_editor_cb_alter_file_t callback,
+                            apr_pool_t *scratch_pool)
 {
-  editor->funcs.cb_set_text = callback;
+  editor->funcs.cb_alter_file = callback;
   return SVN_NO_ERROR;
 }
 
 
 svn_error_t *
-svn_editor_setcb_set_target(svn_editor_t *editor,
-                            svn_editor_cb_set_target_t callback,
-                            apr_pool_t *scratch_pool)
+svn_editor_setcb_alter_symlink(svn_editor_t *editor,
+                               svn_editor_cb_alter_symlink_t callback,
+                               apr_pool_t *scratch_pool)
 {
-  editor->funcs.cb_set_target = callback;
+  editor->funcs.cb_alter_symlink = callback;
   return SVN_NO_ERROR;
 }
 
@@ -192,6 +308,16 @@ svn_editor_setcb_move(svn_editor_t *edit
 
 
 svn_error_t *
+svn_editor_setcb_rotate(svn_editor_t *editor,
+                        svn_editor_cb_rotate_t callback,
+                        apr_pool_t *scratch_pool)
+{
+  editor->funcs.cb_rotate = callback;
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
 svn_editor_setcb_complete(svn_editor_t *editor,
                           svn_editor_cb_complete_t callback,
                           apr_pool_t *scratch_pool)
@@ -222,12 +348,13 @@ svn_editor_setcb_many(svn_editor_t *edit
   COPY_CALLBACK(cb_add_file);
   COPY_CALLBACK(cb_add_symlink);
   COPY_CALLBACK(cb_add_absent);
-  COPY_CALLBACK(cb_set_props);
-  COPY_CALLBACK(cb_set_text);
-  COPY_CALLBACK(cb_set_target);
+  COPY_CALLBACK(cb_alter_directory);
+  COPY_CALLBACK(cb_alter_file);
+  COPY_CALLBACK(cb_alter_symlink);
   COPY_CALLBACK(cb_delete);
   COPY_CALLBACK(cb_copy);
   COPY_CALLBACK(cb_move);
+  COPY_CALLBACK(cb_rotate);
   COPY_CALLBACK(cb_complete);
   COPY_CALLBACK(cb_abort);
 
@@ -244,27 +371,26 @@ svn_editor_add_directory(svn_editor_t *e
                          apr_hash_t *props,
                          svn_revnum_t replaces_rev)
 {
-  svn_error_t *err;
+  svn_error_t *err = SVN_NO_ERROR;
 
-  SVN_ERR_ASSERT(editor->funcs.cb_add_directory != NULL);
-#ifdef ENABLE_ORDERING_CHECK
-  SVN_ERR_ASSERT(!editor->finished);
-  SVN_ERR_ASSERT(!apr_hash_get(editor->completed_nodes, relpath,
-                               APR_HASH_KEY_STRING));
-#endif
+  SVN_ERR_ASSERT(children != NULL);
+  SVN_ERR_ASSERT(props != NULL);
+  SHOULD_NOT_BE_FINISHED(editor);
+  SHOULD_ALLOW_ADD(editor, relpath);
+  CHECK_UNKNOWN_CHILD(editor, relpath);
 
   if (editor->cancel_func)
     SVN_ERR(editor->cancel_func(editor->cancel_baton));
 
-  err = editor->funcs.cb_add_directory(editor->baton, relpath, children,
-                                       props, replaces_rev,
-                                       editor->scratch_pool);
+  if (editor->funcs.cb_add_directory)
+    err = editor->funcs.cb_add_directory(editor->baton, relpath, children,
+                                         props, replaces_rev,
+                                         editor->scratch_pool);
+
+  MARK_ADDED_DIR(editor, relpath);
+  CLEAR_INCOMPLETE(editor, relpath);
+
 #ifdef ENABLE_ORDERING_CHECK
-  apr_hash_set(editor->completed_nodes,
-               apr_pstrdup(editor->result_pool, relpath),
-               APR_HASH_KEY_STRING, (void *) 0x5ca1ab1e);
-  apr_hash_set(editor->pending_incomplete_children, relpath,
-               APR_HASH_KEY_STRING, NULL);
   {
     int i;
     for (i = 0; i < children->nelts; i++)
@@ -274,10 +400,11 @@ svn_editor_add_directory(svn_editor_t *e
                                              editor->result_pool);
 
         apr_hash_set(editor->pending_incomplete_children, child,
-                     APR_HASH_KEY_STRING, (void *)0xdeadbeef);
+                     APR_HASH_KEY_STRING, "");
       }
   }
 #endif
+
   svn_pool_clear(editor->scratch_pool);
   return err;
 }
@@ -291,28 +418,26 @@ svn_editor_add_file(svn_editor_t *editor
                     apr_hash_t *props,
                     svn_revnum_t replaces_rev)
 {
-  svn_error_t *err;
+  svn_error_t *err = SVN_NO_ERROR;
 
-  SVN_ERR_ASSERT(editor->funcs.cb_add_file != NULL);
-#ifdef ENABLE_ORDERING_CHECK
-  SVN_ERR_ASSERT(!editor->finished);
-  SVN_ERR_ASSERT(!apr_hash_get(editor->completed_nodes, relpath,
-                               APR_HASH_KEY_STRING));
-#endif
+  SVN_ERR_ASSERT(checksum != NULL);
+  SVN_ERR_ASSERT(contents != NULL);
+  SVN_ERR_ASSERT(props != NULL);
+  SHOULD_NOT_BE_FINISHED(editor);
+  SHOULD_ALLOW_ADD(editor, relpath);
+  CHECK_UNKNOWN_CHILD(editor, relpath);
 
   if (editor->cancel_func)
     SVN_ERR(editor->cancel_func(editor->cancel_baton));
 
-  err = editor->funcs.cb_add_file(editor->baton, relpath,
-                                  checksum, contents, props,
-                                  replaces_rev, editor->scratch_pool);
-#ifdef ENABLE_ORDERING_CHECK
-  apr_hash_set(editor->completed_nodes,
-               apr_pstrdup(editor->result_pool, relpath),
-               APR_HASH_KEY_STRING, (void *) 0x5ca1ab1e);
-  apr_hash_set(editor->pending_incomplete_children, relpath,
-               APR_HASH_KEY_STRING, NULL);
-#endif
+  if (editor->funcs.cb_add_file)
+    err = editor->funcs.cb_add_file(editor->baton, relpath,
+                                    checksum, contents, props,
+                                    replaces_rev, editor->scratch_pool);
+
+  MARK_COMPLETED(editor, relpath);
+  CLEAR_INCOMPLETE(editor, relpath);
+
   svn_pool_clear(editor->scratch_pool);
   return err;
 }
@@ -325,27 +450,23 @@ svn_editor_add_symlink(svn_editor_t *edi
                        apr_hash_t *props,
                        svn_revnum_t replaces_rev)
 {
-  svn_error_t *err;
+  svn_error_t *err = SVN_NO_ERROR;
 
-  SVN_ERR_ASSERT(editor->funcs.cb_add_symlink != NULL);
-#ifdef ENABLE_ORDERING_CHECK
-  SVN_ERR_ASSERT(!editor->finished);
-  SVN_ERR_ASSERT(!apr_hash_get(editor->completed_nodes, relpath,
-                               APR_HASH_KEY_STRING));
-#endif
+  SVN_ERR_ASSERT(props != NULL);
+  SHOULD_NOT_BE_FINISHED(editor);
+  SHOULD_ALLOW_ADD(editor, relpath);
+  CHECK_UNKNOWN_CHILD(editor, relpath);
 
   if (editor->cancel_func)
     SVN_ERR(editor->cancel_func(editor->cancel_baton));
 
-  err = editor->funcs.cb_add_symlink(editor->baton, relpath, target, props,
-                                     replaces_rev, editor->scratch_pool);
-#ifdef ENABLE_ORDERING_CHECK
-  apr_hash_set(editor->completed_nodes,
-               apr_pstrdup(editor->result_pool, relpath),
-               APR_HASH_KEY_STRING, (void *) 0x5ca1ab1e);
-  apr_hash_set(editor->pending_incomplete_children, relpath,
-               APR_HASH_KEY_STRING, NULL);
-#endif
+  if (editor->funcs.cb_add_symlink)
+    err = editor->funcs.cb_add_symlink(editor->baton, relpath, target, props,
+                                       replaces_rev, editor->scratch_pool);
+
+  MARK_COMPLETED(editor, relpath);
+  CLEAR_INCOMPLETE(editor, relpath);
+
   svn_pool_clear(editor->scratch_pool);
   return err;
 }
@@ -357,134 +478,110 @@ svn_editor_add_absent(svn_editor_t *edit
                       svn_kind_t kind,
                       svn_revnum_t replaces_rev)
 {
-  svn_error_t *err;
+  svn_error_t *err = SVN_NO_ERROR;
 
-  SVN_ERR_ASSERT(editor->funcs.cb_add_absent != NULL);
-#ifdef ENABLE_ORDERING_CHECK
-  SVN_ERR_ASSERT(!editor->finished);
-  SVN_ERR_ASSERT(!apr_hash_get(editor->completed_nodes, relpath,
-                               APR_HASH_KEY_STRING));
-#endif
+  SHOULD_NOT_BE_FINISHED(editor);
+  SHOULD_ALLOW_ADD(editor, relpath);
+  CHECK_UNKNOWN_CHILD(editor, relpath);
 
   if (editor->cancel_func)
     SVN_ERR(editor->cancel_func(editor->cancel_baton));
 
-  err = editor->funcs.cb_add_absent(editor->baton, relpath, kind,
-                                    replaces_rev, editor->scratch_pool);
-#ifdef ENABLE_ORDERING_CHECK
-  apr_hash_set(editor->completed_nodes,
-               apr_pstrdup(editor->result_pool, relpath),
-               APR_HASH_KEY_STRING, (void *) 0x5ca1ab1e);
-  apr_hash_set(editor->pending_incomplete_children, relpath,
-               APR_HASH_KEY_STRING, NULL);
-#endif
+  if (editor->funcs.cb_add_absent)
+    err = editor->funcs.cb_add_absent(editor->baton, relpath, kind,
+                                      replaces_rev, editor->scratch_pool);
+
+  MARK_COMPLETED(editor, relpath);
+  CLEAR_INCOMPLETE(editor, relpath);
+
   svn_pool_clear(editor->scratch_pool);
   return err;
 }
 
 
 svn_error_t *
-svn_editor_set_props(svn_editor_t *editor,
-                     const char *relpath,
-                     svn_revnum_t revision,
-                     apr_hash_t *props,
-                     svn_boolean_t complete)
+svn_editor_alter_directory(svn_editor_t *editor,
+                           const char *relpath,
+                           svn_revnum_t revision,
+                           apr_hash_t *props)
 {
-  svn_error_t *err;
+  svn_error_t *err = SVN_NO_ERROR;
 
-  SVN_ERR_ASSERT(editor->funcs.cb_set_props != NULL);
-#ifdef ENABLE_ORDERING_CHECK
-  SVN_ERR_ASSERT(!editor->finished);
-  SVN_ERR_ASSERT(!apr_hash_get(editor->completed_nodes, relpath,
-                               APR_HASH_KEY_STRING));
-#endif
+  SVN_ERR_ASSERT(props != NULL);
+  SHOULD_NOT_BE_FINISHED(editor);
+  SHOULD_ALLOW_ALTER(editor, relpath);
 
   if (editor->cancel_func)
     SVN_ERR(editor->cancel_func(editor->cancel_baton));
 
-  err = editor->funcs.cb_set_props(editor->baton, relpath, revision, props,
-                                   complete, editor->scratch_pool);
-#ifdef ENABLE_ORDERING_CHECK
-  /* ### Some of the ordering here depends upon the kind of RELPATH, but
-   * ### we have no way of determining what that is. */
-  if (complete)
-    {
-      apr_hash_set(editor->completed_nodes,
-                   apr_pstrdup(editor->result_pool, relpath),
-                   APR_HASH_KEY_STRING, (void *) 0x5ca1ab1e);
-    }
-  else
-    {
-      apr_hash_set(editor->needs_text_or_target,
-                   apr_pstrdup(editor->result_pool, relpath),
-                   APR_HASH_KEY_STRING, (void *) 0xba5eba11);
-    }
-#endif
+  if (editor->funcs.cb_alter_directory)
+    err = editor->funcs.cb_alter_directory(editor->baton,
+                                           relpath, revision, props,
+                                           editor->scratch_pool);
+
+  MARK_COMPLETED(editor, relpath);
+
   svn_pool_clear(editor->scratch_pool);
   return err;
 }
 
 
 svn_error_t *
-svn_editor_set_text(svn_editor_t *editor,
-                    const char *relpath,
-                    svn_revnum_t revision,
-                    const svn_checksum_t *checksum,
-                    svn_stream_t *contents)
-{
-  svn_error_t *err;
-
-  SVN_ERR_ASSERT(editor->funcs.cb_set_text != NULL);
-#ifdef ENABLE_ORDERING_CHECK
-  SVN_ERR_ASSERT(!editor->finished);
-  SVN_ERR_ASSERT(!apr_hash_get(editor->completed_nodes, relpath,
-                               APR_HASH_KEY_STRING));
-#endif
+svn_editor_alter_file(svn_editor_t *editor,
+                      const char *relpath,
+                      svn_revnum_t revision,
+                      apr_hash_t *props,
+                      const svn_checksum_t *checksum,
+                      svn_stream_t *contents)
+{
+  svn_error_t *err = SVN_NO_ERROR;
+
+  SVN_ERR_ASSERT((checksum != NULL && contents != NULL)
+                 || (checksum == NULL && contents == NULL));
+  SVN_ERR_ASSERT(props != NULL || checksum != NULL);
+  SHOULD_NOT_BE_FINISHED(editor);
+  SHOULD_ALLOW_ALTER(editor, relpath);
 
   if (editor->cancel_func)
     SVN_ERR(editor->cancel_func(editor->cancel_baton));
 
-  err = editor->funcs.cb_set_text(editor->baton, relpath, revision,
-                                  checksum, contents, editor->scratch_pool);
-#ifdef ENABLE_ORDERING_CHECK
-  apr_hash_set(editor->needs_text_or_target, relpath, APR_HASH_KEY_STRING,
-               NULL);
-  apr_hash_set(editor->completed_nodes,
-               apr_pstrdup(editor->result_pool, relpath),
-               APR_HASH_KEY_STRING, (void *) 0x5ca1ab1e);
-#endif
+  if (editor->funcs.cb_alter_file)
+    err = editor->funcs.cb_alter_file(editor->baton,
+                                      relpath, revision, props,
+                                      checksum, contents,
+                                      editor->scratch_pool);
+
+  MARK_COMPLETED(editor, relpath);
+
   svn_pool_clear(editor->scratch_pool);
   return err;
 }
 
 
 svn_error_t *
-svn_editor_set_target(svn_editor_t *editor,
-                      const char *relpath,
-                      svn_revnum_t revision,
-                      const char *target)
+svn_editor_alter_symlink(svn_editor_t *editor,
+                         const char *relpath,
+                         svn_revnum_t revision,
+                         apr_hash_t *props,
+                         const char *target)
 {
-  svn_error_t *err;
+  svn_error_t *err = SVN_NO_ERROR;
 
-  SVN_ERR_ASSERT(editor->funcs.cb_set_target != NULL);
-#ifdef ENABLE_ORDERING_CHECK
-  SVN_ERR_ASSERT(!editor->finished);
-  SVN_ERR_ASSERT(!apr_hash_get(editor->completed_nodes, relpath,
-                               APR_HASH_KEY_STRING));
-#endif
+  SVN_ERR_ASSERT(props != NULL || target != NULL);
+  SHOULD_NOT_BE_FINISHED(editor);
+  SHOULD_ALLOW_ALTER(editor, relpath);
 
   if (editor->cancel_func)
     SVN_ERR(editor->cancel_func(editor->cancel_baton));
 
-  err = editor->funcs.cb_set_target(editor->baton, relpath, revision,
-                                    target, editor->scratch_pool);
-#ifdef ENABLE_ORDERING_CHECK
-  apr_hash_set(editor->needs_text_or_target, relpath, APR_HASH_KEY_STRING,
-               NULL);
-  apr_hash_set(editor->completed_nodes,
-               apr_pstrdup(editor->result_pool, relpath),
-               APR_HASH_KEY_STRING, (void *) 0x5ca1ab1e);
-#endif
+  if (editor->funcs.cb_alter_symlink)
+    err = editor->funcs.cb_alter_symlink(editor->baton,
+                                         relpath, revision, props,
+                                         target,
+                                         editor->scratch_pool);
+
+  MARK_COMPLETED(editor, relpath);
+
   svn_pool_clear(editor->scratch_pool);
   return err;
 }
@@ -495,25 +592,20 @@ svn_editor_delete(svn_editor_t *editor,
                   const char *relpath,
                   svn_revnum_t revision)
 {
-  svn_error_t *err;
+  svn_error_t *err = SVN_NO_ERROR;
 
-  SVN_ERR_ASSERT(editor->funcs.cb_delete != NULL);
-#ifdef ENABLE_ORDERING_CHECK
-  SVN_ERR_ASSERT(!editor->finished);
-  SVN_ERR_ASSERT(!apr_hash_get(editor->completed_nodes, relpath,
-                               APR_HASH_KEY_STRING));
-#endif
+  SHOULD_NOT_BE_FINISHED(editor);
+  SHOULD_NOT_BE_COMPLETED(editor, relpath);
 
   if (editor->cancel_func)
     SVN_ERR(editor->cancel_func(editor->cancel_baton));
 
-  err = editor->funcs.cb_delete(editor->baton, relpath, revision,
-                                editor->scratch_pool);
-#ifdef ENABLE_ORDERING_CHECK
-  apr_hash_set(editor->completed_nodes,
-               apr_pstrdup(editor->result_pool, relpath),
-               APR_HASH_KEY_STRING, (void *) 0x5ca1ab1e);
-#endif
+  if (editor->funcs.cb_delete)
+    err = editor->funcs.cb_delete(editor->baton, relpath, revision,
+                                  editor->scratch_pool);
+
+  MARK_COMPLETED(editor, relpath);
+
   svn_pool_clear(editor->scratch_pool);
   return err;
 }
@@ -526,21 +618,22 @@ svn_editor_copy(svn_editor_t *editor,
                 const char *dst_relpath,
                 svn_revnum_t replaces_rev)
 {
-  svn_error_t *err;
+  svn_error_t *err = SVN_NO_ERROR;
 
-  SVN_ERR_ASSERT(editor->funcs.cb_copy != NULL);
-#ifdef ENABLE_ORDERING_CHECK
-  SVN_ERR_ASSERT(!editor->finished);
-  SVN_ERR_ASSERT(!apr_hash_get(editor->completed_nodes, dst_relpath,
-                               APR_HASH_KEY_STRING));
-#endif
+  SHOULD_NOT_BE_FINISHED(editor);
+  SHOULD_ALLOW_ADD(editor, dst_relpath);
 
   if (editor->cancel_func)
     SVN_ERR(editor->cancel_func(editor->cancel_baton));
 
-  err = editor->funcs.cb_copy(editor->baton, src_relpath, src_revision,
-                              dst_relpath, replaces_rev,
-                              editor->scratch_pool);
+  if (editor->funcs.cb_copy)
+    err = editor->funcs.cb_copy(editor->baton, src_relpath, src_revision,
+                                dst_relpath, replaces_rev,
+                                editor->scratch_pool);
+
+  MARK_ALLOW_ALTER(editor, dst_relpath);
+  CLEAR_INCOMPLETE(editor, dst_relpath);
+
   svn_pool_clear(editor->scratch_pool);
   return err;
 }
@@ -553,39 +646,66 @@ svn_editor_move(svn_editor_t *editor,
                 const char *dst_relpath,
                 svn_revnum_t replaces_rev)
 {
-  svn_error_t *err;
+  svn_error_t *err = SVN_NO_ERROR;
+
+  SHOULD_NOT_BE_FINISHED(editor);
+  SHOULD_NOT_BE_COMPLETED(editor, src_relpath);
+  SHOULD_ALLOW_ADD(editor, dst_relpath);
 
-  SVN_ERR_ASSERT(editor->funcs.cb_move != NULL);
+  if (editor->cancel_func)
+    SVN_ERR(editor->cancel_func(editor->cancel_baton));
+
+  if (editor->funcs.cb_move)
+    err = editor->funcs.cb_move(editor->baton, src_relpath, src_revision,
+                                dst_relpath, replaces_rev,
+                                editor->scratch_pool);
+
+  MARK_ALLOW_ADD(editor, src_relpath);
+  MARK_ALLOW_ALTER(editor, dst_relpath);
+  CLEAR_INCOMPLETE(editor, dst_relpath);
+
+  svn_pool_clear(editor->scratch_pool);
+  return err;
+}
+
+
+svn_error_t *
+svn_editor_rotate(svn_editor_t *editor,
+                  const apr_array_header_t *relpaths,
+                  const apr_array_header_t *revisions)
+{
+  svn_error_t *err = SVN_NO_ERROR;
+
+  SHOULD_NOT_BE_FINISHED(editor);
 #ifdef ENABLE_ORDERING_CHECK
-  SVN_ERR_ASSERT(!editor->finished);
-  SVN_ERR_ASSERT(!apr_hash_get(editor->completed_nodes, src_relpath,
-                               APR_HASH_KEY_STRING));
-  SVN_ERR_ASSERT(!apr_hash_get(editor->completed_nodes, dst_relpath,
-                               APR_HASH_KEY_STRING));
+  {
+    int i;
+    for (i = 0; i < relpaths->nelts; i++)
+      {
+        const char *relpath = APR_ARRAY_IDX(relpaths, i, const char *);
+        SHOULD_NOT_BE_COMPLETED(editor, relpath);
+      }
+  }
 #endif
 
   if (editor->cancel_func)
     SVN_ERR(editor->cancel_func(editor->cancel_baton));
 
-  err = editor->funcs.cb_move(editor->baton, src_relpath, src_revision,
-                              dst_relpath, replaces_rev,
-                              editor->scratch_pool);
+  if (editor->funcs.cb_rotate)
+    err = editor->funcs.cb_rotate(editor->baton, relpaths, revisions,
+                                  editor->scratch_pool);
+
 #ifdef ENABLE_ORDERING_CHECK
-  /* ### after moving a node away, a new one can be created. how does
-     ### affect the "replaces_rev" concept elsewhere?  */
-#if 0
-  apr_hash_set(editor->completed_nodes,
-               apr_pstrdup(editor->result_pool, src_relpath),
-               APR_HASH_KEY_STRING, (void *) 0x5ca1ab1e);
+  {
+    int i;
+    for (i = 0; i < relpaths->nelts; i++)
+      {
+        const char *relpath = APR_ARRAY_IDX(relpaths, i, const char *);
+        MARK_ALLOW_ALTER(editor, relpath);
+      }
+  }
 #endif
 
-  /* ### hmm. post-move, it should be possible to change props/contents.  */
-#if 0
-  apr_hash_set(editor->completed_nodes,
-               apr_pstrdup(editor->result_pool, dst_relpath),
-               APR_HASH_KEY_STRING, (void *) 0x5ca1ab1e);
-#endif
-#endif
   svn_pool_clear(editor->scratch_pool);
   return err;
 }
@@ -594,19 +714,18 @@ svn_editor_move(svn_editor_t *editor,
 svn_error_t *
 svn_editor_complete(svn_editor_t *editor)
 {
-  svn_error_t *err;
+  svn_error_t *err = SVN_NO_ERROR;
 
-  SVN_ERR_ASSERT(editor->funcs.cb_complete != NULL);
+  SHOULD_NOT_BE_FINISHED(editor);
 #ifdef ENABLE_ORDERING_CHECK
-  SVN_ERR_ASSERT(!editor->finished);
   SVN_ERR_ASSERT(apr_hash_count(editor->pending_incomplete_children) == 0);
-  SVN_ERR_ASSERT(apr_hash_count(editor->needs_text_or_target) == 0);
 #endif
 
-  err = editor->funcs.cb_complete(editor->baton, editor->scratch_pool);
-#ifdef ENABLE_ORDERING_CHECK
-  editor->finished = TRUE;
-#endif
+  if (editor->funcs.cb_complete)
+    err = editor->funcs.cb_complete(editor->baton, editor->scratch_pool);
+
+  MARK_FINISHED(editor);
+
   svn_pool_clear(editor->scratch_pool);
   return err;
 }
@@ -615,17 +734,15 @@ svn_editor_complete(svn_editor_t *editor
 svn_error_t *
 svn_editor_abort(svn_editor_t *editor)
 {
-  svn_error_t *err;
+  svn_error_t *err = SVN_NO_ERROR;
 
-  SVN_ERR_ASSERT(editor->funcs.cb_abort != NULL);
-#ifdef ENABLE_ORDERING_CHECK
-  SVN_ERR_ASSERT(!editor->finished);
-#endif
+  SHOULD_NOT_BE_FINISHED(editor);
+
+  if (editor->funcs.cb_abort)
+    err = editor->funcs.cb_abort(editor->baton, editor->scratch_pool);
+
+  MARK_FINISHED(editor);
 
-  err = editor->funcs.cb_abort(editor->baton, editor->scratch_pool);
-#ifdef ENABLE_ORDERING_CHECK
-  editor->finished = TRUE;
-#endif
   svn_pool_clear(editor->scratch_pool);
   return err;
 }

Modified: subversion/branches/svn-bisect/subversion/libsvn_delta/svndiff.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_delta/svndiff.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_delta/svndiff.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_delta/svndiff.c Mon Jul 30 06:39:28 2012
@@ -31,6 +31,8 @@
 #include "svn_private_config.h"
 #include <zlib.h>
 
+#include "private/svn_error_private.h"
+
 /* The zlib compressBound function was not exported until 1.2.0. */
 #if ZLIB_VERNUM >= 0x1200
 #define svnCompressBound(LEN) compressBound(LEN)
@@ -156,15 +158,18 @@ zlib_encode(const char *data,
     }
   else
     {
+      int zerr;
+
       svn_stringbuf_ensure(out, svnCompressBound(len) + intlen);
       endlen = out->blocksize;
 
-      if (compress2((unsigned char *)out->data + intlen, &endlen,
-                    (const unsigned char *)data, len,
-                    compression_level) != Z_OK)
-        return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA,
-                                NULL,
-                                _("Compression of svndiff data failed"));
+      zerr = compress2((unsigned char *)out->data + intlen, &endlen,
+                       (const unsigned char *)data, len,
+                       compression_level);
+      if (zerr != Z_OK)
+        return svn_error_trace(svn_error__wrap_zlib(
+                                 zerr, "compress2",
+                                 _("Compression of svndiff data failed")));
 
       /* Compression didn't help :(, just append the original text */
       if (endlen >= len)
@@ -472,12 +477,14 @@ zlib_decode(const unsigned char *in, apr
   else
     {
       unsigned long zlen = len;
+      int zerr;
 
       svn_stringbuf_ensure(out, len);
-      if (uncompress((unsigned char *)out->data, &zlen, in, inLen) != Z_OK)
-        return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA,
-                                NULL,
-                                _("Decompression of svndiff data failed"));
+      zerr = uncompress((unsigned char *)out->data, &zlen, in, inLen);
+      if (zerr != Z_OK)
+        return svn_error_trace(svn_error__wrap_zlib(
+                                 zerr, "uncompress",
+                                 _("Decompression of svndiff data failed")));
 
       /* Zlib should not produce something that has a different size than the
          original length we stored. */

Modified: subversion/branches/svn-bisect/subversion/libsvn_delta/text_delta.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_delta/text_delta.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_delta/text_delta.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_delta/text_delta.c Mon Jul 30 06:39:28 2012
@@ -276,6 +276,48 @@ svn_txdelta__insert_op(svn_txdelta__ops_
   ++build_baton->num_ops;
 }
 
+apr_size_t
+svn_txdelta__remove_copy(svn_txdelta__ops_baton_t *build_baton,
+                         apr_size_t max_len)
+{
+  svn_txdelta_op_t *op;
+  apr_size_t len = 0;
+
+  /* remove ops back to front */
+  while (build_baton->num_ops > 0)
+    {
+      op = &build_baton->ops[build_baton->num_ops-1];
+
+      /*  we can't modify svn_txdelta_target ops -> stop there */
+      if (op->action_code == svn_txdelta_target)
+        break;
+      
+      /*  handle the case that we cannot remove the op entirely */
+      if (op->length + len > max_len)
+        {
+          /* truncate only insertions. Copies don't benefit
+             from being truncated. */
+          if (op->action_code == svn_txdelta_new)
+            {
+               build_baton->new_data->len -= max_len - len;
+               op->length -= max_len - len;
+               len = max_len;
+            }
+          
+          break;
+        }
+        
+      /* drop the op entirely */
+      if (op->action_code == svn_txdelta_new)
+        build_baton->new_data->len -= op->length;
+      
+      len += op->length;
+      --build_baton->num_ops;
+    }
+    
+  return len;
+}
+
 
 
 /* Generic delta stream functions. */

Modified: subversion/branches/svn-bisect/subversion/libsvn_delta/xdelta.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_delta/xdelta.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_delta/xdelta.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_delta/xdelta.c Mon Jul 30 06:39:28 2012
@@ -44,6 +44,10 @@
  */
 #define MATCH_BLOCKSIZE 64
 
+/* "no" / "invalid" / "unused" value for positions within the detla windows
+ */
+#define NO_POSITION ((apr_uint32_t)-1)
+
 /* Feed C_IN into the adler32 checksum and remove C_OUT at the same time.
  * This function may (and will) only be called for characters that are
  * MATCH_BLOCKSIZE positions apart.
@@ -96,17 +100,22 @@ init_adler32(const char *data)
 struct block
 {
   apr_uint32_t adlersum;
-  apr_size_t pos;
+
+/* Even in 64 bit systems, store only 32 bit offsets in our hash table
+   (our delta window size much much smaller then 4GB).
+   That reduces the hash table size by 50% from 32to 16KB
+   and makes it easier to fit into the CPU's L1 cache. */
+  apr_uint32_t pos;			/* NO_POSITION -> block is not used */
 };
 
 /* A hash table, using open addressing, of the blocks of the source. */
 struct blocks
 {
   /* The largest valid index of slots. */
-  apr_size_t max;
+  apr_uint32_t max;
   /* Source buffer that the positions in SLOTS refer to. */
   const char* data;
-  /* The vector of blocks.  A pos value of (apr_size_t)-1 represents an unused
+  /* The vector of blocks.  A pos value of NO_POSITION represents an unused
      slot. */
   struct block *slots;
 };
@@ -114,7 +123,7 @@ struct blocks
 
 /* Return a hash value calculated from the adler32 SUM, suitable for use with
    our hash table. */
-static apr_size_t hash_func(apr_uint32_t sum)
+static apr_uint32_t hash_func(apr_uint32_t sum)
 {
   /* Since the adl32 checksum have a bad distribution for the 11th to 16th
      bits when used for our small block size, we add some bits from the
@@ -126,12 +135,12 @@ static apr_size_t hash_func(apr_uint32_t
    data into the table BLOCKS.  Ignore true duplicates, i.e. blocks with
    actually the same content. */
 static void
-add_block(struct blocks *blocks, apr_uint32_t adlersum, apr_size_t pos)
+add_block(struct blocks *blocks, apr_uint32_t adlersum, apr_uint32_t pos)
 {
-  apr_size_t h = hash_func(adlersum) & blocks->max;
+  apr_uint32_t h = hash_func(adlersum) & blocks->max;
 
   /* This will terminate, since we know that we will not fill the table. */
-  for (; blocks->slots[h].pos != (apr_size_t)-1; h = (h + 1) & blocks->max)
+  for (; blocks->slots[h].pos != NO_POSITION; h = (h + 1) & blocks->max)
     if (blocks->slots[h].adlersum == adlersum)
       if (memcmp(blocks->data + blocks->slots[h].pos, blocks->data + pos,
                  MATCH_BLOCKSIZE) == 0)
@@ -143,21 +152,21 @@ add_block(struct blocks *blocks, apr_uin
 
 /* Find a block in BLOCKS with the checksum ADLERSUM and matching the content
    at DATA, returning its position in the source data.  If there is no such
-   block, return (apr_size_t)-1. */
-static apr_size_t
+   block, return NO_POSITION. */
+static apr_uint32_t
 find_block(const struct blocks *blocks,
            apr_uint32_t adlersum,
            const char* data)
 {
-  apr_size_t h = hash_func(adlersum) & blocks->max;
+  apr_uint32_t h = hash_func(adlersum) & blocks->max;
 
-  for (; blocks->slots[h].pos != (apr_size_t)-1; h = (h + 1) & blocks->max)
+  for (; blocks->slots[h].pos != NO_POSITION; h = (h + 1) & blocks->max)
     if (blocks->slots[h].adlersum == adlersum)
       if (memcmp(blocks->data + blocks->slots[h].pos, data,
                  MATCH_BLOCKSIZE) == 0)
         return blocks->slots[h].pos;
 
-  return (apr_size_t)-1;
+  return NO_POSITION;
 }
 
 /* Initialize the matches table from DATA of size DATALEN.  This goes
@@ -187,7 +196,7 @@ init_blocks_table(const char *data,
     {
       /* Avoid using an indeterminate value in the lookup. */
       blocks->slots[i].adlersum = 0;
-      blocks->slots[i].pos = (apr_size_t)-1;
+      blocks->slots[i].pos = NO_POSITION;
     }
 
   /* If there is an odd block at the end of the buffer, we will
@@ -226,6 +235,39 @@ match_length(const char *a, const char *
   return pos;
 }
 
+/* Return the smallest byte index at which positions left of A and B differ
+ * (A[-result] != B[-result]).  If no difference can be found in the first
+ * MAX_LEN characters, MAX_LEN will be returned.
+ */
+static apr_size_t
+reverse_match_length(const char *a, const char *b, apr_size_t max_len)
+{
+  apr_size_t pos = 0;
+
+#if SVN_UNALIGNED_ACCESS_IS_OK
+
+  /* Chunky processing is so much faster ...
+   *
+   * We can't make this work on architectures that require aligned access
+   * because A and B will probably have different alignment. So, skipping
+   * the first few chars until alignment is reached is not an option.
+   */
+  for (pos = sizeof(apr_size_t); pos <= max_len; pos += sizeof(apr_size_t))
+    if (*(const apr_size_t*)(a - pos) != *(const apr_size_t*)(b - pos))
+      break;
+
+  pos -= sizeof(apr_size_t);
+    
+#endif
+
+  while (++pos <= max_len)
+    if (a[-pos] != b[-pos])
+      break;
+    
+  return pos-1;
+}
+
+
 /* Try to find a match for the target data B in BLOCKS, and then
    extend the match as long as data in A and B at the match position
    continues to match.  We set the position in A we ended up in (in
@@ -252,7 +294,7 @@ find_match(const struct blocks *blocks,
   apos = find_block(blocks, rolling, b + bpos);
 
   /* See if we have a match.  */
-  if (apos == (apr_size_t)-1)
+  if (apos == NO_POSITION)
     return 0;
 
   /* Extend the match forward as far as possible */
@@ -278,6 +320,38 @@ find_match(const struct blocks *blocks,
   return MATCH_BLOCKSIZE + delta;
 }
 
+/* Utility for compute_delta() that compares the range B[START,BSIZE) with
+ * the range of similar size before A[ASIZE]. Create corresponding copy and
+ * insert operations.
+ *
+ * BUILD_BATON and POOL will be passed through from compute_delta().
+ */
+static void
+store_delta_trailer(svn_txdelta__ops_baton_t *build_baton,
+                    const char *a,
+                    apr_size_t asize,
+                    const char *b,
+                    apr_size_t bsize,
+                    apr_size_t start,
+                    apr_pool_t *pool)
+{
+  apr_size_t end_match;
+  apr_size_t max_len = asize > (bsize - start) ? bsize - start : asize;
+  if (max_len == 0)
+    return;
+
+  end_match = reverse_match_length(a + asize, b + bsize, max_len);
+  if (end_match <= 4)
+    end_match = 0;
+
+  if (bsize - start > end_match)
+    svn_txdelta__insert_op(build_baton, svn_txdelta_new,
+                           start, bsize - start - end_match, b + start, pool);
+  if (end_match)
+    svn_txdelta__insert_op(build_baton, svn_txdelta_source,
+                           asize - end_match, end_match, NULL, pool);
+}
+
 
 /* Compute a delta from A to B using xdelta.
 
@@ -315,12 +389,24 @@ compute_delta(svn_txdelta__ops_baton_t *
   apr_uint32_t rolling;
   apr_size_t lo = 0, pending_insert_start = 0;
 
+  /* Optimization: directly compare window starts. If more than 4
+   * bytes match, we can immediately create a matching windows. 
+   * Shorter sequences result in a net data increase. */
+  lo = match_length(a, b, asize > bsize ? bsize : asize);
+  if ((lo > 4) || (lo == bsize))
+    {
+      svn_txdelta__insert_op(build_baton, svn_txdelta_source,
+                             0, lo, NULL, pool);
+      pending_insert_start = lo;
+    }
+  else
+    lo = 0;
+
   /* If the size of the target is smaller than the match blocksize, just
      insert the entire target.  */
-  if (bsize < MATCH_BLOCKSIZE)
+  if ((bsize - lo < MATCH_BLOCKSIZE) || (asize < MATCH_BLOCKSIZE))
     {
-      svn_txdelta__insert_op(build_baton, svn_txdelta_new,
-                             0, bsize, b, pool);
+      store_delta_trailer(build_baton, a, asize, b, bsize, lo, pool);
       return;
     }
 
@@ -328,7 +414,7 @@ compute_delta(svn_txdelta__ops_baton_t *
   init_blocks_table(a, asize, &blocks, pool);
 
   /* Initialize our rolling checksum.  */
-  rolling = init_adler32(b);
+  rolling = init_adler32(b + lo);
   while (lo < bsize)
     {
       apr_size_t matchlen = 0;
@@ -356,6 +442,19 @@ compute_delta(svn_txdelta__ops_baton_t *
             svn_txdelta__insert_op(build_baton, svn_txdelta_new,
                                    0, lo - pending_insert_start,
                                    b + pending_insert_start, pool);
+          else 
+            {
+              /* the match borders on the previous op. Maybe, we found a
+               * match that is better than / overlapping the previous one. */
+              apr_size_t len = reverse_match_length(a + apos, b + lo, apos < lo ? apos : lo);
+              if (len > 0)
+                {
+                  len = svn_txdelta__remove_copy(build_baton, len);
+                  apos -= len;
+                  matchlen += len;
+                  lo -= len;
+                }
+            }
 
           /* Reset the pending insert start to immediately after the
              match. */
@@ -373,12 +472,7 @@ compute_delta(svn_txdelta__ops_baton_t *
     }
 
   /* If we still have an insert pending at the end, throw it in.  */
-  if (lo - pending_insert_start > 0)
-    {
-      svn_txdelta__insert_op(build_baton, svn_txdelta_new,
-                             0, lo - pending_insert_start,
-                             b + pending_insert_start, pool);
-    }
+  store_delta_trailer(build_baton, a, asize, b, bsize, pending_insert_start, pool);
 }
 
 void

Modified: subversion/branches/svn-bisect/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_diff/parse-diff.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_diff/parse-diff.c Mon Jul 30 06:39:28 2012
@@ -590,11 +590,19 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
   svn_boolean_t eof, in_hunk, hunk_seen;
   apr_off_t pos, last_line;
   apr_off_t start, end;
+  apr_off_t original_end;
+  apr_off_t modified_end;
   svn_linenum_t original_lines;
   svn_linenum_t modified_lines;
   svn_linenum_t leading_context;
   svn_linenum_t trailing_context;
   svn_boolean_t changed_line_seen;
+  enum {
+    noise_line,
+    original_line,
+    modified_line,
+    context_line
+  } last_line_type;
   apr_pool_t *iterpool;
 
   *prop_operation = svn_diff_op_unchanged;
@@ -615,12 +623,17 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
   leading_context = 0;
   trailing_context = 0;
   changed_line_seen = FALSE;
+  original_end = 0;
+  modified_end = 0;
   *hunk = apr_pcalloc(result_pool, sizeof(**hunk));
 
   /* Get current seek position -- APR has no ftell() :( */
   pos = 0;
   SVN_ERR(svn_io_file_seek(apr_file, APR_CUR, &pos, scratch_pool));
 
+  /* Start out assuming noise. */
+  last_line_type = noise_line;
+
   iterpool = svn_pool_create(scratch_pool);
   do
     {
@@ -632,17 +645,58 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
       SVN_ERR(readline(apr_file, &line, NULL, &eof, APR_SIZE_MAX,
                        iterpool, iterpool));
 
-      if (! eof)
-        {
-          /* Update line offset for next iteration. */
-          pos = 0;
-          SVN_ERR(svn_io_file_seek(apr_file, APR_CUR, &pos, iterpool));
-        }
+      /* Update line offset for next iteration. */
+      pos = 0;
+      SVN_ERR(svn_io_file_seek(apr_file, APR_CUR, &pos, iterpool));
 
       /* Lines starting with a backslash are comments, such as
        * "\ No newline at end of file". */
       if (line->data[0] == '\\')
-        continue;
+        {
+          if (in_hunk &&
+              ((!*is_property &&
+                strcmp(line->data, "\\ No newline at end of file") == 0) ||
+               (*is_property &&
+                strcmp(line->data, "\\ No newline at end of property") == 0)))
+            {
+              char eolbuf[2];
+              apr_size_t len;
+              apr_off_t off;
+              apr_off_t hunk_text_end;
+
+              /* Comment terminates the hunk text and says the hunk text
+               * has no trailing EOL. Snip off trailing EOL which is part
+               * of the patch file but not part of the hunk text. */
+              off = last_line - 2;
+              SVN_ERR(svn_io_file_seek(apr_file, APR_SET, &off, iterpool));
+              len = sizeof(eolbuf);
+              SVN_ERR(svn_io_file_read_full2(apr_file, eolbuf, len, &len,
+                                             &eof, iterpool));
+              if (eolbuf[0] == '\r' && eolbuf[1] == '\n')
+                hunk_text_end = last_line - 2;
+              else if (eolbuf[1] == '\n' || eolbuf[1] == '\r')
+                hunk_text_end = last_line - 1;
+              else
+                hunk_text_end = last_line;
+
+              if (last_line_type == original_line && original_end == 0)
+                original_end = hunk_text_end;
+              else if (last_line_type == modified_line && modified_end == 0)
+                modified_end = hunk_text_end;
+              else if (last_line_type == context_line)
+                {
+                  if (original_end == 0)
+                    original_end = hunk_text_end;
+                  if (modified_end == 0)
+                    modified_end = hunk_text_end;
+                  break;
+                }
+
+              SVN_ERR(svn_io_file_seek(apr_file, APR_SET, &pos, iterpool));
+            }
+
+          continue;
+        }
 
       if (in_hunk)
         {
@@ -673,6 +727,7 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
                 trailing_context++;
               else
                 leading_context++;
+              last_line_type = context_line;
             }
           else if (original_lines > 0 && c == del)
             {
@@ -686,6 +741,7 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
                 trailing_context = 0;
 
               original_lines--;
+              last_line_type = original_line;
             }
           else if (modified_lines > 0 && c == add)
             {
@@ -699,13 +755,26 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
                 trailing_context = 0;
 
               modified_lines--;
+              last_line_type = modified_line;
             }
           else
             {
-              /* The start of the current line marks the first byte
-               * after the hunk text. */
-              end = last_line;
+              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;
+                }
 
+              if (original_end == 0)
+                original_end = end;
+              if (modified_end == 0)
+                modified_end = end;
               break; /* Hunk was empty or has been read. */
             }
         }
@@ -785,10 +854,10 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
       (*hunk)->diff_text_range.end = end;
       (*hunk)->original_text_range.start = start;
       (*hunk)->original_text_range.current = start;
-      (*hunk)->original_text_range.end = end;
+      (*hunk)->original_text_range.end = original_end;
       (*hunk)->modified_text_range.start = start;
       (*hunk)->modified_text_range.current = start;
-      (*hunk)->modified_text_range.end = end;
+      (*hunk)->modified_text_range.end = modified_end;
     }
   else
     /* Something went wrong, just discard the result. */

Modified: subversion/branches/svn-bisect/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_fs/fs-loader.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_fs/fs-loader.c Mon Jul 30 06:39:28 2012
@@ -394,7 +394,9 @@ svn_error_t *
 svn_fs_verify(const char *path,
               svn_cancel_func_t cancel_func,
               void *cancel_baton,
-              apr_pool_t *pool) 
+              svn_revnum_t start,
+              svn_revnum_t end,
+              apr_pool_t *pool)
 {
   fs_library_vtable_t *vtable;
   svn_fs_t *fs;
@@ -404,7 +406,7 @@ svn_fs_verify(const char *path,
 
   SVN_MUTEX__WITH_LOCK(common_pool_lock,
                        vtable->verify_fs(fs, path, cancel_func, cancel_baton,
-                                         pool, common_pool));
+                                         start, end, pool, common_pool));
   return SVN_NO_ERROR;
 }
 
@@ -424,16 +426,72 @@ svn_fs_delete_fs(const char *path, apr_p
 }
 
 svn_error_t *
-svn_fs_hotcopy(const char *src_path, const char *dest_path,
-               svn_boolean_t clean, apr_pool_t *pool)
+svn_fs_hotcopy2(const char *src_path, const char *dst_path,
+                svn_boolean_t clean, svn_boolean_t incremental,
+                svn_cancel_func_t cancel_func, void *cancel_baton,
+                apr_pool_t *scratch_pool)
 {
   fs_library_vtable_t *vtable;
-  const char *fs_type;
+  const char *src_fs_type;
+  svn_fs_t *src_fs;
+  svn_fs_t *dst_fs;
+  const char *dst_fs_type;
+  svn_node_kind_t dst_kind;
+
+  if (strcmp(src_path, dst_path) == 0)
+    return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
+                             _("Hotcopy source and destination are equal"));
+
+  SVN_ERR(svn_fs_type(&src_fs_type, src_path, scratch_pool));
+  SVN_ERR(get_library_vtable(&vtable, src_fs_type, scratch_pool));
+  src_fs = fs_new(NULL, scratch_pool);
+  dst_fs = fs_new(NULL, scratch_pool);
+
+  SVN_ERR(svn_io_check_path(dst_path, &dst_kind, scratch_pool));
+  if (dst_kind == svn_node_file)
+    return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
+                             _("'%s' already exists and is a file"),
+                             svn_dirent_local_style(dst_path,
+                                                    scratch_pool));
+  if (dst_kind == svn_node_unknown)
+    return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
+                             _("'%s' already exists and has an unknown "
+                               "node kind"),
+                             svn_dirent_local_style(dst_path,
+                                                    scratch_pool));
+  if (dst_kind == svn_node_dir)
+    {
+      svn_node_kind_t type_file_kind;
+
+      SVN_ERR(svn_io_check_path(svn_dirent_join(dst_path,
+                                                FS_TYPE_FILENAME,
+                                                scratch_pool),
+                                &type_file_kind, scratch_pool));
+      if (type_file_kind != svn_node_none)
+        {
+          SVN_ERR(svn_fs_type(&dst_fs_type, dst_path, scratch_pool));
+          if (strcmp(src_fs_type, dst_fs_type) != 0)
+            return svn_error_createf(
+                     SVN_ERR_ILLEGAL_TARGET, NULL,
+                     _("The filesystem type of the hotcopy source "
+                       "('%s') does not match the filesystem "
+                       "type of the hotcopy destination ('%s')"),
+                     src_fs_type, dst_fs_type);
+        }
+    }
+
+  SVN_ERR(vtable->hotcopy(src_fs, dst_fs, src_path, dst_path, clean,
+                          incremental, cancel_func, cancel_baton,
+                          scratch_pool));
+  return svn_error_trace(write_fs_type(dst_path, src_fs_type, scratch_pool));
+}
 
-  SVN_ERR(svn_fs_type(&fs_type, src_path, pool));
-  SVN_ERR(get_library_vtable(&vtable, fs_type, pool));
-  SVN_ERR(vtable->hotcopy(src_path, dest_path, clean, pool));
-  return svn_error_trace(write_fs_type(dest_path, fs_type, pool));
+svn_error_t *
+svn_fs_hotcopy(const char *src_path, const char *dest_path,
+               svn_boolean_t clean, apr_pool_t *pool)
+{
+  return svn_error_trace(svn_fs_hotcopy2(src_path, dest_path, clean,
+                                         FALSE, NULL, NULL, pool));
 }
 
 svn_error_t *

Modified: subversion/branches/svn-bisect/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_fs/fs-loader.h?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_fs/fs-loader.h Mon Jul 30 06:39:28 2012
@@ -25,7 +25,7 @@
 #ifndef LIBSVN_FS_FS_H
 #define LIBSVN_FS_FS_H
 
-#include "svn_version.h"
+#include "svn_types.h"
 #include "svn_fs.h"
 
 #ifdef __cplusplus
@@ -90,11 +90,16 @@ typedef struct fs_library_vtable_t
   svn_error_t *(*verify_fs)(svn_fs_t *fs, const char *path,
                             /* ### notification? */
                             svn_cancel_func_t cancel_func, void *cancel_baton,
+                            svn_revnum_t start,
+                            svn_revnum_t end,
                             apr_pool_t *pool,
                             apr_pool_t *common_pool);
   svn_error_t *(*delete_fs)(const char *path, apr_pool_t *pool);
-  svn_error_t *(*hotcopy)(const char *src_path, const char *dest_path,
-                          svn_boolean_t clean, apr_pool_t *pool);
+  svn_error_t *(*hotcopy)(svn_fs_t *src_fs, svn_fs_t *dst_fs,
+                          const char *src_path, const char *dst_path,
+                          svn_boolean_t clean, svn_boolean_t incremental,
+                          svn_cancel_func_t cancel_func, void *cancel_baton,
+                          apr_pool_t *pool);
   const char *(*get_description)(void);
   svn_error_t *(*recover)(svn_fs_t *fs,
                           svn_cancel_func_t cancel_func, void *cancel_baton,

Modified: subversion/branches/svn-bisect/subversion/libsvn_fs_base/bdb/env.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_fs_base/bdb/env.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_fs_base/bdb/env.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_fs_base/bdb/env.c Mon Jul 30 06:39:28 2012
@@ -226,7 +226,7 @@ bdb_error_gatherer(const DB_ENV *dbenv, 
 
   SVN_BDB_ERROR_GATHERER_IGNORE(dbenv);
 
-  new_err = svn_error_createf(SVN_NO_ERROR, NULL, "bdb: %s", msg);
+  new_err = svn_error_createf(APR_SUCCESS, NULL, "bdb: %s", msg);
   if (error_info->pending_errors)
     svn_error_compose(error_info->pending_errors, new_err);
   else

Modified: subversion/branches/svn-bisect/subversion/libsvn_fs_base/bdb/locks-table.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_fs_base/bdb/locks-table.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_fs_base/bdb/locks-table.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_fs_base/bdb/locks-table.c Mon Jul 30 06:39:28 2012
@@ -207,6 +207,7 @@ svn_fs_bdb__locks_get(svn_fs_t *fs,
   svn_lock_t *lock;
   svn_error_t *err;
   const char *lookup_path = path;
+  apr_size_t lookup_len;
 
   /* First, try to lookup PATH itself. */
   err = svn_fs_bdb__lock_token_get(&lock_token, fs, path, trail, pool);
@@ -224,7 +225,12 @@ svn_fs_bdb__locks_get(svn_fs_t *fs,
     {
       SVN_ERR(get_lock(&lock, fs, path, lock_token, trail, pool));
       if (lock && get_locks_func)
-        SVN_ERR(get_locks_func(get_locks_baton, lock, pool));
+        {
+          SVN_ERR(get_locks_func(get_locks_baton, lock, pool));
+
+          /* Found a lock so PATH is a file and we can ignore depth */
+          return SVN_NO_ERROR;
+        }
     }
 
   /* If we're only looking at PATH itself (depth = empty), stop here. */
@@ -250,11 +256,13 @@ svn_fs_bdb__locks_get(svn_fs_t *fs,
 
   if (!svn_fspath__is_root(path, strlen(path)))
     lookup_path = apr_pstrcat(pool, path, "/", (char *)NULL);
+  lookup_len = strlen(lookup_path);
 
   /* As long as the prefix of the returned KEY matches LOOKUP_PATH we
      know it is either LOOKUP_PATH or a decendant thereof.  */
   while ((! db_err)
-         && strncmp(lookup_path, key.data, strlen(lookup_path)) == 0)
+         && lookup_len < key.size
+         && strncmp(lookup_path, key.data, lookup_len) == 0)
     {
       const char *child_path;
 

Modified: subversion/branches/svn-bisect/subversion/libsvn_fs_base/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_fs_base/fs.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_fs_base/fs.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_fs_base/fs.c Mon Jul 30 06:39:28 2012
@@ -876,6 +876,8 @@ static svn_error_t *
 base_verify(svn_fs_t *fs, const char *path,
             svn_cancel_func_t cancel_func,
             void *cancel_baton,
+            svn_revnum_t start,
+            svn_revnum_t end,
             apr_pool_t *pool,
             apr_pool_t *common_pool)
 {
@@ -1165,9 +1167,14 @@ copy_db_file_safely(const char *src_dir,
 
 
 static svn_error_t *
-base_hotcopy(const char *src_path,
+base_hotcopy(svn_fs_t *src_fs,
+             svn_fs_t *dst_fs,
+             const char *src_path,
              const char *dest_path,
              svn_boolean_t clean_logs,
+             svn_boolean_t incremental,
+             svn_cancel_func_t cancel_func,
+             void *cancel_baton,
              apr_pool_t *pool)
 {
   svn_error_t *err;
@@ -1175,6 +1182,11 @@ base_hotcopy(const char *src_path,
   svn_boolean_t log_autoremove = FALSE;
   int format;
 
+  if (incremental)
+    return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+                             _("BDB repositories do not support incremental "
+                               "hotcopy"));
+
   /* Check the FS format number to be certain that we know how to
      hotcopy this FS.  Pre-1.2 filesystems did not have a format file (you
      could say they were format "0"), so we will error here.  This is not

Modified: subversion/branches/svn-bisect/subversion/libsvn_fs_base/id.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_fs_base/id.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_fs_base/id.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_fs_base/id.c Mon Jul 30 06:39:28 2012
@@ -168,7 +168,7 @@ svn_fs_base__id_parse(const char *data,
 {
   svn_fs_id_t *id;
   id_private_t *pvt;
-  char *data_copy, *str, *last_str;
+  char *data_copy, *str;
 
   /* Dup the ID data into POOL.  Our returned ID will have references
      into this memory. */
@@ -181,24 +181,25 @@ svn_fs_base__id_parse(const char *data,
   id->fsap_data = pvt;
 
   /* Now, we basically just need to "split" this data on `.'
-     characters.  We will use apr_strtok, which will put terminators
-     where each of the '.'s used to be.  Then our new id field will
-     reference string locations inside our duplicate string.*/
+     characters.  We will use svn_cstring_tokenize, which will put
+     terminators where each of the '.'s used to be.  Then our new
+     id field will reference string locations inside our duplicate
+     string.*/
 
   /* Node Id */
-  str = apr_strtok(data_copy, ".", &last_str);
+  str = svn_cstring_tokenize(".", &data_copy);
   if (str == NULL)
     return NULL;
   pvt->node_id = str;
 
   /* Copy Id */
-  str = apr_strtok(NULL, ".", &last_str);
+  str = svn_cstring_tokenize(".", &data_copy);
   if (str == NULL)
     return NULL;
   pvt->copy_id = str;
 
   /* Txn Id */
-  str = apr_strtok(NULL, ".", &last_str);
+  str = svn_cstring_tokenize(".", &data_copy);
   if (str == NULL)
     return NULL;
   pvt->txn_id = str;

Modified: subversion/branches/svn-bisect/subversion/libsvn_fs_base/notes/structure
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_fs_base/notes/structure?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_fs_base/notes/structure (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_fs_base/notes/structure Mon Jul 30 06:39:28 2012
@@ -104,8 +104,8 @@ structure summary" section of this docum
 NODE-REVISION: how we represent a node revision
 
 We represent a given revision of a file or directory node using a list
-skel (see skel.h for an explanation of skels).  A node revision skel
-has the form:
+skel (see include/private/svn_skel.h for an explanation of skels).
+A node revision skel has the form:
 
     (HEADER PROP-KEY KIND-SPECIFIC ...)
 

Modified: subversion/branches/svn-bisect/subversion/libsvn_fs_base/reps-strings.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_fs_base/reps-strings.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_fs_base/reps-strings.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_fs_base/reps-strings.c Mon Jul 30 06:39:28 2012
@@ -489,8 +489,7 @@ rep_read_range(svn_fs_t *fs,
           /* Make a list of all the rep's we need to undeltify this range.
              We'll have to read them within this trail anyway, so we might
              as well do it once and up front. */
-          apr_array_header_t *reps =  /* ### what constant here? */
-            apr_array_make(pool, 666, sizeof(rep));
+          apr_array_header_t *reps = apr_array_make(pool, 30, sizeof(rep));
           do
             {
               const rep_delta_chunk_t *const first_chunk
@@ -674,8 +673,10 @@ struct rep_read_baton
      is digestified. */
   svn_boolean_t checksum_finalized;
 
-  /* Used for temporary allocations, iff `trail' (above) is null.  */
-  apr_pool_t *pool;
+  /* Used for temporary allocations.  This pool is cleared at the
+     start of each invocation of the relevant stream read function --
+     see rep_read_contents().  */
+  apr_pool_t *scratch_pool;
 
 };
 
@@ -703,7 +704,7 @@ rep_read_get_baton(struct rep_read_baton
   b->checksum_finalized = FALSE;
   b->fs = fs;
   b->trail = use_trail_for_reads ? trail : NULL;
-  b->pool = pool;
+  b->scratch_pool = svn_pool_create(pool);
   b->rep_key = rep_key;
   b->offset = 0;
 
@@ -869,7 +870,7 @@ txn_body_read_rep(void *baton, trail_t *
                              args->buf,
                              args->len,
                              trail,
-                             trail->pool));
+                             args->rb->scratch_pool));
 
       args->rb->offset += *(args->len);
 
@@ -956,6 +957,9 @@ rep_read_contents(void *baton, char *buf
   struct rep_read_baton *rb = baton;
   struct read_rep_args args;
 
+  /* Clear the scratch pool of the results of previous invocations. */
+  svn_pool_clear(rb->scratch_pool);
+
   args.rb = rb;
   args.buf = buf;
   args.len = len;
@@ -974,7 +978,7 @@ rep_read_contents(void *baton, char *buf
                                      txn_body_read_rep,
                                      &args,
                                      TRUE,
-                                     rb->pool));
+                                     rb->scratch_pool));
     }
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/svn-bisect/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_fs_fs/caching.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_fs_fs/caching.c Mon Jul 30 06:39:28 2012
@@ -219,7 +219,7 @@ create_cache(svn_cache__t **cache_p,
       {
         SVN_ERR(svn_cache__create_membuffer_cache(
                   cache_p, membuffer, serializer, deserializer,
-                  klen, prefix, pool));
+                  klen, prefix, FALSE, pool));
       }
     else if (pages)
       {
@@ -360,6 +360,27 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
 
   SVN_ERR(init_callbacks(ffd->txdelta_window_cache, fs, no_handler, pool));
 
+  /* initialize txdelta window cache, if that has been enabled */
+  if (cache_txdeltas)
+    {
+      SVN_ERR(create_cache(&(ffd->combined_window_cache),
+                           NULL,
+                           membuffer,
+                           0, 0, /* Do not use inprocess cache */
+                           /* Values are svn_stringbuf_t */
+                           NULL, NULL,
+                           APR_HASH_KEY_STRING,
+                           apr_pstrcat(pool, prefix, "COMBINED_WINDOW",
+                                       (char *)NULL),
+                           fs->pool));
+    }
+  else
+    {
+      ffd->combined_window_cache = NULL;
+    }
+
+  SVN_ERR(init_callbacks(ffd->combined_window_cache, fs, no_handler, pool));
+
   /* initialize node revision cache, if caching has been enabled */
   SVN_ERR(create_cache(&(ffd->node_revision_cache),
                        NULL,

Modified: subversion/branches/svn-bisect/subversion/libsvn_fs_fs/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_fs_fs/dag.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_fs_fs/dag.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_fs_fs/dag.c Mon Jul 30 06:39:28 2012
@@ -449,7 +449,7 @@ svn_fs_fs__dag_dir_entry(svn_fs_dirent_t
 
   /* Get a dirent hash for this directory. */
   return svn_fs_fs__rep_contents_dir_entry(dirent, node->fs,
-                                           noderev, name, pool);
+                                           noderev, name, pool, pool);
 }
 
 

Modified: subversion/branches/svn-bisect/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_fs_fs/fs.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_fs_fs/fs.c Mon Jul 30 06:39:28 2012
@@ -243,6 +243,8 @@ static svn_error_t *
 fs_verify(svn_fs_t *fs, const char *path,
           svn_cancel_func_t cancel_func,
           void *cancel_baton,
+          svn_revnum_t start,
+          svn_revnum_t end,
           apr_pool_t *pool,
           apr_pool_t *common_pool)
 {
@@ -251,7 +253,7 @@ fs_verify(svn_fs_t *fs, const char *path
   SVN_ERR(svn_fs_fs__open(fs, path, pool));
   SVN_ERR(svn_fs_fs__initialize_caches(fs, pool));
   SVN_ERR(fs_serialized_init(fs, common_pool, pool));
-  return svn_fs_fs__verify(fs, cancel_func, cancel_baton, pool);
+  return svn_fs_fs__verify(fs, cancel_func, cancel_baton, start, end, pool);
 }
 
 static svn_error_t *
@@ -276,16 +278,28 @@ fs_pack(svn_fs_t *fs,
 
 
 /* This implements the fs_library_vtable_t.hotcopy() API.  Copy a
-   possibly live Subversion filesystem from SRC_PATH to DEST_PATH.
+   possibly live Subversion filesystem SRC_FS from SRC_PATH to a
+   DST_FS at DEST_PATH. If INCREMENTAL is TRUE, make an effort not to
+   re-copy data which already exists in DST_FS.
    The CLEAN_LOGS argument is ignored and included for Subversion
    1.0.x compatibility.  Perform all temporary allocations in POOL. */
 static svn_error_t *
-fs_hotcopy(const char *src_path,
-           const char *dest_path,
+fs_hotcopy(svn_fs_t *src_fs,
+           svn_fs_t *dst_fs,
+           const char *src_path,
+           const char *dst_path,
            svn_boolean_t clean_logs,
+           svn_boolean_t incremental,
+           svn_cancel_func_t cancel_func,
+           void *cancel_baton,
            apr_pool_t *pool)
 {
-  return svn_fs_fs__hotcopy(src_path, dest_path, pool);
+  SVN_ERR(initialize_fs_struct(src_fs));
+  SVN_ERR(fs_serialized_init(src_fs, pool, pool));
+  SVN_ERR(initialize_fs_struct(dst_fs));
+  SVN_ERR(fs_serialized_init(dst_fs, pool, pool));
+  return svn_fs_fs__hotcopy(src_fs, dst_fs, src_path, dst_path,
+                            incremental, cancel_func, cancel_baton, pool);
 }
 
 

Modified: subversion/branches/svn-bisect/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_fs_fs/fs.h?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_fs_fs/fs.h Mon Jul 30 06:39:28 2012
@@ -224,15 +224,17 @@ typedef struct fs_fs_data_t
      (svn_fs_id_t *).  (Not threadsafe.) */
   svn_cache__t *rev_root_id_cache;
 
-  /* DAG node cache for immutable nodes */
+  /* DAG node cache for immutable nodes.  Maps (revision, fspath)
+     to (dag_node_t *). */
   svn_cache__t *rev_node_cache;
 
   /* A cache of the contents of immutable directories; maps from
-     unparsed FS ID to ###x. */
+     unparsed FS ID to a apr_hash_t * mapping (const char *) dirent
+     names to (svn_fs_dirent_t *). */
   svn_cache__t *dir_cache;
 
   /* Fulltext cache; currently only used with memcached.  Maps from
-     rep key to svn_string_t. */
+     rep key (revision/offset) to svn_string_t. */
   svn_cache__t *fulltext_cache;
 
   /* Pack manifest cache; a cache mapping (svn_revnum_t) shard number to
@@ -244,6 +246,10 @@ typedef struct fs_fs_data_t
   /* Cache for txdelta_window_t objects; the key is (revFilePath, offset) */
   svn_cache__t *txdelta_window_cache;
 
+  /* Cache for combined windows as svn_stringbuf_t objects; 
+     the key is (revFilePath, offset) */
+  svn_cache__t *combined_window_cache;
+
   /* Cache for node_revision_t objects; the key is (revision, id offset) */
   svn_cache__t *node_revision_cache;