Modified: subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c (original) +++ subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c Tue Dec 13 09:49:29 2022 @@ -154,6 +154,7 @@ #include "conflicts.h" #include "workqueue.h" #include "token-map.h" +#include "textbase.h" /* Helper functions */ /* Return the absolute path, in local path style, of LOCAL_RELPATH @@ -970,15 +971,28 @@ tc_editor_add_file(node_move_baton_t *nm } else { + const char *src_abspath; + const char *install_from; + svn_skel_t *cleanup_work_item; + + src_abspath = svn_dirent_join(b->wcroot->abspath, nmb->src_relpath, + scratch_pool); + /* Update working file. */ + SVN_ERR(svn_wc__textbase_setaside_wq(&install_from, + &cleanup_work_item, + b->db, src_abspath, NULL, + b->cancel_func, b->cancel_baton, + scratch_pool, scratch_pool)); SVN_ERR(svn_wc__wq_build_file_install(&work_item, b->db, svn_dirent_join(b->wcroot->abspath, relpath, scratch_pool), - NULL, + install_from, FALSE /*FIXME: use_commit_times?*/, TRUE /* record_file_info */, scratch_pool, scratch_pool)); + work_item = svn_wc__wq_merge(work_item, cleanup_work_item, scratch_pool); } SVN_ERR(update_move_list_add(b->wcroot, relpath, b->db, @@ -1369,33 +1383,56 @@ tc_editor_alter_file(node_move_baton_t * scratch_pool)); if (!is_locally_modified) { + const char *src_abspath; + const char *install_from; + svn_skel_t *cleanup_work_item; + + src_abspath = svn_dirent_join(b->wcroot->abspath, nmb->src_relpath, + scratch_pool); + + SVN_ERR(svn_wc__textbase_setaside_wq(&install_from, + &cleanup_work_item, + b->db, src_abspath, NULL, + b->cancel_func, b->cancel_baton, + scratch_pool, scratch_pool)); SVN_ERR(svn_wc__wq_build_file_install(&work_item, b->db, local_abspath, - NULL, + install_from, FALSE /* FIXME: use_commit_times? */, TRUE /* record_file_info */, scratch_pool, scratch_pool)); work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool); + work_items = svn_wc__wq_merge(work_items, cleanup_work_item, scratch_pool); content_state = svn_wc_notify_state_changed; } else { + svn_skel_t *cleanup_queue = NULL; + /* * Run a 3-way merge to update the file, using the pre-update * pristine text as the merge base, the post-update pristine * text as the merge-left version, and the current content of the * moved-here working file as the merge-right version. */ - SVN_ERR(svn_wc__db_pristine_get_path(&old_pristine_abspath, - b->db, b->wcroot->abspath, + SVN_ERR(svn_wc__textbase_setaside_wq(&old_pristine_abspath, + &work_item, b->db, + local_abspath, old_version.checksum, + b->cancel_func, b->cancel_baton, scratch_pool, scratch_pool)); - SVN_ERR(svn_wc__db_pristine_get_path(&new_pristine_abspath, - b->db, b->wcroot->abspath, + cleanup_queue = svn_wc__wq_merge(cleanup_queue, work_item, scratch_pool); + + SVN_ERR(svn_wc__textbase_setaside_wq(&new_pristine_abspath, + &work_item, b->db, + local_abspath, new_version.checksum, + b->cancel_func, b->cancel_baton, scratch_pool, scratch_pool)); + cleanup_queue = svn_wc__wq_merge(cleanup_queue, work_item, scratch_pool); + SVN_ERR(svn_wc__internal_merge(&work_item, &conflict_skel, &merge_outcome, b->db, old_pristine_abspath, @@ -1412,6 +1449,7 @@ tc_editor_alter_file(node_move_baton_t * scratch_pool, scratch_pool)); work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool); + work_items = svn_wc__wq_merge(work_items, cleanup_queue, scratch_pool); if (merge_outcome == svn_wc_merge_conflict) content_state = svn_wc_notify_state_conflicted; @@ -1599,6 +1637,7 @@ tc_editor_update_incoming_moved_file(nod const char *src_abspath; const char *label_left; const char *label_target; + svn_skel_t *cleanup_queue = NULL; /* * Run a 3-way merge to update the file at its post-move location, @@ -1607,12 +1646,17 @@ tc_editor_update_incoming_moved_file(nod * content of the working file at the pre-move location as the * merge-left version. */ - SVN_ERR(svn_wc__db_pristine_get_path(&old_pristine_abspath, - b->db, b->wcroot->abspath, - src_checksum, - scratch_pool, scratch_pool)); src_abspath = svn_dirent_join(b->wcroot->abspath, src_relpath, scratch_pool); + + SVN_ERR(svn_wc__textbase_setaside_wq(&old_pristine_abspath, + &work_item, b->db, + src_abspath, + src_checksum, + b->cancel_func, b->cancel_baton, + scratch_pool, scratch_pool)); + cleanup_queue = svn_wc__wq_merge(cleanup_queue, work_item, scratch_pool); + label_left = apr_psprintf(scratch_pool, ".r%ld", b->old_version->peg_rev); label_target = apr_psprintf(scratch_pool, ".r%ld", @@ -1635,6 +1679,7 @@ tc_editor_update_incoming_moved_file(nod scratch_pool, scratch_pool)); work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool); + work_items = svn_wc__wq_merge(work_items, cleanup_queue, scratch_pool); if (merge_outcome == svn_wc_merge_conflict) content_state = svn_wc_notify_state_conflicted; @@ -3147,14 +3192,22 @@ tc_editor_update_add_merge_files(added_n if (!is_modified) { svn_skel_t *work_item = NULL; + const char *install_from; + svn_skel_t *cleanup_work_item; + SVN_ERR(svn_wc__textbase_setaside_wq(&install_from, + &cleanup_work_item, + b->db, local_abspath, NULL, + b->cancel_func, b->cancel_baton, + scratch_pool, scratch_pool)); SVN_ERR(svn_wc__wq_build_file_install(&work_item, b->db, - local_abspath, NULL, + local_abspath, install_from, /* FIXME: use_commit_times? */ FALSE, TRUE, /* record_file_info */ scratch_pool, scratch_pool)); work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool); + work_items = svn_wc__wq_merge(work_items, cleanup_work_item, scratch_pool); content_state = svn_wc_notify_state_changed; } else @@ -3162,6 +3215,7 @@ tc_editor_update_add_merge_files(added_n const char *empty_file_abspath; const char *pristine_abspath; svn_skel_t *work_item = NULL; + svn_skel_t *cleanup_queue = NULL; /* * Run a 3-way merge to update the file, using the empty file @@ -3172,9 +3226,13 @@ tc_editor_update_add_merge_files(added_n SVN_ERR(svn_io_open_unique_file3(NULL, &empty_file_abspath, NULL, svn_io_file_del_on_pool_cleanup, scratch_pool, scratch_pool)); - SVN_ERR(svn_wc__db_pristine_get_path(&pristine_abspath, b->db, - b->wcroot->abspath, base_checksum, + SVN_ERR(svn_wc__textbase_setaside_wq(&pristine_abspath, + &work_item, b->db, + local_abspath, + base_checksum, + b->cancel_func, b->cancel_baton, scratch_pool, scratch_pool)); + cleanup_queue = svn_wc__wq_merge(cleanup_queue, work_item, scratch_pool); /* Create a property diff which shows all props as added. */ SVN_ERR(svn_prop_diffs(&propchanges, working_props, @@ -3196,6 +3254,7 @@ tc_editor_update_add_merge_files(added_n scratch_pool, scratch_pool)); work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool); + work_items = svn_wc__wq_merge(work_items, cleanup_queue, scratch_pool); if (merge_outcome == svn_wc_merge_conflict) content_state = svn_wc_notify_state_conflicted; @@ -3373,12 +3432,23 @@ update_locally_added_node(added_node_bat * is currently not installed because the base tree is shadowed. * Queue an installation of this node into the working copy. */ if (base_kind == svn_node_file || base_kind == svn_node_symlink) - SVN_ERR(svn_wc__wq_build_file_install(&work_item, db, local_abspath, - NULL, - /* FIXME: use_commit_times? */ - FALSE, - TRUE, /* record_file_info */ - scratch_pool, scratch_pool)); + { + const char *install_from; + svn_skel_t *cleanup_work_item; + + SVN_ERR(svn_wc__textbase_setaside_wq(&install_from, + &cleanup_work_item, + db, local_abspath, NULL, + b->cancel_func, b->cancel_baton, + scratch_pool, scratch_pool)); + SVN_ERR(svn_wc__wq_build_file_install(&work_item, db, local_abspath, + install_from, + /* FIXME: use_commit_times? */ + FALSE, + TRUE, /* record_file_info */ + scratch_pool, scratch_pool)); + work_item = svn_wc__wq_merge(work_item, cleanup_work_item, scratch_pool); + } else if (base_kind == svn_node_dir) SVN_ERR(svn_wc__wq_build_dir_install(&work_item, db, local_abspath, scratch_pool, scratch_pool));
Modified: subversion/trunk/subversion/libsvn_wc/wc_db_wcroot.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db_wcroot.c?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_wc/wc_db_wcroot.c (original) +++ subversion/trunk/subversion/libsvn_wc/wc_db_wcroot.c Tue Dec 13 09:49:29 2022 @@ -301,6 +301,7 @@ svn_wc__db_pdh_create_wcroot(svn_wc__db_ apr_int64_t wc_id, int format, svn_boolean_t verify_format, + svn_boolean_t store_pristine, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { @@ -388,6 +389,7 @@ svn_wc__db_pdh_create_wcroot(svn_wc__db_ (*wcroot)->owned_locks = apr_array_make(result_pool, 8, sizeof(svn_wc__db_wclock_t)); (*wcroot)->access_cache = apr_hash_make(result_pool); + (*wcroot)->store_pristine = store_pristine; /* SDB will be NULL for pre-NG working copies. We only need to run a cleanup when the SDB is present. */ @@ -494,12 +496,45 @@ verify_stats_table(svn_sqlite__db_t *sdb return SVN_NO_ERROR; } +/* Read and return the settings for WC_ID in SDB. */ +static svn_error_t * +read_settings(svn_boolean_t *store_pristine_p, + svn_sqlite__db_t *sdb, + int format, + apr_int64_t wc_id, + apr_pool_t *scratch_pool) +{ + if (format >= SVN_WC__HAS_SETTINGS) + { + svn_sqlite__stmt_t *stmt; + svn_boolean_t have_row; + + SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_SETTINGS)); + SVN_ERR(svn_sqlite__bindf(stmt, "i", wc_id)); + SVN_ERR(svn_sqlite__step(&have_row, stmt)); + + if (have_row) + *store_pristine_p = svn_sqlite__column_boolean(stmt, 0); + else + *store_pristine_p = TRUE; + + SVN_ERR(svn_sqlite__reset(stmt)); + } + else + { + *store_pristine_p = TRUE; + } + + 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_boolean_t *store_pristine, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool) { @@ -510,7 +545,7 @@ fetch_sdb_info(apr_int64_t *wc_id, 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, + read_settings(store_pristine, sdb, *format, *wc_id, scratch_pool), sdb); return SVN_NO_ERROR; @@ -763,9 +798,10 @@ try_symlink_as_dir: apr_int64_t wc_id; int format; + svn_boolean_t store_pristine; svn_error_t *err; - err = fetch_sdb_info(&wc_id, &format, sdb, scratch_pool); + err = fetch_sdb_info(&wc_id, &format, &store_pristine, sdb, scratch_pool); if (err) { if (err->apr_err == SVN_ERR_WC_CORRUPT) @@ -786,6 +822,7 @@ try_symlink_as_dir: : local_abspath), sdb, wc_id, format, db->verify_format, + store_pristine, db->state_pool, scratch_pool); if (err && (err->apr_err == SVN_ERR_WC_UNSUPPORTED_FORMAT || err->apr_err == SVN_ERR_WC_UPGRADE_REQUIRED) && @@ -861,6 +898,7 @@ try_symlink_as_dir: : local_abspath), NULL, UNKNOWN_WC_ID, wc_format, db->verify_format, + TRUE, db->state_pool, scratch_pool)); } @@ -1031,10 +1069,11 @@ svn_wc__db_drop_root(svn_wc__db_t *db, svn_error_t * -svn_wc__format_from_context(int *format, - svn_wc_context_t *wc_ctx, - const char *local_abspath, - apr_pool_t *scratch_pool) +svn_wc__settings_from_context(int *format_p, + svn_boolean_t *store_pristine_p, + svn_wc_context_t *wc_ctx, + const char *local_abspath, + apr_pool_t *scratch_pool) { const char *current_path = local_abspath; @@ -1045,7 +1084,8 @@ svn_wc__format_from_context(int *format, wcroot = svn_hash_gets(wc_ctx->db->dir_data, current_path); if (wcroot) { - *format = wcroot->format; + *format_p = wcroot->format; + *store_pristine_p = wcroot->store_pristine; return SVN_NO_ERROR; } @@ -1053,6 +1093,7 @@ svn_wc__format_from_context(int *format, } while (!svn_dirent_is_root(current_path, strlen(current_path))); - *format = SVN_WC__DEFAULT_VERSION; + *format_p = SVN_WC__DEFAULT_VERSION; + *store_pristine_p = TRUE; return SVN_NO_ERROR; } Modified: subversion/trunk/subversion/svn/checkout-cmd.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/checkout-cmd.c?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/svn/checkout-cmd.c (original) +++ subversion/trunk/subversion/svn/checkout-cmd.c Tue Dec 13 09:49:29 2022 @@ -173,6 +173,7 @@ svn_cl__checkout(apr_getopt_t *os, opt_state->ignore_externals, opt_state->force, opt_state->compatible_version, + opt_state->store_pristine, ctx, subpool)); } svn_pool_destroy(subpool); Modified: subversion/trunk/subversion/svn/cl.h URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/cl.h?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/svn/cl.h (original) +++ subversion/trunk/subversion/svn/cl.h Tue Dec 13 09:49:29 2022 @@ -276,6 +276,7 @@ typedef struct svn_cl__opt_state_t svn_cl__viewspec_svn11 } viewspec; /* value of --x-viewspec */ svn_version_t *compatible_version; /* working copy compatibility version */ + svn_boolean_t store_pristine; } svn_cl__opt_state_t; /* Conflict stats for operations such as update and merge. */ @@ -376,6 +377,7 @@ typedef enum svn_cl__longopt_t { opt_drop, opt_viewspec, opt_compatible_version, + opt_store_pristine } svn_cl__longopt_t; /* Options for giving a log message. (Some of these also have other uses.) @@ -709,6 +711,11 @@ svn_cl__notifier_mark_export(void *baton svn_error_t * svn_cl__notifier_mark_wc_to_repos_copy(void *baton); +/* Make the notifier for use with BATON suppress progress notifications + */ +svn_error_t * +svn_cl__notifier_suppress_progress_output(void *baton); + /* Baton for use with svn_cl__check_externals_failed_notify_wrapper(). */ struct svn_cl__check_externals_failed_notify_baton { Modified: subversion/trunk/subversion/svn/info-cmd.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/info-cmd.c?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/svn/info-cmd.c (original) +++ subversion/trunk/subversion/svn/info-cmd.c Tue Dec 13 09:49:29 2022 @@ -371,7 +371,8 @@ typedef enum info_item_depth, info_item_changelist, info_item_wc_format, - info_item_wc_compatible_version + info_item_wc_compatible_version, + info_item_store_pristine, } info_item_t; /* Mapping between option keywords and info_item_t. */ @@ -401,6 +402,7 @@ static const info_item_map_t info_item_m { SVN__STATIC_STRING("wc-format"), info_item_wc_format }, { SVN__STATIC_STRING("wc-compatible-version"), info_item_wc_compatible_version }, + { SVN__STATIC_STRING("store-pristine"), info_item_store_pristine }, }; static const apr_size_t info_item_map_len = @@ -607,6 +609,10 @@ print_info_xml(void *baton, info->wc_info->wc_format)); } + /* "<store-pristine> xx </store-pristine>" */ + svn_cl__xml_tagged_cdata(&sb, pool, "store-pristine", + info->wc_info->store_pristine ? "yes" : "no"); + /* "<schedule> xx </schedule>" */ svn_cl__xml_tagged_cdata(&sb, pool, "schedule", schedule_str(info->wc_info->schedule)); @@ -763,6 +769,15 @@ print_info(void *baton, info->wc_info->wc_format)); } + if (info->wc_info) + { + if (info->wc_info->store_pristine) + SVN_ERR(svn_cmdline_fputs(_("Working Copy Store Pristine: yes\n"), + stdout, pool)); + else + SVN_ERR(svn_cmdline_fputs(_("Working Copy Store Pristine: no\n"), + stdout, pool)); + } if (info->URL) SVN_ERR(svn_cmdline_printf(pool, _("URL: %s\n"), info->URL)); @@ -1296,6 +1311,19 @@ print_info_item(void *baton, target_path, pool)); break; + case info_item_store_pristine: + { + const char *text; + + if (info->wc_info) + text = info->wc_info->store_pristine ? "yes" : "no"; + else + text = NULL; + + SVN_ERR(print_info_item_string(text, target_path, pool)); + } + break; + default: SVN_ERR_MALFUNCTION(); } Modified: subversion/trunk/subversion/svn/notify.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/notify.c?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/svn/notify.c (original) +++ subversion/trunk/subversion/svn/notify.c Tue Dec 13 09:49:29 2022 @@ -53,8 +53,10 @@ struct notify_baton svn_boolean_t is_export; svn_boolean_t is_wc_to_repos_copy; svn_boolean_t sent_first_txdelta; + svn_boolean_t hydrating_printed_start; int in_external; svn_revnum_t progress_revision; + svn_boolean_t progress_output; svn_boolean_t had_print_error; /* Used to not keep printing error messages when we've already had one print error. */ svn_boolean_t wc_was_upgraded; @@ -1207,6 +1209,29 @@ notify_body(struct notify_baton *nb, SVN_ERR(svn_cmdline_printf(pool, _("Committing transaction...\n"))); break; + case svn_wc_notify_hydrating_start: + nb->hydrating_printed_start = FALSE; + break; + + case svn_wc_notify_hydrating_file: + if (!nb->hydrating_printed_start) + { + if (nb->progress_output) + SVN_ERR(svn_cmdline_printf(pool, _("Fetching text bases "))); + nb->hydrating_printed_start = TRUE; + } + if (nb->progress_output) + SVN_ERR(svn_cmdline_printf(pool, ".")); + break; + + case svn_wc_notify_hydrating_end: + if (nb->hydrating_printed_start) + { + if (nb->progress_output) + SVN_ERR(svn_cmdline_printf(pool, _("done\n"))); + } + break; + case svn_wc_notify_warning: /* using handle_error rather than handle_warning in order to show the * whole error chain; the latter only shows one error in the chain */ @@ -1261,11 +1286,13 @@ svn_cl__get_notifier(svn_wc_notify_func2 nb->received_some_change = FALSE; nb->sent_first_txdelta = FALSE; + nb->hydrating_printed_start = FALSE; nb->is_checkout = FALSE; nb->is_export = FALSE; nb->is_wc_to_repos_copy = FALSE; nb->in_external = 0; nb->progress_revision = 0; + nb->progress_output = TRUE; nb->had_print_error = FALSE; nb->conflict_stats = conflict_stats; SVN_ERR(svn_dirent_get_absolute(&nb->path_prefix, "", pool)); @@ -1302,6 +1329,15 @@ svn_cl__notifier_mark_wc_to_repos_copy(v return SVN_NO_ERROR; } +svn_error_t * +svn_cl__notifier_suppress_progress_output(void *baton) +{ + struct notify_baton *nb = baton; + + nb->progress_output = FALSE; + return SVN_NO_ERROR; +} + void svn_cl__check_externals_failed_notify_wrapper(void *baton, const svn_wc_notify_t *n, Modified: subversion/trunk/subversion/svn/schema/info.rnc URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/schema/info.rnc?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/svn/schema/info.rnc (original) +++ subversion/trunk/subversion/svn/schema/info.rnc Tue Dec 13 09:49:29 2022 @@ -59,6 +59,7 @@ wc-info = wcroot-abspath?, wc-compatible-version?, wc-format?, + store-pristine?, schedule?, changelist?, copy-from-url?, @@ -74,6 +75,7 @@ wc-info = wcroot-abspath = element wcroot-abspath { string } wc-compatible-version = element wc-compatible-version { string } wc-format = element wc-format { xsd:nonNegativeInteger } +store-pristine = element store-pristine { "yes" | "no" } schedule = element schedule { "normal" | "add" | "delete" | "replace" | "none" } Modified: subversion/trunk/subversion/svn/svn.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/svn.c?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/svn/svn.c (original) +++ subversion/trunk/subversion/svn/svn.c Tue Dec 13 09:49:29 2022 @@ -371,6 +371,17 @@ const apr_getopt_option_t svn_cl__option " " "version ARG (\"1.8\", \"1.9.5\", etc.)")}, + {"store-pristine", opt_store_pristine, 1, + N_("Configure the working copy to either store local\n" + " " + "copies of pristine contents ('yes') or to fetch\n" + " " + "them on demand ('no'). Fetching on demand saves\n" + " " + "disk space, but may require network access for\n" + " " + "commands such as diff or revert. Default: 'yes'.")}, + /* Long-opt Aliases * * These have NULL descriptions, but an option code that matches some @@ -543,7 +554,7 @@ svn_cl__cmd_table_main[] = " reporting the action taken.\n" )}, {'r', 'q', 'N', opt_depth, opt_force, opt_ignore_externals, - opt_compatible_version}, + opt_compatible_version, opt_store_pristine}, {{'N', N_("obsolete; same as --depth=files")}} }, { "cleanup", svn_cl__cleanup, {0}, {N_( @@ -800,7 +811,11 @@ svn_cl__cmd_table_main[] = " " " first version supporting TARGET WC\n" " " - " 'changelist' changelist of TARGET in WC")}}, + " 'changelist' changelist of TARGET in WC\n" + " " + " 'store-pristine'\n" + " " + " TARGET's working copy pristine mode")}}, }, { "list", svn_cl__list, {"ls"}, @@ -2178,6 +2193,7 @@ sub_main(int *exit_code, int argc, const opt_state.accept_which = svn_cl__accept_unspecified; opt_state.show_revs = svn_cl__show_revs_invalid; opt_state.file_size_unit = SVN_CL__SIZE_UNIT_NONE; + opt_state.store_pristine = svn_tristate_unknown; /* No args? Show usage. */ if (argc <= 1) @@ -2734,6 +2750,15 @@ sub_main(int *exit_code, int argc, const case opt_compatible_version: SVN_ERR(parse_compatible_version(&opt_state, opt_arg, pool)); break; + case opt_store_pristine: + SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool)); + opt_state.store_pristine = svn_tristate__from_word(utf8_opt_arg); + if (opt_state.store_pristine == svn_tristate_unknown) + return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("Unknown value '%s' for %s.\n" + "Supported values: %s"), + utf8_opt_arg, "--store-pristine", "yes, no"); + break; default: /* Hmmm. Perhaps this would be a good place to squirrel away opts that commands like svn diff might need. Hmmm indeed. */ @@ -3244,6 +3269,12 @@ sub_main(int *exit_code, int argc, const { SVN_ERR(svn_cl__get_notifier(&ctx->notify_func2, &ctx->notify_baton2, conflict_stats, pool)); + + /* Data-outputting commands should not print progress notifications + * (such as hydrating text bases) on stdout. */ + if (subcommand->cmd_func == svn_cl__cat + || subcommand->cmd_func == svn_cl__diff) + SVN_ERR(svn_cl__notifier_suppress_progress_output(ctx->notify_baton2)); } /* Get password from stdin if necessary */ Modified: subversion/trunk/subversion/tests/cmdline/authz_tests.py URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/authz_tests.py?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/tests/cmdline/authz_tests.py (original) +++ subversion/trunk/subversion/tests/cmdline/authz_tests.py Tue Dec 13 09:49:29 2022 @@ -1657,11 +1657,26 @@ def remove_access_after_commit(sbox): # And expect a mixed rev copy expected_status.tweak('A/D/G/rho', status='A ', entry_status=' ') - svntest.actions.run_and_verify_update(wc_dir, - expected_output, - expected_disk, - expected_status, - [], True) + + if svntest.actions.get_wc_store_pristine(wc_dir): + svntest.actions.run_and_verify_update(wc_dir, + expected_output, + expected_disk, + expected_status, + [], True) + else: + # We are unable to fetch the pristine without read access. + # So in a working copy without local pristines, the update is + # currently expected to fail. + if svntest.main.is_ra_type_dav(): + expected_err = ".*svn: E175013: .*[Ff]orbidden.*" + elif svntest.main.is_ra_type_svn(): + expected_err = ".*svn: E170001: Authorization failed.*" + else: + raise svntest.Failure + + svntest.actions.run_and_verify_update(wc_dir, None, None, None, + expected_err, True) @Issue(4793) @Skip(svntest.main.is_ra_type_file) @@ -1818,6 +1833,36 @@ def log_inaccessible_copyfrom(sbox): 'log', '-r2', '-v', sbox.repo_url) +@Skip(svntest.main.is_ra_type_file) +def cat_base_after_repo_access_removed(sbox): + "cat_base_after_repo_access_removed" + + sbox.build() + wc_dir = sbox.wc_dir + + svntest.main.write_restrictive_svnserve_conf(sbox.repo_dir) + svntest.main.write_authz_file(sbox, { "/" : "*=rw", + "/A/D" : "*="}) + + # Local modification so base can't be derived from working version + sbox.simple_append('A/D/G/pi', 'appended\n') + + # With repository read access denied, expect we can still access the + # text base locally, if and only if text bases are present. + if svntest.actions.get_wc_store_pristine(wc_dir): + svntest.actions.run_and_verify_svn("This is the file 'pi'.\n", [], + 'cat', sbox.ospath('A/D/G/pi') + '@BASE') + else: + if svntest.main.is_ra_type_dav(): + expected_err = ".*svn: E175013: .*[Ff]orbidden.*" + elif svntest.main.is_ra_type_svn(): + expected_err = ".*svn: E170001: Authorization failed.*" + else: + raise svntest.Failure + + svntest.actions.run_and_verify_svn(None, expected_err, + 'cat', sbox.ospath('A/D/G/pi') + '@BASE') + ######################################################################## # Run the tests @@ -1860,6 +1905,7 @@ test_list = [ None, empty_group, delete_file_with_starstar_rules, log_inaccessible_copyfrom, + cat_base_after_repo_access_removed, ] serial_only = True Modified: subversion/trunk/subversion/tests/cmdline/basic_tests.py URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/basic_tests.py?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/tests/cmdline/basic_tests.py (original) +++ subversion/trunk/subversion/tests/cmdline/basic_tests.py Tue Dec 13 09:49:29 2022 @@ -377,6 +377,10 @@ def basic_commit_corruption(sbox): mu_path = sbox.ospath('A/mu') svntest.main.file_append(mu_path, 'appended mu text') + # We are about to manually edit mu's text-base, so run "diff" to + # guarantee that the text-base is available in all pristine modes. + svntest.actions.run_and_verify_svn(None, [], 'diff', mu_path) + # Created expected output tree for 'svn ci' expected_output = wc.State(wc_dir, { 'A/mu' : Item(verb='Sending'), @@ -444,6 +448,12 @@ def basic_update_corruption(sbox): svntest.actions.run_and_verify_svn(None, [], 'co', sbox.repo_url, other_wc) + # The test manually edits mu's text-base when mu is unmodified. + # Unmodified files don't have their text-bases available with + # --store-pristine=no, so skip if that is the case. + if not svntest.actions.get_wc_store_pristine(other_wc): + raise svntest.Skip('Test assumes a working copy with pristine') + # Make a local mod to mu mu_path = sbox.ospath('A/mu') svntest.main.file_append(mu_path, 'appended mu text') @@ -2544,6 +2554,9 @@ def basic_auth_test(sbox): if svntest.main.options.wc_format_version: common_opts += ('--compatible-version', svntest.main.options.wc_format_version) + if svntest.main.options.store_pristine: + common_opts += ('--store-pristine', + svntest.main.options.store_pristine) # Checkout with jrandom exit_code, output, errput = svntest.main.run_command( Modified: subversion/trunk/subversion/tests/cmdline/diff_tests.py URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/diff_tests.py?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/tests/cmdline/diff_tests.py (original) +++ subversion/trunk/subversion/tests/cmdline/diff_tests.py Tue Dec 13 09:49:29 2022 @@ -3082,16 +3082,16 @@ def diff_external_diffcmd(sbox): if sys.platform == 'win32': diff_script_path = "%s.bat" % diff_script_path - expected_output = svntest.verify.ExpectedOutput([ + expected_output = svntest.verify.RegexListOutput([ "Index: iota\n", "===================================================================\n", "-u\n", "-L\n", - "iota\t(revision 1)\n", + r"iota\t\(revision 1\)\n", "-L\n", - "iota\t(working copy)\n", - os.path.abspath(svntest.wc.text_base_path("iota")) + "\n", - os.path.abspath("iota") + "\n"]) + r"iota\t\(working copy\)\n", + re.escape(os.path.abspath(svntest.main.get_admin_name())) + '.*' + "\n", + re.escape(os.path.abspath("iota")) + "\n"]) # Check that the output of diff corresponds with the expected arguments, # in the correct order. Modified: subversion/trunk/subversion/tests/cmdline/externals_tests.py URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/externals_tests.py?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/tests/cmdline/externals_tests.py (original) +++ subversion/trunk/subversion/tests/cmdline/externals_tests.py Tue Dec 13 09:49:29 2022 @@ -3431,6 +3431,7 @@ def update_deletes_file_external(sbox): @Issue(4519) +@Wimp("May trigger an existing issue, see upgrade_tests.py:upgrade_latest_format()") def switch_relative_externals(sbox): "switch relative externals" Modified: subversion/trunk/subversion/tests/cmdline/move_tests.py URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/move_tests.py?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/tests/cmdline/move_tests.py (original) +++ subversion/trunk/subversion/tests/cmdline/move_tests.py Tue Dec 13 09:49:29 2022 @@ -1599,21 +1599,26 @@ def move_conflict_details(sbox): sbox.simple_append('B/E/new-dir3', 'something') sbox.simple_add('B/E/new-dir3') + store_pristine = svntest.actions.get_wc_store_pristine(sbox.wc_dir) - expected_output = [ - " C %s\n" % sbox.ospath('B'), # Property conflicted - " U %s\n" % sbox.ospath('B/E'), # Just updated - "C %s\n" % sbox.ospath('B/E/alpha'), # Text conflicted - " C %s\n" % sbox.ospath('B/E/beta'), - " C %s\n" % sbox.ospath('B/E/new'), - " C %s\n" % sbox.ospath('B/E/new-dir1'), - " C %s\n" % sbox.ospath('B/E/new-dir2'), - " C %s\n" % sbox.ospath('B/E/new-dir3'), - " C %s\n" % sbox.ospath('B/F'), - " C %s\n" % sbox.ospath('B/lambda'), - "Updated to revision 2.\n", - "Tree conflict at '%s' marked as resolved.\n" % sbox.ospath('A/B') - ] + expected_output = svntest.verify.RegexListOutput( + ([] if store_pristine else ["Fetching text bases [.]+done"]) + + + [re.escape(x) for x in [ + " C %s\n" % sbox.ospath('B'), # Property conflicted + " U %s\n" % sbox.ospath('B/E'), # Just updated + "C %s\n" % sbox.ospath('B/E/alpha'), # Text conflicted + " C %s\n" % sbox.ospath('B/E/beta'), + " C %s\n" % sbox.ospath('B/E/new'), + " C %s\n" % sbox.ospath('B/E/new-dir1'), + " C %s\n" % sbox.ospath('B/E/new-dir2'), + " C %s\n" % sbox.ospath('B/E/new-dir3'), + " C %s\n" % sbox.ospath('B/F'), + " C %s\n" % sbox.ospath('B/lambda'), + "Updated to revision 2.\n", + "Tree conflict at '%s' marked as resolved.\n" % sbox.ospath('A/B') + ]] + ) svntest.actions.run_and_verify_svn(expected_output, [], 'resolve', sbox.ospath('A/B'), '--depth', 'empty', Modified: subversion/trunk/subversion/tests/cmdline/revert_tests.py URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/revert_tests.py?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/tests/cmdline/revert_tests.py (original) +++ subversion/trunk/subversion/tests/cmdline/revert_tests.py Tue Dec 13 09:49:29 2022 @@ -60,8 +60,8 @@ def run_and_verify_revert(targets, optio if reverted_paths is None: reverted_paths = targets expected_output = expected_output_revert(reverted_paths, skipped_paths) - svntest.actions.run_and_verify_svn(expected_output, [], - *(['revert'] + options + targets)) + svntest.actions.run_and_verify_revert_output(expected_output, + *(options + targets)) def revert_replacement_with_props(sbox, wc_copy): """Helper implementing the core of @@ -260,6 +260,34 @@ def revert_reexpand_keyword(sbox): sbox.build() wc_dir = sbox.wc_dir + + # The test expects two different things to happen during revert, depending + # on whether an `svn cleanup` or any other command that repairs the + # timestamps was called in between: + # + # - In the first part, we expect a revert to change file contents and + # re-expand its keywords, because a revert happens right after editing + # the file. + # + # - In the second part, we expect a revert to skip the file with exactly + # the same contents, because there's an in-between operation that has + # recorded the new unmodified timestamp in the db. (See r1101730 and + # r1101817.) + # + # This is a problem, because we expect two different things to happen for + # two identical on-disk file states. The only difference is whether any + # of the commands that perform the internal timestamp bookkeeping was + # called in between. For example, calling `svn cleanup` after editing the + # file makes the first and the second parts of the test behave identically. + # + # This problem prevents us from properly testing the `--store-pristine=no` + # case, because when we walk the text-bases we use that opportunity to + # repair timestamps, but that also makes the first and the second reverts + # in this test behave identically. Let's skip testing this case for now, + # until we resolve the described problem with opposite expectations. + if not svntest.actions.get_wc_store_pristine(wc_dir): + raise svntest.Skip() + newfile_path = os.path.join(wc_dir, "newfile") unexpanded_contents = "This is newfile: $Rev$.\n" Modified: subversion/trunk/subversion/tests/cmdline/svntest/actions.py URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/svntest/actions.py?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/tests/cmdline/svntest/actions.py (original) +++ subversion/trunk/subversion/tests/cmdline/svntest/actions.py Tue Dec 13 09:49:29 2022 @@ -527,7 +527,7 @@ def expected_noop_update_output(rev): """Return an ExpectedOutput object describing what we'd expect to see from an update to revision REV that was effectively a no-op (no server changes transmitted).""" - return verify.createExpectedOutput("Updating '.*':|At revision %d." + return verify.createExpectedOutput("Updating '.*':|Fetching text bases [.]+done|At revision %d." % (rev), "no-op update") @@ -1931,8 +1931,12 @@ def _run_and_verify_resolve(cmd, expecte expected_paths]), ], match_all=False) - run_and_verify_svn(expected_output, [], - cmd, *args) + exit_code, out, err = main.run_svn(None, cmd, *args) + out = [line for line in out + if not re.match(r'Fetching text bases [.]+done\n', line)] + verify.verify_outputs("Unexpected output", out, err, + expected_output, []) + verify.verify_exit_code("Unexpected return code", exit_code, 0) def run_and_verify_resolve(expected_paths, *args): """Run "svn resolve" with arguments ARGS, and verify that it resolves the @@ -1955,8 +1959,18 @@ def run_and_verify_revert(expected_paths expected_output = verify.UnorderedOutput([ "Reverted '" + path + "'\n" for path in expected_paths]) - run_and_verify_svn(expected_output, [], - "revert", *args) + run_and_verify_revert_output(expected_output, *args) + +def run_and_verify_revert_output(expected_output, *args): + """Run "svn revert" with arguments ARGS, and verify that it outputs + the text in EXPECTED_OUTPUT (and no stderr or exit code). + """ + exit_code, out, err = main.run_svn(None, "revert", *args) + out = [line for line in out + if not re.match(r'Fetching text bases [.]+done\n', line)] + verify.verify_outputs("Unexpected output", out, err, + expected_output, []) + verify.verify_exit_code("Unexpected return code", exit_code, 0) ###################################################################### @@ -2075,6 +2089,20 @@ def get_wc_base_rev(wc_dir): "Return the BASE revision of the working copy at WC_DIR." return run_and_parse_info(wc_dir)[0]['Revision'] +def get_wc_store_pristine(wc_dir): + "Return whether the working copy at WC_DIR stores pristine contents." + _, output, _ = run_and_verify_svn( + None, [], + 'info', '--show-item=store-pristine', '--no-newline', + wc_dir) + + if output == ['yes']: + return True + elif output == ['no']: + return False + else: + raise verify.SVNUnexpectedStdout(output) + def load_dumpfile(filename): "Return the contents of the FILENAME assuming that it is a dump file" with open(filename, "rb") as fp: Modified: subversion/trunk/subversion/tests/cmdline/svntest/main.py URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/svntest/main.py?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/tests/cmdline/svntest/main.py (original) +++ subversion/trunk/subversion/tests/cmdline/svntest/main.py Tue Dec 13 09:49:29 2022 @@ -800,6 +800,18 @@ def copy_trust(dst_cfgdir, src_cfgdir): for f in os.listdir(src_ssl_dir): shutil.copy(os.path.join(src_ssl_dir, f), os.path.join(dst_ssl_dir, f)) +def _with_store_pristine(args): + if '--store-pristine' in args \ + or any(str(one_arg).startswith('--store-pristine=') for one_arg in args) \ + or options.store_pristine is None: + return args + non_opt_args = [a for a in args if not str(a).startswith('-')] + if non_opt_args: + subcommand = non_opt_args[0] + if subcommand in ['co', 'checkout']: + return args + ('--store-pristine', options.store_pristine) + return args + def _with_wc_format_version(args): if '--compatible-version' in args \ or any(str(one_arg).startswith('--compatible-version=') for one_arg in args) \ @@ -847,7 +859,8 @@ def run_svn(error_expected, *varargs): you're just checking that something does/doesn't come out of stdout/stderr, you might want to use actions.run_and_verify_svn().""" return run_command(svn_binary, error_expected, False, - *(_with_wc_format_version(_with_auth(_with_config_dir(varargs))))) + *(_with_store_pristine(_with_wc_format_version( + _with_auth(_with_config_dir(varargs)))))) # For running svnadmin. Ignores the output. def run_svnadmin(*varargs): @@ -1765,6 +1778,11 @@ def wc_format(ver=None): return 31 raise Exception("Unrecognized version number '%s'" % (ver,)) +def wc_supports_optional_pristine(): + if options.wc_format_version is None: + return True + else: + return wc_format(options.wc_format_version) >= 32 ###################################################################### @@ -1852,6 +1870,8 @@ class TestSpawningThread(threading.Threa args.append('--allow-remote-http-connection') if options.svn_bin: args.append('--bin=' + options.svn_bin) + if options.store_pristine: + args.append('--store-pristine=' + options.store_pristine) result, stdout_lines, stderr_lines = spawn_process(command, 0, False, None, *args) @@ -2291,6 +2311,8 @@ def _create_parser(usage=None): help='Set directory deltification option (for fsfs)') parser.add_option('--allow-remote-http-connection', action='store_true', help='Run tests that connect to remote HTTP(S) servers') + parser.add_option('--store-pristine', action='store', type='str', + help='Set the WC pristine mode') # most of the defaults are None, but some are other values, set them here parser.set_defaults( Modified: subversion/trunk/subversion/tests/cmdline/svntest/mergetrees.py URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/svntest/mergetrees.py?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/tests/cmdline/svntest/mergetrees.py (original) +++ subversion/trunk/subversion/tests/cmdline/svntest/mergetrees.py Tue Dec 13 09:49:29 2022 @@ -95,6 +95,8 @@ def expected_merge_output(rev_ranges, ad if (two_url): lines += ["--- Recording mergeinfo for merge between repository URLs .*\n"] + lines += ["Fetching text bases [.]+done\n"] + # Address "The Backslash Plague" # # If ADDITIONAL_LINES are present there are possibly paths in it with Modified: subversion/trunk/subversion/tests/cmdline/svntest/wc.py URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/svntest/wc.py?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/tests/cmdline/svntest/wc.py (original) +++ subversion/trunk/subversion/tests/cmdline/svntest/wc.py Tue Dec 13 09:49:29 2022 @@ -590,7 +590,7 @@ class State: desc = { } for line in lines: - if line.startswith('DBG:'): + if line.startswith('DBG:') or re.match('^Fetching text bases [.]+done$', line): continue match = _re_parse_checkout.search(line) Modified: subversion/trunk/subversion/tests/cmdline/trans_tests.py URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/trans_tests.py?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/tests/cmdline/trans_tests.py (original) +++ subversion/trunk/subversion/tests/cmdline/trans_tests.py Tue Dec 13 09:49:29 2022 @@ -393,9 +393,16 @@ def keywords_from_birth(sbox): '$URL::x%sx$\n' % (' ' * len(url_expand_test_data)) ] - fp = open(svntest.wc.text_base_path(fixed_length_keywords_path), 'r') - actual_textbase_kw = fp.readlines() - fp.close() + # Read the text base, either from a locally stored file or from the repo. + if svntest.actions.get_wc_store_pristine(wc_dir): + fp = open(svntest.wc.text_base_path(fixed_length_keywords_path), 'r') + actual_textbase_kw = fp.readlines() + fp.close() + else: + _, actual_textbase_kw, _ = svntest.main.run_svn(False, + 'cat', '-rHEAD', '--ignore-keywords', + fixed_length_keywords_path) + check_keywords(actual_textbase_kw, kw_textbase, "text base") # Check the Id keyword for filename with spaces. @@ -597,10 +604,11 @@ def eol_change_is_text_mod(sbox): if contents != b"1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n": raise svntest.Failure - foo_base_path = svntest.wc.text_base_path(foo_path) - base_contents = open(foo_base_path, 'rb').read() - if contents != base_contents: - raise svntest.Failure + if svntest.actions.get_wc_store_pristine(wc_dir): + foo_base_path = svntest.wc.text_base_path(foo_path) + base_contents = open(foo_base_path, 'rb').read() + if contents != base_contents: + raise svntest.Failure #---------------------------------------------------------------------- # Regression test for issue #1151. A single file in a directory Modified: subversion/trunk/subversion/tests/cmdline/update_tests.py URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/update_tests.py?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/tests/cmdline/update_tests.py (original) +++ subversion/trunk/subversion/tests/cmdline/update_tests.py Tue Dec 13 09:49:29 2022 @@ -1188,10 +1188,13 @@ def another_hudson_problem(sbox): 'D '+G_path+'\n', 'Updated to revision 3.\n', ] + expected_output = [re.escape(s) for s in expected_output] + if not svntest.actions.get_wc_store_pristine(wc_dir): + expected_output.append('Fetching text bases [.]*done\n') # Sigh, I can't get run_and_verify_update to work (but not because # of issue 919 as far as I can tell) - expected_output = svntest.verify.UnorderedOutput(expected_output) + expected_output = svntest.verify.UnorderedRegexListOutput(expected_output) svntest.actions.run_and_verify_svn(expected_output, [], 'up', G_path) @@ -3713,65 +3716,74 @@ def update_accept_conflicts(sbox): # Setup SVN_EDITOR and SVN_MERGE for --accept={edit,launch}. svntest.main.use_editor('append_foo') + def run_and_verify_update_output(expected_stdout, expected_stderr, *args): + expected_exit = 0 + exit_code, out, err = svntest.main.run_svn(True, *args) + out = [line for line in out + if not re.match(r'Fetching text bases [.]+done\n', line)] + verify.verify_outputs("Unexpected output", out, err, + expected_stdout, expected_stderr) + verify.verify_exit_code("Unexpected return code", exit_code, expected_exit) + # iota: no accept option # Just leave the conflicts alone, since run_and_verify_svn already uses # the --non-interactive option. - svntest.actions.run_and_verify_svn(update_output_with_conflicts( - 3, iota_path_backup), - [], - 'update', iota_path_backup) + run_and_verify_update_output(update_output_with_conflicts( + 3, iota_path_backup), + [], + 'update', iota_path_backup) # lambda: --accept=postpone # Just leave the conflicts alone. - svntest.actions.run_and_verify_svn(update_output_with_conflicts( - 3, lambda_path_backup), - [], - 'update', '--accept=postpone', - lambda_path_backup) + run_and_verify_update_output(update_output_with_conflicts( + 3, lambda_path_backup), + [], + 'update', '--accept=postpone', + lambda_path_backup) # mu: --accept=base # Accept the pre-update base file. - svntest.actions.run_and_verify_svn(update_output_with_conflicts_resolved( - 3, mu_path_backup), - [], - 'update', '--accept=base', - mu_path_backup) + run_and_verify_update_output(update_output_with_conflicts_resolved( + 3, mu_path_backup), + [], + 'update', '--accept=base', + mu_path_backup) # alpha: --accept=mine # Accept the user's working file. - svntest.actions.run_and_verify_svn(update_output_with_conflicts_resolved( - 3, alpha_path_backup), - [], - 'update', '--accept=mine-full', - alpha_path_backup) + run_and_verify_update_output(update_output_with_conflicts_resolved( + 3, alpha_path_backup), + [], + 'update', '--accept=mine-full', + alpha_path_backup) # beta: --accept=theirs # Accept their file. - svntest.actions.run_and_verify_svn(update_output_with_conflicts_resolved( - 3, beta_path_backup), - [], - 'update', '--accept=theirs-full', - beta_path_backup) + run_and_verify_update_output(update_output_with_conflicts_resolved( + 3, beta_path_backup), + [], + 'update', '--accept=theirs-full', + beta_path_backup) # pi: --accept=edit # Run editor and accept the edited file. The merge tool will leave # conflicts in place, so expect a message on stderr, but expect # svn to exit with an exit code of 0. - svntest.actions.run_and_verify_svn2(update_output_with_conflicts_resolved( - 3, p_i_path_backup), - "system(.*) returned.*", 0, - 'update', '--accept=edit', - '--force-interactive', - p_i_path_backup) + run_and_verify_update_output(update_output_with_conflicts_resolved( + 3, p_i_path_backup), + "system(.*) returned.*", + 'update', '--accept=edit', + '--force-interactive', + p_i_path_backup) # rho: --accept=launch # Run the external merge tool, it should leave conflict markers in place. - svntest.actions.run_and_verify_svn(update_output_with_conflicts( - 3, rho_path_backup), - [], - 'update', '--accept=launch', - '--force-interactive', - rho_path_backup) + run_and_verify_update_output(update_output_with_conflicts( + 3, rho_path_backup), + [], + 'update', '--accept=launch', + '--force-interactive', + rho_path_backup) # Set the expected disk contents for the test expected_disk = svntest.main.greek_state.copy() @@ -5175,14 +5187,27 @@ def skip_access_denied(sbox): expected_status = svntest.actions.get_virginal_state(wc_dir, 1) expected_status.tweak('iota', status='M ', wc_rev=2) - # And now check that update skips the path - # *and* status shows the path as modified. - svntest.actions.run_and_verify_update(wc_dir, - expected_output, - None, - expected_status, - [], False, - wc_dir, '-r', '1') + if svntest.actions.get_wc_store_pristine(wc_dir): + # And now check that update skips the path *and* status shows + # the path as modified. + svntest.actions.run_and_verify_update(wc_dir, + expected_output, + None, + expected_status, + [], False, + wc_dir, '-r', '1') + else: + # For a working copy that doesn't store local pristine contents, don't + # skip access violation errors when determining if a file was modified. + # Because if we did that (and treated such files as modified, see above), + # we'd also find ourselves uncontrollably fetching and removing pristines + # based on transient errors -- which probably is an undesired property. + # So we currently expect to receive an error: + expected_err = ".*svn: E155039: Couldn't open a working copy file*" + svntest.actions.run_and_verify_update(wc_dir, + None, None, None, + expected_err, False, + wc_dir, '-r', '1') f.close() Modified: subversion/trunk/subversion/tests/cmdline/upgrade_tests.py URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/upgrade_tests.py?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/tests/cmdline/upgrade_tests.py (original) +++ subversion/trunk/subversion/tests/cmdline/upgrade_tests.py Tue Dec 13 09:49:29 2022 @@ -116,14 +116,14 @@ def check_formats(sbox, expected_formats raise svntest.Failure("found format '%s'; expected '%s'; in wc '%s'" % (formats, expected_formats, sbox.wc_dir)) - def check_pristine(sbox, files): for file in files: file_path = sbox.ospath(file) - file_text = open(file_path, 'r').read() - file_pristine = open(svntest.wc.text_base_path(file_path), 'r').read() - if (file_text != file_pristine): - raise svntest.Failure("pristine mismatch for '%s'" % (file)) + if svntest.actions.get_wc_store_pristine(file_path): + file_text = open(file_path, 'r').read() + file_pristine = open(svntest.wc.text_base_path(file_path), 'r').read() + if (file_text != file_pristine): + raise svntest.Failure("pristine mismatch for '%s'" % (file)) def check_dav_cache(dir_path, wc_id, expected_dav_caches): dot_svn = svntest.main.get_admin_name() @@ -140,9 +140,8 @@ def check_dav_cache(dir_path, wc_id, exp minor = sqlite_ver[1] patch = sqlite_ver[2] - if major < 3 or (major == 3 and minor < 6) \ - or (major == 3 and minor == 6 and patch < 18): - return # We need a newer SQLite + if major < 3 or (major == 3 and minor < 9): + return # We need a newer SQLite for local_relpath, expected_dav_cache in expected_dav_caches.items(): # NODES conversion is complete enough that we can use it if it exists Modified: subversion/trunk/subversion/tests/libsvn_client/client-test.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_client/client-test.c?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/tests/libsvn_client/client-test.c (original) +++ subversion/trunk/subversion/tests/libsvn_client/client-test.c Tue Dec 13 09:49:29 2022 @@ -392,7 +392,9 @@ test_patch(const svn_test_opts_t *opts, SVN_ERR(svn_client_checkout4(NULL, repos_url, wc_path, &peg_rev, &rev, svn_depth_infinity, TRUE, FALSE, - opts->wc_format_version, ctx, pool)); + opts->wc_format_version, + opts->store_pristine, + ctx, pool)); /* Create the patch file. */ patch_file_path = svn_dirent_join_many( @@ -466,13 +468,17 @@ test_wc_add_scenarios(const svn_test_opt /* Checkout greek tree as wc_path */ SVN_ERR(svn_client_checkout4(NULL, repos_url, wc_path, &peg_rev, &rev, svn_depth_infinity, FALSE, FALSE, - opts->wc_format_version, ctx, pool)); + opts->wc_format_version, + opts->store_pristine, + ctx, pool)); /* Now checkout again as wc_path/NEW */ new_dir_path = svn_dirent_join(wc_path, "NEW", pool); SVN_ERR(svn_client_checkout4(NULL, repos_url, new_dir_path, &peg_rev, &rev, svn_depth_infinity, FALSE, FALSE, - opts->wc_format_version, ctx, pool)); + opts->wc_format_version, + opts->store_pristine, + ctx, pool)); ex_dir_path = svn_dirent_join(wc_path, "NEW_add", pool); ex2_dir_path = svn_dirent_join(wc_path, "NEW_add2", pool); @@ -632,7 +638,9 @@ test_16k_add(const svn_test_opts_t *opts SVN_ERR(svn_client_checkout4(NULL, repos_url, wc_path, &peg_rev, &rev, svn_depth_infinity, TRUE, FALSE, - opts->wc_format_version, ctx, pool)); + opts->wc_format_version, + opts->store_pristine, + ctx, pool)); for (i = 0; i < 16384; i++) { @@ -763,7 +771,9 @@ test_foreign_repos_copy(const svn_test_o SVN_ERR(svn_client_checkout4(NULL, repos_url, wc_path, &peg_rev, &rev, svn_depth_infinity, FALSE, FALSE, - opts->wc_format_version, ctx, pool)); + opts->wc_format_version, + opts->store_pristine, + ctx, pool)); SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &loc, repos2_url, NULL, &peg_rev, &rev, @@ -832,7 +842,9 @@ test_suggest_mergesources(const svn_test wc_path, &head_rev, &head_rev, svn_depth_empty, FALSE, FALSE, - opts->wc_format_version, ctx, pool)); + opts->wc_format_version, + opts->store_pristine, + ctx, pool)); SVN_ERR(svn_client_suggest_merge_sources(&results, wc_path, @@ -979,7 +991,9 @@ test_remote_only_status(const svn_test_o apr_pstrcat(pool, repos_url, "/A", SVN_VA_NULL), wc_path, &rev, &rev, svn_depth_immediates, FALSE, FALSE, - opts->wc_format_version, ctx, pool)); + opts->wc_format_version, + opts->store_pristine, + ctx, pool)); /* Add a local file; this is a double-check to make sure that remote-only status ignores local changes. */ Modified: subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c (original) +++ subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c Tue Dec 13 09:49:29 2022 @@ -6117,7 +6117,9 @@ test_file_vs_dir_move_merge_assertion_fa "A1", pool), wc_path, &peg_rev, &opt_rev, svn_depth_infinity, TRUE, FALSE, - opts->wc_format_version, ctx, pool)); + opts->wc_format_version, + opts->store_pristine, + ctx, pool)); SVN_ERR(svn_client_merge_peg5(svn_path_url_add_component2(b->repos_url, "A", pool), Modified: subversion/trunk/subversion/tests/libsvn_wc/entries-compat.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_wc/entries-compat.c?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/tests/libsvn_wc/entries-compat.c (original) +++ subversion/trunk/subversion/tests/libsvn_wc/entries-compat.c Tue Dec 13 09:49:29 2022 @@ -620,7 +620,7 @@ test_access_baton_like_locking(const svn svn_path_url_add_component2(url, "sub-wc", pool), repos_root_url, repos_uuid, 0, svn_depth_infinity, - pool)); + opts->store_pristine, pool)); SVN_ERR(svn_wc__db_is_switched(&is_root, NULL, NULL, wc_ctx->db, subdir, pool)); Modified: subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c (original) +++ subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c Tue Dec 13 09:49:29 2022 @@ -2063,6 +2063,30 @@ typedef struct actual_row_t { const char *changelist; } actual_row_t; +/* Return STMT_FOR_F31 or STMT_FOR_F32 according to the format (31 or 32) + * of the WC in sandbox B. On error, return -1 to trigger a SQLite API error. + */ +static int +stmt_for_f31_or_f32(svn_test__sandbox_t *b, + int stmt_for_f31, + int stmt_for_f32) +{ + svn_error_t *err; + svn_wc__db_wcroot_t *wcroot; + const char *local_relpath; + + err = svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, + b->wc_ctx->db, b->wc_abspath, + b->pool, b->pool); + if (err) + { + svn_error_clear(err); + return -1; + } + + return (wcroot->format >= 32 ? stmt_for_f32 : stmt_for_f31); +} + static svn_error_t * insert_actual(svn_test__sandbox_t *b, actual_row_t *actual) @@ -2092,7 +2116,10 @@ insert_actual(svn_test__sandbox_t *b, if (actual->changelist) { SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, - STMT_ENSURE_EMPTY_PRISTINE)); + stmt_for_f31_or_f32( + b, + STMT_ENSURE_EMPTY_PRISTINE_F31, + STMT_ENSURE_EMPTY_PRISTINE_F32))); SVN_ERR(svn_sqlite__step_done(stmt)); SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_NODES_SET_FILE)); SVN_ERR(svn_sqlite__bindf(stmt, "s", actual->local_relpath)); Modified: subversion/trunk/subversion/tests/libsvn_wc/pristine-store-test.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_wc/pristine-store-test.c?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/tests/libsvn_wc/pristine-store-test.c (original) +++ subversion/trunk/subversion/tests/libsvn_wc/pristine-store-test.c Tue Dec 13 09:49:29 2022 @@ -94,7 +94,7 @@ pristine_write_read(const svn_test_opts_ SVN_ERR(svn_wc__db_pristine_prepare_install(&pristine_stream, &install_data, &data_sha1, &data_md5, - db, wc_abspath, + db, wc_abspath, TRUE, pool, pool)); sz = strlen(data); @@ -104,10 +104,12 @@ pristine_write_read(const svn_test_opts_ /* Ensure it's not already in the store. */ { svn_boolean_t present; + svn_boolean_t hydrated; - SVN_ERR(svn_wc__db_pristine_check(&present, db, wc_abspath, data_sha1, - pool)); + SVN_ERR(svn_wc__db_pristine_check(&present, &hydrated, db, wc_abspath, + data_sha1, pool)); SVN_TEST_ASSERT(! present); + SVN_TEST_ASSERT(! hydrated); } /* Install the new pristine file, referenced by its checksum. */ @@ -117,10 +119,12 @@ pristine_write_read(const svn_test_opts_ /* Ensure it is now found in the store. */ { svn_boolean_t present; + svn_boolean_t hydrated; - SVN_ERR(svn_wc__db_pristine_check(&present, db, wc_abspath, data_sha1, - pool)); + SVN_ERR(svn_wc__db_pristine_check(&present, &hydrated, db, wc_abspath, + data_sha1, pool)); SVN_TEST_ASSERT(present); + SVN_TEST_ASSERT(hydrated); } /* Look up its MD-5 from its SHA-1, and check it's the same MD-5. */ @@ -161,10 +165,12 @@ pristine_write_read(const svn_test_opts_ /* Ensure it's no longer found in the store. */ { svn_boolean_t present; + svn_boolean_t hydrated; - SVN_ERR(svn_wc__db_pristine_check(&present, db, wc_abspath, data_sha1, - pool)); + SVN_ERR(svn_wc__db_pristine_check(&present, &hydrated, db, wc_abspath, + data_sha1, pool)); SVN_TEST_ASSERT(! present); + SVN_TEST_ASSERT(! hydrated); } return SVN_NO_ERROR; @@ -191,7 +197,7 @@ pristine_delete_while_open(const svn_tes SVN_ERR(svn_wc__db_pristine_prepare_install(&pristine_stream, &install_data, &data_sha1, &data_md5, - db, wc_abspath, + db, wc_abspath, TRUE, pool, pool)); sz = strlen(data); @@ -221,10 +227,12 @@ pristine_delete_while_open(const svn_tes * an orphan, depending on the implementation.) */ { svn_boolean_t present; + svn_boolean_t hydrated; - SVN_ERR(svn_wc__db_pristine_check(&present, db, wc_abspath, data_sha1, - pool)); + SVN_ERR(svn_wc__db_pristine_check(&present, &hydrated, db, wc_abspath, + data_sha1, pool)); SVN_TEST_ASSERT(! present); + SVN_TEST_ASSERT(! hydrated); } /* Close the read stream */ @@ -264,7 +272,7 @@ reject_mismatching_text(const svn_test_o SVN_ERR(svn_wc__db_pristine_prepare_install(&pristine_stream, &install_data, &data_sha1, &data_md5, - db, wc_abspath, + db, wc_abspath, TRUE, pool, pool)); sz = strlen(data); @@ -286,7 +294,7 @@ reject_mismatching_text(const svn_test_o SVN_ERR(svn_wc__db_pristine_prepare_install(&pristine_stream, &install_data, &data_sha1, &data_md5, - db, wc_abspath, + db, wc_abspath, TRUE, pool, pool)); sz = strlen(data2); @@ -306,6 +314,233 @@ reject_mismatching_text(const svn_test_o #endif } +static svn_error_t * +pristine_install_dehydrated(const svn_test_opts_t *opts, + apr_pool_t *pool) +{ + svn_wc__db_t *db; + const char *wc_abspath; + + svn_wc__db_install_data_t *install_data; + svn_stream_t *pristine_stream; + apr_size_t sz; + + const char data[] = "Blah"; + svn_checksum_t *data_sha1, *data_md5; + + svn_boolean_t store_pristine; + + SVN_ERR(create_repos_and_wc(&wc_abspath, &db, + "pristine_install_dehydrated", opts, pool)); + + SVN_ERR(svn_wc__db_get_settings(NULL, &store_pristine, db, wc_abspath, pool)); + if (store_pristine) + return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL, + "Test assumes a working copy without pristine"); + + /* Write DATA into a new temporary pristine file, set PRISTINE_TMP_ABSPATH + * to its path and set DATA_SHA1 and DATA_MD5 to its checksums. */ + SVN_ERR(svn_wc__db_pristine_prepare_install(&pristine_stream, + &install_data, + &data_sha1, &data_md5, + db, wc_abspath, FALSE, + pool, pool)); + + sz = strlen(data); + SVN_ERR(svn_stream_write(pristine_stream, data, &sz)); + SVN_ERR(svn_stream_close(pristine_stream)); + + /* Ensure it's not already in the store. */ + { + svn_boolean_t present; + svn_boolean_t hydrated; + + SVN_ERR(svn_wc__db_pristine_check(&present, &hydrated, db, wc_abspath, + data_sha1, pool)); + SVN_TEST_ASSERT(! present); + SVN_TEST_ASSERT(! hydrated); + } + + /* Install the new pristine file, referenced by its checksum. */ + SVN_ERR(svn_wc__db_pristine_install(install_data, + data_sha1, data_md5, pool)); + + /* Ensure it is now found in the store. */ + { + svn_boolean_t present; + svn_boolean_t hydrated; + + SVN_ERR(svn_wc__db_pristine_check(&present, &hydrated, db, wc_abspath, + data_sha1, pool)); + SVN_TEST_ASSERT(present); + SVN_TEST_ASSERT(! hydrated); + } + + /* Look up its MD-5 from its SHA-1, and check it's the same MD-5. */ + { + const svn_checksum_t *looked_up_md5; + + SVN_ERR(svn_wc__db_pristine_get_md5(&looked_up_md5, db, wc_abspath, + data_sha1, pool, pool)); + SVN_TEST_ASSERT(looked_up_md5->kind == svn_checksum_md5); + SVN_TEST_ASSERT(svn_checksum_match(data_md5, looked_up_md5)); + } + + /* Check the saved pristine size and try to read the pristine text back. */ + { + svn_stream_t *actual_contents; + svn_filesize_t actual_size; + + SVN_ERR(svn_wc__db_pristine_read(&actual_contents, &actual_size, + db, wc_abspath, data_sha1, pool, pool)); + SVN_TEST_ASSERT(actual_contents == NULL); + SVN_TEST_INT_ASSERT(actual_size, sz); + } + + /* Trivially test the "remove if unreferenced" API: it's not referenced + so we should be able to remove it. */ + { + svn_error_t *err; + svn_stream_t *data_read_back; + + SVN_ERR(svn_wc__db_pristine_remove(db, wc_abspath, data_sha1, pool)); + err = svn_wc__db_pristine_read(&data_read_back, NULL, db, wc_abspath, + data_sha1, pool, pool); + SVN_TEST_ASSERT_ERROR(err, SVN_ERR_WC_PATH_NOT_FOUND); + } + + /* Ensure it's no longer found in the store. */ + { + svn_boolean_t present; + svn_boolean_t hydrated; + + SVN_ERR(svn_wc__db_pristine_check(&present, &hydrated, db, wc_abspath, + data_sha1, pool)); + SVN_TEST_ASSERT(! present); + SVN_TEST_ASSERT(! hydrated); + } + + return SVN_NO_ERROR; +} + +static svn_error_t * +pristine_dehydrate(const svn_test_opts_t *opts, + apr_pool_t *pool) +{ + svn_wc__db_t *db; + const char *wc_abspath; + + svn_wc__db_install_data_t *install_data; + svn_stream_t *pristine_stream; + apr_size_t sz; + + const char data[] = "Blah"; + svn_string_t *data_string = svn_string_create(data, pool); + svn_checksum_t *data_sha1, *data_md5; + + svn_boolean_t store_pristine; + + SVN_ERR(create_repos_and_wc(&wc_abspath, &db, + "pristine_dehydrate", opts, pool)); + + SVN_ERR(svn_wc__db_get_settings(NULL, &store_pristine, db, wc_abspath, pool)); + if (store_pristine) + return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL, + "Test assumes a working copy without pristine"); + + /* Write DATA into a new temporary pristine file, set PRISTINE_TMP_ABSPATH + * to its path and set DATA_SHA1 and DATA_MD5 to its checksums. */ + SVN_ERR(svn_wc__db_pristine_prepare_install(&pristine_stream, + &install_data, + &data_sha1, &data_md5, + db, wc_abspath, TRUE, + pool, pool)); + + sz = strlen(data); + SVN_ERR(svn_stream_write(pristine_stream, data, &sz)); + SVN_ERR(svn_stream_close(pristine_stream)); + + /* Install the new pristine file, referenced by its checksum. */ + SVN_ERR(svn_wc__db_pristine_install(install_data, + data_sha1, data_md5, pool)); + + /* Check the state of the pristine. */ + { + svn_boolean_t present; + svn_boolean_t hydrated; + + SVN_ERR(svn_wc__db_pristine_check(&present, &hydrated, db, wc_abspath, + data_sha1, pool)); + SVN_TEST_ASSERT(present); + SVN_TEST_ASSERT(hydrated); + } + + /* Dehydrate the pristine. */ + SVN_ERR(svn_wc__db_pristine_dehydrate(db, wc_abspath, data_sha1, pool)); + + /* Check the state of the pristine. */ + { + svn_boolean_t present; + svn_boolean_t hydrated; + + SVN_ERR(svn_wc__db_pristine_check(&present, &hydrated, db, wc_abspath, + data_sha1, pool)); + SVN_TEST_ASSERT(present); + SVN_TEST_ASSERT(! hydrated); + } + + /* Check the saved pristine size and try to read the pristine text back. */ + { + svn_stream_t *actual_contents; + svn_filesize_t actual_size; + + SVN_ERR(svn_wc__db_pristine_read(&actual_contents, &actual_size, + db, wc_abspath, data_sha1, pool, pool)); + SVN_TEST_ASSERT(actual_contents == NULL); + SVN_TEST_INT_ASSERT(actual_size, sz); + } + + /* Rehydrate it by installing the pristine again. */ + SVN_ERR(svn_wc__db_pristine_prepare_install(&pristine_stream, + &install_data, + &data_sha1, &data_md5, + db, wc_abspath, TRUE, + pool, pool)); + + sz = strlen(data); + SVN_ERR(svn_stream_write(pristine_stream, data, &sz)); + SVN_ERR(svn_stream_close(pristine_stream)); + + SVN_ERR(svn_wc__db_pristine_install(install_data, + data_sha1, data_md5, pool)); + + /* Check the state of the pristine. */ + { + svn_boolean_t present; + svn_boolean_t hydrated; + + SVN_ERR(svn_wc__db_pristine_check(&present, &hydrated, db, wc_abspath, + data_sha1, pool)); + SVN_TEST_ASSERT(present); + SVN_TEST_ASSERT(hydrated); + } + + /* Read the pristine text back and verify it's the same content. */ + { + svn_stream_t *data_stream = svn_stream_from_string(data_string, pool); + svn_stream_t *data_read_back; + svn_boolean_t same; + + SVN_ERR(svn_wc__db_pristine_read(&data_read_back, NULL, db, wc_abspath, + data_sha1, pool, pool)); + SVN_ERR(svn_stream_contents_same2(&same, data_read_back, data_stream, + pool)); + SVN_TEST_ASSERT(same); + } + + return SVN_NO_ERROR; +} + static int max_threads = -1; @@ -318,6 +553,10 @@ static struct svn_test_descriptor_t test "pristine_delete_while_open"), SVN_TEST_OPTS_PASS(reject_mismatching_text, "reject_mismatching_text"), + SVN_TEST_OPTS_PASS(pristine_install_dehydrated, + "pristine_install_dehydrated"), + SVN_TEST_OPTS_PASS(pristine_dehydrate, + "pristine_dehydrate"), SVN_TEST_NULL }; Modified: subversion/trunk/subversion/tests/libsvn_wc/utils.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_wc/utils.c?rev=1905955&r1=1905954&r2=1905955&view=diff ============================================================================== --- subversion/trunk/subversion/tests/libsvn_wc/utils.c (original) +++ subversion/trunk/subversion/tests/libsvn_wc/utils.c Tue Dec 13 09:49:29 2022 @@ -108,6 +108,7 @@ create_repos_and_wc(const char **repos_u FALSE /* ignore_externals */, FALSE /* allow_unver_obstructions */, opts->wc_format_version, + opts->store_pristine, ctx, subpool)); svn_pool_destroy(subpool); } @@ -145,10 +146,10 @@ svn_test__create_fake_wc(const char *wc_ my_statements = apr_palloc(scratch_pool, 7 * sizeof(const char *)); i = 0; my_statements[i++] = statements[STMT_CREATE_SCHEMA]; + my_statements[i++] = extra_statements; if (target_format >= 32) my_statements[i++] = statements[STMT_UPGRADE_TO_32]; my_statements[i++] = statements[STMT_INSTALL_SCHEMA_STATISTICS]; - my_statements[i++] = extra_statements; my_statements[i++] = NULL; /* Create fake-wc/SUBDIR/.svn/ for placing the metadata. */ @@ -413,28 +414,22 @@ sbox_wc_copy_url(svn_test__sandbox_t *b, svn_error_t * sbox_wc_revert(svn_test__sandbox_t *b, const char *path, svn_depth_t depth) { - const char *abspath = sbox_wc_path(b, path); - const char *dir_abspath; - const char *lock_root_abspath; + svn_client_ctx_t *ctx; + apr_array_header_t *paths; - if (strcmp(abspath, b->wc_abspath)) - dir_abspath = svn_dirent_dirname(abspath, b->pool); - else - dir_abspath = abspath; + SVN_ERR(svn_test__create_client_ctx(&ctx, b, b->pool)); + + paths = apr_array_make(b->pool, 1, sizeof(const char *)); + APR_ARRAY_PUSH(paths, const char *) = sbox_wc_path(b, path); + + SVN_ERR(svn_client_revert4(paths, depth, + NULL /* changelists */, + FALSE /* clear_changelists */, + FALSE /* metadata_only */, + TRUE /*added_keep_local*/, + ctx, + b->pool)); - SVN_ERR(svn_wc__acquire_write_lock(&lock_root_abspath, b->wc_ctx, - dir_abspath, FALSE /* lock_anchor */, - b->pool, b->pool)); - SVN_ERR(svn_wc_revert6(b->wc_ctx, abspath, depth, - FALSE /* use_commit_times */, - NULL /* changelist_filter */, - FALSE /* clear_changelists */, - FALSE /* metadata_only */, - TRUE /*added_keep_local*/, - NULL, NULL, /* cancel baton + func */ - NULL, NULL, /* notify baton + func */ - b->pool)); - SVN_ERR(svn_wc__release_write_lock(b->wc_ctx, lock_root_abspath, b->pool)); return SVN_NO_ERROR; } @@ -584,27 +579,14 @@ svn_error_t * sbox_wc_resolve(svn_test__sandbox_t *b, const char *path, svn_depth_t depth, svn_wc_conflict_choice_t conflict_choice) { - const char *lock_abspath; - svn_error_t *err; + svn_client_ctx_t *ctx; + + SVN_ERR(svn_test__create_client_ctx(&ctx, b, b->pool)); - SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, b->wc_ctx, - sbox_wc_path(b, path), - b->pool, b->pool)); - err = svn_wc__resolve_conflicts(b->wc_ctx, sbox_wc_path(b, path), - depth, - TRUE /* resolve_text */, - "" /* resolve_prop (ALL props) */, - TRUE /* resolve_tree */, - conflict_choice, - NULL, NULL, /* conflict func */ - NULL, NULL, /* cancellation */ - NULL, NULL, /* notification */ - b->pool); - - err = svn_error_compose_create(err, svn_wc__release_write_lock(b->wc_ctx, - lock_abspath, - b->pool)); - return err; + SVN_ERR(svn_client_resolve(sbox_wc_path(b, path), depth, conflict_choice, + ctx, b->pool)); + + return SVN_NO_ERROR; } svn_error_t *