Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db.h URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db.h?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db.h (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db.h Sun Jun 14 20:58:10 2015 @@ -20,7 +20,7 @@ * ==================================================================== * @endcopyright * - * @file svn_wc_db.h + * @file wc_db.h * @brief The Subversion Working Copy Library - Metadata/Base-Text Support * * Requires: @@ -676,13 +676,15 @@ svn_wc__db_base_add_not_present_node(svn const svn_skel_t *work_items, apr_pool_t *scratch_pool); +/* Remove a node and all its descendants from the BASE tree. This can + be done in two modes: -/* Remove a node and all its descendants from the BASE tree. This handles - the deletion of a tree from the update editor and some file external - scenarios. + * Remove everything, scheduling wq operations to clean up + the working copy. (KEEP_WORKING = FALSE) - The node to remove is indicated by LOCAL_ABSPATH from the local - filesystem. + * Bump things to WORKING, so the BASE layer is free, but the working + copy unmodified, except that everything that was visible from + BASE is now a copy of what it used to be. (KEEP_WORKING = TRUE) This operation *installs* workqueue operations to update the local filesystem after the database operation. @@ -693,21 +695,11 @@ svn_wc__db_base_add_not_present_node(svn actual node will be removed if the actual node does not mark a conflict. - If KEEP_AS_WORKING is TRUE, then the base tree is copied to higher - layers as a copy of itself before deleting the BASE nodes. - If KEEP_AS_WORKING is FALSE, and QUEUE_DELETES is TRUE, also queue - workqueue items to delete all in-wc representations that aren't - shadowed by higher layers. - (With KEEP_AS_WORKING TRUE, this is a no-op, as everything is - automatically shadowed by the created copy) - - If REMOVE_LOCKS is TRUE, all locks of this node and any subnodes - are also removed. This is to be done during commit of deleted nodes. - - If NOT_PRESENT_REVISION specifies a valid revision a not-present - node is installed in BASE node with kind NOT_PRESENT_KIND after - deleting. + If MARK_NOT_PRESENT or MARK_EXCLUDED is TRUE, install a marker + of the specified type at the root of the now removed tree, with + either the specified revision (or in case of SVN_INVALID_REVNUM) + the original revision. If CONFLICT and/or WORK_ITEMS are passed they are installed as part of the operation, after the work items inserted by the operation @@ -716,10 +708,10 @@ svn_wc__db_base_add_not_present_node(svn svn_error_t * svn_wc__db_base_remove(svn_wc__db_t *db, const char *local_abspath, - svn_boolean_t keep_as_working, - svn_boolean_t queue_deletes, - svn_boolean_t remove_locks, - svn_revnum_t not_present_revision, + svn_boolean_t keep_working, + svn_boolean_t mark_not_present, + svn_boolean_t mark_excluded, + svn_revnum_t marker_revision, svn_skel_t *conflict, svn_skel_t *work_items, apr_pool_t *scratch_pool); @@ -1421,8 +1413,8 @@ svn_wc__db_op_copy_dir(svn_wc__db_t *db, const char *original_uuid, svn_revnum_t original_revision, const apr_array_header_t *children, - svn_boolean_t is_move, svn_depth_t depth, + svn_boolean_t is_move, const svn_skel_t *conflict, const svn_skel_t *work_items, apr_pool_t *scratch_pool); @@ -1463,6 +1455,7 @@ svn_wc__db_op_copy_symlink(svn_wc__db_t const char *original_uuid, svn_revnum_t original_revision, const char *target, + svn_boolean_t is_move, const svn_skel_t *conflict, const svn_skel_t *work_items, apr_pool_t *scratch_pool); @@ -2026,6 +2019,7 @@ struct svn_wc__db_info_t { svn_boolean_t moved_here; /* Only on op-roots. */ svn_boolean_t file_external; + svn_boolean_t has_descendants; /* Is dir, or has tc descendants */ }; /* Return in *NODES a hash mapping name->struct svn_wc__db_info_t for @@ -2064,6 +2058,7 @@ svn_wc__db_read_single_info(const struct /* Structure returned by svn_wc__db_read_walker_info. Only has the fields needed by svn_wc__internal_walk_children(). */ struct svn_wc__db_walker_info_t { + const char *name; svn_wc__db_status_t status; svn_node_kind_t kind; }; @@ -2124,11 +2119,10 @@ svn_wc__db_read_node_install_info(const apr_pool_t *result_pool, apr_pool_t *scratch_pool); -/* Return in *NODES a hash mapping name->struct svn_wc__db_walker_info_t for - the children of DIR_ABSPATH. "name" is the child's name relative to - DIR_ABSPATH, not an absolute path. */ +/* Return in *ITEMS an array of struct svn_wc__db_walker_info_t* for + the direct children of DIR_ABSPATH. */ svn_error_t * -svn_wc__db_read_children_walker_info(apr_hash_t **nodes, +svn_wc__db_read_children_walker_info(const apr_array_header_t **items, svn_wc__db_t *db, const char *dir_abspath, apr_pool_t *result_pool, @@ -2136,15 +2130,26 @@ svn_wc__db_read_children_walker_info(apr /** - * Set *URL to the corresponding url for LOCAL_ABSPATH. - * If the node is added, return the url it will have in the repository. - */ -svn_error_t * -svn_wc__db_read_url(const char **url, - svn_wc__db_t *db, - const char *local_abspath, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool); + * Set *revision, *repos_relpath, *repos_root_url, *repos_uuid to + * the intended/commit location of LOCAL_ABSPATH. These arguments may be + * NULL if they are not needed. + * + * If the node is deleted, return the url it would have in the repository + * if it wouldn't be deleted. If the node is added return the url it will + * have in the repository, once committed. + * + * If the node is not added and has an existing repository location, set + * revision to its existing revision, otherwise to SVN_INVALID_REVNUM. + */ +svn_error_t * +svn_wc__db_read_repos_info(svn_revnum_t *revision, + const char **repos_relpath, + const char **repos_root_url, + const char **repos_uuid, + svn_wc__db_t *db, + const char *local_abspath, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); /* Set *PROPS to the properties of the node LOCAL_ABSPATH in the ACTUAL @@ -2308,6 +2313,14 @@ svn_wc__db_read_children_of_working_node apr_pool_t *result_pool, apr_pool_t *scratch_pool); +svn_error_t * +svn_wc__db_base_read_not_present_children( + const apr_array_header_t **children, + svn_wc__db_t *db, + const char *local_abspath, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + /* Like svn_wc__db_read_children_of_working_node(), except also include any path that was a child of a deleted directory that existed at LOCAL_ABSPATH, even if that directory is now scheduled to be replaced by @@ -2350,7 +2363,10 @@ svn_wc__db_get_conflict_marker_files(apr apr_pool_t *scratch_pool); /* Read the conflict information recorded on LOCAL_ABSPATH in *CONFLICT, - an editable conflict skel. + an editable conflict skel. If kind is not NULL, also read the node kind + in *KIND. (SHOW_HIDDEN: false, SHOW_DELETED: true). If props is not NULL + read the actual properties in this value if they exist. (Set to NULL in case + the node is deleted, etc.) If the node exists, but does not have a conflict set *CONFLICT to NULL, otherwise return a SVN_ERR_WC_PATH_NOT_FOUND error. @@ -2359,6 +2375,8 @@ svn_wc__db_get_conflict_marker_files(apr SCRATCH_POOL */ svn_error_t * svn_wc__db_read_conflict(svn_skel_t **conflict, + svn_node_kind_t *kind, + apr_hash_t **props, svn_wc__db_t *db, const char *local_abspath, apr_pool_t *result_pool, @@ -2394,16 +2412,6 @@ svn_wc__db_read_kind(svn_node_kind_t *ki svn_boolean_t show_hidden, apr_pool_t *scratch_pool); - -/* An analog to svn_wc__entry_is_hidden(). Set *HIDDEN to TRUE if - LOCAL_ABSPATH in DB "is not present, and I haven't scheduled something - over the top of it." */ -svn_error_t * -svn_wc__db_node_hidden(svn_boolean_t *hidden, - svn_wc__db_t *db, - const char *local_abspath, - apr_pool_t *scratch_pool); - /* Checks if a node replaces a node in a different layer. Also check if it replaces a BASE (op_depth 0) node or just a node in a higher layer (a copy). Finally check if this is the root of the replacement, or if the replacement @@ -2515,11 +2523,6 @@ svn_wc__db_global_relocate(svn_wc__db_t CHANGED_AUTHOR is the (server-side) author of CHANGED_REVISION. It may be NULL if the revprop is missing on the revision. - One or both of NEW_CHECKSUM and NEW_CHILDREN should be NULL. For new: - files: NEW_CHILDREN should be NULL - dirs: NEW_CHECKSUM should be NULL - symlinks: both should be NULL - WORK_ITEMS will be place into the work queue. */ svn_error_t * @@ -2530,7 +2533,6 @@ svn_wc__db_global_commit(svn_wc__db_t *d apr_time_t changed_date, const char *changed_author, const svn_checksum_t *new_checksum, - const apr_array_header_t *new_children, apr_hash_t *new_dav_cache, svn_boolean_t keep_changelist, svn_boolean_t no_unlock, @@ -2933,34 +2935,6 @@ svn_wc__db_upgrade_begin(svn_sqlite__db_ const char *repos_uuid, apr_pool_t *scratch_pool); - -svn_error_t * -svn_wc__db_upgrade_apply_dav_cache(svn_sqlite__db_t *sdb, - const char *dir_relpath, - apr_hash_t *cache_values, - apr_pool_t *scratch_pool); - - -/* ### need much more docco - - ### this function should be called within a sqlite transaction. it makes - ### assumptions around this fact. - - Apply the various sets of properties to the database nodes based on - their existence/presence, the current state of the node, and the original - format of the working copy which provided these property sets. -*/ -svn_error_t * -svn_wc__db_upgrade_apply_props(svn_sqlite__db_t *sdb, - const char *dir_abspath, - const char *local_relpath, - apr_hash_t *base_props, - apr_hash_t *revert_props, - apr_hash_t *working_props, - int original_format, - apr_int64_t wc_id, - apr_pool_t *scratch_pool); - /* Simply insert (or replace) one row in the EXTERNALS table. */ svn_error_t * svn_wc__db_upgrade_insert_external(svn_wc__db_t *db, @@ -2975,20 +2949,6 @@ svn_wc__db_upgrade_insert_external(svn_w svn_revnum_t def_revision, apr_pool_t *scratch_pool); -/* Get the repository identifier corresponding to REPOS_ROOT_URL from the - database in SDB. The value is returned in *REPOS_ID. All allocations - are allocated in SCRATCH_POOL. - - NOTE: the row in REPOSITORY must exist. If not, then SVN_ERR_WC_DB_ERROR - is returned. - - ### unclear on whether/how this interface will stay/evolve. */ -svn_error_t * -svn_wc__db_upgrade_get_repos_id(apr_int64_t *repos_id, - svn_sqlite__db_t *sdb, - const char *repos_root_url, - apr_pool_t *scratch_pool); - /* Upgrade the metadata concerning the WC at WCROOT_ABSPATH, in DB, * to the SVN_WC__VERSION format. * @@ -3129,10 +3089,6 @@ svn_wc__db_wclock_owns_lock(svn_boolean_ This operation always recursively removes all nodes at and below LOCAL_ABSPATH from NODES and ACTUAL. - If NOT_PRESENT_REVISION specifies a valid revision, leave a not_present - BASE node at local_abspath of the specified status and kind. - (Requires an existing BASE node before removing) - If DESTROY_WC is TRUE, this operation *installs* workqueue operations to update the local filesystem after the database operation. If DESTROY_CHANGES is FALSE, modified and unversioned files are left after running this @@ -3150,9 +3106,6 @@ svn_wc__db_op_remove_node(svn_boolean_t const char *local_abspath, svn_boolean_t destroy_wc, svn_boolean_t destroy_changes, - svn_revnum_t not_present_revision, - svn_wc__db_status_t not_present_status, - svn_node_kind_t not_present_kind, const svn_skel_t *conflict, const svn_skel_t *work_items, svn_cancel_func_t cancel_func, @@ -3315,7 +3268,8 @@ svn_wc__db_get_not_present_descendants(c * * Indicate in *IS_SPARSE_CHECKOUT whether any of the nodes within * LOCAL_ABSPATH is sparse. - * Indicate in *IS_MODIFIED whether the working copy has local modifications. + * Indicate in *IS_MODIFIED whether the working copy has local modifications + * recorded for it in DB. * * Indicate in *IS_SWITCHED whether any node beneath LOCAL_ABSPATH * is switched. If TRAIL_URL is non-NULL, use it to determine if LOCAL_ABSPATH @@ -3336,8 +3290,6 @@ svn_wc__db_revision_status(svn_revnum_t const char *local_abspath, const char *trail_url, svn_boolean_t committed, - svn_cancel_func_t cancel_func, - void *cancel_baton, apr_pool_t *scratch_pool); /* Set *MIN_REVISION and *MAX_REVISION to the lowest and highest revision @@ -3398,16 +3350,13 @@ svn_wc__db_get_excluded_subtrees(apr_has /* Indicate in *IS_MODIFIED whether the working copy has local modifications, * using DB. Use SCRATCH_POOL for temporary allocations. * - * This function provides a subset of the functionality of - * svn_wc__db_revision_status() and is more efficient if the caller - * doesn't need all information returned by svn_wc__db_revision_status(). */ + * This function does not check the working copy state, but is a lot more + * efficient than a full status walk. */ svn_error_t * -svn_wc__db_has_local_mods(svn_boolean_t *is_modified, - svn_wc__db_t *db, - const char *local_abspath, - svn_cancel_func_t cancel_func, - void *cancel_baton, - apr_pool_t *scratch_pool); +svn_wc__db_has_db_mods(svn_boolean_t *is_modified, + svn_wc__db_t *db, + const char *local_abspath, + apr_pool_t *scratch_pool); /* Verify the consistency of metadata concerning the WC that contains @@ -3477,41 +3426,24 @@ svn_wc__db_vacuum(svn_wc__db_t *db, comment in resolve_conflict_on_node about combining with another function. */ 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); - -/* Like svn_wc__db_resolve_delete_raise_moved_away this should be - combined. - - ### LOCAL_ABSPATH specifies the move origin, but the move origin - ### is not necessary unique enough. This function needs an op_root_abspath - ### argument to differentiate between different origins. - - ### See move_tests.py: move_many_update_delete for an example case. - */ -svn_error_t * -svn_wc__db_resolve_break_moved_away(svn_wc__db_t *db, - const char *local_abspath, - const char *src_op_root_abspath, - svn_wc_notify_func2_t notify_func, - void *notify_baton, - apr_pool_t *scratch_pool); +svn_wc__db_op_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); -/* Break moves for all moved-away children of LOCAL_ABSPATH, within - * a single transaction. - * - * ### Like svn_wc__db_resolve_delete_raise_moved_away this should be - * combined. */ +/* Breaks all moves of nodes that exist at or below LOCAL_ABSPATH as + shadowed (read: deleted) by the opration rooted at + delete_op_root_abspath. + */ svn_error_t * -svn_wc__db_resolve_break_moved_away_children(svn_wc__db_t *db, - const char *local_abspath, - const char *src_op_root_abspath, - svn_wc_notify_func2_t notify_func, - void *notify_baton, - apr_pool_t *scratch_pool); +svn_wc__db_op_break_moved_away(svn_wc__db_t *db, + const char *local_abspath, + const char *delete_op_root_abspath, + svn_boolean_t mark_tc_resolved, + svn_wc_notify_func2_t notify_func, + void *notify_baton, + apr_pool_t *scratch_pool); /* Set *REQUIRED_ABSPATH to the path that should be locked to ensure * that the lock covers all paths affected by resolving the conflicts @@ -3524,6 +3456,28 @@ svn_wc__required_lock_for_resolve(const apr_pool_t *scratch_pool); /* @} */ +typedef svn_error_t * (*svn_wc__db_verify_cb_t)(void *baton, + const char *wc_abspath, + const char *local_relpath, + int op_depth, + int id, + const char *description, + apr_pool_t *scratch_pool); + +/* Checks the database for FULL-correctness according to the spec. + + Note that typical 1.7-1.9 databases WILL PRODUCE warnings. + + This is mainly useful for WC-NG developers, as there will be + warnings without the database being corrupt +*/ +svn_error_t * +svn_wc__db_verify_db_full(svn_wc__db_t *db, + const char *wri_abspath, + svn_wc__db_verify_cb_t callback, + void *baton, + apr_pool_t *scratch_pool); + #ifdef __cplusplus }
Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db_private.h URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db_private.h?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db_private.h (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db_private.h Sun Jun 14 20:58:10 2015 @@ -313,6 +313,32 @@ svn_wc__db_depth_get_info(svn_wc__db_sta apr_pool_t *result_pool, apr_pool_t *scratch_pool); +svn_error_t * +svn_wc__db_scan_addition_internal( + svn_wc__db_status_t *status, + const char **op_root_relpath_p, + const char **repos_relpath, + apr_int64_t *repos_id, + const char **original_repos_relpath, + apr_int64_t *original_repos_id, + svn_revnum_t *original_revision, + svn_wc__db_wcroot_t *wcroot, + const char *local_relpath, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +svn_error_t * +svn_wc__db_scan_deletion_internal( + const char **base_del_relpath, + const char **moved_to_relpath, + const char **work_del_relpath, + const char **moved_to_op_root_relpath, + svn_wc__db_wcroot_t *wcroot, + const char *local_relpath, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + + /* Look up REPOS_ID in WCROOT->SDB and set *REPOS_ROOT_URL and/or *REPOS_UUID to its root URL and UUID respectively. If REPOS_ID is INVALID_REPOS_ID, use NULL for both URL and UUID. Either or both output parameters may be @@ -328,6 +354,8 @@ svn_wc__db_fetch_repos_info(const char * DB+LOCAL_ABSPATH, and outputting relpaths instead of abspaths. */ svn_error_t * svn_wc__db_read_conflict_internal(svn_skel_t **conflict, + svn_node_kind_t *kind, + apr_hash_t **props, svn_wc__db_wcroot_t *wcroot, const char *local_relpath, apr_pool_t *result_pool, @@ -344,23 +372,6 @@ svn_wc__db_mark_conflict_internal(svn_wc /* Transaction handling */ -/* A callback which supplies WCROOTs and LOCAL_RELPATHs. */ -typedef svn_error_t *(*svn_wc__db_txn_callback_t)(void *baton, - svn_wc__db_wcroot_t *wcroot, - const char *local_relpath, - apr_pool_t *scratch_pool); - - -/* Run CB_FUNC in a SQLite transaction with CB_BATON, using WCROOT and - LOCAL_RELPATH. If callbacks require additional information, they may - provide it using CB_BATON. */ -svn_error_t * -svn_wc__db_with_txn(svn_wc__db_wcroot_t *wcroot, - const char *local_relpath, - svn_wc__db_txn_callback_t cb_func, - void *cb_baton, - apr_pool_t *scratch_pool); - /* Evaluate the expression EXPR within a transaction. * * Begin a transaction in WCROOT's DB; evaluate the expression EXPR, which would @@ -399,6 +410,7 @@ svn_wc__db_op_copy_layer_internal(svn_wc svn_error_t * svn_wc__db_op_make_copy_internal(svn_wc__db_wcroot_t *wcroot, const char *local_relpath, + svn_boolean_t move_move_info, const svn_skel_t *conflicts, const svn_skel_t *work_items, apr_pool_t *scratch_pool); @@ -485,16 +497,27 @@ svn_wc__db_bump_moved_away(svn_wc__db_wc svn_error_t * svn_wc__db_op_break_move_internal(svn_wc__db_wcroot_t *wcroot, const char *src_relpath, - int src_op_depth, + int delete_op_depth, const char *dst_relpath, const svn_skel_t *work_items, apr_pool_t *scratch_pool); svn_error_t * +svn_wc__db_op_mark_resolved_internal(svn_wc__db_wcroot_t *wcroot, + const char *local_relpath, + svn_wc__db_t *db, + svn_boolean_t resolved_text, + svn_boolean_t resolved_props, + svn_boolean_t resolved_tree, + const svn_skel_t *work_items, + apr_pool_t *scratch_pool); + +/* op_depth is the depth at which the node is added. */ +svn_error_t * svn_wc__db_op_raise_moved_away_internal( svn_wc__db_wcroot_t *wcroot, const char *local_relpath, - int delete_op_depth, + int op_depth, svn_wc__db_t *db, svn_wc_operation_t operation, svn_wc_conflict_action_t action, @@ -510,4 +533,10 @@ svn_wc__db_update_move_list_notify(svn_w void *notify_baton, apr_pool_t *scratch_pool); +svn_error_t * +svn_wc__db_verify_db_full_internal(svn_wc__db_wcroot_t *wcroot, + svn_wc__db_verify_cb_t callback, + void *baton, + apr_pool_t *scratch_pool); + #endif /* WC_DB_PRIVATE_H */ Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db_update_move.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db_update_move.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db_update_move.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db_update_move.c Sun Jun 14 20:58:10 2015 @@ -166,7 +166,7 @@ find_src_op_depth(int *src_op_depth, *src_op_depth = svn_sqlite__column_int(stmt, 0); SVN_ERR(svn_sqlite__reset(stmt)); if (!have_row) - return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL, _("'%s' is not deleted"), path_for_error_message(wcroot, src_relpath, scratch_pool)); @@ -377,7 +377,8 @@ create_tree_conflict(svn_skel_t **confli child_relpath, scratch_pool); } - err = svn_wc__db_read_conflict_internal(&conflict, wcroot, local_relpath, + err = svn_wc__db_read_conflict_internal(&conflict, NULL, NULL, + wcroot, local_relpath, result_pool, scratch_pool); if (err && err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND) return svn_error_trace(err); @@ -399,7 +400,7 @@ create_tree_conflict(svn_skel_t **confli if (conflict_operation != svn_wc_operation_update && conflict_operation != svn_wc_operation_switch) - return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + return svn_error_createf(SVN_ERR_WC_FOUND_CONFLICT, NULL, _("'%s' already in conflict"), path_for_error_message(wcroot, local_relpath, scratch_pool)); @@ -423,7 +424,7 @@ create_tree_conflict(svn_skel_t **confli && strcmp(move_src_op_root_relpath, svn_dirent_skip_ancestor(wcroot->abspath, existing_abspath)))) - return svn_error_createf(SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL, + return svn_error_createf(SVN_ERR_WC_FOUND_CONFLICT, NULL, _("'%s' already in conflict"), path_for_error_message(wcroot, local_relpath, @@ -447,16 +448,10 @@ create_tree_conflict(svn_skel_t **confli result_pool, scratch_pool)); - if (reason != svn_wc_conflict_reason_unversioned - && old_repos_relpath != NULL /* no local additions */) - { - conflict_old_version = svn_wc_conflict_version_create2( + 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 - conflict_old_version = NULL; conflict_new_version = svn_wc_conflict_version_create2( new_version->repos_url, new_version->repos_uuid, @@ -487,7 +482,6 @@ create_node_tree_conflict(svn_skel_t **c const char *dst_local_relpath, svn_node_kind_t old_kind, svn_node_kind_t new_kind, - const char *old_repos_relpath, svn_wc_conflict_reason_t reason, svn_wc_conflict_action_t action, const char *move_src_op_root_relpath, @@ -495,16 +489,28 @@ create_node_tree_conflict(svn_skel_t **c apr_pool_t *scratch_pool) { update_move_baton_t *umb = nmb->umb; + const char *dst_repos_relpath; + const char *dst_root_relpath = svn_relpath_prefix(nmb->dst_relpath, + nmb->umb->dst_op_depth, + scratch_pool); + + dst_repos_relpath = + svn_relpath_join(nmb->umb->old_version->path_in_repos, + svn_relpath_skip_ancestor(dst_root_relpath, + nmb->dst_relpath), + scratch_pool); + + return svn_error_trace( create_tree_conflict(conflict_p, umb->wcroot, dst_local_relpath, - svn_relpath_limit(dst_local_relpath, - umb->dst_op_depth, - scratch_pool), + svn_relpath_prefix(dst_local_relpath, + umb->dst_op_depth, + scratch_pool), umb->db, umb->old_version, umb->new_version, umb->operation, old_kind, new_kind, - old_repos_relpath, + dst_repos_relpath, reason, action, move_src_op_root_relpath, result_pool, scratch_pool)); } @@ -547,7 +553,6 @@ static svn_error_t * mark_tc_on_op_root(node_move_baton_t *nmb, svn_node_kind_t old_kind, svn_node_kind_t new_kind, - const char *old_repos_relpath, svn_wc_conflict_action_t action, apr_pool_t *scratch_pool) { @@ -569,7 +574,6 @@ mark_tc_on_op_root(node_move_baton_t *nm SVN_ERR(create_node_tree_conflict(&conflict, nmb, nmb->dst_relpath, old_kind, new_kind, - old_repos_relpath, (move_dst_relpath ? svn_wc_conflict_reason_moved_away : svn_wc_conflict_reason_deleted), @@ -611,10 +615,9 @@ mark_node_edited(node_move_baton_t *nmb, if (nmb->shadowed && !(nmb->pb && nmb->pb->shadowed)) { svn_node_kind_t dst_kind, src_kind; - const char *dst_repos_relpath; SVN_ERR(svn_wc__db_depth_get_info(NULL, &dst_kind, NULL, - &dst_repos_relpath, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, nmb->umb->wcroot, nmb->dst_relpath, nmb->umb->dst_op_depth, @@ -629,7 +632,6 @@ mark_node_edited(node_move_baton_t *nmb, SVN_ERR(mark_tc_on_op_root(nmb, dst_kind, src_kind, - dst_repos_relpath, svn_wc_conflict_action_edit, scratch_pool)); } @@ -659,61 +661,61 @@ tc_editor_add_directory(node_move_baton_ apr_pool_t *scratch_pool) { update_move_baton_t *b = nmb->umb; - const char *move_dst_repos_relpath; const char *local_abspath; svn_node_kind_t wc_kind; svn_skel_t *work_item = NULL; svn_skel_t *conflict = NULL; + svn_wc_conflict_reason_t reason = svn_wc_conflict_reason_unversioned; SVN_ERR(mark_parent_edited(nmb, scratch_pool)); if (nmb->skip) return SVN_NO_ERROR; - /* We can't read the information from the pre-add node to obtain the - relpath, but in WORKING we can just calculate it from the op-root */ - { - const char *dst_op_root_relpath = svn_relpath_limit(nmb->pb->dst_relpath, - b->dst_op_depth, - scratch_pool); - SVN_ERR(svn_wc__db_depth_get_info(NULL, NULL, NULL, - &move_dst_repos_relpath, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, - NULL, - b->wcroot, dst_op_root_relpath, - b->dst_op_depth, - scratch_pool, scratch_pool)); - - move_dst_repos_relpath = - svn_relpath_join(move_dst_repos_relpath, - svn_relpath_skip_ancestor(dst_op_root_relpath, - relpath), - scratch_pool); - } - if (nmb->shadowed) { - SVN_ERR(mark_tc_on_op_root(nmb, - svn_node_none, svn_node_dir, - move_dst_repos_relpath, - svn_wc_conflict_action_add, - scratch_pool)); - return SVN_NO_ERROR; + svn_wc__db_status_t status; + + SVN_ERR(svn_wc__db_read_info_internal(&status, &wc_kind, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + b->wcroot, relpath, + scratch_pool, scratch_pool)); + + if (status == svn_wc__db_status_deleted) + reason = svn_wc_conflict_reason_deleted; + else if (status != svn_wc__db_status_added) + wc_kind = svn_node_none; + else if (old_kind == svn_node_none) + reason = svn_wc_conflict_reason_added; + else + reason = svn_wc_conflict_reason_replaced; } + else + wc_kind = svn_node_none; - /* Check for unversioned tree-conflict */ local_abspath = svn_dirent_join(b->wcroot->abspath, relpath, scratch_pool); - SVN_ERR(svn_io_check_path(local_abspath, &wc_kind, scratch_pool)); - if (wc_kind == old_kind) + if (wc_kind == svn_node_none) + { + /* Check for unversioned tree-conflict */ + SVN_ERR(svn_io_check_path(local_abspath, &wc_kind, scratch_pool)); + } + + if (!nmb->shadowed && wc_kind == old_kind) wc_kind = svn_node_none; /* Node will be gone once we install */ - if (wc_kind != svn_node_none) + if (wc_kind != svn_node_none + && (nmb->shadowed || wc_kind != old_kind)) /* replace */ { SVN_ERR(create_node_tree_conflict(&conflict, nmb, relpath, - wc_kind, svn_node_dir, - move_dst_repos_relpath, - svn_wc_conflict_reason_unversioned, - svn_wc_conflict_action_add, NULL, + old_kind, svn_node_dir, + reason, + (old_kind == svn_node_none) + ? svn_wc_conflict_action_add + : svn_wc_conflict_action_replace, + NULL, scratch_pool, scratch_pool)); nmb->skip = TRUE; } @@ -743,7 +745,7 @@ tc_editor_add_file(node_move_baton_t *nm apr_pool_t *scratch_pool) { update_move_baton_t *b = nmb->umb; - const char *move_dst_repos_relpath; + svn_wc_conflict_reason_t reason = svn_wc_conflict_reason_unversioned; svn_node_kind_t wc_kind; const char *local_abspath; svn_skel_t *work_item = NULL; @@ -753,52 +755,48 @@ tc_editor_add_file(node_move_baton_t *nm if (nmb->skip) return SVN_NO_ERROR; - /* We can't read the information from the pre-add node to obtain the - relpath, but in WORKING we can just calculate it from the op-root */ - { - const char *dst_op_root_relpath = svn_relpath_limit(nmb->pb->dst_relpath, - b->dst_op_depth, - scratch_pool); - SVN_ERR(svn_wc__db_depth_get_info(NULL, NULL, NULL, - &move_dst_repos_relpath, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, - NULL, - b->wcroot, dst_op_root_relpath, - b->dst_op_depth, - scratch_pool, scratch_pool)); - - move_dst_repos_relpath = - svn_relpath_join(move_dst_repos_relpath, - svn_relpath_skip_ancestor(dst_op_root_relpath, - relpath), - scratch_pool); - } - - /* Check for NODES tree-conflict. */ if (nmb->shadowed) { - SVN_ERR(mark_tc_on_op_root(nmb, - svn_node_none, svn_node_file, - move_dst_repos_relpath, - svn_wc_conflict_action_add, - scratch_pool)); - return SVN_NO_ERROR; + svn_wc__db_status_t status; + + SVN_ERR(svn_wc__db_read_info_internal(&status, &wc_kind, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + b->wcroot, relpath, + scratch_pool, scratch_pool)); + + if (status == svn_wc__db_status_deleted) + reason = svn_wc_conflict_reason_deleted; + else if (status != svn_wc__db_status_added) + wc_kind = svn_node_none; + else if (old_kind == svn_node_none) + reason = svn_wc_conflict_reason_added; + else + reason = svn_wc_conflict_reason_replaced; } + else + wc_kind = svn_node_none; - /* Check for unversioned tree-conflict */ local_abspath = svn_dirent_join(b->wcroot->abspath, relpath, scratch_pool); - SVN_ERR(svn_io_check_path(local_abspath, &wc_kind, scratch_pool)); - if (wc_kind == old_kind) - wc_kind = svn_node_none; /* Node will be gone once we install */ + if (wc_kind == svn_node_none) + { + /* Check for unversioned tree-conflict */ + SVN_ERR(svn_io_check_path(local_abspath, &wc_kind, scratch_pool)); + } - if (wc_kind != svn_node_none) + if (wc_kind != svn_node_none + && (nmb->shadowed || wc_kind != old_kind)) /* replace */ { SVN_ERR(create_node_tree_conflict(&conflict, nmb, relpath, - wc_kind, svn_node_file, - move_dst_repos_relpath, - svn_wc_conflict_reason_unversioned, - svn_wc_conflict_action_add, NULL, + old_kind, svn_node_file, + reason, + (old_kind == svn_node_none) + ? svn_wc_conflict_action_add + : svn_wc_conflict_action_replace, + NULL, scratch_pool, scratch_pool)); nmb->skip = TRUE; } @@ -977,8 +975,7 @@ tc_editor_alter_directory(node_move_bato if (wc_kind != svn_node_none && wc_kind != svn_node_dir) { SVN_ERR(create_node_tree_conflict(&conflict_skel, nmb, dst_relpath, - wc_kind, svn_node_dir, - NULL /* local obstruction relpath */, + svn_node_dir, svn_node_dir, svn_wc_conflict_reason_obstructed, svn_wc_conflict_action_edit, NULL, @@ -1080,8 +1077,7 @@ tc_editor_alter_file(node_move_baton_t * if (wc_kind != svn_node_none && wc_kind != svn_node_file) { SVN_ERR(create_node_tree_conflict(&conflict_skel, nmb, dst_relpath, - wc_kind, svn_node_file, - NULL /* local obstruction relpath */, + svn_node_file, svn_node_file, svn_wc_conflict_reason_obstructed, svn_wc_conflict_action_edit, NULL, @@ -1209,8 +1205,6 @@ tc_editor_delete(node_move_baton_t *nmb, { update_move_baton_t *b = nmb->umb; svn_sqlite__stmt_t *stmt; - const char *move_dst_repos_relpath; - svn_node_kind_t move_dst_kind; const char *local_abspath; svn_boolean_t is_modified, is_all_deletes; svn_skel_t *work_items = NULL; @@ -1220,21 +1214,13 @@ tc_editor_delete(node_move_baton_t *nmb, if (nmb->skip) return SVN_NO_ERROR; - SVN_ERR(svn_wc__db_depth_get_info(NULL, &move_dst_kind, NULL, - &move_dst_repos_relpath, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, - b->wcroot, relpath, b->dst_op_depth, - scratch_pool, scratch_pool)); - /* Check before retracting delete to catch delete-delete conflicts. This catches conflicts on the node itself; deleted children are caught as local modifications below.*/ if (nmb->shadowed) { SVN_ERR(mark_tc_on_op_root(nmb, - move_dst_kind, - new_kind, - move_dst_repos_relpath, + old_kind, new_kind, svn_wc_conflict_action_delete, scratch_pool)); return SVN_NO_ERROR; @@ -1242,7 +1228,7 @@ tc_editor_delete(node_move_baton_t *nmb, local_abspath = svn_dirent_join(b->wcroot->abspath, relpath, scratch_pool); SVN_ERR(svn_wc__node_has_local_mods(&is_modified, &is_all_deletes, - nmb->umb->db, local_abspath, + nmb->umb->db, local_abspath, FALSE, NULL, NULL, scratch_pool)); if (is_modified) { @@ -1256,14 +1242,13 @@ tc_editor_delete(node_move_baton_t *nmb, * it is not the/an op-root. (or we can't make us a copy) */ - SVN_ERR(svn_wc__db_op_make_copy_internal(b->wcroot, relpath, + SVN_ERR(svn_wc__db_op_make_copy_internal(b->wcroot, relpath, FALSE, NULL, NULL, scratch_pool)); reason = svn_wc_conflict_reason_edited; SVN_ERR(create_node_tree_conflict(&conflict, nmb, relpath, - move_dst_kind, new_kind, - move_dst_repos_relpath, reason, + old_kind, new_kind, reason, (new_kind == svn_node_none) ? svn_wc_conflict_action_delete : svn_wc_conflict_action_replace, @@ -1331,7 +1316,7 @@ tc_editor_delete(node_move_baton_t *nmb, if (conflict || (new_kind == svn_node_none)) SVN_ERR(update_move_list_add(b->wcroot, relpath, b->db, svn_wc_notify_update_delete, - move_dst_kind, + new_kind, svn_wc_notify_state_inapplicable, svn_wc_notify_state_inapplicable, conflict, work_items, scratch_pool)); @@ -1358,68 +1343,6 @@ tc_editor_delete(node_move_baton_t *nmb, * single-revision. */ -/* Set *OPERATION, *LOCAL_CHANGE, *INCOMING_CHANGE, *OLD_VERSION, *NEW_VERSION - * to reflect the tree conflict on the victim SRC_ABSPATH in DB. - * - * If SRC_ABSPATH is not a tree-conflict victim, return an error. - */ -static svn_error_t * -get_tc_info(svn_wc_operation_t *operation, - svn_wc_conflict_reason_t *local_change, - svn_wc_conflict_action_t *incoming_change, - const char **move_src_op_root_abspath, - svn_wc_conflict_version_t **old_version, - svn_wc_conflict_version_t **new_version, - svn_wc__db_t *db, - const char *src_abspath, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) -{ - const apr_array_header_t *locations; - svn_boolean_t tree_conflicted; - svn_skel_t *conflict_skel; - - /* Check for tree conflict on src. */ - SVN_ERR(svn_wc__db_read_conflict(&conflict_skel, db, - src_abspath, - scratch_pool, scratch_pool)); - if (!conflict_skel) - return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, - _("'%s' is not in conflict"), - svn_dirent_local_style(src_abspath, - scratch_pool)); - - SVN_ERR(svn_wc__conflict_read_info(operation, &locations, - NULL, NULL, &tree_conflicted, - db, src_abspath, - conflict_skel, result_pool, - scratch_pool)); - if ((*operation != svn_wc_operation_update - && *operation != svn_wc_operation_switch) - || !tree_conflicted) - return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, - _("'%s' is not a tree-conflict victim"), - svn_dirent_local_style(src_abspath, - scratch_pool)); - if (locations) - { - SVN_ERR_ASSERT(locations->nelts >= 2); - *old_version = APR_ARRAY_IDX(locations, 0, - svn_wc_conflict_version_t *); - *new_version = APR_ARRAY_IDX(locations, 1, - svn_wc_conflict_version_t *); - } - - SVN_ERR(svn_wc__conflict_read_tree_conflict(local_change, - incoming_change, - move_src_op_root_abspath, - db, src_abspath, - conflict_skel, scratch_pool, - scratch_pool)); - - return SVN_NO_ERROR; -} - /* Return *PROPS, *CHECKSUM, *CHILDREN and *KIND for LOCAL_RELPATH at OP_DEPTH provided the row exists. Return *KIND of svn_node_none if the row does not exist, or only describes a delete of a lower op-depth. @@ -1957,6 +1880,7 @@ depth_sufficient_to_bump(svn_boolean_t * static svn_error_t * bump_mark_tree_conflict(svn_wc__db_wcroot_t *wcroot, const char *move_src_root_relpath, + int src_op_depth, const char *move_src_op_root_relpath, const char *move_dst_op_root_relpath, svn_wc__db_t *db, @@ -1979,12 +1903,12 @@ bump_mark_tree_conflict(svn_wc__db_wcroo SVN_ERR(verify_write_lock(wcroot, move_src_root_relpath, scratch_pool)); /* 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_depth_get_info(NULL, &new_kind, &new_rev, + &new_repos_relpath, &repos_id, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + wcroot, move_src_op_root_relpath, + src_op_depth, scratch_pool, scratch_pool)); SVN_ERR(svn_wc__db_fetch_repos_info(&repos_root_url, &repos_uuid, wcroot, repos_id, scratch_pool)); @@ -2120,6 +2044,7 @@ bump_moved_layer(svn_boolean_t *recurse, svn_boolean_t have_row; svn_skel_t *conflict; svn_boolean_t can_bump; + const char *src_root_relpath; SVN_ERR(verify_write_lock(wcroot, local_relpath, scratch_pool)); @@ -2158,24 +2083,21 @@ bump_moved_layer(svn_boolean_t *recurse, can_bump = FALSE; } - { - const char *src_root_relpath = src_relpath; - while (relpath_depth(src_root_relpath) > src_del_depth) - src_root_relpath = svn_relpath_dirname(src_root_relpath, scratch_pool); - - if (!can_bump) - { - SVN_ERR(bump_mark_tree_conflict(wcroot, src_relpath, - src_root_relpath, dst_relpath, - db, scratch_pool)); + src_root_relpath = svn_relpath_prefix(src_relpath, src_del_depth, + scratch_pool); - return SVN_NO_ERROR; - } + if (!can_bump) + { + SVN_ERR(bump_mark_tree_conflict(wcroot, src_relpath, op_depth, + src_root_relpath, dst_relpath, + db, scratch_pool)); - SVN_ERR(svn_wc__db_read_conflict_internal(&conflict, wcroot, - src_root_relpath, - scratch_pool, scratch_pool)); - } + return SVN_NO_ERROR; + } + + SVN_ERR(svn_wc__db_read_conflict_internal(&conflict, NULL, NULL, + wcroot, src_root_relpath, + scratch_pool, scratch_pool)); /* ### TODO: check this is the right sort of tree-conflict? */ if (!conflict) @@ -2331,7 +2253,7 @@ svn_wc__db_bump_moved_away(svn_wc__db_wc if (locked) { SVN_ERR(bump_mark_tree_conflict(wcroot, - move_src_root_relpath, + move_src_root_relpath, 0, delete_relpath, move_dst_op_root_relpath, db, scratch_pool)); @@ -2346,11 +2268,103 @@ svn_wc__db_bump_moved_away(svn_wc__db_wc return SVN_NO_ERROR; } +/* Set *OPERATION, *LOCAL_CHANGE, *INCOMING_CHANGE, *OLD_VERSION, *NEW_VERSION + * to reflect the tree conflict on the victim SRC_ABSPATH in DB. + * + * If SRC_ABSPATH is not a tree-conflict victim, return an error. + */ +static svn_error_t * +fetch_conflict_details(int *src_op_depth, + svn_wc_operation_t *operation, + svn_wc_conflict_action_t *action, + svn_wc_conflict_version_t **left_version, + svn_wc_conflict_version_t **right_version, + svn_wc__db_wcroot_t *wcroot, + svn_wc__db_t *db, + const char *local_relpath, + const svn_skel_t *conflict_skel, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const apr_array_header_t *locations; + svn_boolean_t text_conflicted; + svn_boolean_t prop_conflicted; + svn_boolean_t tree_conflicted; + const char *move_src_op_root_abspath; + svn_wc_conflict_reason_t reason; + const char *local_abspath = svn_dirent_join(wcroot->abspath, local_relpath, + scratch_pool); + + if (!conflict_skel) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("'%s' is not in conflict"), + path_for_error_message(wcroot, local_relpath, + scratch_pool)); + + SVN_ERR(svn_wc__conflict_read_info(operation, &locations, + &text_conflicted, &prop_conflicted, + &tree_conflicted, + db, local_abspath, + conflict_skel, result_pool, + scratch_pool)); + + if (text_conflicted || prop_conflicted || !tree_conflicted) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("'%s' is not a valid tree-conflict victim"), + path_for_error_message(wcroot, local_relpath, + scratch_pool)); + + SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, + action, + &move_src_op_root_abspath, + db, local_abspath, + conflict_skel, result_pool, + scratch_pool)); + + if (reason == svn_wc_conflict_reason_moved_away) + return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL, + _("'%s' is already a moved away tree-conflict"), + path_for_error_message(wcroot, local_relpath, + scratch_pool)); + + if (left_version) + { + if (locations && locations->nelts > 0) + *left_version = APR_ARRAY_IDX(locations, 0, + svn_wc_conflict_version_t *); + else + *left_version = NULL; + } + + if (right_version) + { + if (locations && locations->nelts > 1) + *right_version = APR_ARRAY_IDX(locations, 1, + svn_wc_conflict_version_t *); + else + *right_version = NULL; + } + + { + int del_depth = relpath_depth(local_relpath); + + if (move_src_op_root_abspath) + del_depth = relpath_depth( + svn_dirent_skip_ancestor(wcroot->abspath, + move_src_op_root_abspath)); + + SVN_ERR(find_src_op_depth(src_op_depth, wcroot, local_relpath, del_depth, + scratch_pool)); + } + + return SVN_NO_ERROR; +} + svn_error_t * svn_wc__db_op_raise_moved_away_internal( svn_wc__db_wcroot_t *wcroot, const char *local_relpath, - int delete_op_depth, + int src_op_depth, svn_wc__db_t *db, svn_wc_operation_t operation, svn_wc_conflict_action_t action, @@ -2366,13 +2380,14 @@ svn_wc__db_op_raise_moved_away_internal( STMT_CREATE_UPDATE_MOVE_LIST)); SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, - STMT_SELECT_MOVED_DESCENDANTS_SHD)); + STMT_SELECT_MOVED_DESCENDANTS_SRC)); SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath, - delete_op_depth)); + src_op_depth)); SVN_ERR(svn_sqlite__step(&have_row, stmt)); while(have_row) { svn_error_t *err; + int delete_op_depth = svn_sqlite__column_int(stmt, 0); const char *src_relpath = svn_sqlite__column_text(stmt, 1, NULL); svn_node_kind_t src_kind = svn_sqlite__column_token(stmt, 2, kind_map); const char *src_repos_relpath = svn_sqlite__column_text(stmt, 3, NULL); @@ -2389,9 +2404,9 @@ svn_wc__db_op_raise_moved_away_internal( src_repos_relpath, svn_wc_conflict_reason_moved_away, action, - svn_relpath_limit(src_relpath, - delete_op_depth, - iterpool), + svn_relpath_prefix(src_relpath, + delete_op_depth, + iterpool), iterpool, iterpool); if (!err) @@ -2415,42 +2430,52 @@ svn_wc__db_op_raise_moved_away_internal( } 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_op_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; const char *local_relpath; svn_wc_operation_t operation; - svn_wc_conflict_reason_t reason; svn_wc_conflict_action_t action; - svn_wc_conflict_version_t *old_version, *new_version; + svn_wc_conflict_version_t *left_version, *right_version; + int move_src_op_depth; + svn_skel_t *conflict; SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db, local_abspath, scratch_pool, scratch_pool)); VERIFY_USABLE_WCROOT(wcroot); - SVN_ERR(get_tc_info(&operation, &reason, &action, NULL, - &old_version, &new_version, - db, local_abspath, scratch_pool, scratch_pool)); - - SVN_WC__DB_WITH_TXN( + SVN_WC__DB_WITH_TXN4( + svn_wc__db_read_conflict_internal(&conflict, NULL, NULL, + wcroot, local_relpath, + scratch_pool, scratch_pool), + fetch_conflict_details(&move_src_op_depth, + &operation, &action, + &left_version, &right_version, + wcroot, db, local_relpath, conflict, + scratch_pool, scratch_pool), + svn_wc__db_op_mark_resolved_internal(wcroot, local_relpath, db, + FALSE, FALSE, TRUE, + NULL, scratch_pool), svn_wc__db_op_raise_moved_away_internal(wcroot, local_relpath, - relpath_depth(local_relpath), + move_src_op_depth, db, operation, action, - old_version, new_version, + left_version, right_version, scratch_pool), wcroot); + /* These version numbers are valid for update/switch notifications + only! */ SVN_ERR(svn_wc__db_update_move_list_notify(wcroot, - (old_version - ? old_version->peg_rev + (left_version + ? left_version->peg_rev : SVN_INVALID_REVNUM), - (new_version - ? new_version->peg_rev + (right_version + ? right_version->peg_rev : SVN_INVALID_REVNUM), notify_func, notify_baton, scratch_pool)); @@ -2460,44 +2485,15 @@ svn_wc__db_resolve_delete_raise_moved_aw static svn_error_t * break_moved_away(svn_wc__db_wcroot_t *wcroot, + svn_wc__db_t *db, const char *local_relpath, - int op_depth, + int parent_src_op_depth, apr_pool_t *scratch_pool) { - const char *dst_relpath; - int src_op_depth; - const char *delete_relpath; - - SVN_ERR(find_src_op_depth(&src_op_depth, wcroot, - local_relpath, op_depth, - scratch_pool)); - - - SVN_ERR(svn_wc__db_scan_moved_to_internal(NULL, &dst_relpath, - &delete_relpath, - wcroot, local_relpath, - src_op_depth, - scratch_pool, scratch_pool)); - - SVN_ERR_ASSERT(dst_relpath != NULL && delete_relpath != NULL); - - SVN_ERR(svn_wc__db_op_break_move_internal(wcroot, local_relpath, - relpath_depth(delete_relpath), - dst_relpath, NULL, - scratch_pool)); - - return SVN_NO_ERROR; -} - -static svn_error_t * -break_moved_away_children(svn_wc__db_wcroot_t *wcroot, - svn_wc__db_t *db, - const char *local_relpath, - apr_pool_t *scratch_pool) -{ svn_sqlite__stmt_t *stmt; svn_boolean_t have_row; apr_pool_t *iterpool; + svn_error_t *err = NULL; SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb, STMT_CREATE_UPDATE_MOVE_LIST)); @@ -2505,112 +2501,92 @@ break_moved_away_children(svn_wc__db_wcr SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_MOVED_DESCENDANTS_SRC)); SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath, - relpath_depth(local_relpath))); + parent_src_op_depth)); SVN_ERR(svn_sqlite__step(&have_row, stmt)); iterpool = svn_pool_create(scratch_pool); while (have_row) { - int src_op_depth = svn_sqlite__column_int(stmt, 0) ; + int src_op_depth = svn_sqlite__column_int(stmt, 0); const char *src_relpath = svn_sqlite__column_text(stmt, 1, NULL); svn_node_kind_t src_kind = svn_sqlite__column_token(stmt, 2, kind_map); const char *dst_relpath = svn_sqlite__column_text(stmt, 4, NULL); - svn_error_t *err; svn_pool_clear(iterpool); - err = svn_wc__db_op_break_move_internal(wcroot, - src_relpath, src_op_depth, - dst_relpath, NULL, iterpool); + err = verify_write_lock(wcroot, src_relpath, iterpool); - if (! err) - { - err = update_move_list_add(wcroot, src_relpath, db, - svn_wc_notify_move_broken, - src_kind, - svn_wc_notify_state_inapplicable, - svn_wc_notify_state_inapplicable, - NULL, NULL, scratch_pool); - } + if (!err) + err = verify_write_lock(wcroot, dst_relpath, iterpool); if (err) - { - return svn_error_trace( - svn_error_compose_create(err, - svn_sqlite__reset(stmt))); - } - - SVN_ERR(svn_sqlite__step(&have_row, stmt)); - } - svn_pool_destroy(iterpool); - - SVN_ERR(svn_sqlite__reset(stmt)); - - return SVN_NO_ERROR; -} - -svn_error_t * -svn_wc__db_resolve_break_moved_away(svn_wc__db_t *db, - const char *local_abspath, - const char *src_op_root_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; - const char *src_relpath; + break; - SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, - db, local_abspath, - scratch_pool, scratch_pool)); - VERIFY_USABLE_WCROOT(wcroot); + err = svn_error_trace( + svn_wc__db_op_break_move_internal(wcroot, + src_relpath, src_op_depth, + dst_relpath, NULL, iterpool)); - src_relpath = svn_dirent_skip_ancestor(wcroot->abspath, src_op_root_abspath); - SVN_ERR_ASSERT(src_relpath != NULL); + if (err) + break; - SVN_WC__DB_WITH_TXN(break_moved_away(wcroot, local_relpath, - relpath_depth(src_relpath), - scratch_pool), - wcroot); + err = svn_error_trace( + update_move_list_add(wcroot, src_relpath, db, + svn_wc_notify_move_broken, + src_kind, + svn_wc_notify_state_inapplicable, + svn_wc_notify_state_inapplicable, + NULL, NULL, scratch_pool)); - if (notify_func) - { - svn_wc_notify_t *notify; + if (err) + break; - 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); + SVN_ERR(svn_sqlite__step(&have_row, stmt)); } + svn_pool_destroy(iterpool); - return SVN_NO_ERROR; + return svn_error_compose_create(err, svn_sqlite__reset(stmt)); } svn_error_t * -svn_wc__db_resolve_break_moved_away_children(svn_wc__db_t *db, - const char *local_abspath, - const char *src_op_root_abspath, - svn_wc_notify_func2_t notify_func, - void *notify_baton, - apr_pool_t *scratch_pool) +svn_wc__db_op_break_moved_away(svn_wc__db_t *db, + const char *local_abspath, + const char *del_op_root_abspath, + svn_boolean_t mark_tc_resolved, + 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; + const char *del_relpath; + int src_op_depth; 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(wcroot, db, local_relpath, scratch_pool), + if (del_op_root_abspath) + del_relpath = svn_dirent_skip_ancestor(wcroot->abspath, + del_op_root_abspath); + else + del_relpath = NULL; + + + SVN_WC__DB_WITH_TXN4( + find_src_op_depth(&src_op_depth, wcroot, local_relpath, + del_relpath ? relpath_depth(del_relpath) + : relpath_depth(local_relpath), + scratch_pool), + break_moved_away(wcroot, db, local_relpath, src_op_depth, + scratch_pool), + mark_tc_resolved + ? svn_wc__db_op_mark_resolved_internal(wcroot, local_relpath, db, + FALSE, FALSE, TRUE, + NULL, scratch_pool) + : SVN_NO_ERROR, + SVN_NO_ERROR, wcroot); SVN_ERR(svn_wc__db_update_move_list_notify(wcroot, Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db_util.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db_util.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db_util.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db_util.c Sun Jun 14 20:58:10 2015 @@ -83,7 +83,7 @@ static svn_error_t * relpath_depth_sqlite(svn_sqlite__context_t *sctx, int argc, svn_sqlite__value_t *values[], - apr_pool_t *scratch_pool) + void *baton) { const char *path = NULL; apr_int64_t depth; @@ -152,63 +152,3 @@ svn_wc__db_util_open_db(svn_sqlite__db_t return SVN_NO_ERROR; } - -/* Some helpful transaction helpers. - - Instead of directly using SQLite transactions, these wrappers - relieve the consumer from the need to wrap the wcroot and - local_relpath, which are almost always used within the transaction. - - This also means if we later want to implement some wc_db-specific txn - handling, we have a convenient place to do it. - */ - -/* A callback which supplies WCROOTs and LOCAL_RELPATHs. */ -typedef svn_error_t *(*db_txn_callback_t)(void *baton, - svn_wc__db_wcroot_t *wcroot, - const char *local_relpath, - apr_pool_t *scratch_pool); - -/* Baton for use with run_txn() and with_db_txn(). */ -struct txn_baton_t -{ - svn_wc__db_wcroot_t *wcroot; - const char *local_relpath; - - db_txn_callback_t cb_func; - void *cb_baton; -}; - - -/* Unwrap the sqlite transaction into a wc_db txn. - Implements svn_sqlite__transaction_callback_t. */ -static svn_error_t * -run_txn(void *baton, svn_sqlite__db_t *db, apr_pool_t *scratch_pool) -{ - struct txn_baton_t *tb = baton; - - return svn_error_trace( - tb->cb_func(tb->cb_baton, tb->wcroot, tb->local_relpath, scratch_pool)); -} - - -/* Run CB_FUNC in a SQLite transaction with CB_BATON, using WCROOT and - LOCAL_RELPATH. If callbacks require additional information, they may - provide it using CB_BATON. */ -svn_error_t * -svn_wc__db_with_txn(svn_wc__db_wcroot_t *wcroot, - const char *local_relpath, - svn_wc__db_txn_callback_t cb_func, - void *cb_baton, - apr_pool_t *scratch_pool) -{ - struct txn_baton_t tb; - - tb.wcroot = wcroot; - tb.local_relpath = local_relpath; - tb.cb_func = cb_func; - tb.cb_baton = cb_baton; - - return svn_error_trace( - svn_sqlite__with_lock(wcroot->sdb, run_txn, &tb, scratch_pool)); -} Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db_wcroot.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db_wcroot.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db_wcroot.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_wc/wc_db_wcroot.c Sun Jun 14 20:58:10 2015 @@ -28,6 +28,7 @@ #include "svn_dirent_uri.h" #include "svn_hash.h" #include "svn_path.h" +#include "svn_pools.h" #include "svn_version.h" #include "wc.h" @@ -42,7 +43,7 @@ #define UNKNOWN_WC_ID ((apr_int64_t) -1) #define FORMAT_FROM_SDB (-1) - +/* #define VERIFY_ON_CLOSE */ /* Get the format version from a wc-1 directory. If it is not a working copy directory, then it sets VERSION to zero and returns no error. */ @@ -162,6 +163,27 @@ svn_wc__db_verify_no_work(svn_sqlite__db return SVN_NO_ERROR; } +#if defined(VERIFY_ON_CLOSE) && defined(SVN_DEBUG) +/* Implements svn_wc__db_verify_cb_t */ +static svn_error_t * +verify_db_cb(void *baton, + const char *wc_abspath, + const char *local_relpath, + int op_depth, + int id, + const char *msg, + apr_pool_t *scratch_pool) +{ + if (op_depth >= 0) + SVN_DBG(("DB-VRFY: %s: %s (%d): SV%04d %s", + wc_abspath, local_relpath, op_depth, id, msg)); + else + SVN_DBG(("DB-VRFY: %s: %s: SV%04d %s", + wc_abspath, local_relpath, id, msg)); + + return SVN_NO_ERROR; +} +#endif /* */ static apr_status_t @@ -172,6 +194,18 @@ close_wcroot(void *data) SVN_ERR_ASSERT_NO_RETURN(wcroot->sdb != NULL); +#if defined(VERIFY_ON_CLOSE) && defined(SVN_DEBUG) + if (getenv("SVN_CMDLINE_VERIFY_SQL_AT_CLOSE")) + { + apr_pool_t *scratch_pool = svn_pool_create(NULL); + + svn_error_clear(svn_wc__db_verify_db_full_internal( + wcroot, verify_db_cb, NULL, scratch_pool)); + + svn_pool_destroy(scratch_pool); + } +#endif + err = svn_sqlite__close(wcroot->sdb); wcroot->sdb = NULL; if (err) @@ -270,7 +304,7 @@ svn_wc__db_pdh_create_wcroot(svn_wc__db_ apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - if (sdb != NULL) + if (sdb && format == FORMAT_FROM_SDB) SVN_ERR(svn_sqlite__read_schema_version(&format, sdb, scratch_pool)); /* If we construct a wcroot, then we better have a format. */ @@ -422,6 +456,56 @@ read_link_target(const char **link_targe return SVN_NO_ERROR; } +/* Verify if the sqlite_stat1 table exists and if not tries to add + this table (but ignores errors on adding the schema) */ +static svn_error_t * +verify_stats_table(svn_sqlite__db_t *sdb, + int format, + apr_pool_t *scratch_pool) +{ + svn_sqlite__stmt_t *stmt; + svn_boolean_t have_row; + + if (format != SVN_WC__ENSURE_STAT1_TABLE) + return SVN_NO_ERROR; + + SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, + STMT_HAVE_STAT1_TABLE)); + SVN_ERR(svn_sqlite__step(&have_row, stmt)); + SVN_ERR(svn_sqlite__reset(stmt)); + + if (!have_row) + { + svn_error_clear( + svn_wc__db_install_schema_statistics(sdb, scratch_pool)); + } + + return SVN_NO_ERROR; +} + +/* Sqlite transaction helper for opening the db in + svn_wc__db_wcroot_parse_local_abspath() to avoid multiple + db operations that each obtain and release a lock */ +static svn_error_t * +fetch_sdb_info(apr_int64_t *wc_id, + int *format, + svn_sqlite__db_t *sdb, + apr_pool_t *scratch_pool) +{ + *wc_id = -1; + *format = -1; + + SVN_SQLITE__WITH_LOCK4( + svn_wc__db_util_fetch_wc_id(wc_id, sdb, scratch_pool), + svn_sqlite__read_schema_version(format, sdb, scratch_pool), + verify_stats_table(sdb, *format, scratch_pool), + SVN_NO_ERROR, + sdb); + + return SVN_NO_ERROR; +} + + svn_error_t * svn_wc__db_wcroot_parse_local_abspath(svn_wc__db_wcroot_t **wcroot, const char **local_relpath, @@ -662,17 +746,16 @@ try_symlink_as_dir: /* We finally found the database. Construct a wcroot_t for it. */ apr_int64_t wc_id; + int format; svn_error_t *err; - err = svn_wc__db_util_fetch_wc_id(&wc_id, sdb, scratch_pool); + err = fetch_sdb_info(&wc_id, &format, sdb, scratch_pool); if (err) { if (err->apr_err == SVN_ERR_WC_CORRUPT) - return svn_error_quick_wrap( - err, apr_psprintf(scratch_pool, - _("Missing a row in WCROOT for '%s'."), - svn_dirent_local_style(original_abspath, - scratch_pool))); + return svn_error_quick_wrapf( + err, _("Missing a row in WCROOT for '%s'."), + svn_dirent_local_style(original_abspath, scratch_pool)); return svn_error_trace(err); } @@ -685,7 +768,7 @@ try_symlink_as_dir: symlink_wcroot_abspath ? symlink_wcroot_abspath : local_abspath), - sdb, wc_id, FORMAT_FROM_SDB, + sdb, wc_id, format, db->verify_format, db->state_pool, scratch_pool); if (err && (err->apr_err == SVN_ERR_WC_UNSUPPORTED_FORMAT || Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/workqueue.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/workqueue.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_wc/workqueue.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_wc/workqueue.c Sun Jun 14 20:58:10 2015 @@ -143,8 +143,7 @@ run_base_remove(work_item_baton_t *wqb, SVN_ERR(svn_wc__db_base_remove(db, local_abspath, FALSE /* keep_as_working */, - TRUE /* queue_deletes */, - FALSE /* remove_locks */, + SVN_IS_VALID_REVNUM(not_present_rev), FALSE, not_present_rev, NULL, NULL, scratch_pool)); @@ -1107,7 +1106,7 @@ run_prej_install(work_item_baton_t *wqb, SVN_ERR(svn_wc__db_from_relpath(&local_abspath, db, wri_abspath, local_relpath, scratch_pool, scratch_pool)); - SVN_ERR(svn_wc__db_read_conflict(&conflicts, db, local_abspath, + SVN_ERR(svn_wc__db_read_conflict(&conflicts, NULL, NULL, db, local_abspath, scratch_pool, scratch_pool)); SVN_ERR(svn_wc__conflict_read_prop_conflict(&prejfile_abspath, @@ -1287,7 +1286,7 @@ run_set_text_conflict_markers(work_item_ /* Check if we should combine with a property conflict... */ svn_skel_t *conflicts; - SVN_ERR(svn_wc__db_read_conflict(&conflicts, db, local_abspath, + SVN_ERR(svn_wc__db_read_conflict(&conflicts, NULL, NULL, db, local_abspath, scratch_pool, scratch_pool)); if (! conflicts) @@ -1353,7 +1352,8 @@ run_set_property_conflict_marker(work_it svn_skel_t *conflicts; apr_hash_t *prop_names; - SVN_ERR(svn_wc__db_read_conflict(&conflicts, db, local_abspath, + SVN_ERR(svn_wc__db_read_conflict(&conflicts, NULL, NULL, + db, local_abspath, scratch_pool, scratch_pool)); if (! conflicts) Modified: subversion/branches/fsx-1.10/subversion/mod_dav_svn/deadprops.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/mod_dav_svn/deadprops.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/mod_dav_svn/deadprops.c (original) +++ subversion/branches/fsx-1.10/subversion/mod_dav_svn/deadprops.c Sun Jun 14 20:58:10 2015 @@ -163,6 +163,23 @@ get_value(dav_db *db, const dav_prop_nam } +static svn_error_t * +change_txn_prop(svn_fs_txn_t *txn, + const char *propname, + const svn_string_t *value, + apr_pool_t *scratch_pool) +{ + if (strcmp(propname, SVN_PROP_REVISION_AUTHOR) == 0) + return svn_error_create(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL, + "Attempted to modify 'svn:author' property " + "on a transaction"); + + SVN_ERR(svn_repos_fs_change_txn_prop(txn, propname, value, scratch_pool)); + + return SVN_NO_ERROR; +} + + static dav_error * save_value(dav_db *db, const dav_prop_name *name, const svn_string_t *const *old_value_p, @@ -213,9 +230,8 @@ save_value(dav_db *db, const dav_prop_na { if (resource->working) { - serr = svn_repos_fs_change_txn_prop(resource->info->root.txn, - propname, value, - subpool); + serr = change_txn_prop(resource->info->root.txn, propname, + value, subpool); } else { @@ -254,8 +270,8 @@ save_value(dav_db *db, const dav_prop_na } else if (resource->info->restype == DAV_SVN_RESTYPE_TXN_COLLECTION) { - serr = svn_repos_fs_change_txn_prop(resource->info->root.txn, - propname, value, subpool); + serr = change_txn_prop(resource->info->root.txn, propname, + value, subpool); } else { @@ -560,8 +576,8 @@ db_remove(dav_db *db, const dav_prop_nam /* Working Baseline or Working (Version) Resource */ if (db->resource->baselined) if (db->resource->working) - serr = svn_repos_fs_change_txn_prop(db->resource->info->root.txn, - propname, NULL, subpool); + serr = change_txn_prop(db->resource->info->root.txn, propname, + NULL, subpool); else /* ### VIOLATING deltaV: you can't proppatch a baseline, it's not a working resource! But this is how we currently Modified: subversion/branches/fsx-1.10/subversion/mod_dav_svn/liveprops.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/mod_dav_svn/liveprops.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/mod_dav_svn/liveprops.c (original) +++ subversion/branches/fsx-1.10/subversion/mod_dav_svn/liveprops.c Sun Jun 14 20:58:10 2015 @@ -239,7 +239,7 @@ get_last_modified_time(const char **date } if (timeval) - memcpy(timeval, &timeval_tmp, sizeof(*timeval)); + *timeval = timeval_tmp; if (! datestring) return 0; @@ -787,20 +787,30 @@ insert_prop_internal(const dav_resource case SVN_PROPID_deadprop_count: { - unsigned int propcount; - apr_hash_t *proplist; + svn_boolean_t has_props; if (resource->type != DAV_RESOURCE_TYPE_REGULAR) return DAV_PROP_INSERT_NOTSUPP; - serr = svn_fs_node_proplist(&proplist, - resource->info->root.root, - resource->info->repos_path, scratch_pool); + /* Retrieving the actual properties is quite expensive while + svn clients only want to know if there are properties, by + using this svn defined property. + + Our and and SvnKit's implementation of the ra layer check + for '> 0' to provide the boolean if the node has custom + properties or not, so starting with 1.9 we just provide + "1" or "0". + */ + serr = svn_fs_node_has_props(&has_props, + resource->info->root.root, + resource->info->repos_path, + scratch_pool); + if (serr != NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, serr->apr_err, resource->info->r, - "Can't fetch proplist of '%s': " + "Can't fetch has properties on '%s': " "%s", resource->info->repos_path, serr->message); @@ -809,8 +819,7 @@ insert_prop_internal(const dav_resource break; } - propcount = apr_hash_count(proplist); - value = apr_psprintf(scratch_pool, "%u", propcount); + value = has_props ? "1" : "0"; break; } Modified: subversion/branches/fsx-1.10/subversion/mod_dav_svn/lock.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/mod_dav_svn/lock.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/mod_dav_svn/lock.c (original) +++ subversion/branches/fsx-1.10/subversion/mod_dav_svn/lock.c Sun Jun 14 20:58:10 2015 @@ -805,7 +805,7 @@ append_locks(dav_lockdb *lockdb, to return the lock details? Add yet another custom header? - Just an header doesn't handle a full error chain... + Just an header doesn't handle a full error chain... ### Current behavior: we don't report an error. */
