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 BABFED727 for ; Fri, 13 Jul 2012 19:05:27 +0000 (UTC) Received: (qmail 40436 invoked by uid 500); 13 Jul 2012 19:05:27 -0000 Delivered-To: apmail-subversion-commits-archive@subversion.apache.org Received: (qmail 40402 invoked by uid 500); 13 Jul 2012 19:05:27 -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 40395 invoked by uid 99); 13 Jul 2012 19:05:27 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 13 Jul 2012 19:05:27 +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; Fri, 13 Jul 2012 19:05:25 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 7195B2388AC8; Fri, 13 Jul 2012 19:04:43 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1361339 [7/14] - in /subversion/branches/master-passphrase: ./ build/generator/templates/ notes/directory-index/ notes/wc-ng/ subversion/bindings/javahl/native/ subversion/bindings/javahl/tests/org/apache/subversion/javahl/ subversion/bind... Date: Fri, 13 Jul 2012 19:04:36 -0000 To: commits@subversion.apache.org From: cmpilato@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20120713190443.7195B2388AC8@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Modified: subversion/branches/master-passphrase/subversion/libsvn_wc/props.c URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_wc/props.c?rev=1361339&r1=1361338&r2=1361339&view=diff ============================================================================== --- subversion/branches/master-passphrase/subversion/libsvn_wc/props.c (original) +++ subversion/branches/master-passphrase/subversion/libsvn_wc/props.c Fri Jul 13 19:04:32 2012 @@ -87,39 +87,6 @@ append_prop_conflict(svn_stream_t *strea return svn_stream_puts(stream, native_text); } - -/* Get the property reject file for LOCAL_ABSPATH in DB. Set - *PREJFILE_ABSPATH to the name of that file, or to NULL if no such - file is named. The file may, or may not, exist on disk. */ -svn_error_t * -svn_wc__get_prejfile_abspath(const char **prejfile_abspath, - svn_wc__db_t *db, - const char *local_abspath, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) -{ - const apr_array_header_t *conflicts; - int i; - - SVN_ERR(svn_wc__db_read_conflicts(&conflicts, db, local_abspath, - scratch_pool, scratch_pool)); - - for (i = 0; i < conflicts->nelts; i++) - { - const svn_wc_conflict_description2_t *cd; - cd = APR_ARRAY_IDX(conflicts, i, const svn_wc_conflict_description2_t *); - - if (cd->kind == svn_wc_conflict_kind_property) - { - *prejfile_abspath = apr_pstrdup(result_pool, cd->their_abspath); - return SVN_NO_ERROR; - } - } - - *prejfile_abspath = NULL; - return SVN_NO_ERROR; -} - /*---------------------------------------------------------------------*/ /*** Merging propchanges into the working copy ***/ @@ -237,14 +204,16 @@ svn_wc__perform_props_merge(svn_wc_notif apr_hash_t *new_actual_props; svn_boolean_t had_props, props_mod; svn_boolean_t have_base; - svn_skel_t *work_items; + svn_boolean_t conflicted; + svn_skel_t *work_items = NULL; + svn_skel_t *conflict_skel = NULL; /* IMPORTANT: svn_wc_merge_prop_diffs relies on the fact that baseprops may be NULL. */ 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, + NULL, NULL, NULL, NULL, NULL, &conflicted, NULL, &had_props, &props_mod, &have_base, NULL, NULL, db, local_abspath, scratch_pool, scratch_pool)); @@ -268,6 +237,30 @@ svn_wc__perform_props_merge(svn_wc_notif _("The node '%s' does not have properties in this state."), svn_dirent_local_style(local_abspath, scratch_pool)); } + else if (conflicted) + { + svn_boolean_t text_conflicted; + svn_boolean_t prop_conflicted; + svn_boolean_t tree_conflicted; + + SVN_ERR(svn_wc__internal_conflicted_p(&text_conflicted, + &prop_conflicted, + &tree_conflicted, + db, local_abspath, + scratch_pool)); + + /* We can't install two text/prop conflicts on a single node, so + avoid even checking that we have to merge it */ + if (text_conflicted || prop_conflicted || tree_conflicted) + { + return svn_error_createf( + SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL, + _("Can't merge into conflicted node '%s'"), + svn_dirent_local_style(local_abspath, + scratch_pool)); + } + /* else: Conflict was resolved by removing markers */ + } /* The PROPCHANGES may not have non-"normal" properties in it. If entry or wc props were allowed, then the following code would install them @@ -299,24 +292,38 @@ svn_wc__perform_props_merge(svn_wc_notif /* Note that while this routine does the "real" work, it's only prepping tempfiles and writing log commands. */ - SVN_ERR(svn_wc__merge_props(&work_items, state, + SVN_ERR(svn_wc__merge_props(&conflict_skel, state, &new_pristine_props, &new_actual_props, db, local_abspath, kind, - left_version, right_version, baseprops /* server_baseprops */, pristine_props, actual_props, propchanges, base_merge, dry_run, - conflict_func, conflict_baton, cancel_func, cancel_baton, scratch_pool, scratch_pool)); if (dry_run) { - SVN_ERR_ASSERT(! work_items); return SVN_NO_ERROR; } + if (conflict_skel) + { + svn_skel_t *work_item; + SVN_ERR(svn_wc__conflict_skel_set_op_merge(conflict_skel, + left_version, + right_version, + scratch_pool, + scratch_pool)); + + SVN_ERR(svn_wc__conflict_create_markers(&work_item, + db, local_abspath, + conflict_skel, + scratch_pool, scratch_pool)); + + work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool); + } + { const char *dir_abspath; @@ -344,9 +351,10 @@ svn_wc__perform_props_merge(svn_wc_notif return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, U_("base_merge=TRUE is no longer supported")); #endif + SVN_ERR(svn_wc__db_op_set_props(db, local_abspath, new_actual_props, svn_wc__has_magic_property(propchanges), - NULL /* conflict */, + conflict_skel, work_items, scratch_pool)); @@ -355,6 +363,12 @@ svn_wc__perform_props_merge(svn_wc_notif scratch_pool)); } + if (conflict_skel && conflict_func) + SVN_ERR(svn_wc__conflict_invoke_resolver(db, local_abspath, conflict_skel, + NULL /* merge_options */, + conflict_func, conflict_baton, + scratch_pool)); + return SVN_NO_ERROR; } @@ -619,7 +633,7 @@ prop_conflict_from_skel(const svn_string if (!(original_is_binary || mine_is_binary || incoming_is_binary)) { diff_opts = svn_diff_file_options_create(scratch_pool); - diff_opts->ignore_space = FALSE; + diff_opts->ignore_space = svn_diff_file_ignore_space_none; diff_opts->ignore_eol_style = FALSE; diff_opts->show_c_function = FALSE; SVN_ERR(svn_diff_mem_string_diff3(&diff, original, mine, incoming, @@ -769,268 +783,6 @@ set_prop_merge_state(svn_wc_notify_state *state = new_value; } -/* Helper function for the three apply_* functions below, used when - * merging properties together. - * - * Given property PROPNAME on LOCAL_ABSPATH, and four possible property - * values, generate four tmpfiles and pass them to CONFLICT_FUNC callback. - * This gives the client an opportunity to interactively resolve the - * property conflict. - * - * BASE_VAL/WORKING_VAL represent the current state of the working - * copy, and INCOMING_OLD_VAL/INCOMING_NEW_VAL represents the incoming - * propchange. Any of these values might be NULL, indicating either - * non-existence or intent-to-delete. - * - * If the callback isn't available, or if it responds with - * 'choose_postpone', then set *CONFLICT_REMAINS to TRUE and return. - * - * If the callback responds with a choice of 'base', 'theirs', 'mine', - * or 'merged', then install the proper value into ACTUAL_PROPS and - * set *CONFLICT_REMAINS to FALSE. - */ -static svn_error_t * -maybe_generate_propconflict(svn_boolean_t *conflict_remains, - svn_wc__db_t *db, - const char *local_abspath, - const svn_wc_conflict_version_t *left_version, - const svn_wc_conflict_version_t *right_version, - svn_boolean_t is_dir, - const char *propname, - apr_hash_t *actual_props, - const svn_string_t *incoming_old_val, - const svn_string_t *incoming_new_val, - const svn_string_t *base_val, - const svn_string_t *working_val, - svn_wc_conflict_resolver_func2_t conflict_func, - void *conflict_baton, - svn_boolean_t dry_run, - apr_pool_t *scratch_pool) -{ - svn_wc_conflict_result_t *result = NULL; - apr_pool_t *filepool = svn_pool_create(scratch_pool); - svn_wc_conflict_description2_t *cdesc; - const char *dirpath = svn_dirent_dirname(local_abspath, filepool); - - if (! conflict_func || dry_run) - { - /* Just postpone the conflict. */ - *conflict_remains = TRUE; - return SVN_NO_ERROR; - } - - cdesc = svn_wc_conflict_description_create_prop2( - local_abspath, - is_dir ? svn_node_dir : svn_node_file, propname, scratch_pool); - - cdesc->src_left_version = left_version; - cdesc->src_right_version = right_version; - - /* Create a tmpfile for each of the string_t's we've got. */ - if (working_val) - { - const char *file_name; - - SVN_ERR(svn_io_write_unique(&file_name, dirpath, working_val->data, - working_val->len, - svn_io_file_del_on_pool_cleanup, filepool)); - cdesc->my_abspath = svn_dirent_join(dirpath, file_name, filepool); - } - - if (incoming_new_val) - { - const char *file_name; - - SVN_ERR(svn_io_write_unique(&file_name, dirpath, incoming_new_val->data, - incoming_new_val->len, - svn_io_file_del_on_pool_cleanup, filepool)); - cdesc->their_abspath = svn_dirent_join(dirpath, file_name, filepool); - } - - if (!base_val && !incoming_old_val) - { - /* If base and old are both NULL, then that's fine, we just let - base_file stay NULL as-is. Both agents are attempting to add a - new property. */ - } - - else if ((base_val && !incoming_old_val) - || (!base_val && incoming_old_val)) - { - /* If only one of base and old are defined, then we've got a - situation where one agent is attempting to add the property - for the first time, and the other agent is changing a - property it thinks already exists. In this case, we return - whichever older-value happens to be defined, so that the - conflict-callback can still attempt a 3-way merge. */ - - const svn_string_t *conflict_base_val = base_val ? base_val - : incoming_old_val; - const char *file_name; - - SVN_ERR(svn_io_write_unique(&file_name, dirpath, - conflict_base_val->data, - conflict_base_val->len, - svn_io_file_del_on_pool_cleanup, - filepool)); - cdesc->base_abspath = svn_dirent_join(dirpath, file_name, filepool); - } - - else /* base and old are both non-NULL */ - { - const svn_string_t *conflict_base_val; - const char *file_name; - - if (! svn_string_compare(base_val, incoming_old_val)) - { - /* What happens if 'base' and 'old' don't match up? In an - ideal situation, they would. But if they don't, this is - a classic example of a patch 'hunk' failing to apply due - to a lack of context. For example: imagine that the user - is busy changing the property from a value of "cat" to - "dog", but the incoming propchange wants to change the - same property value from "red" to "green". Total context - mismatch. - - HOWEVER: we can still pass one of the two base values as - 'base_file' to the callback anyway. It's still useful to - present the working and new values to the user to - compare. */ - - if (working_val && svn_string_compare(base_val, working_val)) - conflict_base_val = incoming_old_val; - else - conflict_base_val = base_val; - } - else - { - conflict_base_val = base_val; - } - - SVN_ERR(svn_io_write_unique(&file_name, dirpath, conflict_base_val->data, - conflict_base_val->len, - svn_io_file_del_on_pool_cleanup, filepool)); - cdesc->base_abspath = svn_dirent_join(dirpath, file_name, filepool); - - if (working_val && incoming_new_val) - { - svn_stream_t *mergestream; - svn_diff_t *diff; - svn_diff_file_options_t *options = - svn_diff_file_options_create(filepool); - - SVN_ERR(svn_stream_open_unique(&mergestream, &cdesc->merged_file, - NULL, svn_io_file_del_on_pool_cleanup, - filepool, scratch_pool)); - SVN_ERR(svn_diff_mem_string_diff3(&diff, conflict_base_val, - working_val, - incoming_new_val, options, filepool)); - SVN_ERR(svn_diff_mem_string_output_merge2 - (mergestream, diff, conflict_base_val, working_val, - incoming_new_val, NULL, NULL, NULL, NULL, - svn_diff_conflict_display_modified_latest, filepool)); - SVN_ERR(svn_stream_close(mergestream)); - } - } - - /* Build the rest of the description object: */ - cdesc->mime_type = (is_dir ? NULL : svn_prop_get_value(actual_props, - SVN_PROP_MIME_TYPE)); - cdesc->is_binary = (cdesc->mime_type - && svn_mime_type_is_binary(cdesc->mime_type)); - - if (!incoming_old_val && incoming_new_val) - cdesc->action = svn_wc_conflict_action_add; - else if (incoming_old_val && !incoming_new_val) - cdesc->action = svn_wc_conflict_action_delete; - else - cdesc->action = svn_wc_conflict_action_edit; - - if (base_val && !working_val) - cdesc->reason = svn_wc_conflict_reason_deleted; - else if (!base_val && working_val) - cdesc->reason = svn_wc_conflict_reason_obstructed; - else - cdesc->reason = svn_wc_conflict_reason_edited; - - /* Invoke the interactive conflict callback. */ - { - SVN_ERR(conflict_func(&result, cdesc, conflict_baton, scratch_pool, - scratch_pool)); - } - if (result == NULL) - { - *conflict_remains = TRUE; - return svn_error_create(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, - NULL, _("Conflict callback violated API:" - " returned no results.")); - } - - switch (result->choice) - { - default: - case svn_wc_conflict_choose_postpone: - { - *conflict_remains = TRUE; - break; - } - case svn_wc_conflict_choose_mine_full: - { - /* No need to change actual_props; it already contains working_val */ - *conflict_remains = FALSE; - break; - } - /* I think _mine_full and _theirs_full are appropriate for prop - behavior as well as the text behavior. There should even be - analogous behaviors for _mine and _theirs when those are - ready, namely: fold in all non-conflicting prop changes, and - then choose _mine side or _theirs side for conflicting ones. */ - case svn_wc_conflict_choose_theirs_full: - { - apr_hash_set(actual_props, propname, APR_HASH_KEY_STRING, - incoming_new_val); - *conflict_remains = FALSE; - break; - } - case svn_wc_conflict_choose_base: - { - apr_hash_set(actual_props, propname, APR_HASH_KEY_STRING, base_val); - *conflict_remains = FALSE; - break; - } - case svn_wc_conflict_choose_merged: - { - if (!cdesc->merged_file && !result->merged_file) - return svn_error_create - (SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, - NULL, _("Conflict callback violated API:" - " returned no merged file.")); - else - { - svn_stringbuf_t *merged_stringbuf; - svn_string_t *merged_string; - - SVN_ERR(svn_stringbuf_from_file2(&merged_stringbuf, - result->merged_file ? - result->merged_file : - cdesc->merged_file, - scratch_pool)); - merged_string = svn_stringbuf__morph_into_string(merged_stringbuf); - apr_hash_set(actual_props, propname, - APR_HASH_KEY_STRING, merged_string); - *conflict_remains = FALSE; - } - break; - } - } - - /* Delete any tmpfiles we made. */ - svn_pool_destroy(filepool); - - return SVN_NO_ERROR; -} - - /* Add the property with name PROPNAME to the set of ACTUAL_PROPS on * PATH, setting *STATE or *CONFLICT_REMAINS according to merge outcomes. * @@ -1040,26 +792,16 @@ maybe_generate_propconflict(svn_boolean_ * BASE_VAL contains the working copy base property value * * NEW_VAL contains the value to be set. - * - * CONFLICT_FUNC/BATON is a callback to be called before declaring a - * property conflict; it gives the client a chance to resolve the - * conflict interactively. */ static svn_error_t * apply_single_prop_add(svn_wc_notify_state_t *state, svn_boolean_t *conflict_remains, svn_wc__db_t *db, const char *local_abspath, - const svn_wc_conflict_version_t *left_version, - const svn_wc_conflict_version_t *right_version, - svn_boolean_t is_dir, apr_hash_t *actual_props, const char *propname, const svn_string_t *base_val, const svn_string_t *new_val, - svn_wc_conflict_resolver_func2_t conflict_func, - void *conflict_baton, - svn_boolean_t dry_run, apr_pool_t *result_pool, apr_pool_t *scratch_pool) @@ -1112,31 +854,11 @@ apply_single_prop_add(svn_wc_notify_stat } if (!merged_prop) - { - SVN_ERR(maybe_generate_propconflict(conflict_remains, - db, local_abspath, - left_version, right_version, - is_dir, - propname, actual_props, - NULL, new_val, - base_val, working_val, - conflict_func, - conflict_baton, - dry_run, scratch_pool)); - } + *conflict_remains = TRUE; } } else if (base_val) - { - SVN_ERR(maybe_generate_propconflict(conflict_remains, - db, local_abspath, - left_version, right_version, - is_dir, propname, - actual_props, NULL, new_val, - base_val, NULL, - conflict_func, conflict_baton, - dry_run, scratch_pool)); - } + *conflict_remains = TRUE; else /* property doesn't yet exist in actual_props... */ /* so just set it */ apr_hash_set(actual_props, propname, APR_HASH_KEY_STRING, new_val); @@ -1156,26 +878,16 @@ apply_single_prop_add(svn_wc_notify_stat * * OLD_VAL contains the value the of the property the server * thinks it's deleting. - * - * CONFLICT_FUNC/BATON is a callback to be called before declaring a - * property conflict; it gives the client a chance to resolve the - * conflict interactively. */ static svn_error_t * apply_single_prop_delete(svn_wc_notify_state_t *state, svn_boolean_t *conflict_remains, svn_wc__db_t *db, const char *local_abspath, - const svn_wc_conflict_version_t *left_version, - const svn_wc_conflict_version_t *right_version, - svn_boolean_t is_dir, apr_hash_t *actual_props, const char *propname, const svn_string_t *base_val, const svn_string_t *old_val, - svn_wc_conflict_resolver_func2_t conflict_func, - void *conflict_baton, - svn_boolean_t dry_run, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { @@ -1190,14 +902,7 @@ apply_single_prop_delete(svn_wc_notify_s && !svn_string_compare(working_val, old_val)) { /* We are trying to delete a locally-added prop. */ - SVN_ERR(maybe_generate_propconflict(conflict_remains, - db, local_abspath, - left_version, right_version, - is_dir, propname, - actual_props, old_val, NULL, - base_val, working_val, - conflict_func, conflict_baton, - dry_run, scratch_pool)); + *conflict_remains = TRUE; } else { @@ -1217,18 +922,7 @@ apply_single_prop_delete(svn_wc_notify_s /* they have the same values, so it's an update */ apr_hash_set(actual_props, propname, APR_HASH_KEY_STRING, NULL); else - { - SVN_ERR(maybe_generate_propconflict(conflict_remains, - db, local_abspath, - left_version, right_version, - is_dir, - propname, actual_props, - old_val, NULL, - base_val, working_val, - conflict_func, - conflict_baton, - dry_run, scratch_pool)); - } + *conflict_remains = TRUE; } else /* The property is locally deleted from the same value, so it's @@ -1237,16 +931,7 @@ apply_single_prop_delete(svn_wc_notify_s } else - { - SVN_ERR(maybe_generate_propconflict(conflict_remains, - db, local_abspath, - left_version, right_version, - is_dir, propname, - actual_props, old_val, NULL, - base_val, working_val, - conflict_func, conflict_baton, - dry_run, scratch_pool)); - } + *conflict_remains = TRUE; return SVN_NO_ERROR; } @@ -1264,17 +949,11 @@ apply_single_mergeinfo_prop_change(svn_w svn_boolean_t *conflict_remains, svn_wc__db_t *db, const char *local_abspath, - const svn_wc_conflict_version_t *left_version, - const svn_wc_conflict_version_t *right_version, - svn_boolean_t is_dir, apr_hash_t *actual_props, const char *propname, const svn_string_t *base_val, const svn_string_t *old_val, const svn_string_t *new_val, - svn_wc_conflict_resolver_func2_t conflict_func, - void *conflict_baton, - svn_boolean_t dry_run, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { @@ -1312,14 +991,7 @@ apply_single_mergeinfo_prop_change(svn_w else { /* There is a base_val but no working_val */ - SVN_ERR(maybe_generate_propconflict(conflict_remains, - db, local_abspath, - left_version, right_version, - is_dir, propname, actual_props, - old_val, new_val, - base_val, working_val, - conflict_func, conflict_baton, - dry_run, scratch_pool)); + *conflict_remains = TRUE; } } @@ -1376,17 +1048,11 @@ apply_single_generic_prop_change(svn_wc_ svn_boolean_t *conflict_remains, svn_wc__db_t *db, const char *local_abspath, - const svn_wc_conflict_version_t *left_version, - const svn_wc_conflict_version_t *right_version, - svn_boolean_t is_dir, apr_hash_t *actual_props, const char *propname, const svn_string_t *base_val, const svn_string_t *old_val, const svn_string_t *new_val, - svn_wc_conflict_resolver_func2_t conflict_func, - void *conflict_baton, - svn_boolean_t dry_run, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { @@ -1414,14 +1080,7 @@ apply_single_generic_prop_change(svn_wc_ else { /* Merge the change. */ - SVN_ERR(maybe_generate_propconflict(conflict_remains, - db, local_abspath, - left_version, right_version, - is_dir, propname, actual_props, - old_val, new_val, - base_val, working_val, - conflict_func, conflict_baton, - dry_run, scratch_pool)); + *conflict_remains = TRUE; } return SVN_NO_ERROR; @@ -1439,27 +1098,17 @@ apply_single_generic_prop_change(svn_wc_ * thinks it's overwriting. (Not null.) * * NEW_VAL contains the value to be set. (Not null.) - * - * CONFLICT_FUNC/BATON is a callback to be called before declaring a - * property conflict; it gives the client a chance to resolve the - * conflict interactively. */ static svn_error_t * apply_single_prop_change(svn_wc_notify_state_t *state, svn_boolean_t *conflict_remains, svn_wc__db_t *db, const char *local_abspath, - const svn_wc_conflict_version_t *left_version, - const svn_wc_conflict_version_t *right_version, - svn_boolean_t is_dir, apr_hash_t *actual_props, const char *propname, const svn_string_t *base_val, const svn_string_t *old_val, const svn_string_t *new_val, - svn_wc_conflict_resolver_func2_t conflict_func, - void *conflict_baton, - svn_boolean_t dry_run, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { @@ -1485,17 +1134,11 @@ apply_single_prop_change(svn_wc_notify_s svn_error_t *err = apply_single_mergeinfo_prop_change(state, conflict_remains, db, local_abspath, - left_version, - right_version, - is_dir, actual_props, propname, base_val, old_val, new_val, - conflict_func, - conflict_baton, - dry_run, result_pool, scratch_pool); if (err) @@ -1518,13 +1161,9 @@ apply_single_prop_change(svn_wc_notify_s SVN_ERR(apply_single_generic_prop_change(state, conflict_remains, db, local_abspath, - left_version, right_version, - is_dir, actual_props, propname, base_val, old_val, new_val, - conflict_func, conflict_baton, - dry_run, result_pool, scratch_pool)); } @@ -1533,23 +1172,19 @@ apply_single_prop_change(svn_wc_notify_s svn_error_t * -svn_wc__merge_props(svn_skel_t **work_items, +svn_wc__merge_props(svn_skel_t **conflict_skel, svn_wc_notify_state_t *state, apr_hash_t **new_pristine_props, apr_hash_t **new_actual_props, svn_wc__db_t *db, const char *local_abspath, svn_kind_t kind, - const svn_wc_conflict_version_t *left_version, - const svn_wc_conflict_version_t *right_version, apr_hash_t *server_baseprops, apr_hash_t *pristine_props, apr_hash_t *actual_props, const apr_array_header_t *propchanges, svn_boolean_t base_merge, svn_boolean_t dry_run, - svn_wc_conflict_resolver_func2_t conflict_func, - void *conflict_baton, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *result_pool, @@ -1557,22 +1192,25 @@ svn_wc__merge_props(svn_skel_t **work_it { apr_pool_t *iterpool; int i; - svn_boolean_t is_dir; - svn_skel_t *conflict_skel = NULL; + apr_hash_t *conflict_props = NULL; + apr_hash_t *old_actual_props; + apr_hash_t *their_props; SVN_ERR_ASSERT(pristine_props != NULL); SVN_ERR_ASSERT(actual_props != NULL); - *work_items = NULL; + /* Just copy the pointers as we copy the data in the skel if + necessary */ + old_actual_props = apr_hash_copy(scratch_pool, actual_props); *new_pristine_props = NULL; *new_actual_props = NULL; - is_dir = (kind == svn_kind_dir); - if (!server_baseprops) server_baseprops = pristine_props; + their_props = apr_hash_copy(scratch_pool, server_baseprops); + if (state) { /* Start out assuming no changes or conflicts. Don't bother to @@ -1590,7 +1228,6 @@ svn_wc__merge_props(svn_skel_t **work_it svn_boolean_t conflict_remains; const svn_prop_t *incoming_change; const svn_string_t *from_val, *to_val, *base_val; - const svn_string_t *mine_val; svn_pool_clear(iterpool); @@ -1610,8 +1247,7 @@ svn_wc__merge_props(svn_skel_t **work_it if (base_merge) apr_hash_set(pristine_props, propname, APR_HASH_KEY_STRING, to_val); - /* Save MINE for later message generation. */ - mine_val = apr_hash_get(actual_props, propname, APR_HASH_KEY_STRING); + apr_hash_set(their_props, propname, APR_HASH_KEY_STRING, to_val); /* We already know that state is at least `changed', so mark that, but remember that we may later upgrade to `merged' or @@ -1621,31 +1257,23 @@ svn_wc__merge_props(svn_skel_t **work_it if (! from_val) /* adding a new property */ SVN_ERR(apply_single_prop_add(state, &conflict_remains, db, local_abspath, - left_version, right_version, - is_dir, actual_props, + actual_props, propname, base_val, to_val, - conflict_func, conflict_baton, - dry_run, result_pool, iterpool)); + result_pool, iterpool)); else if (! to_val) /* delete an existing property */ SVN_ERR(apply_single_prop_delete(state, &conflict_remains, db, local_abspath, - left_version, right_version, - is_dir, actual_props, propname, base_val, from_val, - conflict_func, conflict_baton, - dry_run, result_pool, iterpool)); + result_pool, iterpool)); else /* changing an existing property */ SVN_ERR(apply_single_prop_change(state, &conflict_remains, db, local_abspath, - left_version, right_version, - is_dir, actual_props, propname, base_val, from_val, to_val, - conflict_func, conflict_baton, - dry_run, result_pool, iterpool)); + result_pool, iterpool)); /* merging logic complete, now we need to possibly log conflict @@ -1658,17 +1286,11 @@ svn_wc__merge_props(svn_skel_t **work_it if (dry_run) continue; /* skip to next incoming change */ - if (conflict_skel == NULL) - conflict_skel = svn_wc__conflict_skel_new(result_pool); + if (!conflict_props) + conflict_props = apr_hash_make(result_pool); - SVN_ERR(svn_wc__conflict_skel_add_prop_conflict(conflict_skel, - propname, - base_val, - mine_val, - to_val, - from_val, - result_pool, - iterpool)); + apr_hash_set(conflict_props, apr_pstrdup(result_pool, propname), + APR_HASH_KEY_STRING, ""); } } /* foreach propchange ... */ @@ -1682,63 +1304,23 @@ svn_wc__merge_props(svn_skel_t **work_it *new_pristine_props = pristine_props; *new_actual_props = actual_props; - if (conflict_skel != NULL) + if (conflict_props != NULL) { - const char *reject_path; - - /* Now try to get the name of a pre-existing .prej file from the - entries file */ - SVN_ERR(svn_wc__get_prejfile_abspath(&reject_path, db, local_abspath, - scratch_pool, scratch_pool)); - - if (! reject_path) - { - /* Reserve a new .prej file *above* the .svn/ directory by - opening and closing it. */ - const char *reject_dirpath; - const char *reject_filename; - svn_skel_t *work_item; - - if (is_dir) - { - reject_dirpath = local_abspath; - reject_filename = SVN_WC__THIS_DIR_PREJ; - } - else - svn_dirent_split(&reject_dirpath, &reject_filename, local_abspath, - scratch_pool); - - SVN_ERR(svn_io_open_uniquely_named(NULL, &reject_path, - reject_dirpath, - reject_filename, - SVN_WC__PROP_REJ_EXT, - svn_io_file_del_none, - scratch_pool, scratch_pool)); - - /* This file will be overwritten when the wq is run; that's - ok, because at least now we have a reservation on - disk. */ - - /* Mark entry as "conflicted" with a particular .prej file. */ - SVN_ERR(svn_wc__wq_tmp_build_set_property_conflict_marker( - &work_item, - db, local_abspath, reject_path, - result_pool, scratch_pool)); - - *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool); - } - - /* Once the prejfile is recorded, then install the file. */ - { - svn_skel_t *work_item; + /* Ok, we got some conflict. Lets store all the property knowledge we + have for resolving later */ - SVN_ERR(svn_wc__wq_build_prej_install(&work_item, - db, local_abspath, - conflict_skel, - result_pool, scratch_pool)); + if (!*conflict_skel) + *conflict_skel = svn_wc__conflict_skel_create(result_pool); - *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool); - } + SVN_ERR(svn_wc__conflict_skel_add_prop_conflict(*conflict_skel, + db, local_abspath, + NULL /* reject_path */, + old_actual_props, + server_baseprops, + their_props, + conflict_props, + result_pool, + scratch_pool)); } return SVN_NO_ERROR; Modified: subversion/branches/master-passphrase/subversion/libsvn_wc/props.h URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_wc/props.h?rev=1361339&r1=1361338&r2=1361339&view=diff ============================================================================== --- subversion/branches/master-passphrase/subversion/libsvn_wc/props.h (original) +++ subversion/branches/master-passphrase/subversion/libsvn_wc/props.h Fri Jul 13 19:04:32 2012 @@ -91,32 +91,24 @@ svn_wc__internal_propget(const svn_strin into the .prej file later. Modify base properties unconditionally, if BASE_MERGE is TRUE, they do not generate conficts. - TODO ### LEFT_VERSION and RIGHT_VERSION ... - TODO ### DRY_RUN ... - TODO ### CONFLICT_FUNC/CONFLICT_BATON ... - If STATE is non-null, set *STATE to the state of the local properties after the merge. */ svn_error_t * -svn_wc__merge_props(svn_skel_t **work_items, +svn_wc__merge_props(svn_skel_t **conflict_skel, svn_wc_notify_state_t *state, apr_hash_t **new_pristine_props, apr_hash_t **new_actual_props, svn_wc__db_t *db, const char *local_abspath, svn_kind_t kind, - const svn_wc_conflict_version_t *left_version, - const svn_wc_conflict_version_t *right_version, apr_hash_t *server_baseprops, apr_hash_t *pristine_props, apr_hash_t *actual_props, const apr_array_header_t *propchanges, svn_boolean_t base_merge, svn_boolean_t dry_run, - svn_wc_conflict_resolver_func2_t conflict_func, - void *conflict_baton, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *result_pool, @@ -153,13 +145,6 @@ svn_wc__get_actual_props(apr_hash_t **pr apr_pool_t *scratch_pool); svn_error_t * -svn_wc__get_prejfile_abspath(const char **prejfile_abspath, - svn_wc__db_t *db, - const char *local_abspath, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool); - -svn_error_t * svn_wc__create_prejfile(const char **tmp_prejfile_abspath, svn_wc__db_t *db, const char *local_abspath, Modified: subversion/branches/master-passphrase/subversion/libsvn_wc/questions.c URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_wc/questions.c?rev=1361339&r1=1361338&r2=1361339&view=diff ============================================================================== --- subversion/branches/master-passphrase/subversion/libsvn_wc/questions.c (original) +++ subversion/branches/master-passphrase/subversion/libsvn_wc/questions.c Fri Jul 13 19:04:32 2012 @@ -40,8 +40,7 @@ #include "svn_props.h" #include "wc.h" -#include "adm_files.h" -#include "props.h" +#include "conflicts.h" #include "translate.h" #include "wc_db.h" @@ -392,117 +391,106 @@ svn_wc__internal_conflicted_p(svn_boolea apr_pool_t *scratch_pool) { svn_node_kind_t kind; - svn_kind_t node_kind; - const apr_array_header_t *conflicts; - int i; - svn_boolean_t conflicted; + svn_skel_t *conflicts; svn_boolean_t resolved_text = FALSE; svn_boolean_t resolved_props = FALSE; - if (text_conflicted_p) - *text_conflicted_p = FALSE; - if (prop_conflicted_p) - *prop_conflicted_p = FALSE; - if (tree_conflicted_p) - *tree_conflicted_p = FALSE; + SVN_ERR(svn_wc__db_read_conflict(&conflicts, db, local_abspath, + scratch_pool, scratch_pool)); - SVN_ERR(svn_wc__db_read_info(NULL, &node_kind, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, &conflicted, - NULL, NULL, NULL, NULL, NULL, NULL, - db, local_abspath, scratch_pool, - scratch_pool)); + if (!conflicts) + { + if (text_conflicted_p) + *text_conflicted_p = FALSE; + if (prop_conflicted_p) + *prop_conflicted_p = FALSE; + if (tree_conflicted_p) + *tree_conflicted_p = FALSE; - if (!conflicted) - return SVN_NO_ERROR; + return SVN_NO_ERROR; + } + SVN_ERR(svn_wc__conflict_read_info(NULL, NULL, text_conflicted_p, + prop_conflicted_p, tree_conflicted_p, + db, local_abspath, conflicts, + scratch_pool, scratch_pool)); + + if (text_conflicted_p && *text_conflicted_p) + { + const char *mine_abspath; + const char *their_old_abspath; + const char *their_abspath; + svn_boolean_t done = FALSE; + + /* Look for any text conflict, exercising only as much effort as + necessary to obtain a definitive answer. This only applies to + files, but we don't have to explicitly check that entry is a + file, since these attributes would never be set on a directory + anyway. A conflict file entry notation only counts if the + conflict file still exists on disk. */ + + SVN_ERR(svn_wc__conflict_read_text_conflict(&mine_abspath, + &their_old_abspath, + &their_abspath, + db, local_abspath, conflicts, + scratch_pool, scratch_pool)); - SVN_ERR(svn_wc__db_read_conflicts(&conflicts, db, local_abspath, - scratch_pool, scratch_pool)); + if (mine_abspath) + { + SVN_ERR(svn_io_check_path(mine_abspath, &kind, scratch_pool)); - for (i = 0; i < conflicts->nelts; i++) - { - const svn_wc_conflict_description2_t *cd; - cd = APR_ARRAY_IDX(conflicts, i, const svn_wc_conflict_description2_t *); + *text_conflicted_p = (kind == svn_node_file); - switch (cd->kind) + if (*text_conflicted_p) + done = TRUE; + } + + if (!done && their_abspath) { - case svn_wc_conflict_kind_text: - /* Look for any text conflict, exercising only as much effort as - necessary to obtain a definitive answer. This only applies to - files, but we don't have to explicitly check that entry is a - file, since these attributes would never be set on a directory - anyway. A conflict file entry notation only counts if the - conflict file still exists on disk. */ - - if (!text_conflicted_p || *text_conflicted_p) - break; - - if (cd->base_abspath) - { - SVN_ERR(svn_io_check_path(cd->base_abspath, &kind, - scratch_pool)); + SVN_ERR(svn_io_check_path(their_abspath, &kind, scratch_pool)); - *text_conflicted_p = (kind == svn_node_file); + *text_conflicted_p = (kind == svn_node_file); - if (*text_conflicted_p) - break; - } - - if (cd->their_abspath) - { - SVN_ERR(svn_io_check_path(cd->their_abspath, &kind, - scratch_pool)); + if (*text_conflicted_p) + done = TRUE; + } - *text_conflicted_p = (kind == svn_node_file); + if (!done && their_old_abspath) + { + SVN_ERR(svn_io_check_path(their_old_abspath, &kind, scratch_pool)); - if (*text_conflicted_p) - break; - } - - if (cd->my_abspath) - { - SVN_ERR(svn_io_check_path(cd->my_abspath, &kind, - scratch_pool)); + *text_conflicted_p = (kind == svn_node_file); - *text_conflicted_p = (kind == svn_node_file); + if (*text_conflicted_p) + done = TRUE; + } - if (*text_conflicted_p) - break; - } - - resolved_text = TRUE; /* Remove in-db conflict marker */ - break; - - case svn_wc_conflict_kind_property: - if (!prop_conflicted_p || *prop_conflicted_p) - break; - - if (cd->their_abspath) - { - SVN_ERR(svn_io_check_path(cd->their_abspath, &kind, - scratch_pool)); + if (!done && (mine_abspath || their_abspath || their_old_abspath)) + resolved_text = TRUE; /* Remove in-db conflict marker */ + } - *prop_conflicted_p = (kind == svn_node_file); + if (prop_conflicted_p && *prop_conflicted_p) + { + const char *prej_abspath; - if (*prop_conflicted_p) - break; - } - resolved_props = TRUE; /* Remove in-db conflict marker */ - break; + SVN_ERR(svn_wc__conflict_read_prop_conflict(&prej_abspath, + NULL, NULL, NULL, NULL, + db, local_abspath, conflicts, + scratch_pool, scratch_pool)); - case svn_wc_conflict_kind_tree: - if (tree_conflicted_p) - *tree_conflicted_p = TRUE; + if (prej_abspath) + { + SVN_ERR(svn_io_check_path(prej_abspath, &kind, scratch_pool)); - break; + *prop_conflicted_p = (kind == svn_node_file); - default: - /* Ignore other conflict types */ - break; + if (! *prop_conflicted_p) + resolved_props = TRUE; /* Remove in-db conflict marker */ } } + /* tree_conflicts don't have markers, so don't need checking */ + if (resolved_text || resolved_props) { svn_boolean_t own_lock; Modified: subversion/branches/master-passphrase/subversion/libsvn_wc/tree_conflicts.c URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_wc/tree_conflicts.c?rev=1361339&r1=1361338&r2=1361339&view=diff ============================================================================== --- subversion/branches/master-passphrase/subversion/libsvn_wc/tree_conflicts.c (original) +++ subversion/branches/master-passphrase/subversion/libsvn_wc/tree_conflicts.c Fri Jul 13 19:04:32 2012 @@ -27,6 +27,7 @@ #include "svn_pools.h" #include "tree_conflicts.h" +#include "conflicts.h" #include "wc.h" #include "private/svn_skel.h" @@ -389,8 +390,9 @@ svn_wc__del_tree_conflict(svn_wc_context { SVN_ERR_ASSERT(svn_dirent_is_absolute(victim_abspath)); - SVN_ERR(svn_wc__db_op_set_tree_conflict(wc_ctx->db, victim_abspath, - NULL, scratch_pool)); + SVN_ERR(svn_wc__db_op_mark_resolved(wc_ctx->db, victim_abspath, + FALSE, FALSE, TRUE, NULL, + scratch_pool)); return SVN_NO_ERROR; } @@ -400,66 +402,99 @@ svn_wc__add_tree_conflict(svn_wc_context const svn_wc_conflict_description2_t *conflict, apr_pool_t *scratch_pool) { - const svn_wc_conflict_description2_t *existing_conflict; + svn_boolean_t existing_conflict; + svn_skel_t *conflict_skel; + svn_error_t *err; /* Re-adding an existing tree conflict victim is an error. */ - SVN_ERR(svn_wc__db_op_read_tree_conflict(&existing_conflict, wc_ctx->db, - conflict->local_abspath, - scratch_pool, scratch_pool)); - if (existing_conflict != NULL) + err = svn_wc__internal_conflicted_p(NULL, NULL, &existing_conflict, + wc_ctx->db, conflict->local_abspath, + scratch_pool); + if (err) + { + if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND) + return svn_error_trace(err); + + svn_error_clear(err); + } + else if (existing_conflict) return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL, _("Attempt to add tree conflict that already " "exists at '%s'"), svn_dirent_local_style(conflict->local_abspath, scratch_pool)); + else if (!conflict) + return SVN_NO_ERROR; + + conflict_skel = svn_wc__conflict_skel_create(scratch_pool); + + SVN_ERR(svn_wc__conflict_skel_add_tree_conflict(conflict_skel, wc_ctx->db, + conflict->local_abspath, + conflict->reason, + conflict->action, + scratch_pool, scratch_pool)); + + switch(conflict->operation) + { + case svn_wc_operation_update: + default: + SVN_ERR(svn_wc__conflict_skel_set_op_update(conflict_skel, + conflict->src_left_version, + scratch_pool, scratch_pool)); + break; + case svn_wc_operation_switch: + SVN_ERR(svn_wc__conflict_skel_set_op_switch(conflict_skel, + conflict->src_left_version, + scratch_pool, scratch_pool)); + break; + case svn_wc_operation_merge: + SVN_ERR(svn_wc__conflict_skel_set_op_merge(conflict_skel, + conflict->src_left_version, + conflict->src_right_version, + scratch_pool, scratch_pool)); + break; + } return svn_error_trace( - svn_wc__db_op_set_tree_conflict(wc_ctx->db, conflict->local_abspath, - conflict, scratch_pool)); + svn_wc__db_op_mark_conflict(wc_ctx->db, conflict->local_abspath, + conflict_skel, NULL, scratch_pool)); } svn_error_t * svn_wc__get_tree_conflict(const svn_wc_conflict_description2_t **tree_conflict, svn_wc_context_t *wc_ctx, - const char *victim_abspath, + const char *local_abspath, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - SVN_ERR_ASSERT(svn_dirent_is_absolute(victim_abspath)); - - return svn_error_trace( - svn_wc__db_op_read_tree_conflict(tree_conflict, wc_ctx->db, victim_abspath, - result_pool, scratch_pool)); -} + const apr_array_header_t *conflicts; + int i; + SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath)); -svn_error_t * -svn_wc__get_all_tree_conflicts(apr_hash_t **tree_conflicts, - svn_wc_context_t *wc_ctx, - const char *local_abspath, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) -{ - apr_hash_t *conflicts; - apr_hash_index_t *hi; + SVN_ERR(svn_wc__read_conflicts(&conflicts, + wc_ctx->db, local_abspath, + scratch_pool, scratch_pool)); - SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath)); + if (!conflicts || conflicts->nelts == 0) + { + *tree_conflict = NULL; + return SVN_NO_ERROR; + } - SVN_ERR(svn_wc__db_op_read_all_tree_conflicts(&conflicts, wc_ctx->db, - local_abspath, - result_pool, scratch_pool)); - *tree_conflicts = apr_hash_make(result_pool); - /* Convert from basenames as keys to abspaths as keys. */ - for (hi = apr_hash_first(scratch_pool, conflicts); hi; - hi = apr_hash_next(hi)) + for (i = 0; i < conflicts->nelts; i++) { - const char *name = svn__apr_hash_index_key(hi); - const svn_wc_conflict_description2_t *conflict - = svn__apr_hash_index_val(hi); - const char *abspath = svn_dirent_join(local_abspath, name, scratch_pool); + const svn_wc_conflict_description2_t *desc; - apr_hash_set(*tree_conflicts, abspath, APR_HASH_KEY_STRING, conflict); - } + desc = APR_ARRAY_IDX(conflicts, i, svn_wc_conflict_description2_t *); + if (desc->kind == svn_wc_conflict_kind_tree) + { + *tree_conflict = svn_wc__conflict_description2_dup(desc, + result_pool); + return SVN_NO_ERROR; + } + } return SVN_NO_ERROR; } +