You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2014/10/19 15:55:38 UTC

svn commit: r1632906 [6/10] - in /subversion/branches/revprop-caching-ng: ./ build/ notes/ subversion/bindings/ctypes-python/ subversion/bindings/cxxhl/ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_delta/ ...

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_subr/packed_data.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_subr/packed_data.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_subr/packed_data.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_subr/packed_data.c Sun Oct 19 13:55:35 2014
@@ -276,6 +276,33 @@ write_packed_uint_body(unsigned char *bu
   return buffer;
 }
 
+/* Return remapped VALUE.
+ *
+ * Due to sign conversion and diff underflow, values close to UINT64_MAX
+ * are almost as frequent as those close to 0.  Remap them such that the
+ * MSB is stored in the LSB and the remainder stores the absolute distance
+ * to 0.
+ *
+ * This minimizes the absolute value to store in many scenarios.
+ * Hence, the variable-length representation on disk is shorter, too.
+ */
+static apr_uint64_t
+remap_uint(apr_uint64_t value)
+{
+  return value & APR_UINT64_C(0x8000000000000000)
+       ? APR_UINT64_MAX - (2 * value)
+       : 2 * value;
+}
+
+/* Invert remap_uint. */
+static apr_uint64_t
+unmap_uint(apr_uint64_t value)
+{
+  return value & 1
+       ? (APR_UINT64_MAX - value / 2)
+       : value / 2;
+}
+
 /* Empty the unprocessed integer buffer in STREAM by either pushing the
  * data to the sub-streams or writing to the packed data (in case there
  * are no sub-streams).
@@ -313,8 +340,7 @@ svn_packed__data_flush_buffer(svn_packed
           for (i = 0; i < stream->buffer_used; ++i)
             {
               apr_uint64_t temp = stream->buffer[i];
-              apr_int64_t diff = (apr_int64_t)(temp - last_value);
-              stream->buffer[i] = diff < 0 ? -1 - 2 * diff : 2 * diff;
+              stream->buffer[i] = remap_uint(temp - last_value);
               last_value = temp;
             }
 
@@ -327,9 +353,7 @@ svn_packed__data_flush_buffer(svn_packed
          63 bits. */
       if (!private_data->diff && private_data->is_signed)
         for (i = 0; i < stream->buffer_used; ++i)
-          stream->buffer[i] = (apr_int64_t)stream->buffer[i] < 0
-                            ? -1 - 2 * stream->buffer[i]
-                            : 2 * stream->buffer[i];
+          stream->buffer[i] = remap_uint(stream->buffer[i]);
 
       /* auto-create packed data buffer.  Give it some reasonable initial
          size - just enough for a few tens of values. */
@@ -771,8 +795,8 @@ svn_packed__data_fill_buffer(svn_packed_
   else
     {
       /* use this local buffer only if the packed data is shorter than this.
-         The goal is that we don't need to check for overflows that is not
-         detected by read_packed_uint_body. */
+         The goal is that read_packed_uint_body doesn't need check for
+         overflows. */
       unsigned char local_buffer[10 * SVN__PACKED_DATA_BUFFER_SIZE];
       unsigned char *p;
       unsigned char *start;
@@ -808,9 +832,7 @@ svn_packed__data_fill_buffer(svn_packed_
           apr_uint64_t last_value = private_data->last_value;
           for (i = end; i > 0; --i)
             {
-              apr_uint64_t temp = stream->buffer[i-1];
-              temp = (temp % 2) ? -1 - temp / 2 : temp / 2;
-              last_value += temp;
+              last_value += unmap_uint(stream->buffer[i-1]);
               stream->buffer[i-1] = last_value;
             }
 
@@ -820,9 +842,7 @@ svn_packed__data_fill_buffer(svn_packed_
       /* handle signed values, if configured and not handled already */
       if (!private_data->diff && private_data->is_signed)
         for (i = 0; i < end; ++i)
-          stream->buffer[i] = (stream->buffer[i] % 2)
-                            ? -1 - stream->buffer[i] / 2
-                            : stream->buffer[i] / 2;
+          stream->buffer[i] = unmap_uint(stream->buffer[i]);
     }
 
   stream->buffer_used = end;

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_subr/path.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_subr/path.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_subr/path.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_subr/path.c Sun Oct 19 13:55:35 2014
@@ -1299,7 +1299,7 @@ svn_path_resolve_repos_relative_url(cons
                              _("Improper relative URL '%s'"),
                              relative_url);
 
-  /* No assumptions are made about the canonicalization of the inut
+  /* No assumptions are made about the canonicalization of the input
    * arguments, it is presumed that the output will be canonicalized after
    * this function, which will remove any duplicate path separator.
    */

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_subr/sorts.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_subr/sorts.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_subr/sorts.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_subr/sorts.c Sun Oct 19 13:55:35 2014
@@ -244,14 +244,48 @@ svn_sort__array_lookup(const apr_array_h
    * hit location) first.  This speeds up linear scans. */
   if (hint)
     {
-      idx = *hint;
-      *hint = ++idx;
-      if (idx >= 0 && idx < array->nelts)
+      /* We intend to insert right behind *HINT.
+       * Exit this function early, if we actually can. */
+      idx = *hint + 1;
+      if (idx >= array->nelts)
         {
+          /* We intend to insert after the last entry.
+           * That is only allowed if that last entry is smaller than KEY.
+           * In that case, there will be no current entry, i.e. we must
+           * return NULL. */
+          apr_size_t offset;
+
+          *hint = array->nelts;
+          if (array->nelts == 0)
+            return NULL;
+
+          offset = (array->nelts - 1) * array->elt_size;
+          if (compare_func(array->elts + offset, key) < 0)
+            return NULL;
+        }
+      else if (idx > 0)
+        {
+          /* Intend to insert at a position inside the array, i.e. not
+           * at one of the boundaries.  The predecessor must be smaller
+           * and the current entry at IDX must be larger than KEY. */
+		  void *previous;
+
+          *hint = idx;
+		  previous = array->elts + (idx-1) * array->elt_size;
           result = array->elts + idx * array->elt_size;
-          if (!compare_func(result, key))
+          if (compare_func(previous, key) && !compare_func(result, key))
             return result;
         }
+      else if (idx <= 0)
+        {
+          /* Intend to insert at the beginning of an non-empty array.
+           * That requires the first entry to be larger than KEY. */
+          *hint = 0;
+          if (!compare_func(array->elts, key))
+            return array->elts;
+        }
+
+      /* The HINT did not help. */
     }
 
   idx = bsearch_lower_bound(key, array->elts, array->nelts, array->elt_size,

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_subr/string.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_subr/string.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_subr/string.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_subr/string.c Sun Oct 19 13:55:35 2014
@@ -26,6 +26,7 @@
 
 
 #include <apr.h>
+#include <assert.h>
 
 #include <string.h>      /* for memcpy(), memcmp(), strlen() */
 #include <apr_fnmatch.h>
@@ -239,7 +240,9 @@ svn_string_ncreate(const char *bytes, ap
   new_string->data = data;
   new_string->len = size;
 
-  memcpy(data, bytes, size);
+  /* If SIZE is 0, NULL is valid for BYTES. */
+  if (size)
+    memcpy(data, bytes, size);
 
   /* Null termination is the convention -- even if we suspect the data
      to be binary, it's not up to us to decide, it's the caller's
@@ -392,7 +395,10 @@ svn_stringbuf_t *
 svn_stringbuf_ncreate(const char *bytes, apr_size_t size, apr_pool_t *pool)
 {
   svn_stringbuf_t *strbuf = svn_stringbuf_create_ensure(size, pool);
-  memcpy(strbuf->data, bytes, size);
+
+  /* If SIZE is 0, NULL is valid for BYTES. */
+  if (size)
+    memcpy(strbuf->data, bytes, size);
 
   /* Null termination is the convention -- even if we suspect the data
      to be binary, it's not up to us to decide, it's the caller's
@@ -589,6 +595,10 @@ svn_stringbuf_appendbytes(svn_stringbuf_
   apr_size_t total_len;
   void *start_address;
 
+  if (!count)
+    /* Allow BYTES to be NULL by avoiding passing it to memcpy. */
+    return;
+
   total_len = str->len + count;  /* total size needed */
 
   /* svn_stringbuf_ensure adds 1 for null terminator. */
@@ -641,6 +651,10 @@ svn_stringbuf_insert(svn_stringbuf_t *st
                      const char *bytes,
                      apr_size_t count)
 {
+  /* For COUNT==0, we allow BYTES to be NULL. It's a no-op in that case. */
+  if (count == 0)
+    return;
+
   if (bytes + count > str->data && bytes < str->data + str->blocksize)
     {
       /* special case: BYTES overlaps with this string -> copy the source */
@@ -681,6 +695,14 @@ svn_stringbuf_replace(svn_stringbuf_t *s
                       const char *bytes,
                       apr_size_t new_count)
 {
+  /* For COUNT==0, we allow BYTES to be NULL.
+   * In that case, this is just a substring removal. */
+  if (new_count == 0)
+    {
+      svn_stringbuf_remove(str, pos, old_count);
+      return;
+    }
+
   if (bytes + new_count > str->data && bytes < str->data + str->blocksize)
     {
       /* special case: BYTES overlaps with this string -> copy the source */
@@ -1164,7 +1186,7 @@ svn__i64toa(char * dest, apr_int64_t num
     return svn__ui64toa(dest, (apr_uint64_t)number);
 
   *dest = '-';
-  return svn__ui64toa(dest + 1, (apr_uint64_t)(0-number)) + 1;
+  return svn__ui64toa(dest + 1, 0 - (apr_uint64_t)number) + 1;
 }
 
 static void

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_subr/subst.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_subr/subst.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_subr/subst.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_subr/subst.c Sun Oct 19 13:55:35 2014
@@ -159,7 +159,7 @@ keyword_printf(const char *fmt,
                const char *author,
                apr_pool_t *pool)
 {
-  svn_stringbuf_t *value = svn_stringbuf_ncreate("", 0, pool);
+  svn_stringbuf_t *value = svn_stringbuf_create_empty(pool);
   const char *cur;
   size_t n;
 

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_subr/sysinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_subr/sysinfo.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_subr/sysinfo.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_subr/sysinfo.c Sun Oct 19 13:55:35 2014
@@ -1042,16 +1042,17 @@ release_name_from_version(const char *os
   /* See http://en.wikipedia.org/wiki/History_of_OS_X#Release_timeline */
   switch(num)
     {
-    case 0: return "Cheetah";
-    case 1: return "Puma";
-    case 2: return "Jaguar";
-    case 3: return "Panther";
-    case 4: return "Tiger";
-    case 5: return "Leopard";
-    case 6: return "Snow Leopard";
-    case 7: return "Lion";
-    case 8: return "Mountain Lion";
-    case 9: return "Mavericks";
+    case  0: return "Cheetah";
+    case  1: return "Puma";
+    case  2: return "Jaguar";
+    case  3: return "Panther";
+    case  4: return "Tiger";
+    case  5: return "Leopard";
+    case  6: return "Snow Leopard";
+    case  7: return "Lion";
+    case  8: return "Mountain Lion";
+    case  9: return "Mavericks";
+    case 10: return "Yosemite";
     }
 
   return NULL;

Propchange: subversion/branches/revprop-caching-ng/subversion/libsvn_subr/utf8proc/README
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_wc/adm_ops.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_wc/adm_ops.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_wc/adm_ops.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_wc/adm_ops.c Sun Oct 19 13:55:35 2014
@@ -63,23 +63,23 @@ struct svn_wc_committed_queue_t
 {
   /* The pool in which ->queue is allocated. */
   apr_pool_t *pool;
-  /* Mapping (const char *) local_abspath to (committed_queue_item_t *). */
-  apr_hash_t *queue;
-  /* Is any item in the queue marked as 'recursive'? */
-  svn_boolean_t have_recursive;
+  /* Mapping (const char *) wcroot_abspath to svn_wc__db_commit_queue_t * */
+  apr_hash_t *wc_queues;
 };
 
 typedef struct committed_queue_item_t
 {
   const char *local_abspath;
-  svn_boolean_t recurse;
-  svn_boolean_t no_unlock;
-  svn_boolean_t keep_changelist;
+  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;
 
-  /* The pristine text checksum. */
-  const svn_checksum_t *sha1_checksum;
-
-  apr_hash_t *new_dav_cache;
+  apr_hash_t *new_dav_cache; /* New DAV cache for the node */
 } committed_queue_item_t;
 
 
@@ -89,245 +89,6 @@ svn_wc__get_committed_queue_pool(const s
   return queue->pool;
 }
 
-
-
-/*** Finishing updates and commits. ***/
-
-/* Queue work items that will finish a commit of the file or directory
- * LOCAL_ABSPATH in DB:
- *   - queue the removal of any "revert-base" props and text files;
- *   - queue an update of the DB entry for this node
- *
- * ### The Pristine Store equivalent should be:
- *   - remember the old BASE_NODE and WORKING_NODE pristine text c'sums;
- *   - queue an update of the DB entry for this node (incl. updating the
- *       BASE_NODE c'sum and setting the WORKING_NODE c'sum to NULL);
- *   - queue deletion of the old pristine texts by the remembered checksums.
- *
- * CHECKSUM is the checksum of the new text base for LOCAL_ABSPATH, and must
- * be provided if there is one, else NULL.
- *
- * STATUS, KIND, PROP_MODS and OLD_CHECKSUM are the current in-db values of
- * the node LOCAL_ABSPATH.
- */
-static svn_error_t *
-process_committed_leaf(svn_wc__db_t *db,
-                       const char *local_abspath,
-                       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 no_unlock,
-                       svn_boolean_t keep_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;
-
-  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
-
-  {
-    const char *adm_abspath;
-
-    if (kind == svn_node_dir)
-      adm_abspath = local_abspath;
-    else
-      adm_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
-    SVN_ERR(svn_wc__write_check(db, adm_abspath, scratch_pool));
-  }
-
-  if (status == svn_wc__db_status_deleted)
-    {
-      return svn_error_trace(
-                svn_wc__db_base_remove(
-                                db, local_abspath,
-                                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(NULL, 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, NULL,
-                                           db, local_abspath,
-                                           scratch_pool, scratch_pool));
-            }
-        }
-
-      SVN_ERR(svn_wc__wq_build_file_commit(&work_item,
-                                           db, local_abspath,
-                                           prop_mods,
-                                           scratch_pool, scratch_pool));
-    }
-
-  /* The new text base will be found in the pristine store by its checksum. */
-  SVN_ERR(svn_wc__db_global_commit(db, local_abspath,
-                                   new_revnum, new_changed_rev,
-                                   new_changed_date, new_changed_author,
-                                   checksum,
-                                   NULL /* new_children */,
-                                   new_dav_cache,
-                                   keep_changelist,
-                                   no_unlock,
-                                   work_item,
-                                   scratch_pool));
-
-  return SVN_NO_ERROR;
-}
-
-
-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)
-{
-  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(&status, &kind, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, &old_checksum, NULL, NULL,
-                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, &prop_mods, NULL, NULL, NULL,
-                               db, local_abspath,
-                               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, local_abspath, !top_of_recurse,
-                                 status, kind, prop_mods, old_checksum,
-                                 new_revnum, new_date, rev_author,
-                                 new_dav_cache,
-                                 no_unlock, keep_changelist,
-                                 sha1_checksum,
-                                 scratch_pool));
-
-  /* Only check for recursion on nodes that have children */
-  if (kind != svn_node_file
-      || 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(svn_wc__db_read_children(&children, db, local_abspath,
-                                       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_abspath;
-          const committed_queue_item_t *cqi;
-
-          svn_pool_clear(iterpool);
-
-          this_abspath = svn_dirent_join(local_abspath, name, iterpool);
-
-          sha1_checksum = NULL;
-          cqi = svn_hash_gets(queue->queue, this_abspath);
-
-          if (cqi != NULL)
-            sha1_checksum = cqi->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(svn_wc__process_committed_internal(
-                    db, this_abspath,
-                    TRUE /* recurse */,
-                    FALSE /* top_of_recurse */,
-                    new_revnum, new_date,
-                    rev_author,
-                    NULL /* new_dav_cache */,
-                    TRUE /* no_unlock */,
-                    keep_changelist,
-                    sha1_checksum,
-                    queue,
-                    iterpool));
-        }
-
-      svn_pool_destroy(iterpool);
-    }
-
-  return SVN_NO_ERROR;
-}
-
-
 apr_hash_t *
 svn_wc__prop_array_to_hash(const apr_array_header_t *props,
                            apr_pool_t *result_pool)
@@ -358,76 +119,56 @@ svn_wc_committed_queue_create(apr_pool_t
 
   q = apr_palloc(pool, sizeof(*q));
   q->pool = pool;
-  q->queue = apr_hash_make(pool);
-  q->have_recursive = FALSE;
+  q->wc_queues = apr_hash_make(pool);
 
   return q;
 }
 
 
 svn_error_t *
-svn_wc_queue_committed3(svn_wc_committed_queue_t *queue,
+svn_wc_queue_committed4(svn_wc_committed_queue_t *queue,
                         svn_wc_context_t *wc_ctx,
                         const char *local_abspath,
                         svn_boolean_t recurse,
+                        svn_boolean_t is_committed,
                         const apr_array_header_t *wcprop_changes,
                         svn_boolean_t remove_lock,
                         svn_boolean_t remove_changelist,
                         const svn_checksum_t *sha1_checksum,
                         apr_pool_t *scratch_pool)
 {
-  committed_queue_item_t *cqi;
+  const char *wcroot_abspath;
+  svn_wc__db_commit_queue_t *db_queue;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
-  queue->have_recursive |= recurse;
-
   /* Use the same pool as the one QUEUE was allocated in,
      to prevent lifetime issues.  Intermediate operations
      should use SCRATCH_POOL. */
 
-  /* Add to the array with paths and options */
-  cqi = apr_palloc(queue->pool, sizeof(*cqi));
-  cqi->local_abspath = local_abspath;
-  cqi->recurse = recurse;
-  cqi->no_unlock = !remove_lock;
-  cqi->keep_changelist = !remove_changelist;
-  cqi->sha1_checksum = sha1_checksum;
-  cqi->new_dav_cache = svn_wc__prop_array_to_hash(wcprop_changes, queue->pool);
-
-  svn_hash_sets(queue->queue, local_abspath, cqi);
-
-  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(apr_hash_t *queue,
-                      const committed_queue_item_t *item,
-                      apr_pool_t *scratch_pool)
-{
-  apr_hash_index_t *hi;
-  const char *local_abspath = item->local_abspath;
+  SVN_ERR(svn_wc__db_get_wcroot(&wcroot_abspath,
+                                wc_ctx->db, local_abspath,
+                                scratch_pool, scratch_pool));
 
-  for (hi = apr_hash_first(scratch_pool, queue); hi; hi = apr_hash_next(hi))
+  db_queue = svn_hash_gets(queue->wc_queues, wcroot_abspath);
+  if (! db_queue)
     {
-      const committed_queue_item_t *qi = apr_hash_this_val(hi);
+      wcroot_abspath = apr_pstrdup(queue->pool, wcroot_abspath);
 
-      if (qi == item)
-        continue;
+      SVN_ERR(svn_wc__db_create_commit_queue(&db_queue,
+                                             wc_ctx->db, wcroot_abspath,
+                                             queue->pool, scratch_pool));
 
-      if (qi->recurse && svn_dirent_is_child(qi->local_abspath, local_abspath,
-                                             NULL))
-        return TRUE;
+      svn_hash_sets(queue->wc_queues, wcroot_abspath, db_queue);
     }
 
-  return FALSE;
+  return svn_error_trace(
+          svn_wc__db_commit_queue_add(db_queue, local_abspath, recurse,
+                                      is_committed, remove_lock,
+                                      remove_changelist, sha1_checksum,
+                                      svn_wc__prop_array_to_hash(wcprop_changes,
+                                                                 queue->pool),
+                                      queue->pool, scratch_pool));
 }
 
 
@@ -441,75 +182,44 @@ svn_wc_process_committed_queue2(svn_wc_c
                                 void *cancel_baton,
                                 apr_pool_t *scratch_pool)
 {
-  apr_array_header_t *sorted_queue;
+  apr_array_header_t *wcs;
   int i;
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
   apr_time_t new_date;
-  apr_hash_t *run_wqs = apr_hash_make(scratch_pool);
-  apr_hash_index_t *hi;
 
   if (rev_date)
     SVN_ERR(svn_time_from_cstring(&new_date, rev_date, iterpool));
   else
     new_date = 0;
 
-  /* Process the queued items in order of their paths.  (The requirement is
-   * probably just that a directory must be processed before its children.) */
-  sorted_queue = svn_sort__hash(queue->queue, svn_sort_compare_items_as_paths,
-                                scratch_pool);
-  for (i = 0; i < sorted_queue->nelts; i++)
+  /* Process the wc's in order of their paths. */
+  wcs = svn_sort__hash(queue->wc_queues, svn_sort_compare_items_as_paths,
+                       scratch_pool);
+  for (i = 0; i < wcs->nelts; i++)
     {
       const svn_sort__item_t *sort_item
-        = &APR_ARRAY_IDX(sorted_queue, i, svn_sort__item_t);
-      const committed_queue_item_t *cqi = sort_item->value;
-      const char *wcroot_abspath;
+                                = &APR_ARRAY_IDX(wcs, i, svn_sort__item_t);
+      svn_wc__db_commit_queue_t *db_queue = sort_item->value;
 
       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_recursive && have_recursive_parent(queue->queue, cqi,
-                                                         iterpool))
-        continue;
-
-      SVN_ERR(svn_wc__process_committed_internal(
-                wc_ctx->db, cqi->local_abspath,
-                cqi->recurse,
-                TRUE /* top_of_recurse */,
-                new_revnum, new_date, rev_author,
-                cqi->new_dav_cache,
-                cqi->no_unlock,
-                cqi->keep_changelist,
-                cqi->sha1_checksum, queue,
-                iterpool));
-
-      /* Don't run the wq now, but remember that we must call it for this
-         working copy */
-      SVN_ERR(svn_wc__db_get_wcroot(&wcroot_abspath,
-                                    wc_ctx->db, cqi->local_abspath,
-                                    iterpool, iterpool));
-
-      if (! svn_hash_gets(run_wqs, wcroot_abspath))
-        {
-          wcroot_abspath = apr_pstrdup(scratch_pool, wcroot_abspath);
-          svn_hash_sets(run_wqs, wcroot_abspath, wcroot_abspath);
-        }
+      SVN_ERR(svn_wc__db_process_commit_queue(wc_ctx->db, db_queue,
+                                              new_revnum, new_date, rev_author,
+                                              iterpool));
     }
 
   /* Make sure nothing happens if this function is called again.  */
-  apr_hash_clear(queue->queue);
+  apr_hash_clear(queue->wc_queues);
 
   /* Ok; everything is committed now. Now we can start calling callbacks */
-
   if (cancel_func)
     SVN_ERR(cancel_func(cancel_baton));
 
-  for (hi = apr_hash_first(scratch_pool, run_wqs);
-       hi;
-       hi = apr_hash_next(hi))
+  for (i = 0; i < wcs->nelts; i++)
     {
-      const char *wcroot_abspath = apr_hash_this_key(hi);
+      const svn_sort__item_t *sort_item
+          = &APR_ARRAY_IDX(wcs, i, svn_sort__item_t);
+      const char *wcroot_abspath = sort_item->key;
 
       svn_pool_clear(iterpool);
 
@@ -1231,7 +941,7 @@ svn_wc_remove_lock2(svn_wc_context_t *wc
                     apr_pool_t *scratch_pool)
 {
   svn_error_t *err;
-  const svn_string_t *needs_lock;
+  svn_skel_t *work_item;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
@@ -1239,7 +949,12 @@ svn_wc_remove_lock2(svn_wc_context_t *wc
                               svn_dirent_dirname(local_abspath, scratch_pool),
                               scratch_pool));
 
-  err = svn_wc__db_lock_remove(wc_ctx->db, local_abspath, scratch_pool);
+  SVN_ERR(svn_wc__wq_build_sync_file_flags(&work_item,
+                                           wc_ctx->db, local_abspath,
+                                           scratch_pool, scratch_pool));
+
+  err = svn_wc__db_lock_remove(wc_ctx->db, local_abspath, work_item,
+                               scratch_pool);
   if (err)
     {
       if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
@@ -1253,24 +968,9 @@ svn_wc_remove_lock2(svn_wc_context_t *wc
                                                       scratch_pool));
     }
 
-  /* if svn:needs-lock is present, then make the file read-only. */
-  err = svn_wc__internal_propget(&needs_lock, wc_ctx->db, local_abspath,
-                                 SVN_PROP_NEEDS_LOCK, scratch_pool,
-                                 scratch_pool);
-  if (err)
-    {
-      if (err->apr_err != SVN_ERR_WC_PATH_UNEXPECTED_STATUS)
-        return svn_error_trace(err);
-
-      svn_error_clear(err);
-      return SVN_NO_ERROR; /* Node is shadowed and/or deleted,
-                              so we shouldn't apply its lock */
-    }
-
-  if (needs_lock)
-    SVN_ERR(svn_io_set_file_read_only(local_abspath, FALSE, scratch_pool));
-
-  return SVN_NO_ERROR;
+  return svn_error_trace(svn_wc__wq_run(wc_ctx->db, local_abspath,
+                                        NULL, NULL /* cancel*/,
+                                        scratch_pool));
 }
 
 
@@ -1324,9 +1024,8 @@ get_node_changelist(const char *local_ab
                                NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                                b->db, local_abspath,
                                scratch_pool, scratch_pool));
-
-  if (svn_wc__internal_changelist_match(b->db, local_abspath, b->clhash,
-                                        scratch_pool))
+  if (!b->clhash
+      || (changelist && svn_hash_gets(b->clhash, changelist) != NULL))
     SVN_ERR(b->callback_func(b->callback_baton, local_abspath,
                              changelist, scratch_pool));
 

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_wc/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_wc/copy.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_wc/copy.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_wc/copy.c Sun Oct 19 13:55:35 2014
@@ -50,7 +50,14 @@
    TMPDIR_ABSPATH and return the absolute path of the copy in
    *DST_ABSPATH.  Return the node kind of SRC_ABSPATH in *KIND.  If
    SRC_ABSPATH doesn't exist then set *DST_ABSPATH to NULL to indicate
-   that no copy was made. */
+   that no copy was made.
+
+   If DIRENT is not NULL, it contains the on-disk information of SRC_ABSPATH.
+   RECORDED_SIZE (if not SVN_INVALID_FILESIZE) contains the recorded size of
+   SRC_ABSPATH, and RECORDED_TIME the recorded size or 0.
+
+   These values will be used to avoid unneeded work.
+ */
 static svn_error_t *
 copy_to_tmpdir(svn_skel_t **work_item,
                svn_node_kind_t *kind,
@@ -60,6 +67,9 @@ copy_to_tmpdir(svn_skel_t **work_item,
                const char *tmpdir_abspath,
                svn_boolean_t file_copy,
                svn_boolean_t unversioned,
+               const svn_io_dirent2_t *dirent,
+               svn_filesize_t recorded_size,
+               apr_time_t recorded_time,
                svn_cancel_func_t cancel_func,
                void *cancel_baton,
                apr_pool_t *result_pool,
@@ -74,8 +84,14 @@ copy_to_tmpdir(svn_skel_t **work_item,
 
   *work_item = NULL;
 
-  SVN_ERR(svn_io_check_special_path(src_abspath, kind, &is_special,
-                                    scratch_pool));
+  if (dirent)
+    {
+      *kind = dirent->kind;
+      is_special = dirent->special;
+    }
+  else
+    SVN_ERR(svn_io_check_special_path(src_abspath, kind, &is_special,
+                                      scratch_pool));
   if (*kind == svn_node_none)
     {
       return SVN_NO_ERROR;
@@ -104,9 +120,21 @@ copy_to_tmpdir(svn_skel_t **work_item,
          the timestamp might match, than to examine the
          destination later as the destination timestamp will
          never match. */
-      SVN_ERR(svn_wc__internal_file_modified_p(&modified,
-                                               db, src_abspath,
-                                               FALSE, scratch_pool));
+
+      if (dirent
+          && dirent->kind == svn_node_file
+          && recorded_size != SVN_INVALID_FILESIZE
+          && recorded_size == dirent->filesize
+          && recorded_time == dirent->mtime)
+        {
+          modified = FALSE; /* Recorded matches on-disk. Easy out */
+        }
+      else
+        {
+          SVN_ERR(svn_wc__internal_file_modified_p(&modified, db, src_abspath,
+                                                   FALSE, scratch_pool));
+        }
+
       if (!modified)
         {
           /* Why create a temp copy if we can just reinstall from pristine? */
@@ -117,6 +145,15 @@ copy_to_tmpdir(svn_skel_t **work_item,
           return SVN_NO_ERROR;
         }
     }
+  else if (*kind == svn_node_dir && !file_copy)
+    {
+      /* Just build a new direcory from the workqueue */
+      SVN_ERR(svn_wc__wq_build_dir_install(work_item,
+                                           db, dst_abspath,
+                                           result_pool, scratch_pool));
+
+      return SVN_NO_ERROR;
+    }
 
   /* Set DST_TMP_ABSPATH to a temporary unique path.  If *KIND is file, leave
      a file there and then overwrite it; otherwise leave no node on disk at
@@ -172,7 +209,14 @@ copy_to_tmpdir(svn_skel_t **work_item,
    versioned file itself.
 
    This also works for versioned symlinks that are stored in the db as
-   svn_node_file with svn:special set. */
+   svn_node_file with svn:special set.
+
+   If DIRENT is not NULL, it contains the on-disk information of SRC_ABSPATH.
+   RECORDED_SIZE (if not SVN_INVALID_FILESIZE) contains the recorded size of
+   SRC_ABSPATH, and RECORDED_TIME the recorded size or 0.
+
+   These values will be used to avoid unneeded work.
+*/
 static svn_error_t *
 copy_versioned_file(svn_wc__db_t *db,
                     const char *src_abspath,
@@ -182,6 +226,9 @@ copy_versioned_file(svn_wc__db_t *db,
                     svn_boolean_t metadata_only,
                     svn_boolean_t conflicted,
                     svn_boolean_t is_move,
+                    const svn_io_dirent2_t *dirent,
+                    svn_filesize_t recorded_size,
+                    apr_time_t recorded_time,
                     svn_cancel_func_t cancel_func,
                     void *cancel_baton,
                     svn_wc_notify_func2_t notify_func,
@@ -248,6 +295,7 @@ copy_versioned_file(svn_wc__db_t *db,
                              dst_abspath, tmpdir_abspath,
                              TRUE /* file_copy */,
                              handle_as_unversioned /* unversioned */,
+                             dirent, recorded_size, recorded_time,
                              cancel_func, cancel_baton,
                              scratch_pool, scratch_pool));
     }
@@ -265,10 +313,6 @@ copy_versioned_file(svn_wc__db_t *db,
                                scratch_pool);
       notify->kind = svn_node_file;
 
-      /* When we notify that we performed a copy, make sure we already did */
-      if (work_items != NULL)
-        SVN_ERR(svn_wc__wq_run(db, dst_abspath,
-                               cancel_func, cancel_baton, scratch_pool));
       (*notify_func)(notify_baton, notify, scratch_pool);
     }
   return SVN_NO_ERROR;
@@ -282,6 +326,8 @@ copy_versioned_file(svn_wc__db_t *db,
    data in addition to copying the directory.
 
    WITHIN_ONE_WC is TRUE if the copy/move is within a single working copy (root)
+
+   If DIRENT is not NULL, it contains the on-disk information of SRC_ABSPATH.
  */
 static svn_error_t *
 copy_versioned_dir(svn_wc__db_t *db,
@@ -291,6 +337,7 @@ copy_versioned_dir(svn_wc__db_t *db,
                    const char *tmpdir_abspath,
                    svn_boolean_t metadata_only,
                    svn_boolean_t is_move,
+                   const svn_io_dirent2_t *dirent,
                    svn_cancel_func_t cancel_func,
                    void *cancel_baton,
                    svn_wc_notify_func2_t notify_func,
@@ -314,6 +361,7 @@ copy_versioned_dir(svn_wc__db_t *db,
                              tmpdir_abspath,
                              FALSE /* file_copy */,
                              FALSE /* unversioned */,
+                             dirent, SVN_INVALID_FILESIZE, 0,
                              cancel_func, cancel_baton,
                              scratch_pool, scratch_pool));
     }
@@ -395,6 +443,12 @@ copy_versioned_dir(svn_wc__db_t *db,
                                             tmpdir_abspath,
                                             metadata_only, info->conflicted,
                                             is_move,
+                                            disk_children
+                                              ? svn_hash_gets(disk_children,
+                                                              child_name)
+                                              : NULL,
+                                            info->recorded_size,
+                                            info->recorded_time,
                                             cancel_func, cancel_baton,
                                             NULL, NULL,
                                             iterpool));
@@ -404,6 +458,10 @@ copy_versioned_dir(svn_wc__db_t *db,
                                        child_src_abspath, child_dst_abspath,
                                        dst_op_root_abspath, tmpdir_abspath,
                                        metadata_only, is_move,
+                                       disk_children
+                                              ? svn_hash_gets(disk_children,
+                                                              child_name)
+                                              : NULL,
                                        cancel_func, cancel_baton, NULL, NULL,
                                        iterpool));
           else
@@ -422,7 +480,7 @@ copy_versioned_dir(svn_wc__db_t *db,
                                      child_dst_abspath, dst_op_root_abspath,
                                      is_move, NULL, iterpool));
 
-          /* Don't recurse on children while all we do is creating not-present
+          /* Don't recurse on children when all we do is creating not-present
              children */
         }
       else if (info->status == svn_wc__db_status_incomplete)
@@ -489,6 +547,7 @@ copy_versioned_dir(svn_wc__db_t *db,
           SVN_ERR(copy_to_tmpdir(&work_item, NULL, db, unver_src_abspath,
                                  unver_dst_abspath, tmpdir_abspath,
                                  TRUE /* recursive */, TRUE /* unversioned */,
+                                 NULL, SVN_INVALID_FILESIZE, 0,
                                  cancel_func, cancel_baton,
                                  scratch_pool, iterpool));
 
@@ -534,6 +593,8 @@ copy_or_move(svn_boolean_t *move_degrade
   svn_boolean_t within_one_wc;
   svn_wc__db_status_t src_status;
   svn_error_t *err;
+  svn_filesize_t recorded_size;
+  apr_time_t recorded_time;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(src_abspath));
   SVN_ERR_ASSERT(svn_dirent_is_absolute(dst_abspath));
@@ -551,7 +612,8 @@ copy_or_move(svn_boolean_t *move_degrade
     err = svn_wc__db_read_info(&src_status, &src_db_kind, NULL,
                                &src_repos_relpath, &src_repos_root_url,
                                &src_repos_uuid, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL, NULL,
+                               &recorded_size, &recorded_time,
                                NULL, &conflicted, NULL, NULL, NULL, NULL,
                                NULL, NULL,
                                db, src_abspath, scratch_pool, scratch_pool);
@@ -775,6 +837,7 @@ copy_or_move(svn_boolean_t *move_degrade
       err = copy_versioned_file(db, src_abspath, dst_abspath, dst_abspath,
                                 tmpdir_abspath,
                                 metadata_only, conflicted, is_move,
+                                NULL, recorded_size, recorded_time,
                                 cancel_func, cancel_baton,
                                 notify_func, notify_baton,
                                 scratch_pool);
@@ -810,6 +873,7 @@ copy_or_move(svn_boolean_t *move_degrade
 
       err = copy_versioned_dir(db, src_abspath, dst_abspath, dst_abspath,
                                tmpdir_abspath, metadata_only, is_move,
+                               NULL /* dirent */,
                                cancel_func, cancel_baton,
                                notify_func, notify_baton,
                                scratch_pool);

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_wc/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_wc/deprecated.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_wc/deprecated.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_wc/deprecated.c Sun Oct 19 13:55:35 2014
@@ -652,6 +652,24 @@ svn_wc_get_pristine_contents(svn_stream_
   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
 }
 
+svn_error_t *
+svn_wc_queue_committed3(svn_wc_committed_queue_t *queue,
+                        svn_wc_context_t *wc_ctx,
+                        const char *local_abspath,
+                        svn_boolean_t recurse,
+                        const apr_array_header_t *wcprop_changes,
+                        svn_boolean_t remove_lock,
+                        svn_boolean_t remove_changelist,
+                        const svn_checksum_t *sha1_checksum,
+                        apr_pool_t *scratch_pool)
+{
+  return svn_error_trace(
+            svn_wc_queue_committed4(queue, wc_ctx, local_abspath,
+                                    recurse, TRUE /* is_committed */,
+                                    wcprop_changes, remove_lock,
+                                    remove_changelist, sha1_checksum,
+                                    scratch_pool));
+}
 
 svn_error_t *
 svn_wc_queue_committed2(svn_wc_committed_queue_t *queue,
@@ -668,7 +686,9 @@ svn_wc_queue_committed2(svn_wc_committed
   const char *local_abspath;
   const svn_checksum_t *sha1_checksum = NULL;
 
-  SVN_ERR(svn_wc_context_create(&wc_ctx, NULL, scratch_pool, scratch_pool));
+  SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL,
+                                         svn_wc__adm_get_db(adm_access),
+                                         scratch_pool));
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));
 
   if (md5_checksum != NULL)
@@ -759,15 +779,11 @@ svn_wc_process_committed4(const char *pa
   const char *local_abspath;
   const svn_checksum_t *md5_checksum;
   const svn_checksum_t *sha1_checksum = NULL;
-  apr_time_t new_date;
-  apr_hash_t *wcprop_changes_hash;
+  svn_wc_context_t *wc_ctx;
+  svn_wc_committed_queue_t *queue;
 
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
-
-  if (rev_date)
-    SVN_ERR(svn_time_from_cstring(&new_date, rev_date, pool));
-  else
-    new_date = 0;
+  SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL, db, pool));
 
   if (digest)
     md5_checksum = svn_checksum__from_digest_md5(digest, pool);
@@ -790,15 +806,20 @@ svn_wc_process_committed4(const char *pa
         SVN_ERR(err);
     }
 
-  wcprop_changes_hash = svn_wc__prop_array_to_hash(wcprop_changes, pool);
-  SVN_ERR(svn_wc__process_committed_internal(db, local_abspath, recurse, TRUE,
-                                             new_revnum, new_date, rev_author,
-                                             wcprop_changes_hash,
-                                             !remove_lock, !remove_changelist,
-                                             sha1_checksum, NULL, pool));
+  queue = svn_wc_committed_queue_create(pool);
+  SVN_ERR(svn_wc_queue_committed3(queue, wc_ctx, local_abspath, recurse,
+                                  wcprop_changes, remove_lock,
+                                  remove_changelist,
+                                  sha1_checksum /* or NULL if not modified
+                                                           or directory */,
+                                  pool));
 
-  /* Run the log file(s) we just created. */
-  return svn_error_trace(svn_wc__wq_run(db, local_abspath, NULL, NULL, pool));
+  SVN_ERR(svn_wc_process_committed_queue2(queue, wc_ctx,
+                                          new_revnum, rev_date, rev_author,
+                                          NULL, NULL /* cancel */,
+                                          pool));
+
+  return svn_error_trace(svn_wc_context_destroy(wc_ctx));
 }
 
 

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_wc/diff.h
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_wc/diff.h?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_wc/diff.h (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_wc/diff.h Sun Oct 19 13:55:35 2014
@@ -47,9 +47,6 @@ extern "C" {
    svn_wc__db_status_added. When DIFF_PRISTINE is TRUE, report the pristine
    version of LOCAL_ABSPATH as ADDED. In this case an
    svn_wc__db_status_deleted may shadow an added or deleted node.
-
-   If CHANGELIST_HASH is not NULL and LOCAL_ABSPATH's changelist is not
-   in the changelist, don't report the node.
  */
 svn_error_t *
 svn_wc__diff_local_only_file(svn_wc__db_t *db,
@@ -57,7 +54,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,
@@ -73,9 +69,6 @@ svn_wc__diff_local_only_file(svn_wc__db_
    svn_wc__db_status_added. When DIFF_PRISTINE is TRUE, report the pristine
    version of LOCAL_ABSPATH as ADDED. In this case an
    svn_wc__db_status_deleted may shadow an added or deleted node.
-
-   If CHANGELIST_HASH is not NULL and LOCAL_ABSPATH's changelist is not
-   in the changelist, don't report the node.
  */
 svn_error_t *
 svn_wc__diff_local_only_dir(svn_wc__db_t *db,
@@ -84,7 +77,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,
@@ -132,7 +124,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,
@@ -140,6 +131,32 @@ svn_wc__diff_base_working_diff(svn_wc__d
                                void *cancel_baton,
                                apr_pool_t *scratch_pool);
 
+/* Return a tree processor filter that filters by changelist membership.
+ *
+ * This filter only passes on the changes for a file if the file's path
+ * (in the WC) is assigned to one of the changelists in @a changelist_hash.
+ * It also passes on the opening and closing of each directory that contains
+ * such a change, and possibly also of other directories, but not addition
+ * or deletion or changes to a directory.
+ *
+ * If @a changelist_hash is null then no filtering is performed and the
+ * returned diff processor is driven exactly like the input @a processor.
+ *
+ * @a wc_ctx is the WC context and @a root_local_abspath is the WC path of
+ * the root of the diff (for which relpath = "" in the diff processor).
+ *
+ * Allocate the returned diff processor in @a result_pool, or if no
+ * filtering is required then the input pointer @a processor itself may be
+ * returned.
+ */
+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);
+
 
 #ifdef __cplusplus
 }

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_wc/diff_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_wc/diff_editor.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_wc/diff_editor.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_wc/diff_editor.c Sun Oct 19 13:55:35 2014
@@ -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/revprop-caching-ng/subversion/libsvn_wc/diff_local.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_wc/diff_local.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_wc/diff_local.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_wc/diff_local.c Sun Oct 19 13:55:35 2014
@@ -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