subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From prabh...@apache.org
Subject svn commit: r1445542 [5/16] - in /subversion/branches/verify-keep-going: ./ build/generator/ build/generator/swig/ build/generator/templates/ build/win32/ contrib/server-side/fsfsfixer/fixer/ contrib/server-side/svncutter/ notes/ notes/api-errata/1.7/ ...
Date Wed, 13 Feb 2013 10:21:36 GMT
Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/mergeinfo.c?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/mergeinfo.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/mergeinfo.c Wed Feb 13 10:21:33 2013
@@ -217,8 +217,8 @@ svn_client__get_wc_mergeinfo(svn_mergein
   if (limit_abspath)
     SVN_ERR_ASSERT(svn_dirent_is_absolute(limit_abspath));
 
-  SVN_ERR(svn_wc__node_get_base(&base_revision, NULL, NULL, NULL, ctx->wc_ctx,
-                                local_abspath,
+  SVN_ERR(svn_wc__node_get_base(&base_revision, NULL, NULL, NULL, NULL,
+                                ctx->wc_ctx, local_abspath,
                                 scratch_pool, scratch_pool));
 
   iterpool = svn_pool_create(scratch_pool);
@@ -287,7 +287,7 @@ svn_client__get_wc_mergeinfo(svn_mergein
           local_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
 
           SVN_ERR(svn_wc__node_get_base(&parent_base_rev, NULL, NULL, NULL,
-                                        ctx->wc_ctx, local_abspath,
+                                        NULL, ctx->wc_ctx, local_abspath,
                                         scratch_pool, scratch_pool));
           SVN_ERR(svn_wc__node_get_changed_info(&parent_changed_rev,
                                                 NULL, NULL,
@@ -371,27 +371,16 @@ svn_client__get_wc_mergeinfo_catalog(svn
                                      apr_pool_t *result_pool,
                                      apr_pool_t *scratch_pool)
 {
-  const char *target_repos_rel_path;
+  const char *target_repos_relpath;
   svn_mergeinfo_t mergeinfo;
   const char *repos_root;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
   *mergeinfo_cat = NULL;
-  SVN_ERR(svn_wc__node_get_repos_info(&repos_root, NULL,
+  SVN_ERR(svn_wc__node_get_repos_info(NULL, &target_repos_relpath,
+                                      &repos_root, NULL,
                                       ctx->wc_ctx, local_abspath,
                                       scratch_pool, scratch_pool));
-  if (!repos_root)
-    {
-      if (walked_path)
-        *walked_path = "";
-      if (inherited)
-        *inherited = FALSE;
-      return SVN_NO_ERROR;
-    }
-
-  SVN_ERR(svn_wc__node_get_repos_relpath(&target_repos_rel_path,
-                                         ctx->wc_ctx, local_abspath,
-                                         scratch_pool, scratch_pool));
 
   /* Get the mergeinfo for the LOCAL_ABSPATH target and set *INHERITED and
      *WALKED_PATH. */
@@ -406,7 +395,7 @@ svn_client__get_wc_mergeinfo_catalog(svn
     {
       *mergeinfo_cat = apr_hash_make(result_pool);
       apr_hash_set(*mergeinfo_cat,
-                   apr_pstrdup(result_pool, target_repos_rel_path),
+                   apr_pstrdup(result_pool, target_repos_relpath),
                    APR_HASH_KEY_STRING, mergeinfo);
     }
 
@@ -438,9 +427,9 @@ svn_client__get_wc_mergeinfo_catalog(svn
           if (strcmp(node_abspath, local_abspath) == 0)
             continue; /* Already parsed in svn_client__get_wc_mergeinfo */
 
-          SVN_ERR(svn_wc__node_get_repos_relpath(&repos_relpath,
-                                                 ctx->wc_ctx, node_abspath,
-                                                 result_pool, scratch_pool));
+          SVN_ERR(svn_wc__node_get_repos_info(NULL, &repos_relpath, NULL, NULL,
+                                              ctx->wc_ctx, node_abspath,
+                                              result_pool, scratch_pool));
 
           SVN_ERR(svn_mergeinfo_parse(&subtree_mergeinfo, propval->data,
                                       result_pool));
@@ -1631,9 +1620,9 @@ svn_client_mergeinfo_get_merged(apr_hash
       if (! svn_path_is_url(path_or_url))
         {
           SVN_ERR(svn_dirent_get_absolute(&path_or_url, path_or_url, pool));
-          SVN_ERR(svn_wc__node_get_repos_relpath(&repos_relpath,
-                                                 ctx->wc_ctx, path_or_url,
-                                                 pool, pool));
+          SVN_ERR(svn_wc__node_get_repos_info(NULL, &repos_relpath, NULL, NULL,
+                                              ctx->wc_ctx, path_or_url,
+                                              pool, pool));
         }
       else
         {
@@ -1674,7 +1663,7 @@ svn_client_mergeinfo_log2(svn_boolean_t 
 {
   const char *log_target = NULL;
   const char *repos_root;
-  const char *target_repos_rel;
+  const char *target_repos_relpath;
   svn_mergeinfo_catalog_t target_mergeinfo_cat;
 
   /* A hash of paths, at or under TARGET_PATH_OR_URL, mapped to
@@ -1729,18 +1718,20 @@ svn_client_mergeinfo_log2(svn_boolean_t 
     {
       SVN_ERR(svn_dirent_get_absolute(&target_path_or_url,
                                       target_path_or_url, scratch_pool));
-      SVN_ERR(svn_wc__node_get_repos_relpath(&target_repos_rel,
-                                             ctx->wc_ctx, target_path_or_url,
-                                             scratch_pool, scratch_pool));
+      SVN_ERR(svn_wc__node_get_repos_info(NULL, &target_repos_relpath,
+                                          NULL, NULL,
+                                          ctx->wc_ctx, target_path_or_url,
+                                          scratch_pool, scratch_pool));
     }
   else
     {
-      target_repos_rel = svn_uri_skip_ancestor(repos_root, target_path_or_url,
-                                               scratch_pool);
+      target_repos_relpath = svn_uri_skip_ancestor(repos_root,
+                                                   target_path_or_url,
+                                                   scratch_pool);
 
       /* TARGET_REPOS_REL should be non-NULL, else get_mergeinfo
          should have failed.  */
-      SVN_ERR_ASSERT(target_repos_rel != NULL); 
+      SVN_ERR_ASSERT(target_repos_relpath != NULL); 
     }
 
   if (!target_mergeinfo_cat)
@@ -1759,7 +1750,7 @@ svn_client_mergeinfo_log2(svn_boolean_t 
         {
           target_mergeinfo_cat = apr_hash_make(scratch_pool);
           apr_hash_set(target_mergeinfo_cat,
-                       target_repos_rel,
+                       target_repos_relpath,
                        APR_HASH_KEY_STRING,
                        apr_hash_make(scratch_pool));
         }
@@ -1840,7 +1831,7 @@ svn_client_mergeinfo_log2(svn_boolean_t 
       svn_mergeinfo_t merged;
       const char *subtree_path = svn__apr_hash_index_key(hi_catalog);
       svn_boolean_t is_subtree = strcmp(subtree_path,
-                                        target_repos_rel) != 0;
+                                        target_repos_relpath) != 0;
       svn_pool_clear(iterpool);
 
       if (is_subtree)
@@ -1849,7 +1840,7 @@ svn_client_mergeinfo_log2(svn_boolean_t 
              then make a copy of SOURCE_HISTORY that is path adjusted
              for the subtree.  */
           const char *subtree_rel_path =
-            subtree_path + strlen(target_repos_rel) + 1;
+            subtree_path + strlen(target_repos_relpath) + 1;
 
           SVN_ERR(svn_mergeinfo__add_suffix_to_mergeinfo(
             &subtree_source_history, source_history,
@@ -2075,7 +2066,8 @@ svn_client_mergeinfo_log2(svn_boolean_t 
                                        finding_merged,
                                        master_inheritable_rangelist,
                                        target_mergeinfo_cat,
-                                       svn_fspath__join("/", target_repos_rel,
+                                       svn_fspath__join("/",
+                                                        target_repos_relpath,
                                                         scratch_pool),
                                        discover_changed_paths,
                                        revprops,

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/patch.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/patch.c?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/patch.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/patch.c Wed Feb 13 10:21:33 2013
@@ -2388,20 +2388,21 @@ create_missing_parents(patch_target_t *t
           target->skipped = TRUE;
           break;
         }
-      else if (wc_kind == svn_node_dir)
+      else if (disk_kind == svn_node_dir)
         {
-          if (is_deleted)
+          if (wc_kind == svn_node_dir && !is_deleted)
+            present_components++;
+          else if (is_deleted)
+            break;
+          else
             {
               target->skipped = TRUE;
               break;
             }
-
-          /* continue one level deeper */
-          present_components++;
         }
-      else if (disk_kind == svn_node_dir)
+      else if (wc_kind != svn_node_none && !is_deleted)
         {
-          /* Obstructed. ### BH: why? We can just add a directory */
+          /* Node is missing */
           target->skipped = TRUE;
           break;
         }
@@ -2412,7 +2413,6 @@ create_missing_parents(patch_target_t *t
           break;
         }
     }
-
   if (! target->skipped)
     {
       local_abspath = abs_wc_path;
@@ -2504,37 +2504,59 @@ install_patched_target(patch_target_t *t
   else
     {
       svn_node_kind_t parent_db_kind;
-
-      if (target->added)
+      if (target->added || target->replaced)
         {
+          const char *parent_abspath;
+
+          parent_abspath = svn_dirent_dirname(target->local_abspath,
+                                              pool);
           /* If the target's parent directory does not yet exist
            * we need to create it before we can copy the patched
            * result in place. */
           SVN_ERR(svn_wc_read_kind(&parent_db_kind, ctx->wc_ctx,
-                                   svn_dirent_dirname(target->local_abspath,
-                                                      pool),
-                                   FALSE, pool));
-
-          /* We don't allow targets to be added under dirs scheduled for
-           * deletion. */
-          if (parent_db_kind == svn_node_dir)
+                                   parent_abspath, FALSE, pool));
+
+          /* We can't add targets under nodes scheduled for delete, so add
+             a new directory if needed. */
+          if (parent_db_kind == svn_node_dir
+              || parent_db_kind == svn_node_file)
             {
-              const char *parent_abspath;
               svn_boolean_t is_deleted;
 
-              parent_abspath = svn_dirent_dirname(target->local_abspath,
-                                                  pool);
               SVN_ERR(svn_wc__node_is_status_deleted(&is_deleted, ctx->wc_ctx,
                                                      parent_abspath, pool));
               if (is_deleted)
+                SVN_ERR(create_missing_parents(target, abs_wc_path, ctx,
+                                               dry_run, pool));
+              else if (parent_db_kind != svn_node_dir)
+                target->skipped = TRUE;
+              else
                 {
-                  target->skipped = TRUE;
-                  return SVN_NO_ERROR;
+                  svn_node_kind_t disk_kind;
+
+                  SVN_ERR(svn_io_check_path(parent_abspath, &disk_kind, pool));
+                  if (disk_kind != svn_node_dir)
+                    target->skipped = TRUE;
                 }
             }
           else
             SVN_ERR(create_missing_parents(target, abs_wc_path, ctx,
                                            dry_run, pool));
+
+        }
+      else
+        {
+          svn_node_kind_t wc_kind;
+
+          /* The target should exist */
+          SVN_ERR(svn_wc_read_kind(&wc_kind, ctx->wc_ctx,
+                                   target->local_abspath, FALSE, pool));
+
+          if (target->kind_on_disk == svn_node_none
+              || wc_kind != target->kind_on_disk)
+            {
+              target->skipped = TRUE;
+            }
         }
 
       if (! dry_run && ! target->skipped)

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/ra.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/ra.c?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/ra.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/ra.c Wed Feb 13 10:21:33 2013
@@ -324,7 +324,8 @@ svn_client__open_ra_session_internal(svn
 
   if (base_dir_abspath)
     {
-      svn_error_t *err = svn_wc__node_get_repos_info(NULL, &uuid, ctx->wc_ctx,
+      svn_error_t *err = svn_wc__node_get_repos_info(NULL, NULL, NULL, &uuid,
+                                                     ctx->wc_ctx,
                                                      base_dir_abspath,
                                                      pool, pool);
 

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/repos_diff.c?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/repos_diff.c Wed Feb 13 10:21:33 2013
@@ -34,6 +34,7 @@
 
 #include <apr_uri.h>
 #include <apr_md5.h>
+#include <assert.h>
 
 #include "svn_checksum.h"
 #include "svn_hash.h"
@@ -57,7 +58,7 @@ struct edit_baton {
   svn_depth_t depth;
 
   /* The result processor */
-  svn_diff_tree_processor_t *processor;
+  const svn_diff_tree_processor_t *processor;
 
   /* RA_SESSION is the open session for making requests to the RA layer */
   svn_ra_session_t *ra_session;
@@ -77,10 +78,6 @@ struct edit_baton {
   /* Empty hash used for adds. */
   apr_hash_t *empty_hash;
 
-  /* TRUE if the operation needs to walk deleted dirs on the "old" side.
-     FALSE otherwise. */
-  svn_boolean_t walk_deleted_repos_dirs;
-
   /* Whether to report text deltas */
   svn_boolean_t text_deltas;
 
@@ -125,7 +122,7 @@ struct dir_baton {
 
   /* The baton for the parent directory, or null if this is the root of the
      hierarchy to be compared. */
-  struct dir_baton *dir_baton;
+  struct dir_baton *parent_baton;
 
   /* The overall crawler editor baton. */
   struct edit_baton *edit_baton;
@@ -147,11 +144,17 @@ struct dir_baton {
 
   /* Base revision of directory. */
   svn_revnum_t base_revision;
+
+  /* Number of users of baton. Its pool will be destroyed 0 */
+  int users;
 };
 
 /* File level baton.
  */
 struct file_baton {
+  /* Reference to parent baton */
+  struct dir_baton *parent_baton;
+
   /* Gets set if the file is added rather than replaced. */
   svn_boolean_t added;
 
@@ -223,12 +226,12 @@ make_dir_baton(const char *path,
                struct edit_baton *edit_baton,
                svn_boolean_t added,
                svn_revnum_t base_revision,
-               apr_pool_t *pool)
+               apr_pool_t *result_pool)
 {
-  apr_pool_t *dir_pool = svn_pool_create(pool);
+  apr_pool_t *dir_pool = svn_pool_create(result_pool);
   struct dir_baton *dir_baton = apr_pcalloc(dir_pool, sizeof(*dir_baton));
 
-  dir_baton->dir_baton = parent_baton;
+  dir_baton->parent_baton = parent_baton;
   dir_baton->edit_baton = edit_baton;
   dir_baton->added = added;
   dir_baton->tree_conflicted = FALSE;
@@ -236,12 +239,38 @@ make_dir_baton(const char *path,
   dir_baton->skip_children = FALSE;
   dir_baton->pool = dir_pool;
   dir_baton->path = apr_pstrdup(dir_pool, path);
-  dir_baton->propchanges  = apr_array_make(pool, 8, sizeof(svn_prop_t));
+  dir_baton->propchanges  = apr_array_make(dir_pool, 8, sizeof(svn_prop_t));
   dir_baton->base_revision = base_revision;
+  dir_baton->users++;
+
+  if (parent_baton)
+    parent_baton->users++;
 
   return dir_baton;
 }
 
+/* New function. Called by everyone who has a reference when done */
+static svn_error_t *
+release_dir(struct dir_baton *db)
+{
+  assert(db->users > 0);
+
+  db->users--;
+  if (db->users)
+     return SVN_NO_ERROR;
+
+  {
+    struct dir_baton *pb = db->parent_baton;
+
+    svn_pool_destroy(db->pool);
+
+    if (pb != NULL)
+      SVN_ERR(release_dir(pb));
+  }
+
+  return SVN_NO_ERROR;
+}
+
 /* Create a new file baton for PATH in POOL, which is a child of
  * directory PARENT_PATH. ADDED is set if this file is being added
  * rather than replaced.  EDIT_BATON is a pointer to the global edit
@@ -249,21 +278,24 @@ make_dir_baton(const char *path,
  */
 static struct file_baton *
 make_file_baton(const char *path,
+                struct dir_baton *parent_baton,
                 svn_boolean_t added,
-                struct edit_baton *edit_baton,
-                apr_pool_t *pool)
+                apr_pool_t *result_pool)
 {
-  apr_pool_t *file_pool = svn_pool_create(pool);
+  apr_pool_t *file_pool = svn_pool_create(result_pool);
   struct file_baton *file_baton = apr_pcalloc(file_pool, sizeof(*file_baton));
 
-  file_baton->edit_baton = edit_baton;
+  file_baton->parent_baton = parent_baton;
+  file_baton->edit_baton = parent_baton->edit_baton;
   file_baton->added = added;
   file_baton->tree_conflicted = FALSE;
   file_baton->skip = FALSE;
   file_baton->pool = file_pool;
   file_baton->path = apr_pstrdup(file_pool, path);
-  file_baton->propchanges  = apr_array_make(pool, 8, sizeof(svn_prop_t));
-  file_baton->base_revision = edit_baton->revision;
+  file_baton->propchanges  = apr_array_make(file_pool, 8, sizeof(svn_prop_t));
+  file_baton->base_revision = parent_baton->edit_baton->revision;
+
+  parent_baton->users++;
 
   return file_baton;
 }
@@ -424,11 +456,23 @@ open_root(void *edit_baton,
 {
   struct edit_baton *eb = edit_baton;
   struct dir_baton *db = make_dir_baton("", NULL, eb, FALSE, base_revision,
-                                        pool);
+                                        eb->pool);
 
   db->left_source = svn_diff__source_create(eb->revision, db->pool);
   db->right_source = svn_diff__source_create(eb->target_revision, db->pool);
 
+  SVN_ERR(eb->processor->dir_opened(&db->pdb,
+                                    &db->skip,
+                                    &db->skip_children,
+                                    "",
+                                    db->left_source,
+                                    db->right_source,
+                                    NULL,
+                                    NULL,
+                                    eb->processor,
+                                    db->pool,
+                                    db->pool /* scratch_pool */));
+
   *root_baton = db;
   return SVN_NO_ERROR;
 }
@@ -437,11 +481,11 @@ open_root(void *edit_baton,
  */
 static svn_error_t *
 diff_deleted_file(const char *path,
-                  void *ppdb,
-                  struct edit_baton *eb,
+                  struct dir_baton *db,
                   apr_pool_t *scratch_pool)
 {
-  struct file_baton *fb = make_file_baton(path, FALSE, eb, scratch_pool);
+  struct edit_baton *eb = db->edit_baton;
+  struct file_baton *fb = make_file_baton(path, db, FALSE, scratch_pool);
   svn_boolean_t skip = FALSE;
   svn_diff_source_t *left_source = svn_diff__source_create(eb->revision,
                                                            scratch_pool);
@@ -453,7 +497,7 @@ diff_deleted_file(const char *path,
                                      left_source,
                                      NULL /* right_source */,
                                      NULL /* copyfrom_source */,
-                                     ppdb,
+                                     db->pdb,
                                      eb->processor,
                                      scratch_pool, scratch_pool));
 
@@ -487,10 +531,11 @@ diff_deleted_file(const char *path,
 /* ### TODO: Handle depth. */
 static svn_error_t *
 diff_deleted_dir(const char *path,
-                 void *ppdb,
-                 struct edit_baton *eb,
+                 struct dir_baton *pb,
                  apr_pool_t *scratch_pool)
 {
+  struct edit_baton *eb = pb->edit_baton;
+  struct dir_baton *db;
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
   svn_boolean_t skip = FALSE;
   svn_boolean_t skip_children = FALSE;
@@ -498,19 +543,20 @@ diff_deleted_dir(const char *path,
   apr_hash_t *left_props = NULL;
   svn_diff_source_t *left_source = svn_diff__source_create(eb->revision,
                                                            scratch_pool);
-  void *pdb;
+  db = make_dir_baton(path, pb, pb->edit_baton, FALSE, SVN_INVALID_REVNUM,
+                      scratch_pool);
 
   SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(eb->revision));
 
   if (eb->cancel_func)
     SVN_ERR(eb->cancel_func(eb->cancel_baton));
 
-  SVN_ERR(eb->processor->dir_opened(&pdb, &skip, &skip_children,
+  SVN_ERR(eb->processor->dir_opened(&db->pdb, &skip, &skip_children,
                                     path,
                                     left_source,
                                     NULL /* right_source */,
                                     NULL /* copyfrom_source */,
-                                    ppdb,
+                                    pb->pdb,
                                     eb->processor,
                                     scratch_pool, iterpool));
 
@@ -528,7 +574,7 @@ diff_deleted_dir(const char *path,
    * crawl it recursively, diffing each file against the empty file.  This
    * is a workaround for issue 2333 "'svn diff URL1 URL2' not reverse of
    * 'svn diff URL2 URL1'". */
-  if (! skip_children && eb->walk_deleted_repos_dirs)
+  if (! skip_children)
     {
       apr_hash_index_t *hi;
 
@@ -545,11 +591,11 @@ diff_deleted_dir(const char *path,
 
           if (dirent->kind == svn_node_file)
             {
-              SVN_ERR(diff_deleted_file(child_path, pdb, eb, iterpool));
+              SVN_ERR(diff_deleted_file(child_path, db, iterpool));
             }
           else if (dirent->kind == svn_node_dir)
             {
-              SVN_ERR(diff_deleted_dir(child_path, pdb, eb, iterpool));
+              SVN_ERR(diff_deleted_dir(child_path, db, iterpool));
             }
         }
     }
@@ -559,11 +605,13 @@ diff_deleted_dir(const char *path,
       SVN_ERR(eb->processor->dir_deleted(path,
                                          left_source,
                                          left_props,
-                                         pdb,
+                                         db->pdb,
                                          eb->processor,
                                          scratch_pool));
     }
 
+  SVN_ERR(release_dir(db));
+
   svn_pool_destroy(iterpool);
   return SVN_NO_ERROR;
 }
@@ -594,12 +642,12 @@ delete_entry(const char *path,
     {
     case svn_node_file:
       {
-        SVN_ERR(diff_deleted_file(path, pb->pdb, eb, scratch_pool));
+        SVN_ERR(diff_deleted_file(path, pb, scratch_pool));
         break;
       }
     case svn_node_dir:
       {
-        SVN_ERR(diff_deleted_dir(path, pb->pdb, eb, scratch_pool));
+        SVN_ERR(diff_deleted_dir(path, pb, scratch_pool));
         break;
       }
     default:
@@ -626,7 +674,7 @@ add_directory(const char *path,
 
   /* ### TODO: support copyfrom? */
 
-  db = make_dir_baton(path, pb, eb, TRUE, SVN_INVALID_REVNUM, pool);
+  db = make_dir_baton(path, pb, eb, TRUE, SVN_INVALID_REVNUM, pb->pool);
   *child_baton = db;
 
   /* Skip *everything* within a newly tree-conflicted directory,
@@ -667,7 +715,7 @@ open_directory(const char *path,
   struct edit_baton *eb = pb->edit_baton;
   struct dir_baton *db;
 
-  db = make_dir_baton(path, pb, eb, FALSE, base_revision, pool);
+  db = make_dir_baton(path, pb, eb, FALSE, base_revision, pb->pool);
 
   *child_baton = db;
 
@@ -711,7 +759,7 @@ add_file(const char *path,
 
   /* ### TODO: support copyfrom? */
 
-  fb = make_file_baton(path, TRUE, pb->edit_baton, pool);
+  fb = make_file_baton(path, pb, TRUE, pb->pool);
   *file_baton = fb;
 
   /* Process Skips. */
@@ -749,7 +797,7 @@ open_file(const char *path,
   struct dir_baton *pb = parent_baton;
   struct file_baton *fb;
   struct edit_baton *eb = pb->edit_baton;
-  fb = make_file_baton(path, FALSE, pb->edit_baton, pool);
+  fb = make_file_baton(path, pb, FALSE, pb->pool);
   *file_baton = fb;
 
   /* Process Skips. */
@@ -892,6 +940,7 @@ close_file(void *file_baton,
            apr_pool_t *pool)
 {
   struct file_baton *fb = file_baton;
+  struct dir_baton *pb = fb->parent_baton;
   struct edit_baton *eb = fb->edit_baton;
   apr_pool_t *scratch_pool;
 
@@ -899,6 +948,7 @@ close_file(void *file_baton,
   if (fb->skip)
     {
       svn_pool_destroy(fb->pool);
+      SVN_ERR(release_dir(pb));
       return SVN_NO_ERROR;
     }
 
@@ -967,6 +1017,8 @@ close_file(void *file_baton,
 
   svn_pool_destroy(fb->pool); /* Destroy file and scratch pool */
 
+  SVN_ERR(release_dir(pb));
+
   return SVN_NO_ERROR;
 }
 
@@ -1050,8 +1102,7 @@ close_directory(void *dir_baton,
                                         eb->processor,
                                         db->pool));
     }
-
-  svn_pool_destroy(db->pool); /* Destroy baton and scratch_pool */
+  SVN_ERR(release_dir(db));
 
   return SVN_NO_ERROR;
 }
@@ -1260,292 +1311,35 @@ fetch_base_func(const char **filename,
   return SVN_NO_ERROR;
 }
 
-/* Baton for diff_state_* functions */
-struct diff_notify_baton_t
-{
-  /* Hash used to check replaced paths. Key is path relative CWD,
-   * Value is *deleted_path_notify_t.
-   * All allocations are from edit_baton's pool. */
-  apr_hash_t *deleted_paths;
-
-  /* If the func is non-null, send notifications of actions. */
-  svn_wc_notify_func2_t notify_func;
-  void *notify_baton;
-
-  /* If not NULL collects the absent paths */
-  apr_hash_t *absent_relpaths;
-
-  apr_pool_t *pool;
-};
-
-/** Callback for the svn_diff_tree_processor_t wrapper, to allow handling
- *  notifications like how the repos diff in libsvn_client does.
- *
- * Probably only necessary while transitioning to svn_diff_tree_processor_t
- */
-static svn_error_t *
-diff_state_handle(svn_boolean_t tree_conflicted,
-                  svn_wc_notify_state_t *state,
-                  svn_wc_notify_state_t *prop_state,
-                  const char *relpath,
-                  svn_kind_t kind,
-                  svn_boolean_t before_operation,
-                  svn_boolean_t for_add,
-                  svn_boolean_t for_delete,
-                  void *state_baton,
-                  apr_pool_t *scratch_pool)
-{
-  struct diff_notify_baton_t *dnb = state_baton;
-  svn_wc_notify_state_t notify_content_state = svn_wc_notify_state_inapplicable;
-  svn_wc_notify_state_t notify_prop_state = svn_wc_notify_state_inapplicable;
-
-  if (! dnb->notify_func)
-    return SVN_NO_ERROR;
-
-  if ((for_delete && before_operation && !tree_conflicted)
-      || (for_add && kind == svn_kind_dir && !before_operation))
-    return SVN_NO_ERROR;
-
-  if (for_delete)
-    {
-      const char *deleted_path;
-      deleted_path_notify_t *dpn;
-      svn_wc_notify_action_t action;
-
-      deleted_path = apr_pstrdup(dnb->pool, relpath);
-      dpn = apr_pcalloc(dnb->pool, sizeof(*dpn));
-
-      if (!tree_conflicted
-          && state
-             && (*state != svn_wc_notify_state_missing)
-             && (*state != svn_wc_notify_state_obstructed))
-        {
-          action = svn_wc_notify_update_delete;
-        }
-      else
-        action = svn_wc_notify_skip;
-
-      dpn->kind = (kind == svn_kind_dir) ? svn_node_dir : svn_node_file;
-      dpn->action = tree_conflicted ? svn_wc_notify_tree_conflict : action;
-      dpn->state = state ? *state : svn_wc_notify_state_inapplicable;
-      dpn->tree_conflicted = tree_conflicted;
-      apr_hash_set(dnb->deleted_paths, deleted_path, APR_HASH_KEY_STRING, dpn);
-
-      return SVN_NO_ERROR;
-    }
-
-  if (tree_conflicted)
-    {
-      svn_wc_notify_t *notify;
-      deleted_path_notify_t *dpn;
-      svn_node_kind_t notify_kind;
-
-      apr_hash_set(dnb->deleted_paths, relpath,
-                   APR_HASH_KEY_STRING, NULL);
-
-      notify = svn_wc_create_notify(relpath, svn_wc_notify_tree_conflict,
-                                    scratch_pool);
-
-      dpn = apr_hash_get(dnb->deleted_paths, relpath, APR_HASH_KEY_STRING);
-      if (dpn)
-        {
-          /* If any was found, we will handle the pending 'deleted path
-          * notification' (DPN) here. Remove it from the list. */
-          apr_hash_set(dnb->deleted_paths, relpath,
-              APR_HASH_KEY_STRING, NULL);
-
-          /* the pending delete might be on a different node kind. */
-          notify_kind = dpn->kind;
-        }
-
-      notify->kind = notify_kind;
-      (*dnb->notify_func)(dnb->notify_baton, notify, scratch_pool);
-      return SVN_NO_ERROR;
-    }
-
-  if (state)
-    notify_content_state = *state;
-  if (prop_state)
-    notify_prop_state = *prop_state;
-
-  /* These states apply to properties (dirs) and content (files) at the same
-     time, so handle them as the same whatever way we got them. */
-  if (notify_prop_state == svn_wc_notify_state_obstructed
-      || notify_prop_state == svn_wc_notify_state_missing)
-    {
-      notify_content_state = notify_prop_state;
-    }
-
-  if (notify_content_state == svn_wc_notify_state_obstructed
-      || notify_content_state == svn_wc_notify_state_missing)
-    {
-      svn_wc_notify_t *notify;
-
-      notify = svn_wc_create_notify(relpath, svn_wc_notify_skip,
-                                    scratch_pool);
-
-      notify->kind = (kind == svn_kind_dir) ? svn_node_dir : svn_node_file;
-      notify->content_state = notify_content_state;
-      notify->prop_state = notify_prop_state;
-      (*dnb->notify_func)(dnb->notify_baton, notify, scratch_pool);
-      return SVN_NO_ERROR;
-    }
-
-  /* This code is only used from the merge api, and should really be
-     integrated there. */
-
-  {
-    deleted_path_notify_t *dpn;
-    svn_wc_notify_t *notify;
-    svn_wc_notify_action_t action;
-    svn_node_kind_t notify_kind = (kind == svn_kind_dir) ? svn_node_dir
-                                                         : svn_node_file;
-
-    if (for_add)
-      action = svn_wc_notify_update_add;
-    else
-      action = svn_wc_notify_update_update;
-
-    /* Find out if a pending delete notification for this path is
-    * still around. */
-    dpn = apr_hash_get(dnb->deleted_paths, relpath, APR_HASH_KEY_STRING);
-    if (dpn)
-      {
-        /* If any was found, we will handle the pending 'deleted path
-        * notification' (DPN) here. Remove it from the list. */
-        apr_hash_set(dnb->deleted_paths, relpath,
-                     APR_HASH_KEY_STRING, NULL);
-
-        /* the pending delete might be on a different node kind. */
-        notify_kind = dpn->kind;
-        notify_content_state = notify_prop_state = dpn->state;
-
-        if (for_add && dpn->action == svn_wc_notify_update_delete)
-          action = svn_wc_notify_update_replace;
-      }
-
-    notify = svn_wc_create_notify(relpath, action, scratch_pool);
-    notify->kind = notify_kind;
-    notify->content_state = notify_content_state;
-    notify->prop_state = notify_prop_state;
-    (*dnb->notify_func)(dnb->notify_baton, notify, scratch_pool);
-  }
-
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-diff_state_close(const char *relpath,
-                 svn_kind_t kind,
-                 void *state_baton,
-                 apr_pool_t *scratch_pool)
-{
-  struct diff_notify_baton_t *dnb = state_baton;
-  apr_hash_index_t *hi;
-
-  if (! dnb->notify_func)
-    return SVN_NO_ERROR;
-
-  for (hi = apr_hash_first(scratch_pool, dnb->deleted_paths); hi;
-       hi = apr_hash_next(hi))
-    {
-      svn_wc_notify_t *notify;
-      const char *deleted_path = svn__apr_hash_index_key(hi);
-      deleted_path_notify_t *dpn = svn__apr_hash_index_val(hi);
-
-      /* Ignore paths which are not children of bb->path.  (There
-         should be none due to editor ordering constraints, but
-         ra_serf drops the ball here -- see issue #3802 for
-         details.) */
-      if (! svn_relpath_skip_ancestor(relpath, deleted_path))
-        continue;
-
-      notify = svn_wc_create_notify(deleted_path, dpn->action, scratch_pool);
-      notify->kind = dpn->kind;
-      notify->content_state = notify->prop_state = dpn->state;
-      notify->lock_state = svn_wc_notify_lock_state_inapplicable;
-      (*dnb->notify_func)(dnb->notify_baton, notify, scratch_pool);
-      apr_hash_set(dnb->deleted_paths, deleted_path,
-                   APR_HASH_KEY_STRING, NULL);
-    }
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-diff_state_absent(const char *relpath,
-                  void *state_baton,
-                  apr_pool_t *scratch_pool)
-{
-  struct diff_notify_baton_t *dnb = state_baton;
-
-  if (dnb->notify_func)
-    {
-      svn_wc_notify_t *notify
-        = svn_wc_create_notify(relpath, svn_wc_notify_skip, scratch_pool);
-
-      notify->kind = svn_node_unknown;
-      notify->content_state = notify->prop_state
-        = svn_wc_notify_state_missing;
-      (*dnb->notify_func)(dnb->notify_baton, notify, scratch_pool);
-    }
-
-  if (dnb->absent_relpaths)
-    apr_hash_set(dnb->absent_relpaths,
-                 apr_pstrdup(apr_hash_pool_get(dnb->absent_relpaths), relpath),
-                 APR_HASH_KEY_STRING,
-                 "");
-
-  return SVN_NO_ERROR;
-}
-
 /* Create a repository diff editor and baton.  */
 svn_error_t *
-svn_client__get_diff_editor(const svn_delta_editor_t **editor,
-                            void **edit_baton,
-                            svn_depth_t depth,
-                            svn_ra_session_t *ra_session,
-                            svn_revnum_t revision,
-                            svn_boolean_t walk_deleted_dirs,
-                            svn_boolean_t text_deltas,
-                            apr_hash_t *absent_relpaths,
-                            const svn_wc_diff_callbacks4_t *diff_callbacks,
-                            void *diff_cmd_baton,
-                            svn_cancel_func_t cancel_func,
-                            void *cancel_baton,
-                            svn_wc_notify_func2_t notify_func,
-                            void *notify_baton,
-                            apr_pool_t *result_pool)
+svn_client__get_diff_editor2(const svn_delta_editor_t **editor,
+                             void **edit_baton,
+                             svn_ra_session_t *ra_session,
+                             svn_depth_t depth,
+                             svn_revnum_t revision,
+                             svn_boolean_t text_deltas,
+                             const svn_diff_tree_processor_t *processor,
+                             svn_cancel_func_t cancel_func,
+                             void *cancel_baton,
+                             apr_pool_t *result_pool)
 {
   apr_pool_t *editor_pool = svn_pool_create(result_pool);
   svn_delta_editor_t *tree_editor = svn_delta_default_editor(editor_pool);
   struct edit_baton *eb = apr_pcalloc(editor_pool, sizeof(*eb));
-  struct diff_notify_baton_t *dnb = apr_pcalloc(editor_pool, sizeof(*eb));
   svn_delta_shim_callbacks_t *shim_callbacks =
                                 svn_delta_shim_callbacks_default(editor_pool);
 
   eb->pool = editor_pool;
   eb->depth = depth;
 
-  dnb->pool = editor_pool;
-  dnb->deleted_paths = apr_hash_make(eb->pool);
-  dnb->notify_func = notify_func;
-  dnb->notify_baton = notify_baton;
-  dnb->absent_relpaths = absent_relpaths;
-
-  SVN_ERR(svn_wc__wrap_diff_callbacks(&eb->processor,
-                                      diff_callbacks, diff_cmd_baton,
-                                      diff_state_handle,
-                                      diff_state_close,
-                                      diff_state_absent,
-                                      dnb,
-                                      result_pool, result_pool));
+  eb->processor = processor;
 
   eb->ra_session = ra_session;
 
   eb->revision = revision;
   eb->empty_file = NULL;
   eb->empty_hash = apr_hash_make(eb->pool);
-  eb->walk_deleted_repos_dirs = walk_deleted_dirs;
   eb->text_deltas = text_deltas;
   eb->cancel_func = cancel_func;
   eb->cancel_baton = cancel_baton;

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/resolved.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/resolved.c?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/resolved.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/resolved.c Wed Feb 13 10:21:33 2013
@@ -55,17 +55,19 @@ svn_client_resolve(const char *path,
 
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
 
-  SVN_ERR(svn_wc__resolve_conflicts(ctx->wc_ctx, local_abspath,
-                                    depth,
-                                    TRUE /* resolve_text */,
-                                    "" /* resolve_prop (ALL props) */,
-                                    TRUE /* resolve_tree */,
-                                    conflict_choice,
-                                    ctx->conflict_func2,
-                                    ctx->conflict_baton2,
-                                    ctx->cancel_func, ctx->cancel_baton,
-                                    ctx->notify_func2, ctx->notify_baton2,
-                                    pool));
+  SVN_WC__CALL_WITH_WRITE_LOCK(
+      svn_wc__resolve_conflicts(ctx->wc_ctx, local_abspath,
+                                depth,
+                                TRUE /* resolve_text */,
+                                "" /* resolve_prop (ALL props) */,
+                                TRUE /* resolve_tree */,
+                                conflict_choice,
+                                ctx->conflict_func2,
+                                ctx->conflict_baton2,
+                                ctx->cancel_func, ctx->cancel_baton,
+                                ctx->notify_func2, ctx->notify_baton2,
+                                pool),
+      ctx->wc_ctx, local_abspath, TRUE, pool);
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/util.c?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/util.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/util.c Wed Feb 13 10:21:33 2013
@@ -183,6 +183,7 @@ svn_client__wc_node_get_base(svn_client_
                                 &relpath,
                                 &(*base_p)->repos_root_url,
                                 &(*base_p)->repos_uuid,
+                                NULL,
                                 wc_ctx, wc_abspath,
                                 result_pool, scratch_pool));
   if ((*base_p)->repos_root_url && relpath)
@@ -241,10 +242,23 @@ svn_client_get_repos_root(const char **r
   /* If PATH_OR_URL is a local path we can fetch the repos root locally. */
   if (!svn_path_is_url(abspath_or_url))
     {
-      SVN_ERR(svn_wc__node_get_repos_info(repos_root, repos_uuid,
-                                          ctx->wc_ctx, abspath_or_url,
-                                          result_pool, scratch_pool));
-
+      svn_error_t *err;
+      err = svn_wc__node_get_repos_info(NULL, NULL, repos_root, repos_uuid,
+                                        ctx->wc_ctx, abspath_or_url,
+                                        result_pool, scratch_pool);
+
+      if (err)
+        {
+          if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND
+              && err->apr_err != SVN_ERR_WC_NOT_WORKING_COPY)
+            return svn_error_trace(err);
+
+          svn_error_clear(err);
+          if (repos_root)
+            *repos_root = NULL;
+          if (repos_uuid)
+            *repos_uuid = NULL;
+        }
       return SVN_NO_ERROR;
     }
 

Modified: subversion/branches/verify-keep-going/subversion/libsvn_diff/diff_tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_diff/diff_tree.c?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_diff/diff_tree.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_diff/diff_tree.c Wed Feb 13 10:21:33 2013
@@ -25,6 +25,8 @@
 #include <apr_pools.h>
 #include <apr_general.h>
 
+#include <assert.h>
+
 #include "svn_dirent_uri.h"
 #include "svn_error.h"
 #include "svn_pools.h"
@@ -237,7 +239,7 @@ svn_diff__tree_processor_create(void *ba
 
 struct reverse_tree_baton_t
 {
-  svn_diff_tree_processor_t *processor;
+  const svn_diff_tree_processor_t *processor;
   const char *prefix_relpath;
 };
 
@@ -538,14 +540,14 @@ reverse_node_absent(const char *relpath,
 
   SVN_ERR(rb->processor->node_absent(relpath,
                                     dir_baton,
-                                    processor,
+                                    rb->processor,
                                     scratch_pool));
   return SVN_NO_ERROR;
 }
 
 
 const svn_diff_tree_processor_t *
-svn_diff__tree_processor_reverse_create(svn_diff_tree_processor_t * processor,
+svn_diff__tree_processor_reverse_create(const svn_diff_tree_processor_t * processor,
                                         const char *prefix_relpath,
                                         apr_pool_t *result_pool)
 {
@@ -576,6 +578,1110 @@ svn_diff__tree_processor_reverse_create(
   return reverse;
 }
 
+struct filter_tree_baton_t
+{
+  const svn_diff_tree_processor_t *processor;
+  const char *prefix_relpath;
+};
+
+static svn_error_t *
+filter_dir_opened(void **new_dir_baton,
+                  svn_boolean_t *skip,
+                  svn_boolean_t *skip_children,
+                  const char *relpath,
+                  const svn_diff_source_t *left_source,
+                  const svn_diff_source_t *right_source,
+                  const svn_diff_source_t *copyfrom_source,
+                  void *parent_dir_baton,
+                  const svn_diff_tree_processor_t *processor,
+                  apr_pool_t *result_pool,
+                  apr_pool_t *scratch_pool)
+{
+  struct filter_tree_baton_t *fb = processor->baton;
+
+  relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath);
+
+  if (! relpath)
+    {
+      /* Skip work for this, but NOT for DESCENDANTS */
+      *skip = TRUE;
+      return SVN_NO_ERROR;
+    }
+
+  SVN_ERR(fb->processor->dir_opened(new_dir_baton, skip, skip_children,
+                                    relpath,
+                                    left_source, right_source,
+                                    copyfrom_source,
+                                    parent_dir_baton,
+                                    fb->processor,
+                                    result_pool, scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+filter_dir_added(const char *relpath,
+                 const svn_diff_source_t *copyfrom_source,
+                 const svn_diff_source_t *right_source,
+                 /*const*/ apr_hash_t *copyfrom_props,
+                 /*const*/ apr_hash_t *right_props,
+                 void *dir_baton,
+                 const svn_diff_tree_processor_t *processor,
+                 apr_pool_t *scratch_pool)
+{
+  struct filter_tree_baton_t *fb = processor->baton;
+
+  relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath);
+  assert(relpath != NULL); /* Driver error */
+
+  SVN_ERR(fb->processor->dir_added(relpath,
+                                   copyfrom_source,
+                                   right_source,
+                                   copyfrom_props,
+                                   right_props,
+                                   dir_baton,
+                                   fb->processor,
+                                   scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+filter_dir_deleted(const char *relpath,
+                   const svn_diff_source_t *left_source,
+                   /*const*/ apr_hash_t *left_props,
+                   void *dir_baton,
+                   const svn_diff_tree_processor_t *processor,
+                   apr_pool_t *scratch_pool)
+{
+  struct filter_tree_baton_t *fb = processor->baton;
+
+  relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath);
+  assert(relpath != NULL); /* Driver error */
+
+  SVN_ERR(fb->processor->dir_deleted(relpath,
+                                     left_source,
+                                     left_props,
+                                     dir_baton,
+                                     fb->processor,
+                                     scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+filter_dir_changed(const char *relpath,
+                   const svn_diff_source_t *left_source,
+                   const svn_diff_source_t *right_source,
+                   /*const*/ apr_hash_t *left_props,
+                   /*const*/ apr_hash_t *right_props,
+                   const apr_array_header_t *prop_changes,
+                   void *dir_baton,
+                   const struct svn_diff_tree_processor_t *processor,
+                   apr_pool_t *scratch_pool)
+{
+  struct filter_tree_baton_t *fb = processor->baton;
+
+  relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath);
+  assert(relpath != NULL); /* Driver error */
+
+  SVN_ERR(fb->processor->dir_changed(relpath,
+                                     left_source,
+                                     right_source,
+                                     left_props,
+                                     right_props,
+                                     prop_changes,
+                                     dir_baton,
+                                     fb->processor,
+                                     scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+filter_dir_closed(const char *relpath,
+                  const svn_diff_source_t *left_source,
+                  const svn_diff_source_t *right_source,
+                  void *dir_baton,
+                  const svn_diff_tree_processor_t *processor,
+                  apr_pool_t *scratch_pool)
+{
+  struct filter_tree_baton_t *fb = processor->baton;
+
+  relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath);
+  assert(relpath != NULL); /* Driver error */
+
+  SVN_ERR(fb->processor->dir_closed(relpath,
+                                    left_source,
+                                    right_source,
+                                    dir_baton,
+                                    fb->processor,
+                                    scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+filter_file_opened(void **new_file_baton,
+                   svn_boolean_t *skip,
+                   const char *relpath,
+                   const svn_diff_source_t *left_source,
+                   const svn_diff_source_t *right_source,
+                   const svn_diff_source_t *copyfrom_source,
+                   void *dir_baton,
+                   const svn_diff_tree_processor_t *processor,
+                   apr_pool_t *result_pool,
+                   apr_pool_t *scratch_pool)
+{
+  struct filter_tree_baton_t *fb = processor->baton;
+
+  relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath);
+
+  if (! relpath)
+    {
+      *skip = TRUE;
+      return SVN_NO_ERROR;
+    }
+
+  SVN_ERR(fb->processor->file_opened(new_file_baton,
+                                     skip,
+                                     relpath,
+                                     left_source,
+                                     right_source,
+                                     copyfrom_source,
+                                     dir_baton,
+                                     fb->processor,
+                                     result_pool,
+                                     scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+filter_file_added(const char *relpath,
+                  const svn_diff_source_t *copyfrom_source,
+                  const svn_diff_source_t *right_source,
+                  const char *copyfrom_file,
+                  const char *right_file,
+                  /*const*/ apr_hash_t *copyfrom_props,
+                  /*const*/ apr_hash_t *right_props,
+                  void *file_baton,
+                  const svn_diff_tree_processor_t *processor,
+                  apr_pool_t *scratch_pool)
+{
+  struct filter_tree_baton_t *fb = processor->baton;
+
+  relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath);
+  assert(relpath != NULL); /* Driver error */
+
+  SVN_ERR(fb->processor->file_added(relpath,
+                                    copyfrom_source,
+                                    right_source,
+                                    copyfrom_file,
+                                    right_file,
+                                    copyfrom_props,
+                                    right_props,
+                                    file_baton,
+                                    fb->processor,
+                                    scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+filter_file_deleted(const char *relpath,
+                    const svn_diff_source_t *left_source,
+                    const char *left_file,
+                    /*const*/ apr_hash_t *left_props,
+                    void *file_baton,
+                    const svn_diff_tree_processor_t *processor,
+                    apr_pool_t *scratch_pool)
+{
+  struct filter_tree_baton_t *fb = processor->baton;
+
+  relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath);
+  assert(relpath != NULL); /* Driver error */
+
+  SVN_ERR(fb->processor->file_deleted(relpath,
+                                      left_source,
+                                      left_file,
+                                      left_props,
+                                      file_baton,
+                                      fb->processor,
+                                      scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+filter_file_changed(const char *relpath,
+                    const svn_diff_source_t *left_source,
+                    const svn_diff_source_t *right_source,
+                    const char *left_file,
+                    const char *right_file,
+                    /*const*/ apr_hash_t *left_props,
+                    /*const*/ apr_hash_t *right_props,
+                    svn_boolean_t file_modified,
+                    const apr_array_header_t *prop_changes,
+                    void *file_baton,
+                    const svn_diff_tree_processor_t *processor,
+                    apr_pool_t *scratch_pool)
+{
+  struct filter_tree_baton_t *fb = processor->baton;
+
+  relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath);
+  assert(relpath != NULL); /* Driver error */
+
+  SVN_ERR(fb->processor->file_changed(relpath,
+                                      left_source,
+                                      right_source,
+                                      left_file,
+                                      right_file,
+                                      left_props,
+                                      right_props,
+                                      file_modified,
+                                      prop_changes,
+                                      file_baton,
+                                      fb->processor,
+                                      scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+filter_file_closed(const char *relpath,
+                   const svn_diff_source_t *left_source,
+                   const svn_diff_source_t *right_source,
+                   void *file_baton,
+                   const svn_diff_tree_processor_t *processor,
+                   apr_pool_t *scratch_pool)
+{
+  struct filter_tree_baton_t *fb = processor->baton;
+
+  relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath);
+  assert(relpath != NULL); /* Driver error */
+
+  SVN_ERR(fb->processor->file_closed(relpath,
+                                     left_source,
+                                     right_source,
+                                     file_baton,
+                                     fb->processor,
+                                     scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+filter_node_absent(const char *relpath,
+                   void *dir_baton,
+                   const svn_diff_tree_processor_t *processor,
+                   apr_pool_t *scratch_pool)
+{
+  struct filter_tree_baton_t *fb = processor->baton;
+
+  relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath);
+  assert(relpath != NULL); /* Driver error */
+
+  SVN_ERR(fb->processor->node_absent(relpath,
+                                    dir_baton,
+                                    fb->processor,
+                                    scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+
+const svn_diff_tree_processor_t *
+svn_diff__tree_processor_filter_create(const svn_diff_tree_processor_t * processor,
+                                        const char *prefix_relpath,
+                                        apr_pool_t *result_pool)
+{
+  struct filter_tree_baton_t *fb;
+  svn_diff_tree_processor_t *filter;
+
+  fb = apr_pcalloc(result_pool, sizeof(*fb));
+  fb->processor = processor;
+  if (prefix_relpath)
+    fb->prefix_relpath = apr_pstrdup(result_pool, prefix_relpath);
+
+  filter = svn_diff__tree_processor_create(fb, result_pool);
+
+  filter->dir_opened   = filter_dir_opened;
+  filter->dir_added    = filter_dir_added;
+  filter->dir_deleted  = filter_dir_deleted;
+  filter->dir_changed  = filter_dir_changed;
+  filter->dir_closed   = filter_dir_closed;
+
+  filter->file_opened   = filter_file_opened;
+  filter->file_added    = filter_file_added;
+  filter->file_deleted  = filter_file_deleted;
+  filter->file_changed  = filter_file_changed;
+  filter->file_closed   = filter_file_closed;
+
+  filter->node_absent   = filter_node_absent;
+
+  return filter;
+}
+
+struct copy_as_changed_baton_t
+{
+  const svn_diff_tree_processor_t *processor;
+};
+
+static svn_error_t *
+copy_as_changed_dir_opened(void **new_dir_baton,
+                           svn_boolean_t *skip,
+                           svn_boolean_t *skip_children,
+                           const char *relpath,
+                           const svn_diff_source_t *left_source,
+                           const svn_diff_source_t *right_source,
+                           const svn_diff_source_t *copyfrom_source,
+                           void *parent_dir_baton,
+                           const svn_diff_tree_processor_t *processor,
+                           apr_pool_t *result_pool,
+                           apr_pool_t *scratch_pool)
+{
+  struct copy_as_changed_baton_t *cb = processor->baton;
+
+  if (!left_source && copyfrom_source)
+    {
+      assert(right_source != NULL);
+
+      left_source = copyfrom_source;
+      copyfrom_source = NULL;
+    }
+
+  SVN_ERR(cb->processor->dir_opened(new_dir_baton, skip, skip_children,
+                                    relpath,
+                                    left_source, right_source,
+                                    copyfrom_source,
+                                    parent_dir_baton,
+                                    cb->processor,
+                                    result_pool, scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+copy_as_changed_dir_added(const char *relpath,
+                          const svn_diff_source_t *copyfrom_source,
+                          const svn_diff_source_t *right_source,
+                          /*const*/ apr_hash_t *copyfrom_props,
+                          /*const*/ apr_hash_t *right_props,
+                          void *dir_baton,
+                          const svn_diff_tree_processor_t *processor,
+                          apr_pool_t *scratch_pool)
+{
+  struct copy_as_changed_baton_t *cb = processor->baton;
+
+  if (copyfrom_source)
+    {
+      apr_array_header_t *propchanges;
+      SVN_ERR(svn_prop_diffs(&propchanges, right_props, copyfrom_props,
+                             scratch_pool));
+      SVN_ERR(cb->processor->dir_changed(relpath,
+                                         copyfrom_source,
+                                         right_source,
+                                         copyfrom_props,
+                                         right_props,
+                                         propchanges,
+                                         dir_baton,
+                                         cb->processor,
+                                         scratch_pool));
+    }
+  else
+    {
+      SVN_ERR(cb->processor->dir_added(relpath,
+                                       copyfrom_source,
+                                       right_source,
+                                       copyfrom_props,
+                                       right_props,
+                                       dir_baton,
+                                       cb->processor,
+                                       scratch_pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+copy_as_changed_dir_deleted(const char *relpath,
+                            const svn_diff_source_t *left_source,
+                            /*const*/ apr_hash_t *left_props,
+                            void *dir_baton,
+                            const svn_diff_tree_processor_t *processor,
+                            apr_pool_t *scratch_pool)
+{
+  struct copy_as_changed_baton_t *cb = processor->baton;
+
+  SVN_ERR(cb->processor->dir_deleted(relpath,
+                                     left_source,
+                                     left_props,
+                                     dir_baton,
+                                     cb->processor,
+                                     scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+copy_as_changed_dir_changed(const char *relpath,
+                            const svn_diff_source_t *left_source,
+                            const svn_diff_source_t *right_source,
+                            /*const*/ apr_hash_t *left_props,
+                            /*const*/ apr_hash_t *right_props,
+                            const apr_array_header_t *prop_changes,
+                            void *dir_baton,
+                            const struct svn_diff_tree_processor_t *processor,
+                            apr_pool_t *scratch_pool)
+{
+  struct copy_as_changed_baton_t *cb = processor->baton;
+
+  SVN_ERR(cb->processor->dir_changed(relpath,
+                                     left_source,
+                                     right_source,
+                                     left_props,
+                                     right_props,
+                                     prop_changes,
+                                     dir_baton,
+                                     cb->processor,
+                                     scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+copy_as_changed_dir_closed(const char *relpath,
+                           const svn_diff_source_t *left_source,
+                           const svn_diff_source_t *right_source,
+                           void *dir_baton,
+                           const svn_diff_tree_processor_t *processor,
+                           apr_pool_t *scratch_pool)
+{
+  struct copy_as_changed_baton_t *cb = processor->baton;
+
+  SVN_ERR(cb->processor->dir_closed(relpath,
+                                    left_source,
+                                    right_source,
+                                    dir_baton,
+                                    cb->processor,
+                                    scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+copy_as_changed_file_opened(void **new_file_baton,
+                            svn_boolean_t *skip,
+                            const char *relpath,
+                            const svn_diff_source_t *left_source,
+                            const svn_diff_source_t *right_source,
+                            const svn_diff_source_t *copyfrom_source,
+                            void *dir_baton,
+                            const svn_diff_tree_processor_t *processor,
+                            apr_pool_t *result_pool,
+                            apr_pool_t *scratch_pool)
+{
+  struct copy_as_changed_baton_t *cb = processor->baton;
+
+  if (!left_source && copyfrom_source)
+    {
+      assert(right_source != NULL);
+
+      left_source = copyfrom_source;
+      copyfrom_source = NULL;
+    }
+
+  SVN_ERR(cb->processor->file_opened(new_file_baton,
+                                     skip,
+                                     relpath,
+                                     left_source,
+                                     right_source,
+                                     copyfrom_source,
+                                     dir_baton,
+                                     cb->processor,
+                                     result_pool,
+                                     scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+copy_as_changed_file_added(const char *relpath,
+                           const svn_diff_source_t *copyfrom_source,
+                           const svn_diff_source_t *right_source,
+                           const char *copyfrom_file,
+                           const char *right_file,
+                           /*const*/ apr_hash_t *copyfrom_props,
+                           /*const*/ apr_hash_t *right_props,
+                           void *file_baton,
+                           const svn_diff_tree_processor_t *processor,
+                           apr_pool_t *scratch_pool)
+{
+  struct copy_as_changed_baton_t *cb = processor->baton;
+
+  if (copyfrom_source)
+    {
+      apr_array_header_t *propchanges;
+      SVN_ERR(svn_prop_diffs(&propchanges, right_props, copyfrom_props,
+                             scratch_pool));
+
+      SVN_ERR(cb->processor->file_changed(relpath,
+                                          copyfrom_source,
+                                          right_source,
+                                          copyfrom_file,
+                                          right_file,
+                                          copyfrom_props,
+                                          right_props,
+                                          copyfrom_file && right_file,
+                                          propchanges,
+                                          file_baton,
+                                          cb->processor,
+                                          scratch_pool));
+    }
+  else
+    {
+      SVN_ERR(cb->processor->file_added(relpath,
+                                        copyfrom_source,
+                                        right_source,
+                                        copyfrom_file,
+                                        right_file,
+                                        copyfrom_props,
+                                        right_props,
+                                        file_baton,
+                                        cb->processor,
+                                        scratch_pool));
+    }
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+copy_as_changed_file_deleted(const char *relpath,
+                             const svn_diff_source_t *left_source,
+                             const char *left_file,
+                             /*const*/ apr_hash_t *left_props,
+                             void *file_baton,
+                             const svn_diff_tree_processor_t *processor,
+                             apr_pool_t *scratch_pool)
+{
+  struct copy_as_changed_baton_t *cb = processor->baton;
+
+  SVN_ERR(cb->processor->file_deleted(relpath,
+                                      left_source,
+                                      left_file,
+                                      left_props,
+                                      file_baton,
+                                      cb->processor,
+                                      scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+copy_as_changed_file_changed(const char *relpath,
+                             const svn_diff_source_t *left_source,
+                             const svn_diff_source_t *right_source,
+                             const char *left_file,
+                             const char *right_file,
+                             /*const*/ apr_hash_t *left_props,
+                             /*const*/ apr_hash_t *right_props,
+                             svn_boolean_t file_modified,
+                             const apr_array_header_t *prop_changes,
+                             void *file_baton,
+                             const svn_diff_tree_processor_t *processor,
+                             apr_pool_t *scratch_pool)
+{
+  struct copy_as_changed_baton_t *cb = processor->baton;
+
+  SVN_ERR(cb->processor->file_changed(relpath,
+                                      left_source,
+                                      right_source,
+                                      left_file,
+                                      right_file,
+                                      left_props,
+                                      right_props,
+                                      file_modified,
+                                      prop_changes,
+                                      file_baton,
+                                      cb->processor,
+                                      scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+copy_as_changed_file_closed(const char *relpath,
+                            const svn_diff_source_t *left_source,
+                            const svn_diff_source_t *right_source,
+                            void *file_baton,
+                            const svn_diff_tree_processor_t *processor,
+                            apr_pool_t *scratch_pool)
+{
+  struct copy_as_changed_baton_t *cb = processor->baton;
+
+  SVN_ERR(cb->processor->file_closed(relpath,
+                                     left_source,
+                                     right_source,
+                                     file_baton,
+                                     cb->processor,
+                                     scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+copy_as_changed_node_absent(const char *relpath,
+                            void *dir_baton,
+                            const svn_diff_tree_processor_t *processor,
+                            apr_pool_t *scratch_pool)
+{
+  struct copy_as_changed_baton_t *cb = processor->baton;
+
+  SVN_ERR(cb->processor->node_absent(relpath,
+                                    dir_baton,
+                                    cb->processor,
+                                    scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+
+const svn_diff_tree_processor_t *
+svn_diff__tree_processor_copy_as_changed_create(
+                        const svn_diff_tree_processor_t * processor,
+                        apr_pool_t *result_pool)
+{
+  struct copy_as_changed_baton_t *cb;
+  svn_diff_tree_processor_t *filter;
+
+  cb = apr_pcalloc(result_pool, sizeof(*cb));
+  cb->processor = processor;
+
+  filter = svn_diff__tree_processor_create(cb, result_pool);
+  filter->dir_opened   = copy_as_changed_dir_opened;
+  filter->dir_added    = copy_as_changed_dir_added;
+  filter->dir_deleted  = copy_as_changed_dir_deleted;
+  filter->dir_changed  = copy_as_changed_dir_changed;
+  filter->dir_closed   = copy_as_changed_dir_closed;
+
+  filter->file_opened   = copy_as_changed_file_opened;
+  filter->file_added    = copy_as_changed_file_added;
+  filter->file_deleted  = copy_as_changed_file_deleted;
+  filter->file_changed  = copy_as_changed_file_changed;
+  filter->file_closed   = copy_as_changed_file_closed;
+
+  filter->node_absent   = copy_as_changed_node_absent;
+
+  return filter;
+}
+
+
+/* Processor baton for the tee tree processor */
+struct tee_baton_t
+{
+  const svn_diff_tree_processor_t *p1;
+  const svn_diff_tree_processor_t *p2;
+};
+
+/* Wrapper baton for file and directory batons in the tee processor */
+struct tee_node_baton_t
+{
+  void *baton1;
+  void *baton2;
+};
+
+static svn_error_t *
+tee_dir_opened(void **new_dir_baton,
+               svn_boolean_t *skip,
+               svn_boolean_t *skip_children,
+               const char *relpath,
+               const svn_diff_source_t *left_source,
+               const svn_diff_source_t *right_source,
+               const svn_diff_source_t *copyfrom_source,
+               void *parent_dir_baton,
+               const svn_diff_tree_processor_t *processor,
+               apr_pool_t *result_pool,
+               apr_pool_t *scratch_pool)
+{
+  struct tee_baton_t *tb = processor->baton;
+  struct tee_node_baton_t *pb = parent_dir_baton;
+  struct tee_node_baton_t *nb = apr_pcalloc(result_pool, sizeof(*nb));
+
+  SVN_ERR(tb->p1->dir_opened(&(nb->baton1),
+                             skip,
+                             skip_children,
+                             relpath,
+                             left_source,
+                             right_source,
+                             copyfrom_source,
+                             pb ? pb->baton1 : NULL,
+                             tb->p1,
+                             result_pool,
+                             scratch_pool));
+
+  SVN_ERR(tb->p2->dir_opened(&(nb->baton2),
+                             skip,
+                             skip_children,
+                             relpath,
+                             left_source,
+                             right_source,
+                             copyfrom_source,
+                             pb ? pb->baton2 : NULL,
+                             tb->p2,
+                             result_pool,
+                             scratch_pool));
+
+  *new_dir_baton = nb;
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+tee_dir_added(const char *relpath,
+              const svn_diff_source_t *copyfrom_source,
+              const svn_diff_source_t *right_source,
+              /*const*/ apr_hash_t *copyfrom_props,
+              /*const*/ apr_hash_t *right_props,
+              void *dir_baton,
+              const svn_diff_tree_processor_t *processor,
+              apr_pool_t *scratch_pool)
+{
+  struct tee_baton_t *tb = processor->baton;
+  struct tee_node_baton_t *db = dir_baton;
+
+  SVN_ERR(tb->p1->dir_added(relpath,
+                            copyfrom_source,
+                            right_source,
+                            copyfrom_props,
+                            right_props,
+                            db->baton1,
+                            tb->p1,
+                            scratch_pool));
+
+  SVN_ERR(tb->p2->dir_added(relpath,
+                            copyfrom_source,
+                            right_source,
+                            copyfrom_props,
+                            right_props,
+                            db->baton2,
+                            tb->p2,
+                            scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+tee_dir_deleted(const char *relpath,
+                const svn_diff_source_t *left_source,
+                /*const*/ apr_hash_t *left_props,
+                void *dir_baton,
+                const svn_diff_tree_processor_t *processor,
+                apr_pool_t *scratch_pool)
+{
+  struct tee_baton_t *tb = processor->baton;
+  struct tee_node_baton_t *db = dir_baton;
+
+  SVN_ERR(tb->p1->dir_deleted(relpath,
+                              left_source,
+                              left_props,
+                              db->baton1,
+                              tb->p1,
+                              scratch_pool));
+
+  SVN_ERR(tb->p2->dir_deleted(relpath,
+                              left_source,
+                              left_props,
+                              db->baton2,
+                              tb->p2,
+                              scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+tee_dir_changed(const char *relpath,
+                    const svn_diff_source_t *left_source,
+                    const svn_diff_source_t *right_source,
+                    /*const*/ apr_hash_t *left_props,
+                    /*const*/ apr_hash_t *right_props,
+                    const apr_array_header_t *prop_changes,
+                    void *dir_baton,
+                    const struct svn_diff_tree_processor_t *processor,
+                    apr_pool_t *scratch_pool)
+{
+  struct tee_baton_t *tb = processor->baton;
+  struct tee_node_baton_t *db = dir_baton;
+
+  SVN_ERR(tb->p1->dir_changed(relpath,
+                              left_source,
+                              right_source,
+                              left_props,
+                              right_props,
+                              prop_changes,
+                              db->baton1,
+                              tb->p1,
+                              scratch_pool));
+
+  SVN_ERR(tb->p2->dir_changed(relpath,
+                              left_source,
+                              right_source,
+                              left_props,
+                              right_props,
+                              prop_changes,
+                              db->baton2,
+                              tb->p2,
+                              scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+tee_dir_closed(const char *relpath,
+               const svn_diff_source_t *left_source,
+               const svn_diff_source_t *right_source,
+               void *dir_baton,
+               const svn_diff_tree_processor_t *processor,
+               apr_pool_t *scratch_pool)
+{
+  struct tee_baton_t *tb = processor->baton;
+  struct tee_node_baton_t *db = dir_baton;
+
+  SVN_ERR(tb->p1->dir_closed(relpath,
+                             left_source,
+                             right_source,
+                             db->baton1,
+                             tb->p1,
+                             scratch_pool));
+
+  SVN_ERR(tb->p2->dir_closed(relpath,
+                             left_source,
+                             right_source,
+                             db->baton2,
+                             tb->p2,
+                             scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+tee_file_opened(void **new_file_baton,
+                svn_boolean_t *skip,
+                const char *relpath,
+                const svn_diff_source_t *left_source,
+                const svn_diff_source_t *right_source,
+                const svn_diff_source_t *copyfrom_source,
+                void *dir_baton,
+                const svn_diff_tree_processor_t *processor,
+                apr_pool_t *result_pool,
+                apr_pool_t *scratch_pool)
+{
+  struct tee_baton_t *tb = processor->baton;
+  struct tee_node_baton_t *pb = dir_baton;
+  struct tee_node_baton_t *nb = apr_pcalloc(result_pool, sizeof(*nb));
+
+  SVN_ERR(tb->p1->file_opened(&(nb->baton1),
+                              skip,
+                              relpath,
+                              left_source,
+                              right_source,
+                              copyfrom_source,
+                              pb ? pb->baton1 : NULL,
+                              tb->p1,
+                              result_pool,
+                              scratch_pool));
+
+  SVN_ERR(tb->p2->file_opened(&(nb->baton2),
+                              skip,
+                              relpath,
+                              left_source,
+                              right_source,
+                              copyfrom_source,
+                              pb ? pb->baton2 : NULL,
+                              tb->p2,
+                              result_pool,
+                              scratch_pool));
+
+  *new_file_baton = nb;
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+tee_file_added(const char *relpath,
+               const svn_diff_source_t *copyfrom_source,
+               const svn_diff_source_t *right_source,
+               const char *copyfrom_file,
+               const char *right_file,
+               /*const*/ apr_hash_t *copyfrom_props,
+               /*const*/ apr_hash_t *right_props,
+               void *file_baton,
+               const svn_diff_tree_processor_t *processor,
+               apr_pool_t *scratch_pool)
+{
+  struct tee_baton_t *tb = processor->baton;
+  struct tee_node_baton_t *fb = file_baton;
+
+  SVN_ERR(tb->p1->file_added(relpath,
+                             copyfrom_source,
+                             right_source,
+                             copyfrom_file,
+                             right_file,
+                             copyfrom_props,
+                             right_props,
+                             fb->baton1,
+                             tb->p1,
+                             scratch_pool));
+
+  SVN_ERR(tb->p2->file_added(relpath,
+                             copyfrom_source,
+                             right_source,
+                             copyfrom_file,
+                             right_file,
+                             copyfrom_props,
+                             right_props,
+                             fb->baton2,
+                             tb->p2,
+                             scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+tee_file_deleted(const char *relpath,
+                 const svn_diff_source_t *left_source,
+                 const char *left_file,
+                 /*const*/ apr_hash_t *left_props,
+                 void *file_baton,
+                 const svn_diff_tree_processor_t *processor,
+                 apr_pool_t *scratch_pool)
+{
+  struct tee_baton_t *tb = processor->baton;
+  struct tee_node_baton_t *fb = file_baton;
+
+  SVN_ERR(tb->p1->file_deleted(relpath,
+                               left_source,
+                               left_file,
+                               left_props,
+                               fb->baton1,
+                               tb->p1,
+                               scratch_pool));
+
+  SVN_ERR(tb->p2->file_deleted(relpath,
+                               left_source,
+                               left_file,
+                               left_props,
+                               fb->baton2,
+                               tb->p2,
+                               scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+tee_file_changed(const char *relpath,
+                 const svn_diff_source_t *left_source,
+                 const svn_diff_source_t *right_source,
+                 const char *left_file,
+                 const char *right_file,
+                 /*const*/ apr_hash_t *left_props,
+                 /*const*/ apr_hash_t *right_props,
+                 svn_boolean_t file_modified,
+                 const apr_array_header_t *prop_changes,
+                 void *file_baton,
+                 const svn_diff_tree_processor_t *processor,
+                 apr_pool_t *scratch_pool)
+{
+  struct tee_baton_t *tb = processor->baton;
+  struct tee_node_baton_t *fb = file_baton;
+
+  SVN_ERR(tb->p1->file_changed(relpath,
+                               left_source,
+                               right_source,
+                               left_file,
+                               right_file,
+                               left_props,
+                               right_props,
+                               file_modified,
+                               prop_changes,
+                               fb->baton1,
+                               tb->p1,
+                               scratch_pool));
+
+  SVN_ERR(tb->p2->file_changed(relpath,
+                               left_source,
+                               right_source,
+                               left_file,
+                               right_file,
+                               left_props,
+                               right_props,
+                               file_modified,
+                               prop_changes,
+                               fb->baton2,
+                               tb->p2,
+                               scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+tee_file_closed(const char *relpath,
+                    const svn_diff_source_t *left_source,
+                    const svn_diff_source_t *right_source,
+                    void *file_baton,
+                    const svn_diff_tree_processor_t *processor,
+                    apr_pool_t *scratch_pool)
+{
+  struct tee_baton_t *tb = processor->baton;
+  struct tee_node_baton_t *fb = file_baton;
+
+  SVN_ERR(tb->p1->file_closed(relpath,
+                              left_source,
+                              right_source,
+                              fb->baton1,
+                              tb->p1,
+                              scratch_pool));
+
+  SVN_ERR(tb->p2->file_closed(relpath,
+                              left_source,
+                              right_source,
+                              fb->baton2,
+                              tb->p2,
+                              scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+tee_node_absent(const char *relpath,
+                void *dir_baton,
+                const svn_diff_tree_processor_t *processor,
+                apr_pool_t *scratch_pool)
+{
+  struct tee_baton_t *tb = processor->baton;
+  struct tee_node_baton_t *db = dir_baton;
+
+  SVN_ERR(tb->p1->node_absent(relpath,
+                              db ? db->baton1 : NULL,
+                              tb->p1,
+                              scratch_pool));
+
+  SVN_ERR(tb->p2->node_absent(relpath,
+                              db ? db->baton2 : NULL,
+                              tb->p2,
+                              scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+const svn_diff_tree_processor_t *
+svn_diff__tree_processor_tee_create(const svn_diff_tree_processor_t *processor1,
+                                    const svn_diff_tree_processor_t *processor2,
+                                    apr_pool_t *result_pool)
+{
+  struct tee_baton_t *tb = apr_pcalloc(result_pool, sizeof(*tb));
+  svn_diff_tree_processor_t *tee;
+  tb->p1 = processor1;
+  tb->p2 = processor2;
+
+  tee = svn_diff__tree_processor_create(tb, result_pool);
+
+  tee->dir_opened    = tee_dir_opened;
+  tee->dir_added     = tee_dir_added;
+  tee->dir_deleted   = tee_dir_deleted;
+  tee->dir_changed   = tee_dir_changed;
+  tee->dir_closed    = tee_dir_closed;
+  tee->file_opened   = tee_file_opened;
+  tee->file_added    = tee_file_added;
+  tee->file_deleted  = tee_file_deleted;
+  tee->file_changed  = tee_file_changed;
+  tee->file_closed   = tee_file_closed;
+  tee->node_absent   = tee_node_absent;
+
+  return tee;
+}
+
 svn_diff_source_t *
 svn_diff__source_create(svn_revnum_t revision,
                         apr_pool_t *result_pool)

Modified: subversion/branches/verify-keep-going/subversion/libsvn_fs_fs/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_fs_fs/dag.c?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_fs_fs/dag.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_fs_fs/dag.c Wed Feb 13 10:21:33 2013
@@ -1095,7 +1095,7 @@ svn_fs_fs__dag_serialize(void **data,
   svn_temp_serializer__context_t *context =
       svn_temp_serializer__init(node,
                                 sizeof(*node),
-                                503,
+                                1007,
                                 pool);
 
   /* for mutable nodes, we will _never_ cache the noderev */

Modified: subversion/branches/verify-keep-going/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_fs_fs/fs_fs.c?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_fs_fs/fs_fs.c Wed Feb 13 10:21:33 2013
@@ -2244,7 +2244,7 @@ get_cached_node_revision_body(node_revis
     }
   else
     {
-      pair_cache_key_t key;
+      pair_cache_key_t key = { 0 };
 
       key.revision = svn_fs_fs__id_rev(id);
       key.second = svn_fs_fs__id_offset(id);
@@ -2273,7 +2273,7 @@ set_cached_node_revision_body(node_revis
 
   if (ffd->node_revision_cache && !svn_fs_fs__id_txn_id(id))
     {
-      pair_cache_key_t key;
+      pair_cache_key_t key = { 0 };
 
       key.revision = svn_fs_fs__id_rev(id);
       key.second = svn_fs_fs__id_offset(id);
@@ -3536,7 +3536,7 @@ parse_revprop(apr_hash_t **properties,
   if (has_revprop_cache(fs, pool))
     {
       fs_fs_data_t *ffd = fs->fsap_data;
-      pair_cache_key_t key;
+      pair_cache_key_t key = { 0 };
 
       key.revision = revision;
       key.second = generation;
@@ -3839,7 +3839,7 @@ get_revision_proplist(apr_hash_t **propl
   if (has_revprop_cache(fs, pool))
     {
       svn_boolean_t is_cached;
-      pair_cache_key_t key;
+      pair_cache_key_t key = { 0 };
 
       SVN_ERR(read_revprop_generation(&generation, fs, pool));
 
@@ -5192,7 +5192,7 @@ read_representation(svn_stream_t **conte
   else
     {
       fs_fs_data_t *ffd = fs->fsap_data;
-      pair_cache_key_t fulltext_cache_key;
+      pair_cache_key_t fulltext_cache_key = { 0 };
       svn_filesize_t len = rep->expanded_size ? rep->expanded_size : rep->size;
       struct rep_read_baton *rb;
 
@@ -5366,7 +5366,7 @@ svn_fs_fs__try_process_file_contents(svn
   if (rep)
     {
       fs_fs_data_t *ffd = fs->fsap_data;
-      pair_cache_key_t fulltext_cache_key;
+      pair_cache_key_t fulltext_cache_key = { 0 };
 
       fulltext_cache_key.revision = rep->revision;
       fulltext_cache_key.second = rep->offset;
@@ -5673,7 +5673,7 @@ svn_fs_fs__get_proplist(apr_hash_t **pro
     {
       fs_fs_data_t *ffd = fs->fsap_data;
       representation_t *rep = noderev->prop_rep;
-      pair_cache_key_t key;
+      pair_cache_key_t key = { 0 };
 
       key.revision = rep->revision;
       key.second = rep->offset;

Modified: subversion/branches/verify-keep-going/subversion/libsvn_fs_fs/rep-cache-db.sql
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_fs_fs/rep-cache-db.sql?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_fs_fs/rep-cache-db.sql (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_fs_fs/rep-cache-db.sql Wed Feb 13 10:21:33 2013
@@ -22,8 +22,6 @@
  */
 
 -- STMT_CREATE_SCHEMA
-PRAGMA AUTO_VACUUM = 1;
-
 /* A table mapping representation hashes to locations in a rev file. */
 CREATE TABLE rep_cache (
   hash TEXT NOT NULL PRIMARY KEY,

Modified: subversion/branches/verify-keep-going/subversion/libsvn_fs_fs/temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_fs_fs/temp_serializer.c?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_fs_fs/temp_serializer.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_fs_fs/temp_serializer.c Wed Feb 13 10:21:33 2013
@@ -741,7 +741,7 @@ svn_fs_fs__serialize_node_revision(void 
 
   /* create an (empty) serialization context with plenty of buffer space */
   svn_temp_serializer__context_t *context =
-      svn_temp_serializer__init(NULL, 0, 503, pool);
+      svn_temp_serializer__init(NULL, 0, 1007, pool);
 
   /* serialize the noderev */
   svn_fs_fs__noderev_serialize(context, &noderev);



Mime
View raw message