On Thu, May 10, 2012 at 2:13 PM, <rhuij...@apache.org> wrote: > Author: rhuijben > Date: Thu May 10 19:13:11 2012 > New Revision: 1336833 > > URL: http://svn.apache.org/viewvc?rev=1336833&view=rev > Log: > Make the text and property merge handling of 'svn merge' of a single file an > atomic operation by moving the handling into a single libsvn_wc call that > installs or doesn't install the working queue items. > > * subversion/include/svn_wc.h > (svn_wc_merge5): New function. > (svn_wc_merge4): Deprecate function. > > * subversion/libsvn_client/merge.c > (merge_file_changed): Update caller. > > * subversion/libsvn_wc/deprecated.c > (svn_wc_merge4): New function. Wraps svn_wc_merge5(). > > * subversion/libsvn_wc/merge.c > (svn_wc_merge4): Rename to ... > (svn_wc_merge5): ... this and add support for merging properties in the same > operation. At the same time avoid a few more unneeded db operations. > ... > Modified: subversion/trunk/subversion/libsvn_wc/merge.c > URL: > http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/merge.c?rev=1336833&r1=1336832&r2=1336833&view=diff > ============================================================================== > --- subversion/trunk/subversion/libsvn_wc/merge.c (original) > +++ subversion/trunk/subversion/libsvn_wc/merge.c Thu May 10 19:13:11 2012 ... > @@ -1476,7 +1476,8 @@ svn_wc__internal_merge(svn_skel_t **work > > > svn_error_t * > -svn_wc_merge4(enum svn_wc_merge_outcome_t *merge_outcome, > +svn_wc_merge5(enum svn_wc_merge_outcome_t *merge_content_outcome, > + enum svn_wc_notify_state_t *merge_props_outcome, > svn_wc_context_t *wc_ctx, > const char *left_abspath, > const char *right_abspath, > @@ -1489,6 +1490,7 @@ svn_wc_merge4(enum svn_wc_merge_outcome_ > svn_boolean_t dry_run, > const char *diff3_cmd, > const apr_array_header_t *merge_options, > + apr_hash_t *original_props, > const apr_array_header_t *prop_diff, > svn_wc_conflict_resolver_func2_t conflict_func, > void *conflict_baton, > @@ -1497,8 +1499,11 @@ svn_wc_merge4(enum svn_wc_merge_outcome_ > apr_pool_t *scratch_pool) > { > const char *dir_abspath = svn_dirent_dirname(target_abspath, scratch_pool); > + svn_skel_t *prop_items = NULL; > svn_skel_t *work_items; > - apr_hash_t *actual_props; > + apr_hash_t *pristine_props = NULL; > + apr_hash_t *actual_props = NULL; > + apr_hash_t *new_actual_props = NULL; > > SVN_ERR_ASSERT(svn_dirent_is_absolute(left_abspath)); > SVN_ERR_ASSERT(svn_dirent_is_absolute(right_abspath)); > @@ -1508,37 +1513,86 @@ svn_wc_merge4(enum svn_wc_merge_outcome_ > if (!dry_run) > SVN_ERR(svn_wc__write_check(wc_ctx->db, dir_abspath, scratch_pool)); > > - /* Sanity check: the merge target must be under revision control, > - * unless the merge target is a copyfrom text, which lives in a > - * temporary file and does not exist in ACTUAL yet. */ > + /* Sanity check: the merge target must be a file under revision control */ > { > + svn_wc__db_status_t status; > svn_kind_t kind; > - svn_boolean_t hidden; > - SVN_ERR(svn_wc__db_read_kind(&kind, wc_ctx->db, target_abspath, TRUE, > - scratch_pool)); > + svn_boolean_t had_props; > + svn_boolean_t props_mod; > > - if (kind == svn_kind_unknown) > + SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, > NULL, > + NULL, NULL, NULL, NULL, NULL, NULL, NULL, > + NULL, NULL, NULL, NULL, NULL, NULL, NULL, > + NULL, &had_props, &props_mod, NULL, NULL, > + NULL, > + wc_ctx->db, target_abspath, > + scratch_pool, scratch_pool)); > + > + if (kind != svn_kind_file || (status != svn_wc__db_status_normal > + && status != svn_wc__db_status_added)) > { > - *merge_outcome = svn_wc_merge_no_merge; > + *merge_content_outcome = svn_wc_merge_no_merge; > + if (merge_props_outcome) > + *merge_props_outcome = svn_wc_merge_no_merge;
There is a type mismatch here: *merge_props_outcome is an enum of type svn_wc_notify_state_t, but svn_wc_merge_no_merge is one of svn_wc_merge_outcome_t. -Hyrum > return SVN_NO_ERROR; > } > > - SVN_ERR(svn_wc__db_node_hidden(&hidden, wc_ctx->db, target_abspath, > - scratch_pool)); > + if (merge_props_outcome && had_props) > + { > + SVN_ERR(svn_wc__db_read_pristine_props(&pristine_props, > + wc_ctx->db, target_abspath, > + scratch_pool, scratch_pool)); > + } > + else if (merge_props_outcome) > + pristine_props = apr_hash_make(scratch_pool); > > - if (hidden) > + if (props_mod) > { > - *merge_outcome = svn_wc_merge_no_merge; > - return SVN_NO_ERROR; > + SVN_ERR(svn_wc__db_read_props(&actual_props, > + wc_ctx->db, target_abspath, > + scratch_pool, scratch_pool)); > } > + else if (pristine_props) > + actual_props = apr_hash_copy(scratch_pool, pristine_props); > + else > + actual_props = apr_hash_make(scratch_pool); > } > > - SVN_ERR(svn_wc__db_read_props(&actual_props, wc_ctx->db, target_abspath, > - scratch_pool, scratch_pool)); > + if (merge_props_outcome) > + { > + int i; > + apr_hash_t *new_pristine_props; > + /* The PROPCHANGES may not have non-"normal" properties in it. If entry > + or wc props were allowed, then the following code would install them > + into the BASE and/or WORKING properties(!). */ > + for (i = prop_diff->nelts; i--; ) > + { > + const svn_prop_t *change = &APR_ARRAY_IDX(prop_diff, i, > svn_prop_t); > + > + if (!svn_wc_is_normal_prop(change->name)) > + return svn_error_createf(SVN_ERR_BAD_PROP_KIND, NULL, > + _("The property '%s' may not be merged " > + "into '%s'."), > + change->name, > + svn_dirent_local_style(target_abspath, > + scratch_pool)); > + } > + > + SVN_ERR(svn_wc__merge_props(&prop_items, merge_props_outcome, > + &new_pristine_props, &new_actual_props, > + wc_ctx->db, target_abspath, svn_kind_file, > + left_version, right_version, > + original_props, pristine_props, > actual_props, > + prop_diff, FALSE /* base_merge */, > + dry_run, > + conflict_func, conflict_baton, > + cancel_func, cancel_baton, > + scratch_pool, scratch_pool)); > + } > > /* Queue all the work. */ > SVN_ERR(svn_wc__internal_merge(&work_items, > - merge_outcome, > + merge_content_outcome, > wc_ctx->db, > left_abspath, left_version, > right_abspath, right_version, > @@ -1554,16 +1608,24 @@ svn_wc_merge4(enum svn_wc_merge_outcome_ > cancel_func, cancel_baton, > scratch_pool, scratch_pool)); > > + work_items = svn_wc__wq_merge(prop_items, work_items, scratch_pool); > + > /* If this isn't a dry run, then run the work! */ > if (!dry_run) > { > - SVN_ERR(svn_wc__db_wq_add(wc_ctx->db, target_abspath, work_items, > - scratch_pool)); > + if (new_actual_props) > + SVN_ERR(svn_wc__db_op_set_props(wc_ctx->db, target_abspath, > + new_actual_props, > + > svn_wc__has_magic_property(prop_diff), > + NULL, work_items, scratch_pool)); > + else > + SVN_ERR(svn_wc__db_wq_add(wc_ctx->db, target_abspath, work_items, > + scratch_pool)); > SVN_ERR(svn_wc__wq_run(wc_ctx->db, target_abspath, > cancel_func, cancel_baton, > scratch_pool)); > } > - > + > return SVN_NO_ERROR; > } > > > -- uberSVN: Apache Subversion Made Easy http://www.uberSVN.com/