You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2011/12/18 18:36:29 UTC

svn commit: r1220465 [6/13] - in /subversion/branches/file-handle-cache: ./ build/ build/ac-macros/ contrib/client-side/emacs/ contrib/server-side/mod_dontdothat/ notes/ subversion/bindings/javahl/tests/org/apache/subversion/javahl/ subversion/bindings...

Modified: subversion/branches/file-handle-cache/subversion/libsvn_delta/compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/libsvn_delta/compat.c?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/libsvn_delta/compat.c (original)
+++ subversion/branches/file-handle-cache/subversion/libsvn_delta/compat.c Sun Dec 18 17:36:24 2011
@@ -27,6 +27,7 @@
 #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"
 
@@ -98,13 +99,20 @@ typedef svn_error_t *(*start_edit_func_t
     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;
-  svn_revnum_t target_revision;
   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;
@@ -112,6 +120,12 @@ struct ev2_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;
+
+  svn_delta_fetch_base_func_t fetch_base_func;
+  void *fetch_base_baton;
 };
 
 struct ev2_dir_baton
@@ -124,18 +138,25 @@ struct ev2_file_baton
 {
   struct ev2_edit_baton *eb;
   const char *path;
+  const char *delta_base;
 };
 
-enum action
+enum action_code_t
 {
+  ACTION_MOVE,
+  ACTION_MKDIR,
+  ACTION_COPY,
+  ACTION_PROPSET,
+  ACTION_PUT,
   ACTION_ADD,
   ACTION_DELETE,
-  ACTION_SET_PROP
+  ACTION_ADD_ABSENT,
+  ACTION_SET_TEXT
 };
 
 struct path_action
 {
-  enum action action;
+  enum action_code_t action;
   void *args;
 };
 
@@ -145,10 +166,22 @@ struct prop_args
   const svn_string_t *value;
 };
 
+struct copy_args
+{
+  const char *copyfrom_path;
+  svn_revnum_t copyfrom_rev;
+};
+
+struct path_checksum_args
+{
+  const char *path;
+  svn_checksum_t *checksum;
+};
+
 static svn_error_t *
 add_action(struct ev2_edit_baton *eb,
            const char *path,
-           enum action action,
+           enum action_code_t action,
            void *args)
 {
   struct path_action *p_action;
@@ -180,10 +213,18 @@ process_actions(void *edit_baton,
 {
   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 = NULL;
+  svn_checksum_t *checksum = NULL;
+  svn_kind_t kind;
   int i;
 
   if (*path == '/')
-    path++;
+    {
+      path++;
+      *eb->found_abs_paths = TRUE;
+    }
 
   /* Go through all of our actions, populating various datastructures
    * dependent on them. */
@@ -194,7 +235,7 @@ process_actions(void *edit_baton,
 
       switch (action->action)
         {
-          case ACTION_SET_PROP:
+          case ACTION_PROPSET:
             {
               const struct prop_args *p_args = action->args;
 
@@ -227,24 +268,52 @@ process_actions(void *edit_baton,
 
           case ACTION_ADD:
             {
-              svn_kind_t *kind = action->args;
+              kind = *((svn_kind_t *) action->args);
+              need_add = TRUE;
 
-              if (*kind == svn_kind_dir)
+              if (kind == svn_kind_dir)
                 {
-                  apr_array_header_t *children = apr_array_make(
-                                    scratch_pool, 1, sizeof(const char *));
-                  SVN_ERR(svn_editor_add_directory(eb->editor, path, children,
-                                                   NULL, SVN_INVALID_REVNUM));
+                  children = apr_array_make(scratch_pool, 1,
+                                            sizeof(const char *));
                 }
               else
                 {
-                  svn_stream_t *contents = svn_stream_empty(scratch_pool);
-                  SVN_ERR(svn_editor_add_file(eb->editor, path, NULL, contents,
-                                              NULL, SVN_INVALID_REVNUM));
+                  /* The default is an empty file. */
+                  contents = svn_stream_empty(scratch_pool);
+                  checksum = svn_checksum_empty_checksum(svn_checksum_sha1,
+                                                         scratch_pool);
                 }
               break;
             }
 
+          case ACTION_SET_TEXT:
+            {
+              struct path_checksum_args *pca = action->args;
+
+              SVN_ERR(svn_stream_open_readonly(&contents, pca->path,
+                                               scratch_pool, scratch_pool));
+              checksum = pca->checksum;
+              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;
+            }
+
+          case ACTION_ADD_ABSENT:
+            {
+              kind = *((svn_kind_t *) action->args);
+              SVN_ERR(svn_editor_add_absent(eb->editor, path, kind,
+                                            SVN_INVALID_REVNUM));
+              break;
+            }
+
           default:
             SVN_ERR_MALFUNCTION();
         }
@@ -253,12 +322,35 @@ process_actions(void *edit_baton,
   /* 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 (props)
+  if (need_add)
     {
-      /* 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, eb->target_revision,
-                                   props, TRUE));
+      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, checksum, 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, contents == NULL));
+        }
+
+      if (contents)
+        {
+          /* If we have an content for this node, set it now. */
+          SVN_ERR(svn_editor_set_text(eb->editor, path, SVN_INVALID_REVNUM,
+                                      checksum, contents));
+        }
     }
 
   return SVN_NO_ERROR;
@@ -302,7 +394,8 @@ ev2_set_target_revision(void *edit_baton
 {
   struct ev2_edit_baton *eb = edit_baton;
 
-  eb->target_revision = target_revision;
+  SVN_ERR(eb->target_revision_func(eb->target_revision_baton, target_revision,
+                                   scratch_pool));
   return SVN_NO_ERROR;
 }
 
@@ -352,16 +445,29 @@ ev2_add_directory(const char *path,
 {
   struct ev2_dir_baton *pb = parent_baton;
   struct ev2_dir_baton *cb = apr_palloc(result_pool, sizeof(*cb));
-  svn_kind_t *kind;
-
-  kind = apr_palloc(pb->eb->edit_pool, sizeof(*kind));
-  *kind = svn_kind_dir;
-  SVN_ERR(add_action(pb->eb, path, ACTION_ADD, kind));
 
   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;
 }
 
@@ -394,7 +500,7 @@ ev2_change_dir_prop(void *dir_baton,
   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_SET_PROP, p_args));
+  SVN_ERR(add_action(db->eb, db->path, ACTION_PROPSET, p_args));
 
   return SVN_NO_ERROR;
 }
@@ -412,6 +518,11 @@ ev2_absent_directory(const char *path,
                      apr_pool_t *scratch_pool)
 {
   struct ev2_dir_baton *pb = parent_baton;
+  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_ABSENT, kind));
+
   return SVN_NO_ERROR;
 }
 
@@ -425,15 +536,32 @@ ev2_add_file(const char *path,
 {
   struct ev2_file_baton *fb = apr_palloc(result_pool, sizeof(*fb));
   struct ev2_dir_baton *pb = parent_baton;
-  svn_kind_t *kind;
 
   fb->eb = pb->eb;
   fb->path = apr_pstrdup(result_pool, path);
   *file_baton = fb;
 
-  kind = apr_palloc(pb->eb->edit_pool, sizeof(*kind));
-  *kind = svn_kind_file;
-  SVN_ERR(add_action(pb->eb, path, ACTION_ADD, kind));
+  SVN_ERR(fb->eb->fetch_base_func(&fb->delta_base,
+                                  fb->eb->fetch_base_baton,
+                                  path, result_pool, result_pool));
+
+  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;
 }
@@ -451,10 +579,37 @@ ev2_open_file(const char *path,
   fb->eb = pb->eb;
   fb->path = apr_pstrdup(result_pool, path);
 
+  SVN_ERR(fb->eb->fetch_base_func(&fb->delta_base,
+                                  fb->eb->fetch_base_baton,
+                                  path, result_pool, result_pool));
+
   *file_baton = fb;
   return SVN_NO_ERROR;
 }
 
+struct handler_baton
+{
+  svn_txdelta_window_handler_t apply_handler;
+  void *apply_baton;
+
+  apr_pool_t *pool;
+};
+
+static svn_error_t *
+window_handler(svn_txdelta_window_t *window, void *baton)
+{
+  struct handler_baton *hb = baton;
+  svn_error_t *err;
+
+  err = hb->apply_handler(window, hb->apply_baton);
+  if (window != NULL && !err)
+    return SVN_NO_ERROR;
+
+  svn_pool_destroy(hb->pool);
+
+  return svn_error_trace(err);
+}
+
 
 static svn_error_t *
 ev2_apply_textdelta(void *file_baton,
@@ -464,9 +619,40 @@ ev2_apply_textdelta(void *file_baton,
                     void **handler_baton)
 {
   struct ev2_file_baton *fb = file_baton;
+  apr_pool_t *handler_pool = svn_pool_create(fb->eb->edit_pool);
+  struct handler_baton *hb = apr_pcalloc(handler_pool, sizeof(*hb));
+  svn_stream_t *source;
+  svn_stream_t *target;
+  struct path_checksum_args *pca = apr_pcalloc(fb->eb->edit_pool,
+                                               sizeof(*pca));
+
+  if (! fb->delta_base)
+    source = svn_stream_empty(handler_pool);
+  else
+    SVN_ERR(svn_stream_open_readonly(&source, fb->delta_base, handler_pool,
+                                     result_pool));
+
+  SVN_ERR(svn_stream_open_unique(&target, &pca->path, NULL,
+                                 svn_io_file_del_on_pool_cleanup,
+                                 fb->eb->edit_pool, result_pool));
+
+  /* Wrap our target with a checksum'ing stream. */
+  target = svn_stream_checksummed2(target, NULL, &pca->checksum,
+                                   svn_checksum_sha1, TRUE,
+                                   fb->eb->edit_pool);
+
+  svn_txdelta_apply(source, target,
+                    NULL, NULL,
+                    handler_pool,
+                    &hb->apply_handler, &hb->apply_baton);
+
+  hb->pool = handler_pool;
+                    
+  *handler_baton = hb;
+  *handler = window_handler;
+
+  SVN_ERR(add_action(fb->eb, fb->path, ACTION_SET_TEXT, pca));
 
-  *handler_baton = NULL;
-  *handler = svn_delta_noop_window_handler;
   return SVN_NO_ERROR;
 }
 
@@ -482,7 +668,7 @@ ev2_change_file_prop(void *file_baton,
   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_SET_PROP, p_args));
+  SVN_ERR(add_action(fb->eb, fb->path, ACTION_PROPSET, p_args));
 
   return SVN_NO_ERROR;
 }
@@ -501,6 +687,11 @@ ev2_absent_file(const char *path,
                 apr_pool_t *scratch_pool)
 {
   struct ev2_dir_baton *pb = parent_baton;
+  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_ABSENT, kind));
+
   return SVN_NO_ERROR;
 }
 
@@ -545,13 +736,31 @@ start_edit_func(void *baton,
 }
 
 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,
+                  svn_delta_fetch_base_func_t fetch_base_func,
+                  void *fetch_base_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. */
@@ -577,14 +786,22 @@ delta_from_editor(const svn_delta_editor
 
   eb->editor = editor;
   eb->paths = apr_hash_make(pool);
-  eb->target_revision = SVN_INVALID_REVNUM;
   eb->edit_pool = pool;
+  eb->found_abs_paths = found_abs_paths;
+  *eb->found_abs_paths = FALSE;
+
   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->fetch_base_func = fetch_base_func;
+  eb->fetch_base_baton = fetch_base_baton;
+
+  eb->target_revision_func = target_revision;
+  eb->target_revision_baton = target_revision_baton;
+
   *dedit_baton = eb;
   *deditor = &delta_editor;
 
@@ -595,21 +812,13 @@ delta_from_editor(const svn_delta_editor
 
 
 
-typedef enum action_code_t {
-  ACTION_MV,
-  ACTION_MKDIR,
-  ACTION_CP,
-  ACTION_PROPSET,
-  ACTION_PUT,
-  ACTION_RM
-} action_code_t;
-
 struct operation {
   enum {
     OP_OPEN,
     OP_DELETE,
     OP_ADD,
     OP_REPLACE,
+    OP_ADD_ABSENT,
     OP_PROPSET           /* only for files for which no other operation is
                             occuring; directories are OP_OPEN with non-empty
                             props */
@@ -619,8 +828,9 @@ struct operation {
   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 *props;     /* const char *prop_name ->
+  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 */
 };
 
@@ -632,13 +842,18 @@ struct editor_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
@@ -657,7 +872,8 @@ get_operation(const char *path,
       child->operation = OP_OPEN;
       child->copyfrom_revision = SVN_INVALID_REVNUM;
       child->kind = svn_kind_dir;
-      child->props = NULL;
+      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);
     }
@@ -671,9 +887,9 @@ get_operation(const char *path,
       ACTION          URL    REV      SRC-FILE  PROPNAME
       ------------    -----  -------  --------  --------
       ACTION_MKDIR    NULL   invalid  NULL      NULL
-      ACTION_CP       valid  valid    NULL      NULL
+      ACTION_COPY     valid  valid    NULL      NULL
       ACTION_PUT      NULL   invalid  valid     NULL
-      ACTION_RM       NULL   invalid  NULL      NULL
+      ACTION_DELETE   NULL   invalid  NULL      NULL
       ACTION_PROPSET  valid  invalid  NULL      valid
 
    Node type information is obtained for any copy source (to determine
@@ -682,7 +898,7 @@ get_operation(const char *path,
    return an error on non-existent nodes). */
 static svn_error_t *
 build(struct editor_baton *eb,
-      action_code_t action,
+      enum action_code_t action,
       const char *relpath,
       svn_kind_t kind,
       const char *url,
@@ -715,8 +931,33 @@ build(struct editor_baton *eb,
   /* Handle property changes. */
   if (props)
     {
-      SVN_ERR(eb->fetch_kind_func(&operation->kind, eb->fetch_kind_baton,
-                                  relpath, scratch_pool));
+      apr_hash_t *current_props;
+      apr_array_header_t *propdiffs;
+
+      if (kind == svn_kind_unknown)
+        SVN_ERR(eb->fetch_kind_func(&operation->kind, eb->fetch_kind_baton,
+                                    relpath, scratch_pool));
+      else
+        operation->kind = kind;
+
+      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) ||
@@ -726,17 +967,19 @@ build(struct editor_baton *eb,
                    && (operation->operation == OP_OPEN))
             operation->operation = OP_PROPSET;
         }
-      operation->props = svn_prop_hash_dup(props, eb->edit_pool);
       if (!operation->copyfrom_revision)
         operation->copyfrom_revision = rev;
       return SVN_NO_ERROR;
     }
 
-  if (action == ACTION_RM)
+  if (action == ACTION_DELETE)
     operation->operation = OP_DELETE;
 
+  else if (action == ACTION_ADD_ABSENT)
+    operation->operation = OP_ADD_ABSENT;
+
   /* Handle copy operations (which can be adds or replacements). */
-  else if (action == ACTION_CP)
+  else if (action == ACTION_COPY)
     {
       operation->operation =
         operation->operation == OP_DELETE ? OP_REPLACE : OP_ADD;
@@ -815,6 +1058,11 @@ add_directory_cb(void *baton,
                 NULL, SVN_INVALID_REVNUM,
                 NULL, NULL, SVN_INVALID_REVNUM, scratch_pool));
 
+  if (props && apr_hash_count(props) > 0)
+    SVN_ERR(build(eb, ACTION_PROPSET, relpath, svn_kind_dir,
+                  NULL, SVN_INVALID_REVNUM, props,
+                  NULL, SVN_INVALID_REVNUM, scratch_pool));
+
   return SVN_NO_ERROR;
 }
 
@@ -845,6 +1093,11 @@ add_file_cb(void *baton,
                 NULL, SVN_INVALID_REVNUM,
                 NULL, tmp_filename, SVN_INVALID_REVNUM, scratch_pool));
 
+  if (props && apr_hash_count(props) > 0)
+    SVN_ERR(build(eb, ACTION_PROPSET, relpath, svn_kind_file,
+                  NULL, SVN_INVALID_REVNUM, props,
+                  NULL, SVN_INVALID_REVNUM, scratch_pool));
+
   return SVN_NO_ERROR;
 }
 
@@ -876,6 +1129,10 @@ add_absent_cb(void *baton,
 
   SVN_ERR(ensure_root_opened(eb));
 
+  SVN_ERR(build(eb, ACTION_ADD_ABSENT, relpath, kind,
+                NULL, SVN_INVALID_REVNUM,
+                NULL, NULL, SVN_INVALID_REVNUM, scratch_pool));
+
   return SVN_NO_ERROR;
 }
 
@@ -892,7 +1149,7 @@ set_props_cb(void *baton,
 
   SVN_ERR(ensure_root_opened(eb));
 
-  SVN_ERR(build(eb, ACTION_PROPSET, relpath, svn_kind_none,
+  SVN_ERR(build(eb, ACTION_PROPSET, relpath, svn_kind_unknown,
                 NULL, SVN_INVALID_REVNUM,
                 props, NULL, SVN_INVALID_REVNUM, scratch_pool));
 
@@ -954,6 +1211,10 @@ delete_cb(void *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;
 }
 
@@ -970,6 +1231,10 @@ copy_cb(void *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;
 }
 
@@ -990,9 +1255,57 @@ move_cb(void *baton,
 }
 
 static svn_error_t *
-drive(const struct operation *operation,
-      const svn_delta_editor_t *editor,
-      apr_pool_t *scratch_pool)
+change_props(const svn_delta_editor_t *editor,
+             void *baton,
+             const 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_tree(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;
@@ -1008,6 +1321,28 @@ drive(const struct operation *operation,
       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)
@@ -1022,6 +1357,15 @@ drive(const struct operation *operation,
                                      &file_baton));
         }
 
+      if (child->operation == OP_ADD_ABSENT)
+        {
+          if (child->kind == svn_kind_dir)
+            SVN_ERR(editor->absent_directory(path, operation->baton,
+                                             iterpool));
+          else
+            SVN_ERR(editor->absent_file(path, operation->baton, iterpool));
+        }
+
       if (child->src_file && file_baton)
         {
           /* We need to change textual contents. */
@@ -1038,9 +1382,36 @@ drive(const struct operation *operation,
           SVN_ERR(svn_stream_close(contents));
         }
 
-      /*SVN_DBG(("child: '%s'; operation: %d\n", path, child->operation));*/
-      if (child->kind == svn_kind_dir)
-        SVN_ERR(drive(child, editor, iterpool));
+      /* 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_tree(child, editor, make_abs_paths, iterpool));
+          SVN_ERR(editor->close_directory(child->baton, iterpool));
+        }
+    }
+  svn_pool_destroy(iterpool);
+
+  /* Finally, for this node, if it's a directory, change any props before
+     returning (our caller will close the directory. */
+  if (operation->kind == svn_kind_dir
+                   && (operation->operation == OP_OPEN
+                    || operation->operation == OP_PROPSET
+                    || operation->operation == OP_ADD))
+    {
+      SVN_ERR(change_props(editor, operation->baton, operation, scratch_pool));
     }
 
   return SVN_NO_ERROR;
@@ -1054,10 +1425,18 @@ complete_cb(void *baton,
   struct editor_baton *eb = baton;
   svn_error_t *err;
 
+  SVN_ERR(ensure_root_opened(eb));
+
   /* Drive the tree we've created. */
-  err = drive(&eb->root, eb->deditor, scratch_pool);
+  err = drive_tree(&eb->root, eb->deditor, eb->make_abs_paths, scratch_pool);
   if (!err)
-     err = eb->deditor->close_edit(eb->dedit_baton, scratch_pool);
+     {
+       err = eb->deditor->close_directory(eb->root.baton, scratch_pool);
+       err = svn_error_compose_create(err, eb->deditor->close_edit(
+                                                            eb->dedit_baton,
+                                                            scratch_pool));
+     }
+
   if (err)
     svn_error_clear(eb->deditor->abort_edit(eb->dedit_baton, scratch_pool));
 
@@ -1077,7 +1456,7 @@ abort_cb(void *baton,
      point. */
 
   /* Drive the tree we've created. */
-  err = drive(&eb->root, eb->deditor, scratch_pool);
+  err = drive_tree(&eb->root, eb->deditor, eb->make_abs_paths, scratch_pool);
 
   err2 = eb->deditor->abort_edit(eb->dedit_baton, scratch_pool);
 
@@ -1096,10 +1475,13 @@ 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)
 {
@@ -1127,14 +1509,18 @@ editor_from_delta(svn_editor_t **editor_
 
   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.props = NULL;
+  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));
@@ -1177,17 +1563,30 @@ svn_editor__insert_shims(const svn_delta
   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_tree() 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,
-                            NULL, NULL, shim_callbacks->fetch_kind_func,
+                            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,
+                            shim_callbacks->fetch_base_func,
+                            shim_callbacks->fetch_base_baton,
                             start_edit_func, seb,
+                            target_revision_func, seb,
                             result_pool));
 
 #endif

Modified: subversion/branches/file-handle-cache/subversion/libsvn_delta/editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/libsvn_delta/editor.c?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/libsvn_delta/editor.c (original)
+++ subversion/branches/file-handle-cache/subversion/libsvn_delta/editor.c Sun Dec 18 17:36:24 2011
@@ -605,7 +605,8 @@ svn_editor_complete(svn_editor_t *editor
 
   err = editor->funcs.cb_complete(editor->baton, editor->scratch_pool);
 #ifdef ENABLE_ORDERING_CHECK
-  editor->finished = TRUE;
+  if (!err)
+    editor->finished = TRUE;
 #endif
   svn_pool_clear(editor->scratch_pool);
   return err;

Modified: subversion/branches/file-handle-cache/subversion/libsvn_diff/diff_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/libsvn_diff/diff_file.c?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/libsvn_diff/diff_file.c (original)
+++ subversion/branches/file-handle-cache/subversion/libsvn_diff/diff_file.c Sun Dec 18 17:36:24 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--;

Modified: subversion/branches/file-handle-cache/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/libsvn_diff/parse-diff.c?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/branches/file-handle-cache/subversion/libsvn_diff/parse-diff.c Sun Dec 18 17:36:24 2011
@@ -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/file-handle-cache/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/libsvn_fs/fs-loader.c?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/file-handle-cache/subversion/libsvn_fs/fs-loader.c Sun Dec 18 17:36:24 2011
@@ -424,16 +424,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(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_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_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/file-handle-cache/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/libsvn_fs/fs-loader.h?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/file-handle-cache/subversion/libsvn_fs/fs-loader.h Sun Dec 18 17:36:24 2011
@@ -93,8 +93,11 @@ typedef struct fs_library_vtable_t
                             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/file-handle-cache/subversion/libsvn_fs_base/bdb/locks-table.c
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/libsvn_fs_base/bdb/locks-table.c?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/libsvn_fs_base/bdb/locks-table.c (original)
+++ subversion/branches/file-handle-cache/subversion/libsvn_fs_base/bdb/locks-table.c Sun Dec 18 17:36:24 2011
@@ -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/file-handle-cache/subversion/libsvn_fs_base/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/libsvn_fs_base/fs.c?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/libsvn_fs_base/fs.c (original)
+++ subversion/branches/file-handle-cache/subversion/libsvn_fs_base/fs.c Sun Dec 18 17:36:24 2011
@@ -1165,9 +1165,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 +1180,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/file-handle-cache/subversion/libsvn_fs_base/reps-strings.c
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/libsvn_fs_base/reps-strings.c?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/libsvn_fs_base/reps-strings.c (original)
+++ subversion/branches/file-handle-cache/subversion/libsvn_fs_base/reps-strings.c Sun Dec 18 17:36:24 2011
@@ -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/file-handle-cache/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/libsvn_fs_fs/caching.c?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/branches/file-handle-cache/subversion/libsvn_fs_fs/caching.c Sun Dec 18 17:36:24 2011
@@ -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)
       {

Modified: subversion/branches/file-handle-cache/subversion/libsvn_fs_fs/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/libsvn_fs_fs/dag.c?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/libsvn_fs_fs/dag.c (original)
+++ subversion/branches/file-handle-cache/subversion/libsvn_fs_fs/dag.c Sun Dec 18 17:36:24 2011
@@ -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/file-handle-cache/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/file-handle-cache/subversion/libsvn_fs_fs/fs.c?rev=1220465&r1=1220464&r2=1220465&view=diff
==============================================================================
--- subversion/branches/file-handle-cache/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/branches/file-handle-cache/subversion/libsvn_fs_fs/fs.c Sun Dec 18 17:36:24 2011
@@ -276,16 +276,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);
 }