You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2015/02/10 12:41:59 UTC
svn commit: r1658686 [2/19] - in /subversion/branches/pin-externals: ./
build/generator/ build/generator/templates/ subversion/bindings/swig/
subversion/include/ subversion/libsvn_client/ subversion/libsvn_fs_fs/
subversion/libsvn_fs_x/ subversion/libs...
Modified: subversion/branches/pin-externals/subversion/libsvn_wc/conflicts.c
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_wc/conflicts.c?rev=1658686&r1=1658685&r2=1658686&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/libsvn_wc/conflicts.c (original)
+++ subversion/branches/pin-externals/subversion/libsvn_wc/conflicts.c Tue Feb 10 11:41:57 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;
@@ -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);
@@ -2769,7 +2600,7 @@ resolve_tree_conflict_on_node(svn_boolea
scratch_pool));
}
else if (reason == svn_wc_conflict_reason_moved_away
- && action == svn_wc_conflict_action_edit)
+ && action == svn_wc_conflict_action_edit)
{
/* After updates, we can resolve local moved-away
* vs. any incoming change, either by updating the
@@ -2786,7 +2617,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);
@@ -2825,6 +2658,34 @@ resolve_tree_conflict_on_node(svn_boolea
svn_dirent_local_style(local_abspath,
scratch_pool));
}
+ else if (reason == svn_wc_conflict_reason_moved_away
+ && action != svn_wc_conflict_action_edit)
+ {
+ /* action added is impossible, because that would imply that
+ something was added, but before that already moved...
+ (which would imply a replace) */
+ SVN_ERR_ASSERT(action == svn_wc_conflict_action_delete
+ || action == svn_wc_conflict_action_replace);
+
+ if (conflict_choice == svn_wc_conflict_choose_merged)
+ {
+ /* Whatever was moved is removed at its original location by the
+ update. That must also remove the recording of the move, so
+ we don't have to do anything here. */
+
+ *did_resolve = TRUE;
+ }
+ else if (conflict_choice == svn_wc_conflict_choose_mine_conflict)
+ {
+ return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE,
+ NULL,
+ _("Tree conflict can only be "
+ "resolved to 'working' state; "
+ "'%s' is no longer moved"),
+ svn_dirent_local_style(local_abspath,
+ scratch_pool));
+ }
+ }
}
if (! *did_resolve)
@@ -2862,14 +2723,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 *
@@ -2905,6 +2780,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 *
@@ -2920,12 +2824,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));
@@ -2934,16 +2842,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 "
@@ -2953,8 +2867,6 @@ conflict_status_walker(void *baton,
iterpool, iterpool));
my_choice = result->choice;
- merged_file = result->merged_file;
- /* ### Bug: ignores result->save_merged */
}
@@ -2968,11 +2880,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));
@@ -2985,17 +2897,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:
@@ -3013,7 +2934,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));
@@ -3101,7 +3024,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,
@@ -3121,7 +3046,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;
@@ -3132,17 +3057,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/pin-externals/subversion/libsvn_wc/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_wc/status.c?rev=1658686&r1=1658685&r2=1658686&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/libsvn_wc/status.c (original)
+++ subversion/branches/pin-externals/subversion/libsvn_wc/status.c Tue Feb 10 11:41:57 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/pin-externals/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_wc/update_editor.c?rev=1658686&r1=1658685&r2=1658686&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/pin-externals/subversion/libsvn_wc/update_editor.c Tue Feb 10 11:41:57 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/pin-externals/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_wc/wc-queries.sql?rev=1658686&r1=1658685&r2=1658686&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/pin-externals/subversion/libsvn_wc/wc-queries.sql Tue Feb 10 11:41:57 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
@@ -1651,33 +1661,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/pin-externals/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_wc/wc_db.c?rev=1658686&r1=1658685&r2=1658686&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/pin-externals/subversion/libsvn_wc/wc_db.c Tue Feb 10 11:41:57 2015
@@ -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 *
@@ -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;
}
}
@@ -6794,10 +6788,9 @@ 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
{
@@ -6973,14 +6966,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));
@@ -11319,7 +11312,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 +11323,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);
@@ -12871,59 +12864,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 +12951,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 +12959,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;
}
Modified: subversion/branches/pin-externals/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_wc/wc_db.h?rev=1658686&r1=1658685&r2=1658686&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/pin-externals/subversion/libsvn_wc/wc_db.h Tue Feb 10 11:41:57 2015
@@ -412,9 +412,6 @@ svn_wc__db_get_wcroot(const char **wcroo
If DAV_CACHE is not NULL, sets LOCAL_ABSPATH's dav cache to the specified
data.
- If CONFLICT is not NULL, then it describes a conflict for this node. The
- node will be record as conflicted (in ACTUAL).
-
If UPDATE_ACTUAL_PROPS is TRUE, set the properties store NEW_ACTUAL_PROPS
as the new set of properties in ACTUAL. If NEW_ACTUAL_PROPS is NULL or
when the value of NEW_ACTUAL_PROPS matches NEW_PROPS, store NULL in
@@ -424,6 +421,9 @@ svn_wc__db_get_wcroot(const char **wcroo
svn_prop_inherited_item_t * structures that is set as the base node's
inherited_properties.
+ If CONFLICT is not NULL, then it describes a conflict for this node. The
+ node will be record as conflicted (in ACTUAL).
+
Any work items that are necessary as part of this node construction may
be passed in WORK_ITEMS.
@@ -444,10 +444,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);
@@ -3448,14 +3448,14 @@ svn_wc__db_update_moved_away_conflict_vi
/* LOCAL_ABSPATH is moved to MOVE_DST_ABSPATH. MOVE_SRC_ROOT_ABSPATH
* is the root of the move to MOVE_DST_OP_ROOT_ABSPATH.
- * MOVE_SRC_OP_ROOT_ABSPATH is the op-root of the move; it's the same
+ * DELETE_ABSPATH is the op-root of the move; it's the same
* as MOVE_SRC_ROOT_ABSPATH except for moves inside deletes when it is
* the op-root of the delete. */
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,
Modified: subversion/branches/pin-externals/subversion/libsvn_wc/wc_db_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_wc/wc_db_private.h?rev=1658686&r1=1658685&r2=1658686&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/libsvn_wc/wc_db_private.h (original)
+++ subversion/branches/pin-externals/subversion/libsvn_wc/wc_db_private.h Tue Feb 10 11:41:57 2015
@@ -383,17 +383,6 @@ svn_wc__db_with_txn(svn_wc__db_wcroot_t
#define SVN_WC__DB_WITH_TXN4(expr1, expr2, expr3, expr4, wcroot) \
SVN_SQLITE__WITH_LOCK4(expr1, expr2, expr3, expr4, (wcroot)->sdb)
-
-/* Return CHILDREN mapping const char * names to svn_node_kind_t * for the
- children of LOCAL_RELPATH at OP_DEPTH. */
-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);
-
/* Update the single op-depth layer in the move destination subtree
rooted at DST_RELPATH to make it match the move source subtree
rooted at SRC_RELPATH. */
@@ -415,48 +404,43 @@ svn_wc__db_op_make_copy_internal(svn_wc_
apr_pool_t *scratch_pool);
-/* Extract the moved-to information for LOCAL_RELPATH at OP-DEPTH by
- examining the lowest working node above OP_DEPTH. The output paths
- are NULL if there is no move, otherwise:
+/* Extract the moved-to information for LOCAL_RELPATH as it existed
+ at OP-DEPTH. The output paths are optional and set to NULL
+ if there is no move, otherwise:
- *MOVE_DST_RELPATH: the moved-to destination of LOCAL_RELPATH.
+ *MOVE_SRC_RELPATH: the path that was moved (LOCAL_RELPATH or one
+ of its ancestors)
- *MOVE_DST_OP_ROOT_RELPATH: the moved-to destination of the root of
- the move of LOCAL_RELPATH. This may be equal to *MOVE_DST_RELPATH
- if LOCAL_RELPATH is the root of the move.
+ *MOVE_DST_RELPATH: The path *MOVE_SRC_RELPATH was moved to.
- *MOVE_SRC_ROOT_RELPATH: the root of the move source. For moves
- inside a delete this will be different from *MOVE_SRC_OP_ROOT_RELPATH.
+ *DELETE_RELPATH: The path at which LOCAL_RELPATH was removed (
+ *MOVE_SRC_RELPATH or one of its ancestors)
- *MOVE_SRC_OP_ROOT_RELPATH: the root of the source layer that
- contains the move. For moves inside deletes this is the root of
- the delete, for other moves this is the root of the move.
+ Given a path A/B/C with A/B moved to X and A deleted then for A/B/C:
- Given a path A/B/C with A/B moved to X then for A/B/C
+ MOVE_SRC_RELPATH is A/B
+ MOVE_DST_RELPATH is X
+ DELETE_RELPATH is A
- MOVE_DST_RELPATH is X/C
- MOVE_DST_OP_ROOT_RELPATH is X
- MOVE_SRC_ROOT_RELPATH is A/B
- MOVE_SRC_OP_ROOT_RELPATH is A/B
+ X/C can be calculated if necessesary, like with the other
+ scan functions.
- If A is then deleted the MOVE_DST_RELPATH, MOVE_DST_OP_ROOT_RELPATH
- and MOVE_SRC_ROOT_RELPATH remain the same but MOVE_SRC_OP_ROOT_RELPATH
- changes to A.
+ This function returns SVN_ERR_WC_PATH_NOT_FOUND if LOCAL_RELPATH didn't
+ exist at OP_DEPTH, or when it is not shadowed.
### Think about combining with scan_deletion? Also with
### scan_addition to get moved-to for replaces? Do we need to
### return the op-root of the move source, i.e. A/B in the example
### above? */
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);
/* Like svn_wc__db_op_set_props, but updates ACTUAL_NODE directly without
comparing with the pristine properties, etc.
@@ -496,12 +480,15 @@ svn_wc__db_bump_moved_away(svn_wc__db_wc
apr_pool_t *scratch_pool);
/* Unbreak the move from LOCAL_RELPATH on op-depth in WCROOT, by making
- the destination a normal copy */
+ the destination DST_RELPATH a normal copy. SRC_OP_DEPTH is the op-depth
+ where the move_to information is stored */
svn_error_t *
-svn_wc__db_resolve_break_moved_away_internal(svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath,
- int op_depth,
- apr_pool_t *scratch_pool);
+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_error_t *
svn_wc__db_update_move_list_notify(svn_wc__db_wcroot_t *wcroot,