subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ar...@apache.org
Subject svn commit: r1204374 [11/29] - in /subversion/branches/svn-bisect: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ contrib/client-side/ contrib/client-side/emacs/ notes/ notes/wc-ng/ subversion/bindings/javahl/native...
Date Mon, 21 Nov 2011 07:08:07 GMT
Modified: subversion/branches/svn-bisect/subversion/libsvn_delta/compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_delta/compat.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_delta/compat.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_delta/compat.c Mon Nov 21 07:07:56 2011
@@ -21,11 +21,15 @@
  * ====================================================================
  */
 
-#include <apr_pools.h>
-
 #include "svn_types.h"
 #include "svn_error.h"
 #include "svn_delta.h"
+#include "svn_sorts.h"
+#include "svn_dirent_uri.h"
+#include "svn_path.h"
+#include "svn_hash.h"
+#include "svn_props.h"
+#include "svn_pools.h"
 
 
 struct file_rev_handler_wrapper_baton {
@@ -76,3 +80,1346 @@ svn_compat_wrap_file_rev_handler(svn_fil
   *handler2_baton = fwb;
   *handler2 = file_rev_handler_wrapper;
 }
+
+
+/* The following code maps the calls to a traditional delta editor to an
+ * Editorv2 editor.  It does this by keeping track of a lot of state, and
+ * then communicating that state to Ev2 upon closure of the file or dir (or
+ * edit).  Note that Ev2 calls add_symlink() and set_target() are not present
+ * in the delta editor paradigm, so we never call them.
+ *
+ * The general idea here is that we have to see *all* the actions on a node's
+ * parent before we can process that node, which means we need to buffer a
+ * large amount of information in the dir batons, and then process it in the
+ * close_directory() handler. */
+
+typedef svn_error_t *(*start_edit_func_t)(
+    void *baton,
+    svn_revnum_t base_revision,
+    apr_pool_t *result_pool,
+    void **root_baton);
+
+typedef svn_error_t *(*target_revision_func_t)(
+    void *baton,
+    svn_revnum_t target_revision,
+    apr_pool_t *scratch_pool);
+
+struct ev2_edit_baton
+{
+  svn_editor_t *editor;
+  apr_hash_t *paths;
+  apr_pool_t *edit_pool;
+
+  svn_boolean_t *found_abs_paths; /* Did we strip an incoming '/' from the
+                                     paths?  */
+
+  void *root_baton;
+
+  start_edit_func_t start_edit;
+  void *start_edit_baton;
+
+  svn_delta_fetch_props_func_t fetch_props_func;
+  void *fetch_props_baton;
+
+  target_revision_func_t target_revision_func;
+  void *target_revision_baton;
+};
+
+struct ev2_dir_baton
+{
+  struct ev2_edit_baton *eb;
+  const char *path;
+};
+
+struct ev2_file_baton
+{
+  struct ev2_edit_baton *eb;
+  const char *path;
+};
+
+enum action_code_t
+{
+  ACTION_MOVE,
+  ACTION_MKDIR,
+  ACTION_COPY,
+  ACTION_PROPSET,
+  ACTION_PUT,
+  ACTION_ADD,
+  ACTION_DELETE
+};
+
+struct path_action
+{
+  enum action_code_t action;
+  void *args;
+};
+
+struct prop_args
+{
+  const char *name;
+  const svn_string_t *value;
+};
+
+struct copy_args
+{
+  const char *copyfrom_path;
+  svn_revnum_t copyfrom_rev;
+};
+
+static svn_error_t *
+add_action(struct ev2_edit_baton *eb,
+           const char *path,
+           enum action_code_t action,
+           void *args)
+{
+  struct path_action *p_action;
+  apr_array_header_t *action_list = apr_hash_get(eb->paths, path,
+                                                 APR_HASH_KEY_STRING);
+
+  p_action = apr_palloc(eb->edit_pool, sizeof(*p_action));
+  p_action->action = action;
+  p_action->args = args;
+
+  if (action_list == NULL)
+    {
+      action_list = apr_array_make(eb->edit_pool, 1,
+                                   sizeof(struct path_action *));
+      apr_hash_set(eb->paths, apr_pstrdup(eb->edit_pool, path),
+                   APR_HASH_KEY_STRING, action_list);
+    }
+
+  APR_ARRAY_PUSH(action_list, struct path_action *) = p_action;
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+process_actions(void *edit_baton,
+                const char *path,
+                apr_array_header_t *actions,
+                apr_pool_t *scratch_pool)
+{
+  struct ev2_edit_baton *eb = edit_baton;
+  apr_hash_t *props = NULL;
+  svn_boolean_t need_add = FALSE;
+  apr_array_header_t *children;
+  svn_stream_t *contents;
+  svn_kind_t kind;
+  int i;
+
+  if (*path == '/')
+    {
+      path++;
+      *eb->found_abs_paths = TRUE;
+    }
+
+  /* Go through all of our actions, populating various datastructures
+   * dependent on them. */
+  for (i = 0; i < actions->nelts; i++)
+    {
+      const struct path_action *action = APR_ARRAY_IDX(actions, i,
+                                                       struct path_action *);
+
+      switch (action->action)
+        {
+          case ACTION_PROPSET:
+            {
+              const struct prop_args *p_args = action->args;
+
+              if (!props)
+                {
+                  /* Fetch the original props. We can then apply each of
+                     the modifications to it.  */
+                  SVN_ERR(eb->fetch_props_func(&props,
+                                               eb->fetch_props_baton,
+                                               path,
+                                               scratch_pool, scratch_pool));
+                }
+
+              /* Note that p_args->value may be NULL.  */
+              apr_hash_set(props, p_args->name, APR_HASH_KEY_STRING,
+                           p_args->value);
+              break;
+            }
+
+          case ACTION_DELETE:
+            {
+              svn_revnum_t *revnum = action->args;
+
+              /* If we get a delete, we'd better not have gotten any
+                 other actions for this path later, so we can go ahead
+                 and call our handler. */
+              SVN_ERR(svn_editor_delete(eb->editor, path, *revnum));
+              break;
+            }
+
+          case ACTION_ADD:
+            {
+              kind = *((svn_kind_t *) action->args);
+              need_add = TRUE;
+
+              if (kind == svn_kind_dir)
+                {
+                  children = apr_array_make(scratch_pool, 1,
+                                            sizeof(const char *));
+                }
+              else
+                {
+                  /* ### Someday, we'll need the real contents here. */
+                  contents = svn_stream_empty(scratch_pool);
+                }
+              break;
+            }
+
+          case ACTION_COPY:
+            {
+              struct copy_args *c_args = action->args;
+
+              SVN_ERR(svn_editor_copy(eb->editor, c_args->copyfrom_path,
+                                      c_args->copyfrom_rev, path,
+                                      SVN_INVALID_REVNUM));
+              break;
+            }
+
+          default:
+            SVN_ERR_MALFUNCTION();
+        }
+    }
+
+  /* We've now got a wholistic view of what has happened to this node,
+   * so we can call our own editor APIs on it. */
+
+  if (need_add)
+    {
+      if (kind == svn_kind_dir)
+        {
+          SVN_ERR(svn_editor_add_directory(eb->editor, path, children,
+                                           props, SVN_INVALID_REVNUM));
+        }
+      else
+        {
+          SVN_ERR(svn_editor_add_file(eb->editor, path, NULL, contents,
+                                      props, SVN_INVALID_REVNUM));
+        }
+    }
+  else
+    {
+      if (props)
+        {
+          /* We fetched and modified the props in some way. Apply 'em now that
+             we have the new set.  */
+          SVN_ERR(svn_editor_set_props(eb->editor, path, SVN_INVALID_REVNUM,
+                                       props, TRUE));
+        }
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+run_ev2_actions(void *edit_baton,
+                apr_pool_t *scratch_pool)
+{
+  struct ev2_edit_baton *eb = edit_baton;
+  apr_array_header_t *sorted_hash;
+  apr_pool_t *iterpool;
+  int i;
+
+  /* Sort the paths touched by this edit.
+   * Ev2 doesn't really have any particular need for depth-first-ness, but
+   * we want to ensure all parent directories are handled before children in
+   * the case of adds (which does introduce an element of depth-first-ness). */
+  sorted_hash = svn_sort__hash(eb->paths, svn_sort_compare_items_as_paths,
+                               scratch_pool);
+
+  iterpool = svn_pool_create(scratch_pool);
+  for (i = 0; i < sorted_hash->nelts; i++)
+    {
+      svn_sort__item_t *item = &APR_ARRAY_IDX(sorted_hash, i, svn_sort__item_t);
+      apr_array_header_t *actions = item->value;
+      const char *path = item->key;
+
+      svn_pool_clear(iterpool);
+      SVN_ERR(process_actions(edit_baton, path, actions, iterpool));
+    }
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+ev2_set_target_revision(void *edit_baton,
+                        svn_revnum_t target_revision,
+                        apr_pool_t *scratch_pool)
+{
+  struct ev2_edit_baton *eb = edit_baton;
+
+  SVN_ERR(eb->target_revision_func(eb->target_revision_baton, target_revision,
+                                   scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+ev2_open_root(void *edit_baton,
+              svn_revnum_t base_revision,
+              apr_pool_t *result_pool,
+              void **root_baton)
+{
+  struct ev2_dir_baton *db = apr_palloc(result_pool, sizeof(*db));
+  struct ev2_edit_baton *eb = edit_baton;
+
+  db->eb = eb;
+  db->path = "";
+
+  *root_baton = db;
+
+  if (eb->start_edit)
+    SVN_ERR(eb->start_edit(eb->start_edit_baton, base_revision, result_pool,
+                           &eb->root_baton));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+ev2_delete_entry(const char *path,
+                 svn_revnum_t revision,
+                 void *parent_baton,
+                 apr_pool_t *scratch_pool)
+{
+  struct ev2_dir_baton *pb = parent_baton;
+  svn_revnum_t *revnum = apr_palloc(pb->eb->edit_pool, sizeof(*revnum));
+
+  *revnum = revision;
+  SVN_ERR(add_action(pb->eb, path, ACTION_DELETE, revnum));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+ev2_add_directory(const char *path,
+                  void *parent_baton,
+                  const char *copyfrom_path,
+                  svn_revnum_t copyfrom_revision,
+                  apr_pool_t *result_pool,
+                  void **child_baton)
+{
+  struct ev2_dir_baton *pb = parent_baton;
+  struct ev2_dir_baton *cb = apr_palloc(result_pool, sizeof(*cb));
+
+  cb->eb = pb->eb;
+  cb->path = apr_pstrdup(result_pool, path);
+  *child_baton = cb;
+
+  if (!copyfrom_path)
+    {
+      /* A simple add. */
+      svn_kind_t *kind = apr_palloc(pb->eb->edit_pool, sizeof(*kind));
+
+      *kind = svn_kind_dir;
+      SVN_ERR(add_action(pb->eb, path, ACTION_ADD, kind));
+    }
+  else
+    {
+      /* A copy */
+      struct copy_args *args = apr_palloc(pb->eb->edit_pool, sizeof(*args));
+
+      args->copyfrom_path = apr_pstrdup(pb->eb->edit_pool, copyfrom_path);
+      args->copyfrom_rev = copyfrom_revision;
+      SVN_ERR(add_action(pb->eb, path, ACTION_COPY, args));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+ev2_open_directory(const char *path,
+                   void *parent_baton,
+                   svn_revnum_t base_revision,
+                   apr_pool_t *result_pool,
+                   void **child_baton)
+{
+  struct ev2_dir_baton *pb = parent_baton;
+  struct ev2_dir_baton *db = apr_palloc(result_pool, sizeof(*db));
+
+  db->eb = pb->eb;
+  db->path = apr_pstrdup(result_pool, path);
+
+  *child_baton = db;
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+ev2_change_dir_prop(void *dir_baton,
+                    const char *name,
+                    const svn_string_t *value,
+                    apr_pool_t *scratch_pool)
+{
+  struct ev2_dir_baton *db = dir_baton;
+  struct prop_args *p_args = apr_palloc(db->eb->edit_pool, sizeof(*p_args));
+
+  p_args->name = apr_pstrdup(db->eb->edit_pool, name);
+  p_args->value = value ? svn_string_dup(value, db->eb->edit_pool) : NULL;
+
+  SVN_ERR(add_action(db->eb, db->path, ACTION_PROPSET, p_args));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+ev2_close_directory(void *dir_baton,
+                    apr_pool_t *scratch_pool)
+{
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+ev2_absent_directory(const char *path,
+                     void *parent_baton,
+                     apr_pool_t *scratch_pool)
+{
+  struct ev2_dir_baton *pb = parent_baton;
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+ev2_add_file(const char *path,
+             void *parent_baton,
+             const char *copyfrom_path,
+             svn_revnum_t copyfrom_revision,
+             apr_pool_t *result_pool,
+             void **file_baton)
+{
+  struct ev2_file_baton *fb = apr_palloc(result_pool, sizeof(*fb));
+  struct ev2_dir_baton *pb = parent_baton;
+
+  fb->eb = pb->eb;
+  fb->path = apr_pstrdup(result_pool, path);
+  *file_baton = fb;
+
+  if (!copyfrom_path)
+    {
+      /* A simple add. */
+      svn_kind_t *kind = apr_palloc(pb->eb->edit_pool, sizeof(*kind));
+
+      *kind = svn_kind_file;
+      SVN_ERR(add_action(pb->eb, path, ACTION_ADD, kind));
+    }
+  else
+    {
+      /* A copy */
+      struct copy_args *args = apr_palloc(pb->eb->edit_pool, sizeof(*args));
+
+      args->copyfrom_path = apr_pstrdup(pb->eb->edit_pool, copyfrom_path);
+      args->copyfrom_rev = copyfrom_revision;
+      SVN_ERR(add_action(pb->eb, path, ACTION_COPY, args));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+ev2_open_file(const char *path,
+              void *parent_baton,
+              svn_revnum_t base_revision,
+              apr_pool_t *result_pool,
+              void **file_baton)
+{
+  struct ev2_file_baton *fb = apr_palloc(result_pool, sizeof(*fb));
+  struct ev2_dir_baton *pb = parent_baton;
+
+  fb->eb = pb->eb;
+  fb->path = apr_pstrdup(result_pool, path);
+
+  *file_baton = fb;
+  return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+ev2_apply_textdelta(void *file_baton,
+                    const char *base_checksum,
+                    apr_pool_t *result_pool,
+                    svn_txdelta_window_handler_t *handler,
+                    void **handler_baton)
+{
+  struct ev2_file_baton *fb = file_baton;
+
+  *handler_baton = NULL;
+  *handler = svn_delta_noop_window_handler;
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+ev2_change_file_prop(void *file_baton,
+                     const char *name,
+                     const svn_string_t *value,
+                     apr_pool_t *scratch_pool)
+{
+  struct ev2_file_baton *fb = file_baton;
+  struct prop_args *p_args = apr_palloc(fb->eb->edit_pool, sizeof(*p_args));
+
+  p_args->name = apr_pstrdup(fb->eb->edit_pool, name);
+  p_args->value = value ? svn_string_dup(value, fb->eb->edit_pool) : NULL;
+
+  SVN_ERR(add_action(fb->eb, fb->path, ACTION_PROPSET, p_args));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+ev2_close_file(void *file_baton,
+               const char *text_checksum,
+               apr_pool_t *scratch_pool)
+{
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+ev2_absent_file(const char *path,
+                void *parent_baton,
+                apr_pool_t *scratch_pool)
+{
+  struct ev2_dir_baton *pb = parent_baton;
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+ev2_close_edit(void *edit_baton,
+               apr_pool_t *scratch_pool)
+{
+  struct ev2_edit_baton *eb = edit_baton;
+
+  SVN_ERR(run_ev2_actions(edit_baton, scratch_pool));
+  return svn_error_trace(svn_editor_complete(eb->editor));
+}
+
+static svn_error_t *
+ev2_abort_edit(void *edit_baton,
+               apr_pool_t *scratch_pool)
+{
+  struct ev2_edit_baton *eb = edit_baton;
+
+  SVN_ERR(run_ev2_actions(edit_baton, scratch_pool));
+  return svn_error_trace(svn_editor_abort(eb->editor));
+}
+
+struct start_edit_baton
+{
+  const svn_delta_editor_t *deditor;
+  void *dedit_baton;
+};
+
+static svn_error_t *
+start_edit_func(void *baton,
+                svn_revnum_t base_revision,
+                apr_pool_t *result_pool,
+                void **root_baton)
+{
+  struct start_edit_baton *seb = baton;
+
+  SVN_ERR(seb->deditor->open_root(seb->dedit_baton, base_revision, result_pool,
+                                  root_baton));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+target_revision_func(void *baton,
+                     svn_revnum_t target_revision,
+                     apr_pool_t *scratch_pool)
+{
+  struct start_edit_baton *seb = baton;
+
+  SVN_ERR(seb->deditor->set_target_revision(seb->dedit_baton, target_revision,
+                                            scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+delta_from_editor(const svn_delta_editor_t **deditor,
+                  void **dedit_baton,
+                  svn_editor_t *editor,
+                  svn_boolean_t *found_abs_paths,
+                  svn_delta_fetch_props_func_t fetch_props_func,
+                  void *fetch_props_baton,
+                  start_edit_func_t start_edit,
+                  void *start_edit_baton,
+                  target_revision_func_t target_revision,
+                  void *target_revision_baton,
+                  apr_pool_t *pool)
+{
+  /* Static 'cause we don't want it to be on the stack. */
+  static svn_delta_editor_t delta_editor = {
+      ev2_set_target_revision,
+      ev2_open_root,
+      ev2_delete_entry,
+      ev2_add_directory,
+      ev2_open_directory,
+      ev2_change_dir_prop,
+      ev2_close_directory,
+      ev2_absent_directory,
+      ev2_add_file,
+      ev2_open_file,
+      ev2_apply_textdelta,
+      ev2_change_file_prop,
+      ev2_close_file,
+      ev2_absent_file,
+      ev2_close_edit,
+      ev2_abort_edit
+    };
+  struct ev2_edit_baton *eb = apr_pcalloc(pool, sizeof(*eb));
+
+  eb->editor = editor;
+  eb->paths = apr_hash_make(pool);
+  eb->edit_pool = pool;
+  eb->found_abs_paths = found_abs_paths;
+
+  eb->fetch_props_func = fetch_props_func;
+  eb->fetch_props_baton = fetch_props_baton;
+
+  eb->start_edit = start_edit;
+  eb->start_edit_baton = start_edit_baton;
+
+  eb->target_revision_func = target_revision;
+  eb->target_revision_baton = target_revision_baton;
+
+  *dedit_baton = eb;
+  *deditor = &delta_editor;
+
+  return SVN_NO_ERROR;
+}
+
+
+
+
+
+struct operation {
+  enum {
+    OP_OPEN,
+    OP_DELETE,
+    OP_ADD,
+    OP_REPLACE,
+    OP_PROPSET           /* only for files for which no other operation is
+                            occuring; directories are OP_OPEN with non-empty
+                            props */
+  } operation;
+  svn_kind_t kind;  /* to copy, mkdir, put or set revprops */
+  svn_revnum_t copyfrom_revision;      /* to copy, valid for add and replace */
+  const char *copyfrom_url;       /* to copy, valid for add and replace */
+  const char *src_file;  /* for put, the source file for contents */
+  apr_hash_t *children;  /* const char *path -> struct operation * */
+  apr_hash_t *prop_mods; /* const char *prop_name ->
+                            const svn_string_t *prop_value */
+  apr_array_header_t *prop_dels; /* const char *prop_name deletions */
+  void *baton;           /* as returned by the commit editor */
+};
+
+struct editor_baton
+{
+  const svn_delta_editor_t *deditor;
+  void *dedit_baton;
+
+  svn_delta_fetch_kind_func_t fetch_kind_func;
+  void *fetch_kind_baton;
+
+  svn_delta_fetch_props_func_t fetch_props_func;
+  void *fetch_props_baton;
+
+  struct operation root;
+  svn_boolean_t root_opened;
+  svn_boolean_t *make_abs_paths;
+
+  apr_hash_t *paths;
+  apr_pool_t *edit_pool;
+};
+
+
+/* Find the operation associated with PATH, which is a single-path
+   component representing a child of the path represented by
+   OPERATION.  If no such child operation exists, create a new one of
+   type OP_OPEN. */
+static struct operation *
+get_operation(const char *path,
+              struct operation *operation,
+              apr_pool_t *result_pool)
+{
+  struct operation *child = apr_hash_get(operation->children, path,
+                                         APR_HASH_KEY_STRING);
+  if (! child)
+    {
+      child = apr_pcalloc(result_pool, sizeof(*child));
+      child->children = apr_hash_make(result_pool);
+      child->operation = OP_OPEN;
+      child->copyfrom_revision = SVN_INVALID_REVNUM;
+      child->kind = svn_kind_dir;
+      child->prop_mods = apr_hash_make(result_pool);
+      child->prop_dels = apr_array_make(result_pool, 1, sizeof(const char *));
+      apr_hash_set(operation->children, apr_pstrdup(result_pool, path),
+                   APR_HASH_KEY_STRING, child);
+    }
+  return child;
+}
+
+/* Add PATH to the operations tree rooted at OPERATION, creating any
+   intermediate nodes that are required.  Here's what's expected for
+   each action type:
+
+      ACTION          URL    REV      SRC-FILE  PROPNAME
+      ------------    -----  -------  --------  --------
+      ACTION_MKDIR    NULL   invalid  NULL      NULL
+      ACTION_COPY     valid  valid    NULL      NULL
+      ACTION_PUT      NULL   invalid  valid     NULL
+      ACTION_DELETE   NULL   invalid  NULL      NULL
+      ACTION_PROPSET  valid  invalid  NULL      valid
+
+   Node type information is obtained for any copy source (to determine
+   whether to create a file or directory) and for any deleted path (to
+   ensure it exists since svn_delta_editor_t->delete_entry doesn't
+   return an error on non-existent nodes). */
+static svn_error_t *
+build(struct editor_baton *eb,
+      enum action_code_t action,
+      const char *relpath,
+      svn_kind_t kind,
+      const char *url,
+      svn_revnum_t rev,
+      apr_hash_t *props,
+      const char *src_file,
+      svn_revnum_t head,
+      apr_pool_t *scratch_pool)
+{
+  apr_array_header_t *path_bits = svn_path_decompose(relpath, scratch_pool);
+  const char *path_so_far = "";
+  struct operation *operation = &eb->root;
+  int i;
+
+  /* We should only see PROPS when action is ACTION_PROPSET. */
+  SVN_ERR_ASSERT((props && action == ACTION_PROPSET)
+                || (!props && action != ACTION_PROPSET) );
+
+  /* Look for any previous operations we've recognized for PATH.  If
+     any of PATH's ancestors have not yet been traversed, we'll be
+     creating OP_OPEN operations for them as we walk down PATH's path
+     components. */
+  for (i = 0; i < path_bits->nelts; ++i)
+    {
+      const char *path_bit = APR_ARRAY_IDX(path_bits, i, const char *);
+      path_so_far = svn_relpath_join(path_so_far, path_bit, scratch_pool);
+      operation = get_operation(path_so_far, operation, eb->edit_pool);
+    }
+
+  /* Handle property changes. */
+  if (props)
+    {
+      apr_hash_t *current_props;
+      apr_array_header_t *propdiffs;
+
+      SVN_ERR(eb->fetch_kind_func(&operation->kind, eb->fetch_kind_baton,
+                                  relpath, scratch_pool));
+      SVN_ERR(eb->fetch_props_func(&current_props, eb->fetch_props_baton,
+                                   relpath, scratch_pool, scratch_pool));
+
+      /* Use the edit pool, since most of the results will need to be
+         persisted. */
+      SVN_ERR(svn_prop_diffs(&propdiffs, props, current_props, eb->edit_pool));
+
+      for (i = 0; i < propdiffs->nelts; i++)
+        {
+          /* Note: the array returned by svn_prop_diffs() is an array of
+             actual structures, not pointers to them. */
+          svn_prop_t *prop = &APR_ARRAY_IDX(propdiffs, i, svn_prop_t);
+          if (!prop->value)
+            APR_ARRAY_PUSH(operation->prop_dels, const char *) = prop->name;
+          else
+            apr_hash_set(operation->prop_mods, prop->name, APR_HASH_KEY_STRING,
+                         prop->value);
+        }
+
+      /* If we're not adding this thing ourselves, check for existence.  */
+      if (! ((operation->operation == OP_ADD) ||
+             (operation->operation == OP_REPLACE)))
+        {
+          if ((operation->kind == svn_kind_file)
+                   && (operation->operation == OP_OPEN))
+            operation->operation = OP_PROPSET;
+        }
+      if (!operation->copyfrom_revision)
+        operation->copyfrom_revision = rev;
+      return SVN_NO_ERROR;
+    }
+
+  if (action == ACTION_DELETE)
+    operation->operation = OP_DELETE;
+
+  /* Handle copy operations (which can be adds or replacements). */
+  else if (action == ACTION_COPY)
+    {
+      operation->operation =
+        operation->operation == OP_DELETE ? OP_REPLACE : OP_ADD;
+
+      if (kind == svn_kind_none)
+        SVN_ERR(eb->fetch_kind_func(&operation->kind, eb->fetch_kind_baton,
+                                    relpath, scratch_pool));
+      else
+        operation->kind = kind;
+      operation->copyfrom_url = url;
+      operation->copyfrom_revision = rev;
+    }
+  /* Handle mkdir operations (which can be adds or replacements). */
+  else if (action == ACTION_MKDIR)
+    {
+      operation->operation =
+        operation->operation == OP_DELETE ? OP_REPLACE : OP_ADD;
+      operation->kind = svn_kind_dir;
+    }
+  /* Handle put operations (which can be adds, replacements, or opens). */
+  else if (action == ACTION_PUT)
+    {
+      if (operation->operation == OP_DELETE)
+        {
+          operation->operation = OP_REPLACE;
+        }
+      else
+        {
+          if (kind == svn_kind_file)
+            operation->operation = OP_OPEN;
+          else if (kind == svn_kind_none)
+            operation->operation = OP_ADD;
+          else
+            return svn_error_createf(SVN_ERR_BAD_URL, NULL,
+                                     "'%s' is not a file", relpath);
+        }
+      operation->kind = svn_kind_file;
+      operation->src_file = src_file;
+    }
+  else
+    {
+      /* We shouldn't get here. */
+      SVN_ERR_MALFUNCTION();
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+ensure_root_opened(struct editor_baton *eb)
+{
+  if (!eb->root_opened)
+    {
+      SVN_ERR(eb->deditor->open_root(eb->dedit_baton, SVN_INVALID_REVNUM,
+                                     eb->edit_pool, &eb->root.baton));
+      eb->root_opened = TRUE;
+    }
+
+  return SVN_NO_ERROR;
+}
+
+/* This implements svn_editor_cb_add_directory_t */
+static svn_error_t *
+add_directory_cb(void *baton,
+                 const char *relpath,
+                 const apr_array_header_t *children,
+                 apr_hash_t *props,
+                 svn_revnum_t replaces_rev,
+                 apr_pool_t *scratch_pool)
+{
+  struct editor_baton *eb = baton;
+
+  SVN_ERR(ensure_root_opened(eb));
+
+  SVN_ERR(build(eb, ACTION_MKDIR, relpath, svn_kind_dir,
+                NULL, SVN_INVALID_REVNUM,
+                NULL, NULL, SVN_INVALID_REVNUM, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+/* This implements svn_editor_cb_add_file_t */
+static svn_error_t *
+add_file_cb(void *baton,
+            const char *relpath,
+            const svn_checksum_t *checksum,
+            svn_stream_t *contents,
+            apr_hash_t *props,
+            svn_revnum_t replaces_rev,
+            apr_pool_t *scratch_pool)
+{
+  struct editor_baton *eb = baton;
+  const char *tmp_filename;
+  svn_stream_t *tmp_stream;
+
+  SVN_ERR(ensure_root_opened(eb));
+
+  /* Spool the contents to a tempfile, and provide that to the driver. */
+  SVN_ERR(svn_stream_open_unique(&tmp_stream, &tmp_filename, NULL,
+                                 svn_io_file_del_on_pool_cleanup,
+                                 eb->edit_pool, scratch_pool));
+  SVN_ERR(svn_stream_copy3(svn_stream_disown(contents, scratch_pool),
+                           tmp_stream, NULL, NULL, scratch_pool));
+
+  SVN_ERR(build(eb, ACTION_PUT, relpath, svn_kind_none,
+                NULL, SVN_INVALID_REVNUM,
+                NULL, tmp_filename, SVN_INVALID_REVNUM, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+/* This implements svn_editor_cb_add_symlink_t */
+static svn_error_t *
+add_symlink_cb(void *baton,
+               const char *relpath,
+               const char *target,
+               apr_hash_t *props,
+               svn_revnum_t replaces_rev,
+               apr_pool_t *scratch_pool)
+{
+  struct editor_baton *eb = baton;
+
+  SVN_ERR(ensure_root_opened(eb));
+
+  return SVN_NO_ERROR;
+}
+
+/* This implements svn_editor_cb_add_absent_t */
+static svn_error_t *
+add_absent_cb(void *baton,
+              const char *relpath,
+              svn_kind_t kind,
+              svn_revnum_t replaces_rev,
+              apr_pool_t *scratch_pool)
+{
+  struct editor_baton *eb = baton;
+
+  SVN_ERR(ensure_root_opened(eb));
+
+  return SVN_NO_ERROR;
+}
+
+/* This implements svn_editor_cb_set_props_t */
+static svn_error_t *
+set_props_cb(void *baton,
+             const char *relpath,
+             svn_revnum_t revision,
+             apr_hash_t *props,
+             svn_boolean_t complete,
+             apr_pool_t *scratch_pool)
+{
+  struct editor_baton *eb = baton;
+
+  SVN_ERR(ensure_root_opened(eb));
+
+  SVN_ERR(build(eb, ACTION_PROPSET, relpath, svn_kind_none,
+                NULL, SVN_INVALID_REVNUM,
+                props, NULL, SVN_INVALID_REVNUM, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+/* This implements svn_editor_cb_set_text_t */
+static svn_error_t *
+set_text_cb(void *baton,
+            const char *relpath,
+            svn_revnum_t revision,
+            const svn_checksum_t *checksum,
+            svn_stream_t *contents,
+            apr_pool_t *scratch_pool)
+{
+  struct editor_baton *eb = baton;
+  const char *tmp_filename;
+  svn_stream_t *tmp_stream;
+
+  SVN_ERR(ensure_root_opened(eb));
+
+  /* Spool the contents to a tempfile, and provide that to the driver. */
+  SVN_ERR(svn_stream_open_unique(&tmp_stream, &tmp_filename, NULL,
+                                 svn_io_file_del_on_pool_cleanup,
+                                 eb->edit_pool, scratch_pool));
+  SVN_ERR(svn_stream_copy3(svn_stream_disown(contents, scratch_pool),
+                           tmp_stream, NULL, NULL, scratch_pool));
+
+  SVN_ERR(build(eb, ACTION_PUT, relpath, svn_kind_file,
+                NULL, SVN_INVALID_REVNUM,
+                NULL, tmp_filename, SVN_INVALID_REVNUM, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+/* This implements svn_editor_cb_set_target_t */
+static svn_error_t *
+set_target_cb(void *baton,
+              const char *relpath,
+              svn_revnum_t revision,
+              const char *target,
+              apr_pool_t *scratch_pool)
+{
+  struct editor_baton *eb = baton;
+
+  SVN_ERR(ensure_root_opened(eb));
+
+  return SVN_NO_ERROR;
+}
+
+/* This implements svn_editor_cb_delete_t */
+static svn_error_t *
+delete_cb(void *baton,
+          const char *relpath,
+          svn_revnum_t revision,
+          apr_pool_t *scratch_pool)
+{
+  struct editor_baton *eb = baton;
+
+  SVN_ERR(ensure_root_opened(eb));
+
+  SVN_ERR(build(eb, ACTION_DELETE, relpath, svn_kind_unknown,
+                NULL, SVN_INVALID_REVNUM, NULL, NULL, SVN_INVALID_REVNUM,
+                scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+/* This implements svn_editor_cb_copy_t */
+static svn_error_t *
+copy_cb(void *baton,
+        const char *src_relpath,
+        svn_revnum_t src_revision,
+        const char *dst_relpath,
+        svn_revnum_t replaces_rev,
+        apr_pool_t *scratch_pool)
+{
+  struct editor_baton *eb = baton;
+
+  SVN_ERR(ensure_root_opened(eb));
+
+  SVN_ERR(build(eb, ACTION_COPY, dst_relpath, svn_kind_unknown,
+                src_relpath, src_revision, NULL, NULL, SVN_INVALID_REVNUM,
+                scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+/* This implements svn_editor_cb_move_t */
+static svn_error_t *
+move_cb(void *baton,
+        const char *src_relpath,
+        svn_revnum_t src_revision,
+        const char *dst_relpath,
+        svn_revnum_t replaces_rev,
+        apr_pool_t *scratch_pool)
+{
+  struct editor_baton *eb = baton;
+
+  SVN_ERR(ensure_root_opened(eb));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+change_props(const svn_delta_editor_t *editor,
+             void *baton,
+             struct operation *child,
+             apr_pool_t *scratch_pool)
+{
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+
+  if (child->prop_dels)
+    {
+      int i;
+      for (i = 0; i < child->prop_dels->nelts; i++)
+        {
+          const char *prop_name;
+
+          svn_pool_clear(iterpool);
+          prop_name = APR_ARRAY_IDX(child->prop_dels, i, const char *);
+          if (child->kind == svn_kind_dir)
+            SVN_ERR(editor->change_dir_prop(baton, prop_name,
+                                            NULL, iterpool));
+          else
+            SVN_ERR(editor->change_file_prop(baton, prop_name,
+                                             NULL, iterpool));
+        }
+    }
+
+  if (apr_hash_count(child->prop_mods))
+    {
+      apr_hash_index_t *hi;
+      for (hi = apr_hash_first(scratch_pool, child->prop_mods);
+           hi; hi = apr_hash_next(hi))
+        {
+          const char *name = svn__apr_hash_index_key(hi);
+          svn_string_t *val = svn__apr_hash_index_val(hi);
+
+          svn_pool_clear(iterpool);
+          if (child->kind == svn_kind_dir)
+            SVN_ERR(editor->change_dir_prop(baton, name, val, iterpool));
+          else
+            SVN_ERR(editor->change_file_prop(baton, name, val, iterpool));
+        }
+    }
+
+  svn_pool_destroy(iterpool);
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+drive(const struct operation *operation,
+      const svn_delta_editor_t *editor,
+      svn_boolean_t *make_abs_paths,
+      apr_pool_t *scratch_pool)
+{
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  apr_hash_index_t *hi;
+
+  for (hi = apr_hash_first(scratch_pool, operation->children);
+       hi; hi = apr_hash_next(hi))
+    {
+      struct operation *child;
+      const char *path;
+      void *file_baton = NULL;
+
+      svn_pool_clear(iterpool);
+      child = svn__apr_hash_index_val(hi);
+      path = svn__apr_hash_index_key(hi);
+
+      if (path[0] != '/' && *make_abs_paths)
+        path = apr_pstrcat(iterpool, "/", path, NULL);
+
+      /* Deletes are simple -- just delete the thing. */
+      if (child->operation == OP_DELETE)
+        {
+          SVN_ERR(editor->delete_entry(path, SVN_INVALID_REVNUM,
+                                       operation->baton, iterpool));
+        }
+
+      if (child->operation == OP_OPEN || child->operation == OP_PROPSET)
+        {
+          if (child->kind == svn_kind_dir)
+            SVN_ERR(editor->open_directory(path, operation->baton,
+                                           SVN_INVALID_REVNUM,
+                                           iterpool, &child->baton));
+          else
+            SVN_ERR(editor->open_file(path, operation->baton,
+                                      SVN_INVALID_REVNUM,
+                                      iterpool, &file_baton));
+        }
+
+      if (child->operation == OP_ADD)
+        {
+          if (child->kind == svn_kind_dir)
+            SVN_ERR(editor->add_directory(path, operation->baton,
+                                          child->copyfrom_url,
+                                          child->copyfrom_revision,
+                                          iterpool, &child->baton));
+          else
+            SVN_ERR(editor->add_file(path, operation->baton,
+                                     child->copyfrom_url,
+                                     child->copyfrom_revision, iterpool,
+                                     &file_baton));
+        }
+
+      if (child->src_file && file_baton)
+        {
+          /* We need to change textual contents. */
+          svn_txdelta_window_handler_t handler;
+          void *handler_baton;
+          svn_stream_t *contents;
+
+          SVN_ERR(editor->apply_textdelta(file_baton, NULL, iterpool,
+                                          &handler, &handler_baton));
+          SVN_ERR(svn_stream_open_readonly(&contents, child->src_file,
+                                           iterpool, iterpool));
+          SVN_ERR(svn_txdelta_send_stream(contents, handler, handler_baton,
+                                          NULL, iterpool));
+          SVN_ERR(svn_stream_close(contents));
+        }
+
+      /* Only worry about properties and closing the file baton if we've
+         previously opened it. */
+      if (file_baton)
+        {
+          if (child->kind == svn_kind_file)
+            SVN_ERR(change_props(editor, file_baton, child, iterpool));
+          SVN_ERR(editor->close_file(file_baton, NULL, iterpool));
+        }
+
+      /* We *always* open the child directory, so drive the child, change any
+         props, and then close the directory. */
+      if (child->kind == svn_kind_dir
+                   && (child->operation == OP_OPEN
+                    || child->operation == OP_PROPSET
+                    || child->operation == OP_ADD))
+        {
+          SVN_ERR(drive(child, editor, make_abs_paths, iterpool));
+          SVN_ERR(change_props(editor, child->baton, child, iterpool));
+          SVN_ERR(editor->close_directory(child->baton, iterpool));
+        }
+    }
+
+  return SVN_NO_ERROR;
+}
+
+/* This implements svn_editor_cb_complete_t */
+static svn_error_t *
+complete_cb(void *baton,
+            apr_pool_t *scratch_pool)
+{
+  struct editor_baton *eb = baton;
+  svn_error_t *err;
+
+  /* Drive the tree we've created. */
+  err = drive(&eb->root, eb->deditor, eb->make_abs_paths, scratch_pool);
+  if (!err)
+     err = eb->deditor->close_edit(eb->dedit_baton, scratch_pool);
+  if (err)
+    svn_error_clear(eb->deditor->abort_edit(eb->dedit_baton, scratch_pool));
+
+  return svn_error_trace(err);
+}
+
+/* This implements svn_editor_cb_abort_t */
+static svn_error_t *
+abort_cb(void *baton,
+         apr_pool_t *scratch_pool)
+{
+  struct editor_baton *eb = baton;
+  svn_error_t *err;
+  svn_error_t *err2;
+
+  /* We still need to drive anything we collected in the editor to this
+     point. */
+
+  /* Drive the tree we've created. */
+  err = drive(&eb->root, eb->deditor, eb->make_abs_paths, scratch_pool);
+
+  err2 = eb->deditor->abort_edit(eb->dedit_baton, scratch_pool);
+
+  if (err2)
+    {
+      if (err)
+        svn_error_clear(err2);
+      else
+        err = err2;
+    }
+
+  return svn_error_trace(err);
+}
+
+static svn_error_t *
+editor_from_delta(svn_editor_t **editor_p,
+                  const svn_delta_editor_t *deditor,
+                  void *dedit_baton,
+                  svn_boolean_t *send_abs_paths,
+                  svn_cancel_func_t cancel_func,
+                  void *cancel_baton,
+                  svn_delta_fetch_kind_func_t fetch_kind_func,
+                  void *fetch_kind_baton,
+                  svn_delta_fetch_props_func_t fetch_props_func,
+                  void *fetch_props_baton,
+                  apr_pool_t *result_pool,
+                  apr_pool_t *scratch_pool)
+{
+  svn_editor_t *editor;
+  static const svn_editor_cb_many_t editor_cbs = {
+      add_directory_cb,
+      add_file_cb,
+      add_symlink_cb,
+      add_absent_cb,
+      set_props_cb,
+      set_text_cb,
+      set_target_cb,
+      delete_cb,
+      copy_cb,
+      move_cb,
+      complete_cb,
+      abort_cb
+    };
+  struct editor_baton *eb = apr_palloc(result_pool, sizeof(*eb));
+
+  eb->deditor = deditor;
+  eb->dedit_baton = dedit_baton;
+  eb->edit_pool = result_pool;
+  eb->paths = apr_hash_make(result_pool);
+
+  eb->fetch_kind_func = fetch_kind_func;
+  eb->fetch_kind_baton = fetch_kind_baton;
+  eb->fetch_props_func = fetch_props_func;
+  eb->fetch_props_baton = fetch_props_baton;
+
+  eb->root.children = apr_hash_make(result_pool);
+  eb->root.kind = svn_kind_dir;
+  eb->root.operation = OP_OPEN;
+  eb->root.prop_mods = apr_hash_make(result_pool);
+  eb->root.prop_dels = apr_array_make(result_pool, 1, sizeof(const char *));
+  eb->root.copyfrom_revision = SVN_INVALID_REVNUM;
+
+  eb->root_opened = FALSE;
+  eb->make_abs_paths = send_abs_paths;
+
+  SVN_ERR(svn_editor_create(&editor, eb, cancel_func, cancel_baton,
+                            result_pool, scratch_pool));
+  SVN_ERR(svn_editor_setcb_many(editor, &editor_cbs, scratch_pool));
+
+  *editor_p = editor;
+
+  return SVN_NO_ERROR;
+}
+
+svn_delta_shim_callbacks_t *
+svn_delta_shim_callbacks_default(apr_pool_t *result_pool)
+{
+  svn_delta_shim_callbacks_t *shim_callbacks = apr_pcalloc(result_pool,
+                                                     sizeof(*shim_callbacks));
+  return shim_callbacks;
+}
+
+/* Uncomment below to add editor shims throughout Subversion.  In it's
+ * current state, that will likely break The World. */
+/* #define ENABLE_EDITOR_SHIMS*/
+
+svn_error_t *
+svn_editor__insert_shims(const svn_delta_editor_t **deditor_out,
+                         void **dedit_baton_out,
+                         const svn_delta_editor_t *deditor_in,
+                         void *dedit_baton_in,
+                         svn_delta_shim_callbacks_t *shim_callbacks,
+                         apr_pool_t *result_pool,
+                         apr_pool_t *scratch_pool)
+{
+#ifndef ENABLE_EDITOR_SHIMS
+  /* Shims disabled, just copy the editor and baton directly. */
+  *deditor_out = deditor_in;
+  *dedit_baton_out = dedit_baton_in;
+#else
+  /* Use our shim APIs to create an intermediate svn_editor_t, and then
+     wrap that again back into a svn_delta_editor_t.  This introduces
+     a lot of overhead. */
+  svn_editor_t *editor;
+  struct start_edit_baton *seb = apr_palloc(result_pool, sizeof(*seb));
+
+  /* The reason this is a pointer is that we don't know the appropriate
+     value until we start receiving paths.  So process_actions() sets the
+     flag, which drive() later consumes. */
+  svn_boolean_t *found_abs_paths = apr_palloc(result_pool,
+                                              sizeof(*found_abs_paths));
+
+  seb->deditor = deditor_in;
+  seb->dedit_baton = dedit_baton_in;
+
+  SVN_ERR(editor_from_delta(&editor, deditor_in, dedit_baton_in,
+                            found_abs_paths, NULL, NULL,
+                            shim_callbacks->fetch_kind_func,
+                            shim_callbacks->fetch_kind_baton,
+                            shim_callbacks->fetch_props_func,
+                            shim_callbacks->fetch_props_baton,
+                            result_pool, scratch_pool));
+  SVN_ERR(delta_from_editor(deditor_out, dedit_baton_out, editor,
+                            found_abs_paths,
+                            shim_callbacks->fetch_props_func,
+                            shim_callbacks->fetch_props_baton,
+                            start_edit_func, seb,
+                            target_revision_func, seb,
+                            result_pool));
+
+#endif
+  return SVN_NO_ERROR;
+}

Modified: subversion/branches/svn-bisect/subversion/libsvn_delta/compose_delta.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_delta/compose_delta.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_delta/compose_delta.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_delta/compose_delta.c Mon Nov 21 07:07:56 2011
@@ -774,7 +774,7 @@ svn_txdelta_compose_windows(const svn_tx
   /* Read the description of the delta composition algorithm in
      notes/fs-improvements.txt before going any further.
      You have been warned. */
-  build_baton.new_data = svn_stringbuf_create("", pool);
+  build_baton.new_data = svn_stringbuf_create_empty(pool);
   for (i = 0; i < window_B->num_ops; ++i)
     {
       const svn_txdelta_op_t *const op = &window_B->ops[i];

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=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_delta/editor.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_delta/editor.c Mon Nov 21 07:07:56 2011
@@ -26,8 +26,17 @@
 #include "svn_types.h"
 #include "svn_error.h"
 #include "svn_pools.h"
+#include "svn_editor.h"
+#include "svn_dirent_uri.h"
 
-#include "private/svn_editor.h"
+#ifdef SVN_DEBUG
+/* This enables runtime checks of the editor API constraints.  This may
+   introduce additional memory and runtime overhead, and should not be used
+   in production builds.
+   
+   ### Remove before release? */
+#define ENABLE_ORDERING_CHECK
+#endif
 
 
 struct svn_editor_t
@@ -44,6 +53,15 @@ struct svn_editor_t
 
   /* This pool is used as the scratch_pool for all callbacks.  */
   apr_pool_t *scratch_pool;
+
+#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
 };
 
 
@@ -61,6 +79,13 @@ 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
 
   return SVN_NO_ERROR;
 }
@@ -222,6 +247,11 @@ svn_editor_add_directory(svn_editor_t *e
   svn_error_t *err;
 
   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
 
   if (editor->cancel_func)
     SVN_ERR(editor->cancel_func(editor->cancel_baton));
@@ -229,6 +259,25 @@ svn_editor_add_directory(svn_editor_t *e
   err = editor->funcs.cb_add_directory(editor->baton, relpath, children,
                                        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);
+  {
+    int i;
+    for (i = 0; i < children->nelts; i++)
+      {
+        const char *child_basename = APR_ARRAY_IDX(children, i, const char *);
+        const char *child = svn_relpath_join(relpath, child_basename,
+                                             editor->result_pool);
+
+        apr_hash_set(editor->pending_incomplete_children, child,
+                     APR_HASH_KEY_STRING, (void *)0xdeadbeef);
+      }
+  }
+#endif
   svn_pool_clear(editor->scratch_pool);
   return err;
 }
@@ -237,18 +286,33 @@ svn_editor_add_directory(svn_editor_t *e
 svn_error_t *
 svn_editor_add_file(svn_editor_t *editor,
                     const char *relpath,
+                    const svn_checksum_t *checksum,
+                    svn_stream_t *contents,
                     apr_hash_t *props,
                     svn_revnum_t replaces_rev)
 {
   svn_error_t *err;
 
   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
 
   if (editor->cancel_func)
     SVN_ERR(editor->cancel_func(editor->cancel_baton));
 
-  err = editor->funcs.cb_add_file(editor->baton, relpath, props,
+  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
   svn_pool_clear(editor->scratch_pool);
   return err;
 }
@@ -264,12 +328,24 @@ svn_editor_add_symlink(svn_editor_t *edi
   svn_error_t *err;
 
   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
 
   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
   svn_pool_clear(editor->scratch_pool);
   return err;
 }
@@ -278,18 +354,30 @@ svn_editor_add_symlink(svn_editor_t *edi
 svn_error_t *
 svn_editor_add_absent(svn_editor_t *editor,
                       const char *relpath,
-                      svn_node_kind_t kind,
+                      svn_kind_t kind,
                       svn_revnum_t replaces_rev)
 {
   svn_error_t *err;
 
   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
 
   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
   svn_pool_clear(editor->scratch_pool);
   return err;
 }
@@ -305,12 +393,33 @@ svn_editor_set_props(svn_editor_t *edito
   svn_error_t *err;
 
   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
 
   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
   svn_pool_clear(editor->scratch_pool);
   return err;
 }
@@ -326,12 +435,24 @@ svn_editor_set_text(svn_editor_t *editor
   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
 
   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
   svn_pool_clear(editor->scratch_pool);
   return err;
 }
@@ -346,12 +467,24 @@ svn_editor_set_target(svn_editor_t *edit
   svn_error_t *err;
 
   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
 
   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
   svn_pool_clear(editor->scratch_pool);
   return err;
 }
@@ -365,12 +498,22 @@ svn_editor_delete(svn_editor_t *editor,
   svn_error_t *err;
 
   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
 
   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
   svn_pool_clear(editor->scratch_pool);
   return err;
 }
@@ -386,6 +529,11 @@ svn_editor_copy(svn_editor_t *editor,
   svn_error_t *err;
 
   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
 
   if (editor->cancel_func)
     SVN_ERR(editor->cancel_func(editor->cancel_baton));
@@ -408,6 +556,13 @@ svn_editor_move(svn_editor_t *editor,
   svn_error_t *err;
 
   SVN_ERR_ASSERT(editor->funcs.cb_move != NULL);
+#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));
+#endif
 
   if (editor->cancel_func)
     SVN_ERR(editor->cancel_func(editor->cancel_baton));
@@ -415,6 +570,22 @@ svn_editor_move(svn_editor_t *editor,
   err = editor->funcs.cb_move(editor->baton, src_relpath, src_revision,
                               dst_relpath, replaces_rev,
                               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);
+#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;
 }
@@ -426,8 +597,16 @@ svn_editor_complete(svn_editor_t *editor
   svn_error_t *err;
 
   SVN_ERR_ASSERT(editor->funcs.cb_complete != NULL);
+#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
   svn_pool_clear(editor->scratch_pool);
   return err;
 }
@@ -439,8 +618,14 @@ svn_editor_abort(svn_editor_t *editor)
   svn_error_t *err;
 
   SVN_ERR_ASSERT(editor->funcs.cb_abort != NULL);
+#ifdef ENABLE_ORDERING_CHECK
+  SVN_ERR_ASSERT(!editor->finished);
+#endif
 
   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=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_delta/svndiff.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_delta/svndiff.c Mon Nov 21 07:07:56 2011
@@ -182,9 +182,9 @@ window_handler(svn_txdelta_window_t *win
 {
   struct encoder_baton *eb = baton;
   apr_pool_t *pool = svn_pool_create(eb->pool);
-  svn_stringbuf_t *instructions = svn_stringbuf_create("", pool);
-  svn_stringbuf_t *i1 = svn_stringbuf_create("", pool);
-  svn_stringbuf_t *header = svn_stringbuf_create("", pool);
+  svn_stringbuf_t *instructions = svn_stringbuf_create_empty(pool);
+  svn_stringbuf_t *i1 = svn_stringbuf_create_empty(pool);
+  svn_stringbuf_t *header = svn_stringbuf_create_empty(pool);
   const svn_string_t *newdata;
   unsigned char ibuf[MAX_INSTRUCTION_LEN], *ip;
   const svn_txdelta_op_t *op;
@@ -254,8 +254,8 @@ window_handler(svn_txdelta_window_t *win
   append_encoded_int(header, instructions->len);
   if (eb->version == 1)
     {
-      svn_stringbuf_t *temp = svn_stringbuf_create("", pool);
-      svn_string_t *tempstr = svn_string_create("", pool);
+      svn_stringbuf_t *temp = svn_stringbuf_create_empty(pool);
+      svn_string_t *tempstr = svn_string_create_empty(pool);
       SVN_ERR(zlib_encode(window->new_data->data, window->new_data->len,
                           temp, eb->compression_level));
       tempstr->data = temp->data;
@@ -431,20 +431,24 @@ decode_size(apr_size_t *val,
   return NULL;
 }
 
-/* Decode the possibly-zlib compressed string that is in IN, into OUT.
-   We expect an integer is prepended to IN that specifies the original
-   size, and that if encoded size == original size, that the remaining
-   data is not compressed.  */
+/* Decode the possibly-zlib compressed string of length INLEN that is in
+   IN, into OUT.  We expect an integer is prepended to IN that specifies
+   the original size, and that if encoded size == original size, that the
+   remaining data is not compressed.
+   In that case, we will simply return pointer into IN as data pointer for
+   OUT.  The caller is expected not to modify the contents of OUT.
+   An error is returned if the decoded length exceeds the given LIMIT.
+ */
 static svn_error_t *
-zlib_decode(svn_stringbuf_t *in, svn_stringbuf_t *out, apr_size_t limit)
+zlib_decode(const unsigned char *in, apr_size_t inLen, svn_stringbuf_t *out,
+            apr_size_t limit)
 {
   apr_size_t len;
-  char *oldplace = in->data;
+  const unsigned char *oldplace = in;
 
   /* First thing in the string is the original length.  */
-  in->data = (char *)decode_size(&len, (unsigned char *)in->data,
-                                 (unsigned char *)in->data+in->len);
-  if (in->data == NULL)
+  in = decode_size(&len, in, in + inLen);
+  if (in == NULL)
     return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA, NULL,
                             _("Decompression of svndiff data failed: no size"));
   if (len > limit)
@@ -453,33 +457,36 @@ zlib_decode(svn_stringbuf_t *in, svn_str
                               "size too large"));
   /* We need to subtract the size of the encoded original length off the
    *      still remaining input length.  */
-  in->len -= (in->data - oldplace);
-  if (in->len == len)
+  inLen -= (in - oldplace);
+  if (inLen == len)
     {
-      svn_stringbuf_appendstr(out, in);
+      /* "in" is no longer used but the memory remains allocated for
+       * at least as long as "out" will be used by the caller.
+       */
+      out->data = (char *)in;
+      out->len = len;
+      out->blocksize = len; /* sic! */
+
       return SVN_NO_ERROR;
     }
   else
     {
-      unsigned long zliblen;
+      unsigned long zlen = len;
 
       svn_stringbuf_ensure(out, len);
-
-      zliblen = len;
-      if (uncompress  ((unsigned char *)out->data, &zliblen,
-                       (const unsigned char *)in->data, in->len) != Z_OK)
+      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"));
 
       /* Zlib should not produce something that has a different size than the
          original length we stored. */
-      if (zliblen != len)
+      if (zlen != len)
         return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA,
                                 NULL,
                                 _("Size of uncompressed data "
                                   "does not match stored original length"));
-      out->len = zliblen;
+      out->len = zlen;
     }
   return SVN_NO_ERROR;
 }
@@ -627,16 +634,15 @@ decode_window(svn_txdelta_window_t *wind
 
   if (version == 1)
     {
-      svn_stringbuf_t *instin, *ndin;
-      svn_stringbuf_t *instout, *ndout;
+      svn_stringbuf_t *instout = svn_stringbuf_create_empty(pool);
+      svn_stringbuf_t *ndout = svn_stringbuf_create_empty(pool);
 
-      instin = svn_stringbuf_ncreate((const char *)data, insend - data, pool);
-      instout = svn_stringbuf_create("", pool);
-      SVN_ERR(zlib_decode(instin, instout, MAX_INSTRUCTION_SECTION_LEN));
-
-      ndin = svn_stringbuf_ncreate((const char *)insend, newlen, pool);
-      ndout = svn_stringbuf_create("", pool);
-      SVN_ERR(zlib_decode(ndin, ndout, SVN_DELTA_WINDOW_SIZE));
+      /* these may in fact simply return references to insend */
+      
+      SVN_ERR(zlib_decode(insend, newlen, ndout,
+                          SVN_DELTA_WINDOW_SIZE));
+      SVN_ERR(zlib_decode(data, insend - data, instout,
+                          MAX_INSTRUCTION_SECTION_LEN));
 
       newlen = ndout->len;
       data = (unsigned char *)instout->data;
@@ -846,7 +852,7 @@ svn_txdelta_parse_svndiff(svn_txdelta_wi
   db->consumer_baton = handler_baton;
   db->pool = subpool;
   db->subpool = svn_pool_create(subpool);
-  db->buffer = svn_stringbuf_create("", db->subpool);
+  db->buffer = svn_stringbuf_create_empty(db->subpool);
   db->last_sview_offset = 0;
   db->last_sview_len = 0;
   db->header_bytes = 0;

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=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_delta/text_delta.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_delta/text_delta.c Mon Nov 21 07:07:56 2011
@@ -150,7 +150,7 @@ compute_window(const char *data, apr_siz
   svn_txdelta_window_t *window;
 
   /* Compute the delta operations. */
-  build_baton.new_data = svn_stringbuf_create("", pool);
+  build_baton.new_data = svn_stringbuf_create_empty(pool);
 
   if (source_len == 0)
     svn_txdelta__insert_op(&build_baton, svn_txdelta_new, 0, target_len, data,

Modified: subversion/branches/svn-bisect/subversion/libsvn_diff/diff_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_diff/diff_file.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_diff/diff_file.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_diff/diff_file.c Mon Nov 21 07:07:56 2011
@@ -470,8 +470,9 @@ find_identical_prefix(svn_boolean_t *rea
          too many for the \r. */
       svn_boolean_t ended_at_nonmatching_newline = FALSE;
       for (i = 0; i < file_len; i++)
-        ended_at_nonmatching_newline = ended_at_nonmatching_newline
-                                       || *file[i].curp == '\n';
+        if (file[i].curp < file[i].endp)
+          ended_at_nonmatching_newline = ended_at_nonmatching_newline
+                                         || *file[i].curp == '\n';
       if (ended_at_nonmatching_newline)
         {
           lines--;
@@ -591,9 +592,9 @@ find_identical_suffix(apr_off_t *suffix_
   had_nl = FALSE;
   while (is_match)
     {
+#if SVN_UNALIGNED_ACCESS_IS_OK
       /* Initialize the minimum pointer positions. */
       const char *min_curp[4];
-#if SVN_UNALIGNED_ACCESS_IS_OK
       svn_boolean_t can_read_word;
 #endif /* SVN_UNALIGNED_ACCESS_IS_OK */
 
@@ -616,6 +617,7 @@ find_identical_suffix(apr_off_t *suffix_
 
       DECREMENT_POINTERS(file_for_suffix, file_len, pool);
 
+#if SVN_UNALIGNED_ACCESS_IS_OK
 
       min_curp[0] = file_for_suffix[0].chunk == suffix_min_chunk0
                   ? file_for_suffix[0].buffer + suffix_min_offset0 + 1
@@ -623,8 +625,6 @@ find_identical_suffix(apr_off_t *suffix_
       for (i = 1; i < file_len; i++)
         min_curp[i] = file_for_suffix[i].buffer + 1;
 
-#if SVN_UNALIGNED_ACCESS_IS_OK
-
       /* Scan quickly by reading with machine-word granularity. */
       for (i = 0, can_read_word = TRUE; i < file_len; i++)
         can_read_word = can_read_word
@@ -1636,7 +1636,7 @@ output_unified_diff_modified(void *baton
 
       if (output_baton->show_c_function)
         {
-          int p;
+          apr_size_t p;
           const char *invalid_character;
 
           /* Save the extra context for later use.
@@ -1756,9 +1756,9 @@ svn_diff_file_output_unified3(svn_stream
       baton.header_encoding = header_encoding;
       baton.path[0] = original_path;
       baton.path[1] = modified_path;
-      baton.hunk = svn_stringbuf_create("", pool);
+      baton.hunk = svn_stringbuf_create_empty(pool);
       baton.show_c_function = show_c_function;
-      baton.extra_context = svn_stringbuf_create("", pool);
+      baton.extra_context = svn_stringbuf_create_empty(pool);
       baton.extra_skip_match = apr_array_make(pool, 3, sizeof(char **));
 
       c = apr_array_push(baton.extra_skip_match);
@@ -1920,7 +1920,7 @@ flush_context_saver(context_saver_t *cs,
   int i;
   for (i = 0; i < SVN_DIFF__UNIFIED_CONTEXT_SIZE; i++)
     {
-      int slot = (i + cs->next_slot) % SVN_DIFF__UNIFIED_CONTEXT_SIZE;
+      apr_size_t slot = (i + cs->next_slot) % SVN_DIFF__UNIFIED_CONTEXT_SIZE;
       if (cs->data[slot])
         {
           apr_size_t len = cs->len[slot];

Modified: subversion/branches/svn-bisect/subversion/libsvn_diff/diff_memory.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_diff/diff_memory.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_diff/diff_memory.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_diff/diff_memory.c Mon Nov 21 07:07:56 2011
@@ -584,7 +584,7 @@ svn_diff_mem_string_output_unified2(svn_
       baton.output_stream = output_stream;
       baton.pool = svn_pool_create(pool);
       baton.header_encoding = header_encoding;
-      baton.hunk = svn_stringbuf_create("", pool);
+      baton.hunk = svn_stringbuf_create_empty(pool);
       baton.hunk_delimiter = hunk_delimiter;
 
       SVN_ERR(svn_utf_cstring_from_utf8_ex2
@@ -710,7 +710,7 @@ flush_context_saver(context_saver_t *cs,
   int i;
   for (i = 0; i < SVN_DIFF__UNIFIED_CONTEXT_SIZE; i++)
     {
-      int slot = (i + cs->next_slot) % SVN_DIFF__UNIFIED_CONTEXT_SIZE;
+      apr_size_t slot = (i + cs->next_slot) % SVN_DIFF__UNIFIED_CONTEXT_SIZE;
       if (cs->data[slot])
         {
           apr_size_t len = cs->len[slot];

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=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_diff/parse-diff.c Mon Nov 21 07:07:56 2011
@@ -22,6 +22,7 @@
  */
 
 #include <stdlib.h>
+#include <stddef.h>
 #include <string.h>
 
 #include "svn_types.h"
@@ -395,7 +396,7 @@ hunk_readline_original_or_modified(apr_f
       *eof = TRUE;
       if (eol)
         *eol = NULL;
-      *stringbuf = svn_stringbuf_create("", result_pool);
+      *stringbuf = svn_stringbuf_create_empty(result_pool);
       return SVN_NO_ERROR;
     }
 
@@ -489,7 +490,7 @@ svn_diff_hunk_readline_diff_text(svn_dif
       *eof = TRUE;
       if (eol)
         *eol = NULL;
-      *stringbuf = svn_stringbuf_create("", result_pool);
+      *stringbuf = svn_stringbuf_create_empty(result_pool);
       return SVN_NO_ERROR;
     }
 
@@ -965,8 +966,8 @@ git_start(enum parse_state *new_state, c
 
   while (TRUE)
     {
-      int len_old;
-      int len_new;
+      ptrdiff_t len_old;
+      ptrdiff_t len_new;
 
       new_path_marker = strstr(new_path_start, " b/");
 

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=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_fs/fs-loader.c Mon Nov 21 07:07:56 2011
@@ -43,6 +43,7 @@
 #include "private/svn_fs_private.h"
 #include "private/svn_fs_util.h"
 #include "private/svn_utf_private.h"
+#include "private/svn_mutex.h"
 
 #include "fs-loader.h"
 #include "svn_hash.h"
@@ -58,9 +59,7 @@
 /* A pool common to all FS objects.  See the documentation on the
    open/create functions in fs-loader.h and for svn_fs_initialize(). */
 static apr_pool_t *common_pool;
-#if APR_HAS_THREADS
-static apr_thread_mutex_t *common_pool_lock;
-#endif
+svn_mutex__t *common_pool_lock;
 
 
 /* --- Utility functions for the loader --- */
@@ -124,30 +123,6 @@ load_module(fs_init_func_t *initfunc, co
   return SVN_NO_ERROR;
 }
 
-static svn_error_t *
-acquire_fs_mutex(void)
-{
-#if APR_HAS_THREADS
-  apr_status_t status;
-  status = apr_thread_mutex_lock(common_pool_lock);
-  if (status)
-    return svn_error_wrap_apr(status, _("Can't grab FS mutex"));
-#endif
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-release_fs_mutex(void)
-{
-#if APR_HAS_THREADS
-  apr_status_t status;
-  status = apr_thread_mutex_unlock(common_pool_lock);
-  if (status)
-    return svn_error_wrap_apr(status, _("Can't ungrab FS mutex"));
-#endif
-  return SVN_NO_ERROR;
-}
-
 /* Fetch a library vtable by a pointer into the library definitions array. */
 static svn_error_t *
 get_library_vtable_direct(fs_library_vtable_t **vtable,
@@ -168,9 +143,6 @@ get_library_vtable_direct(fs_library_vta
                              fst->fs_type);
 
   {
-    svn_error_t *err;
-    svn_error_t *err2;
-
     /* Per our API compatibility rules, we cannot ensure that
        svn_fs_initialize is called by the application.  If not, we
        cannot create the common pool and lock in a thread-safe fashion,
@@ -183,16 +155,8 @@ get_library_vtable_direct(fs_library_vta
 
     /* Invoke the FS module's initfunc function with the common
        pool protected by a lock. */
-    SVN_ERR(acquire_fs_mutex());
-    err = initfunc(my_version, vtable, common_pool);
-    err2 = release_fs_mutex();
-    if (err)
-      {
-        svn_error_clear(err2);
-        return err;
-      }
-    if (err2)
-      return err2;
+    SVN_MUTEX__WITH_LOCK(common_pool_lock, 
+                         initfunc(my_version, vtable, common_pool));
   }
   fs_version = (*vtable)->get_version();
   if (!svn_ver_equal(my_version, fs_version))
@@ -290,30 +254,18 @@ write_fs_type(const char *path, const ch
 static apr_status_t uninit(void *data)
 {
   common_pool = NULL;
-#if APR_HAS_THREADS
-  common_pool_lock = NULL;
-#endif
   return APR_SUCCESS;
 }
 
 svn_error_t *
 svn_fs_initialize(apr_pool_t *pool)
 {
-#if APR_HAS_THREADS
-  apr_status_t status;
-#endif
-
   /* Protect against multiple calls. */
   if (common_pool)
     return SVN_NO_ERROR;
 
   common_pool = svn_pool_create(pool);
-#if APR_HAS_THREADS
-  status = apr_thread_mutex_create(&common_pool_lock,
-                                   APR_THREAD_MUTEX_DEFAULT, common_pool);
-  if (status)
-    return svn_error_wrap_apr(status, _("Can't allocate FS mutex"));
-#endif
+  SVN_ERR(svn_mutex__init(&common_pool_lock, TRUE, common_pool));
 
   /* ### This won't work if POOL is NULL and libsvn_fs is loaded as a DSO
      ### (via libsvn_ra_local say) since the global common_pool will live
@@ -392,8 +344,6 @@ svn_error_t *
 svn_fs_create(svn_fs_t **fs_p, const char *path, apr_hash_t *fs_config,
               apr_pool_t *pool)
 {
-  svn_error_t *err;
-  svn_error_t *err2;
   fs_library_vtable_t *vtable;
 
   const char *fs_type = svn_hash__get_cstring(fs_config,
@@ -407,57 +357,37 @@ svn_fs_create(svn_fs_t **fs_p, const cha
 
   /* Perform the actual creation. */
   *fs_p = fs_new(fs_config, pool);
-  SVN_ERR(acquire_fs_mutex());
-  err = vtable->create(*fs_p, path, pool, common_pool);
-  err2 = release_fs_mutex();
-  if (err)
-    {
-      svn_error_clear(err2);
-      return svn_error_trace(err);
-    }
-  return svn_error_trace(err2);
+  
+  SVN_MUTEX__WITH_LOCK(common_pool_lock,
+                       vtable->create(*fs_p, path, pool, common_pool));
+  return SVN_NO_ERROR;
 }
 
 svn_error_t *
 svn_fs_open(svn_fs_t **fs_p, const char *path, apr_hash_t *fs_config,
             apr_pool_t *pool)
 {
-  svn_error_t *err;
-  svn_error_t *err2;
   fs_library_vtable_t *vtable;
 
   SVN_ERR(fs_library_vtable(&vtable, path, pool));
   *fs_p = fs_new(fs_config, pool);
-  SVN_ERR(acquire_fs_mutex());
-  err = vtable->open_fs(*fs_p, path, pool, common_pool);
-  err2 = release_fs_mutex();
-  if (err)
-    {
-      svn_error_clear(err2);
-      return svn_error_trace(err);
-    }
-  return svn_error_trace(err2);
+  SVN_MUTEX__WITH_LOCK(common_pool_lock,
+                       vtable->open_fs(*fs_p, path, pool, common_pool));
+  return SVN_NO_ERROR;
 }
 
 svn_error_t *
 svn_fs_upgrade(const char *path, apr_pool_t *pool)
 {
-  svn_error_t *err;
-  svn_error_t *err2;
   fs_library_vtable_t *vtable;
   svn_fs_t *fs;
 
   SVN_ERR(fs_library_vtable(&vtable, path, pool));
   fs = fs_new(NULL, pool);
-  SVN_ERR(acquire_fs_mutex());
-  err = vtable->upgrade_fs(fs, path, pool, common_pool);
-  err2 = release_fs_mutex();
-  if (err)
-    {
-      svn_error_clear(err2);
-      return svn_error_trace(err);
-    }
-  return svn_error_trace(err2);
+
+  SVN_MUTEX__WITH_LOCK(common_pool_lock,
+                       vtable->upgrade_fs(fs, path, pool, common_pool));
+  return SVN_NO_ERROR;
 }
 
 svn_error_t *
@@ -466,23 +396,16 @@ svn_fs_verify(const char *path,
               void *cancel_baton,
               apr_pool_t *pool) 
 {
-  svn_error_t *err;
-  svn_error_t *err2;
   fs_library_vtable_t *vtable;
   svn_fs_t *fs;
 
   SVN_ERR(fs_library_vtable(&vtable, path, pool));
   fs = fs_new(NULL, pool);
-  SVN_ERR(acquire_fs_mutex());
-  err = vtable->verify_fs(fs, path, cancel_func, cancel_baton,
-                          pool, common_pool);
-  err2 = release_fs_mutex();
-  if (err)
-    {
-      svn_error_clear(err2);
-      return svn_error_trace(err);
-    }
-  return svn_error_trace(err2);
+
+  SVN_MUTEX__WITH_LOCK(common_pool_lock,
+                       vtable->verify_fs(fs, path, cancel_func, cancel_baton,
+                                         pool, common_pool));
+  return SVN_NO_ERROR;
 }
 
 const char *
@@ -521,23 +444,16 @@ svn_fs_pack(const char *path,
             void *cancel_baton,
             apr_pool_t *pool)
 {
-  svn_error_t *err;
-  svn_error_t *err2;
   fs_library_vtable_t *vtable;
   svn_fs_t *fs;
 
   SVN_ERR(fs_library_vtable(&vtable, path, pool));
   fs = fs_new(NULL, pool);
-  SVN_ERR(acquire_fs_mutex());
-  err = vtable->pack_fs(fs, path, notify_func, notify_baton,
-                        cancel_func, cancel_baton, pool);
-  err2 = release_fs_mutex();
-  if (err)
-    {
-      svn_error_clear(err2);
-      return svn_error_trace(err);
-    }
-  return svn_error_trace(err2);
+
+  SVN_MUTEX__WITH_LOCK(common_pool_lock,
+                       vtable->pack_fs(fs, path, notify_func, notify_baton,
+                                       cancel_func, cancel_baton, pool));
+  return SVN_NO_ERROR;
 }
 
 svn_error_t *
@@ -545,24 +461,17 @@ svn_fs_recover(const char *path,
                svn_cancel_func_t cancel_func, void *cancel_baton,
                apr_pool_t *pool)
 {
-  svn_error_t *err;
-  svn_error_t *err2;
   fs_library_vtable_t *vtable;
   svn_fs_t *fs;
 
   SVN_ERR(fs_library_vtable(&vtable, path, pool));
   fs = fs_new(NULL, pool);
-  SVN_ERR(acquire_fs_mutex());
-  err = vtable->open_fs_for_recovery(fs, path, pool, common_pool);
-  err2 = release_fs_mutex();
-  if (err)
-    {
-      svn_error_clear(err2);
-      return svn_error_trace(err);
-    }
-  if (! err2)
-    err2 = vtable->recover(fs, cancel_func, cancel_baton, pool);
-  return svn_error_trace(err2);
+
+  SVN_MUTEX__WITH_LOCK(common_pool_lock,
+                       vtable->open_fs_for_recovery(fs, path, pool,
+                                                    common_pool));
+  return svn_error_trace(vtable->recover(fs, cancel_func, cancel_baton,
+                                         pool));
 }
 
 
@@ -571,8 +480,6 @@ svn_fs_recover(const char *path,
 svn_error_t *
 svn_fs_create_berkeley(svn_fs_t *fs, const char *path)
 {
-  svn_error_t *err;
-  svn_error_t *err2;
   fs_library_vtable_t *vtable;
 
   SVN_ERR(get_library_vtable(&vtable, SVN_FS_TYPE_BDB, fs->pool));
@@ -582,34 +489,20 @@ svn_fs_create_berkeley(svn_fs_t *fs, con
   SVN_ERR(write_fs_type(path, SVN_FS_TYPE_BDB, fs->pool));
 
   /* Perform the actual creation. */
-  SVN_ERR(acquire_fs_mutex());
-  err = vtable->create(fs, path, fs->pool, common_pool);
-  err2 = release_fs_mutex();
-  if (err)
-    {
-      svn_error_clear(err2);
-      return svn_error_trace(err);
-    }
-  return svn_error_trace(err2);
+  SVN_MUTEX__WITH_LOCK(common_pool_lock,
+                       vtable->create(fs, path, fs->pool, common_pool));
+  return SVN_NO_ERROR;
 }
 
 svn_error_t *
 svn_fs_open_berkeley(svn_fs_t *fs, const char *path)
 {
-  svn_error_t *err;
-  svn_error_t *err2;
   fs_library_vtable_t *vtable;
 
   SVN_ERR(fs_library_vtable(&vtable, path, fs->pool));
-  SVN_ERR(acquire_fs_mutex());
-  err = vtable->open_fs(fs, path, fs->pool, common_pool);
-  err2 = release_fs_mutex();
-  if (err)
-    {
-      svn_error_clear(err2);
-      return svn_error_trace(err);
-    }
-  return svn_error_trace(err2);
+  SVN_MUTEX__WITH_LOCK(common_pool_lock,
+                       vtable->open_fs(fs, path, fs->pool, common_pool));
+  return SVN_NO_ERROR;
 }
 
 const char *
@@ -1002,15 +895,14 @@ svn_fs_get_mergeinfo2(svn_mergeinfo_cata
                       svn_fs_root_t *root,
                       const apr_array_header_t *paths,
                       svn_mergeinfo_inheritance_t inherit,
-                      svn_boolean_t validate_inherited_mergeinfo,
                       svn_boolean_t include_descendants,
-                      apr_pool_t *pool)
-{
-  return svn_error_trace(root->vtable->get_mergeinfo(catalog, root, paths,
-                                                     inherit,
-                                                     validate_inherited_mergeinfo,
-                                                     include_descendants,
-                                                     pool));
+                      svn_boolean_t adjust_inherited_mergeinfo,
+                      apr_pool_t *result_pool,
+                      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));
 }
 
 svn_error_t *
@@ -1021,24 +913,10 @@ svn_fs_get_mergeinfo(svn_mergeinfo_catal
                      svn_boolean_t include_descendants,
                      apr_pool_t *pool)
 {
-  return svn_error_trace(svn_fs_get_mergeinfo2(catalog, root, paths,
-                                               inherit,
-                                               FALSE,
-                                               include_descendants,
-                                               pool));
-}
-
-svn_error_t *
-svn_fs_validate_mergeinfo(svn_mergeinfo_t *validated_mergeinfo,
-                          svn_fs_t *fs,
-                          svn_mergeinfo_t mergeinfo,
-                          apr_pool_t *result_pool,
-                          apr_pool_t *scratch_pool)
-{
-  return svn_error_trace(fs->vtable->validate_mergeinfo(validated_mergeinfo,
-                                                        fs, mergeinfo,
-                                                        result_pool,
-                                                        scratch_pool));
+  return svn_error_trace(root->vtable->get_mergeinfo(catalog, root, paths,
+                                                     inherit,
+                                                     include_descendants,
+                                                     TRUE, pool, 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=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_fs/fs-loader.h Mon Nov 21 07:07:56 2011
@@ -36,13 +36,14 @@ extern "C" {
 /* The FS loader library implements the a front end to "filesystem
    abstract providers" (FSAPs), which implement the svn_fs API.
 
-   The loader library divides up the FS API into five categories:
+   The loader library divides up the FS API into several categories:
 
      - Top-level functions, which operate on paths to an FS
      - Functions which operate on an FS object
      - Functions which operate on a transaction object
      - Functions which operate on a root object
      - Functions which operate on a history object
+     - Functions which operate on a noderev-ID object
 
    Some generic fields of the FS, transaction, root, and history
    objects are defined by the loader library; the rest are stored in
@@ -199,11 +200,6 @@ typedef struct fs_vtable_t
   svn_error_t *(*bdb_set_errcall)(svn_fs_t *fs,
                                   void (*handler)(const char *errpfx,
                                                   char *msg));
-  svn_error_t *(*validate_mergeinfo)(svn_mergeinfo_t *validated_mergeinfo,
-                                     svn_fs_t *fs,
-                                     svn_mergeinfo_t mergeinfo,
-                                     apr_pool_t *result_pool,
-                                     apr_pool_t *scratch_pool);
 } fs_vtable_t;
 
 
@@ -336,9 +332,10 @@ typedef struct root_vtable_t
                                 svn_fs_root_t *root,
                                 const apr_array_header_t *paths,
                                 svn_mergeinfo_inheritance_t inherit,
-                                svn_boolean_t validate_inherited_mergeinfo,
                                 svn_boolean_t include_descendants,
-                                apr_pool_t *pool);
+                                svn_boolean_t adjust_inherited_mergeinfo,
+                                apr_pool_t *result_pool,
+                                apr_pool_t *scratch_pool);
 } root_vtable_t;
 
 

Modified: subversion/branches/svn-bisect/subversion/libsvn_fs_base/bdb/changes-table.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_fs_base/bdb/changes-table.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_fs_base/bdb/changes-table.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_fs_base/bdb/changes-table.c Mon Nov 21 07:07:56 2011
@@ -325,14 +325,14 @@ svn_fs_bdb__changes_fetch(apr_hash_t **c
               /* KEY is the path. */
               const void *hashkey;
               apr_ssize_t klen;
-              apr_hash_this(hi, &hashkey, &klen, NULL);
+              const char *child_relpath;
 
-              /* If we come across our own path, ignore it. */
-              if (strcmp(change->path, hashkey) == 0)
-                continue;
+              apr_hash_this(hi, &hashkey, &klen, NULL);
 
-              /* If we come across a child of our path, remove it. */
-              if (svn_fspath__is_child(change->path, hashkey, subpool))
+              /* If we come across our own path, ignore it.
+                 If we come across a child of our path, remove it. */
+              child_relpath = svn_fspath__skip_ancestor(change->path, hashkey);
+              if (child_relpath && *child_relpath)
                 apr_hash_set(changes, hashkey, klen, NULL);
             }
         }



Mime
View raw message