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 5A1B410A72 for ; Thu, 12 Feb 2015 12:21:36 +0000 (UTC) Received: (qmail 53213 invoked by uid 500); 12 Feb 2015 12:21:36 -0000 Delivered-To: apmail-subversion-commits-archive@subversion.apache.org Received: (qmail 53181 invoked by uid 500); 12 Feb 2015 12:21:36 -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 52932 invoked by uid 99); 12 Feb 2015 12:21:36 -0000 Received: from eris.apache.org (HELO hades.apache.org) (140.211.11.105) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 12 Feb 2015 12:21:36 +0000 Received: from hades.apache.org (localhost [127.0.0.1]) by hades.apache.org (ASF Mail Server at hades.apache.org) with ESMTP id C4A20AC0308 for ; Thu, 12 Feb 2015 12:21:35 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1659238 [3/21] - in /subversion/branches/fsx-1.10: ./ build/generator/ build/generator/templates/ subversion/bindings/swig/ subversion/include/ subversion/include/private/ subversion/libsvn_delta/ subversion/libsvn_fs_base/ subversion/libs... Date: Thu, 12 Feb 2015 12:21:32 -0000 To: commits@subversion.apache.org From: stefan2@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20150212122135.C4A20AC0308@hades.apache.org> Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/conflicts.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/conflicts.c?rev=1659238&r1=1659237&r2=1659238&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_wc/conflicts.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_wc/conflicts.c Thu Feb 12 12:21:31 2015 @@ -1469,144 +1469,46 @@ merge_showing_conflicts(const char **cho return SVN_NO_ERROR; } -/* Resolve the text conflict on DB/LOCAL_ABSPATH in the manner specified - * by CHOICE. - * - * Set *WORK_ITEMS to new work items that will make the on-disk changes - * needed to complete the resolution (but not to mark it as resolved). - * Set *IS_RESOLVED to true if the conflicts are resolved; otherwise - * (which is only if CHOICE is 'postpone') to false. +/* Prepare to delete an artifact file at ARTIFACT_FILE_ABSPATH in the + * working copy at DB/WRI_ABSPATH. * - * LEFT_ABSPATH, RIGHT_ABSPATH, and DETRANSLATED_TARGET are the - * input files to the 3-way merge that will be performed if CHOICE is - * 'theirs-conflict' or 'mine-conflict'. LEFT_ABSPATH is also the file - * that will be used if CHOICE is 'base', and RIGHT_ABSPATH if CHOICE is - * 'theirs-full'. MERGED_ABSPATH will be used if CHOICE is 'merged'. - * - * DETRANSLATED_TARGET is the detranslated version of 'mine' (see - * detranslate_wc_file() above). MERGE_OPTIONS are passed to the - * diff3 implementation in case a 3-way merge has to be carried out. + * Set *WORK_ITEMS to a new work item that, when run, will delete the + * artifact file; or to NULL if there is no file to delete. * - * ### This is redundantly similar to resolve_text_conflict_on_node(). + * Set *FILE_FOUND to TRUE if the artifact file is found on disk and its + * node kind is 'file'; otherwise do not change *FILE_FOUND. FILE_FOUND + * may be NULL if not required. */ static svn_error_t * -eval_text_conflict_func_result(svn_skel_t **work_items, - svn_boolean_t *is_resolved, +remove_artifact_file_if_exists(svn_skel_t **work_items, + svn_boolean_t *file_found, svn_wc__db_t *db, - const char *local_abspath, - svn_wc_conflict_choice_t choice, - const apr_array_header_t *merge_options, - const char *left_abspath, - const char *right_abspath, - const char *merged_file, - const char *detranslated_target, - svn_cancel_func_t cancel_func, - void *cancel_baton, + const char *wri_abspath, + const char *artifact_file_abspath, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - const char *install_from_abspath = NULL; - svn_boolean_t remove_source = FALSE; - *work_items = NULL; - - switch (choice) + if (artifact_file_abspath) { - /* If the callback wants to use one of the fulltexts - to resolve the conflict, so be it.*/ - case svn_wc_conflict_choose_base: - { - install_from_abspath = left_abspath; - *is_resolved = TRUE; - break; - } - case svn_wc_conflict_choose_theirs_full: - { - install_from_abspath = right_abspath; - *is_resolved = TRUE; - break; - } - case svn_wc_conflict_choose_mine_full: - { - install_from_abspath = detranslated_target; - *is_resolved = TRUE; - break; - } - case svn_wc_conflict_choose_theirs_conflict: - case svn_wc_conflict_choose_mine_conflict: - { - svn_diff_conflict_display_style_t style - = choice == svn_wc_conflict_choose_theirs_conflict - ? svn_diff_conflict_display_latest - : svn_diff_conflict_display_modified; - - SVN_ERR(merge_showing_conflicts(&install_from_abspath, - db, local_abspath, - style, merge_options, - left_abspath, - detranslated_target, - right_abspath, - /* ### why not same as other caller? */ - svn_io_file_del_none, - cancel_func, cancel_baton, - scratch_pool, scratch_pool)); - remove_source = TRUE; - *is_resolved = TRUE; - break; - } + svn_node_kind_t node_kind; - /* For the case of 3-way file merging, we don't - really distinguish between these return values; - if the callback claims to have "generally - resolved" the situation, we still interpret - that as "OK, we'll assume the merged version is - good to use". */ - case svn_wc_conflict_choose_merged: - { - install_from_abspath = merged_file; - *is_resolved = TRUE; - break; - } - case svn_wc_conflict_choose_postpone: - default: + SVN_ERR(svn_io_check_path(artifact_file_abspath, &node_kind, + scratch_pool)); + if (node_kind == svn_node_file) { - /* Assume conflict remains. */ - *is_resolved = FALSE; - return SVN_NO_ERROR; + SVN_ERR(svn_wc__wq_build_file_remove(work_items, + db, wri_abspath, + artifact_file_abspath, + result_pool, scratch_pool)); + if (file_found) + *file_found = TRUE; } } - SVN_ERR_ASSERT(install_from_abspath != NULL); - - { - svn_skel_t *work_item; - - SVN_ERR(svn_wc__wq_build_file_install(&work_item, - db, local_abspath, - install_from_abspath, - FALSE /* use_commit_times */, - FALSE /* record_fileinfo */, - result_pool, scratch_pool)); - *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool); - - SVN_ERR(svn_wc__wq_build_sync_file_flags(&work_item, db, local_abspath, - result_pool, scratch_pool)); - *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool); - - if (remove_source) - { - SVN_ERR(svn_wc__wq_build_file_remove(&work_item, - db, local_abspath, - install_from_abspath, - result_pool, scratch_pool)); - *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool); - } - } - return SVN_NO_ERROR; } - /* Create a new file in the same directory as LOCAL_ABSPATH, with the same basename as LOCAL_ABSPATH, with a ".edited" extension, and set *WORK_ITEM to a new work item that will copy and translate from the file @@ -1649,89 +1551,168 @@ save_merge_result(svn_skel_t **work_item } -/* Call the conflict resolver callback for a text conflict, and resolve - * the conflict if the callback tells us to do so. (Do not mark the - * conflict as resolved.) - * - * Assume that there is a text conflict on the path DB/LOCAL_ABSPATH, - * and CDESC is the conflict description. - * - * Call CONFLICT_FUNC with CONFLICT_BATON to find out whether and how - * it wants to resolve the conflict. - * - * If the callback returns a resolution other than 'postpone', then - * perform that requested resolution and prepare to mark the conflict - * as resolved ... ?? by adding work items to *WORK_ITEMS ??. - * - * MERGE_OPTIONS is used if the resolver callback requests a merge. - * - * Return *WORK_ITEMS that will do the on-disk work required to complete - * the resolution (but not to mark the conflict as resolved), and set - * *WAS_RESOLVED to true, if it was resolved. Set *WORK_ITEMS to NULL - * and *WAS_RESOLVED to FALSE otherwise. + +/* Resolve the text conflict in CONFLICT, which is currently recorded + * on DB/LOCAL_ABSPATH in the manner specified by CHOICE. + * + * Set *WORK_ITEMS to new work items that will make the on-disk changes + * needed to complete the resolution (but not to mark it as resolved). + * + * Set *FOUND_ARTIFACT to true if conflict markers are removed; otherwise + * (which is only if CHOICE is 'postpone') to false. + * + * CHOICE, MERGED_FILE and SAVE_MERGED are typically values provided by + * the conflict resolver. + * + * MERGE_OPTIONS allows customizing the diff handling when using + * per hunk conflict resolving. */ static svn_error_t * -resolve_text_conflict(svn_skel_t **work_items, - svn_boolean_t *was_resolved, - svn_wc__db_t *db, - const char *local_abspath, - svn_wc_conflict_description2_t *cdesc, - const apr_array_header_t *merge_options, - 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, - apr_pool_t *scratch_pool) +build_text_conflict_resolve_items(svn_skel_t **work_items, + svn_boolean_t *found_artifact, + svn_wc__db_t *db, + const char *local_abspath, + const svn_skel_t *conflict, + svn_wc_conflict_choice_t choice, + const char *merged_file, + svn_boolean_t save_merged, + const apr_array_header_t *merge_options, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - svn_wc_conflict_result_t *result; + const char *mine_abspath; + const char *their_old_abspath; + const char *their_abspath; svn_skel_t *work_item; + const char *install_from_abspath = NULL; + svn_boolean_t remove_source = FALSE; *work_items = NULL; - *was_resolved = FALSE; - /* Give the conflict resolution callback a chance to clean - up the conflicts before we mark the file 'conflicted' */ + if (found_artifact) + *found_artifact = FALSE; - SVN_ERR(conflict_func(&result, cdesc, conflict_baton, scratch_pool, - scratch_pool)); - if (result == NULL) - return svn_error_create(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, - _("Conflict callback violated API:" - " returned no results")); - - if (result->save_merged) - { - SVN_ERR(save_merge_result(work_items, - db, local_abspath, - /* Look for callback's own - merged-file first: */ - result->merged_file - ? result->merged_file - : cdesc->merged_file, - result_pool, scratch_pool)); - } + SVN_ERR(svn_wc__conflict_read_text_conflict(&mine_abspath, + &their_old_abspath, + &their_abspath, + db, local_abspath, + conflict, + scratch_pool, scratch_pool)); + + if (save_merged) + SVN_ERR(save_merge_result(work_items, + db, local_abspath, + merged_file + ? merged_file + : local_abspath, + result_pool, scratch_pool)); - if (result->choice != svn_wc_conflict_choose_postpone) + if (choice == svn_wc_conflict_choose_postpone) + return SVN_NO_ERROR; + + switch (choice) { - SVN_ERR(eval_text_conflict_func_result(&work_item, - was_resolved, - db, local_abspath, - result->choice, - merge_options, - cdesc->base_abspath, - cdesc->their_abspath, - /* ### Sure this is an abspath? */ - result->merged_file - ? result->merged_file - : cdesc->merged_file, - cdesc->my_abspath, - cancel_func, cancel_baton, - result_pool, scratch_pool)); + /* If the callback wants to use one of the fulltexts + to resolve the conflict, so be it.*/ + case svn_wc_conflict_choose_base: + { + install_from_abspath = their_old_abspath; + break; + } + case svn_wc_conflict_choose_theirs_full: + { + install_from_abspath = their_abspath; + break; + } + case svn_wc_conflict_choose_mine_full: + { + install_from_abspath = mine_abspath; + break; + } + case svn_wc_conflict_choose_theirs_conflict: + case svn_wc_conflict_choose_mine_conflict: + { + svn_diff_conflict_display_style_t style + = choice == svn_wc_conflict_choose_theirs_conflict + ? svn_diff_conflict_display_latest + : svn_diff_conflict_display_modified; + + SVN_ERR(merge_showing_conflicts(&install_from_abspath, + db, local_abspath, + style, merge_options, + their_old_abspath, + mine_abspath, + their_abspath, + /* ### why not same as other caller? */ + svn_io_file_del_none, + cancel_func, cancel_baton, + scratch_pool, scratch_pool)); + remove_source = TRUE; + break; + } + + /* For the case of 3-way file merging, we don't + really distinguish between these return values; + if the callback claims to have "generally + resolved" the situation, we still interpret + that as "OK, we'll assume the merged version is + good to use". */ + case svn_wc_conflict_choose_merged: + { + install_from_abspath = merged_file + ? merged_file + : local_abspath; + break; + } + case svn_wc_conflict_choose_postpone: + { + /* Assume conflict remains. */ + return SVN_NO_ERROR; + } + default: + SVN_ERR_ASSERT(choice == svn_wc_conflict_choose_postpone); + } + + SVN_ERR_ASSERT(install_from_abspath != NULL); + + /* ### It would be nice if we could somehow pass RECORD_FILEINFO + as true in some easy cases. */ + SVN_ERR(svn_wc__wq_build_file_install(&work_item, + db, local_abspath, + install_from_abspath, + FALSE /* use_commit_times */, + FALSE /* record_fileinfo */, + result_pool, scratch_pool)); + *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool); + + if (remove_source) + { + SVN_ERR(svn_wc__wq_build_file_remove(&work_item, + db, local_abspath, + install_from_abspath, + result_pool, scratch_pool)); *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool); } - else - *was_resolved = FALSE; + + SVN_ERR(remove_artifact_file_if_exists(&work_item, found_artifact, + db, local_abspath, + their_old_abspath, + result_pool, scratch_pool)); + *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool); + + SVN_ERR(remove_artifact_file_if_exists(&work_item, found_artifact, + db, local_abspath, + their_abspath, + result_pool, scratch_pool)); + *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool); + + SVN_ERR(remove_artifact_file_if_exists(&work_item, found_artifact, + db, local_abspath, + mine_abspath, + result_pool, scratch_pool)); + *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool); return SVN_NO_ERROR; } @@ -1865,6 +1846,19 @@ read_tree_conflict_desc(svn_wc_conflict_ return SVN_NO_ERROR; } +/* Forward definition */ +static svn_error_t * +resolve_tree_conflict_on_node(svn_boolean_t *did_resolve, + svn_wc__db_t *db, + const char *local_abspath, + const svn_skel_t *conflict, + svn_wc_conflict_choice_t conflict_choice, + apr_hash_t *resolve_later, + 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_error_t * svn_wc__conflict_invoke_resolver(svn_wc__db_t *db, @@ -1984,6 +1978,7 @@ svn_wc__conflict_invoke_resolver(svn_wc_ svn_boolean_t was_resolved; svn_wc_conflict_description2_t *desc; apr_hash_t *props; + svn_wc_conflict_result_t *result; SVN_ERR(svn_wc__db_read_props(&props, db, local_abspath, scratch_pool, scratch_pool)); @@ -1995,27 +1990,37 @@ svn_wc__conflict_invoke_resolver(svn_wc_ operation, left_version, right_version, scratch_pool, scratch_pool)); - SVN_ERR(resolve_text_conflict(&work_items, &was_resolved, - db, local_abspath, desc, - merge_options, - resolver_func, resolver_baton, - cancel_func, cancel_baton, - scratch_pool, scratch_pool)); - if (was_resolved) - { - if (work_items) - { - SVN_ERR(svn_wc__db_wq_add(db, local_abspath, work_items, - scratch_pool)); - SVN_ERR(svn_wc__wq_run(db, local_abspath, - cancel_func, cancel_baton, - scratch_pool)); - } - SVN_ERR(svn_wc__mark_resolved_text_conflict(db, local_abspath, - cancel_func, - cancel_baton, - scratch_pool)); + work_items = NULL; + was_resolved = FALSE; + + /* Give the conflict resolution callback a chance to clean + up the conflicts before we mark the file 'conflicted' */ + + SVN_ERR(resolver_func(&result, desc, resolver_baton, scratch_pool, + scratch_pool)); + if (result == NULL) + return svn_error_create(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Conflict callback violated API:" + " returned no results")); + + SVN_ERR(build_text_conflict_resolve_items(&work_items, &was_resolved, + db, local_abspath, + conflict_skel, result->choice, + result->merged_file, + result->save_merged, + merge_options, + cancel_func, cancel_baton, + scratch_pool, scratch_pool)); + + if (result->choice != svn_wc_conflict_choose_postpone) + { + SVN_ERR(svn_wc__db_op_mark_resolved(db, local_abspath, + TRUE, FALSE, FALSE, + work_items, scratch_pool)); + SVN_ERR(svn_wc__wq_run(db, local_abspath, + cancel_func, cancel_baton, + scratch_pool)); } } @@ -2023,6 +2028,7 @@ svn_wc__conflict_invoke_resolver(svn_wc_ { svn_wc_conflict_result_t *result; svn_wc_conflict_description2_t *desc; + svn_boolean_t resolved; SVN_ERR(read_tree_conflict_desc(&desc, db, local_abspath, conflict_skel, @@ -2033,9 +2039,21 @@ svn_wc__conflict_invoke_resolver(svn_wc_ SVN_ERR(resolver_func(&result, desc, resolver_baton, scratch_pool, scratch_pool)); - /* Ignore the result. We cannot apply it here since this code runs - * during an update or merge operation. Tree conflicts are always - * postponed and resolved after the operation has completed. */ + if (result == NULL) + return svn_error_create(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Conflict callback violated API:" + " returned no results")); + + /* Pass retry hash to avoid erroring out on cases where update + can continue safely. ### Need notify handling */ + if (result->choice != svn_wc_conflict_choose_postpone) + SVN_ERR(resolve_tree_conflict_on_node(&resolved, + db, local_abspath, conflict_skel, + result->choice, + apr_hash_make(scratch_pool), + NULL, NULL, /* ### notify */ + cancel_func, cancel_baton, + scratch_pool)); } return SVN_NO_ERROR; @@ -2108,8 +2126,8 @@ read_prop_conflict_descs(apr_array_heade return SVN_NO_ERROR; } - SVN_ERR(svn_wc__db_base_get_props(&base_props, db, local_abspath, - result_pool, scratch_pool)); + SVN_ERR(svn_wc__db_read_pristine_props(&base_props, db, local_abspath, + result_pool, scratch_pool)); iterpool = svn_pool_create(scratch_pool); for (hi = apr_hash_first(scratch_pool, conflicted_props); hi; @@ -2300,190 +2318,6 @@ svn_wc__read_conflicts(const apr_array_h /*** Resolving a conflict automatically ***/ -/* Prepare to delete an artifact file at ARTIFACT_FILE_ABSPATH in the - * working copy at DB/WRI_ABSPATH. - * - * Set *WORK_ITEMS to a new work item that, when run, will delete the - * artifact file; or to NULL if there is no file to delete. - * - * Set *FILE_FOUND to TRUE if the artifact file is found on disk and its - * node kind is 'file'; otherwise do not change *FILE_FOUND. FILE_FOUND - * may be NULL if not required. - */ -static svn_error_t * -remove_artifact_file_if_exists(svn_skel_t **work_items, - svn_boolean_t *file_found, - svn_wc__db_t *db, - const char *wri_abspath, - const char *artifact_file_abspath, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) -{ - *work_items = NULL; - if (artifact_file_abspath) - { - svn_node_kind_t node_kind; - - SVN_ERR(svn_io_check_path(artifact_file_abspath, &node_kind, - scratch_pool)); - if (node_kind == svn_node_file) - { - SVN_ERR(svn_wc__wq_build_file_remove(work_items, - db, wri_abspath, - artifact_file_abspath, - result_pool, scratch_pool)); - if (file_found) - *file_found = TRUE; - } - } - - return SVN_NO_ERROR; -} - -/* - * Resolve the text conflict found in DB/LOCAL_ABSPATH according - * to CONFLICT_CHOICE. - * - * It is not an error if there is no text conflict. If a text conflict - * existed and was resolved, set *DID_RESOLVE to TRUE, else set it to FALSE. - * - * 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. - * - * ### This is redundantly similar to eval_text_conflict_func_result(). - */ -static svn_error_t * -resolve_text_conflict_on_node(svn_boolean_t *did_resolve, - svn_wc__db_t *db, - const char *local_abspath, - svn_wc_conflict_choice_t conflict_choice, - const char *merged_file, - svn_cancel_func_t cancel_func, - void *cancel_baton, - 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_skel_t *work_item; - svn_skel_t *work_items = NULL; - svn_skel_t *conflicts; - svn_wc_operation_t operation; - svn_boolean_t text_conflicted; - - *did_resolve = FALSE; - - SVN_ERR(svn_wc__db_read_conflict(&conflicts, db, local_abspath, - scratch_pool, scratch_pool)); - if (!conflicts) - return SVN_NO_ERROR; - - SVN_ERR(svn_wc__conflict_read_info(&operation, NULL, &text_conflicted, - NULL, NULL, db, local_abspath, conflicts, - scratch_pool, scratch_pool)); - if (!text_conflicted) - return SVN_NO_ERROR; - - 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 = merged_file; - break; - case svn_wc_conflict_choose_theirs_conflict: - case svn_wc_conflict_choose_mine_conflict: - { - if (conflict_old && conflict_working && conflict_new) - { - 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(merge_showing_conflicts(&auto_resolve_src, - db, local_abspath, - style, - NULL /*merge_options*/, - conflict_old, - conflict_working, - conflict_new, - /* ### why not same as other caller? */ - svn_io_file_del_on_pool_cleanup, - cancel_func, cancel_baton, - scratch_pool, scratch_pool)); - } - 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) */ - - SVN_ERR(remove_artifact_file_if_exists(&work_item, did_resolve, - db, local_abspath, conflict_old, - scratch_pool, scratch_pool)); - work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool); - - SVN_ERR(remove_artifact_file_if_exists(&work_item, did_resolve, - db, local_abspath, conflict_new, - scratch_pool, scratch_pool)); - work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool); - - SVN_ERR(remove_artifact_file_if_exists(&work_item, did_resolve, - db, local_abspath, conflict_working, - scratch_pool, scratch_pool)); - work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool); - - SVN_ERR(svn_wc__db_op_mark_resolved(db, local_abspath, - TRUE, FALSE, FALSE, - work_items, scratch_pool)); - SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton, - scratch_pool)); - - return SVN_NO_ERROR; -} - /* * Resolve the property conflicts found in DB/LOCAL_ABSPATH according * to CONFLICT_CHOICE. @@ -2681,6 +2515,7 @@ static svn_error_t * resolve_tree_conflict_on_node(svn_boolean_t *did_resolve, svn_wc__db_t *db, const char *local_abspath, + const svn_skel_t *conflicts, svn_wc_conflict_choice_t conflict_choice, apr_hash_t *resolve_later, svn_wc_notify_func2_t notify_func, @@ -2691,18 +2526,12 @@ resolve_tree_conflict_on_node(svn_boolea { svn_wc_conflict_reason_t reason; svn_wc_conflict_action_t action; - svn_skel_t *conflicts; svn_wc_operation_t operation; svn_boolean_t tree_conflicted; const char *src_op_root_abspath; *did_resolve = FALSE; - SVN_ERR(svn_wc__db_read_conflict(&conflicts, db, local_abspath, - scratch_pool, scratch_pool)); - if (!conflicts) - return SVN_NO_ERROR; - SVN_ERR(svn_wc__conflict_read_info(&operation, NULL, NULL, NULL, &tree_conflicted, db, local_abspath, conflicts, scratch_pool, scratch_pool)); @@ -2745,7 +2574,9 @@ resolve_tree_conflict_on_node(svn_boolea if (err) { const char *dup_abspath; - if (err && err->apr_err != SVN_ERR_WC_OBSTRUCTED_UPDATE) + + if (!resolve_later + || err->apr_err != SVN_ERR_WC_OBSTRUCTED_UPDATE) return svn_error_trace(err); svn_error_clear(err); @@ -2778,15 +2609,18 @@ resolve_tree_conflict_on_node(svn_boolea if (conflict_choice == svn_wc_conflict_choose_mine_conflict) { err = svn_wc__db_update_moved_away_conflict_victim( - db, local_abspath, - notify_func, notify_baton, + db, local_abspath, src_op_root_abspath, + operation, action, reason, cancel_func, cancel_baton, + notify_func, notify_baton, scratch_pool); if (err) { const char *dup_abspath; - if (err && err->apr_err != SVN_ERR_WC_OBSTRUCTED_UPDATE) + + if (!resolve_later + || err->apr_err != SVN_ERR_WC_OBSTRUCTED_UPDATE) return svn_error_trace(err); svn_error_clear(err); @@ -2890,14 +2724,28 @@ svn_wc__mark_resolved_text_conflict(svn_ void *cancel_baton, apr_pool_t *scratch_pool) { - svn_boolean_t ignored_result; + svn_skel_t *work_items; + svn_skel_t *conflict; - return svn_error_trace(resolve_text_conflict_on_node( - &ignored_result, - db, local_abspath, - svn_wc_conflict_choose_merged, NULL, - cancel_func, cancel_baton, - scratch_pool)); + SVN_ERR(svn_wc__db_read_conflict(&conflict, db, local_abspath, + scratch_pool, scratch_pool)); + + if (!conflict) + return SVN_NO_ERROR; + + SVN_ERR(build_text_conflict_resolve_items(&work_items, NULL, + db, local_abspath, conflict, + svn_wc_conflict_choose_merged, + NULL, FALSE, NULL, + cancel_func, cancel_baton, + scratch_pool, scratch_pool)); + + SVN_ERR(svn_wc__db_op_mark_resolved(db, local_abspath, TRUE, FALSE, FALSE, + work_items, scratch_pool)); + + return svn_error_trace(svn_wc__wq_run(db, local_abspath, + cancel_func, cancel_baton, + scratch_pool)); } svn_error_t * @@ -2933,6 +2781,35 @@ struct conflict_status_walker_baton apr_hash_t *resolve_later; }; +/* Implements svn_wc_notify_func2_t to collect new conflicts caused by + resolving a tree conflict. */ +static void +tree_conflict_collector(void *baton, + const svn_wc_notify_t *notify, + apr_pool_t *pool) +{ + struct conflict_status_walker_baton *cswb = baton; + + if (cswb->notify_func) + cswb->notify_func(cswb->notify_baton, notify, pool); + + if (cswb->resolve_later + && (notify->action == svn_wc_notify_tree_conflict + || notify->prop_state == svn_wc_notify_state_conflicted + || notify->content_state == svn_wc_notify_state_conflicted)) + { + if (!svn_hash_gets(cswb->resolve_later, notify->path)) + { + const char *dup_path; + + dup_path = apr_pstrdup(apr_hash_pool_get(cswb->resolve_later), + notify->path); + + svn_hash_sets(cswb->resolve_later, dup_path, dup_path); + } + } +} + /* Implements svn_wc_status4_t to walk all conflicts to resolve. */ static svn_error_t * @@ -2948,12 +2825,16 @@ conflict_status_walker(void *baton, apr_pool_t *iterpool; int i; svn_boolean_t resolved = FALSE; + svn_skel_t *conflict; if (!status->conflicted) return SVN_NO_ERROR; iterpool = svn_pool_create(scratch_pool); + SVN_ERR(svn_wc__db_read_conflict(&conflict, db, local_abspath, + scratch_pool, scratch_pool)); + SVN_ERR(svn_wc__read_conflicts(&conflicts, db, local_abspath, TRUE, scratch_pool, iterpool)); @@ -2962,16 +2843,22 @@ 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; - const char *merged_file = NULL; + svn_wc_conflict_result_t *result = NULL; + svn_skel_t *work_items; cd = APR_ARRAY_IDX(conflicts, i, const svn_wc_conflict_description2_t *); + if ((cd->kind == svn_wc_conflict_kind_property && !cswb->resolve_prop) + || (cd->kind == svn_wc_conflict_kind_text && !cswb->resolve_text) + || (cd->kind == svn_wc_conflict_kind_tree && !cswb->resolve_tree)) + { + continue; /* Easy out. Don't call resolver func and ignore result */ + } + svn_pool_clear(iterpool); if (my_choice == svn_wc_conflict_choose_unspecified) { - svn_wc_conflict_result_t *result; - if (!cswb->conflict_func) return svn_error_create(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, _("No conflict-callback and no " @@ -2981,8 +2868,6 @@ conflict_status_walker(void *baton, iterpool, iterpool)); my_choice = result->choice; - merged_file = result->merged_file; - /* ### Bug: ignores result->save_merged */ } @@ -2996,11 +2881,11 @@ conflict_status_walker(void *baton, break; SVN_ERR(resolve_tree_conflict_on_node(&did_resolve, db, - local_abspath, + local_abspath, conflict, my_choice, cswb->resolve_later, - cswb->notify_func, - cswb->notify_baton, + tree_conflict_collector, + cswb, cswb->cancel_func, cswb->cancel_baton, iterpool)); @@ -3013,17 +2898,26 @@ conflict_status_walker(void *baton, if (!cswb->resolve_text) break; - SVN_ERR(resolve_text_conflict_on_node(&did_resolve, - db, - local_abspath, - my_choice, - merged_file, - cswb->cancel_func, - cswb->cancel_baton, - iterpool)); - - if (did_resolve) - resolved = TRUE; + SVN_ERR(build_text_conflict_resolve_items( + &work_items, + &resolved, + db, local_abspath, conflict, + my_choice, + result ? result->merged_file + : NULL, + result ? result->save_merged + : FALSE, + NULL /* merge_options */, + cswb->cancel_func, + cswb->cancel_baton, + iterpool, iterpool)); + + SVN_ERR(svn_wc__db_op_mark_resolved(db, local_abspath, + TRUE, FALSE, FALSE, + work_items, iterpool)); + SVN_ERR(svn_wc__wq_run(db, local_abspath, + cswb->cancel_func, cswb->cancel_baton, + iterpool)); break; case svn_wc_conflict_kind_property: @@ -3041,7 +2935,9 @@ conflict_status_walker(void *baton, local_abspath, cd->property_name, my_choice, - merged_file, + result + ? result->merged_file + : NULL, cswb->cancel_func, cswb->cancel_baton, iterpool)); @@ -3129,7 +3025,9 @@ svn_wc__resolve_conflicts(svn_wc_context cswb.notify_func = notify_func; cswb.notify_baton = notify_baton; - cswb.resolve_later = apr_hash_make(scratch_pool); + cswb.resolve_later = (depth != svn_depth_empty) + ? apr_hash_make(scratch_pool) + : NULL; if (notify_func) notify_func(notify_baton, @@ -3149,7 +3047,7 @@ svn_wc__resolve_conflicts(svn_wc_context cancel_func, cancel_baton, scratch_pool); - while (!err && apr_hash_count(cswb.resolve_later)) + while (!err && cswb.resolve_later && apr_hash_count(cswb.resolve_later)) { apr_hash_index_t *hi; svn_boolean_t cleared_one = FALSE; @@ -3160,17 +3058,19 @@ svn_wc__resolve_conflicts(svn_wc_context else iterpool = svn_pool_create(scratch_pool); - for (hi = apr_hash_first(scratch_pool, cswb.resolve_later); - hi && !err; - hi = apr_hash_next(hi)) + hi = apr_hash_first(scratch_pool, cswb.resolve_later); + cswb.resolve_later = apr_hash_make(scratch_pool); + + for (; hi && !err; hi = apr_hash_next(hi)) { tc_abspath = apr_hash_this_key(hi); svn_pool_clear(iterpool); - svn_hash_sets(cswb.resolve_later, tc_abspath, NULL); + /* ### TODO: Check if tc_abspath falls within selected depth */ - err = svn_wc_walk_status(wc_ctx, tc_abspath, depth, FALSE, FALSE, - TRUE, NULL, conflict_status_walker, &cswb, + err = svn_wc_walk_status(wc_ctx, tc_abspath, svn_depth_empty, + FALSE, FALSE, TRUE, NULL, + conflict_status_walker, &cswb, cancel_func, cancel_baton, iterpool); Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/status.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/status.c?rev=1659238&r1=1659237&r2=1659238&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_wc/status.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_wc/status.c Thu Feb 12 12:21:31 2015 @@ -36,7 +36,6 @@ #include "svn_string.h" #include "svn_error.h" #include "svn_dirent_uri.h" -#include "svn_path.h" #include "svn_io.h" #include "svn_config.h" #include "svn_time.h" @@ -47,9 +46,6 @@ #include "wc.h" #include "props.h" -#include "entries.h" -#include "translate.h" -#include "tree_conflicts.h" #include "private/svn_sorts_private.h" #include "private/svn_wc_private.h" Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/token-map.h URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/token-map.h?rev=1659238&r1=1659237&r2=1659238&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_wc/token-map.h (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_wc/token-map.h Thu Feb 12 12:21:31 2015 @@ -33,6 +33,7 @@ extern "C" { #endif +/* The kind values used on NODES */ static const svn_token_map_t kind_map[] = { { "file", svn_node_file }, /* MAP_FILE */ { "dir", svn_node_dir }, /* MAP_DIR */ @@ -41,6 +42,16 @@ static const svn_token_map_t kind_map[] { NULL } }; +/* Like kind_map, but also supports 'none' */ +static const svn_token_map_t kind_map_none[] = { + { "none", svn_node_none }, + { "file", svn_node_file }, + { "dir", svn_node_dir }, + { "symlink", svn_node_symlink }, + { "unknown", svn_node_unknown }, + { NULL } +}; + /* Note: we only decode presence values from the database. These are a subset of all the status values. */ static const svn_token_map_t presence_map[] = { Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/update_editor.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/update_editor.c?rev=1659238&r1=1659237&r2=1659238&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_wc/update_editor.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_wc/update_editor.c Thu Feb 12 12:21:31 2015 @@ -2288,15 +2288,7 @@ add_directory(const char *path, if (tree_conflict != NULL) { - if (eb->conflict_func) - SVN_ERR(svn_wc__conflict_invoke_resolver(eb->db, db->local_abspath, - tree_conflict, - NULL /* merge_options */, - eb->conflict_func, - eb->conflict_baton, - eb->cancel_func, - eb->cancel_baton, - scratch_pool)); + db->edit_conflict = tree_conflict; db->already_notified = TRUE; do_notification(eb, db->local_abspath, svn_node_dir, @@ -2906,10 +2898,9 @@ close_directory(void *dir_baton, (dav_prop_changes->nelts > 0) ? svn_prop_array_to_hash(dav_prop_changes, pool) : NULL, - conflict_skel, (! db->shadowed) && new_base_props != NULL, - new_actual_props, - iprops, all_work_items, + new_actual_props, iprops, + conflict_skel, all_work_items, scratch_pool)); } @@ -3295,7 +3286,7 @@ add_file(const char *path, eb->db, fb->local_abspath, tree_conflict, - fb->pool, fb->pool)); + fb->pool, scratch_pool)); tree_conflict = svn_wc__conflict_skel_create(fb->pool); @@ -3304,7 +3295,7 @@ add_file(const char *path, eb->db, fb->local_abspath, reason, svn_wc_conflict_action_replace, move_src_op_root_abspath, - fb->pool, fb->pool)); + fb->pool, scratch_pool)); /* And now stop checking for conflicts here and just perform a shadowed update */ @@ -3401,7 +3392,7 @@ add_file(const char *path, fb->local_abspath, status, FALSE, svn_node_none, svn_wc_conflict_action_add, - scratch_pool, scratch_pool)); + fb->pool, scratch_pool)); } if (tree_conflict == NULL) @@ -3463,15 +3454,7 @@ add_file(const char *path, tree_conflict, NULL, scratch_pool)); - if (eb->conflict_func) - SVN_ERR(svn_wc__conflict_invoke_resolver(eb->db, fb->local_abspath, - tree_conflict, - NULL /* merge_options */, - eb->conflict_func, - eb->conflict_baton, - eb->cancel_func, - eb->cancel_baton, - scratch_pool)); + fb->edit_conflict = tree_conflict; fb->already_notified = TRUE; do_notification(eb, fb->local_abspath, svn_node_file, Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/wc-queries.sql URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/wc-queries.sql?rev=1659238&r1=1659237&r2=1659238&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_wc/wc-queries.sql (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_wc/wc-queries.sql Thu Feb 12 12:21:31 2015 @@ -99,7 +99,7 @@ LIMIT 1 -- STMT_SELECT_DEPTH_NODE SELECT repos_id, repos_path, presence, kind, revision, checksum, translated_size, changed_revision, changed_date, changed_author, depth, - symlink_target, last_mod_time, properties + symlink_target, properties, moved_to, moved_here FROM nodes WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?3 @@ -332,6 +332,15 @@ WHERE wc_id = ?1 AND op_depth = ?3 AND presence != MAP_BASE_DELETED AND file_external is NULL +ORDER BY local_relpath + +-- STMT_SELECT_OP_DEPTH_CHILDREN_EXISTS +SELECT local_relpath, kind FROM nodes +WHERE wc_id = ?1 + AND parent_relpath = ?2 + AND op_depth = ?3 + AND presence IN (MAP_NORMAL, MAP_INCOMPLETE) +ORDER BY local_relpath /* Used by non-recursive revert to detect higher level children, and actual-only rows that would be left orphans, if the revert @@ -479,7 +488,8 @@ SELECT op_depth, moved_to FROM nodes WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth > ?3 AND EXISTS(SELECT * from nodes - WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?3) + WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?3 + AND presence IN (MAP_NORMAL, MAP_INCOMPLETE)) ORDER BY op_depth ASC LIMIT 1 @@ -1378,8 +1388,9 @@ BEGIN WHERE n.wc_id = OLD.wc_id AND n.local_relpath = OLD.local_relpath) THEN 1 - ELSE NULL - END; + END notify + WHERE OLD.conflict_data IS NOT NULL + OR notify IS NOT NULL; END; DROP TRIGGER IF EXISTS trigger_revert_list_actual_update; CREATE TEMPORARY TRIGGER trigger_revert_list_actual_update @@ -1395,8 +1406,9 @@ BEGIN WHERE n.wc_id = OLD.wc_id AND n.local_relpath = OLD.local_relpath) THEN 1 - ELSE NULL - END; + END notify + WHERE OLD.conflict_data IS NOT NULL + OR notify IS NOT NULL; END -- STMT_DROP_REVERT_LIST_TRIGGERS @@ -1422,12 +1434,15 @@ ORDER BY local_relpath DELETE FROM revert_list WHERE local_relpath = ?1 -- STMT_SELECT_REVERT_LIST_RECURSIVE -SELECT DISTINCT local_relpath -FROM revert_list -WHERE (local_relpath = ?1 - OR IS_STRICT_DESCENDANT_OF(local_relpath, ?1)) - AND (notify OR actual = 0) -ORDER BY local_relpath +SELECT p.local_relpath, n.kind, a.notify, a.kind +FROM (SELECT DISTINCT local_relpath + FROM revert_list + WHERE (local_relpath = ?1 + OR IS_STRICT_DESCENDANT_OF(local_relpath, ?1))) p + +LEFT JOIN revert_list n ON n.local_relpath=p.local_relpath AND n.actual=0 +LEFT JOIN revert_list a ON a.local_relpath=p.local_relpath AND a.actual=1 +ORDER BY p.local_relpath -- STMT_DELETE_REVERT_LIST_RECURSIVE DELETE FROM revert_list @@ -1476,7 +1491,7 @@ CREATE TEMPORARY TABLE update_move_list ### working copies. queries, etc will need to be adjusted. */ local_relpath TEXT PRIMARY KEY NOT NULL UNIQUE, action INTEGER NOT NULL, - kind INTEGER NOT NULL, + kind TEXT NOT NULL, content_state INTEGER NOT NULL, prop_state INTEGER NOT NULL ) @@ -1494,6 +1509,11 @@ ORDER BY local_relpath -- STMT_FINALIZE_UPDATE_MOVE DROP TABLE IF EXISTS update_move_list +-- STMT_MOVE_NOTIFY_TO_REVERT +INSERT INTO revert_list (local_relpath, notify, kind, actual) + SELECT local_relpath, 2, kind, 1 FROM update_move_list; +DROP TABLE update_move_list + /* ------------------------------------------------------------------------- */ /* Queries for revision status. */ @@ -1651,33 +1671,38 @@ WHERE wc_id = ?1 AND moved_to IS NOT NULL AND NOT IS_STRICT_DESCENDANT_OF(moved_to, ?2) --- STMT_SELECT_OP_DEPTH_MOVED_PAIR -SELECT n.local_relpath, p.kind, n.moved_to, p.repos_path -FROM nodes n -JOIN nodes p ON p.wc_id = ?1 AND p.local_relpath = ?2 - AND p.op_depth=(SELECT MAX(d.op_depth) +/* This statement is very similar to STMT_SELECT_MOVED_DESCENDANTS_SRC + but the passed op-depth is the depth of the shadowing node. + + This version is slightly more efficient as the most inner query is + only executed once, but the Sqlite page cache makes the difference + not really measurable */ +-- STMT_SELECT_MOVED_DESCENDANTS_SHD +SELECT n.op_depth, n.local_relpath, n.kind, n.repos_path, s.moved_to +FROM nodes s +JOIN nodes n ON n.wc_id = ?1 AND n.local_relpath = s.local_relpath + AND n.op_depth=(SELECT MAX(d.op_depth) FROM nodes d WHERE d.wc_id = ?1 AND d.local_relpath = ?2 AND d.op_depth < ?3) -WHERE n.wc_id = ?1 - AND IS_STRICT_DESCENDANT_OF(n.local_relpath, ?2) - AND n.op_depth = ?3 - AND n.moved_to IS NOT NULL +WHERE s.wc_id = ?1 AND s.op_depth = ?3 + AND IS_STRICT_DESCENDANT_OF(s.local_relpath, ?2) + AND s.moved_to IS NOT NULL --- STMT_SELECT_MOVED_DESCENDANTS -SELECT n.local_relpath, h.moved_to -FROM nodes n, nodes h -WHERE n.wc_id = ?1 - AND h.wc_id = ?1 +/* This statement is very similar to STMT_SELECT_MOVED_DESCENDANTS_SHD, + but the passed op-depth is the depth of the node as it originally existed */ +-- STMT_SELECT_MOVED_DESCENDANTS_SRC +SELECT s.op_depth, n.local_relpath, n.kind, n.repos_path, s.moved_to +FROM nodes n +JOIN nodes s ON s.wc_id = n.wc_id AND s.local_relpath = n.local_relpath + AND s.op_depth = (SELECT MIN(d.op_depth) + FROM nodes d + WHERE d.wc_id = ?1 + AND d.local_relpath = s.local_relpath + AND d.op_depth > ?3) +WHERE n.wc_id = ?1 AND n.op_depth = ?3 AND IS_STRICT_DESCENDANT_OF(n.local_relpath, ?2) - AND h.local_relpath = n.local_relpath - AND n.op_depth = ?3 - AND h.op_depth = (SELECT MIN(o.op_depth) - FROM nodes o - WHERE o.wc_id = ?1 - AND o.local_relpath = n.local_relpath - AND o.op_depth > ?3) - AND h.moved_to IS NOT NULL + AND s.moved_to IS NOT NULL -- STMT_COMMIT_UPDATE_ORIGIN UPDATE nodes SET repos_id = ?4, Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db.c?rev=1659238&r1=1659237&r2=1659238&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db.c Thu Feb 12 12:21:31 2015 @@ -418,7 +418,7 @@ lock_from_columns(svn_sqlite__stmt_t *st svn_error_t * svn_wc__db_fetch_repos_info(const char **repos_root_url, const char **repos_uuid, - svn_sqlite__db_t *sdb, + svn_wc__db_wcroot_t *wcroot, apr_int64_t repos_id, apr_pool_t *result_pool) { @@ -437,7 +437,7 @@ svn_wc__db_fetch_repos_info(const char * return SVN_NO_ERROR; } - SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, + SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_REPOSITORY_BY_ID)); SVN_ERR(svn_sqlite__bindf(stmt, "i", repos_id)); SVN_ERR(svn_sqlite__step(&have_row, stmt)); @@ -1295,42 +1295,6 @@ gather_repo_children(const apr_array_hea return SVN_NO_ERROR; } -svn_error_t * -svn_wc__db_get_children_op_depth(apr_hash_t **children, - svn_wc__db_wcroot_t *wcroot, - const char *local_relpath, - int op_depth, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) -{ - svn_sqlite__stmt_t *stmt; - svn_boolean_t have_row; - - *children = apr_hash_make(result_pool); - - SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, - STMT_SELECT_OP_DEPTH_CHILDREN)); - SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath, - op_depth)); - SVN_ERR(svn_sqlite__step(&have_row, stmt)); - while (have_row) - { - const char *child_relpath = svn_sqlite__column_text(stmt, 0, NULL); - svn_node_kind_t *child_kind = apr_palloc(result_pool, sizeof(svn_node_kind_t)); - - *child_kind = svn_sqlite__column_token(stmt, 1, kind_map); - svn_hash_sets(*children, - svn_relpath_basename(child_relpath, result_pool), - child_kind); - - SVN_ERR(svn_sqlite__step(&have_row, stmt)); - } - SVN_ERR(svn_sqlite__reset(stmt)); - - return SVN_NO_ERROR; -} - - /* Return TRUE if CHILD_ABSPATH is an immediate child of PARENT_ABSPATH. * Else, return FALSE. */ static svn_boolean_t @@ -1771,10 +1735,10 @@ svn_wc__db_base_add_directory(svn_wc__db const apr_array_header_t *children, svn_depth_t depth, apr_hash_t *dav_cache, - const svn_skel_t *conflict, svn_boolean_t update_actual_props, apr_hash_t *new_actual_props, apr_array_header_t *new_iprops, + const svn_skel_t *conflict, const svn_skel_t *work_items, apr_pool_t *scratch_pool) { @@ -2210,6 +2174,36 @@ clear_moved_here(svn_wc__db_wcroot_t *wc return SVN_NO_ERROR; } +svn_error_t * +svn_wc__db_op_break_move_internal(svn_wc__db_wcroot_t *wcroot, + const char *src_relpath, + int src_op_depth, + const char *dst_relpath, + const svn_skel_t *work_items, + apr_pool_t *scratch_pool) +{ + svn_sqlite__stmt_t *stmt; + int affected; + + SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, + STMT_CLEAR_MOVED_TO_RELPATH)); + SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, src_relpath, + src_op_depth)); + SVN_ERR(svn_sqlite__update(&affected, stmt)); + + if (affected != 1) + return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL, + _("Path '%s' is not moved"), + path_for_error_message(wcroot, src_relpath, + scratch_pool)); + + SVN_ERR(clear_moved_here(wcroot, dst_relpath, scratch_pool)); + + SVN_ERR(add_work_items(wcroot->sdb, work_items, scratch_pool)); + return SVN_NO_ERROR; +} + + /* The body of svn_wc__db_base_remove(). */ static svn_error_t * @@ -2695,7 +2689,7 @@ svn_wc__db_base_get_info(svn_wc__db_stat wcroot, local_relpath, result_pool, scratch_pool), svn_wc__db_fetch_repos_info(repos_root_url, repos_uuid, - wcroot->sdb, repos_id, result_pool), + wcroot, repos_id, result_pool), SVN_NO_ERROR, SVN_NO_ERROR, wcroot); @@ -2756,7 +2750,7 @@ base_get_children_info(apr_hash_t **node svn_error_t *err; err = svn_wc__db_fetch_repos_info(&last_repos_root_url, NULL, - wcroot->sdb, repos_id, + wcroot, repos_id, result_pool); if (err) @@ -3032,21 +3026,21 @@ svn_wc__db_depth_get_info(svn_wc__db_sta } if (had_props) { - *had_props = SQLITE_PROPERTIES_AVAILABLE(stmt, 13); + *had_props = SQLITE_PROPERTIES_AVAILABLE(stmt, 12); } if (props) { if (node_status == svn_wc__db_status_normal || node_status == svn_wc__db_status_incomplete) { - SVN_ERR(svn_sqlite__column_properties(props, stmt, 13, + SVN_ERR(svn_sqlite__column_properties(props, stmt, 12, result_pool, scratch_pool)); if (*props == NULL) *props = apr_hash_make(result_pool); } else { - assert(svn_sqlite__column_is_null(stmt, 13)); + assert(svn_sqlite__column_is_null(stmt, 12)); *props = NULL; } } @@ -3631,7 +3625,7 @@ svn_wc__db_external_read(svn_wc__db_stat err = svn_error_compose_create( err, svn_wc__db_fetch_repos_info(repos_root_url, repos_uuid, - wcroot->sdb, repos_id, + wcroot, repos_id, result_pool)); } @@ -4352,7 +4346,7 @@ get_info_for_copy(apr_int64_t *copyfrom_ working copies in a single db)! */ SVN_ERR(svn_wc__db_fetch_repos_info(&repos_root_url, &repos_uuid, - src_wcroot->sdb, *copyfrom_id, + src_wcroot, *copyfrom_id, scratch_pool)); SVN_ERR(create_repos_id(copyfrom_id, repos_root_url, repos_uuid, @@ -5311,7 +5305,7 @@ db_op_copy_shadowed_layer(svn_wc__db_wcr const char *repos_uuid; SVN_ERR(svn_wc__db_fetch_repos_info(&repos_root_url, &repos_uuid, - src_wcroot->sdb, node_repos_id, + src_wcroot, node_repos_id, scratch_pool)); SVN_ERR(create_repos_id(&node_repos_id, repos_root_url, repos_uuid, @@ -6744,6 +6738,8 @@ op_revert_txn(void *baton, svn_boolean_t moved_here; int affected_rows; const char *moved_to; + int op_depth_increased = 0; + svn_skel_t *conflict; /* ### Similar structure to op_revert_recursive_txn, should they be combined? */ @@ -6794,52 +6790,18 @@ op_revert_txn(void *baton, if (moved_to) { - SVN_ERR(svn_wc__db_resolve_break_moved_away_internal(wcroot, - local_relpath, - op_depth, - scratch_pool)); + SVN_ERR(svn_wc__db_op_break_move_internal(wcroot, + local_relpath, op_depth, + moved_to, NULL, scratch_pool)); } else { - svn_skel_t *conflict; - SVN_ERR(svn_wc__db_read_conflict_internal(&conflict, wcroot, local_relpath, scratch_pool, scratch_pool)); - if (conflict) - { - svn_wc_operation_t operation; - svn_boolean_t tree_conflicted; - - SVN_ERR(svn_wc__conflict_read_info(&operation, NULL, NULL, NULL, - &tree_conflicted, - db, wcroot->abspath, - conflict, - scratch_pool, scratch_pool)); - if (tree_conflicted - && (operation == svn_wc_operation_update - || operation == svn_wc_operation_switch)) - { - svn_wc_conflict_reason_t reason; - svn_wc_conflict_action_t action; - - SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, &action, - NULL, - db, wcroot->abspath, - conflict, - scratch_pool, - scratch_pool)); - - if (reason == svn_wc_conflict_reason_deleted) - SVN_ERR(svn_wc__db_resolve_delete_raise_moved_away( - db, svn_dirent_join(wcroot->abspath, local_relpath, - scratch_pool), - NULL, NULL /* ### How do we notify this? */, - scratch_pool)); - } - } } + if (op_depth > 0 && op_depth == relpath_depth(local_relpath)) { /* Can't do non-recursive revert if children exist */ @@ -6864,7 +6826,7 @@ op_revert_txn(void *baton, SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath, op_depth)); - SVN_ERR(svn_sqlite__step_done(stmt)); + SVN_ERR(svn_sqlite__update(&op_depth_increased, stmt)); SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_DELETE_WORKING_NODE)); @@ -6882,6 +6844,54 @@ op_revert_txn(void *baton, SVN_ERR(clear_moved_to(wcroot, local_relpath, scratch_pool)); } + if (op_depth_increased && conflict) + { + svn_wc_operation_t operation; + svn_boolean_t tree_conflicted; + const apr_array_header_t *locations; + + SVN_ERR(svn_wc__conflict_read_info(&operation, &locations, NULL, NULL, + &tree_conflicted, + db, wcroot->abspath, + conflict, + scratch_pool, scratch_pool)); + if (tree_conflicted + && (operation == svn_wc_operation_update + || operation == svn_wc_operation_switch)) + { + svn_wc_conflict_reason_t reason; + svn_wc_conflict_action_t action; + + SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, &action, + NULL, + db, wcroot->abspath, + conflict, + scratch_pool, + scratch_pool)); + + if (reason == svn_wc_conflict_reason_deleted + || reason == svn_wc_conflict_reason_replaced) + { + SVN_ERR(svn_wc__db_op_raise_moved_away_internal( + wcroot, local_relpath, op_depth+1, db, + operation, action, + (locations && locations->nelts > 0) + ? APR_ARRAY_IDX(locations, 0, + const svn_wc_conflict_version_t *) + : NULL, + (locations && locations->nelts > 1) + ? APR_ARRAY_IDX(locations, 1, + const svn_wc_conflict_version_t *) + : NULL, + scratch_pool)); + + /* Transform the move information into revert information */ + SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb, + STMT_MOVE_NOTIFY_TO_REVERT)); + } + } + } + if (rvb->clear_changelists) { SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, @@ -6973,14 +6983,14 @@ op_revert_recursive_txn(void *baton, SVN_ERR(svn_sqlite__step(&have_row, stmt)); while (have_row) { - const char *move_src_relpath = svn_sqlite__column_text(stmt, 0, NULL); + const char *src_relpath = svn_sqlite__column_text(stmt, 0, NULL); + const char *dst_relpath = svn_sqlite__column_text(stmt, 1, NULL); int move_op_depth = svn_sqlite__column_int(stmt, 2); svn_error_t *err; - err = svn_wc__db_resolve_break_moved_away_internal(wcroot, - move_src_relpath, - move_op_depth, - scratch_pool); + err = svn_wc__db_op_break_move_internal(wcroot, + src_relpath, move_op_depth, + dst_relpath, NULL, scratch_pool); if (err) return svn_error_compose_create(err, svn_sqlite__reset(stmt)); @@ -7313,16 +7323,39 @@ svn_wc__db_revert_list_notify(svn_wc_not while (have_row) { const char *notify_relpath = svn_sqlite__column_text(stmt, 0, NULL); + svn_wc_notify_t *notify; svn_pool_clear(iterpool); - notify_func(notify_baton, - svn_wc_create_notify(svn_dirent_join(wcroot->abspath, - notify_relpath, - iterpool), - svn_wc_notify_revert, - iterpool), - iterpool); + notify = svn_wc_create_notify(svn_dirent_join(wcroot->abspath, + notify_relpath, + iterpool), + svn_wc_notify_revert, + iterpool); + + if (!svn_sqlite__column_is_null(stmt, 1)) + notify->kind = svn_sqlite__column_token(stmt, 1, kind_map); + else + { + if (!svn_sqlite__column_is_null(stmt, 3)) + notify->kind = svn_sqlite__column_token(stmt, 3, kind_map_none); + + switch (svn_sqlite__column_int(stmt, 2)) + { + case 0: + continue; + case 1: + /* standard revert */ + break; + case 2: + notify->action = svn_wc_notify_tree_conflict; + break; + default: + SVN_ERR_MALFUNCTION(); + } + } + + notify_func(notify_baton, notify, iterpool); SVN_ERR(svn_sqlite__step(&have_row, stmt)); } @@ -9082,9 +9115,9 @@ svn_wc__db_read_info(svn_wc__db_status_t have_base, have_more_work, have_work, wcroot, local_relpath, result_pool, scratch_pool), svn_wc__db_fetch_repos_info(repos_root_url, repos_uuid, - wcroot->sdb, repos_id, result_pool), + wcroot, repos_id, result_pool), svn_wc__db_fetch_repos_info(original_root_url, original_uuid, - wcroot->sdb, original_repos_id, + wcroot, original_repos_id, result_pool), SVN_NO_ERROR, wcroot); @@ -9197,7 +9230,7 @@ read_children_info(svn_wc__db_wcroot_t * last_repos_root_url = repos_root_url; err = svn_wc__db_fetch_repos_info(&repos_root_url, &repos_uuid, - wcroot->sdb, repos_id, + wcroot, repos_id, result_pool); if (err) SVN_ERR(svn_error_compose_create(err, @@ -9580,7 +9613,7 @@ read_single_info(const struct svn_wc__db mtb->copied = (original_repos_relpath != NULL); SVN_ERR(svn_wc__db_fetch_repos_info(&mtb->repos_root_url, &mtb->repos_uuid, - wcroot->sdb, repos_id, result_pool)); + wcroot, repos_id, result_pool)); if (!base_tree_only && mtb->kind == svn_node_dir) SVN_ERR(is_wclocked(&mtb->locked, wcroot, local_relpath, scratch_pool)); @@ -10023,7 +10056,7 @@ read_url_txn(const char **url, } } - SVN_ERR(svn_wc__db_fetch_repos_info(&repos_root_url, NULL, wcroot->sdb, + SVN_ERR(svn_wc__db_fetch_repos_info(&repos_root_url, NULL, wcroot, repos_id, scratch_pool)); SVN_ERR_ASSERT(repos_root_url != NULL && repos_relpath != NULL); @@ -11173,7 +11206,7 @@ relocate_txn(svn_wc__db_wcroot_t *wcroot scratch_pool, scratch_pool)); } - SVN_ERR(svn_wc__db_fetch_repos_info(NULL, &repos_uuid, wcroot->sdb, + SVN_ERR(svn_wc__db_fetch_repos_info(NULL, &repos_uuid, wcroot, old_repos_id, scratch_pool)); SVN_ERR_ASSERT(repos_uuid); /* This function affects all the children of the given local_relpath, but the way that it does this is through the repos inheritance mechanism. @@ -11319,7 +11352,7 @@ moved_descendant_commit(svn_wc__db_wcroo && *repos_relpath != '\0'); SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, - STMT_SELECT_MOVED_DESCENDANTS)); + STMT_SELECT_MOVED_DESCENDANTS_SRC)); SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath, op_depth)); @@ -11330,12 +11363,12 @@ moved_descendant_commit(svn_wc__db_wcroo children = apr_hash_make(scratch_pool); - /* First, obtain all moved children */ + /* First, obtain all moved descendants */ /* To keep error handling simple, first cache them in a hashtable */ while (have_row) { - const char *src_relpath = svn_sqlite__column_text(stmt, 0, scratch_pool); - const char *to_relpath = svn_sqlite__column_text(stmt, 1, scratch_pool); + const char *src_relpath = svn_sqlite__column_text(stmt, 1, scratch_pool); + const char *to_relpath = svn_sqlite__column_text(stmt, 4, scratch_pool); svn_hash_sets(children, src_relpath, to_relpath); @@ -12644,7 +12677,7 @@ svn_wc__db_scan_addition(svn_wc__db_stat local_abspath, scratch_pool, scratch_pool)); VERIFY_USABLE_WCROOT(wcroot); - SVN_WC__DB_WITH_TXN( + SVN_WC__DB_WITH_TXN4( scan_addition(status, op_root_abspath ? &op_root_relpath @@ -12654,6 +12687,12 @@ svn_wc__db_scan_addition(svn_wc__db_stat original_revision, NULL, NULL, NULL, wcroot, local_relpath, result_pool, scratch_pool), + svn_wc__db_fetch_repos_info(repos_root_url, repos_uuid, wcroot, + repos_id, result_pool), + svn_wc__db_fetch_repos_info(original_root_url, original_uuid, + wcroot, original_repos_id, + result_pool), + SVN_NO_ERROR, wcroot); if (op_root_abspath) @@ -12662,12 +12701,6 @@ svn_wc__db_scan_addition(svn_wc__db_stat /* REPOS_ID must be valid if requested; ORIGINAL_REPOS_ID need not be. */ SVN_ERR_ASSERT(repos_id_p == NULL || repos_id != INVALID_REPOS_ID); - SVN_ERR(svn_wc__db_fetch_repos_info(repos_root_url, repos_uuid, wcroot->sdb, - repos_id, result_pool)); - SVN_ERR(svn_wc__db_fetch_repos_info(original_root_url, original_uuid, - wcroot->sdb, original_repos_id, - result_pool)); - return SVN_NO_ERROR; } @@ -12871,59 +12904,81 @@ svn_wc__db_follow_moved_to(apr_array_hea } svn_error_t * -svn_wc__db_op_depth_moved_to(const char **move_dst_relpath, - const char **move_dst_op_root_relpath, - const char **move_src_root_relpath, - const char **move_src_op_root_relpath, - int op_depth, - svn_wc__db_wcroot_t *wcroot, - const char *local_relpath, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) +svn_wc__db_scan_moved_to_internal(const char **move_src_relpath, + const char **move_dst_relpath, + const char **delete_relpath, + svn_wc__db_wcroot_t *wcroot, + const char *local_relpath, + int op_depth, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { svn_sqlite__stmt_t *stmt; svn_boolean_t have_row; int delete_op_depth; const char *relpath = local_relpath; + const char *dst_relpath; SVN_ERR_ASSERT(local_relpath[0]); /* Not valid on the WC root */ - *move_dst_relpath = *move_dst_op_root_relpath = NULL; - *move_src_root_relpath = *move_src_op_root_relpath = NULL; + if (move_src_relpath) + *move_src_relpath = NULL; + if (move_dst_relpath) + *move_dst_relpath = NULL; + if (delete_relpath) + *delete_relpath = NULL; - do + SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, + STMT_SELECT_OP_DEPTH_MOVED_TO)); + SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, relpath, op_depth)); + + SVN_ERR(svn_sqlite__step(&have_row, stmt)); + + if (!have_row) { + return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, + svn_sqlite__reset(stmt), + _("Node '%s' is not shadowed"), + path_for_error_message(wcroot, local_relpath, + scratch_pool)); + } + + delete_op_depth = svn_sqlite__column_int(stmt, 0); + dst_relpath = svn_sqlite__column_text(stmt, 1, scratch_pool); + + SVN_ERR(svn_sqlite__reset(stmt)); + + while (!dst_relpath && have_row) + { + relpath = svn_relpath_dirname(relpath, scratch_pool); + + if (relpath_depth(relpath) < delete_op_depth) + break; + SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, - STMT_SELECT_LOWEST_WORKING_NODE)); - SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, relpath, op_depth)); + STMT_SELECT_DEPTH_NODE)); + SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, relpath, + delete_op_depth)); + SVN_ERR(svn_sqlite__step(&have_row, stmt)); + if (have_row) - { - delete_op_depth = svn_sqlite__column_int(stmt, 0); - *move_dst_op_root_relpath = svn_sqlite__column_text(stmt, 3, - result_pool); - if (*move_dst_op_root_relpath) - { - *move_src_root_relpath = apr_pstrdup(result_pool, relpath); - SVN_ERR(svn_sqlite__reset(stmt)); + dst_relpath = svn_sqlite__column_text(stmt, 13, scratch_pool); - break; - } - } SVN_ERR(svn_sqlite__reset(stmt)); - relpath = svn_relpath_dirname(relpath, scratch_pool); } - while (have_row && delete_op_depth <= relpath_depth(relpath)); - if (*move_dst_op_root_relpath) + if (dst_relpath) { - *move_dst_relpath - = svn_relpath_join(*move_dst_op_root_relpath, - svn_relpath_skip_ancestor(relpath, local_relpath), - result_pool); + if (move_src_relpath) + *move_src_relpath = apr_pstrdup(result_pool, relpath); - *move_src_op_root_relpath = svn_relpath_limit(relpath, delete_op_depth, - result_pool); + if (move_dst_relpath) + *move_dst_relpath = apr_pstrdup(result_pool, dst_relpath); + + if (delete_relpath) + *delete_relpath = svn_relpath_limit(local_relpath, delete_op_depth, + result_pool); } return SVN_NO_ERROR; @@ -12936,7 +12991,7 @@ svn_error_t * svn_wc__db_base_moved_to(const char **move_dst_abspath, const char **move_dst_op_root_abspath, const char **move_src_root_abspath, - const char **move_src_op_root_abspath, + const char **delete_abspath, svn_wc__db_t *db, const char *local_abspath, apr_pool_t *result_pool, @@ -12944,47 +12999,54 @@ svn_wc__db_base_moved_to(const char **mo { svn_wc__db_wcroot_t *wcroot; const char *local_relpath; - const char *move_dst_relpath, *move_dst_op_root_relpath; - const char *move_src_root_relpath, *move_src_op_root_relpath; + const char *dst_root_relpath; + const char *src_root_relpath, *delete_relpath; SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath)); + SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db, local_abspath, scratch_pool, scratch_pool)); VERIFY_USABLE_WCROOT(wcroot); - SVN_WC__DB_WITH_TXN(svn_wc__db_op_depth_moved_to(&move_dst_relpath, - &move_dst_op_root_relpath, - &move_src_root_relpath, - &move_src_op_root_relpath, - 0 /* BASE op-depth */, - wcroot, local_relpath, - scratch_pool, scratch_pool), + SVN_WC__DB_WITH_TXN(svn_wc__db_scan_moved_to_internal(&src_root_relpath, + &dst_root_relpath, + &delete_relpath, + wcroot, local_relpath, + 0 /* BASE */, + scratch_pool, + scratch_pool), wcroot); if (move_dst_abspath) - *move_dst_abspath - = move_dst_relpath - ? svn_dirent_join(wcroot->abspath, move_dst_relpath, result_pool) - : NULL; + *move_dst_abspath = + dst_root_relpath + ? svn_dirent_join(wcroot->abspath, + svn_dirent_join( + dst_root_relpath, + svn_relpath_skip_ancestor(src_root_relpath, + local_relpath), + scratch_pool), + result_pool) + : NULL; if (move_dst_op_root_abspath) - *move_dst_op_root_abspath - = move_dst_op_root_relpath - ? svn_dirent_join(wcroot->abspath, move_dst_op_root_relpath, result_pool) - : NULL; + *move_dst_op_root_abspath = + dst_root_relpath + ? svn_dirent_join(wcroot->abspath, dst_root_relpath, result_pool) + : NULL; if (move_src_root_abspath) - *move_src_root_abspath - = move_src_root_relpath - ? svn_dirent_join(wcroot->abspath, move_src_root_relpath, result_pool) - : NULL; - - if (move_src_op_root_abspath) - *move_src_op_root_abspath - = move_src_op_root_relpath - ? svn_dirent_join(wcroot->abspath, move_src_op_root_relpath, result_pool) - : NULL; + *move_src_root_abspath = + src_root_relpath + ? svn_dirent_join(wcroot->abspath, src_root_relpath, result_pool) + : NULL; + + if (delete_abspath) + *delete_abspath = + delete_relpath + ? svn_dirent_join(wcroot->abspath, delete_relpath, result_pool) + : NULL; return SVN_NO_ERROR; } @@ -15231,7 +15293,7 @@ has_switched_subtrees(svn_boolean_t *is_ does not match the given trailing URL then the whole working copy is switched. */ - SVN_ERR(svn_wc__db_fetch_repos_info(&repos_root_url, NULL, wcroot->sdb, + SVN_ERR(svn_wc__db_fetch_repos_info(&repos_root_url, NULL, wcroot, repos_id, scratch_pool)); url = svn_path_url_add_component2(repos_root_url, repos_relpath, scratch_pool); @@ -15620,7 +15682,7 @@ svn_wc__db_base_get_lock_tokens_recursiv if (child_repos_id != last_repos_id) { svn_error_t *err = svn_wc__db_fetch_repos_info(&last_repos_root_url, - NULL, wcroot->sdb, + NULL, wcroot, child_repos_id, scratch_pool);