On Tue, Apr 05, 2011 at 02:18:01PM -0000, rhuij...@apache.org wrote: > Author: rhuijben > Date: Tue Apr 5 14:18:00 2011 > New Revision: 1089058 > > URL: http://svn.apache.org/viewvc?rev=1089058&view=rev > Log: > Start recording mixed-revision copies as multiple op_depths. Do this by > adding not-present nodes at the op-depth of the parent operation. Before this > patch we created multiple copy operations at the same op depth when you > were using a simple 'svn cp DIR DIR2', while using separate operations > could give you multiple layers with the same result on commit. > > This change doesn't introduce new database states that couldn't exist before, > but it does bring the working copy closer to the model used for committing > (and the formal tree model we used for designing WC-NG). > > This change also slightly changes the behavior of delete and revert on > children of a copy operation as it allows you to revert the separate commands > that will be performed on commit. > > On top of that this commit will finally allow the commit processing to use > depth handling.
Here is my patch that introduces depth to post-commit processing. Last I tried, tests failed with it. I don't have time to look at it today but in case it helps I thought I'd share it. Index: subversion/include/svn_wc.h =================================================================== --- subversion/include/svn_wc.h (revision 1086444) +++ subversion/include/svn_wc.h (working copy) @@ -4753,9 +4753,11 @@ svn_wc_committed_queue_create(apr_pool_t *pool); * identify the node's pristine text. * ### NOT YET IMPLEMENTED. * - * If @a recurse is TRUE and @a local_abspath is a directory, then bump every - * versioned object at or under @a local_abspath. This is usually done for - * copied trees. + * If @a local_abspath is a directory, then bump every versioned object + * within the specified @a depth at or under @a local_abspath. + * This is usually done for copied trees. + * @a depth must be greater or equal @c svn_depth_empty. + * It must NOT be @c svn_depth_unknown or @c svn_depth_exclude. * * ### In the present implementation, if a recursive directory item is in * the queue, then any children (at any depth) of that directory that @@ -4771,7 +4773,7 @@ svn_wc_committed_queue_create(apr_pool_t *pool); * 'remove_changelist' from the recursive parent item; * 'md5_checksum' = NULL ### means what? * - * @note the @a recurse parameter should be used with extreme care since + * @note the @a depth infinity should be used with extreme care since * it will bump ALL nodes under the directory, regardless of their * actual inclusion in the new revision. * @@ -4788,7 +4790,7 @@ 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, + svn_depth_t depth, const apr_array_header_t *wcprop_changes, svn_boolean_t remove_lock, svn_boolean_t remove_changelist, @@ -4797,8 +4799,8 @@ svn_wc_queue_committed3(svn_wc_committed_queue_t * apr_pool_t *scratch_pool); /** Same as svn_wc_queue_committed3() except @a path doesn't have to be an - * abspath and @a adm_access is unused and a SHA-1 checksum cannot be - * specified. + * abspath, and @a adm_access is unused, and a SHA-1 checksum cannot be + * specified, and there is a boolean parameter @a recurse instead of depth. * * @since New in 1.6. * Index: subversion/include/svn_client.h =================================================================== --- subversion/include/svn_client.h (revision 1086444) +++ subversion/include/svn_client.h (working copy) @@ -473,6 +473,11 @@ typedef struct svn_client_commit_item3_t * same lifetime as this data structure. */ apr_array_header_t *outgoing_prop_changes; + + /** The depth this item was committed with. This is needed to retain + * local mods (such as deleted children) within copied directories that + * are committed with depth less than infinity. */ + svn_depth_t depth; } svn_client_commit_item3_t; /** The commit candidate structure. Index: subversion/libsvn_wc/deprecated.c =================================================================== --- subversion/libsvn_wc/deprecated.c (revision 1086444) +++ subversion/libsvn_wc/deprecated.c (working copy) @@ -664,7 +664,8 @@ svn_wc_process_committed4(const char *path, SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool)); wcprop_changes_hash = svn_wc__prop_array_to_hash(wcprop_changes, pool); - SVN_ERR(svn_wc__process_committed_internal(db, local_abspath, recurse, TRUE, + SVN_ERR(svn_wc__process_committed_internal(db, local_abspath, + svn_depth_infinity, TRUE, new_revnum, new_date, rev_author, wcprop_changes_hash, !remove_lock, !remove_changelist, Index: subversion/libsvn_wc/wc.h =================================================================== --- subversion/libsvn_wc/wc.h (revision 1086444) +++ subversion/libsvn_wc/wc.h (working copy) @@ -270,7 +270,7 @@ svn_wc__get_committed_queue_pool(const struct svn_ svn_error_t * svn_wc__process_committed_internal(svn_wc__db_t *db, const char *local_abspath, - svn_boolean_t recurse, + svn_depth_t depth, svn_boolean_t top_of_recurse, svn_revnum_t new_revnum, apr_time_t new_date, Index: subversion/libsvn_wc/adm_ops.c =================================================================== --- subversion/libsvn_wc/adm_ops.c (revision 1086444) +++ subversion/libsvn_wc/adm_ops.c (working copy) @@ -70,14 +70,14 @@ struct svn_wc_committed_queue_t 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; + /* Is any item in the queue committed with depth > 'empty'? */ + svn_boolean_t have_depth_greater_empty; }; typedef struct committed_queue_item_t { const char *local_abspath; - svn_boolean_t recurse; + svn_depth_t depth; svn_boolean_t no_unlock; svn_boolean_t keep_changelist; @@ -225,7 +225,7 @@ process_committed_leaf(svn_wc__db_t *db, svn_error_t * svn_wc__process_committed_internal(svn_wc__db_t *db, const char *local_abspath, - svn_boolean_t recurse, + svn_depth_t depth, svn_boolean_t top_of_recurse, svn_revnum_t new_revnum, apr_time_t new_date, @@ -239,9 +239,25 @@ svn_wc__process_committed_internal(svn_wc__db_t *d apr_pool_t *scratch_pool) { svn_wc__db_kind_t kind; + svn_depth_t depth_below_here; SVN_ERR(svn_wc__db_read_kind(&kind, db, local_abspath, TRUE, scratch_pool)); + switch (depth) + { + case svn_depth_empty: + case svn_depth_files: + case svn_depth_immediates: + depth_below_here = svn_depth_empty; + break; + case svn_depth_infinity: + depth_below_here = svn_depth_infinity; + break; + default: + SVN_ERR_MALFUNCTION(); + } + + SVN_ERR(process_committed_leaf(db, local_abspath, !top_of_recurse, new_revnum, new_date, rev_author, new_dav_cache, @@ -249,7 +265,7 @@ svn_wc__process_committed_internal(svn_wc__db_t *d sha1_checksum, scratch_pool)); - if (recurse && kind == svn_wc__db_kind_dir) + if (depth > svn_depth_empty && kind == svn_wc__db_kind_dir) { const apr_array_header_t *children; apr_pool_t *iterpool = svn_pool_create(scratch_pool); @@ -331,7 +347,7 @@ svn_wc__process_committed_internal(svn_wc__db_t *d 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 */, + depth_below_here, FALSE, new_revnum, new_date, rev_author, @@ -384,7 +400,7 @@ svn_wc_committed_queue_create(apr_pool_t *pool) q = apr_palloc(pool, sizeof(*q)); q->pool = pool; q->queue = apr_hash_make(pool); - q->have_recursive = FALSE; + q->have_depth_greater_empty = FALSE; return q; } @@ -393,7 +409,7 @@ 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, + svn_depth_t depth, const apr_array_header_t *wcprop_changes, svn_boolean_t remove_lock, svn_boolean_t remove_changelist, @@ -405,7 +421,7 @@ svn_wc_queue_committed3(svn_wc_committed_queue_t * SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath)); - queue->have_recursive |= recurse; + queue->have_depth_greater_empty |= (depth > svn_depth_empty); /* Use the same pool as the one QUEUE was allocated in, to prevent lifetime issues. Intermediate operations @@ -414,7 +430,7 @@ svn_wc_queue_committed3(svn_wc_committed_queue_t * /* Add to the array with paths and options */ cqi = apr_palloc(queue->pool, sizeof(*cqi)); cqi->local_abspath = local_abspath; - cqi->recurse = recurse; + cqi->depth = depth; cqi->no_unlock = !remove_lock; cqi->keep_changelist = !remove_changelist; cqi->md5_checksum = md5_checksum; @@ -443,13 +459,31 @@ have_recursive_parent(apr_hash_t *queue, for (hi = apr_hash_first(scratch_pool, queue); hi; hi = apr_hash_next(hi)) { const committed_queue_item_t *qi = svn__apr_hash_index_val(hi); + const char *child_remainder; if (qi == item) continue; - if (qi->recurse && svn_dirent_is_child(qi->local_abspath, local_abspath, - NULL)) - return TRUE; + child_remainder = svn_dirent_is_child(qi->local_abspath, + local_abspath, NULL); + if (child_remainder == NULL) + continue; + + /* Check if the item is within reach of the parent's commit depth. */ + switch (qi->depth) + { + case svn_depth_empty: + continue; + case svn_depth_files: + case svn_depth_immediates: + if (svn_path_component_count(child_remainder) == 1) + return TRUE; + continue; + case svn_depth_infinity: + return TRUE; + default: + SVN_ERR_MALFUNCTION_NO_RETURN(); + } } return FALSE; @@ -488,12 +522,12 @@ svn_wc_process_committed_queue2(svn_wc_committed_q /* 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)) + if (queue->have_depth_greater_empty && + have_recursive_parent(queue->queue, cqi, iterpool)) continue; SVN_ERR(svn_wc__process_committed_internal(wc_ctx->db, cqi->local_abspath, - cqi->recurse, TRUE, new_revnum, + cqi->depth, TRUE, new_revnum, new_date, rev_author, cqi->new_dav_cache, cqi->no_unlock, Index: subversion/libsvn_client/commit_util.c =================================================================== --- subversion/libsvn_client/commit_util.c (revision 1086444) +++ subversion/libsvn_client/commit_util.c (working copy) @@ -84,6 +84,7 @@ add_committable(apr_hash_t *committables, const char *copyfrom_relpath, svn_revnum_t copyfrom_rev, apr_byte_t state_flags, + svn_depth_t depth, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { @@ -126,6 +127,7 @@ add_committable(apr_hash_t *committables, new_item->state_flags = state_flags; new_item->incoming_prop_changes = apr_array_make(result_pool, 1, sizeof(svn_prop_t *)); + new_item->depth = depth; /* Now, add the commit item to the array. */ APR_ARRAY_PUSH(array, svn_client_commit_item3_t *) = new_item; @@ -717,6 +719,7 @@ harvest_committables(apr_hash_t *committables, cf_relpath, cf_rev, state_flags, + depth, result_pool, scratch_pool)); if (state_flags & SVN_CLIENT_COMMIT_ITEM_LOCK_TOKEN) apr_hash_set(lock_tokens, Index: subversion/libsvn_client/commit.c =================================================================== --- subversion/libsvn_client/commit.c (revision 1086444) +++ subversion/libsvn_client/commit.c (working copy) @@ -925,19 +925,13 @@ post_process_commit_item(svn_wc_committed_queue_t const svn_checksum_t *sha1_checksum, apr_pool_t *scratch_pool) { - svn_boolean_t loop_recurse = FALSE; svn_boolean_t remove_lock; - if ((item->state_flags & SVN_CLIENT_COMMIT_ITEM_ADD) - && (item->kind == svn_node_dir) - && (item->copyfrom_url)) - loop_recurse = TRUE; - remove_lock = (! keep_locks && (item->state_flags & SVN_CLIENT_COMMIT_ITEM_LOCK_TOKEN)); return svn_wc_queue_committed3(queue, wc_ctx, item->path, - loop_recurse, item->incoming_prop_changes, + item->depth, item->incoming_prop_changes, remove_lock, !keep_changelists, md5_checksum, sha1_checksum, scratch_pool); }