Return-Path: X-Original-To: apmail-subversion-commits-archive@minotaur.apache.org Delivered-To: apmail-subversion-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id A43C0ED18 for ; Wed, 30 Jan 2013 18:20:01 +0000 (UTC) Received: (qmail 28234 invoked by uid 500); 30 Jan 2013 18:20:01 -0000 Delivered-To: apmail-subversion-commits-archive@subversion.apache.org Received: (qmail 28206 invoked by uid 500); 30 Jan 2013 18:20:01 -0000 Mailing-List: contact commits-help@subversion.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@subversion.apache.org Delivered-To: mailing list commits@subversion.apache.org Received: (qmail 28199 invoked by uid 99); 30 Jan 2013 18:20:01 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 30 Jan 2013 18:20:01 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 30 Jan 2013 18:19:57 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 680D02388847; Wed, 30 Jan 2013 18:19:37 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1440575 - /subversion/trunk/subversion/libsvn_client/merge.c Date: Wed, 30 Jan 2013 18:19:37 -0000 To: commits@subversion.apache.org From: rhuijben@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20130130181937.680D02388847@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: rhuijben Date: Wed Jan 30 18:19:36 2013 New Revision: 1440575 URL: http://svn.apache.org/viewvc?rev=1440575&view=rev Log: Refactor merge_dir_props_changed() and merge_dir_added() to become propert diff tree processor functions. This temporarily duplicates some code that was used for quite different purposes. * subversion/libsvn_client/merge.c (merge_dir_props_changed): Rename this function to ... (merge_dir_changed): ... this. Extract the new directory code into ... (merge_dir_added): ... this function. (ignore_dir_props_changed, ignore_dir_added): New stubs. (merge_callbacks): Install stubs. (do_merge): Hook property change functions. Modified: subversion/trunk/subversion/libsvn_client/merge.c Modified: subversion/trunk/subversion/libsvn_client/merge.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/merge.c?rev=1440575&r1=1440574&r2=1440575&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_client/merge.c (original) +++ subversion/trunk/subversion/libsvn_client/merge.c Wed Jan 30 18:19:36 2013 @@ -2594,21 +2594,29 @@ merge_dir_opened(void **new_dir_baton, return SVN_NO_ERROR; } -/* An svn_wc_diff_callbacks4_t function. */ +/* An svn_diff_tree_processor_t function. + * + * Called after merge_dir_opened() when a node exists in both the left and + * right source, but has its properties changed inbetween. + * + * After the merge_dir_opened() but before the call to this merge_dir_changed() + * function all descendants will have been updated. + */ static svn_error_t * -merge_dir_props_changed(svn_wc_notify_state_t *state, - svn_boolean_t *tree_conflicted, - const char *local_relpath, - svn_boolean_t dir_was_added, - const apr_array_header_t *propchanges, - apr_hash_t *original_props, - void *diff_baton, - apr_pool_t *scratch_pool) +merge_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) { - merge_cmd_baton_t *merge_b = diff_baton; + merge_cmd_baton_t *merge_b = processor->baton; const apr_array_header_t *props; const char *local_abspath = svn_dirent_join(merge_b->target->abspath, - local_relpath, scratch_pool); + relpath, scratch_pool); svn_wc_notify_state_t obstr_state; svn_boolean_t is_deleted; svn_node_kind_t kind; @@ -2653,14 +2661,121 @@ merge_dir_props_changed(svn_wc_notify_st return SVN_NO_ERROR; } - if (dir_was_added - && merge_b->dry_run + SVN_ERR(prepare_merge_props_changed(&props, local_abspath, prop_changes, + merge_b, scratch_pool, scratch_pool)); + + if (props->nelts) + { + const svn_wc_conflict_version_t *left; + const svn_wc_conflict_version_t *right; + svn_client_ctx_t *ctx = merge_b->ctx; + svn_wc_notify_state_t prop_state; + + SVN_ERR(make_conflict_versions(&left, &right, local_abspath, + svn_node_dir, &merge_b->merge_source, + merge_b->target, merge_b->pool)); + + SVN_ERR(svn_wc_merge_props3(&prop_state, ctx->wc_ctx, local_abspath, + left, right, + left_props, props, + merge_b->dry_run, + ctx->conflict_func2, ctx->conflict_baton2, + ctx->cancel_func, ctx->cancel_baton, + scratch_pool)); + + if (prop_state == svn_wc_notify_state_conflicted) + { + alloc_and_store_path(&merge_b->conflicted_paths, local_abspath, + merge_b->pool); + } + + if (prop_state == svn_wc_notify_state_conflicted + || prop_state == svn_wc_notify_state_merged + || prop_state == svn_wc_notify_state_changed) + { + SVN_ERR(record_update_update(merge_b, local_abspath, svn_node_file, + svn_wc_notify_state_inapplicable, + prop_state, scratch_pool)); + } + } + + return SVN_NO_ERROR; +} + + +/* An svn_diff_tree_processor_t function. + * + * Called after merge_dir_opened() when a node doesn't exist in LEFT_SOURCE, + * but does in RIGHT_SOURCE. After the merge_dir_opened() but before the call + * to this merge_dir_added() function all descendants will have been added. + * + * When a node is replaced instead of just added a separate opened+deleted will + * be invoked before the current open+added. + */ +static svn_error_t * +merge_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 struct svn_diff_tree_processor_t *processor, + apr_pool_t *scratch_pool) +{ + merge_cmd_baton_t *merge_b = processor->baton; + const char *local_abspath = svn_dirent_join(merge_b->target->abspath, + relpath, scratch_pool); + svn_wc_notify_state_t obstr_state; + svn_boolean_t is_deleted; + svn_node_kind_t kind; + + SVN_ERR(perform_obstruction_check(&obstr_state, &is_deleted, &kind, + merge_b, local_abspath, svn_node_dir, + scratch_pool)); + + if (obstr_state != svn_wc_notify_state_inapplicable) + { + SVN_ERR(record_skip(merge_b, local_abspath, svn_node_dir, + obstr_state, scratch_pool)); + return SVN_NO_ERROR; + } + + if (kind != svn_node_dir || is_deleted) + { + svn_wc_conflict_reason_t reason; + const char *moved_away_op_root_abspath = NULL; + + if (is_deleted) + { + SVN_ERR(check_moved_away(&moved_away_op_root_abspath, + merge_b->ctx->wc_ctx, + local_abspath, scratch_pool)); + + if (moved_away_op_root_abspath) + reason = svn_wc_conflict_reason_moved_away; + else + reason = svn_wc_conflict_reason_deleted; + } + else + reason = svn_wc_conflict_reason_missing; + + SVN_ERR(tree_conflict(merge_b, local_abspath, svn_node_file, + svn_wc_conflict_action_edit, reason, + moved_away_op_root_abspath)); + + SVN_ERR(record_tree_conflict(merge_b, local_abspath, svn_node_dir, + scratch_pool)); + + return SVN_NO_ERROR; + } + + if (merge_b->dry_run && dry_run_added_p(merge_b, local_abspath)) { return SVN_NO_ERROR; /* We can't do a real prop merge for added dirs */ } - if (dir_was_added && merge_b->same_repos) + if (merge_b->same_repos) { /* When the directory was added in merge_dir_added() we didn't update its pristine properties. Instead we receive the property changes later and @@ -2681,8 +2796,7 @@ merge_dir_props_changed(svn_wc_notify_st const char *child; /* Creating a hash containing regular and entry props */ - apr_hash_t *new_pristine_props = svn_prop__patch(original_props, propchanges, - scratch_pool); + apr_hash_t *new_pristine_props = right_props; parent_abspath = svn_dirent_dirname(local_abspath, scratch_pool); child = svn_dirent_is_child(merge_b->target->abspath, local_abspath, NULL); @@ -2726,66 +2840,38 @@ merge_dir_props_changed(svn_wc_notify_st return SVN_NO_ERROR; } - - SVN_ERR(prepare_merge_props_changed(&props, local_abspath, propchanges, - merge_b, scratch_pool, scratch_pool)); - - if (props->nelts) + else { - const svn_wc_conflict_version_t *left; - const svn_wc_conflict_version_t *right; - svn_client_ctx_t *ctx = merge_b->ctx; + apr_array_header_t *regular_props; + apr_hash_t *new_props; svn_wc_notify_state_t prop_state; - SVN_ERR(make_conflict_versions(&left, &right, local_abspath, - svn_node_dir, &merge_b->merge_source, - merge_b->target, merge_b->pool)); + SVN_ERR(svn_categorize_props(svn_prop_hash_to_array(right_props, + scratch_pool), + NULL, NULL, ®ular_props, scratch_pool)); - SVN_ERR(svn_wc_merge_props3(&prop_state, ctx->wc_ctx, local_abspath, - left, right, - original_props, props, - merge_b->dry_run, - ctx->conflict_func2, ctx->conflict_baton2, - ctx->cancel_func, ctx->cancel_baton, - scratch_pool)); + new_props = svn_prop_array_to_hash(regular_props, scratch_pool); - if (prop_state == svn_wc_notify_state_conflicted) - { - alloc_and_store_path(&merge_b->conflicted_paths, local_abspath, - merge_b->pool); - } + apr_hash_set(new_props, SVN_PROP_MERGEINFO, APR_HASH_KEY_STRING, NULL); - if (prop_state == svn_wc_notify_state_conflicted - || prop_state == svn_wc_notify_state_merged - || prop_state == svn_wc_notify_state_changed) - { - SVN_ERR(record_update_update(merge_b, local_abspath, svn_node_file, - svn_wc_notify_state_inapplicable, - prop_state, scratch_pool)); - } - } - - return SVN_NO_ERROR; -} + /* ### What is the easiest way to set new_props on LOCAL_ABSPATH? + ### This doesn't need a merge as we just added the node + ### (or installed a tree conflict and skipped this node)*/ -/* An svn_wc_diff_callbacks4_t function. */ -static svn_error_t * -merge_dir_added(svn_wc_notify_state_t *state, - svn_boolean_t *tree_conflicted, - svn_boolean_t *skip, - svn_boolean_t *skip_children, - const char *local_relpath, - svn_revnum_t rev, - const char *copyfrom_path, - svn_revnum_t copyfrom_revision, - void *baton, - apr_pool_t *scratch_pool) -{ - merge_cmd_baton_t *merge_b = baton; - /*const char *local_abspath = svn_dirent_join(merge_b->target->abspath, - local_relpath, scratch_pool);*/ - + SVN_ERR(svn_wc_merge_props3(&prop_state, merge_b->ctx->wc_ctx, + local_abspath, + NULL, NULL, + apr_hash_make(scratch_pool), + svn_prop_hash_to_array(new_props, + scratch_pool), + merge_b->dry_run, + merge_b->ctx->conflict_func2, + merge_b->ctx->conflict_baton2, + merge_b->ctx->cancel_func, + merge_b->ctx->cancel_baton, + scratch_pool)); + } return SVN_NO_ERROR; } @@ -3061,6 +3147,35 @@ ignore_dir_opened(svn_boolean_t *tree_co return SVN_NO_ERROR; } +static svn_error_t * +ignore_dir_props_changed(svn_wc_notify_state_t *state, + svn_boolean_t *tree_conflicted, + const char *local_relpath, + svn_boolean_t dir_was_added, + const apr_array_header_t *propchanges, + apr_hash_t *original_props, + void *diff_baton, + apr_pool_t *scratch_pool) +{ + return SVN_NO_ERROR; +} + +static svn_error_t * +ignore_dir_added(svn_wc_notify_state_t *state, + svn_boolean_t *tree_conflicted, + svn_boolean_t *skip, + svn_boolean_t *skip_children, + const char *local_relpath, + svn_revnum_t rev, + const char *copyfrom_path, + svn_revnum_t copyfrom_revision, + void *baton, + apr_pool_t *scratch_pool) +{ + return SVN_NO_ERROR; +} + + /* The main callback table for 'svn merge'. */ static const svn_wc_diff_callbacks4_t merge_callbacks = @@ -3071,8 +3186,8 @@ merge_callbacks = ignore_file_deleted, merge_dir_deleted, ignore_dir_opened, - merge_dir_added, - merge_dir_props_changed, + ignore_dir_added, + ignore_dir_props_changed, merge_dir_closed }; @@ -9262,6 +9377,8 @@ do_merge(apr_hash_t **modified_subtrees, scratch_pool); merge_processor->dir_opened = merge_dir_opened; + merge_processor->dir_changed = merge_dir_changed; + merge_processor->dir_added = merge_dir_added; merge_processor->file_opened = merge_file_opened; merge_processor->file_changed = merge_file_changed;