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