You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2015/01/03 15:00:44 UTC

svn commit: r1649205 [22/30] - in /subversion/branches/authzperf: ./ build/ build/ac-macros/ notes/ subversion/bindings/ctypes-python/ subversion/bindings/cxxhl/ subversion/bindings/javahl/tests/org/apache/subversion/javahl/ subversion/bindings/swig/ s...

Modified: subversion/branches/authzperf/subversion/libsvn_wc/diff_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_wc/diff_editor.c?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_wc/diff_editor.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_wc/diff_editor.c Sat Jan  3 14:00:41 2015
@@ -115,9 +115,6 @@ struct edit_baton_t
   /* Possibly diff repos against text-bases instead of working files. */
   svn_boolean_t diff_pristine;
 
-  /* Hash whose keys are const char * changelist names. */
-  apr_hash_t *changelist_hash;
-
   /* Cancel function/baton */
   svn_cancel_func_t cancel_func;
   void *cancel_baton;
@@ -239,11 +236,6 @@ struct file_baton_t
  * calculating diffs.  USE_TEXT_BASE defines whether to compare
  * against working files or text-bases.  REVERSE_ORDER defines which
  * direction to perform the diff.
- *
- * CHANGELIST_FILTER is a list of const char * changelist names, used to
- * filter diff output responses to only those items in one of the
- * specified changelists, empty (or NULL altogether) if no changelist
- * filtering is requested.
  */
 static svn_error_t *
 make_edit_baton(struct edit_baton_t **edit_baton,
@@ -255,20 +247,14 @@ make_edit_baton(struct edit_baton_t **ed
                 svn_boolean_t ignore_ancestry,
                 svn_boolean_t use_text_base,
                 svn_boolean_t reverse_order,
-                const apr_array_header_t *changelist_filter,
                 svn_cancel_func_t cancel_func,
                 void *cancel_baton,
                 apr_pool_t *pool)
 {
-  apr_hash_t *changelist_hash = NULL;
   struct edit_baton_t *eb;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(anchor_abspath));
 
-  if (changelist_filter && changelist_filter->nelts)
-    SVN_ERR(svn_hash_from_cstring_keys(&changelist_hash, changelist_filter,
-                                       pool));
-
   eb = apr_pcalloc(pool, sizeof(*eb));
   eb->db = db;
   eb->anchor_abspath = apr_pstrdup(pool, anchor_abspath);
@@ -278,7 +264,6 @@ make_edit_baton(struct edit_baton_t **ed
   eb->ignore_ancestry = ignore_ancestry;
   eb->local_before_remote = reverse_order;
   eb->diff_pristine = use_text_base;
-  eb->changelist_hash = changelist_hash;
   eb->cancel_func = cancel_func;
   eb->cancel_baton = cancel_baton;
   eb->pool = pool;
@@ -392,7 +377,6 @@ svn_wc__diff_base_working_diff(svn_wc__d
                                const char *local_abspath,
                                const char *relpath,
                                svn_revnum_t revision,
-                               apr_hash_t *changelist_hash,
                                const svn_diff_tree_processor_t *processor,
                                void *processor_dir_baton,
                                svn_boolean_t diff_pristine,
@@ -419,12 +403,11 @@ svn_wc__diff_base_working_diff(svn_wc__d
   apr_hash_t *base_props;
   apr_hash_t *local_props;
   apr_array_header_t *prop_changes;
-  const char *changelist;
 
   SVN_ERR(svn_wc__db_read_info(&status, NULL, &db_revision, NULL, NULL, NULL,
                                NULL, NULL, NULL, NULL, &working_checksum, NULL,
                                NULL, NULL, NULL, NULL, NULL, &recorded_size,
-                               &recorded_time, &changelist, NULL, NULL,
+                               &recorded_time, NULL, NULL, NULL,
                                &had_props, &props_mod, NULL, NULL, NULL,
                                db, local_abspath, scratch_pool, scratch_pool));
   checksum = working_checksum;
@@ -433,12 +416,6 @@ svn_wc__diff_base_working_diff(svn_wc__d
          || status == svn_wc__db_status_added
          || (status == svn_wc__db_status_deleted && diff_pristine));
 
-  /* If the item is not a member of a specified changelist (and there are
-     some specified changelists), skip it. */
-  if (changelist_hash && !svn_hash_gets(changelist_hash, changelist))
-    return SVN_NO_ERROR;
-
-
   if (status != svn_wc__db_status_normal)
     {
       SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL, &db_revision,
@@ -768,7 +745,6 @@ walk_local_nodes_diff(struct edit_baton_
                 SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,
                                                      child_relpath,
                                                      eb->processor, dir_baton,
-                                                     eb->changelist_hash,
                                                      eb->diff_pristine,
                                                      eb->cancel_func,
                                                      eb->cancel_baton,
@@ -778,7 +754,6 @@ walk_local_nodes_diff(struct edit_baton_
                                                     child_relpath,
                                                     depth_below_here,
                                                     eb->processor, dir_baton,
-                                                    eb->changelist_hash,
                                                     eb->diff_pristine,
                                                     eb->cancel_func,
                                                     eb->cancel_baton,
@@ -814,7 +789,6 @@ walk_local_nodes_diff(struct edit_baton_
                                                 db, child_abspath,
                                                 child_relpath,
                                                 eb->revnum,
-                                                eb->changelist_hash,
                                                 eb->processor, dir_baton,
                                                 eb->diff_pristine,
                                                 eb->cancel_func,
@@ -837,7 +811,6 @@ walk_local_nodes_diff(struct edit_baton_
                 SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,
                                                      child_relpath,
                                                      eb->processor, dir_baton,
-                                                     eb->changelist_hash,
                                                      eb->diff_pristine,
                                                      eb->cancel_func,
                                                      eb->cancel_baton,
@@ -846,7 +819,6 @@ walk_local_nodes_diff(struct edit_baton_
                 SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath,
                                                      child_relpath, depth_below_here,
                                                      eb->processor, dir_baton,
-                                                     eb->changelist_hash,
                                                      eb->diff_pristine,
                                                      eb->cancel_func,
                                                      eb->cancel_baton,
@@ -858,13 +830,9 @@ walk_local_nodes_diff(struct edit_baton_
   if (compared)
     return SVN_NO_ERROR;
 
-    /* Check for local property mods on this directory, if we haven't
-     already reported them and we aren't changelist-filted.
-     ### it should be noted that we do not currently allow directories
-     ### to be part of changelists, so if a changelist is provided, the
-     ### changelist check will always fail. */
+  /* Check for local property mods on this directory, if we haven't
+     already reported them. */
   if (! skip
-      && ! eb->changelist_hash
       && ! in_anchor_not_target
       && props_mod)
     {
@@ -907,7 +875,6 @@ svn_wc__diff_local_only_file(svn_wc__db_
                              const char *relpath,
                              const svn_diff_tree_processor_t *processor,
                              void *processor_parent_baton,
-                             apr_hash_t *changelist_hash,
                              svn_boolean_t diff_pristine,
                              svn_cancel_func_t cancel_func,
                              void *cancel_baton,
@@ -920,7 +887,6 @@ svn_wc__diff_local_only_file(svn_wc__db_
   const svn_checksum_t *checksum;
   const char *original_repos_relpath;
   svn_revnum_t original_revision;
-  const char *changelist;
   svn_boolean_t had_props;
   svn_boolean_t props_mod;
   apr_hash_t *pristine_props;
@@ -936,7 +902,7 @@ svn_wc__diff_local_only_file(svn_wc__db_
                                NULL, NULL, NULL, NULL, &checksum, NULL,
                                &original_repos_relpath, NULL, NULL,
                                &original_revision, NULL, NULL, NULL,
-                               &changelist, NULL, NULL, &had_props,
+                               NULL, NULL, NULL, &had_props,
                                &props_mod, NULL, NULL, NULL,
                                db, local_abspath,
                                scratch_pool, scratch_pool));
@@ -947,10 +913,6 @@ svn_wc__diff_local_only_file(svn_wc__db_
              || (status == svn_wc__db_status_deleted && diff_pristine)));
 
 
-  if (changelist && changelist_hash
-      && !svn_hash_gets(changelist_hash, changelist))
-    return SVN_NO_ERROR;
-
   if (status == svn_wc__db_status_deleted)
     {
       assert(diff_pristine);
@@ -1053,7 +1015,6 @@ svn_wc__diff_local_only_dir(svn_wc__db_t
                             svn_depth_t depth,
                             const svn_diff_tree_processor_t *processor,
                             void *processor_parent_baton,
-                            apr_hash_t *changelist_hash,
                             svn_boolean_t diff_pristine,
                             svn_cancel_func_t cancel_func,
                             void *cancel_baton,
@@ -1075,9 +1036,6 @@ svn_wc__diff_local_only_dir(svn_wc__db_t
   svn_boolean_t skip_children = FALSE;
   svn_diff_source_t *right_src = svn_diff__source_create(SVN_INVALID_REVNUM,
                                                          scratch_pool);
-  svn_depth_t depth_below_here = depth;
-  apr_hash_t *nodes;
-  apr_hash_t *conflicts;
 
   SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL,
                                NULL, NULL, NULL, NULL, NULL, NULL,
@@ -1128,71 +1086,81 @@ svn_wc__diff_local_only_dir(svn_wc__db_t
                                 processor,
                                 scratch_pool, iterpool));
 
-  SVN_ERR(svn_wc__db_read_children_info(&nodes, &conflicts, db, local_abspath,
-                                        FALSE /* base_tree_only */,
-                                        scratch_pool, iterpool));
-
-  if (depth_below_here == svn_depth_immediates)
-    depth_below_here = svn_depth_empty;
-
-  children = svn_sort__hash(nodes, svn_sort_compare_items_lexically,
-                            scratch_pool);
-
-  for (i = 0; i < children->nelts; i++)
+  if ((depth > svn_depth_empty || depth == svn_depth_unknown)
+      && ! skip_children)
     {
-      svn_sort__item_t *item = &APR_ARRAY_IDX(children, i, svn_sort__item_t);
-      const char *name = item->key;
-      struct svn_wc__db_info_t *info = item->value;
-      const char *child_abspath;
-      const char *child_relpath;
+      svn_depth_t depth_below_here = depth;
+      apr_hash_t *nodes;
+      apr_hash_t *conflicts;
+
+      if (depth_below_here == svn_depth_immediates)
+        depth_below_here = svn_depth_empty;
 
-      svn_pool_clear(iterpool);
+      SVN_ERR(svn_wc__db_read_children_info(&nodes, &conflicts,
+                                            db, local_abspath,
+                                            FALSE /* base_tree_only */,
+                                            scratch_pool, iterpool));
 
-      if (cancel_func)
-        SVN_ERR(cancel_func(cancel_baton));
 
-      child_abspath = svn_dirent_join(local_abspath, name, iterpool);
+      children = svn_sort__hash(nodes, svn_sort_compare_items_lexically,
+                                scratch_pool);
 
-      if (NOT_PRESENT(info->status))
+      for (i = 0; i < children->nelts; i++)
         {
-          continue;
-        }
+          svn_sort__item_t *item = &APR_ARRAY_IDX(children, i, svn_sort__item_t);
+          const char *name = item->key;
+          struct svn_wc__db_info_t *info = item->value;
+          const char *child_abspath;
+          const char *child_relpath;
 
-      /* If comparing against WORKING, skip entries that are
-         schedule-deleted - they don't really exist. */
-      if (!diff_pristine && info->status == svn_wc__db_status_deleted)
-        continue;
+          svn_pool_clear(iterpool);
 
-      child_relpath = svn_relpath_join(relpath, name, iterpool);
+          if (cancel_func)
+            SVN_ERR(cancel_func(cancel_baton));
 
-      switch (info->kind)
-        {
-        case svn_node_file:
-        case svn_node_symlink:
-          SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,
-                                               child_relpath,
-                                               processor, pdb,
-                                               changelist_hash,
-                                               diff_pristine,
-                                               cancel_func, cancel_baton,
-                                               scratch_pool));
-          break;
+          child_abspath = svn_dirent_join(local_abspath, name, iterpool);
 
-        case svn_node_dir:
-          if (depth > svn_depth_files || depth == svn_depth_unknown)
+          if (NOT_PRESENT(info->status))
             {
-              SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath,
-                                                  child_relpath, depth_below_here,
-                                                  processor, pdb,
-                                                  changelist_hash,
-                                                  diff_pristine,
-                                                  cancel_func, cancel_baton,
-                                                  iterpool));
+              continue;
             }
-          break;
 
-        default:
-          break;
+          /* If comparing against WORKING, skip entries that are
+             schedule-deleted - they don't really exist. */
+          if (!diff_pristine && info->status == svn_wc__db_status_deleted)
+            continue;
+
+          child_relpath = svn_relpath_join(relpath, name, iterpool);
+
+          switch (info->kind)
+            {
+            case svn_node_file:
+            case svn_node_symlink:
+              SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,
+                                                   child_relpath,
+                                                   processor, pdb,
+                                                   diff_pristine,
+                                                   cancel_func, cancel_baton,
+                                                   scratch_pool));
+              break;
+
+            case svn_node_dir:
+              if (depth > svn_depth_files || depth == svn_depth_unknown)
+                {
+                  SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath,
+                                                      child_relpath,
+                                                      depth_below_here,
+                                                      processor, pdb,
+                                                      diff_pristine,
+                                                      cancel_func,
+                                                      cancel_baton,
+                                                      iterpool));
+                }
+              break;
+
+            default:
+              break;
+            }
         }
     }
 
@@ -1282,7 +1250,6 @@ handle_local_only(struct dir_baton_t *pb
                       svn_relpath_join(pb->relpath, name, scratch_pool),
                       repos_delete ? svn_depth_infinity : depth,
                       eb->processor, pb->pdb,
-                      eb->changelist_hash,
                       eb->diff_pristine,
                       eb->cancel_func, eb->cancel_baton,
                       scratch_pool));
@@ -1293,7 +1260,6 @@ handle_local_only(struct dir_baton_t *pb
                       svn_dirent_join(pb->local_abspath, name, scratch_pool),
                       svn_relpath_join(pb->relpath, name, scratch_pool),
                       eb->processor, pb->pdb,
-                      eb->changelist_hash,
                       eb->diff_pristine,
                       eb->cancel_func, eb->cancel_baton,
                       scratch_pool));
@@ -2068,7 +2034,14 @@ close_file(void *file_baton,
   const char *repos_file;
   apr_hash_t *repos_props;
 
-  if (!fb->skip && expected_md5_digest != NULL)
+  if (fb->skip)
+    {
+      svn_pool_destroy(fb->pool); /* destroys scratch_pool and fb */
+      SVN_ERR(maybe_done(pb));
+      return SVN_NO_ERROR;
+    }
+
+  if (expected_md5_digest != NULL)
     {
       svn_checksum_t *expected_checksum;
       const svn_checksum_t *result_checksum;
@@ -2123,11 +2096,7 @@ close_file(void *file_baton,
       }
   }
 
-  if (fb->skip)
-    {
-      /* Diff processor requested skipping information */
-    }
-  else if (fb->repos_only)
+  if (fb->repos_only)
     {
       SVN_ERR(eb->processor->file_deleted(fb->relpath,
                                           fb->left_src,
@@ -2307,12 +2276,24 @@ svn_wc__get_diff_editor(const svn_delta_
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(anchor_abspath));
 
+  /* Apply changelist filtering to the output */
+  if (changelist_filter && changelist_filter->nelts)
+    {
+      apr_hash_t *changelist_hash;
+
+      SVN_ERR(svn_hash_from_cstring_keys(&changelist_hash, changelist_filter,
+                                         result_pool));
+      diff_processor = svn_wc__changelist_filter_tree_processor_create(
+                         diff_processor, wc_ctx, anchor_abspath,
+                         changelist_hash, result_pool);
+    }
+
   SVN_ERR(make_edit_baton(&eb,
                           wc_ctx->db,
                           anchor_abspath, target,
                           diff_processor,
                           depth, ignore_ancestry,
-                          use_text_base, reverse_order, changelist_filter,
+                          use_text_base, reverse_order,
                           cancel_func, cancel_baton,
                           result_pool));
 
@@ -2778,3 +2759,329 @@ svn_wc__wrap_diff_callbacks(const svn_di
   *diff_processor = processor;
   return SVN_NO_ERROR;
 }
+
+/* =====================================================================
+ * A tree processor filter that filters by changelist membership
+ * =====================================================================
+ *
+ * The current implementation queries the WC for the changelist of each
+ * file as it comes through, and sets the 'skip' flag for a non-matching
+ * file.
+ *
+ * (It doesn't set the 'skip' flag for a directory, as we need to receive
+ * the changed/added/deleted/closed call to know when it is closed, in
+ * order to preserve the strict open-close semantics for the wrapped tree
+ * processor.)
+ *
+ * It passes on the opening and closing of every directory, even if there
+ * are no file changes to be passed on inside that directory.
+ */
+
+typedef struct filter_tree_baton_t
+{
+  const svn_diff_tree_processor_t *processor;
+  svn_wc_context_t *wc_ctx;
+  /* WC path of the root of the diff (where relpath = "") */
+  const char *root_local_abspath;
+  /* Hash whose keys are const char * changelist names. */
+  apr_hash_t *changelist_hash;
+} filter_tree_baton_t;
+
+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;
+
+  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;
+
+  SVN_ERR(fb->processor->dir_closed(relpath,
+                                    NULL,
+                                    right_source,
+                                    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;
+
+  SVN_ERR(fb->processor->dir_closed(relpath,
+                                    left_source,
+                                    NULL,
+                                    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;
+
+  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_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;
+
+  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;
+  const char *local_abspath
+    = svn_dirent_join(fb->root_local_abspath, relpath, scratch_pool);
+
+  /* Skip if not a member of a given changelist */
+  if (! svn_wc__changelist_match(fb->wc_ctx, local_abspath,
+                                 fb->changelist_hash, scratch_pool))
+    {
+      *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;
+
+  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;
+
+  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;
+
+  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;
+
+  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;
+
+  SVN_ERR(fb->processor->node_absent(relpath,
+                                     dir_baton,
+                                     fb->processor,
+                                     scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+const svn_diff_tree_processor_t *
+svn_wc__changelist_filter_tree_processor_create(
+                                const svn_diff_tree_processor_t *processor,
+                                svn_wc_context_t *wc_ctx,
+                                const char *root_local_abspath,
+                                apr_hash_t *changelist_hash,
+                                apr_pool_t *result_pool)
+{
+  struct filter_tree_baton_t *fb;
+  svn_diff_tree_processor_t *filter;
+
+  if (! changelist_hash)
+    return processor;
+
+  fb = apr_pcalloc(result_pool, sizeof(*fb));
+  fb->processor = processor;
+  fb->wc_ctx = wc_ctx;
+  fb->root_local_abspath = root_local_abspath;
+  fb->changelist_hash = changelist_hash;
+
+  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;
+}
+

Modified: subversion/branches/authzperf/subversion/libsvn_wc/diff_local.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_wc/diff_local.c?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_wc/diff_local.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_wc/diff_local.c Sat Jan  3 14:00:41 2015
@@ -89,9 +89,6 @@ struct diff_baton
   /* Should this diff ignore node ancestry? */
   svn_boolean_t ignore_ancestry;
 
-  /* Hash whose keys are const char * changelist names. */
-  apr_hash_t *changelist_hash;
-
   /* Cancel function/baton */
   svn_cancel_func_t cancel_func;
   void *cancel_baton;
@@ -249,11 +246,6 @@ diff_status_callback(void *baton,
   if (eb->cur && eb->cur->skip_children)
     return SVN_NO_ERROR;
 
-  if (eb->changelist_hash != NULL
-      && (!status->changelist
-          || ! svn_hash_gets(eb->changelist_hash, status->changelist)))
-    return SVN_NO_ERROR; /* Filtered via changelist */
-
   /* This code does about the same thing as the inner body of
      walk_local_nodes_diff() in diff_editor.c, except that
      it is already filtered by the status walker, doesn't have to
@@ -358,7 +350,6 @@ diff_status_callback(void *baton,
             SVN_ERR(svn_wc__diff_base_working_diff(db, child_abspath,
                                                    child_relpath,
                                                    SVN_INVALID_REVNUM,
-                                                   eb->changelist_hash,
                                                    eb->processor,
                                                    eb->cur
                                                         ? eb->cur->baton
@@ -402,7 +393,6 @@ diff_status_callback(void *baton,
                                                child_relpath,
                                                eb->processor,
                                                eb->cur ? eb->cur->baton : NULL,
-                                               eb->changelist_hash,
                                                FALSE,
                                                eb->cancel_func,
                                                eb->cancel_baton,
@@ -412,7 +402,6 @@ diff_status_callback(void *baton,
                                               child_relpath, depth_below_here,
                                               eb->processor,
                                               eb->cur ? eb->cur->baton : NULL,
-                                              eb->changelist_hash,
                                               FALSE,
                                               eb->cancel_func,
                                               eb->cancel_baton,
@@ -475,15 +464,23 @@ svn_wc__diff7(const char **root_relpath,
   if (root_is_dir)
     *root_is_dir = (kind == svn_node_dir);
 
+  /* Apply changelist filtering to the output */
+  if (changelist_filter && changelist_filter->nelts)
+    {
+      apr_hash_t *changelist_hash;
+
+      SVN_ERR(svn_hash_from_cstring_keys(&changelist_hash, changelist_filter,
+                                         result_pool));
+      diff_processor = svn_wc__changelist_filter_tree_processor_create(
+                         diff_processor, wc_ctx, local_abspath,
+                         changelist_hash, result_pool);
+    }
+
   eb.db = wc_ctx->db;
   eb.processor = diff_processor;
   eb.ignore_ancestry = ignore_ancestry;
   eb.pool = scratch_pool;
 
-  if (changelist_filter && changelist_filter->nelts)
-    SVN_ERR(svn_hash_from_cstring_keys(&eb.changelist_hash, changelist_filter,
-                                       scratch_pool));
-
   if (ignore_ancestry)
     get_all = TRUE; /* We need unmodified descendants of copies */
   else

Modified: subversion/branches/authzperf/subversion/libsvn_wc/externals.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_wc/externals.c?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_wc/externals.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_wc/externals.c Sat Jan  3 14:00:41 2015
@@ -159,7 +159,7 @@ find_and_remove_externals_revision(int *
 
 svn_error_t *
 svn_wc_parse_externals_description3(apr_array_header_t **externals_p,
-                                    const char *parent_directory,
+                                    const char *defining_directory,
                                     const char *desc,
                                     svn_boolean_t canonicalize_url,
                                     apr_pool_t *pool)
@@ -167,8 +167,8 @@ svn_wc_parse_externals_description3(apr_
   int i;
   apr_array_header_t *externals = NULL;
   apr_array_header_t *lines = svn_cstring_split(desc, "\n\r", TRUE, pool);
-  const char *parent_directory_display = svn_path_is_url(parent_directory) ?
-    parent_directory : svn_dirent_local_style(parent_directory, pool);
+  const char *defining_directory_display = svn_path_is_url(defining_directory) ?
+    defining_directory : svn_dirent_local_style(defining_directory, pool);
 
   /* If an error occurs halfway through parsing, *externals_p should stay
    * untouched. So, store the list in a local var first. */
@@ -231,7 +231,7 @@ svn_wc_parse_externals_description3(apr_
           (SVN_ERR_CLIENT_INVALID_EXTERNALS_DESCRIPTION, NULL,
            _("Error parsing %s property on '%s': '%s'"),
            SVN_PROP_EXTERNALS,
-           parent_directory_display,
+           defining_directory_display,
            line);
 
       /* To make it easy to check for the forms, find and remove -r N
@@ -242,7 +242,7 @@ svn_wc_parse_externals_description3(apr_
       SVN_ERR(find_and_remove_externals_revision(&rev_idx,
                                                  (const char **)line_parts,
                                                  num_line_parts, item,
-                                                 parent_directory_display,
+                                                 defining_directory_display,
                                                  line, pool));
 
       token0 = line_parts[0];
@@ -258,7 +258,7 @@ svn_wc_parse_externals_description3(apr_
              "cannot use two absolute URLs ('%s' and '%s') in an external; "
              "one must be a path where an absolute or relative URL is "
              "checked out to"),
-           SVN_PROP_EXTERNALS, parent_directory_display, token0, token1);
+           SVN_PROP_EXTERNALS, defining_directory_display, token0, token1);
 
       if (0 == rev_idx && token1_is_url)
         return svn_error_createf
@@ -266,7 +266,7 @@ svn_wc_parse_externals_description3(apr_
            _("Invalid %s property on '%s': "
              "cannot use a URL '%s' as the target directory for an external "
              "definition"),
-           SVN_PROP_EXTERNALS, parent_directory_display, token1);
+           SVN_PROP_EXTERNALS, defining_directory_display, token1);
 
       if (1 == rev_idx && token0_is_url)
         return svn_error_createf
@@ -274,7 +274,7 @@ svn_wc_parse_externals_description3(apr_
            _("Invalid %s property on '%s': "
              "cannot use a URL '%s' as the target directory for an external "
              "definition"),
-           SVN_PROP_EXTERNALS, parent_directory_display, token0);
+           SVN_PROP_EXTERNALS, defining_directory_display, token0);
 
       /* The appearance of -r N or -rN forces the type of external.
          If -r is at the beginning of the line or the first token is
@@ -316,7 +316,7 @@ svn_wc_parse_externals_description3(apr_
            _("Invalid %s property on '%s': "
              "target '%s' is an absolute path or involves '..'"),
            SVN_PROP_EXTERNALS,
-           parent_directory_display,
+           defining_directory_display,
            item->target_dir);
 
       if (canonicalize_url)
@@ -943,29 +943,62 @@ close_edit(void *edit_baton,
 {
   struct edit_baton *eb = edit_baton;
 
-  if (!eb->file_closed
-      || eb->iprops)
+  if (!eb->file_closed)
     {
-      apr_hash_t *wcroot_iprops = NULL;
+      /* The file wasn't updated, but its url or revision might have...
+         e.g. switch between branches for relative externals.
 
-      if (eb->iprops)
-        {
-          wcroot_iprops = apr_hash_make(pool);
-          svn_hash_sets(wcroot_iprops, eb->local_abspath, eb->iprops);
-        }
+         Just bump the information as that is just as expensive as
+         investigating when we should and shouldn't update it...
+         and avoid hard to debug edge cases */
+
+      svn_node_kind_t kind;
+      const char *old_repos_relpath;
+      svn_revnum_t changed_rev;
+      apr_time_t changed_date;
+      const char *changed_author;
+      const svn_checksum_t *checksum;
+      apr_hash_t *pristine_props;
+      const char *repos_relpath = svn_uri_skip_ancestor(eb->repos_root_url,
+                                                        eb->url, pool);
+
+      SVN_ERR(svn_wc__db_base_get_info(NULL, &kind, NULL, &old_repos_relpath,
+                                       NULL, NULL, &changed_rev, &changed_date,
+                                       &changed_author, NULL, &checksum, NULL,
+                                       NULL, NULL, &pristine_props, NULL,
+                                       eb->db, eb->local_abspath,
+                                       pool, pool));
 
-      /* The node wasn't updated, so we just have to bump its revision */
-      SVN_ERR(svn_wc__db_op_bump_revisions_post_update(eb->db,
-                                                       eb->local_abspath,
-                                                       svn_depth_infinity,
-                                                       NULL, NULL, NULL,
-                                                       *eb->target_revision,
-                                                       apr_hash_make(pool),
-                                                       wcroot_iprops,
-                                                       TRUE /* empty update */,
-                                                       eb->notify_func,
-                                                       eb->notify_baton,
-                                                       pool));
+      if (kind != svn_node_file)
+        return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
+                                   _("Node '%s' is no existing file external"),
+                                   svn_dirent_local_style(eb->local_abspath,
+                                                          pool));
+
+      SVN_ERR(svn_wc__db_external_add_file(
+                    eb->db,
+                    eb->local_abspath,
+                    eb->wri_abspath,
+                    repos_relpath,
+                    eb->repos_root_url,
+                    eb->repos_uuid,
+                    *eb->target_revision,
+                    pristine_props,
+                    eb->iprops,
+                    eb->changed_rev,
+                    eb->changed_date,
+                    eb->changed_author,
+                    checksum,
+                    NULL /* clear dav props */,
+                    eb->record_ancestor_abspath,
+                    eb->recorded_repos_relpath,
+                    eb->recorded_peg_revision,
+                    eb->recorded_revision,
+                    FALSE, NULL,
+                    TRUE /* keep_recorded_info */,
+                    NULL /* conflict_skel */,
+                    NULL /* work_items */,
+                    pool));
     }
 
   return SVN_NO_ERROR;

Modified: subversion/branches/authzperf/subversion/libsvn_wc/node.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_wc/node.c?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_wc/node.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_wc/node.c Sat Jan  3 14:00:41 2015
@@ -471,6 +471,7 @@ svn_wc__internal_walk_children(svn_wc__d
   svn_node_kind_t kind;
   svn_wc__db_status_t status;
   apr_hash_t *changelist_hash = NULL;
+  const char *changelist = NULL;
 
   SVN_ERR_ASSERT(walk_depth >= svn_depth_empty
                  && walk_depth <= svn_depth_infinity);
@@ -483,14 +484,17 @@ svn_wc__internal_walk_children(svn_wc__d
   SVN_ERR(svn_wc__db_read_info(&status, &db_kind, NULL, NULL, NULL, NULL,
                                NULL, NULL, NULL, NULL, NULL, NULL,
                                NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                               changelist_hash ? &changelist : NULL,
+                               NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                                db, local_abspath, scratch_pool, scratch_pool));
 
   SVN_ERR(convert_db_kind_to_node_kind(&kind, db_kind, status, show_hidden));
 
-  if (svn_wc__internal_changelist_match(db, local_abspath,
-                                        changelist_hash, scratch_pool))
-    SVN_ERR(walk_callback(local_abspath, kind, walk_baton, scratch_pool));
+  if (!changelist_hash
+      || (changelist && svn_hash_gets(changelist_hash, changelist)))
+    {
+      SVN_ERR(walk_callback(local_abspath, kind, walk_baton, scratch_pool));
+    }
 
   if (db_kind == svn_node_file
       || status == svn_wc__db_status_not_present
@@ -632,7 +636,6 @@ svn_wc__node_get_base(svn_node_kind_t *k
                       svn_wc_context_t *wc_ctx,
                       const char *local_abspath,
                       svn_boolean_t ignore_enoent,
-                      svn_boolean_t show_hidden,
                       apr_pool_t *result_pool,
                       apr_pool_t *scratch_pool)
 {
@@ -652,9 +655,8 @@ svn_wc__node_get_base(svn_node_kind_t *k
   if (err && err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
     return svn_error_trace(err);
   else if (err
-           || (!err && !show_hidden
-               && (status != svn_wc__db_status_normal
-                   && status != svn_wc__db_status_incomplete)))
+           || (status != svn_wc__db_status_normal
+               && status != svn_wc__db_status_incomplete))
     {
       if (!ignore_enoent)
         {

Modified: subversion/branches/authzperf/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_wc/update_editor.c?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_wc/update_editor.c Sat Jan  3 14:00:41 2015
@@ -4342,7 +4342,7 @@ close_file(void *file_baton,
                 || strcmp(fb->new_repos_relpath, fb->old_repos_relpath) == 0)
               {
                 SVN_ERR_ASSERT(prop->value == NULL);
-                SVN_ERR(svn_wc__db_lock_remove(eb->db, fb->local_abspath,
+                SVN_ERR(svn_wc__db_lock_remove(eb->db, fb->local_abspath, NULL,
                                                scratch_pool));
 
                 lock_state = svn_wc_notify_lock_state_unlocked;

Modified: subversion/branches/authzperf/subversion/libsvn_wc/wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_wc/wc.h?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_wc/wc.h (original)
+++ subversion/branches/authzperf/subversion/libsvn_wc/wc.h Sat Jan  3 14:00:41 2015
@@ -249,52 +249,6 @@ svn_wc__context_create_with_db(svn_wc_co
 apr_pool_t *
 svn_wc__get_committed_queue_pool(const struct svn_wc_committed_queue_t *queue);
 
-
-/** Internal helper for svn_wc_process_committed_queue2().
- *
- * ### If @a queue is NULL, then ...?
- * ### else:
- * Bump an item from @a queue (the one associated with @a
- * local_abspath) to @a new_revnum after a commit succeeds, recursing
- * if @a recurse is set.
- *
- * @a new_date is the (server-side) date of the new revision, or 0.
- *
- * @a rev_author is the (server-side) author of the new
- * revision; it may be @c NULL.
- *
- * @a new_dav_cache is a hash of dav property changes to be made to
- * the @a local_abspath.
- *   ### [JAF]  Is it? See svn_wc_queue_committed3(). It ends up being
- *   ### assigned as a whole to wc.db:BASE_NODE:dav_cache.
- *
- * If @a no_unlock is set, don't release any user locks on @a
- * local_abspath; otherwise release them as part of this processing.
- *
- * If @a keep_changelist is set, don't remove any changeset assignments
- * from @a local_abspath; otherwise, clear it of such assignments.
- *
- * If @a sha1_checksum is non-NULL, use it to identify the node's pristine
- * text.
- *
- * Set TOP_OF_RECURSE to TRUE to show that this the top of a possibly
- * recursive commit operation.
- */
-svn_error_t *
-svn_wc__process_committed_internal(svn_wc__db_t *db,
-                                   const char *local_abspath,
-                                   svn_boolean_t recurse,
-                                   svn_boolean_t top_of_recurse,
-                                   svn_revnum_t new_revnum,
-                                   apr_time_t new_date,
-                                   const char *rev_author,
-                                   apr_hash_t *new_dav_cache,
-                                   svn_boolean_t no_unlock,
-                                   svn_boolean_t keep_changelist,
-                                   const svn_checksum_t *sha1_checksum,
-                                   const svn_wc_committed_queue_t *queue,
-                                   apr_pool_t *scratch_pool);
-
 
 /*** Update traversals. ***/
 

Modified: subversion/branches/authzperf/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_wc/wc_db.c?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_wc/wc_db.c Sat Jan  3 14:00:41 2015
@@ -4700,25 +4700,23 @@ struct op_copy_baton
   const char *dst_op_root_relpath;
 };
 
-/* Helper for svn_wc__db_op_copy().
- *
- * Implements svn_sqlite__transaction_callback_t. */
+/* Helper for svn_wc__db_op_copy(). */
 static svn_error_t *
-op_copy_txn(void * baton,
-            svn_sqlite__db_t *sdb,
+op_copy_txn(svn_wc__db_wcroot_t *wcroot,
+            struct op_copy_baton *ocb,
             apr_pool_t *scratch_pool)
 {
-  struct op_copy_baton *ocb = baton;
   int move_op_depth;
 
-  if (sdb != ocb->dst_wcroot->sdb)
+  if (wcroot != ocb->dst_wcroot)
     {
        /* Source and destination databases differ; so also start a lock
-          in the destination database, by calling ourself in a lock. */
+          in the destination database, by calling ourself in an extra lock. */
 
-      return svn_error_trace(
-                        svn_sqlite__with_lock(ocb->dst_wcroot->sdb,
-                                              op_copy_txn, ocb, scratch_pool));
+      SVN_WC__DB_WITH_TXN(op_copy_txn(ocb->dst_wcroot, ocb, scratch_pool),
+                          ocb->dst_wcroot);
+
+      return SVN_NO_ERROR;
     }
 
   /* From this point we can assume a lock in the src and dst databases */
@@ -4769,8 +4767,8 @@ svn_wc__db_op_copy(svn_wc__db_t *db,
 
   /* Call with the sdb in src_wcroot. It might call itself again to
      also obtain a lock in dst_wcroot */
-  SVN_ERR(svn_sqlite__with_lock(ocb.src_wcroot->sdb, op_copy_txn, &ocb,
-                                scratch_pool));
+  SVN_WC__DB_WITH_TXN(op_copy_txn(ocb.src_wcroot, &ocb, scratch_pool),
+                      ocb.src_wcroot);
 
   return SVN_NO_ERROR;
 }
@@ -5212,15 +5210,12 @@ db_op_copy_shadowed_layer(svn_wc__db_wcr
   return SVN_NO_ERROR;
 }
 
-/* Helper for svn_wc__db_op_copy_shadowed_layer().
- *
- * Implements  svn_sqlite__transaction_callback_t. */
+/* Helper for svn_wc__db_op_copy_shadowed_layer(). */
 static svn_error_t *
-op_copy_shadowed_layer_txn(void *baton,
-                           svn_sqlite__db_t *sdb,
+op_copy_shadowed_layer_txn(svn_wc__db_wcroot_t *wcroot,
+                           struct op_copy_baton *ocb,
                            apr_pool_t *scratch_pool)
 {
-  struct op_copy_baton *ocb = baton;
   const char *src_parent_relpath;
   const char *dst_parent_relpath;
   int src_op_depth;
@@ -5230,15 +5225,16 @@ op_copy_shadowed_layer_txn(void *baton,
   apr_int64_t repos_id = INVALID_REPOS_ID;
   svn_revnum_t revision = SVN_INVALID_REVNUM;
 
-  if (sdb != ocb->dst_wcroot->sdb)
+  if (wcroot != ocb->dst_wcroot)
     {
-       /* Source and destination databases differ; so also start a lock
-          in the destination database, by calling ourself in a lock. */
+      /* Source and destination databases differ; so also start a lock
+         in the destination database, by calling ourself in an extra lock. */
 
-      return svn_error_trace(
-                        svn_sqlite__with_lock(ocb->dst_wcroot->sdb,
-                                              op_copy_shadowed_layer_txn,
-                                              ocb, scratch_pool));
+      SVN_WC__DB_WITH_TXN(op_copy_shadowed_layer_txn(ocb->dst_wcroot, ocb,
+                                                     scratch_pool),
+                          ocb->dst_wcroot);
+
+      return SVN_NO_ERROR;
     }
 
   /* From this point we can assume a lock in the src and dst databases */
@@ -5320,9 +5316,9 @@ svn_wc__db_op_copy_shadowed_layer(svn_wc
 
   /* Call with the sdb in src_wcroot. It might call itself again to
      also obtain a lock in dst_wcroot */
-  SVN_ERR(svn_sqlite__with_lock(ocb.src_wcroot->sdb,
-                                op_copy_shadowed_layer_txn,
-                                &ocb, scratch_pool));
+  SVN_WC__DB_WITH_TXN(op_copy_shadowed_layer_txn(ocb.src_wcroot, &ocb,
+                                                 scratch_pool),
+                      ocb.src_wcroot);
 
   return SVN_NO_ERROR;
 }
@@ -11925,6 +11921,7 @@ svn_wc__db_lock_add(svn_wc__db_t *db,
 static svn_error_t *
 lock_remove_txn(svn_wc__db_wcroot_t *wcroot,
                 const char *local_relpath,
+                svn_skel_t *work_items,
                 apr_pool_t *scratch_pool)
 {
   const char *repos_relpath;
@@ -11944,6 +11941,8 @@ lock_remove_txn(svn_wc__db_wcroot_t *wcr
 
   SVN_ERR(svn_sqlite__step_done(stmt));
 
+  SVN_ERR(add_work_items(wcroot->sdb, work_items, scratch_pool));
+
   return SVN_NO_ERROR;
 }
 
@@ -11951,6 +11950,7 @@ lock_remove_txn(svn_wc__db_wcroot_t *wcr
 svn_error_t *
 svn_wc__db_lock_remove(svn_wc__db_t *db,
                        const char *local_abspath,
+                       svn_skel_t *work_items,
                        apr_pool_t *scratch_pool)
 {
   svn_wc__db_wcroot_t *wcroot;
@@ -11963,7 +11963,7 @@ svn_wc__db_lock_remove(svn_wc__db_t *db,
   VERIFY_USABLE_WCROOT(wcroot);
 
   SVN_WC__DB_WITH_TXN(
-    lock_remove_txn(wcroot, local_relpath, scratch_pool),
+    lock_remove_txn(wcroot, local_relpath, work_items, scratch_pool),
     wcroot);
 
   /* There may be some entries, and the lock info is now out of date.  */
@@ -15521,3 +15521,514 @@ svn_wc__db_vacuum(svn_wc__db_t *db,
 
   return SVN_NO_ERROR;
 }
+
+/* Item queued with svn_wc__db_commit_queue_add */
+typedef struct commit_queue_item_t
+{
+  const char *local_relpath;
+  svn_boolean_t recurse; /* Use legacy recursion */
+  svn_boolean_t committed; /* Process the node as committed */
+  svn_boolean_t remove_lock; /* Remove existing lock on node */
+  svn_boolean_t remove_changelist; /* Remove changelist on node */
+
+  /* The pristine text checksum. NULL if the old value should be kept
+     and for directories */
+  const svn_checksum_t *new_sha1_checksum;
+
+  apr_hash_t *new_dav_cache; /* New DAV cache for the node */
+} commit_queue_item_t;
+
+/* The queue definition for vn_wc__db_create_commit_queue,
+   svn_wc__db_commit_queue_add and finally svn_wc__db_process_commit_queue */
+struct svn_wc__db_commit_queue_t
+{
+  svn_wc__db_wcroot_t *wcroot; /* Wcroot for ITEMS */
+  apr_array_header_t *items; /* List of commit_queue_item_t* */
+  svn_boolean_t have_recurse; /* Is one or more item[x]->recurse TRUE? */
+};
+
+/* Create a new svn_wc__db_commit_queue_t instance in RESULT_POOL for the
+   working copy specified with WRI_ABSPATH */
+svn_error_t *
+svn_wc__db_create_commit_queue(svn_wc__db_commit_queue_t **queue,
+                               svn_wc__db_t *db,
+                               const char *wri_abspath,
+                               apr_pool_t *result_pool,
+                               apr_pool_t *scratch_pool)
+{
+  svn_wc__db_wcroot_t *wcroot;
+  const char *local_relpath;
+  svn_wc__db_commit_queue_t *q;
+
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
+
+  SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
+                              wri_abspath, result_pool, scratch_pool));
+  VERIFY_USABLE_WCROOT(wcroot);
+
+  q = apr_pcalloc(result_pool, sizeof(*q));
+
+  SVN_ERR_ASSERT(wcroot->sdb);
+
+  q->wcroot = wcroot;
+  q->items = apr_array_make(result_pool, 64,
+                            sizeof(commit_queue_item_t*));
+  q->have_recurse = FALSE;
+
+  *queue = q;
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__db_commit_queue_add(svn_wc__db_commit_queue_t *queue,
+                            const char *local_abspath,
+                            svn_boolean_t recurse,
+                            svn_boolean_t is_commited,
+                            svn_boolean_t remove_lock,
+                            svn_boolean_t remove_changelist,
+                            const svn_checksum_t *new_sha1_checksum,
+                            apr_hash_t *new_dav_cache,
+                            apr_pool_t *result_pool,
+                            apr_pool_t *scratch_pool)
+{
+  commit_queue_item_t *cqi;
+  const char *local_relpath;
+
+  local_relpath = svn_dirent_skip_ancestor(queue->wcroot->abspath,
+                                           local_abspath);
+
+  if (! local_relpath)
+    return svn_error_createf(
+                SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+                _("The path '%s' is not in the working copy '%s'"),
+                svn_dirent_local_style(local_abspath, scratch_pool),
+                svn_dirent_local_style(queue->wcroot->abspath, scratch_pool));
+
+  cqi = apr_pcalloc(result_pool, sizeof(*cqi));
+  cqi->local_relpath = local_relpath;
+  cqi->recurse = recurse;
+  cqi->committed = is_commited;
+  cqi->remove_lock = remove_lock;
+  cqi->remove_changelist = remove_changelist;
+  cqi->new_sha1_checksum = new_sha1_checksum;
+  cqi->new_dav_cache = new_dav_cache;
+
+  queue->have_recurse |= recurse;
+
+  APR_ARRAY_PUSH(queue->items, commit_queue_item_t *) = cqi;
+  return SVN_NO_ERROR;
+}
+
+/*** Finishing updates and commits. ***/
+
+/* Post process an item that is committed in the repository. Collapse layers into
+ * BASE. Queue work items that will finish a commit of the file or directory
+ * LOCAL_ABSPATH in DB:
+ */
+static svn_error_t *
+process_committed_leaf(svn_wc__db_t *db,
+                       svn_wc__db_wcroot_t *wcroot,
+                       const char *local_relpath,
+                       svn_boolean_t via_recurse,
+                       svn_wc__db_status_t status,
+                       svn_node_kind_t kind,
+                       svn_boolean_t prop_mods,
+                       const svn_checksum_t *old_checksum,
+                       svn_revnum_t new_revnum,
+                       apr_time_t new_changed_date,
+                       const char *new_changed_author,
+                       apr_hash_t *new_dav_cache,
+                       svn_boolean_t remove_lock,
+                       svn_boolean_t remove_changelist,
+                       const svn_checksum_t *checksum,
+                       apr_pool_t *scratch_pool)
+{
+  svn_revnum_t new_changed_rev = new_revnum;
+  svn_skel_t *work_item = NULL;
+
+  {
+    const char *lock_relpath;
+    svn_boolean_t locked;
+
+    if (kind == svn_node_dir)
+      lock_relpath = local_relpath;
+    else
+      lock_relpath = svn_relpath_dirname(local_relpath, scratch_pool);
+
+    SVN_ERR(svn_wc__db_wclock_owns_lock_internal(&locked, wcroot,
+                                                 lock_relpath, FALSE,
+                                                 scratch_pool));
+
+    if (!locked)
+      return svn_error_createf(SVN_ERR_WC_NOT_LOCKED, NULL,
+                             _("No write-lock in '%s'"),
+                             path_for_error_message(wcroot, local_relpath,
+                                                    scratch_pool));
+
+    SVN_ERR(flush_entries(wcroot, lock_relpath, svn_depth_empty,
+                          scratch_pool));
+  }
+
+  if (status == svn_wc__db_status_deleted)
+    {
+      return svn_error_trace(
+                 db_base_remove(wcroot, local_relpath, db,
+                                FALSE /* keep_as_working */,
+                                FALSE /* queue_deletes */,
+                                TRUE  /* remove_locks */,
+                                (! via_recurse)
+                                    ? new_revnum : SVN_INVALID_REVNUM,
+                                NULL, NULL,
+                                scratch_pool));
+    }
+  else if (status == svn_wc__db_status_not_present)
+    {
+      /* We are committing the leaf of a copy operation.
+         We leave the not-present marker to allow pulling in excluded
+         children of a copy.
+
+         The next update will remove the not-present marker. */
+
+      return SVN_NO_ERROR;
+    }
+
+  SVN_ERR_ASSERT(status == svn_wc__db_status_normal
+                 || status == svn_wc__db_status_incomplete
+                 || status == svn_wc__db_status_added);
+
+  if (kind != svn_node_dir)
+    {
+      /* If we sent a delta (meaning: post-copy modification),
+         then this file will appear in the queue and so we should have
+         its checksum already. */
+      if (checksum == NULL)
+        {
+          /* It was copied and not modified. We must have a text
+             base for it. And the node should have a checksum. */
+          SVN_ERR_ASSERT(old_checksum != NULL);
+
+          checksum = old_checksum;
+
+          /* Is the node completely unmodified and are we recursing? */
+          if (via_recurse && !prop_mods)
+            {
+              /* If a copied node itself is not modified, but the op_root of
+                 the copy is committed we have to make sure that changed_rev,
+                 changed_date and changed_author don't change or the working
+                 copy used for committing will show different last modified
+                 information then a clean checkout of exactly the same
+                 revisions. (Issue #3676) */
+
+              SVN_ERR(svn_wc__db_read_info_internal(
+                                           NULL, NULL, NULL, NULL, NULL,
+                                           &new_changed_rev,
+                                           &new_changed_date,
+                                           &new_changed_author, NULL, NULL,
+                                           NULL, NULL, NULL, NULL, NULL,
+                                           NULL, NULL, NULL, NULL,
+                                           NULL, NULL, NULL, NULL,
+                                           NULL, NULL,
+                                           wcroot, local_relpath,
+                                           scratch_pool, scratch_pool));
+            }
+        }
+
+      SVN_ERR(svn_wc__wq_build_file_commit(&work_item,
+                                           db, svn_dirent_join(wcroot->abspath,
+                                                               local_relpath,
+                                                               scratch_pool),
+                                           prop_mods,
+                                           scratch_pool, scratch_pool));
+    }
+
+  /* The new text base will be found in the pristine store by its checksum. */
+  SVN_ERR(commit_node(wcroot, local_relpath,
+                      new_revnum, new_changed_rev,
+                      new_changed_date, new_changed_author,
+                      checksum,
+                      NULL /* new_children */,
+                      new_dav_cache,
+                      !remove_changelist,
+                      !remove_lock,
+                      work_item,
+                      scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+/** Internal helper for svn_wc_process_committed_queue2().
+ * Bump a commit item, collapsing local changes with the new repository
+ * information to a new BASE node.
+ *
+ * @a new_date is the (server-side) date of the new revision, or 0.
+ *
+ * @a rev_author is the (server-side) author of the new
+ * revision; it may be @c NULL.
+ *
+ * @a new_dav_cache is a hash of all the new dav properties for LOCAL_RELPATH.
+ *
+ * If @a remove_lock is set, release any user locks on @a
+ * local_abspath; otherwise keep them during processing.
+ *
+ * If @a remove_changelist is set, clear any changeset assignments
+ * from @a local_abspath; otherwise, keep such assignments.
+ *
+ * If @a new_sha1_checksum is non-NULL, use it to identify the node's pristine
+ * text.
+ *
+ * Set TOP_OF_RECURSE to TRUE to show that this the top of a possibly
+ * recursive commit operation. (Part of the legacy recurse handling)
+ */
+static svn_error_t *
+process_committed_internal(svn_wc__db_t *db,
+                           svn_wc__db_wcroot_t *wcroot,
+                           const char *local_relpath,
+                           svn_boolean_t recurse,
+                           svn_boolean_t top_of_recurse,
+                           svn_revnum_t new_revnum,
+                           apr_time_t new_date,
+                           const char *rev_author,
+                           apr_hash_t *new_dav_cache,
+                           svn_boolean_t remove_lock,
+                           svn_boolean_t remove_changelist,
+                           const svn_checksum_t *new_sha1_checksum,
+                           apr_hash_t *items_by_relpath,
+                           apr_pool_t *scratch_pool)
+{
+  svn_wc__db_status_t status;
+  svn_node_kind_t kind;
+  const svn_checksum_t *old_checksum;
+  svn_boolean_t prop_mods;
+
+  SVN_ERR(svn_wc__db_read_info_internal(&status, &kind, NULL, NULL, NULL, NULL, NULL,
+                                        NULL, NULL, &old_checksum, NULL, NULL,
+                                        NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                                        NULL, &prop_mods, NULL, NULL, NULL,
+                                        wcroot, local_relpath,
+                                        scratch_pool, scratch_pool));
+
+  /* NOTE: be wary of making crazy semantic changes in this function, since
+     svn_wc_process_committed4() calls this.  */
+
+  SVN_ERR(process_committed_leaf(db, wcroot, local_relpath, !top_of_recurse,
+                                 status, kind, prop_mods, old_checksum,
+                                 new_revnum, new_date, rev_author,
+                                 new_dav_cache,
+                                 remove_lock, remove_changelist,
+                                 new_sha1_checksum,
+                                 scratch_pool));
+
+  /* Only check for recursion on nodes that have children */
+  if (kind != svn_node_dir
+      || status == svn_wc__db_status_not_present
+      || status == svn_wc__db_status_excluded
+      || status == svn_wc__db_status_server_excluded
+      /* Node deleted -> then no longer a directory */
+      || status == svn_wc__db_status_deleted)
+    {
+      return SVN_NO_ERROR;
+    }
+
+  if (recurse)
+    {
+      const apr_array_header_t *children;
+      apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+      int i;
+
+      /* Read PATH's entries;  this is the absolute path. */
+      SVN_ERR(gather_children(&children, wcroot, local_relpath,
+                              scratch_pool, iterpool));
+
+      /* Recursively loop over all children. */
+      for (i = 0; i < children->nelts; i++)
+        {
+          const char *name = APR_ARRAY_IDX(children, i, const char *);
+          const char *this_relpath;
+          const commit_queue_item_t *cqi;
+
+          svn_pool_clear(iterpool);
+
+          this_relpath = svn_dirent_join(local_relpath, name, iterpool);
+
+          new_sha1_checksum = NULL;
+          cqi = svn_hash_gets(items_by_relpath, this_relpath);
+
+          if (cqi != NULL)
+            new_sha1_checksum = cqi->new_sha1_checksum;
+
+          /* Recurse.  Pass NULL for NEW_DAV_CACHE, because the
+             ones present in the current call are only applicable to
+             this one committed item. */
+          SVN_ERR(process_committed_internal(
+                    db, wcroot, this_relpath,
+                    TRUE /* recurse */,
+                    FALSE /* top_of_recurse */,
+                    new_revnum, new_date,
+                    rev_author,
+                    NULL /* new_dav_cache */,
+                    FALSE /* remove_lock */,
+                    remove_changelist,
+                    new_sha1_checksum,
+                    items_by_relpath,
+                    iterpool));
+        }
+
+      svn_pool_destroy(iterpool);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+/* Return TRUE if any item of QUEUE is a parent of ITEM and will be
+   processed recursively, return FALSE otherwise.
+
+   The algorithmic complexity of this search implementation is O(queue
+   length), but it's quite quick.
+*/
+static svn_boolean_t
+have_recursive_parent(const apr_array_header_t *all_items,
+                      const commit_queue_item_t *item,
+                      apr_pool_t *scratch_pool)
+{
+  const char *local_relpath = item->local_relpath;
+  int i;
+
+  for (i = 0; i < all_items->nelts; i++)
+    {
+      const commit_queue_item_t *qi
+        = APR_ARRAY_IDX(all_items, i, const commit_queue_item_t *);
+
+      if (qi == item)
+        continue;
+
+      if (qi->recurse && svn_relpath_skip_ancestor(qi->local_relpath,
+                                                   local_relpath))
+        {
+          return TRUE;
+        }
+    }
+
+  return FALSE;
+}
+
+/* Compare function for svn_sort__array */
+static int
+compare_queue_items(const void *v1,
+                    const void *v2)
+{
+  const commit_queue_item_t *cqi1 
+              = *(const commit_queue_item_t **)v1;
+  const commit_queue_item_t *cqi2
+              = *(const commit_queue_item_t **)v2;
+
+  return svn_path_compare_paths(cqi1->local_relpath, cqi2->local_relpath);
+}
+
+/* Internal, locked version of svn_wc__db_process_commit_queue */
+static svn_error_t *
+db_process_commit_queue(svn_wc__db_t *db,
+                        svn_wc__db_commit_queue_t *queue,
+                        svn_revnum_t new_revnum,
+                        apr_time_t new_date,
+                        const char *new_author,
+                        apr_pool_t *scratch_pool)
+{
+  apr_hash_t *items_by_relpath = NULL;
+  int j;
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+
+  svn_sort__array(queue->items, compare_queue_items);
+
+  if (queue->have_recurse)
+    {
+      items_by_relpath = apr_hash_make(scratch_pool);
+
+      for (j = 0; j < queue->items->nelts; j++)
+        {
+          commit_queue_item_t *cqi
+            = APR_ARRAY_IDX(queue->items, j, commit_queue_item_t *);
+
+          svn_hash_sets(items_by_relpath, cqi->local_relpath, cqi);
+        }
+    }
+
+  for (j = 0; j < queue->items->nelts; j++)
+    {
+      commit_queue_item_t *cqi
+        = APR_ARRAY_IDX(queue->items, j, commit_queue_item_t *);
+
+      svn_pool_clear(iterpool);
+
+      /* Skip this item if it is a child of a recursive item, because it has
+         been (or will be) accounted for when that recursive item was (or
+         will be) processed. */
+      if (queue->have_recurse && have_recursive_parent(queue->items, cqi,
+                                                       iterpool))
+        continue;
+
+      if (!cqi->committed)
+        {
+          if (cqi->remove_lock)
+            {
+              svn_skel_t *work_item;
+
+              SVN_ERR(svn_wc__wq_build_sync_file_flags(
+                                                    &work_item,
+                                                    db,
+                                                    svn_dirent_join(
+                                                        queue->wcroot->abspath,
+                                                        cqi->local_relpath,
+                                                        iterpool),
+                                                    iterpool, iterpool));
+
+              lock_remove_txn(queue->wcroot, cqi->local_relpath, work_item,
+                              iterpool);
+            }
+          if (cqi->remove_changelist)
+            SVN_ERR(svn_wc__db_op_set_changelist(db,
+                                                 svn_dirent_join(
+                                                        queue->wcroot->abspath,
+                                                        cqi->local_relpath,
+                                                        iterpool),
+                                                 NULL, NULL,
+                                                 svn_depth_empty,
+                                                 NULL, NULL, /* notify */
+                                                 NULL, NULL, /* cancel */
+                                                 iterpool));
+        }
+      else
+        {
+          SVN_ERR(process_committed_internal(
+                                  db, queue->wcroot, cqi->local_relpath,
+                                  cqi->recurse,
+                                  TRUE /* top_of_recurse */,
+                                  new_revnum, new_date, new_author,
+                                  cqi->new_dav_cache,
+                                  cqi->remove_lock,
+                                  cqi->remove_changelist,
+                                  cqi->new_sha1_checksum,
+                                  items_by_relpath,
+                                  iterpool));
+        }
+    }
+
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__db_process_commit_queue(svn_wc__db_t *db,
+                                svn_wc__db_commit_queue_t *queue,
+                                svn_revnum_t new_revnum,
+                                apr_time_t new_date,
+                                const char *new_author,
+                                apr_pool_t *scratch_pool)
+{
+  SVN_WC__DB_WITH_TXN(db_process_commit_queue(db, queue,
+                                              new_revnum, new_date,
+                                              new_author, scratch_pool),
+                        queue->wcroot);
+
+  return SVN_NO_ERROR;
+}

Modified: subversion/branches/authzperf/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_wc/wc_db.h?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/authzperf/subversion/libsvn_wc/wc_db.h Sat Jan  3 14:00:41 2015
@@ -1261,6 +1261,53 @@ svn_wc__db_committable_externals_below(a
                                        apr_pool_t *result_pool,
                                        apr_pool_t *scratch_pool);
 
+/* Opaque struct for svn_wc__db_create_commit_queue, svn_wc__db_commit_queue_add,
+   svn_wc__db_process_commit_queue */
+typedef struct svn_wc__db_commit_queue_t svn_wc__db_commit_queue_t;
+
+/* Create a new svn_wc__db_commit_queue_t instance in RESULT_POOL for the
+   working copy specified with WRI_ABSPATH */
+svn_error_t *
+svn_wc__db_create_commit_queue(svn_wc__db_commit_queue_t **queue,
+                               svn_wc__db_t *db,
+                               const char *wri_abspath,
+                               apr_pool_t *result_pool,
+                               apr_pool_t *scratch_pool);
+
+/* Adds the specified path to the commit queue with the related information.
+
+   See svn_wc_queue_committed4() for argument documentation.
+
+   Note that this function currently DOESN'T copy the passed values to
+   RESULT_POOL, but expects them to be valid until processing. Otherwise the
+   only users memory requirements would +- double.
+  */
+svn_error_t *
+svn_wc__db_commit_queue_add(svn_wc__db_commit_queue_t *queue,
+                            const char *local_abspath,
+                            svn_boolean_t recurse,
+                            svn_boolean_t is_commited,
+                            svn_boolean_t remove_lock,
+                            svn_boolean_t remove_changelist,
+                            const svn_checksum_t *new_sha1_checksum,
+                            apr_hash_t *new_dav_cache,
+                            apr_pool_t *result_pool,
+                            apr_pool_t *scratch_pool);
+
+/* Process the items in QUEUE in a single transaction. Commit workqueue items
+   for items that need post processing.
+
+   Implementation detail of svn_wc_process_committed_queue2().
+ */
+svn_error_t *
+svn_wc__db_process_commit_queue(svn_wc__db_t *db,
+                                svn_wc__db_commit_queue_t *queue,
+                                svn_revnum_t new_revnum,
+                                apr_time_t new_date,
+                                const char *new_author,
+                                apr_pool_t *scratch_pool);
+
+
 /* Gets a mapping from const char * local abspaths of externals to the const
    char * local abspath of where they are defined for all externals defined
    at or below LOCAL_ABSPATH.
@@ -2633,10 +2680,12 @@ svn_wc__db_lock_add(svn_wc__db_t *db,
                     apr_pool_t *scratch_pool);
 
 
-/* Remove any lock for LOCAL_ABSPATH in DB.  */
+/* Remove any lock for LOCAL_ABSPATH in DB and install WORK_ITEMS
+   (if not NULL) in DB */
 svn_error_t *
 svn_wc__db_lock_remove(svn_wc__db_t *db,
                        const char *local_abspath,
+                       svn_skel_t *work_items,
                        apr_pool_t *scratch_pool);
 
 

Modified: subversion/branches/authzperf/subversion/libsvn_wc/workqueue.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_wc/workqueue.c?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_wc/workqueue.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_wc/workqueue.c Sat Jan  3 14:00:41 2015
@@ -1016,8 +1016,8 @@ svn_error_t *
 svn_wc__wq_build_dir_install(svn_skel_t **work_item,
                              svn_wc__db_t *db,
                              const char *local_abspath,
-                             apr_pool_t *scratch_pool,
-                             apr_pool_t *result_pool)
+                             apr_pool_t *result_pool,
+                             apr_pool_t *scratch_pool)
 {
   const char *local_relpath;
 

Modified: subversion/branches/authzperf/subversion/libsvn_wc/workqueue.h
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_wc/workqueue.h?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_wc/workqueue.h (original)
+++ subversion/branches/authzperf/subversion/libsvn_wc/workqueue.h Sat Jan  3 14:00:41 2015
@@ -215,8 +215,8 @@ svn_error_t *
 svn_wc__wq_build_dir_install(svn_skel_t **work_item,
                              svn_wc__db_t *db,
                              const char *local_abspath,
-                             apr_pool_t *scratch_pool,
-                             apr_pool_t *result_pool);
+                             apr_pool_t *result_pool,
+                             apr_pool_t *scratch_pool);
 
 svn_error_t *
 svn_wc__wq_build_postupgrade(svn_skel_t **work_item,

Modified: subversion/branches/authzperf/subversion/mod_authz_svn/mod_authz_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/mod_authz_svn/mod_authz_svn.c?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/mod_authz_svn/mod_authz_svn.c (original)
+++ subversion/branches/authzperf/subversion/mod_authz_svn/mod_authz_svn.c Sat Jan  3 14:00:41 2015
@@ -361,7 +361,7 @@ get_access_conf(request_rec *r, authz_sv
   svn_error_t *svn_err = SVN_NO_ERROR;
   dav_error *dav_err;
 
-  dav_err = dav_svn_get_repos_path(r, conf->base_path, &repos_path);
+  dav_err = dav_svn_get_repos_path2(r, conf->base_path, &repos_path, scratch_pool);
   if (dav_err)
     {
       ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "%s", dav_err->desc);

Modified: subversion/branches/authzperf/subversion/mod_dav_svn/deadprops.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/mod_dav_svn/deadprops.c?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/mod_dav_svn/deadprops.c (original)
+++ subversion/branches/authzperf/subversion/mod_dav_svn/deadprops.c Sat Jan  3 14:00:41 2015
@@ -323,7 +323,7 @@ db_open(apr_pool_t *p,
   db->p = svn_pool_create(p);
 
   /* ### temp hack */
-  db->work = svn_stringbuf_ncreate("", 0, db->p);
+  db->work = svn_stringbuf_create_empty(db->p);
 
   /* make our path-based authz callback available to svn_repos_* funcs. */
   arb = apr_pcalloc(p, sizeof(*arb));

Modified: subversion/branches/authzperf/subversion/mod_dav_svn/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/mod_dav_svn/lock.c?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/mod_dav_svn/lock.c (original)
+++ subversion/branches/authzperf/subversion/mod_dav_svn/lock.c Sat Jan  3 14:00:41 2015
@@ -787,7 +787,31 @@ append_locks(dav_lockdb *lockdb,
                                 DAV_ERR_LOCK_SAVE_LOCK,
                                 "Anonymous lock creation is not allowed.");
     }
-  else if (serr && (serr->apr_err == SVN_ERR_REPOS_HOOK_FAILURE ||
+  else if (serr && serr->apr_err == SVN_ERR_REPOS_POST_LOCK_HOOK_FAILED)
+    {
+      /* The lock was created in the repository, so we should report the node
+         as locked to the client */
+
+      /* First log the hook failure, for diagnostics. This clears serr */
+      dav_svn__log_err(info->r,
+                       dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
+                                            "Post lock hook failure.",
+                                            resource->pool),
+                       APLOG_WARNING);
+
+      /* How can we report the error to the client?
+
+         We can't return an error code, as that would make it impossible
+         to return the lock details?
+
+         Add yet another custom header?
+         Just an header doesn't handle a full error chain... 
+
+         ### Current behavior: we don't report an error.
+       */
+
+    }
+  else if (serr && (svn_error_find_cause(serr, SVN_ERR_REPOS_HOOK_FAILURE) ||
                     serr->apr_err == SVN_ERR_FS_NO_SUCH_LOCK ||
                     serr->apr_err == SVN_ERR_FS_LOCK_EXPIRED ||
                     SVN_ERR_IS_LOCK_ERROR(serr)))
@@ -897,6 +921,22 @@ remove_lock(dav_lockdb *lockdb,
                                     DAV_ERR_LOCK_SAVE_LOCK,
                                     "Anonymous lock removal is not allowed.");
         }
+      else if (serr && serr->apr_err == SVN_ERR_REPOS_POST_UNLOCK_HOOK_FAILED
+               && !resource->info->repos->is_svn_client)
+        {
+          /* Generic DAV clients don't understand the specific error code we
+             would produce here as being just a warning, so lets produce a
+             success result. We removed the lock anyway. */
+
+          /* First log the hook failure, for diagnostics. This clears serr */
+          dav_svn__log_err(info->r,
+                           dav_svn__convert_err(serr,
+                                                HTTP_INTERNAL_SERVER_ERROR,
+                                                "Post unlock hook failure.",
+                                                resource->pool),
+                           APLOG_WARNING);
+
+        }
       else if (serr)
         return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                     "Failed to remove a lock.",
@@ -1016,7 +1056,7 @@ refresh_locks(dav_lockdb *lockdb,
                                 DAV_ERR_LOCK_SAVE_LOCK,
                                 "Anonymous lock refreshing is not allowed.");
     }
-  else if (serr && (serr->apr_err == SVN_ERR_REPOS_HOOK_FAILURE ||
+  else if (serr && (svn_error_find_cause(serr, SVN_ERR_REPOS_HOOK_FAILURE) ||
                     serr->apr_err == SVN_ERR_FS_NO_SUCH_LOCK ||
                     serr->apr_err == SVN_ERR_FS_LOCK_EXPIRED ||
                     SVN_ERR_IS_LOCK_ERROR(serr)))

Modified: subversion/branches/authzperf/subversion/mod_dav_svn/mod_dav_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/mod_dav_svn/mod_dav_svn.c?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/mod_dav_svn/mod_dav_svn.c (original)
+++ subversion/branches/authzperf/subversion/mod_dav_svn/mod_dav_svn.c Sat Jan  3 14:00:41 2015
@@ -662,9 +662,10 @@ dav_svn__get_fs_parent_path(request_rec
 
 
 AP_MODULE_DECLARE(dav_error *)
-dav_svn_get_repos_path(request_rec *r,
-                       const char *root_path,
-                       const char **repos_path)
+dav_svn_get_repos_path2(request_rec *r,
+                        const char *root_path,
+                        const char **repos_path,
+                        apr_pool_t *pool)
 {
 
   const char *fs_path;
@@ -692,19 +693,26 @@ dav_svn_get_repos_path(request_rec *r,
 
   /* Split the svn URI to get the name of the repository below
      the parent path. */
-  derr = dav_svn_split_uri(r, r->uri, root_path,
-                           &ignored_cleaned_uri, &ignored_had_slash,
-                           &repos_name,
-                           &ignored_relative, &ignored_path_in_repos);
+  derr = dav_svn_split_uri2(r, r->uri, root_path,
+                            &ignored_cleaned_uri, &ignored_had_slash,
+                            &repos_name,
+                            &ignored_relative, &ignored_path_in_repos, pool);
   if (derr)
     return derr;
 
   /* Construct the full path from the parent path base directory
      and the repository name. */
-  *repos_path = svn_dirent_join(fs_parent_path, repos_name, r->pool);
+  *repos_path = svn_dirent_join(fs_parent_path, repos_name, pool);
   return NULL;
 }
 
+AP_MODULE_DECLARE(dav_error *)
+dav_svn_get_repos_path(request_rec *r,
+                       const char *root_path,
+                       const char **repos_path)
+{
+  return dav_svn_get_repos_path2(r, root_path, repos_path, r->pool);
+}
 
 const char *
 dav_svn__get_repo_name(request_rec *r)
@@ -1324,8 +1332,8 @@ static const command_rec cmds[] =
   AP_INIT_TAKE1("SVNInMemoryCacheSize", SVNInMemoryCacheSize_cmd, NULL,
                 RSRC_CONF,
                 "specifies the maximum size in kB per process of Subversion's "
-                "in-memory object cache (default value is 16384; 0 deactivates "
-                "the cache)."),
+                "in-memory object cache (default value is 16384; 0 switches "
+                "to dynamically sized caches)."),
   /* per server */
   AP_INIT_TAKE1("SVNCompressionLevel", SVNCompressionLevel_cmd, NULL,
                 RSRC_CONF,

Modified: subversion/branches/authzperf/subversion/mod_dav_svn/reports/deleted-rev.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/mod_dav_svn/reports/deleted-rev.c?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/mod_dav_svn/reports/deleted-rev.c (original)
+++ subversion/branches/authzperf/subversion/mod_dav_svn/reports/deleted-rev.c Sat Jan  3 14:00:41 2015
@@ -56,6 +56,9 @@ dav_svn__get_deleted_rev_report(const da
   dav_error *derr = NULL;
 
   /* Sanity check. */
+  if (!resource->info->repos_path)
+    return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0,
+                              "The request does not specify a repository path");
   ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE);
   if (ns == -1)
     return dav_svn__new_error_svn(resource->pool, HTTP_BAD_REQUEST, 0,