You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ko...@apache.org on 2022/12/13 09:49:30 UTC
svn commit: r1905955 [5/6] - in /subversion/trunk: ./ build/ build/generator/ notes/i525/ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_fs_x/ subversion/libsvn_ra/ subversion/libsvn_ra_local/ subversion/lib...
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 *