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 7EB44E97F for ; Wed, 6 Mar 2013 11:11:17 +0000 (UTC) Received: (qmail 30076 invoked by uid 500); 6 Mar 2013 11:11:17 -0000 Delivered-To: apmail-subversion-commits-archive@subversion.apache.org Received: (qmail 30053 invoked by uid 500); 6 Mar 2013 11:11:17 -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 30041 invoked by uid 99); 6 Mar 2013 11:11:17 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 06 Mar 2013 11:11:17 +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, 06 Mar 2013 11:11:07 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id EB9C22388B75; Wed, 6 Mar 2013 11:10:16 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1453290 [6/15] - in /subversion/branches/fsfs-format7: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apache/subversion/javahl/ subversion/bindin... Date: Wed, 06 Mar 2013 11:10:05 -0000 To: commits@subversion.apache.org From: stefan2@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20130306111016.EB9C22388B75@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Modified: subversion/branches/fsfs-format7/subversion/libsvn_wc/conflicts.c URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_wc/conflicts.c?rev=1453290&r1=1453289&r2=1453290&view=diff ============================================================================== --- subversion/branches/fsfs-format7/subversion/libsvn_wc/conflicts.c (original) +++ subversion/branches/fsfs-format7/subversion/libsvn_wc/conflicts.c Wed Mar 6 11:10:01 2013 @@ -1286,9 +1286,18 @@ generate_propconflict(svn_boolean_t *con svn_kind_t kind; const svn_string_t *new_value = NULL; - SVN_ERR(svn_wc__db_read_kind(&kind, db, local_abspath, FALSE, FALSE, + SVN_ERR(svn_wc__db_read_kind(&kind, db, local_abspath, + FALSE /* allow_missing */, + FALSE /* show_deleted */, + FALSE /* show_hidden */, scratch_pool)); + if (kind == svn_kind_none) + return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL, + _("The node '%s' was not found."), + svn_dirent_local_style(local_abspath, + scratch_pool)); + cdesc = svn_wc_conflict_description_create_prop2( local_abspath, (kind == svn_kind_dir) ? svn_node_dir : svn_node_file, @@ -2302,15 +2311,456 @@ svn_wc__read_conflicts(const apr_array_h /*** Resolving a conflict automatically ***/ +/* + * Resolve the text conflict found in DB/LOCAL_ABSPATH/CONFLICTS + * according to CONFLICT_CHOICE. (Don't mark it as resolved.) + * + * If there were any marker files recorded and present on disk, append to + * *WORK_ITEMS work items to remove them, and set *REMOVED_REJECT_FILES + * to TRUE. Otherwise, don't change *REMOVED_REJECT_FILES. + * + * It is an error if there is no text conflict. + * + * Note: When there are no conflict markers to remove there is no existing + * text conflict; just a database containing old information, which we should + * remove to avoid checking all the time. Resolving a text conflict by + * removing all the marker files is a fully supported scenario since + * Subversion 1.0. + */ +static svn_error_t * +resolve_text_conflict_on_node(svn_boolean_t *removed_reject_files, + svn_skel_t **work_items, + svn_wc__db_t *db, + const char *local_abspath, + svn_wc_operation_t operation, + svn_skel_t *conflicts, + svn_wc_conflict_choice_t conflict_choice, + apr_pool_t *scratch_pool) +{ + const char *conflict_old = NULL; + const char *conflict_new = NULL; + const char *conflict_working = NULL; + const char *auto_resolve_src; + svn_node_kind_t node_kind; + svn_skel_t *work_item; + + SVN_ERR(svn_wc__conflict_read_text_conflict(&conflict_working, + &conflict_old, + &conflict_new, + db, local_abspath, conflicts, + scratch_pool, scratch_pool)); + + /* Handle automatic conflict resolution before the temporary files are + * deleted, if necessary. */ + switch (conflict_choice) + { + case svn_wc_conflict_choose_base: + auto_resolve_src = conflict_old; + break; + case svn_wc_conflict_choose_mine_full: + auto_resolve_src = conflict_working; + break; + case svn_wc_conflict_choose_theirs_full: + auto_resolve_src = conflict_new; + break; + case svn_wc_conflict_choose_merged: + auto_resolve_src = NULL; + break; + case svn_wc_conflict_choose_theirs_conflict: + case svn_wc_conflict_choose_mine_conflict: + { + if (conflict_old && conflict_working && conflict_new) + { + const char *temp_dir; + svn_stream_t *tmp_stream = NULL; + svn_diff_t *diff; + svn_diff_conflict_display_style_t style = + conflict_choice == svn_wc_conflict_choose_theirs_conflict + ? svn_diff_conflict_display_latest + : svn_diff_conflict_display_modified; + + SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&temp_dir, db, + local_abspath, + scratch_pool, + scratch_pool)); + SVN_ERR(svn_stream_open_unique(&tmp_stream, + &auto_resolve_src, + temp_dir, + svn_io_file_del_on_pool_cleanup, + scratch_pool, scratch_pool)); + + SVN_ERR(svn_diff_file_diff3_2(&diff, + conflict_old, + conflict_working, + conflict_new, + svn_diff_file_options_create( + scratch_pool), + scratch_pool)); + SVN_ERR(svn_diff_file_output_merge2(tmp_stream, diff, + conflict_old, + conflict_working, + conflict_new, + /* markers ignored */ + NULL, NULL, NULL, NULL, + style, + scratch_pool)); + SVN_ERR(svn_stream_close(tmp_stream)); + } + else + auto_resolve_src = NULL; + break; + } + default: + return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL, + _("Invalid 'conflict_result' argument")); + } + + if (auto_resolve_src) + { + SVN_ERR(svn_wc__wq_build_file_copy_translated( + &work_item, db, local_abspath, + auto_resolve_src, local_abspath, scratch_pool, scratch_pool)); + *work_items = svn_wc__wq_merge(*work_items, work_item, scratch_pool); + + SVN_ERR(svn_wc__wq_build_sync_file_flags(&work_item, db, + local_abspath, + scratch_pool, scratch_pool)); + *work_items = svn_wc__wq_merge(*work_items, work_item, scratch_pool); + } + + /* Legacy behavior: Only report text conflicts as resolved when at least + one conflict marker file exists. + + If not the UI shows the conflict as already resolved + (and in this case we just remove the in-db conflict) */ + + if (conflict_old) + { + SVN_ERR(svn_io_check_path(conflict_old, &node_kind, scratch_pool)); + if (node_kind == svn_node_file) + { + SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db, + local_abspath, + conflict_old, + scratch_pool, scratch_pool)); + *work_items = svn_wc__wq_merge(*work_items, work_item, scratch_pool); + *removed_reject_files = TRUE; + } + } + + if (conflict_new) + { + SVN_ERR(svn_io_check_path(conflict_new, &node_kind, scratch_pool)); + if (node_kind == svn_node_file) + { + SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db, + local_abspath, + conflict_new, + scratch_pool, scratch_pool)); + *work_items = svn_wc__wq_merge(*work_items, work_item, scratch_pool); + *removed_reject_files = TRUE; + } + } + + if (conflict_working) + { + SVN_ERR(svn_io_check_path(conflict_working, &node_kind, scratch_pool)); + if (node_kind == svn_node_file) + { + SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db, + local_abspath, + conflict_working, + scratch_pool, scratch_pool)); + *work_items = svn_wc__wq_merge(*work_items, work_item, scratch_pool); + *removed_reject_files = TRUE; + } + } + + return SVN_NO_ERROR; +} + +/* + * Resolve the property conflicts found in DB/LOCAL_ABSPATH/CONFLICTS + * according to CONFLICT_CHOICE. (Don't mark it as resolved.) + * + * If there was a reject file recorded and present on disk, append to + * *WORK_ITEMS a work item to remove it, and set *REMOVED_REJECT_FILE + * to TRUE. Otherwise, don't change *REMOVED_REJECT_FILE. + * + * It is an error if there is no prop conflict. + * + * Note: When there are no conflict markers on-disk to remove there is + * no existing text conflict (unless we are still in the process of + * creating the text conflict and we didn't register a marker file yet). + * In this case the database contains old information, which we should + * remove to avoid checking the next time. Resolving a property conflict + * by just removing the marker file is a fully supported scenario since + * Subversion 1.0. + * + * ### TODO [JAF] The '*_full' and '*_conflict' choices should differ. + * In my opinion, 'mine_full'/'theirs_full' should select + * the entire set of properties from 'mine' or 'theirs' respectively, + * while 'mine_conflict'/'theirs_conflict' should select just the + * properties that are in conflict. Or, '_full' should select the + * entire property whereas '_conflict' should do a text merge within + * each property, selecting hunks. Or all three kinds of behaviour + * should be available (full set of props, full value of conflicting + * props, or conflicting text hunks). + * ### BH: If we make *_full select the full set of properties, we should + * check if we shouldn't make it also select the full text for files. + * + * ### TODO [JAF] All this complexity should not be down here in libsvn_wc + * but in a layer above. + * + * ### TODO [JAF] Options for 'base' should be like options for 'mine' and + * for 'theirs' -- choose full set of props, full value of conflicting + * props, or conflicting text hunks. + * + */ +static svn_error_t * +resolve_prop_conflict_on_node(svn_boolean_t *removed_reject_file, + svn_skel_t **work_items, + svn_wc__db_t *db, + const char *local_abspath, + svn_wc_operation_t operation, + svn_skel_t *conflicts, + svn_wc_conflict_choice_t conflict_choice, + apr_pool_t *scratch_pool) +{ + svn_node_kind_t node_kind; + const char *prop_reject_file; + apr_hash_t *mine_props; + apr_hash_t *their_old_props; + apr_hash_t *their_props; + apr_hash_t *conflicted_props; + apr_hash_t *old_props; + apr_hash_t *resolve_from = NULL; + + SVN_ERR(svn_wc__conflict_read_prop_conflict(&prop_reject_file, + &mine_props, &their_old_props, + &their_props, &conflicted_props, + db, local_abspath, conflicts, + scratch_pool, scratch_pool)); + + if (operation == svn_wc_operation_merge) + SVN_ERR(svn_wc__db_read_pristine_props(&old_props, db, local_abspath, + scratch_pool, scratch_pool)); + else + old_props = their_old_props; + + /* We currently handle *_conflict as *_full as this argument is currently + always applied for all conflicts on a node at the same time. Giving + an error would break some tests that assumed that this would just + resolve property conflicts to working. + + An alternative way to handle these conflicts would be to just copy all + property state from mine/theirs on the _full option instead of just the + conflicted properties. In some ways this feels like a sensible option as + that would take both properties and text from mine/theirs, but when not + both properties and text are conflicted we would fail in doing so. + */ + switch (conflict_choice) + { + case svn_wc_conflict_choose_base: + resolve_from = their_old_props ? their_old_props : old_props; + break; + case svn_wc_conflict_choose_mine_full: + case svn_wc_conflict_choose_mine_conflict: + resolve_from = mine_props; + break; + case svn_wc_conflict_choose_theirs_full: + case svn_wc_conflict_choose_theirs_conflict: + resolve_from = their_props; + break; + case svn_wc_conflict_choose_merged: + resolve_from = NULL; + break; + default: + return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL, + _("Invalid 'conflict_result' argument")); + } + + if (conflicted_props && apr_hash_count(conflicted_props) && resolve_from) + { + apr_hash_index_t *hi; + apr_hash_t *actual_props; + + SVN_ERR(svn_wc__db_read_props(&actual_props, db, local_abspath, + scratch_pool, scratch_pool)); + + for (hi = apr_hash_first(scratch_pool, conflicted_props); + hi; + hi = apr_hash_next(hi)) + { + const char *propname = svn__apr_hash_index_key(hi); + svn_string_t *new_value = NULL; + + new_value = apr_hash_get(resolve_from, propname, + APR_HASH_KEY_STRING); + + apr_hash_set(actual_props, propname, APR_HASH_KEY_STRING, + new_value); + } + SVN_ERR(svn_wc__db_op_set_props(db, local_abspath, actual_props, + FALSE, NULL, NULL, + scratch_pool)); + } + + /* Legacy behavior: Only report property conflicts as resolved when the + property reject file exists + + If not the UI shows the conflict as already resolved + (and in this case we just remove the in-db conflict) */ + + if (prop_reject_file) + { + SVN_ERR(svn_io_check_path(prop_reject_file, &node_kind, scratch_pool)); + if (node_kind == svn_node_file) + { + svn_skel_t *work_item; + + SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db, + local_abspath, + prop_reject_file, + scratch_pool, scratch_pool)); + *work_items = svn_wc__wq_merge(*work_items, work_item, scratch_pool); + *removed_reject_file = TRUE; + } + } + + return SVN_NO_ERROR; +} + +/* + * Resolve the tree conflict found in DB/LOCAL_ABSPATH/CONFLICTS + * according to CONFLICT_CHOICE. (Don't mark it as resolved.) + * + * ### ... append to *WORK_ITEMS work items to ...? + * + * It is an error if there is no tree conflict. + */ +static svn_error_t * +resolve_tree_conflict_on_node(svn_skel_t **work_items, + svn_wc__db_t *db, + const char *local_abspath, + svn_wc_operation_t operation, + svn_skel_t *conflicts, + svn_wc_conflict_choice_t conflict_choice, + svn_wc_notify_func2_t notify_func, + void *notify_baton, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *scratch_pool) +{ + svn_wc_conflict_reason_t reason; + svn_wc_conflict_action_t action; + svn_boolean_t did_resolve = FALSE; + + SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, &action, NULL, + db, local_abspath, + conflicts, + scratch_pool, scratch_pool)); + + if (operation == svn_wc_operation_update + || operation == svn_wc_operation_switch) + { + if (reason == svn_wc_conflict_reason_deleted || + reason == svn_wc_conflict_reason_replaced) + { + if (conflict_choice == svn_wc_conflict_choose_merged) + { + /* Break moves for any children moved out of this directory, + * and leave this directory deleted. */ + SVN_ERR(svn_wc__db_resolve_break_moved_away_children( + db, local_abspath, notify_func, notify_baton, + scratch_pool)); + did_resolve = TRUE; + } + else if (conflict_choice == svn_wc_conflict_choose_mine_conflict) + { + /* Raised moved-away conflicts on any children moved out of + * this directory, and leave this directory deleted. + * The newly conflicted moved-away children will be updated + * if they are resolved with 'mine_conflict' as well. */ + SVN_ERR(svn_wc__db_resolve_delete_raise_moved_away( + db, local_abspath, notify_func, notify_baton, + scratch_pool)); + did_resolve = TRUE; + } + else + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, + NULL, + _("Tree conflict can only be resolved to " + "'working' or 'mine-conflict' state; " + "'%s' not resolved"), + svn_dirent_local_style(local_abspath, + scratch_pool)); + } + else if (reason == svn_wc_conflict_reason_moved_away + && action == svn_wc_conflict_action_edit) + { + /* After updates, we can resolve local moved-away + * vs. any incoming change, either by updating the + * moved-away node (mine-conflict) or by breaking the + * move (theirs-conflict). */ + if (conflict_choice == svn_wc_conflict_choose_mine_conflict) + { + SVN_ERR(svn_wc__db_update_moved_away_conflict_victim( + db, local_abspath, + notify_func, notify_baton, + cancel_func, cancel_baton, + scratch_pool)); + did_resolve = TRUE; + } + else if (conflict_choice == svn_wc_conflict_choose_merged) + { + /* We must break the move if the user accepts the current + * working copy state instead of updating the move. + * Else the move would be left in an invalid state. */ + + /* ### This breaks the move but leaves the conflict + ### involving the move until + ### svn_wc__db_op_mark_resolved. */ + SVN_ERR(svn_wc__db_resolve_break_moved_away(db, local_abspath, + notify_func, + notify_baton, + scratch_pool)); + did_resolve = TRUE; + } + else + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, + NULL, + _("Tree conflict can only be resolved to " + "'working' or 'mine-conflict' state; " + "'%s' not resolved"), + svn_dirent_local_style(local_abspath, + scratch_pool)); + } + } + + if (! did_resolve && conflict_choice != svn_wc_conflict_choose_merged) + { + /* For other tree conflicts, there is no way to pick + * theirs-full or mine-full, etc. Throw an error if the + * user expects us to be smarter than we really are. */ + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, + NULL, + _("Tree conflict can only be " + "resolved to 'working' state; " + "'%s' not resolved"), + svn_dirent_local_style(local_abspath, + scratch_pool)); + } + + return SVN_NO_ERROR; +} + /* Conflict resolution involves removing the conflict files, if they exist, and clearing the conflict filenames from the entry. The latter needs to be done whether or not the conflict files exist. ### This func combines *resolving* and *marking as resolved* -- seems poor. - ### Resolving is shared between this func and its caller - 'conflict_status_walker()' -- seems poor. - LOCAL_ABSPATH in DB is the path to the item to be resolved. RESOLVE_TEXT, RESOLVE_PROPS and RESOLVE_TREE are TRUE iff text, property and tree conflicts respectively are to be resolved. @@ -2337,7 +2787,6 @@ resolve_conflict_on_node(svn_boolean_t * svn_boolean_t resolve_props, svn_boolean_t resolve_tree, svn_wc_conflict_choice_t conflict_choice, - svn_skel_t *work_items, svn_wc_notify_func2_t notify_func, void *notify_baton, svn_cancel_func_t cancel_func, @@ -2349,8 +2798,7 @@ resolve_conflict_on_node(svn_boolean_t * svn_boolean_t text_conflicted; svn_boolean_t prop_conflicted; svn_boolean_t tree_conflicted; - svn_skel_t *work_item; - apr_pool_t *pool = scratch_pool; + svn_skel_t *work_items = NULL; *did_resolve = FALSE; @@ -2366,318 +2814,28 @@ resolve_conflict_on_node(svn_boolean_t * scratch_pool, scratch_pool)); if (resolve_text && text_conflicted) - { - const char *conflict_old = NULL; - const char *conflict_new = NULL; - const char *conflict_working = NULL; - const char *auto_resolve_src; - svn_node_kind_t node_kind; - - SVN_ERR(svn_wc__conflict_read_text_conflict(&conflict_working, - &conflict_old, - &conflict_new, - db, local_abspath, conflicts, - scratch_pool, scratch_pool)); - - /* Handle automatic conflict resolution before the temporary files are - * deleted, if necessary. */ - switch (conflict_choice) - { - case svn_wc_conflict_choose_base: - auto_resolve_src = conflict_old; - break; - case svn_wc_conflict_choose_mine_full: - auto_resolve_src = conflict_working; - break; - case svn_wc_conflict_choose_theirs_full: - auto_resolve_src = conflict_new; - break; - case svn_wc_conflict_choose_merged: - auto_resolve_src = NULL; - break; - case svn_wc_conflict_choose_theirs_conflict: - case svn_wc_conflict_choose_mine_conflict: - { - if (conflict_old && conflict_working && conflict_new) - { - const char *temp_dir; - svn_stream_t *tmp_stream = NULL; - svn_diff_t *diff; - svn_diff_conflict_display_style_t style = - conflict_choice == svn_wc_conflict_choose_theirs_conflict - ? svn_diff_conflict_display_latest - : svn_diff_conflict_display_modified; - - SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&temp_dir, db, - local_abspath, - pool, pool)); - SVN_ERR(svn_stream_open_unique(&tmp_stream, - &auto_resolve_src, - temp_dir, - svn_io_file_del_on_pool_cleanup, - pool, pool)); - - SVN_ERR(svn_diff_file_diff3_2(&diff, - conflict_old, - conflict_working, - conflict_new, - svn_diff_file_options_create(pool), - pool)); - SVN_ERR(svn_diff_file_output_merge2(tmp_stream, diff, - conflict_old, - conflict_working, - conflict_new, - /* markers ignored */ - NULL, NULL, NULL, NULL, - style, - pool)); - SVN_ERR(svn_stream_close(tmp_stream)); - } - else - auto_resolve_src = NULL; - break; - } - default: - return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL, - _("Invalid 'conflict_result' argument")); - } - - if (auto_resolve_src) - { - SVN_ERR(svn_wc__wq_build_file_copy_translated( - &work_item, db, local_abspath, - auto_resolve_src, local_abspath, pool, pool)); - work_items = svn_wc__wq_merge(work_items, work_item, pool); - - SVN_ERR(svn_wc__wq_build_sync_file_flags(&work_item, db, - local_abspath, - pool, pool)); - work_items = svn_wc__wq_merge(work_items, work_item, pool); - } - - /* Legacy behavior: Only report text conflicts as resolved when at least - one conflict marker file exists. - - If not the UI shows the conflict as already resolved - (and in this case we just remove the in-db conflict) */ - - if (conflict_old) - { - SVN_ERR(svn_io_check_path(conflict_old, &node_kind, pool)); - if (node_kind == svn_node_file) - { - SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db, - local_abspath, - conflict_old, - pool, pool)); - work_items = svn_wc__wq_merge(work_items, work_item, pool); - *did_resolve = TRUE; - } - } - - if (conflict_new) - { - SVN_ERR(svn_io_check_path(conflict_new, &node_kind, pool)); - if (node_kind == svn_node_file) - { - SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db, - local_abspath, - conflict_new, - pool, pool)); - work_items = svn_wc__wq_merge(work_items, work_item, pool); - *did_resolve = TRUE; - } - } - - if (conflict_working) - { - SVN_ERR(svn_io_check_path(conflict_working, &node_kind, pool)); - if (node_kind == svn_node_file) - { - SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db, - local_abspath, - conflict_working, - pool, pool)); - work_items = svn_wc__wq_merge(work_items, work_item, pool); - *did_resolve = TRUE; - } - } - } + SVN_ERR(resolve_text_conflict_on_node(did_resolve, &work_items, + db, local_abspath, + operation, conflicts, + conflict_choice, + scratch_pool)); if (resolve_props && prop_conflicted) - { - svn_node_kind_t node_kind; - const char *prop_reject_file; - apr_hash_t *mine_props; - apr_hash_t *their_old_props; - apr_hash_t *their_props; - apr_hash_t *conflicted_props; - apr_hash_t *old_props; - apr_hash_t *resolve_from = NULL; - - SVN_ERR(svn_wc__conflict_read_prop_conflict(&prop_reject_file, - &mine_props, &their_old_props, - &their_props, &conflicted_props, - db, local_abspath, conflicts, - scratch_pool, scratch_pool)); - - if (operation == svn_wc_operation_merge) - SVN_ERR(svn_wc__db_read_pristine_props(&old_props, db, local_abspath, - scratch_pool, scratch_pool)); - else - old_props = their_old_props; - - /* We currently handle *_conflict as *_full as this argument is currently - always applied for all conflicts on a node at the same time. Giving - an error would break some tests that assumed that this would just - resolve property conflicts to working. - - An alternative way to handle these conflicts would be to just copy all - property state from mine/theirs on the _full option instead of just the - conflicted properties. In some ways this feels like a sensible option as - that would take both properties and text from mine/theirs, but when not - both properties and text are conflicted we would fail in doing so. - */ - switch (conflict_choice) - { - case svn_wc_conflict_choose_base: - resolve_from = their_old_props ? their_old_props : old_props; - break; - case svn_wc_conflict_choose_mine_full: - case svn_wc_conflict_choose_mine_conflict: - resolve_from = mine_props; - break; - case svn_wc_conflict_choose_theirs_full: - case svn_wc_conflict_choose_theirs_conflict: - resolve_from = their_props; - break; - case svn_wc_conflict_choose_merged: - resolve_from = NULL; - break; - default: - return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL, - _("Invalid 'conflict_result' argument")); - } - - if (conflicted_props && apr_hash_count(conflicted_props) && resolve_from) - { - apr_hash_index_t *hi; - apr_hash_t *actual_props; - - SVN_ERR(svn_wc__db_read_props(&actual_props, db, local_abspath, - scratch_pool, scratch_pool)); - - for (hi = apr_hash_first(scratch_pool, conflicted_props); - hi; - hi = apr_hash_next(hi)) - { - const char *propname = svn__apr_hash_index_key(hi); - svn_string_t *new_value = NULL; - - new_value = apr_hash_get(resolve_from, propname, - APR_HASH_KEY_STRING); - - apr_hash_set(actual_props, propname, APR_HASH_KEY_STRING, - new_value); - } - SVN_ERR(svn_wc__db_op_set_props(db, local_abspath, actual_props, - FALSE, NULL, NULL, + SVN_ERR(resolve_prop_conflict_on_node(did_resolve, &work_items, + db, local_abspath, + operation, conflicts, + conflict_choice, scratch_pool)); - } - - /* Legacy behavior: Only report property conflicts as resolved when the - property reject file exists - - If not the UI shows the conflict as already resolved - (and in this case we just remove the in-db conflict) */ - - if (prop_reject_file) - { - SVN_ERR(svn_io_check_path(prop_reject_file, &node_kind, pool)); - if (node_kind == svn_node_file) - { - SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db, - local_abspath, - prop_reject_file, - pool, pool)); - work_items = svn_wc__wq_merge(work_items, work_item, pool); - *did_resolve = TRUE; - } - } - } if (resolve_tree) { - svn_wc_conflict_reason_t reason; - svn_wc_conflict_action_t action; - - SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, &action, NULL, - db, local_abspath, - conflicts, - scratch_pool, scratch_pool)); - - if (operation == svn_wc_operation_update - || operation == svn_wc_operation_switch) - { - if (reason == svn_wc_conflict_reason_deleted) - { - if (conflict_choice == svn_wc_conflict_choose_merged) - { - SVN_ERR(svn_wc__db_resolve_delete_raise_moved_away( - db, local_abspath, scratch_pool)); - *did_resolve = TRUE; - } - } - else if (reason == svn_wc_conflict_reason_moved_away - && action == svn_wc_conflict_action_edit) - { - /* After updates, we can resolve local moved-away - * vs. any incoming change, either by updating the - * moved-away node (mine-conflict) or by breaking the - * move (theirs-conflict). */ - if (conflict_choice == svn_wc_conflict_choose_mine_conflict) - { - SVN_ERR(svn_wc__db_update_moved_away_conflict_victim( - &work_items, - db, local_abspath, - notify_func, notify_baton, - cancel_func, cancel_baton, - scratch_pool, scratch_pool)); - *did_resolve = TRUE; - } - else if (conflict_choice == svn_wc_conflict_choose_theirs_conflict - || conflict_choice == svn_wc_conflict_choose_merged) - { - /* We must break the move even if the user accepts - * the current working copy state (choose_merged) - * instead of updating the move. Else the move would - * be left in an invalid state. */ - - /* ### This breaks the move but leaves the conflict - ### involving the move until - ### svn_wc__db_op_mark_resolved. */ - SVN_ERR(svn_wc__db_resolve_break_moved_away(db, local_abspath, - scratch_pool)); - *did_resolve = TRUE; - } - } - } - - if (*did_resolve == FALSE && - conflict_choice != svn_wc_conflict_choose_merged) - { - /* For other tree conflicts, there is no way to pick - * theirs-full or mine-full, etc. Throw an error if the - * user expects us to be smarter than we really are. */ - return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, - NULL, - _("Tree conflict can only be " - "resolved to 'working' state; " - "'%s' not resolved"), - svn_dirent_local_style(local_abspath, - scratch_pool)); - } - + SVN_ERR(resolve_tree_conflict_on_node(&work_items, + db, local_abspath, + operation, conflicts, + conflict_choice, + notify_func, notify_baton, + cancel_func, cancel_baton, + scratch_pool)); *did_resolve = TRUE; } @@ -2685,12 +2843,13 @@ resolve_conflict_on_node(svn_boolean_t * { SVN_ERR(svn_wc__db_op_mark_resolved(db, local_abspath, resolve_text, resolve_props, - resolve_tree, work_items, pool)); + resolve_tree, work_items, + scratch_pool)); /* Run the work queue to remove conflict marker files. */ SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton, - pool)); + scratch_pool)); } return SVN_NO_ERROR; @@ -2711,7 +2870,6 @@ svn_wc__mark_resolved_text_conflict(svn_ FALSE /* resolve_props */, FALSE /* resolve_tree */, svn_wc_conflict_choose_merged, - NULL, NULL, NULL, /* notify_func */ NULL, NULL, /* cancel_func */ scratch_pool)); @@ -2731,7 +2889,6 @@ svn_wc__mark_resolved_prop_conflicts(svn TRUE /* resolve_props */, FALSE /* resolve_tree */, svn_wc_conflict_choose_merged, - NULL /* work_items */, NULL, NULL, /* notify_func */ NULL, NULL, /* cancel_func */ scratch_pool)); @@ -2754,7 +2911,10 @@ struct conflict_status_walker_baton void *notify_baton; }; -/* Implements svn_wc_status4_t to walk all conflicts to resolve */ +/* Implements svn_wc_status4_t to walk all conflicts to resolve. + * + * ### Bug: ignores the resolver callback's 'result->merged_file' output. + */ static svn_error_t * conflict_status_walker(void *baton, const char *local_abspath, @@ -2782,8 +2942,6 @@ conflict_status_walker(void *baton, const svn_wc_conflict_description2_t *cd; svn_boolean_t did_resolve; svn_wc_conflict_choice_t my_choice = cswb->conflict_choice; - svn_skel_t *work_items = NULL; - cd = APR_ARRAY_IDX(conflicts, i, const svn_wc_conflict_description2_t *); @@ -2802,6 +2960,7 @@ conflict_status_walker(void *baton, iterpool, iterpool)); my_choice = result->choice; + /* ### Bug: ignores result->merged_file (and ->save_merged) */ } @@ -2820,7 +2979,6 @@ conflict_status_walker(void *baton, FALSE /* resolve_props */, TRUE /* resolve_tree */, my_choice, - work_items, cswb->notify_func, cswb->notify_baton, cswb->cancel_func, @@ -2841,7 +2999,6 @@ conflict_status_walker(void *baton, FALSE /* resolve_props */, FALSE /* resolve_tree */, my_choice, - NULL, cswb->notify_func, cswb->notify_baton, cswb->cancel_func, @@ -2873,7 +3030,6 @@ conflict_status_walker(void *baton, TRUE /* resolve_props */, FALSE /* resolve_tree */, my_choice, - NULL, cswb->notify_func, cswb->notify_baton, cswb->cancel_func, Modified: subversion/branches/fsfs-format7/subversion/libsvn_wc/conflicts.h URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_wc/conflicts.h?rev=1453290&r1=1453289&r2=1453290&view=diff ============================================================================== --- subversion/branches/fsfs-format7/subversion/libsvn_wc/conflicts.h (original) +++ subversion/branches/fsfs-format7/subversion/libsvn_wc/conflicts.h Wed Mar 6 11:10:01 2013 @@ -163,6 +163,8 @@ svn_wc__conflict_skel_add_text_conflict( The DB, WRI_ABSPATH pair specifies in which working copy the conflict will be recorded. (Needed for making the paths relative). + The MARKER_ABSPATH is NULL when raising a conflict in v1.8+. See below. + The MINE_PROPS, THEIR_OLD_PROPS and THEIR_PROPS are hashes mapping a const char * property name to a const svn_string_t* value. @@ -174,8 +176,14 @@ svn_wc__conflict_skel_add_text_conflict( ### Maybe useful for calling (legacy) conflict resolvers that expect one ### property conflict per invocation. - It is an error to add another text conflict to a conflict skel that - already contains a text conflict. + When raising a property conflict in the course of upgrading an old WC, + MARKER_ABSPATH is the path to the file containing a human-readable + description of the conflict, MINE_PROPS and THEIR_OLD_PROPS and + THEIR_PROPS are all NULL, and CONFLICTED_PROP_NAMES is an empty hash. + + It is an error to add another prop conflict to a conflict skel that + already contains a prop conflict. (A single call to this function can + record that multiple properties are in conflict.) Do temporary allocations in SCRATCH_POOL. */ @@ -198,9 +206,6 @@ svn_wc__conflict_skel_add_prop_conflict( LOCAL_CHANGE is the local tree change made to the node. INCOMING_CHANGE is the incoming change made to the node. - It is an error to add another tree conflict to a conflict skel that - already contains a tree conflict. - MOVE_SRC_OP_ROOT_ABSPATH must be set when LOCAL_CHANGE is svn_wc_conflict_reason_moved_away and NULL otherwise and the operation is svn_wc_operation_update or svn_wc_operation_switch. It should be @@ -215,7 +220,9 @@ svn_wc__conflict_skel_add_prop_conflict( with (1), MOVE_SRC_OP_ROOT_ABSPATH should be A/B for a conflict associated with (2). - ### Is it an error to add a tree conflict to any existing conflict? + It is an error to add another tree conflict to a conflict skel that + already contains a tree conflict. (It is not an error, at this level, + to add a tree conflict to an existing text or property conflict skel.) Do temporary allocations in SCRATCH_POOL. */ Modified: subversion/branches/fsfs-format7/subversion/libsvn_wc/copy.c URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_wc/copy.c?rev=1453290&r1=1453289&r2=1453290&view=diff ============================================================================== --- subversion/branches/fsfs-format7/subversion/libsvn_wc/copy.c (original) +++ subversion/branches/fsfs-format7/subversion/libsvn_wc/copy.c Wed Mar 6 11:10:01 2013 @@ -429,7 +429,7 @@ copy_versioned_dir(svn_wc__db_t *db, copy as much as possible, or give up early? */ return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL, _("Cannot handle status of '%s'"), - svn_dirent_local_style(src_abspath, + svn_dirent_local_style(child_src_abspath, iterpool)); } else @@ -438,7 +438,7 @@ copy_versioned_dir(svn_wc__db_t *db, return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL, _("Cannot copy '%s' excluded by server"), - svn_dirent_local_style(src_abspath, + svn_dirent_local_style(child_src_abspath, iterpool)); } @@ -531,6 +531,7 @@ copy_or_move(svn_boolean_t *move_degrade const char *src_wcroot_abspath; const char *dst_wcroot_abspath; svn_boolean_t within_one_wc; + svn_wc__db_status_t src_status; svn_error_t *err; SVN_ERR_ASSERT(svn_dirent_is_absolute(src_abspath)); @@ -541,15 +542,17 @@ copy_or_move(svn_boolean_t *move_degrade /* Ensure DSTDIR_ABSPATH belongs to the same repository as SRC_ABSPATH; throw an error if not. */ { - svn_wc__db_status_t src_status, dstdir_status; + svn_wc__db_status_t dstdir_status; const char *src_repos_root_url, *dst_repos_root_url; const char *src_repos_uuid, *dst_repos_uuid; + const char *src_repos_relpath; - err = svn_wc__db_read_info(&src_status, &src_db_kind, NULL, NULL, - &src_repos_root_url, &src_repos_uuid, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, &conflicted, - NULL, NULL, NULL, NULL, NULL, NULL, + 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, &conflicted, NULL, NULL, NULL, NULL, + NULL, NULL, db, src_abspath, scratch_pool, scratch_pool); if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) @@ -587,6 +590,23 @@ copy_or_move(svn_boolean_t *move_degrade break; } + if (is_move && ! strcmp(src_abspath, src_wcroot_abspath)) + { + return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL, + _("'%s' is the root of a working copy and " + "cannot be moved"), + svn_dirent_local_style(src_abspath, + scratch_pool)); + } + if (is_move && src_repos_relpath && !src_repos_relpath[0]) + { + return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL, + _("'%s' represents the repository root " + "and cannot be moved"), + svn_dirent_local_style(src_abspath, + scratch_pool)); + } + err = svn_wc__db_read_info(&dstdir_status, NULL, NULL, NULL, &dst_repos_root_url, &dst_repos_uuid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -618,7 +638,7 @@ copy_or_move(svn_boolean_t *move_degrade SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, NULL, &src_repos_root_url, &src_repos_uuid, NULL, NULL, NULL, - NULL, NULL, NULL, + NULL, db, src_abspath, scratch_pool, scratch_pool)); else @@ -635,7 +655,7 @@ copy_or_move(svn_boolean_t *move_degrade SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, NULL, &dst_repos_root_url, &dst_repos_uuid, NULL, NULL, NULL, - NULL, NULL, NULL, + NULL, db, dstdir_abspath, scratch_pool, scratch_pool)); else @@ -728,13 +748,13 @@ copy_or_move(svn_boolean_t *move_degrade within_one_wc = (strcmp(src_wcroot_abspath, dst_wcroot_abspath) == 0); - if (move_degraded_to_copy != NULL) + if (is_move + && !within_one_wc) { - /* Cross-WC moves cannot be tracked. - * Degrade such moves to a copy+delete. */ - *move_degraded_to_copy = (is_move && !within_one_wc); - if (*move_degraded_to_copy) - is_move = FALSE; + if (move_degraded_to_copy) + *move_degraded_to_copy = TRUE; + + is_move = FALSE; } if (!within_one_wc) @@ -754,7 +774,8 @@ copy_or_move(svn_boolean_t *move_degrade } else { - if (is_move && !allow_mixed_revisions) + if (is_move + && src_status == svn_wc__db_status_normal) { svn_revnum_t min_rev; svn_revnum_t max_rev; @@ -764,12 +785,20 @@ copy_or_move(svn_boolean_t *move_degrade src_abspath, FALSE, scratch_pool)); if (SVN_IS_VALID_REVNUM(min_rev) && SVN_IS_VALID_REVNUM(max_rev) && min_rev != max_rev) - return svn_error_createf(SVN_ERR_WC_MIXED_REVISIONS, NULL, - _("Cannot move mixed-revision subtree '%s' " - "[%ld:%ld]; try updating it first"), - svn_dirent_local_style(src_abspath, - scratch_pool), - min_rev, max_rev); + { + if (!allow_mixed_revisions) + return svn_error_createf(SVN_ERR_WC_MIXED_REVISIONS, NULL, + _("Cannot move mixed-revision " + "subtree '%s' [%ld:%ld]; " + "try updating it first"), + svn_dirent_local_style(src_abspath, + scratch_pool), + min_rev, max_rev); + + is_move = FALSE; + if (move_degraded_to_copy) + *move_degraded_to_copy = TRUE; + } } err = copy_versioned_dir(db, src_abspath, dst_abspath, dst_abspath, @@ -782,6 +811,13 @@ copy_or_move(svn_boolean_t *move_degrade if (err && svn_error_find_cause(err, SVN_ERR_CANCELLED)) return svn_error_trace(err); + if (is_move) + err = svn_error_compose_create(err, + svn_wc__db_op_handle_move_back(NULL, + db, dst_abspath, src_abspath, + NULL /* work_items */, + scratch_pool)); + /* Run the work queue with the remaining work */ SVN_ERR(svn_error_compose_create( err, @@ -836,7 +872,7 @@ remove_node_conflict_markers(svn_wc__db_ svn_skel_t *conflict; SVN_ERR(svn_wc__db_read_conflict(&conflict, db, src_abspath, - scratch_pool, scratch_pool)); + scratch_pool, scratch_pool)); /* Do we have conflict markers that should be removed? */ if (conflict != NULL) @@ -947,6 +983,8 @@ svn_wc__move2(svn_wc_context_t *wc_ctx, { svn_wc__db_t *db = wc_ctx->db; svn_boolean_t move_degraded_to_copy = FALSE; + svn_kind_t kind; + svn_boolean_t conflicted; /* Verify that we have the required write locks. */ SVN_ERR(svn_wc__write_check(wc_ctx->db, @@ -965,7 +1003,7 @@ svn_wc__move2(svn_wc_context_t *wc_ctx, notify_func, notify_baton, scratch_pool)); - /* An iterrupt at this point will leave the new copy marked as + /* An interrupt at this point will leave the new copy marked as moved-here but the source has not yet been deleted or marked as moved-to. */ @@ -982,32 +1020,29 @@ svn_wc__move2(svn_wc_context_t *wc_ctx, if (!metadata_only) SVN_ERR(svn_io_file_rename(src_abspath, dst_abspath, scratch_pool)); - { - svn_kind_t kind; - svn_boolean_t conflicted; + SVN_ERR(svn_wc__db_read_info(NULL, &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, src_abspath, + scratch_pool, scratch_pool)); - SVN_ERR(svn_wc__db_read_info(NULL, &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, src_abspath, - scratch_pool, scratch_pool)); - - if (kind == svn_kind_dir) - SVN_ERR(remove_all_conflict_markers(db, src_abspath, dst_abspath, - scratch_pool)); - - if (conflicted) - SVN_ERR(remove_node_conflict_markers(db, src_abspath, dst_abspath, - scratch_pool)); - } + if (kind == svn_kind_dir) + SVN_ERR(remove_all_conflict_markers(db, src_abspath, dst_abspath, + scratch_pool)); - SVN_ERR(svn_wc__delete_internal(wc_ctx, src_abspath, TRUE, FALSE, - move_degraded_to_copy ? NULL : dst_abspath, - cancel_func, cancel_baton, - notify_func, notify_baton, - scratch_pool)); + if (conflicted) + SVN_ERR(remove_node_conflict_markers(db, src_abspath, dst_abspath, + scratch_pool)); + + SVN_ERR(svn_wc__db_op_delete(db, src_abspath, + move_degraded_to_copy ? NULL : dst_abspath, + TRUE /* delete_dir_externals */, + NULL /* conflict */, NULL /* work_items */, + cancel_func, cancel_baton, + notify_func, notify_baton, + scratch_pool)); return SVN_NO_ERROR; } Modified: subversion/branches/fsfs-format7/subversion/libsvn_wc/delete.c URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_wc/delete.c?rev=1453290&r1=1453289&r2=1453290&view=diff ============================================================================== --- subversion/branches/fsfs-format7/subversion/libsvn_wc/delete.c (original) +++ subversion/branches/fsfs-format7/subversion/libsvn_wc/delete.c Wed Mar 6 11:10:01 2013 @@ -198,13 +198,15 @@ svn_wc__delete_many(svn_wc_context_t *wc for (i = 0; i < targets->nelts; i++) { svn_boolean_t conflicted = FALSE; + const char *repos_relpath; svn_pool_clear(iterpool); local_abspath = APR_ARRAY_IDX(targets, i, const char *); - 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, &conflicted, + err = svn_wc__db_read_info(&status, &kind, NULL, &repos_relpath, 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, iterpool, iterpool); @@ -255,6 +257,12 @@ svn_wc__delete_many(svn_wc_context_t *wc svn_dirent_local_style(local_abspath, iterpool)); } + if (repos_relpath && !repos_relpath[0]) + return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL, + _("'%s' represents the repository root " + "and cannot be deleted"), + svn_dirent_local_style(local_abspath, + iterpool)); /* Verify if we have a write lock on the parent of this node as we might be changing the childlist of that directory. */ @@ -301,16 +309,15 @@ svn_wc__delete_many(svn_wc_context_t *wc } svn_error_t * -svn_wc__delete_internal(svn_wc_context_t *wc_ctx, - const char *local_abspath, - svn_boolean_t keep_local, - svn_boolean_t delete_unversioned_target, - const char *moved_to_abspath, - svn_cancel_func_t cancel_func, - void *cancel_baton, - svn_wc_notify_func2_t notify_func, - void *notify_baton, - apr_pool_t *scratch_pool) +svn_wc_delete4(svn_wc_context_t *wc_ctx, + const char *local_abspath, + svn_boolean_t keep_local, + svn_boolean_t delete_unversioned_target, + svn_cancel_func_t cancel_func, + void *cancel_baton, + svn_wc_notify_func2_t notify_func, + void *notify_baton, + apr_pool_t *scratch_pool) { apr_pool_t *pool = scratch_pool; svn_wc__db_t *db = wc_ctx->db; @@ -319,10 +326,11 @@ svn_wc__delete_internal(svn_wc_context_t svn_kind_t kind; svn_boolean_t conflicted; svn_skel_t *work_items = NULL; + const char *repos_relpath; - err = svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL, + err = svn_wc__db_read_info(&status, &kind, NULL, &repos_relpath, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, &conflicted, + NULL, NULL, NULL, NULL, NULL, NULL, &conflicted, NULL, NULL, NULL, NULL, NULL, NULL, db, local_abspath, pool, pool); @@ -366,6 +374,11 @@ svn_wc__delete_internal(svn_wc_context_t "cannot be deleted"), svn_dirent_local_style(local_abspath, pool)); } + if (repos_relpath && !repos_relpath[0]) + return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL, + _("'%s' represents the repository root " + "and cannot be deleted"), + svn_dirent_local_style(local_abspath, pool)); /* Verify if we have a write lock on the parent of this node as we might be changing the childlist of that directory. */ @@ -380,7 +393,8 @@ svn_wc__delete_internal(svn_wc_context_t scratch_pool, scratch_pool)); } - SVN_ERR(svn_wc__db_op_delete(db, local_abspath, moved_to_abspath, + SVN_ERR(svn_wc__db_op_delete(db, local_abspath, + NULL /*moved_to_abspath */, !keep_local /* delete_dir_externals */, NULL, work_items, cancel_func, cancel_baton, @@ -395,26 +409,6 @@ svn_wc__delete_internal(svn_wc_context_t } svn_error_t * -svn_wc_delete4(svn_wc_context_t *wc_ctx, - const char *local_abspath, - svn_boolean_t keep_local, - svn_boolean_t delete_unversioned_target, - svn_cancel_func_t cancel_func, - void *cancel_baton, - svn_wc_notify_func2_t notify_func, - void *notify_baton, - apr_pool_t *scratch_pool) -{ - return svn_error_trace(svn_wc__delete_internal(wc_ctx, local_abspath, - keep_local, - delete_unversioned_target, - NULL, - cancel_func, cancel_baton, - notify_func, notify_baton, - scratch_pool)); -} - -svn_error_t * svn_wc__internal_remove_from_revision_control(svn_wc__db_t *db, const char *local_abspath, svn_boolean_t destroy_wf, Modified: subversion/branches/fsfs-format7/subversion/libsvn_wc/deprecated.c URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_wc/deprecated.c?rev=1453290&r1=1453289&r2=1453290&view=diff ============================================================================== --- subversion/branches/fsfs-format7/subversion/libsvn_wc/deprecated.c (original) +++ subversion/branches/fsfs-format7/subversion/libsvn_wc/deprecated.c Wed Mar 6 11:10:01 2013 @@ -974,6 +974,7 @@ svn_wc_add3(const char *path, SVN_ERR(svn_wc__db_read_kind(&kind, wc_db, local_abspath, FALSE /* allow_missing */, + TRUE /* show_deleted */, FALSE /* show_hidden */, pool)); if (kind == svn_kind_dir) { @@ -4565,3 +4566,27 @@ svn_wc_move(svn_wc_context_t *wc_ctx, notify_func, notify_baton, scratch_pool)); } + +svn_error_t * +svn_wc_read_kind(svn_node_kind_t *kind, + svn_wc_context_t *wc_ctx, + const char *abspath, + svn_boolean_t show_hidden, + apr_pool_t *scratch_pool) +{ + return svn_error_trace( + svn_wc_read_kind2(kind, + wc_ctx, abspath, + TRUE /* show_deleted */, + show_hidden, + scratch_pool)); + + /*if (db_kind == svn_kind_dir) + *kind = svn_node_dir; + else if (db_kind == svn_kind_file || db_kind == svn_kind_symlink) + *kind = svn_node_file; + else + *kind = svn_node_none;*/ + + return SVN_NO_ERROR; +}