Modified: subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_pristine.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_pristine.c?rev=1432504&r1=1432503&r2=1432504&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_pristine.c (original) +++ subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_pristine.c Sat Jan 12 20:24:12 2013 @@ -25,6 +25,7 @@ #define SVN_WC__I_AM_WC_DB +#include "svn_pools.h" #include "svn_dirent_uri.h" #include "wc.h" @@ -500,118 +501,84 @@ svn_wc__db_pristine_get_sha1(const svn_c return svn_error_trace(svn_sqlite__reset(stmt)); } -/* Transaction implementation of svn_wc__db_pristine_transfer(). - We have a lock on DST_WCROOT and a lock on SRC_WCROOT. - - Outputs: - *TEMPFILE_ABSPATH is the path to the source file that is to be moved - into place. - *PRISTINE_ABSPATH is the target path for the file (within the pristine - store). - *SHA1_CHECKSUM is the pristine text's SHA-1 checksum. - *MD5_CHECKSUM is the pristine text's MD-5 checksum. - - If there is nothing to transfer (it is not found in the source, or is - already in the destination), then set *TEMPFILE_ABSPATH_P to NULL. - */ +/* Handle the moving of a pristine from SRC_WCROOT to DST_WCROOT. The existing + pristine in SRC_WCROOT is described by CHECKSUM, MD5_CHECKSUM and SIZE */ static svn_error_t * -pristine_transfer_txn2(const char **tempfile_abspath, - const char **pristine_abspath, - const svn_checksum_t **sha1_checksum, - const svn_checksum_t **md5_checksum, - svn_wc__db_wcroot_t *src_wcroot, - svn_wc__db_wcroot_t *dst_wcroot, - const char *src_relpath, - svn_cancel_func_t cancel_func, - void *cancel_baton, - apr_pool_t *scratch_pool) +maybe_transfer_one_pristine(svn_wc__db_wcroot_t *src_wcroot, + svn_wc__db_wcroot_t *dst_wcroot, + const svn_checksum_t *checksum, + const svn_checksum_t *md5_checksum, + apr_int64_t size, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *scratch_pool) { + const char *pristine_abspath; svn_sqlite__stmt_t *stmt; - svn_boolean_t have_row; + svn_stream_t *src_stream; + svn_stream_t *dst_stream; + const char *tmp_abspath; + const char *src_abspath; + int affected_rows; + svn_error_t *err; - *tempfile_abspath = NULL; + SVN_ERR(svn_sqlite__get_statement(&stmt, dst_wcroot->sdb, + STMT_INSERT_OR_IGNORE_PRISTINE)); + SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, checksum, scratch_pool)); + SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, md5_checksum, scratch_pool)); + SVN_ERR(svn_sqlite__bind_int64(stmt, 3, size)); - /* Get the SHA1 checksum */ - SVN_ERR(svn_sqlite__get_statement(&stmt, src_wcroot->sdb, - STMT_SELECT_NODE_INFO)); - SVN_ERR(svn_sqlite__bindf(stmt, "is", - src_wcroot->wc_id, src_relpath)); - SVN_ERR(svn_sqlite__step(&have_row, stmt)); - if (have_row) - SVN_ERR(svn_sqlite__column_checksum(sha1_checksum, stmt, 6, - scratch_pool)); - SVN_ERR(svn_sqlite__reset(stmt)); + SVN_ERR(svn_sqlite__update(&affected_rows, stmt)); - if (! *sha1_checksum) - return SVN_NO_ERROR; /* Nothing to transfer */ + if (affected_rows == 0) + return SVN_NO_ERROR; - /* Check if we have the pristine in the destination wcroot */ - SVN_ERR(svn_sqlite__get_statement(&stmt, dst_wcroot->sdb, - STMT_SELECT_PRISTINE)); - SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, *sha1_checksum, - scratch_pool)); - SVN_ERR(svn_sqlite__step(&have_row, stmt)); - SVN_ERR(svn_sqlite__reset(stmt)); + SVN_ERR(svn_stream_open_unique(&dst_stream, &tmp_abspath, + pristine_get_tempdir(dst_wcroot, + scratch_pool, + scratch_pool), + svn_io_file_del_on_pool_cleanup, + scratch_pool, scratch_pool)); - /* Destination repository already has this pristine. We're done */ - if (have_row) - return SVN_NO_ERROR; + SVN_ERR(get_pristine_fname(&src_abspath, src_wcroot->abspath, checksum, + scratch_pool, scratch_pool)); - /* Verify if the pristine actually exists and get the MD5 in one query */ - SVN_ERR(svn_sqlite__get_statement(&stmt, src_wcroot->sdb, - STMT_SELECT_PRISTINE)); - SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, *sha1_checksum, - scratch_pool)); - SVN_ERR(svn_sqlite__step(&have_row, stmt)); + SVN_ERR(svn_stream_open_readonly(&src_stream, src_abspath, + scratch_pool, scratch_pool)); - if (!have_row) + /* ### Should we verify the SHA1 or MD5 here, or is that too expensive? */ + SVN_ERR(svn_stream_copy3(src_stream, dst_stream, + cancel_func, cancel_baton, + scratch_pool)); + + SVN_ERR(get_pristine_fname(&pristine_abspath, dst_wcroot->abspath, checksum, + scratch_pool, scratch_pool)); + + /* Move the file to its target location. (If it is already there, it is + * an orphan file and it doesn't matter if we overwrite it.) */ + err = svn_io_file_rename(tmp_abspath, pristine_abspath, scratch_pool); + + /* Maybe the directory doesn't exist yet? */ + if (err && APR_STATUS_IS_ENOENT(err->apr_err)) { - return svn_error_createf(SVN_ERR_WC_DB_ERROR, svn_sqlite__reset(stmt), - _("The pristine text with checksum '%s' was " - "not found"), - svn_checksum_to_cstring_display( - *sha1_checksum, scratch_pool)); - } - SVN_ERR(svn_sqlite__column_checksum(md5_checksum, stmt, 0, - scratch_pool)); - SVN_ERR(svn_sqlite__reset(stmt)); + svn_error_t *err2; - /* We have read locks in both working copies, so we can safely copy the - file to the temp location of the destination working copy */ - { - svn_stream_t *src_stream; - svn_stream_t *dst_stream; - const char *tmp_abspath; - const char *src_abspath; - - SVN_ERR(svn_stream_open_unique(&dst_stream, &tmp_abspath, - pristine_get_tempdir(dst_wcroot, - scratch_pool, - scratch_pool), - svn_io_file_del_on_pool_cleanup, - scratch_pool, scratch_pool)); + err2 = svn_io_dir_make(svn_dirent_dirname(pristine_abspath, + scratch_pool), + APR_OS_DEFAULT, scratch_pool); + + if (err2) + /* Creating directory didn't work: Return all errors */ + return svn_error_trace(svn_error_compose_create(err, err2)); + else + /* We could create a directory: retry install */ + svn_error_clear(err); + + SVN_ERR(svn_io_file_rename(tmp_abspath, pristine_abspath, scratch_pool)); + } + else + SVN_ERR(err); - SVN_ERR(get_pristine_fname(&src_abspath, src_wcroot->abspath, - *sha1_checksum, - scratch_pool, scratch_pool)); - - SVN_ERR(svn_stream_open_readonly(&src_stream, src_abspath, - scratch_pool, scratch_pool)); - - /* ### Should we verify the SHA1 or MD5 here, or is that too expensive? */ - SVN_ERR(svn_stream_copy3(src_stream, dst_stream, - cancel_func, cancel_baton, - scratch_pool)); - - /* And now set the right information to install once we leave the - src transaction */ - - SVN_ERR(get_pristine_fname(pristine_abspath, - dst_wcroot->abspath, - *sha1_checksum, - scratch_pool, scratch_pool)); - *tempfile_abspath = tmp_abspath; - } return SVN_NO_ERROR; } @@ -619,32 +586,53 @@ pristine_transfer_txn2(const char **temp We have a lock on DST_WCROOT. */ static svn_error_t * -pristine_transfer_txn1(svn_wc__db_wcroot_t *src_wcroot, +pristine_transfer_txn(svn_wc__db_wcroot_t *src_wcroot, svn_wc__db_wcroot_t *dst_wcroot, const char *src_relpath, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *scratch_pool) { - const char *tempfile_abspath; - const char *pristine_abspath; - const svn_checksum_t *sha1_checksum; - const svn_checksum_t *md5_checksum; + svn_sqlite__stmt_t *stmt; + svn_boolean_t got_row; + apr_pool_t *iterpool = svn_pool_create(scratch_pool); + + SVN_ERR(svn_sqlite__get_statement(&stmt, src_wcroot->sdb, + STMT_SELECT_COPY_PRISTINES)); + SVN_ERR(svn_sqlite__bindf(stmt, "is", src_wcroot->wc_id, src_relpath)); + + /* This obtains an sqlite read lock on src_wcroot */ + SVN_ERR(svn_sqlite__step(&got_row, stmt)); + + while (got_row) + { + const svn_checksum_t *checksum; + const svn_checksum_t *md5_checksum; + apr_int64_t size; + svn_error_t *err; + + svn_pool_clear(iterpool); + + SVN_ERR(svn_sqlite__column_checksum(&checksum, stmt, 0, iterpool)); + SVN_ERR(svn_sqlite__column_checksum(&md5_checksum, stmt, 1, iterpool)); + size = svn_sqlite__column_int64(stmt, 2); + + err = maybe_transfer_one_pristine(src_wcroot, dst_wcroot, + checksum, md5_checksum, size, + cancel_func, cancel_baton, + iterpool); + + if (err) + return svn_error_trace(svn_error_compose_create( + err, + svn_sqlite__reset(stmt))); + + SVN_ERR(svn_sqlite__step(&got_row, stmt)); + } + SVN_ERR(svn_sqlite__reset(stmt)); + + svn_pool_destroy(iterpool); - /* Get all the info within a src wcroot lock */ - SVN_WC__DB_WITH_TXN( - pristine_transfer_txn2(&tempfile_abspath, &pristine_abspath, - &sha1_checksum, &md5_checksum, - src_wcroot, dst_wcroot, src_relpath, - cancel_func, cancel_baton, scratch_pool), - src_wcroot); - - /* And do the final install, while we still have the dst lock */ - if (tempfile_abspath) - SVN_ERR(pristine_install_txn(dst_wcroot->sdb, - tempfile_abspath, pristine_abspath, - sha1_checksum, md5_checksum, - scratch_pool)); return SVN_NO_ERROR; } @@ -675,8 +663,8 @@ svn_wc__db_pristine_transfer(svn_wc__db_ } SVN_WC__DB_WITH_TXN( - pristine_transfer_txn1(src_wcroot, dst_wcroot, src_relpath, - cancel_func, cancel_baton, scratch_pool), + pristine_transfer_txn(src_wcroot, dst_wcroot, src_relpath, + cancel_func, cancel_baton, scratch_pool), dst_wcroot); return SVN_NO_ERROR;
Modified: subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_private.h URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_private.h?rev=1432504&r1=1432503&r2=1432504&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_private.h (original) +++ subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_private.h Sat Jan 12 20:24:12 2013 @@ -367,4 +367,14 @@ svn_wc__db_retract_parent_delete(svn_wc_ int op_depth, apr_pool_t *scratch_pool); +/* Do a post-drive revision bump for the moved-away destination for + any move sources under LOCAL_RELPATH. This is called from within + the revision bump transaction after the tree at LOCAL_RELPATH has + been bumped. */ +svn_error_t * +svn_wc__db_bump_moved_away(svn_wc__db_wcroot_t *wcroot, + const char *local_relpath, + svn_depth_t depth, + apr_pool_t *scratch_pool); + #endif /* WC_DB_PRIVATE_H */ Modified: subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_update_move.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_update_move.c?rev=1432504&r1=1432503&r2=1432504&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_update_move.c (original) +++ subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_update_move.c Sat Jan 12 20:24:12 2013 @@ -90,6 +90,7 @@ #include "wc-queries.h" #include "conflicts.h" #include "workqueue.h" +#include "token-map.h" /* * Receiver code. @@ -109,6 +110,11 @@ struct tc_editor_baton { svn_wc__db_t *db; svn_wc__db_wcroot_t *wcroot; const char *move_root_dst_relpath; + + /* The most recent conflict raised during this drive. We rely on the + non-Ev2, depth-first, drive for this to make sense. */ + const char *conflict_root_relpath; + svn_wc_conflict_version_t *old_version; svn_wc_conflict_version_t *new_version; svn_wc_notify_func2_t notify_func; @@ -116,13 +122,73 @@ struct tc_editor_baton { apr_pool_t *result_pool; }; -/* If LOCAL_RELPATH is shadowed then raise a tree-conflict on the root - of the obstruction 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, + svn_node_kind_t old_kind, + svn_node_kind_t new_kind, + svn_wc_conflict_reason_t reason, + svn_wc_conflict_action_t action, + apr_pool_t *scratch_pool) +{ + const char *repos_relpath; + svn_skel_t *conflict = svn_wc__conflict_skel_create(scratch_pool); + svn_wc_conflict_version_t *old_version, *new_version; - KIND is the node kind of ... ### what? + b->conflict_root_relpath = apr_pstrdup(b->result_pool, local_relpath); - Set *IS_CONFLICTED ... ### if/iff what? - */ + SVN_ERR(svn_wc__conflict_skel_add_tree_conflict( + conflict, NULL, + svn_dirent_join(b->wcroot->abspath, local_relpath, + scratch_pool), + reason, + action, + scratch_pool, + scratch_pool)); + + if (reason != svn_wc_conflict_reason_unversioned) + { + repos_relpath = svn_relpath_join(b->old_version->path_in_repos, + svn_relpath_skip_ancestor(b->move_root_dst_relpath, + local_relpath), + scratch_pool); + old_version = svn_wc_conflict_version_create2(b->old_version->repos_url, + b->old_version->repos_uuid, + repos_relpath, + b->old_version->peg_rev, + old_kind, + scratch_pool); + } + else + old_version = NULL; + + repos_relpath = svn_relpath_join(b->new_version->path_in_repos, + svn_relpath_skip_ancestor(b->move_root_dst_relpath, + local_relpath), + scratch_pool); + new_version = svn_wc_conflict_version_create2(b->new_version->repos_url, + b->new_version->repos_uuid, + repos_relpath, + b->new_version->peg_rev, + new_kind, + scratch_pool); + + /* What about switch? */ + SVN_ERR(svn_wc__conflict_skel_set_op_update(conflict, + old_version, new_version, + scratch_pool, scratch_pool)); + SVN_ERR(svn_wc__db_mark_conflict_internal(b->wcroot, local_relpath, + conflict, scratch_pool)); + + return SVN_NO_ERROR; +} + +/* If LOCAL_RELPATH is a child of the most recently raised + tree-conflict or is shadowed then set *IS_CONFLICTED to TRUE and + raise a tree-conflict on the root of the obstruction if such a + tree-conflict does not already exist. KIND is the kind of the + incoming LOCAL_RELPATH. This relies on the non-Ev2, depth-first, + drive. */ static svn_error_t * check_tree_conflict(svn_boolean_t *is_conflicted, struct tc_editor_baton *b, @@ -134,10 +200,20 @@ check_tree_conflict(svn_boolean_t *is_co svn_boolean_t have_row; int dst_op_depth = relpath_depth(b->move_root_dst_relpath); int op_depth; + svn_node_kind_t old_kind; const char *conflict_root_relpath = local_relpath; const char *moved_to_relpath; svn_skel_t *conflict; - svn_wc_conflict_version_t *version; + + if (b->conflict_root_relpath) + { + if (svn_relpath_skip_ancestor(b->conflict_root_relpath, local_relpath)) + { + *is_conflicted = TRUE; + return SVN_NO_ERROR; + } + b->conflict_root_relpath = NULL; + } SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb, STMT_SELECT_LOWEST_WORKING_NODE)); @@ -145,7 +221,11 @@ check_tree_conflict(svn_boolean_t *is_co dst_op_depth)); SVN_ERR(svn_sqlite__step(&have_row, stmt)); if (have_row) - op_depth = svn_sqlite__column_int(stmt, 0); + { + op_depth = svn_sqlite__column_int(stmt, 0); + old_kind = svn__node_kind_from_kind(svn_sqlite__column_token(stmt, 2, + kind_map)); + } SVN_ERR(svn_sqlite__reset(stmt)); if (!have_row) @@ -157,8 +237,11 @@ check_tree_conflict(svn_boolean_t *is_co *is_conflicted = TRUE; while (relpath_depth(conflict_root_relpath) > op_depth) - conflict_root_relpath = svn_relpath_dirname(conflict_root_relpath, - scratch_pool); + { + conflict_root_relpath = svn_relpath_dirname(conflict_root_relpath, + scratch_pool); + old_kind = svn_node_dir; + } SVN_ERR(svn_wc__db_read_conflict_internal(&conflict, b->wcroot, conflict_root_relpath, @@ -173,67 +256,12 @@ check_tree_conflict(svn_boolean_t *is_co b->wcroot, conflict_root_relpath, scratch_pool, scratch_pool)); - conflict = svn_wc__conflict_skel_create(scratch_pool); - SVN_ERR(svn_wc__conflict_skel_add_tree_conflict( - conflict, NULL, - svn_dirent_join(b->wcroot->abspath, conflict_root_relpath, - scratch_pool), - (moved_to_relpath - ? svn_wc_conflict_reason_moved_away - : svn_wc_conflict_reason_deleted), - svn_wc_conflict_action_edit, - scratch_pool, - scratch_pool)); - - version = svn_wc_conflict_version_create2(b->old_version->repos_url, - b->old_version->repos_uuid, - local_relpath /* ### need *repos* relpath */, - b->old_version->peg_rev, - kind /* ### need *old* kind for this node */, - scratch_pool); - - /* What about switch? */ - SVN_ERR(svn_wc__conflict_skel_set_op_update(conflict, version, NULL /* ### derive from b->new_version & new kind? */, - scratch_pool, scratch_pool)); - SVN_ERR(svn_wc__db_mark_conflict_internal(b->wcroot, conflict_root_relpath, - conflict, scratch_pool)); - - return SVN_NO_ERROR; -} - -/* Mark a unversioned-add tree-conflict on RELPATH. */ -static svn_error_t * -mark_unversioned_add_conflict(struct tc_editor_baton *b, - const char *relpath, - svn_node_kind_t kind, - apr_pool_t *scratch_pool) -{ - svn_skel_t *conflict = svn_wc__conflict_skel_create(scratch_pool); - svn_wc_conflict_version_t *version; - - SVN_ERR(svn_wc__conflict_skel_add_tree_conflict( - conflict, NULL, - svn_dirent_join(b->wcroot->abspath, relpath, - scratch_pool), - svn_wc_conflict_reason_unversioned, - svn_wc_conflict_action_add, - scratch_pool, - scratch_pool)); - - version = svn_wc_conflict_version_create2(b->old_version->repos_url, - b->old_version->repos_uuid, - relpath /* ### need *repos* relpath */, - b->old_version->peg_rev, - kind /* ### need *old* kind for this node */, - scratch_pool); - - /* ### How about switch? */ - SVN_ERR(svn_wc__conflict_skel_set_op_update(conflict, version, - NULL /* ### derive from b->new_version & new kind? */, - scratch_pool, scratch_pool)); - SVN_ERR(svn_wc__db_mark_conflict_internal(b->wcroot, relpath, - conflict, scratch_pool)); - + SVN_ERR(mark_tree_conflict(b, conflict_root_relpath, old_kind, kind, + (moved_to_relpath + ? svn_wc_conflict_reason_moved_away + : svn_wc_conflict_reason_deleted), + svn_wc_conflict_action_edit, + scratch_pool)); return SVN_NO_ERROR; } @@ -271,8 +299,10 @@ tc_editor_add_directory(void *baton, { case svn_node_file: default: - SVN_ERR(mark_unversioned_add_conflict(b, relpath, svn_node_dir, - scratch_pool)); + SVN_ERR(mark_tree_conflict(b, relpath, kind, svn_node_dir, + svn_wc_conflict_reason_unversioned, + svn_wc_conflict_action_add, + scratch_pool)); break; case svn_node_none: @@ -322,8 +352,10 @@ tc_editor_add_file(void *baton, if (kind != svn_node_none) { - SVN_ERR(mark_unversioned_add_conflict(b, relpath, svn_node_file, - scratch_pool)); + SVN_ERR(mark_tree_conflict(b, relpath, kind, svn_node_file, + svn_wc_conflict_reason_unversioned, + svn_wc_conflict_action_add, + scratch_pool)); return SVN_NO_ERROR; } @@ -718,8 +750,6 @@ tc_editor_alter_file(void *baton, new_version.checksum = new_checksum ? new_checksum : old_version.checksum; new_version.props = new_props ? new_props : old_version.props; - /* ### TODO update revision etc. in NODES table */ - /* Update file and prop contents if the update has changed them. */ if (!svn_checksum_match(new_checksum, old_version.checksum) /* ### || props have changed */) @@ -1004,6 +1034,8 @@ update_moved_away_dir(svn_editor_t *tc_e SVN_ERR(svn_wc__db_read_pristine_props(&new_props, db, src_abspath, scratch_pool, scratch_pool)); + /* This is a non-Ev2, depth-first, drive that calls add/alter on all + directories. */ if (add) SVN_ERR(svn_editor_add_directory(tc_editor, dst_relpath, new_children, new_props, @@ -1108,7 +1140,6 @@ update_moved_away_subtree(svn_editor_t * svn_pool_clear(iterpool); child_dst_relpath = svn_relpath_join(dst_relpath, dst_name, iterpool); - /* FIXME: editor API violation: missing svn_editor_alter_directory. */ SVN_ERR(svn_editor_delete(tc_editor, child_dst_relpath, move_root_dst_revision)); } @@ -1359,3 +1390,93 @@ svn_wc__db_update_moved_away_conflict_vi return SVN_NO_ERROR; } + +static svn_error_t * +bump_moved_away(svn_wc__db_wcroot_t *wcroot, + const char *local_relpath, + svn_depth_t depth, + int op_depth, + apr_pool_t *scratch_pool) +{ + svn_sqlite__stmt_t *stmt; + svn_boolean_t have_row; + apr_pool_t *iterpool; + + iterpool = svn_pool_create(scratch_pool); + + SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, + STMT_SELECT_MOVED_PAIR3)); + 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) + { + svn_sqlite__stmt_t *stmt2; + const char *src_relpath, *dst_relpath; + int src_op_depth = svn_sqlite__column_int(stmt, 2); + svn_error_t *err; + svn_skel_t *conflict; + + svn_pool_clear(iterpool); + + src_relpath = svn_sqlite__column_text(stmt, 0, iterpool); + dst_relpath = svn_sqlite__column_text(stmt, 1, iterpool); + + err = svn_sqlite__get_statement(&stmt2, wcroot->sdb, + STMT_HAS_LAYER_BETWEEN); + if (!err) + err = svn_sqlite__bindf(stmt2, "isdd", wcroot->wc_id, local_relpath, + op_depth, src_op_depth); + if (!err) + err = svn_sqlite__step(&have_row, stmt2); + if (!err) + err = svn_sqlite__reset(stmt2); + if (!err && !have_row) + { + 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); + + 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, depth, + relpath_depth(dst_relpath), iterpool); + } + } + + if (err) + return svn_error_compose_create(err, svn_sqlite__reset(stmt)); + + SVN_ERR(svn_sqlite__step(&have_row, stmt)); + } + SVN_ERR(svn_sqlite__reset(stmt)); + + svn_pool_destroy(iterpool); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_wc__db_bump_moved_away(svn_wc__db_wcroot_t *wcroot, + const char *local_relpath, + svn_depth_t depth, + apr_pool_t *scratch_pool) +{ + /* ### TODO: raise tree-conflicts? */ + if (depth != svn_depth_infinity) + return SVN_NO_ERROR; + + SVN_ERR(bump_moved_away(wcroot, local_relpath, depth, 0, scratch_pool)); + + return SVN_NO_ERROR; +} Modified: subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_util.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_util.c?rev=1432504&r1=1432503&r2=1432504&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_util.c (original) +++ subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_util.c Sat Jan 12 20:24:12 2013 @@ -136,6 +136,22 @@ svn_wc__db_util_open_db(svn_sqlite__db_t svn_dirent_local_style(sdb_abspath, scratch_pool)); } +#ifndef WIN32 + else + { + apr_file_t *f; + + /* A standard SQLite build creates a DB with mode 644 ^ !umask + which means the file doesn't have group/world write access + even when umask allows it. By ensuring the file exists before + SQLite gets involved we give it the permissions allowed by + umask. */ + SVN_ERR(svn_io_file_open(&f, sdb_abspath, + (APR_READ | APR_WRITE | APR_CREATE), + APR_OS_DEFAULT, scratch_pool)); + SVN_ERR(svn_io_file_close(f, scratch_pool)); + } +#endif SVN_ERR(svn_sqlite__open(sdb, sdb_abspath, smode, my_statements ? my_statements : statements, Modified: subversion/branches/ev2-export/subversion/mod_dav_svn/deadprops.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/mod_dav_svn/deadprops.c?rev=1432504&r1=1432503&r2=1432504&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/mod_dav_svn/deadprops.c (original) +++ subversion/branches/ev2-export/subversion/mod_dav_svn/deadprops.c Sat Jan 12 20:24:12 2013 @@ -136,7 +136,7 @@ get_value(dav_db *db, const dav_prop_nam propname, db->p); else serr = svn_repos_fs_revision_prop(pvalue, - db->resource->info-> repos->repos, + db->resource->info->repos->repos, db->resource->info->root.rev, propname, db->authz_read_func, db->authz_read_baton, db->p); Modified: subversion/branches/ev2-export/subversion/mod_dav_svn/reports/replay.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/mod_dav_svn/reports/replay.c?rev=1432504&r1=1432503&r2=1432504&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/mod_dav_svn/reports/replay.c (original) +++ subversion/branches/ev2-export/subversion/mod_dav_svn/reports/replay.c Sat Jan 12 20:24:12 2013 @@ -418,11 +418,11 @@ dav_svn__replay_report(const dav_resourc { dav_error *derr = NULL; svn_revnum_t low_water_mark = SVN_INVALID_REVNUM; - svn_revnum_t rev = SVN_INVALID_REVNUM; + svn_revnum_t rev; const svn_delta_editor_t *editor; svn_boolean_t send_deltas = TRUE; dav_svn__authz_read_baton arb; - const char *base_dir = resource->info->repos_path; + const char *base_dir; apr_bucket_brigade *bb; apr_xml_elem *child; svn_fs_root_t *root; @@ -430,10 +430,27 @@ dav_svn__replay_report(const dav_resourc void *edit_baton; int ns; - /* The request won't have a repos_path if it's for the root. */ - if (! base_dir) - base_dir = ""; - + /* In Subversion 1.8, we allowed this REPORT to be issue against a + revision resource. Doing so means the REV is part of the request + URL, and BASE_DIR is embedded in the request body. + + The old-school (and incorrect, see issue #4287 -- + http://subversion.tigris.org/issues/show_bug.cgi?id=4287) way was + to REPORT on the public URL of the BASE_DIR and embed the REV in + the report body. + */ + if (resource->baselined + && (resource->type == DAV_RESOURCE_TYPE_VERSION)) + { + rev = resource->info->root.rev; + base_dir = NULL; + } + else + { + rev = SVN_INVALID_REVNUM; + base_dir = resource->info->repos_path; + } + arb.r = resource->info->r; arb.repos = resource->info->repos; @@ -455,9 +472,17 @@ dav_svn__replay_report(const dav_resourc if (strcmp(child->name, "revision") == 0) { + if (SVN_IS_VALID_REVNUM(rev)) + { + /* Uh... we already have a revision to use, either + because this tag is non-unique or because the + request was submitted against a revision-bearing + resource URL. Either way, something's not + right. */ + return malformed_element_error("revision", resource->pool); + } + cdata = dav_xml_get_cdata(child, resource->pool, 1); - if (! cdata) - return malformed_element_error("revision", resource->pool); rev = SVN_STR_TO_REV(cdata); } else if (strcmp(child->name, "low-water-mark") == 0) @@ -481,7 +506,16 @@ dav_svn__replay_report(const dav_resourc svn_error_clear(err); return malformed_element_error("send-deltas", resource->pool); } - send_deltas = parsed_val ? TRUE : FALSE; + send_deltas = parsed_val != 0; + } + else if (strcmp(child->name, "include-path") == 0) + { + cdata = dav_xml_get_cdata(child, resource->pool, 1); + if ((derr = dav_svn__test_canonical(cdata, resource->pool))) + return derr; + + /* Force BASE_DIR to be a relative path, not an fspath. */ + base_dir = svn_relpath_canonicalize(cdata, resource->pool); } } } @@ -498,6 +532,9 @@ dav_svn__replay_report(const dav_resourc "Request was missing the low-water-mark argument.", SVN_DAV_ERROR_NAMESPACE, SVN_DAV_ERROR_TAG); + if (! base_dir) + base_dir = ""; + bb = apr_brigade_create(resource->pool, output->c->bucket_alloc); if ((err = svn_fs_revision_root(&root, resource->info->repos->fs, rev, Modified: subversion/branches/ev2-export/subversion/mod_dav_svn/version.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/mod_dav_svn/version.c?rev=1432504&r1=1432503&r2=1432504&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/mod_dav_svn/version.c (original) +++ subversion/branches/ev2-export/subversion/mod_dav_svn/version.c Sat Jan 12 20:24:12 2013 @@ -266,6 +266,14 @@ get_option(const dav_resource *resource, { "create-txn-with-props", { 1, 8, 0, "" } }, }; + /* Add the header which indicates that this server can handle + replay REPORTs submitted against an HTTP v2 revision resource. */ + apr_table_addn(r->headers_out, "DAV", + SVN_DAV_NS_DAV_SVN_REPLAY_REV_RESOURCE); + + /* Add a bunch of HTTP v2 headers which carry resource and + resource stub URLs that the client can use to naively build + addressable resources. */ apr_table_set(r->headers_out, SVN_DAV_ROOT_URI_HEADER, repos_root_uri); apr_table_set(r->headers_out, SVN_DAV_ME_RESOURCE_HEADER, apr_pstrcat(resource->pool, repos_root_uri, "/",
