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 2013/03/06 12:10:05 UTC
svn commit: r1453290 [10/15] - in /subversion/branches/fsfs-format7: ./
build/ build/ac-macros/ build/generator/ build/generator/templates/
subversion/bindings/javahl/native/
subversion/bindings/javahl/src/org/apache/subversion/javahl/
subversion/bindi...
Modified: subversion/branches/fsfs-format7/subversion/libsvn_wc/wc_db_update_move.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_wc/wc_db_update_move.c?rev=1453290&r1=1453289&r2=1453290&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_wc/wc_db_update_move.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_wc/wc_db_update_move.c Wed Mar 6 11:10:01 2013
@@ -114,7 +114,6 @@
*/
struct tc_editor_baton {
- svn_skel_t **work_items;
svn_wc__db_t *db;
svn_wc__db_wcroot_t *wcroot;
const char *move_root_dst_relpath;
@@ -126,9 +125,7 @@ struct tc_editor_baton {
svn_wc_operation_t operation;
svn_wc_conflict_version_t *old_version;
svn_wc_conflict_version_t *new_version;
- svn_wc_notify_func2_t notify_func;
- void *notify_baton;
- apr_pool_t *result_pool;
+ apr_pool_t *result_pool; /* For things that live as long as the baton. */
};
/*
@@ -161,48 +158,52 @@ update_move_list_add(svn_wc__db_wcroot_t
/* Send all notifications stored in the notification list, and then
* remove the temporary database table. */
-static svn_error_t *
-update_move_list_notify(svn_wc__db_wcroot_t *wcroot,
- svn_revnum_t old_revision,
- svn_revnum_t new_revision,
- svn_wc_notify_func2_t notify_func,
- void *notify_baton,
- apr_pool_t *scratch_pool)
+svn_error_t *
+svn_wc__db_update_move_list_notify(svn_wc__db_wcroot_t *wcroot,
+ svn_revnum_t old_revision,
+ svn_revnum_t new_revision,
+ svn_wc_notify_func2_t notify_func,
+ void *notify_baton,
+ apr_pool_t *scratch_pool)
{
svn_sqlite__stmt_t *stmt;
- svn_boolean_t have_row;
- apr_pool_t *iterpool;
- SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_SELECT_UPDATE_MOVE_LIST));
- SVN_ERR(svn_sqlite__step(&have_row, stmt));
-
- iterpool = svn_pool_create(scratch_pool);
- while (have_row)
+ if (notify_func)
{
- const char *local_relpath;
- svn_wc_notify_action_t action;
- svn_wc_notify_t *notify;
+ apr_pool_t *iterpool;
+ svn_boolean_t have_row;
- svn_pool_clear(iterpool);
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_SELECT_UPDATE_MOVE_LIST));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
- local_relpath = svn_sqlite__column_text(stmt, 0, NULL);
- action = svn_sqlite__column_int(stmt, 1);
- notify = svn_wc_create_notify(svn_dirent_join(wcroot->abspath,
- local_relpath,
- iterpool),
- action, iterpool);
- notify->kind = svn_sqlite__column_int(stmt, 2);
- notify->content_state = svn_sqlite__column_int(stmt, 3);
- notify->prop_state = svn_sqlite__column_int(stmt, 4);
- notify->old_revision = old_revision;
- notify->revision = new_revision;
- notify_func(notify_baton, notify, scratch_pool);
+ iterpool = svn_pool_create(scratch_pool);
+ while (have_row)
+ {
+ const char *local_relpath;
+ svn_wc_notify_action_t action;
+ svn_wc_notify_t *notify;
- SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ svn_pool_clear(iterpool);
+
+ local_relpath = svn_sqlite__column_text(stmt, 0, NULL);
+ action = svn_sqlite__column_int(stmt, 1);
+ notify = svn_wc_create_notify(svn_dirent_join(wcroot->abspath,
+ local_relpath,
+ iterpool),
+ action, iterpool);
+ notify->kind = svn_sqlite__column_int(stmt, 2);
+ notify->content_state = svn_sqlite__column_int(stmt, 3);
+ notify->prop_state = svn_sqlite__column_int(stmt, 4);
+ notify->old_revision = old_revision;
+ notify->revision = new_revision;
+ notify_func(notify_baton, notify, scratch_pool);
+
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ }
+ svn_pool_destroy(iterpool);
+ SVN_ERR(svn_sqlite__reset(stmt));
}
- svn_pool_destroy(iterpool);
- SVN_ERR(svn_sqlite__reset(stmt));
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_FINALIZE_UPDATE_MOVE));
@@ -211,9 +212,16 @@ update_move_list_notify(svn_wc__db_wcroo
return SVN_NO_ERROR;
}
+/* Mark a tree-conflict on LOCAL_RELPATH if such a tree-conflict does
+ not already exist. */
static svn_error_t *
-mark_tree_conflict(struct tc_editor_baton *b,
- const char *local_relpath,
+mark_tree_conflict(const char *local_relpath,
+ svn_wc__db_wcroot_t *wcroot,
+ svn_wc__db_t *db,
+ const svn_wc_conflict_version_t *old_version,
+ const svn_wc_conflict_version_t *new_version,
+ const char *move_root_dst_relpath,
+ svn_wc_operation_t operation,
svn_node_kind_t old_kind,
svn_node_kind_t new_kind,
const char *old_repos_relpath,
@@ -224,34 +232,34 @@ mark_tree_conflict(struct tc_editor_bato
{
svn_error_t *err;
svn_skel_t *conflict;
- svn_wc_conflict_version_t *old_version, *new_version;
+ svn_wc_conflict_version_t *conflict_old_version, *conflict_new_version;
const char *move_src_op_root_abspath
= move_src_op_root_relpath
- ? svn_dirent_join(b->wcroot->abspath,
+ ? svn_dirent_join(wcroot->abspath,
move_src_op_root_relpath, scratch_pool)
: NULL;
const char *old_repos_relpath_part
= old_repos_relpath
- ? svn_relpath_skip_ancestor(b->old_version->path_in_repos,
+ ? svn_relpath_skip_ancestor(old_version->path_in_repos,
old_repos_relpath)
: NULL;
const char *new_repos_relpath
= old_repos_relpath_part
- ? svn_relpath_join(b->new_version->path_in_repos, old_repos_relpath_part,
+ ? svn_relpath_join(new_version->path_in_repos, old_repos_relpath_part,
scratch_pool)
: NULL;
if (!new_repos_relpath)
new_repos_relpath
- = svn_relpath_join(b->new_version->path_in_repos,
- svn_relpath_skip_ancestor(b->move_root_dst_relpath,
+ = svn_relpath_join(new_version->path_in_repos,
+ svn_relpath_skip_ancestor(move_root_dst_relpath,
local_relpath),
scratch_pool);
- err = svn_wc__db_read_conflict_internal(&conflict, b->wcroot, local_relpath,
+ err = svn_wc__db_read_conflict_internal(&conflict, wcroot, local_relpath,
scratch_pool, scratch_pool);
if (err && err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
- return err;
+ return svn_error_trace(err);
else if (err)
{
svn_error_clear(err);
@@ -260,16 +268,16 @@ mark_tree_conflict(struct tc_editor_bato
if (conflict)
{
- svn_wc_operation_t operation;
+ svn_wc_operation_t conflict_operation;
svn_boolean_t tree_conflicted;
- SVN_ERR(svn_wc__conflict_read_info(&operation, NULL, NULL, NULL,
+ SVN_ERR(svn_wc__conflict_read_info(&conflict_operation, NULL, NULL, NULL,
&tree_conflicted,
- b->db, b->wcroot->abspath, conflict,
+ db, wcroot->abspath, conflict,
scratch_pool, scratch_pool));
- if (operation != svn_wc_operation_update
- && operation != svn_wc_operation_switch)
+ if (conflict_operation != svn_wc_operation_update
+ && conflict_operation != svn_wc_operation_switch)
return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
_("'%s' already in conflict"),
svn_dirent_local_style(local_relpath,
@@ -284,7 +292,7 @@ mark_tree_conflict(struct tc_editor_bato
SVN_ERR(svn_wc__conflict_read_tree_conflict(&existing_reason,
&existing_action,
&existing_abspath,
- b->db, b->wcroot->abspath,
+ db, wcroot->abspath,
conflict,
scratch_pool,
scratch_pool));
@@ -292,7 +300,7 @@ mark_tree_conflict(struct tc_editor_bato
|| action != existing_action
|| (reason == svn_wc_conflict_reason_moved_away
&& strcmp(move_src_op_root_relpath,
- svn_dirent_skip_ancestor(b->wcroot->abspath,
+ svn_dirent_skip_ancestor(wcroot->abspath,
existing_abspath))))
return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
_("'%s' already in conflict"),
@@ -306,11 +314,9 @@ mark_tree_conflict(struct tc_editor_bato
else
conflict = svn_wc__conflict_skel_create(scratch_pool);
- b->conflict_root_relpath = apr_pstrdup(b->result_pool, local_relpath);
-
SVN_ERR(svn_wc__conflict_skel_add_tree_conflict(
- conflict, b->db,
- svn_dirent_join(b->wcroot->abspath, local_relpath,
+ conflict, db,
+ svn_dirent_join(wcroot->abspath, local_relpath,
scratch_pool),
reason,
action,
@@ -320,40 +326,41 @@ mark_tree_conflict(struct tc_editor_bato
if (reason != svn_wc_conflict_reason_unversioned)
{
- old_version = svn_wc_conflict_version_create2(b->old_version->repos_url,
- b->old_version->repos_uuid,
- old_repos_relpath,
- b->old_version->peg_rev,
- old_kind,
- scratch_pool);
+ conflict_old_version = svn_wc_conflict_version_create2(
+ old_version->repos_url, old_version->repos_uuid,
+ old_repos_relpath, old_version->peg_rev,
+ old_kind, scratch_pool);
}
else
- old_version = NULL;
+ conflict_old_version = NULL;
- new_version = svn_wc_conflict_version_create2(b->new_version->repos_url,
- b->new_version->repos_uuid,
- new_repos_relpath,
- b->new_version->peg_rev,
- new_kind,
- scratch_pool);
+ conflict_new_version = svn_wc_conflict_version_create2(
+ new_version->repos_url, new_version->repos_uuid,
+ new_repos_relpath, new_version->peg_rev,
+ new_kind, scratch_pool);
- if (b->operation == svn_wc_operation_update)
+ if (operation == svn_wc_operation_update)
{
SVN_ERR(svn_wc__conflict_skel_set_op_update(
- conflict, old_version, new_version,
+ conflict, conflict_old_version, conflict_new_version,
scratch_pool, scratch_pool));
}
else
{
- assert(b->operation == svn_wc_operation_switch);
+ assert(operation == svn_wc_operation_switch);
SVN_ERR(svn_wc__conflict_skel_set_op_switch(
- conflict, old_version, new_version,
+ conflict, conflict_old_version, conflict_new_version,
scratch_pool, scratch_pool));
}
- SVN_ERR(svn_wc__db_mark_conflict_internal(b->wcroot, local_relpath,
+ SVN_ERR(svn_wc__db_mark_conflict_internal(wcroot, local_relpath,
conflict, scratch_pool));
+ SVN_ERR(update_move_list_add(wcroot, local_relpath,
+ svn_wc_notify_tree_conflict,
+ new_kind,
+ svn_wc_notify_state_inapplicable,
+ svn_wc_notify_state_inapplicable));
return SVN_NO_ERROR;
}
@@ -427,19 +434,17 @@ check_tree_conflict(svn_boolean_t *is_co
b->wcroot, conflict_root_relpath,
scratch_pool, scratch_pool));
- SVN_ERR(mark_tree_conflict(b, conflict_root_relpath, old_kind, new_kind,
+ SVN_ERR(mark_tree_conflict(conflict_root_relpath,
+ b->wcroot, b->db, b->old_version, b->new_version,
+ b->move_root_dst_relpath, b->operation,
+ old_kind, new_kind,
old_repos_relpath,
(move_dst_relpath
? svn_wc_conflict_reason_moved_away
: svn_wc_conflict_reason_deleted),
action, move_src_op_root_relpath,
scratch_pool));
- if (b->notify_func)
- SVN_ERR(update_move_list_add(b->wcroot, local_relpath,
- svn_wc_notify_tree_conflict,
- new_kind,
- svn_wc_notify_state_inapplicable,
- svn_wc_notify_state_inapplicable));
+ b->conflict_root_relpath = apr_pstrdup(b->result_pool, conflict_root_relpath);
return SVN_NO_ERROR;
}
@@ -488,7 +493,7 @@ tc_editor_add_directory(void *baton,
/* Check for NODES tree-conflict. */
SVN_ERR(check_tree_conflict(&is_conflicted, b, relpath,
- move_dst_kind, svn_node_dir,
+ old_kind, svn_node_dir,
move_dst_repos_relpath,
svn_wc_conflict_action_add,
scratch_pool));
@@ -503,17 +508,21 @@ tc_editor_add_directory(void *baton,
{
case svn_node_file:
default:
- SVN_ERR(mark_tree_conflict(b, relpath, old_kind, svn_node_dir,
+ SVN_ERR(mark_tree_conflict(relpath, b->wcroot, b->db, b->old_version,
+ b->new_version, b->move_root_dst_relpath,
+ b->operation, old_kind, svn_node_dir,
move_dst_repos_relpath,
svn_wc_conflict_reason_unversioned,
svn_wc_conflict_action_add, NULL,
scratch_pool));
+ b->conflict_root_relpath = apr_pstrdup(b->result_pool, relpath);
action = svn_wc_notify_tree_conflict;
+ is_conflicted = TRUE;
break;
case svn_node_none:
SVN_ERR(svn_wc__wq_build_dir_install(&work_item, b->db, abspath,
- scratch_pool, b->result_pool));
+ scratch_pool, scratch_pool));
SVN_ERR(svn_wc__db_wq_add(b->db, b->wcroot->abspath, work_item,
scratch_pool));
@@ -522,7 +531,7 @@ tc_editor_add_directory(void *baton,
break;
}
- if (b->notify_func)
+ if (!is_conflicted)
SVN_ERR(update_move_list_add(b->wcroot, relpath,
action,
svn_node_dir,
@@ -564,7 +573,7 @@ tc_editor_add_file(void *baton,
if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
{
svn_error_clear(err);
- old_kind = svn_kind_none;
+ old_kind = svn_node_none;
move_dst_repos_relpath = NULL;
}
else
@@ -587,17 +596,14 @@ tc_editor_add_file(void *baton,
if (old_kind != svn_node_none)
{
- SVN_ERR(mark_tree_conflict(b, relpath, old_kind, svn_node_file,
+ SVN_ERR(mark_tree_conflict(relpath, b->wcroot, b->db, b->old_version,
+ b->new_version, b->move_root_dst_relpath,
+ b->operation, old_kind, svn_node_file,
move_dst_repos_relpath,
svn_wc_conflict_reason_unversioned,
svn_wc_conflict_action_add, NULL,
scratch_pool));
- if (b->notify_func)
- SVN_ERR(update_move_list_add(b->wcroot, relpath,
- svn_wc_notify_tree_conflict,
- svn_node_file,
- svn_wc_notify_state_inapplicable,
- svn_wc_notify_state_inapplicable));
+ b->conflict_root_relpath = apr_pstrdup(b->result_pool, relpath);
return SVN_NO_ERROR;
}
@@ -609,17 +615,16 @@ tc_editor_add_file(void *baton,
NULL,
FALSE /* FIXME: use_commit_times? */,
TRUE /* record_file_info */,
- scratch_pool, b->result_pool));
+ scratch_pool, scratch_pool));
SVN_ERR(svn_wc__db_wq_add(b->db, b->wcroot->abspath, work_item,
scratch_pool));
- if (b->notify_func)
- SVN_ERR(update_move_list_add(b->wcroot, relpath,
- svn_wc_notify_update_add,
- svn_node_file,
- svn_wc_notify_state_inapplicable,
- svn_wc_notify_state_inapplicable));
+ SVN_ERR(update_move_list_add(b->wcroot, relpath,
+ svn_wc_notify_update_add,
+ svn_node_file,
+ svn_wc_notify_state_inapplicable,
+ svn_wc_notify_state_inapplicable));
return SVN_NO_ERROR;
}
@@ -652,6 +657,7 @@ typedef struct working_node_version_t
const svn_checksum_t *checksum; /* for files only */
} working_node_version_t;
+/* Return *WORK_ITEMS to create a conflict on LOCAL_ABSPATH. */
static svn_error_t *
create_conflict_markers(svn_skel_t **work_items,
const char *local_abspath,
@@ -661,21 +667,26 @@ create_conflict_markers(svn_skel_t **wor
svn_wc_operation_t operation,
const working_node_version_t *old_version,
const working_node_version_t *new_version,
- svn_kind_t local_kind,
+ svn_node_kind_t kind,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- svn_skel_t *work_item;
svn_wc_conflict_version_t *original_version;
svn_wc_conflict_version_t *conflicted_version;
+ const char *part;
original_version = svn_wc_conflict_version_dup(
old_version->location_and_kind, scratch_pool);
- original_version->path_in_repos = repos_relpath;
-
+ original_version->node_kind = kind;
conflicted_version = svn_wc_conflict_version_dup(
new_version->location_and_kind, scratch_pool);
- conflicted_version->node_kind = svn__node_kind_from_kind(local_kind);
+ conflicted_version->node_kind = kind;
+
+ part = svn_relpath_skip_ancestor(original_version->path_in_repos,
+ repos_relpath);
+ conflicted_version->path_in_repos
+ = svn_relpath_join(conflicted_version->path_in_repos, part, scratch_pool);
+ original_version->path_in_repos = repos_relpath;
if (operation == svn_wc_operation_update)
{
@@ -694,12 +705,11 @@ create_conflict_markers(svn_skel_t **wor
/* According to this func's doc string, it is "Currently only used for
* property conflicts as text conflict markers are just in-wc files." */
- SVN_ERR(svn_wc__conflict_create_markers(&work_item, db,
+ SVN_ERR(svn_wc__conflict_create_markers(work_items, db,
local_abspath,
conflict_skel,
result_pool,
scratch_pool));
- *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
return SVN_NO_ERROR;
}
@@ -788,7 +798,8 @@ tc_editor_alter_directory(void *baton,
SVN_ERR_ASSERT(move_dst_kind == svn_kind_dir);
SVN_ERR(check_tree_conflict(&is_conflicted, b, dst_relpath,
- move_dst_kind, svn_node_dir,
+ svn__node_kind_from_kind(move_dst_kind),
+ svn_node_dir,
move_dst_repos_relpath,
svn_wc_conflict_action_edit,
scratch_pool));
@@ -815,27 +826,30 @@ tc_editor_alter_directory(void *baton,
&propchanges, &actual_props,
b->db, dst_abspath,
&old_version, &new_version,
- b->result_pool, scratch_pool));
+ scratch_pool, scratch_pool));
if (conflict_skel)
{
- SVN_ERR(create_conflict_markers(b->work_items, dst_abspath,
+ svn_skel_t *work_items;
+
+ SVN_ERR(create_conflict_markers(&work_items, dst_abspath,
b->db, move_dst_repos_relpath,
conflict_skel, b->operation,
&old_version, &new_version,
- move_dst_kind,
- b->result_pool, scratch_pool));
+ svn_node_dir,
+ scratch_pool, scratch_pool));
SVN_ERR(svn_wc__db_mark_conflict_internal(b->wcroot, dst_relpath,
conflict_skel,
scratch_pool));
+ SVN_ERR(svn_wc__db_wq_add(b->db, b->wcroot->abspath, work_items,
+ scratch_pool));
}
- if (b->notify_func)
- SVN_ERR(update_move_list_add(b->wcroot, dst_relpath,
- svn_wc_notify_update_update,
- svn_node_dir,
- svn_wc_notify_state_inapplicable,
- prop_state));
+ SVN_ERR(update_move_list_add(b->wcroot, dst_relpath,
+ svn_wc_notify_update_update,
+ svn_node_dir,
+ svn_wc_notify_state_inapplicable,
+ prop_state));
}
return SVN_NO_ERROR;
@@ -857,17 +871,13 @@ tc_editor_alter_directory(void *baton,
* Set *WORK_ITEMS to any required work items, allocated in RESULT_POOL.
* Use SCRATCH_POOL for temporary allocations. */
static svn_error_t *
-update_working_file(svn_skel_t **work_items,
- const char *local_relpath,
+update_working_file(const char *local_relpath,
const char *repos_relpath,
svn_wc_operation_t operation,
const working_node_version_t *old_version,
const working_node_version_t *new_version,
svn_wc__db_wcroot_t *wcroot,
svn_wc__db_t *db,
- svn_wc_notify_func2_t notify_func,
- void *notify_baton,
- apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
const char *local_abspath = svn_dirent_join(wcroot->abspath,
@@ -880,84 +890,91 @@ update_working_file(svn_skel_t **work_it
apr_array_header_t *propchanges;
enum svn_wc_merge_outcome_t merge_outcome;
svn_wc_notify_state_t prop_state, content_state;
- svn_skel_t *work_item;
-
- *work_items = NULL;
+ svn_skel_t *work_item, *work_items = NULL;
SVN_ERR(update_working_props(&prop_state, &conflict_skel, &propchanges,
&actual_props, db, local_abspath,
old_version, new_version,
- result_pool, scratch_pool));
+ scratch_pool, scratch_pool));
- /*
- * Run a 3-way merge to update the file, using the pre-update
- * pristine text as the merge base, the post-update pristine
- * text as the merge-left version, and the current content of the
- * moved-here working file as the merge-right version.
- */
- SVN_ERR(svn_wc__db_pristine_get_path(&old_pristine_abspath,
- db, wcroot->abspath,
- old_version->checksum,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_wc__db_pristine_get_path(&new_pristine_abspath,
- db, wcroot->abspath,
- new_version->checksum,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_wc__internal_merge(&work_item, &conflict_skel,
- &merge_outcome, db,
- old_pristine_abspath,
- new_pristine_abspath,
- local_abspath,
- local_abspath,
- NULL, NULL, NULL, /* diff labels */
- actual_props,
- FALSE, /* dry-run */
- NULL, /* diff3-cmd */
- NULL, /* merge options */
- propchanges,
- NULL, NULL, /* cancel_func + baton */
- result_pool, scratch_pool));
+ if (!svn_checksum_match(new_version->checksum, old_version->checksum))
+ {
+ /*
+ * Run a 3-way merge to update the file, using the pre-update
+ * pristine text as the merge base, the post-update pristine
+ * text as the merge-left version, and the current content of the
+ * moved-here working file as the merge-right version.
+ */
+ SVN_ERR(svn_wc__db_pristine_get_path(&old_pristine_abspath,
+ db, wcroot->abspath,
+ old_version->checksum,
+ scratch_pool, scratch_pool));
+ SVN_ERR(svn_wc__db_pristine_get_path(&new_pristine_abspath,
+ db, wcroot->abspath,
+ new_version->checksum,
+ scratch_pool, scratch_pool));
+ SVN_ERR(svn_wc__internal_merge(&work_item, &conflict_skel,
+ &merge_outcome, db,
+ old_pristine_abspath,
+ new_pristine_abspath,
+ local_abspath,
+ local_abspath,
+ NULL, NULL, NULL, /* diff labels */
+ actual_props,
+ FALSE, /* dry-run */
+ NULL, /* diff3-cmd */
+ NULL, /* merge options */
+ propchanges,
+ NULL, NULL, /* cancel_func + baton */
+ scratch_pool, scratch_pool));
- *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
+ work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
+
+ if (merge_outcome == svn_wc_merge_conflict)
+ {
+ content_state = svn_wc_notify_state_conflicted;
+ }
+ else
+ {
+ svn_boolean_t is_locally_modified;
+
+ SVN_ERR(svn_wc__internal_file_modified_p(&is_locally_modified,
+ db, local_abspath,
+ FALSE /* exact_comparison */,
+ scratch_pool));
+ if (is_locally_modified)
+ content_state = svn_wc_notify_state_merged;
+ else
+ content_state = svn_wc_notify_state_changed;
+ }
+ }
+ else
+ content_state = svn_wc_notify_state_unchanged;
/* If there are any conflicts to be stored, convert them into work items
* too. */
if (conflict_skel)
{
- SVN_ERR(create_conflict_markers(work_items, local_abspath, db,
+ SVN_ERR(create_conflict_markers(&work_item, local_abspath, db,
repos_relpath, conflict_skel,
operation, old_version, new_version,
- svn_kind_file,
- result_pool, scratch_pool));
+ svn_node_file,
+ scratch_pool, scratch_pool));
+
SVN_ERR(svn_wc__db_mark_conflict_internal(wcroot, local_relpath,
conflict_skel,
scratch_pool));
- }
- if (merge_outcome == svn_wc_merge_conflict)
- {
- content_state = svn_wc_notify_state_conflicted;
+ work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
}
- else
- {
- svn_boolean_t is_locally_modified;
- SVN_ERR(svn_wc__internal_file_modified_p(&is_locally_modified,
- db, local_abspath,
- FALSE /* exact_comparison */,
- scratch_pool));
- if (is_locally_modified)
- content_state = svn_wc_notify_state_merged;
- else
- content_state = svn_wc_notify_state_changed;
- }
+ SVN_ERR(svn_wc__db_wq_add(db, wcroot->abspath, work_items, scratch_pool));
- if (notify_func)
- SVN_ERR(update_move_list_add(wcroot, local_relpath,
- svn_wc_notify_update_update,
- svn_node_file,
- content_state,
- prop_state));
+ SVN_ERR(update_move_list_add(wcroot, local_relpath,
+ svn_wc_notify_update_update,
+ svn_node_file,
+ content_state,
+ prop_state));
return SVN_NO_ERROR;
}
@@ -993,7 +1010,8 @@ tc_editor_alter_file(void *baton,
SVN_ERR_ASSERT(move_dst_kind == svn_kind_file);
SVN_ERR(check_tree_conflict(&is_conflicted, b, dst_relpath,
- move_dst_kind, svn_node_file,
+ svn__node_kind_from_kind(move_dst_kind),
+ svn_node_file,
move_dst_repos_relpath,
svn_wc_conflict_action_edit,
scratch_pool));
@@ -1010,16 +1028,10 @@ tc_editor_alter_file(void *baton,
/* Update file and prop contents if the update has changed them. */
if (!svn_checksum_match(new_checksum, old_version.checksum) || new_props)
{
- svn_skel_t *work_items;
-
- SVN_ERR(update_working_file(&work_items, dst_relpath,
- move_dst_repos_relpath,
+ SVN_ERR(update_working_file(dst_relpath, move_dst_repos_relpath,
b->operation, &old_version, &new_version,
b->wcroot, b->db,
- b->notify_func, b->notify_baton,
- b->result_pool, scratch_pool));
- *b->work_items = svn_wc__wq_merge(*b->work_items, work_items,
- b->result_pool);
+ scratch_pool));
}
return SVN_NO_ERROR;
@@ -1063,7 +1075,8 @@ tc_editor_delete(void *baton,
conflicts. This catches conflicts on the node itself; deleted
children are caught as local modifications below.*/
SVN_ERR(check_tree_conflict(&is_conflicted, b, relpath,
- move_dst_kind, svn_node_unknown,
+ svn__node_kind_from_kind(move_dst_kind),
+ svn_node_unknown,
move_dst_repos_relpath,
svn_wc_conflict_action_delete,
scratch_pool));
@@ -1104,16 +1117,15 @@ tc_editor_delete(void *baton,
must_delete_working_nodes = TRUE;
}
is_conflicted = TRUE;
- SVN_ERR(mark_tree_conflict(b, relpath, move_dst_kind, svn_node_none,
+ SVN_ERR(mark_tree_conflict(relpath, b->wcroot, b->db, b->old_version,
+ b->new_version, b->move_root_dst_relpath,
+ b->operation,
+ svn__node_kind_from_kind(move_dst_kind),
+ svn_node_none,
move_dst_repos_relpath, reason,
svn_wc_conflict_action_delete, NULL,
scratch_pool));
- if (b->notify_func)
- SVN_ERR(update_move_list_add(b->wcroot, relpath,
- svn_wc_notify_tree_conflict,
- svn_node_dir, /* ### kinds? */
- svn_wc_notify_state_inapplicable,
- svn_wc_notify_state_inapplicable));
+ b->conflict_root_relpath = apr_pstrdup(b->result_pool, relpath);
}
}
@@ -1176,7 +1188,7 @@ tc_editor_delete(void *baton,
SVN_ERR(svn_wc__db_wq_add(b->db, b->wcroot->abspath, work_item,
iterpool));
- if (b->notify_func && !is_conflicted)
+ if (!is_conflicted)
SVN_ERR(update_move_list_add(b->wcroot, relpath,
svn_wc_notify_update_delete,
svn__node_kind_from_kind(del_kind),
@@ -1234,30 +1246,6 @@ static svn_error_t *
tc_editor_complete(void *baton,
apr_pool_t *scratch_pool)
{
- struct tc_editor_baton *b = baton;
-
- /* Send all queued up notifications. */
- SVN_ERR(update_move_list_notify(b->wcroot,
- b->old_version->peg_rev,
- b->new_version->peg_rev,
- b->notify_func, b->notify_baton,
- scratch_pool));
- if (b->notify_func)
- {
- svn_wc_notify_t *notify;
-
- notify = svn_wc_create_notify(svn_dirent_join(b->wcroot->abspath,
- b->move_root_dst_relpath,
- scratch_pool),
- svn_wc_notify_update_completed,
- scratch_pool);
- notify->kind = svn_node_none;
- notify->content_state = svn_wc_notify_state_inapplicable;
- notify->prop_state = svn_wc_notify_state_inapplicable;
- notify->revision = b->new_version->peg_rev;
- b->notify_func(b->notify_baton, notify, scratch_pool);
- }
-
return SVN_NO_ERROR;
}
@@ -1763,15 +1751,28 @@ suitable_for_move(svn_wc__db_wcroot_t *w
relpath = svn_relpath_skip_ancestor(local_relpath, relpath);
relpath = svn_relpath_join(repos_relpath, relpath, iterpool);
- if (revision != node_revision
- || strcmp(relpath, svn_sqlite__column_text(stmt, 1, NULL)))
+ if (revision != node_revision)
+ return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE,
+ svn_sqlite__reset(stmt),
+ _("Cannot apply update because move source "
+ "%s' is a mixed-revision working copy"),
+ svn_dirent_local_style(svn_dirent_join(
+ wcroot->abspath,
+ local_relpath,
+ scratch_pool),
+ scratch_pool));
+
+ if (strcmp(relpath, svn_sqlite__column_text(stmt, 1, NULL)))
return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE,
svn_sqlite__reset(stmt),
- _("The tree '%s' is not single-revision and unswitched"),
- svn_dirent_local_style(svn_dirent_join(wcroot->abspath,
- local_relpath,
- scratch_pool),
- scratch_pool));
+ _("Cannot apply update because move source "
+ "'%s' is a switched subtree"),
+ svn_dirent_local_style(svn_dirent_join(
+ wcroot->abspath,
+ local_relpath,
+ scratch_pool),
+ scratch_pool));
+
SVN_ERR(svn_sqlite__step(&have_row, stmt));
}
SVN_ERR(svn_sqlite__reset(stmt));
@@ -1784,8 +1785,7 @@ suitable_for_move(svn_wc__db_wcroot_t *w
/* The body of svn_wc__db_update_moved_away_conflict_victim(), which see.
*/
static svn_error_t *
-update_moved_away_conflict_victim(svn_skel_t **work_items,
- svn_wc__db_t *db,
+update_moved_away_conflict_victim(svn_wc__db_t *db,
svn_wc__db_wcroot_t *wcroot,
const char *victim_relpath,
svn_wc_operation_t operation,
@@ -1794,11 +1794,8 @@ update_moved_away_conflict_victim(svn_sk
const char *move_src_op_root_relpath,
svn_wc_conflict_version_t *old_version,
svn_wc_conflict_version_t *new_version,
- svn_wc_notify_func2_t notify_func,
- void *notify_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
- apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
svn_editor_t *tc_editor;
@@ -1807,6 +1804,7 @@ update_moved_away_conflict_victim(svn_sk
svn_boolean_t have_row;
const char *dummy1, *dummy2, *dummy3;
int src_op_depth;
+ const char *move_root_dst_abspath;
/* ### assumes wc write lock already held */
@@ -1823,15 +1821,18 @@ update_moved_away_conflict_victim(svn_sk
svn_dirent_join(wcroot->abspath, victim_relpath,
scratch_pool),
scratch_pool));
+
+ move_root_dst_abspath
+ = svn_dirent_join(wcroot->abspath, tc_editor_baton->move_root_dst_relpath,
+ scratch_pool);
+ SVN_ERR(svn_wc__write_check(db, move_root_dst_abspath, scratch_pool));
+
tc_editor_baton->operation = operation;
tc_editor_baton->old_version= old_version;
tc_editor_baton->new_version= new_version;
tc_editor_baton->db = db;
tc_editor_baton->wcroot = wcroot;
- tc_editor_baton->work_items = work_items;
- tc_editor_baton->notify_func = notify_func;
- tc_editor_baton->notify_baton = notify_baton;
- tc_editor_baton->result_pool = result_pool;
+ tc_editor_baton->result_pool = scratch_pool;
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_SELECT_HIGHEST_WORKING_NODE));
@@ -1880,14 +1881,12 @@ update_moved_away_conflict_victim(svn_sk
svn_error_t *
-svn_wc__db_update_moved_away_conflict_victim(svn_skel_t **work_items,
- svn_wc__db_t *db,
+svn_wc__db_update_moved_away_conflict_victim(svn_wc__db_t *db,
const char *victim_abspath,
svn_wc_notify_func2_t notify_func,
void *notify_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
- apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
svn_wc__db_wcroot_t *wcroot;
@@ -1905,6 +1904,8 @@ svn_wc__db_update_moved_away_conflict_vi
db, victim_abspath,
scratch_pool, scratch_pool));
+ SVN_ERR(svn_wc__write_check(db, move_src_op_root_abspath, scratch_pool));
+
SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath,
db, victim_abspath,
scratch_pool, scratch_pool));
@@ -1915,15 +1916,158 @@ svn_wc__db_update_moved_away_conflict_vi
SVN_WC__DB_WITH_TXN(
update_moved_away_conflict_victim(
- work_items, db, wcroot, local_relpath,
+ db, wcroot, local_relpath,
operation, local_change, incoming_change,
move_src_op_root_relpath,
old_version, new_version,
- notify_func, notify_baton,
cancel_func, cancel_baton,
- result_pool, scratch_pool),
+ scratch_pool),
wcroot);
+ /* Send all queued up notifications. */
+ SVN_ERR(svn_wc__db_update_move_list_notify(wcroot,
+ old_version->peg_rev,
+ new_version->peg_rev,
+ notify_func, notify_baton,
+ scratch_pool));
+ if (notify_func)
+ {
+ svn_wc_notify_t *notify;
+
+ notify = svn_wc_create_notify(svn_dirent_join(wcroot->abspath,
+ local_relpath,
+ scratch_pool),
+ svn_wc_notify_update_completed,
+ scratch_pool);
+ notify->kind = svn_node_none;
+ notify->content_state = svn_wc_notify_state_inapplicable;
+ notify->prop_state = svn_wc_notify_state_inapplicable;
+ notify->revision = new_version->peg_rev;
+ notify_func(notify_baton, notify, scratch_pool);
+ }
+
+
+ return SVN_NO_ERROR;
+}
+
+/* Set *CAN_BUMP to TRUE if DEPTH is sufficient to cover the entire
+ BASE tree at LOCAL_RELPATH, to FALSE otherwise. */
+static svn_error_t *
+depth_sufficient_to_bump(svn_boolean_t *can_bump,
+ const char *local_relpath,
+ svn_wc__db_wcroot_t *wcroot,
+ svn_depth_t depth,
+ apr_pool_t *scratch_pool)
+{
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
+
+ switch (depth)
+ {
+ case svn_depth_infinity:
+ *can_bump = TRUE;
+ return SVN_NO_ERROR;
+
+ case svn_depth_empty:
+ 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, 0));
+ break;
+
+ case svn_depth_files:
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_SELECT_HAS_NON_FILE_CHILDREN));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id,
+ local_relpath));
+ break;
+
+ case svn_depth_immediates:
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_SELECT_HAS_GRANDCHILDREN));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id,
+ local_relpath));
+ break;
+ default:
+ SVN_ERR_MALFUNCTION();
+ }
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ SVN_ERR(svn_sqlite__reset(stmt));
+
+ *can_bump = !have_row;
+ return SVN_NO_ERROR;
+}
+
+/* Mark a move-edit conflict on MOVE_SRC_ROOT_RELPATH. */
+static svn_error_t *
+bump_mark_tree_conflict(svn_wc__db_wcroot_t *wcroot,
+ const char *move_src_root_relpath,
+ const char *move_src_op_root_relpath,
+ const char *move_dst_op_root_relpath,
+ svn_wc__db_t *db,
+ apr_pool_t *scratch_pool)
+{
+ apr_int64_t repos_id;
+ const char *repos_root_url;
+ const char *repos_uuid;
+ const char *old_repos_relpath;
+ const char *new_repos_relpath;
+ svn_revnum_t old_rev;
+ svn_revnum_t new_rev;
+ const char *old_repos_url;
+ const char *new_repos_url;
+ svn_kind_t old_kind;
+ svn_kind_t new_kind;
+ svn_wc_conflict_version_t *old_version;
+ svn_wc_conflict_version_t *new_version;
+
+ /* Read new (post-update) information from the new move source BASE node. */
+ SVN_ERR(svn_wc__db_base_get_info_internal(NULL, &new_kind, &new_rev,
+ &new_repos_relpath, &repos_id,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ wcroot, move_src_op_root_relpath,
+ scratch_pool, scratch_pool));
+ SVN_ERR(svn_wc__db_fetch_repos_info(&repos_root_url, &repos_uuid,
+ wcroot->sdb, repos_id, scratch_pool));
+ new_repos_url = svn_uri_canonicalize(apr_pstrcat(scratch_pool,
+ repos_root_url, "/",
+ new_repos_relpath,
+ (const char *)NULL),
+ scratch_pool);
+
+ /* Read old (pre-update) information from the move destination node. */
+ SVN_ERR(svn_wc__db_depth_get_info(NULL, &old_kind, &old_rev,
+ &old_repos_relpath, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ wcroot, move_dst_op_root_relpath,
+ relpath_depth(move_dst_op_root_relpath),
+ scratch_pool, scratch_pool));
+ old_repos_url = svn_uri_canonicalize(apr_pstrcat(scratch_pool,
+ repos_root_url, "/",
+ old_repos_relpath,
+ (const char *)NULL),
+ scratch_pool);
+
+ old_version = svn_wc_conflict_version_create2(
+ old_repos_url, repos_uuid, old_repos_relpath, old_rev,
+ svn__node_kind_from_kind(old_kind), scratch_pool);
+ new_version = svn_wc_conflict_version_create2(
+ new_repos_url, repos_uuid, new_repos_relpath, new_rev,
+ svn__node_kind_from_kind(new_kind), scratch_pool);
+
+ SVN_ERR(mark_tree_conflict(move_src_root_relpath,
+ wcroot, db, old_version, new_version,
+ move_dst_op_root_relpath,
+ svn_wc_operation_update,
+ svn__node_kind_from_kind(old_kind),
+ svn__node_kind_from_kind(new_kind),
+ old_repos_relpath,
+ svn_wc_conflict_reason_moved_away,
+ svn_wc_conflict_action_edit,
+ move_src_op_root_relpath,
+ scratch_pool));
+
return SVN_NO_ERROR;
}
@@ -1936,6 +2080,8 @@ bump_moved_away(svn_wc__db_wcroot_t *wcr
const char *local_relpath,
int op_depth,
apr_hash_t *src_done,
+ svn_depth_t depth,
+ svn_wc__db_t *db,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
@@ -1957,12 +2103,51 @@ bump_moved_away(svn_wc__db_wcroot_t *wcr
int src_op_depth = svn_sqlite__column_int(stmt, 2);
svn_error_t *err;
svn_skel_t *conflict;
+ svn_depth_t src_depth = depth;
svn_pool_clear(iterpool);
src_relpath = svn_sqlite__column_text(stmt, 0, iterpool);
dst_relpath = svn_sqlite__column_text(stmt, 1, iterpool);
+ if (depth != svn_depth_infinity)
+ {
+ svn_boolean_t skip_this_src = FALSE;
+ svn_kind_t src_kind;
+
+ if (strcmp(src_relpath, local_relpath))
+ {
+ switch (depth)
+ {
+ case svn_depth_empty:
+ skip_this_src = TRUE;
+ break;
+ case svn_depth_files:
+ src_kind = svn_sqlite__column_token(stmt, 3, kind_map);
+ if (src_kind != svn_kind_file)
+ {
+ skip_this_src = TRUE;
+ break;
+ }
+ /* Fallthrough */
+ case svn_depth_immediates:
+ if (strcmp(svn_relpath_dirname(src_relpath, scratch_pool),
+ local_relpath))
+ skip_this_src = TRUE;
+ src_depth = svn_depth_empty;
+ break;
+ default:
+ SVN_ERR_MALFUNCTION();
+ }
+ }
+
+ if (skip_this_src)
+ {
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ continue;
+ }
+ }
+
err = svn_sqlite__get_statement(&stmt2, wcroot->sdb,
STMT_HAS_LAYER_BETWEEN);
if (!err)
@@ -1974,29 +2159,55 @@ bump_moved_away(svn_wc__db_wcroot_t *wcr
err = svn_sqlite__reset(stmt2);
if (!err && !have_row)
{
+ svn_boolean_t can_bump;
const char *src_root_relpath = src_relpath;
- while (relpath_depth(src_root_relpath) > src_op_depth)
- src_root_relpath = svn_relpath_dirname(src_root_relpath, iterpool);
+ if (op_depth == 0)
+ err = depth_sufficient_to_bump(&can_bump, src_relpath, wcroot,
+ src_depth, scratch_pool);
+ else
+ /* Having chosen to bump an entire BASE tree move we
+ always have sufficient depth to bump subtree moves. */
+ can_bump = TRUE;
- if (!apr_hash_get(src_done, src_relpath, APR_HASH_KEY_STRING))
+ if (!err)
{
- apr_hash_set(src_done, apr_pstrdup(result_pool, src_relpath),
- APR_HASH_KEY_STRING, "");
- err = svn_wc__db_read_conflict_internal(&conflict, wcroot,
- src_root_relpath,
- iterpool, iterpool);
- /* ### TODO: check this is the right sort of tree-conflict? */
- if (!err && !conflict)
+ if (!can_bump)
+ {
+ err = bump_mark_tree_conflict(wcroot, src_relpath,
+ src_root_relpath, dst_relpath,
+ db, scratch_pool);
+ if (err)
+ return svn_error_compose_create(err,
+ svn_sqlite__reset(stmt));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ continue;
+ }
+
+ while (relpath_depth(src_root_relpath) > src_op_depth)
+ src_root_relpath = svn_relpath_dirname(src_root_relpath,
+ iterpool);
+
+ if (!apr_hash_get(src_done, src_relpath, APR_HASH_KEY_STRING))
{
- /* ### TODO: verify moved_here? */
- err = replace_moved_layer(src_relpath, dst_relpath, op_depth,
- wcroot, iterpool);
-
- if (!err)
- err = bump_moved_away(wcroot, dst_relpath,
- relpath_depth(dst_relpath), src_done,
- result_pool, iterpool);
+ apr_hash_set(src_done, apr_pstrdup(result_pool, src_relpath),
+ APR_HASH_KEY_STRING, "");
+ err = svn_wc__db_read_conflict_internal(&conflict, wcroot,
+ src_root_relpath,
+ iterpool, iterpool);
+ /* ### TODO: check this is the right sort of tree-conflict? */
+ if (!err && !conflict)
+ {
+ /* ### TODO: verify moved_here? */
+ err = replace_moved_layer(src_relpath, dst_relpath,
+ op_depth, wcroot, iterpool);
+
+ if (!err)
+ err = bump_moved_away(wcroot, dst_relpath,
+ relpath_depth(dst_relpath),
+ src_done, depth, db,
+ result_pool, iterpool);
+ }
}
}
}
@@ -2017,16 +2228,37 @@ svn_error_t *
svn_wc__db_bump_moved_away(svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
svn_depth_t depth,
+ svn_wc__db_t *db,
apr_pool_t *scratch_pool)
{
+ const char *dummy1, *move_dst_op_root_relpath;
+ const char *move_src_root_relpath, *move_src_op_root_relpath;
apr_hash_t *src_done;
- /* ### TODO: raise tree-conflicts? */
- if (depth != svn_depth_infinity)
- return SVN_NO_ERROR;
+ SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb,
+ STMT_CREATE_UPDATE_MOVE_LIST));
+
+ SVN_ERR(svn_wc__db_op_depth_moved_to(&dummy1, &move_dst_op_root_relpath,
+ &move_src_root_relpath,
+ &move_src_op_root_relpath, 0,
+ wcroot, local_relpath,
+ scratch_pool, scratch_pool));
+
+ if (move_src_root_relpath)
+ {
+ if (strcmp(move_src_root_relpath, local_relpath))
+ {
+ SVN_ERR(bump_mark_tree_conflict(wcroot, move_src_root_relpath,
+ move_src_op_root_relpath,
+ move_dst_op_root_relpath,
+ db, scratch_pool));
+ return SVN_NO_ERROR;
+ }
+
+ }
src_done = apr_hash_make(scratch_pool);
- SVN_ERR(bump_moved_away(wcroot, local_relpath, 0, src_done,
+ SVN_ERR(bump_moved_away(wcroot, local_relpath, 0, src_done, depth, db,
scratch_pool, scratch_pool));
return SVN_NO_ERROR;
@@ -2047,6 +2279,9 @@ resolve_delete_raise_moved_away(svn_wc__
int op_depth = relpath_depth(local_relpath);
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb,
+ STMT_CREATE_UPDATE_MOVE_LIST));
+
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_SELECT_OP_DEPTH_MOVED_PAIR));
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
@@ -2054,30 +2289,22 @@ resolve_delete_raise_moved_away(svn_wc__
SVN_ERR(svn_sqlite__step(&have_row, stmt));
while(have_row)
{
- struct tc_editor_baton b;
-
const char *moved_relpath = svn_sqlite__column_text(stmt, 0, NULL);
+ const char *move_root_dst_relpath = svn_sqlite__column_text(stmt, 1,
+ NULL);
const char *moved_dst_repos_relpath = svn_sqlite__column_text(stmt, 2,
NULL);
-
svn_pool_clear(iterpool);
- b.wcroot = wcroot;
- b.db = db;
- b.operation = operation;
- b.old_version = old_version;
- b.new_version = new_version;
- b.move_root_dst_relpath = svn_sqlite__column_text(stmt, 1, NULL);
- b.result_pool = scratch_pool;
-
- SVN_ERR(mark_tree_conflict(&b, moved_relpath,
+ SVN_ERR(mark_tree_conflict(moved_relpath,
+ wcroot, db, old_version, new_version,
+ move_root_dst_relpath, operation,
svn_node_dir /* ### ? */,
svn_node_dir /* ### ? */,
moved_dst_repos_relpath,
svn_wc_conflict_reason_moved_away,
- action, local_relpath, iterpool));
-
- /* ### Do notification? */
+ action, local_relpath,
+ iterpool));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
}
@@ -2091,6 +2318,8 @@ resolve_delete_raise_moved_away(svn_wc__
svn_error_t *
svn_wc__db_resolve_delete_raise_moved_away(svn_wc__db_t *db,
const char *local_abspath,
+ svn_wc_notify_func2_t notify_func,
+ void *notify_baton,
apr_pool_t *scratch_pool)
{
svn_wc__db_wcroot_t *wcroot;
@@ -2116,6 +2345,40 @@ svn_wc__db_resolve_delete_raise_moved_aw
scratch_pool),
wcroot);
+ SVN_ERR(svn_wc__db_update_move_list_notify(wcroot,
+ old_version->peg_rev,
+ (new_version
+ ? new_version->peg_rev
+ : SVN_INVALID_REVNUM),
+ notify_func, notify_baton,
+ scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+break_move(svn_wc__db_wcroot_t *wcroot,
+ const char *src_relpath,
+ int src_op_depth,
+ const char *dst_relpath,
+ int dst_op_depth,
+ apr_pool_t *scratch_pool)
+{
+ svn_sqlite__stmt_t *stmt;
+
+ 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__step_done(stmt));
+
+ /* This statement clears moved_here. */
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_UPDATE_OP_DEPTH_RECURSIVE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isdd", wcroot->wc_id,
+ dst_relpath, dst_op_depth, dst_op_depth));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+
return SVN_NO_ERROR;
}
@@ -2126,8 +2389,6 @@ svn_wc__db_resolve_break_moved_away_inte
{
const char *dummy1, *move_dst_op_root_relpath;
const char *dummy2, *move_src_op_root_relpath;
- svn_sqlite__stmt_t *stmt;
- int dst_op_depth;
SVN_ERR(svn_wc__db_op_depth_moved_to(&dummy1, &move_dst_op_root_relpath,
&dummy2,
@@ -2135,21 +2396,53 @@ svn_wc__db_resolve_break_moved_away_inte
relpath_depth(local_relpath) - 1,
wcroot, local_relpath,
scratch_pool, scratch_pool));
- dst_op_depth = relpath_depth(move_dst_op_root_relpath);
+ SVN_ERR(break_move(wcroot, local_relpath,
+ relpath_depth(move_src_op_root_relpath),
+ move_dst_op_root_relpath,
+ relpath_depth(move_dst_op_root_relpath),
+ scratch_pool));
- SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_CLEAR_MOVED_TO_RELPATH));
- SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
- relpath_depth(move_src_op_root_relpath)));
- SVN_ERR(svn_sqlite__step_done(stmt));
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+break_moved_away_children_internal(svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *scratch_pool)
+{
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
+ apr_pool_t *iterpool;
+
+ SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb,
+ STMT_CREATE_UPDATE_MOVE_LIST));
- /* This statement clears moved_here. */
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_UPDATE_OP_DEPTH_RECURSIVE));
- SVN_ERR(svn_sqlite__bindf(stmt, "isdd", wcroot->wc_id,
- move_dst_op_root_relpath,
- dst_op_depth, dst_op_depth));
- SVN_ERR(svn_sqlite__step_done(stmt));
+ STMT_SELECT_MOVED_PAIR2));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+ iterpool = svn_pool_create(scratch_pool);
+ while (have_row)
+ {
+ const char *src_relpath = svn_sqlite__column_text(stmt, 0, iterpool);
+ const char *dst_relpath = svn_sqlite__column_text(stmt, 1, iterpool);
+ int src_op_depth = svn_sqlite__column_int(stmt, 2);
+
+ svn_pool_clear(iterpool);
+
+ SVN_ERR(break_move(wcroot, src_relpath, src_op_depth, dst_relpath,
+ relpath_depth(dst_relpath), iterpool));
+ SVN_ERR(update_move_list_add(wcroot, src_relpath,
+ svn_wc_notify_move_broken,
+ svn_node_unknown,
+ svn_wc_notify_state_inapplicable,
+ svn_wc_notify_state_inapplicable));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ }
+ svn_pool_destroy(iterpool);
+
+ SVN_ERR(svn_sqlite__reset(stmt));
return SVN_NO_ERROR;
}
@@ -2157,6 +2450,8 @@ svn_wc__db_resolve_break_moved_away_inte
svn_error_t *
svn_wc__db_resolve_break_moved_away(svn_wc__db_t *db,
const char *local_abspath,
+ svn_wc_notify_func2_t notify_func,
+ void *notify_baton,
apr_pool_t *scratch_pool)
{
svn_wc__db_wcroot_t *wcroot;
@@ -2172,5 +2467,116 @@ svn_wc__db_resolve_break_moved_away(svn_
scratch_pool),
wcroot);
+ if (notify_func)
+ {
+ svn_wc_notify_t *notify;
+
+ notify = svn_wc_create_notify(svn_dirent_join(wcroot->abspath,
+ local_relpath,
+ scratch_pool),
+ svn_wc_notify_move_broken,
+ scratch_pool);
+ notify->kind = svn_node_unknown;
+ notify->content_state = svn_wc_notify_state_inapplicable;
+ notify->prop_state = svn_wc_notify_state_inapplicable;
+ notify->revision = SVN_INVALID_REVNUM;
+ notify_func(notify_baton, notify, scratch_pool);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__db_resolve_break_moved_away_children(svn_wc__db_t *db,
+ const char *local_abspath,
+ svn_wc_notify_func2_t notify_func,
+ void *notify_baton,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_wcroot_t *wcroot;
+ const char *local_relpath;
+
+ 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(
+ break_moved_away_children_internal(wcroot, local_relpath, scratch_pool),
+ wcroot);
+
+ SVN_ERR(svn_wc__db_update_move_list_notify(wcroot,
+ SVN_INVALID_REVNUM,
+ SVN_INVALID_REVNUM,
+ notify_func, notify_baton,
+ scratch_pool));
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+required_lock_for_resolve(const char **required_relpath,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
+
+ *required_relpath = local_relpath;
+
+ /* This simply looks for all moves out of the LOCAL_RELPATH tree. We
+ could attempt to limit it to only those moves that are going to
+ be resolved but that would require second guessing the resolver.
+ This simple algorithm is sufficient although it may give a
+ strictly larger/deeper lock than necessary. */
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_SELECT_MOVED_OUTSIDE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath, 0));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+ while (have_row)
+ {
+ const char *move_dst_relpath = svn_sqlite__column_text(stmt, 1,
+ NULL);
+
+ *required_relpath
+ = svn_relpath_get_longest_ancestor(*required_relpath,
+ move_dst_relpath,
+ scratch_pool);
+
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ }
+ SVN_ERR(svn_sqlite__reset(stmt));
+
+ *required_relpath = apr_pstrdup(result_pool, *required_relpath);
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__required_lock_for_resolve(const char **required_abspath,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_wcroot_t *wcroot;
+ const char *local_relpath;
+ const char *required_relpath;
+
+ 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(
+ required_lock_for_resolve(&required_relpath, wcroot, local_relpath,
+ scratch_pool, scratch_pool),
+ wcroot);
+
+ *required_abspath = svn_dirent_join(wcroot->abspath, required_relpath,
+ result_pool);
+
return SVN_NO_ERROR;
}
Modified: subversion/branches/fsfs-format7/subversion/libsvn_wc/workqueue.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_wc/workqueue.c?rev=1453290&r1=1453289&r2=1453290&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_wc/workqueue.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_wc/workqueue.c Wed Mar 6 11:10:01 2013
@@ -63,10 +63,12 @@
/* For work queue debugging. Generates output about its operation. */
/* #define SVN_DEBUG_WORK_QUEUE */
+typedef struct work_item_baton_t work_item_baton_t;
struct work_item_dispatch {
const char *name;
- svn_error_t *(*func)(svn_wc__db_t *db,
+ svn_error_t *(*func)(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -74,30 +76,12 @@ struct work_item_dispatch {
apr_pool_t *scratch_pool);
};
-
+/* Forward definition */
static svn_error_t *
-get_and_record_fileinfo(svn_wc__db_t *db,
+get_and_record_fileinfo(work_item_baton_t *wqb,
const char *local_abspath,
svn_boolean_t ignore_enoent,
- apr_pool_t *scratch_pool)
-{
- const svn_io_dirent2_t *dirent;
-
- SVN_ERR(svn_io_stat_dirent(&dirent, local_abspath, ignore_enoent,
- scratch_pool, scratch_pool));
-
- if (dirent->kind == svn_node_none)
- {
- /* Skip file not found if ignore_enoent */
- return SVN_NO_ERROR;
- }
-
- return svn_error_trace(svn_wc__db_global_record_fileinfo(
- db, local_abspath,
- dirent->filesize, dirent->mtime,
- scratch_pool));
-}
-
+ apr_pool_t *scratch_pool);
/* ------------------------------------------------------------------------ */
/* OP_REMOVE_BASE */
@@ -111,7 +95,8 @@ get_and_record_fileinfo(svn_wc__db_t *db
* See svn_wc__wq_build_remove_base() which generates this work item.
* Implements (struct work_item_dispatch).func. */
static svn_error_t *
-run_base_remove(svn_wc__db_t *db,
+run_base_remove(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -349,7 +334,8 @@ process_commit_file_install(svn_wc__db_t
static svn_error_t *
-run_file_commit(svn_wc__db_t *db,
+run_file_commit(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -397,7 +383,8 @@ svn_wc__wq_build_file_commit(svn_skel_t
/* OP_POSTUPGRADE */
static svn_error_t *
-run_postupgrade(svn_wc__db_t *db,
+run_postupgrade(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -465,7 +452,8 @@ svn_wc__wq_build_postupgrade(svn_skel_t
* See svn_wc__wq_build_file_install() which generates this work item.
* Implements (struct work_item_dispatch).func. */
static svn_error_t *
-run_file_install(svn_wc__db_t *db,
+run_file_install(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -665,7 +653,7 @@ run_file_install(svn_wc__db_t *db,
/* ### this should happen before we rename the file into place. */
if (record_fileinfo)
{
- SVN_ERR(get_and_record_fileinfo(db, local_abspath,
+ SVN_ERR(get_and_record_fileinfo(wqb, local_abspath,
FALSE /* ignore_enoent */,
scratch_pool));
}
@@ -717,12 +705,13 @@ svn_wc__wq_build_file_install(svn_skel_t
* See svn_wc__wq_build_file_remove() which generates this work item.
* Implements (struct work_item_dispatch).func. */
static svn_error_t *
-run_file_remove(svn_wc__db_t *db,
- const svn_skel_t *work_item,
- const char *wri_abspath,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *scratch_pool)
+run_file_remove(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
+ const svn_skel_t *work_item,
+ const char *wri_abspath,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
{
const svn_skel_t *arg1 = work_item->children->next;
const char *local_relpath;
@@ -766,7 +755,8 @@ svn_wc__wq_build_file_remove(svn_skel_t
* See svn_wc__wq_build_file_remove() which generates this work item.
* Implements (struct work_item_dispatch).func. */
static svn_error_t *
-run_dir_remove(svn_wc__db_t *db,
+run_dir_remove(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -847,12 +837,13 @@ svn_wc__wq_build_dir_remove(svn_skel_t *
* See svn_wc__wq_build_file_move() which generates this work item.
* Implements (struct work_item_dispatch).func. */
static svn_error_t *
-run_file_move(svn_wc__db_t *db,
- const svn_skel_t *work_item,
- const char *wri_abspath,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *scratch_pool)
+run_file_move(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
+ const svn_skel_t *work_item,
+ const char *wri_abspath,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
{
const svn_skel_t *arg1 = work_item->children->next;
const char *src_abspath, *dst_abspath;
@@ -929,7 +920,8 @@ svn_wc__wq_build_file_move(svn_skel_t **
* See run_file_copy_translated() which generates this work item.
* Implements (struct work_item_dispatch).func. */
static svn_error_t *
-run_file_copy_translated(svn_wc__db_t *db,
+run_file_copy_translated(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -1023,12 +1015,13 @@ svn_wc__wq_build_file_copy_translated(sv
/* OP_DIRECTORY_INSTALL */
static svn_error_t *
-run_dir_install(svn_wc__db_t *db,
- const svn_skel_t *work_item,
- const char *wri_abspath,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *scratch_pool)
+run_dir_install(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
+ const svn_skel_t *work_item,
+ const char *wri_abspath,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
{
const svn_skel_t *arg1 = work_item->children->next;
const char *local_relpath;
@@ -1072,7 +1065,8 @@ svn_wc__wq_build_dir_install(svn_skel_t
* See svn_wc__wq_build_sync_file_flags() which generates this work item.
* Implements (struct work_item_dispatch).func. */
static svn_error_t *
-run_sync_file_flags(svn_wc__db_t *db,
+run_sync_file_flags(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -1117,7 +1111,8 @@ svn_wc__wq_build_sync_file_flags(svn_ske
/* OP_PREJ_INSTALL */
static svn_error_t *
-run_prej_install(svn_wc__db_t *db,
+run_prej_install(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -1196,7 +1191,8 @@ svn_wc__wq_build_prej_install(svn_skel_t
static svn_error_t *
-run_record_fileinfo(svn_wc__db_t *db,
+run_record_fileinfo(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -1241,7 +1237,7 @@ run_record_fileinfo(svn_wc__db_t *db,
}
- return svn_error_trace(get_and_record_fileinfo(db, local_abspath,
+ return svn_error_trace(get_and_record_fileinfo(wqb, local_abspath,
TRUE /* ignore_enoent */,
scratch_pool));
}
@@ -1252,12 +1248,13 @@ run_record_fileinfo(svn_wc__db_t *db,
static svn_error_t *
-run_set_text_conflict_markers(svn_wc__db_t *db,
- const svn_skel_t *work_item,
- const char *wri_abspath,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *scratch_pool)
+run_set_text_conflict_markers(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
+ const svn_skel_t *work_item,
+ const char *wri_abspath,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
{
const svn_skel_t *arg = work_item->children->next;
const char *local_relpath;
@@ -1346,7 +1343,8 @@ run_set_text_conflict_markers(svn_wc__db
/* OP_TMP_SET_PROPERTY_CONFLICT_MARKER */
static svn_error_t *
-run_set_property_conflict_marker(svn_wc__db_t *db,
+run_set_property_conflict_marker(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -1432,9 +1430,19 @@ static const struct work_item_dispatch d
{ NULL }
};
+struct work_item_baton_t
+{
+ apr_pool_t *result_pool; /* Pool to allocate result in */
+
+ svn_boolean_t used; /* needs reset */
+
+ apr_hash_t *record_map; /* const char * -> svn_io_dirent2_t map */
+};
+
static svn_error_t *
-dispatch_work_item(svn_wc__db_t *db,
+dispatch_work_item(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const char *wri_abspath,
const svn_skel_t *work_item,
svn_cancel_func_t cancel_func,
@@ -1452,7 +1460,7 @@ dispatch_work_item(svn_wc__db_t *db,
#ifdef SVN_DEBUG_WORK_QUEUE
SVN_DBG(("dispatch: operation='%s'\n", scan->name));
#endif
- SVN_ERR((*scan->func)(db, work_item, wri_abspath,
+ SVN_ERR((*scan->func)(wqb, db, work_item, wri_abspath,
cancel_func, cancel_baton,
scratch_pool));
@@ -1497,6 +1505,8 @@ svn_wc__wq_run(svn_wc__db_t *db,
{
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
apr_uint64_t last_id = 0;
+ work_item_baton_t wib = { 0 };
+ wib.result_pool = svn_pool_create(scratch_pool);
#ifdef SVN_DEBUG_WORK_QUEUE
SVN_DBG(("wq_run: wri='%s'\n", wri_abspath));
@@ -1517,11 +1527,29 @@ svn_wc__wq_run(svn_wc__db_t *db,
svn_pool_clear(iterpool);
- /* Make sure to do this *early* in the loop iteration. There may
- be a LAST_ID that needs to be marked as completed, *before* we
- start worrying about anything else. */
- SVN_ERR(svn_wc__db_wq_fetch_next(&id, &work_item, db, wri_abspath,
- last_id, iterpool, iterpool));
+ if (! wib.used)
+ {
+ /* Make sure to do this *early* in the loop iteration. There may
+ be a LAST_ID that needs to be marked as completed, *before* we
+ start worrying about anything else. */
+ SVN_ERR(svn_wc__db_wq_fetch_next(&id, &work_item, db, wri_abspath,
+ last_id, iterpool, iterpool));
+ }
+ else
+ {
+ /* Make sure to do this *early* in the loop iteration. There may
+ be a LAST_ID that needs to be marked as completed, *before* we
+ start worrying about anything else. */
+ SVN_ERR(svn_wc__db_wq_record_and_fetch_next(&id, &work_item,
+ db, wri_abspath,
+ last_id, wib.record_map,
+ iterpool,
+ wib.result_pool));
+
+ svn_pool_clear(wib.result_pool);
+ wib.record_map = NULL;
+ wib.used = FALSE;
+ }
/* Stop work queue processing, if requested. A future 'svn cleanup'
should be able to continue the processing. Note that we may
@@ -1534,7 +1562,7 @@ svn_wc__wq_run(svn_wc__db_t *db,
if (work_item == NULL)
break;
- err = dispatch_work_item(db, wri_abspath, work_item,
+ err = dispatch_work_item(&wib, db, wri_abspath, work_item,
cancel_func, cancel_baton, iterpool);
if (err)
{
@@ -1604,3 +1632,29 @@ svn_wc__wq_merge(svn_skel_t *work_item1,
svn_skel__append(work_item1, work_item2->children);
return work_item1;
}
+
+
+static svn_error_t *
+get_and_record_fileinfo(work_item_baton_t *wqb,
+ const char *local_abspath,
+ svn_boolean_t ignore_enoent,
+ apr_pool_t *scratch_pool)
+{
+ const svn_io_dirent2_t *dirent;
+
+ SVN_ERR(svn_io_stat_dirent2(&dirent, local_abspath, FALSE, ignore_enoent,
+ wqb->result_pool, scratch_pool));
+
+ if (dirent->kind != svn_node_file)
+ return SVN_NO_ERROR;
+
+ wqb->used = TRUE;
+
+ if (! wqb->record_map)
+ wqb->record_map = apr_hash_make(wqb->result_pool);
+
+ svn_hash_sets(wqb->record_map, apr_pstrdup(wqb->result_pool, local_abspath),
+ dirent);
+
+ return SVN_NO_ERROR;
+}
Modified: subversion/branches/fsfs-format7/subversion/mod_dav_svn/version.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/mod_dav_svn/version.c?rev=1453290&r1=1453289&r2=1453290&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/mod_dav_svn/version.c (original)
+++ subversion/branches/fsfs-format7/subversion/mod_dav_svn/version.c Wed Mar 6 11:10:01 2013
@@ -150,6 +150,7 @@ get_vsn_options(apr_pool_t *p, apr_text_
apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_PARTIAL_REPLAY);
apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_INHERITED_PROPS);
apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_INLINE_PROPS);
+ apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_GET_FILE_REVS_REVERSE);
/* Mergeinfo is a special case: here we merely say that the server
* knows how to handle mergeinfo -- whether the repository does too
* is a separate matter.
@@ -242,6 +243,24 @@ get_option(const dav_resource *resource,
}
}
+ if (resource->info->repos->repos)
+ {
+ svn_error_t *serr;
+ svn_boolean_t has;
+
+ serr = svn_repos_has_capability(resource->info->repos->repos, &has,
+ SVN_REPOS_CAPABILITY_MERGEINFO,
+ r->pool);
+ if (serr)
+ return dav_svn__convert_err
+ (serr, HTTP_INTERNAL_SERVER_ERROR,
+ "Error fetching repository capabilities",
+ resource->pool);
+
+ apr_table_set(r->headers_out, SVN_DAV_REPOSITORY_MERGEINFO,
+ has ? "yes" : "no");
+ }
+
/* Welcome to the 2nd generation of the svn HTTP protocol, now
DeltaV-free! If we're configured to advise this support, do so. */
if (resource->info->repos->v2_protocol)