svn_error_t * svn_wc__adm_destroy(svn_wc__db_t *db, const char *dir_abspath, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *scratch_pool) { const char *adm_abspath; SVN_ERR_ASSERT(svn_dirent_is_absolute(dir_abspath)); SVN_ERR(svn_wc__write_check(db, dir_abspath, scratch_pool)); SVN_ERR(svn_wc__db_get_wcroot(&adm_abspath, db, dir_abspath, scratch_pool, scratch_pool)); /* Well, the coast is clear for blowing away the administrative directory, which also removes remaining locks */ /* Now close the DB, and we can delete the working copy */ if (strcmp(adm_abspath, dir_abspath) == 0) { SVN_ERR(svn_wc__db_drop_root(db, adm_abspath, scratch_pool)); SVN_ERR(svn_io_remove_dir2(svn_wc__adm_child(adm_abspath, NULL, scratch_pool), FALSE, cancel_func, cancel_baton, scratch_pool)); } return SVN_NO_ERROR; }
svn_error_t * svn_wc__adm_cleanup_tmp_area(svn_wc__db_t *db, const char *adm_abspath, apr_pool_t *scratch_pool) { const char *tmp_path; SVN_ERR_ASSERT(svn_dirent_is_absolute(adm_abspath)); SVN_ERR(svn_wc__write_check(db, adm_abspath, scratch_pool)); /* Get the path to the tmp area, and blow it away. */ tmp_path = svn_wc__adm_child(adm_abspath, SVN_WC__ADM_TMP, scratch_pool); SVN_ERR(svn_io_remove_dir2(tmp_path, TRUE, NULL, NULL, scratch_pool)); /* Now, rebuild the tmp area. */ return svn_error_trace(init_adm_tmp_area(adm_abspath, scratch_pool)); }
svn_error_t * svn_wc_copy3(svn_wc_context_t *wc_ctx, const char *src_abspath, const char *dst_abspath, svn_boolean_t metadata_only, svn_cancel_func_t cancel_func, void *cancel_baton, svn_wc_notify_func2_t notify_func, void *notify_baton, apr_pool_t *scratch_pool) { /* Verify that we have the required write lock. */ SVN_ERR(svn_wc__write_check(wc_ctx->db, svn_dirent_dirname(dst_abspath, scratch_pool), scratch_pool)); return svn_error_trace(copy_or_move(NULL, wc_ctx, src_abspath, dst_abspath, metadata_only, FALSE /* is_move */, TRUE /* allow_mixed_revisions */, cancel_func, cancel_baton, notify_func, notify_baton, scratch_pool)); }
svn_error_t * svn_wc__delete_many(svn_wc_context_t *wc_ctx, const apr_array_header_t *targets, svn_boolean_t keep_local, svn_boolean_t delete_unversioned_target, svn_cancel_func_t cancel_func, void *cancel_baton, svn_wc_notify_func2_t notify_func, void *notify_baton, apr_pool_t *scratch_pool) { svn_wc__db_t *db = wc_ctx->db; svn_error_t *err; svn_wc__db_status_t status; svn_node_kind_t kind; svn_skel_t *work_items = NULL; apr_array_header_t *versioned_targets; const char *local_abspath; int i; apr_pool_t *iterpool; iterpool = svn_pool_create(scratch_pool); versioned_targets = apr_array_make(scratch_pool, targets->nelts, sizeof(const char *)); for (i = 0; i < targets->nelts; i++) { svn_boolean_t conflicted = FALSE; const char *repos_relpath; svn_pool_clear(iterpool); local_abspath = APR_ARRAY_IDX(targets, i, const char *); err = svn_wc__db_read_info(&status, &kind, NULL, &repos_relpath, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &conflicted, NULL, NULL, NULL, NULL, NULL, NULL, db, local_abspath, iterpool, iterpool); if (err) { if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) { svn_error_clear(err); if (delete_unversioned_target && !keep_local) SVN_ERR(erase_unversioned_from_wc(local_abspath, FALSE, cancel_func, cancel_baton, iterpool)); continue; } else return svn_error_trace(err); } APR_ARRAY_PUSH(versioned_targets, const char *) = local_abspath; switch (status) { /* svn_wc__db_status_server_excluded handled by * svn_wc__db_op_delete_many */ case svn_wc__db_status_excluded: case svn_wc__db_status_not_present: return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL, _("'%s' cannot be deleted"), svn_dirent_local_style(local_abspath, iterpool)); /* Explicitly ignore other statii */ default: break; } if (status == svn_wc__db_status_normal && kind == svn_node_dir) { svn_boolean_t is_wcroot; SVN_ERR(svn_wc__db_is_wcroot(&is_wcroot, db, local_abspath, iterpool)); if (is_wcroot) return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL, _("'%s' is the root of a working copy and " "cannot be deleted"), svn_dirent_local_style(local_abspath, iterpool)); } if (repos_relpath && !repos_relpath[0]) return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL, _("'%s' represents the repository root " "and cannot be deleted"), svn_dirent_local_style(local_abspath, iterpool)); /* Verify if we have a write lock on the parent of this node as we might be changing the childlist of that directory. */ SVN_ERR(svn_wc__write_check(db, svn_dirent_dirname(local_abspath, iterpool), iterpool)); /* Prepare the on-disk delete */ if (!keep_local) { svn_skel_t *work_item; SVN_ERR(create_delete_wq_items(&work_item, db, local_abspath, kind, conflicted, scratch_pool, iterpool)); work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool); } } if (versioned_targets->nelts == 0) return SVN_NO_ERROR; SVN_ERR(svn_wc__db_op_delete_many(db, versioned_targets, !keep_local /* delete_dir_externals */, work_items, cancel_func, cancel_baton, notify_func, notify_baton, iterpool)); if (work_items != NULL) { /* Our only caller locked the wc, so for now assume it only passed nodes from a single wc (asserted in svn_wc__db_op_delete_many) */ local_abspath = APR_ARRAY_IDX(versioned_targets, 0, const char *); SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton, iterpool)); }
svn_error_t * svn_wc__move2(svn_wc_context_t *wc_ctx, const char *src_abspath, const char *dst_abspath, svn_boolean_t metadata_only, svn_boolean_t allow_mixed_revisions, svn_cancel_func_t cancel_func, void *cancel_baton, svn_wc_notify_func2_t notify_func, void *notify_baton, apr_pool_t *scratch_pool) { svn_wc__db_t *db = wc_ctx->db; svn_boolean_t move_degraded_to_copy = FALSE; svn_node_kind_t kind; svn_boolean_t conflicted; /* Verify that we have the required write locks. */ SVN_ERR(svn_wc__write_check(wc_ctx->db, svn_dirent_dirname(src_abspath, scratch_pool), scratch_pool)); SVN_ERR(svn_wc__write_check(wc_ctx->db, svn_dirent_dirname(dst_abspath, scratch_pool), scratch_pool)); SVN_ERR(copy_or_move(&move_degraded_to_copy, wc_ctx, src_abspath, dst_abspath, TRUE /* metadata_only */, TRUE /* is_move */, allow_mixed_revisions, cancel_func, cancel_baton, notify_func, notify_baton, scratch_pool)); /* An interrupt at this point will leave the new copy marked as moved-here but the source has not yet been deleted or marked as moved-to. */ /* Should we be using a workqueue for this move? It's not clear. What should happen if the copy above is interrupted? The user may want to abort the move and a workqueue might interfere with that. BH: On Windows it is not unlikely to encounter an access denied on this line. Installing the move in the workqueue via the copy_or_move might make it hard to recover from that situation, while the DB is still in a valid state. So be careful when switching this over to the workqueue. */ if (!metadata_only) SVN_ERR(svn_io_file_rename(src_abspath, dst_abspath, scratch_pool)); SVN_ERR(svn_wc__db_read_info(NULL, &kind, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &conflicted, NULL, NULL, NULL, NULL, NULL, NULL, db, src_abspath, scratch_pool, scratch_pool)); if (kind == svn_node_dir) SVN_ERR(remove_all_conflict_markers(db, src_abspath, dst_abspath, scratch_pool)); if (conflicted) SVN_ERR(remove_node_conflict_markers(db, src_abspath, dst_abspath, scratch_pool)); SVN_ERR(svn_wc__db_op_delete(db, src_abspath, move_degraded_to_copy ? NULL : dst_abspath, TRUE /* delete_dir_externals */, NULL /* conflict */, NULL /* work_items */, cancel_func, cancel_baton, notify_func, notify_baton, scratch_pool)); return SVN_NO_ERROR; }