You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2022/02/10 20:04:43 UTC
svn commit: r1897946 [2/3] - in /subversion/branches/pristines-on-demand-on-mwf: ./ build/ subversion/bindings/swig/python/tests/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_wc/ subversion/tests/cmdline/ subversion/tests/cmd...
Modified: subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/diff_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/diff_editor.c?rev=1897946&r1=1897945&r2=1897946&view=diff
==============================================================================
--- subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/diff_editor.c (original)
+++ subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/diff_editor.c Thu Feb 10 20:04:43 2022
@@ -75,6 +75,7 @@
#include "adm_files.h"
#include "translate.h"
#include "diff.h"
+#include "textbase.h"
#include "svn_private_config.h"
@@ -476,15 +477,17 @@ svn_wc__diff_base_working_diff(svn_wc__d
if (skip)
return SVN_NO_ERROR;
- SVN_ERR(svn_wc__db_pristine_get_path(&pristine_file,
- db, local_abspath, checksum,
- scratch_pool, scratch_pool));
+ SVN_ERR(svn_wc__textbase_setaside(&pristine_file,
+ db, local_abspath, checksum,
+ cancel_func, cancel_baton,
+ scratch_pool, scratch_pool));
if (diff_pristine)
- SVN_ERR(svn_wc__db_pristine_get_path(&local_file,
- db, local_abspath,
- working_checksum,
- scratch_pool, scratch_pool));
+ SVN_ERR(svn_wc__textbase_setaside(&local_file,
+ db, local_abspath,
+ working_checksum,
+ cancel_func, cancel_baton,
+ scratch_pool, scratch_pool));
else if (! (had_props || props_mod))
local_file = local_abspath;
else if (files_same)
@@ -1019,8 +1022,9 @@ svn_wc__diff_local_only_file(svn_wc__db_
right_props = svn_prop_hash_dup(pristine_props, scratch_pool);
if (checksum)
- SVN_ERR(svn_wc__db_pristine_get_path(&pristine_file, db, local_abspath,
- checksum, scratch_pool, scratch_pool));
+ SVN_ERR(svn_wc__textbase_setaside(&pristine_file, db, local_abspath,
+ checksum, cancel_func, cancel_baton,
+ scratch_pool, scratch_pool));
else
pristine_file = NULL;
@@ -1415,9 +1419,10 @@ svn_wc__diff_base_only_file(svn_wc__db_t
if (skip)
return SVN_NO_ERROR;
- SVN_ERR(svn_wc__db_pristine_get_path(&pristine_file,
- db, local_abspath, checksum,
- scratch_pool, scratch_pool));
+ SVN_ERR(svn_wc__textbase_setaside(&pristine_file,
+ db, local_abspath, checksum,
+ NULL, NULL,
+ scratch_pool, scratch_pool));
SVN_ERR(processor->file_deleted(relpath,
left_src,
@@ -2111,17 +2116,17 @@ apply_textdelta(void *file_baton,
pool));
}
- SVN_ERR(svn_wc__db_pristine_read(&source, NULL,
- eb->db, fb->local_abspath,
- fb->base_checksum,
- pool, pool));
+ SVN_ERR(svn_wc__textbase_get_contents(&source,
+ eb->db, fb->local_abspath,
+ fb->base_checksum, FALSE,
+ pool, pool));
}
else if (fb->base_checksum)
{
- SVN_ERR(svn_wc__db_pristine_read(&source, NULL,
- eb->db, fb->local_abspath,
- fb->base_checksum,
- pool, pool));
+ SVN_ERR(svn_wc__textbase_get_contents(&source,
+ eb->db, fb->local_abspath,
+ fb->base_checksum, FALSE,
+ pool, pool));
}
else
source = svn_stream_empty(pool);
@@ -2215,10 +2220,11 @@ close_file(void *file_baton,
if (! repos_file)
{
assert(fb->base_checksum);
- SVN_ERR(svn_wc__db_pristine_get_path(&repos_file,
- eb->db, eb->anchor_abspath,
- fb->base_checksum,
- scratch_pool, scratch_pool));
+ SVN_ERR(svn_wc__textbase_setaside(&repos_file,
+ eb->db, fb->local_abspath,
+ fb->base_checksum,
+ eb->cancel_func, eb->cancel_baton,
+ scratch_pool, scratch_pool));
}
}
@@ -2251,10 +2257,11 @@ close_file(void *file_baton,
eb->db, fb->local_abspath,
scratch_pool, scratch_pool));
assert(checksum);
- SVN_ERR(svn_wc__db_pristine_get_path(&localfile,
- eb->db, eb->anchor_abspath,
- checksum,
- scratch_pool, scratch_pool));
+ SVN_ERR(svn_wc__textbase_setaside(&localfile,
+ eb->db, fb->local_abspath,
+ checksum,
+ eb->cancel_func, eb->cancel_baton,
+ scratch_pool, scratch_pool));
}
else
{
Modified: subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/externals.c
URL: http://svn.apache.org/viewvc/subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/externals.c?rev=1897946&r1=1897945&r2=1897946&view=diff
==============================================================================
--- subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/externals.c (original)
+++ subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/externals.c Thu Feb 10 20:04:43 2022
@@ -53,6 +53,7 @@
#include "translate.h"
#include "workqueue.h"
#include "conflicts.h"
+#include "textbase.h"
#include "svn_private_config.h"
@@ -631,19 +632,21 @@ apply_textdelta(void *file_baton,
pool)));
}
- SVN_ERR(svn_wc__db_pristine_read(&src_stream, NULL, eb->db,
- eb->wri_abspath, eb->original_checksum,
- pool, pool));
+ SVN_ERR(svn_wc__textbase_get_contents(&src_stream, eb->db,
+ eb->local_abspath,
+ eb->original_checksum,
+ FALSE, pool, pool));
}
else
src_stream = svn_stream_empty(pool);
- SVN_ERR(svn_wc__db_pristine_prepare_install(&dest_stream,
- &eb->install_data,
- &eb->new_sha1_checksum,
- &eb->new_md5_checksum,
- eb->db, eb->wri_abspath,
- eb->pool, pool));
+ SVN_ERR(svn_wc__textbase_prepare_install(&dest_stream,
+ &eb->install_data,
+ &eb->new_sha1_checksum,
+ &eb->new_md5_checksum,
+ eb->db, eb->local_abspath,
+ TRUE,
+ eb->pool, pool));
svn_txdelta_apply(src_stream, dest_stream, NULL, eb->local_abspath, pool,
handler, handler_baton);
@@ -887,13 +890,43 @@ close_file(void *file_baton,
}
if (install_pristine)
{
+ svn_stream_t *contents;
+ const char *tmpdir_abspath;
+ svn_stream_t *tmpstream;
+ const char *tmpfile_abspath;
+
+ SVN_ERR(svn_wc__db_pristine_read(&contents, NULL, eb->db,
+ eb->wri_abspath,
+ eb->new_sha1_checksum,
+ pool, pool));
+ if (!contents)
+ return svn_error_create(SVN_ERR_WC_PATH_UNEXPECTED_STATUS,
+ NULL, NULL);
+
+ SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&tmpdir_abspath,
+ eb->db, eb->wri_abspath,
+ pool, pool));
+ SVN_ERR(svn_stream_open_unique(&tmpstream, &tmpfile_abspath,
+ tmpdir_abspath,
+ svn_io_file_del_none,
+ pool, pool));
+ SVN_ERR(svn_stream_copy3(contents, tmpstream, eb->cancel_func,
+ eb->cancel_baton, pool));
+
SVN_ERR(svn_wc__wq_build_file_install(&work_item, eb->db,
eb->local_abspath,
- NULL,
+ tmpfile_abspath,
eb->use_commit_times, TRUE,
pool, pool));
all_work_items = svn_wc__wq_merge(all_work_items, work_item, pool);
+
+ SVN_ERR(svn_wc__wq_build_file_remove(&work_item, eb->db,
+ eb->wri_abspath,
+ tmpfile_abspath,
+ pool, pool));
+
+ all_work_items = svn_wc__wq_merge(all_work_items, work_item, pool);
}
}
else
Modified: subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/questions.c
URL: http://svn.apache.org/viewvc/subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/questions.c?rev=1897946&r1=1897945&r2=1897946&view=diff
==============================================================================
--- subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/questions.c (original)
+++ subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/questions.c Thu Feb 10 20:04:43 2022
@@ -79,15 +79,14 @@
/* Set *MODIFIED_P to TRUE if (after translation) VERSIONED_FILE_ABSPATH
- * (of VERSIONED_FILE_SIZE bytes) differs from PRISTINE_STREAM (of
- * PRISTINE_SIZE bytes), else to FALSE if not.
+ * (of VERSIONED_FILE_SIZE bytes) differs from pristine file with checksum
+ * PRISTINE_CHECKSUM, else to FALSE if not.
*
* If EXACT_COMPARISON is FALSE, translate VERSIONED_FILE_ABSPATH's EOL
* style and keywords to repository-normal form according to its properties,
- * and compare the result with PRISTINE_STREAM. If EXACT_COMPARISON is
- * TRUE, translate PRISTINE_STREAM's EOL style and keywords to working-copy
- * form according to VERSIONED_FILE_ABSPATH's properties, and compare the
- * result with VERSIONED_FILE_ABSPATH.
+ * calculate checksum and compare the result with PRISTINE_STREAM.
+ * If EXACT_COMPARISON is TRUE, also check that VERSIONED_FILE_ABSPATH
+ * contents remains the same when retranslated according to its properties.
*
* HAS_PROPS should be TRUE if the file had properties when it was not
* modified, otherwise FALSE.
@@ -95,8 +94,6 @@
* PROPS_MOD should be TRUE if the file's properties have been changed,
* otherwise FALSE.
*
- * PRISTINE_STREAM will be closed before a successful return.
- *
* DB is a wc_db; use SCRATCH_POOL for temporary allocation.
*/
static svn_error_t *
@@ -104,20 +101,20 @@ compare_and_verify(svn_boolean_t *modifi
svn_wc__db_t *db,
const char *versioned_file_abspath,
svn_filesize_t versioned_file_size,
- svn_stream_t *pristine_stream,
- svn_filesize_t pristine_size,
+ const svn_checksum_t *pristine_checksum,
svn_boolean_t has_props,
svn_boolean_t props_mod,
svn_boolean_t exact_comparison,
apr_pool_t *scratch_pool)
{
- svn_boolean_t same;
svn_subst_eol_style_t eol_style;
const char *eol_str;
apr_hash_t *keywords;
svn_boolean_t special = FALSE;
svn_boolean_t need_translation;
svn_stream_t *v_stream; /* versioned_file */
+ svn_checksum_t *v_checksum;
+ svn_error_t *err;
SVN_ERR_ASSERT(svn_dirent_is_absolute(versioned_file_abspath));
@@ -133,6 +130,9 @@ compare_and_verify(svn_boolean_t *modifi
!exact_comparison,
scratch_pool, scratch_pool));
+ if (eol_style == svn_subst_eol_style_unknown)
+ return svn_error_create(SVN_ERR_IO_UNKNOWN_EOL, NULL, NULL);
+
need_translation = svn_subst_translation_required(eol_style, eol_str,
keywords, special,
TRUE);
@@ -140,13 +140,20 @@ compare_and_verify(svn_boolean_t *modifi
else
need_translation = FALSE;
- if (! need_translation
- && (versioned_file_size != pristine_size))
+ if (! need_translation)
{
- *modified_p = TRUE;
+ svn_filesize_t pristine_size;
+
+ SVN_ERR(svn_wc__db_pristine_read(NULL, &pristine_size, db,
+ versioned_file_abspath, pristine_checksum,
+ scratch_pool, scratch_pool));
+
+ if (versioned_file_size != pristine_size)
+ {
+ *modified_p = TRUE;
- /* ### Why did we open the pristine? */
- return svn_error_trace(svn_stream_close(pristine_stream));
+ return SVN_NO_ERROR;
+ }
}
/* ### Other checks possible? */
@@ -162,46 +169,97 @@ compare_and_verify(svn_boolean_t *modifi
/* We don't use APR-level buffering because the comparison function
* will do its own buffering. */
apr_file_t *file;
- SVN_ERR(svn_io_file_open(&file, versioned_file_abspath, APR_READ,
- APR_OS_DEFAULT, scratch_pool));
+ err = svn_io_file_open(&file, versioned_file_abspath, APR_READ,
+ APR_OS_DEFAULT, scratch_pool);
+ /* Convert EACCESS on working copy path to WC specific error code. */
+ if (err && APR_STATUS_IS_EACCES(err->apr_err))
+ return svn_error_create(SVN_ERR_WC_PATH_ACCESS_DENIED, err, NULL);
+ else
+ SVN_ERR(err);
v_stream = svn_stream_from_aprfile2(file, FALSE, scratch_pool);
if (need_translation)
{
- if (!exact_comparison)
+ const char *pristine_eol_str;
+
+ if (eol_style == svn_subst_eol_style_native)
+ pristine_eol_str = SVN_SUBST_NATIVE_EOL_STR;
+ else
+ pristine_eol_str = eol_str;
+
+ if (exact_comparison)
{
- if (eol_style == svn_subst_eol_style_native)
- eol_str = SVN_SUBST_NATIVE_EOL_STR;
- else if (eol_style != svn_subst_eol_style_fixed
- && eol_style != svn_subst_eol_style_none)
- return svn_error_create(SVN_ERR_IO_UNKNOWN_EOL,
- svn_stream_close(v_stream), NULL);
+ svn_checksum_t *working_checksum;
+ svn_checksum_t *detranslated_checksum;
+ svn_checksum_t *retranslated_checksum;
+
+ v_stream = svn_stream_checksummed2(v_stream,
+ &working_checksum, NULL,
+ pristine_checksum->kind, TRUE,
+ scratch_pool);
+
+ v_stream = svn_subst_stream_translated(v_stream,
+ pristine_eol_str, TRUE,
+ keywords, FALSE,
+ scratch_pool);
+ v_stream = svn_stream_checksummed2(v_stream,
+ &detranslated_checksum, NULL,
+ pristine_checksum->kind, TRUE,
+ scratch_pool);
+
+ v_stream = svn_subst_stream_translated(v_stream, eol_str, FALSE,
+ keywords, TRUE,
+ scratch_pool);
+ v_stream = svn_stream_checksummed2(v_stream,
+ &retranslated_checksum, NULL,
+ pristine_checksum->kind, TRUE,
+ scratch_pool);
+
+ err = svn_stream_copy3(v_stream, svn_stream_empty(scratch_pool),
+ NULL, NULL, scratch_pool);
+ /* Convert EACCESS on working copy path to WC specific error code. */
+ if (err && APR_STATUS_IS_EACCES(err->apr_err))
+ return svn_error_create(SVN_ERR_WC_PATH_ACCESS_DENIED, err, NULL);
+ else
+ SVN_ERR(err);
+
+ if (svn_checksum_match(detranslated_checksum, pristine_checksum) &&
+ svn_checksum_match(working_checksum, retranslated_checksum))
+ {
+ *modified_p = FALSE;
+ }
+ else
+ {
+ *modified_p = TRUE;
+ }
+ return SVN_NO_ERROR;
+ }
+ else
+ {
/* Wrap file stream to detranslate into normal form,
* "repairing" the EOL style if it is inconsistent. */
v_stream = svn_subst_stream_translated(v_stream,
- eol_str,
+ pristine_eol_str,
TRUE /* repair */,
keywords,
FALSE /* expand */,
scratch_pool);
}
- else
- {
- /* Wrap base stream to translate into working copy form, and
- * arrange to throw an error if its EOL style is inconsistent. */
- pristine_stream = svn_subst_stream_translated(pristine_stream,
- eol_str, FALSE,
- keywords, TRUE,
- scratch_pool);
- }
}
}
- SVN_ERR(svn_stream_contents_same2(&same, pristine_stream, v_stream,
- scratch_pool));
+ /* Get checksum of detranslated (normalized) content. */
+ err = svn_stream_contents_checksum(&v_checksum, v_stream,
+ pristine_checksum->kind,
+ scratch_pool, scratch_pool);
+ /* Convert EACCESS on working copy path to WC specific error code. */
+ if (err && APR_STATUS_IS_EACCES(err->apr_err))
+ return svn_error_create(SVN_ERR_WC_PATH_ACCESS_DENIED, err, NULL);
+ else
+ SVN_ERR(err);
- *modified_p = (! same);
+ *modified_p = (! svn_checksum_match(v_checksum, pristine_checksum));
return SVN_NO_ERROR;
}
@@ -213,8 +271,6 @@ svn_wc__internal_file_modified_p(svn_boo
svn_boolean_t exact_comparison,
apr_pool_t *scratch_pool)
{
- svn_stream_t *pristine_stream;
- svn_filesize_t pristine_size;
svn_wc__db_status_t status;
svn_node_kind_t kind;
const svn_checksum_t *checksum;
@@ -302,27 +358,12 @@ svn_wc__internal_file_modified_p(svn_boo
}
compare_them:
- SVN_ERR(svn_wc__db_pristine_read(&pristine_stream, &pristine_size,
- db, local_abspath, checksum,
- scratch_pool, scratch_pool));
-
/* Check all bytes, and verify checksum if requested. */
- {
- svn_error_t *err;
- err = compare_and_verify(modified_p, db,
+ SVN_ERR(compare_and_verify(modified_p, db,
local_abspath, dirent->filesize,
- pristine_stream, pristine_size,
- has_props, props_mod,
+ checksum, has_props, props_mod,
exact_comparison,
- scratch_pool);
-
- /* At this point we already opened the pristine file, so we know that
- the access denied applies to the working copy path */
- if (err && APR_STATUS_IS_EACCES(err->apr_err))
- return svn_error_create(SVN_ERR_WC_PATH_ACCESS_DENIED, err, NULL);
- else
- SVN_ERR(err);
- }
+ scratch_pool));
if (!*modified_p)
{
Modified: subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/revert.c
URL: http://svn.apache.org/viewvc/subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/revert.c?rev=1897946&r1=1897945&r2=1897946&view=diff
==============================================================================
--- subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/revert.c (original)
+++ subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/revert.c Thu Feb 10 20:04:43 2022
@@ -42,6 +42,7 @@
#include "wc.h"
#include "adm_files.h"
#include "workqueue.h"
+#include "textbase.h"
#include "svn_private_config.h"
#include "private/svn_io_private.h"
@@ -714,10 +715,21 @@ revert_wc_data(svn_boolean_t *run_wq,
if (kind == svn_node_file)
{
svn_skel_t *work_item;
+ 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,
+ cancel_func, cancel_baton,
+ scratch_pool, scratch_pool));
SVN_ERR(svn_wc__wq_build_file_install(&work_item, db, local_abspath,
- NULL, use_commit_times, TRUE,
+ install_from,
+ use_commit_times, TRUE,
scratch_pool, scratch_pool));
+ work_item = svn_wc__wq_merge(work_item, cleanup_work_item,
+ scratch_pool);
+
SVN_ERR(svn_wc__db_wq_add(db, local_abspath, work_item,
scratch_pool));
*run_wq = TRUE;
Modified: subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/update_editor.c?rev=1897946&r1=1897945&r2=1897946&view=diff
==============================================================================
--- subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/update_editor.c Thu Feb 10 20:04:43 2022
@@ -48,6 +48,7 @@
#include "conflicts.h"
#include "translate.h"
#include "workqueue.h"
+#include "textbase.h"
#include "private/svn_subr_private.h"
#include "private/svn_wc_private.h"
@@ -439,7 +440,8 @@ struct handler_baton
/* Get an empty file in the temporary area for WRI_ABSPATH. The file will
not be set for automatic deletion, and the name will be returned in
- TMP_FILENAME.
+ TMP_FILENAME_P. Set *CLEANUP_WORK_ITEM_P to a new work item that will
+ remove the temporary file.
This implementation creates a new empty file with a unique name.
@@ -451,19 +453,35 @@ struct handler_baton
### file name to create later. A better way may not be readily available.
*/
static svn_error_t *
-get_empty_tmp_file(const char **tmp_filename,
+get_empty_tmp_file(const char **tmp_filename_p,
+ svn_skel_t **cleanup_work_item_p,
svn_wc__db_t *db,
const char *wri_abspath,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
const char *temp_dir_abspath;
+ const char *tmp_filename;
+ svn_skel_t *work_item;
+ svn_error_t *err;
SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&temp_dir_abspath, db, wri_abspath,
scratch_pool, scratch_pool));
- SVN_ERR(svn_io_open_unique_file3(NULL, tmp_filename, temp_dir_abspath,
+ SVN_ERR(svn_io_open_unique_file3(NULL, &tmp_filename, temp_dir_abspath,
svn_io_file_del_none,
scratch_pool, scratch_pool));
+ err = svn_wc__wq_build_file_remove(&work_item, db, wri_abspath,
+ tmp_filename,
+ result_pool, scratch_pool);
+ if (err)
+ {
+ return svn_error_compose_create(
+ err,
+ svn_io_remove_file2(tmp_filename, TRUE, scratch_pool));
+ }
+
+ *tmp_filename_p = tmp_filename;
+ *cleanup_work_item_p = work_item;
return SVN_NO_ERROR;
}
@@ -3726,10 +3744,10 @@ lazy_open_source(svn_stream_t **stream,
{
struct file_baton *fb = baton;
- SVN_ERR(svn_wc__db_pristine_read(stream, NULL, fb->edit_baton->db,
- fb->local_abspath,
- fb->original_checksum,
- result_pool, scratch_pool));
+ SVN_ERR(svn_wc__textbase_get_contents(stream, fb->edit_baton->db,
+ fb->local_abspath,
+ fb->original_checksum, FALSE,
+ result_pool, scratch_pool));
return SVN_NO_ERROR;
@@ -3748,19 +3766,35 @@ lazy_open_target(svn_stream_t **stream_p
svn_stream_t *pristine_install_stream;
svn_wc__working_file_writer_t *file_writer;
svn_stream_t *stream;
+ svn_boolean_t hydrated;
+
+ if (fb->shadowed || fb->obstruction_found || fb->edit_obstructed)
+ {
+ hydrated = TRUE;
+ }
+ else if (fb->adding_file && !fb->add_existed)
+ {
+ /* Clean new file, hint that we don't need the text-base. */
+ hydrated = FALSE;
+ }
+ else
+ {
+ hydrated = TRUE;
+ }
/* By convention return value is undefined on error, but we rely
on HB->INSTALL_DATA value in window_handler() and abort
INSTALL_STREAM if is not NULL on error.
So we store INSTALL_DATA to local variable first, to leave
HB->INSTALL_DATA unchanged on error. */
- SVN_ERR(svn_wc__db_pristine_prepare_install(&pristine_install_stream,
- &pristine_install_data,
- &hb->new_text_base_sha1_checksum,
- NULL,
- fb->edit_baton->db,
- fb->dir_baton->local_abspath,
- result_pool, scratch_pool));
+ SVN_ERR(svn_wc__textbase_prepare_install(&pristine_install_stream,
+ &pristine_install_data,
+ &hb->new_text_base_sha1_checksum,
+ NULL,
+ fb->edit_baton->db,
+ fb->local_abspath,
+ hydrated,
+ result_pool, scratch_pool));
if (fb->shadowed || fb->obstruction_found || fb->edit_obstructed)
{
@@ -4062,17 +4096,19 @@ svn_wc__perform_file_merge(svn_skel_t **
the textual changes into the working file. */
const char *oldrev_str, *newrev_str, *mine_str;
const char *merge_left;
- svn_boolean_t delete_left = FALSE;
const char *path_ext = "";
const char *new_pristine_abspath;
enum svn_wc_merge_outcome_t merge_outcome = svn_wc_merge_unchanged;
svn_skel_t *work_item;
+ svn_skel_t *cleanup_queue = NULL;
*work_items = NULL;
- SVN_ERR(svn_wc__db_pristine_get_path(&new_pristine_abspath,
- db, wri_abspath, new_checksum,
- scratch_pool, scratch_pool));
+ SVN_ERR(svn_wc__textbase_setaside_wq(&new_pristine_abspath, &work_item,
+ db, local_abspath, new_checksum,
+ cancel_func, cancel_baton,
+ result_pool, scratch_pool));
+ cleanup_queue = svn_wc__wq_merge(cleanup_queue, work_item, result_pool);
/* If we have any file extensions we're supposed to
preserve in generated conflict file names, then find
@@ -4106,14 +4142,19 @@ svn_wc__perform_file_merge(svn_skel_t **
if (! original_checksum)
{
- SVN_ERR(get_empty_tmp_file(&merge_left, db, wri_abspath,
+ SVN_ERR(get_empty_tmp_file(&merge_left, &work_item, db, wri_abspath,
result_pool, scratch_pool));
- delete_left = TRUE;
+ cleanup_queue = svn_wc__wq_merge(cleanup_queue, work_item, result_pool);
}
else
- SVN_ERR(svn_wc__db_pristine_get_path(&merge_left, db, wri_abspath,
- original_checksum,
- result_pool, scratch_pool));
+ {
+ SVN_ERR(svn_wc__textbase_setaside_wq(&merge_left, &work_item,
+ db, local_abspath,
+ original_checksum,
+ cancel_func, cancel_baton,
+ result_pool, scratch_pool));
+ cleanup_queue = svn_wc__wq_merge(cleanup_queue, work_item, result_pool);
+ }
/* Merge the changes from the old textbase to the new
textbase into the file we're updating.
@@ -4134,16 +4175,9 @@ svn_wc__perform_file_merge(svn_skel_t **
result_pool, scratch_pool));
*work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
- *found_conflict = (merge_outcome == svn_wc_merge_conflict);
+ *work_items = svn_wc__wq_merge(*work_items, cleanup_queue, result_pool);
- /* If we created a temporary left merge file, get rid of it. */
- if (delete_left)
- {
- SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db, wri_abspath,
- merge_left,
- result_pool, scratch_pool));
- *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
- }
+ *found_conflict = (merge_outcome == svn_wc_merge_conflict);
return SVN_NO_ERROR;
}
@@ -4728,9 +4762,9 @@ close_file(void *file_baton,
}
else
{
- SVN_ERR(svn_wc__db_pristine_read(&src_stream, NULL, eb->db,
- eb->wcroot_abspath, new_checksum,
- scratch_pool, scratch_pool));
+ SVN_ERR(svn_wc__textbase_get_contents(&src_stream, eb->db,
+ fb->local_abspath, new_checksum,
+ FALSE, scratch_pool, scratch_pool));
}
SVN_ERR(svn_stream_copy3(src_stream, dst_stream, NULL, NULL, scratch_pool));
@@ -4870,6 +4904,7 @@ update_keywords_after_switch_cb(void *ba
svn_boolean_t record_fileinfo;
svn_skel_t *work_items;
const char *install_from;
+ svn_skel_t *cleanup_work_item;
propval = svn_hash_gets(props, SVN_PROP_KEYWORDS);
if (!propval)
@@ -4895,11 +4930,18 @@ update_keywords_after_switch_cb(void *ba
SVN_ERR(svn_stream_copy3(working_stream, install_from_stream,
eb->cancel_func, eb->cancel_baton,
scratch_pool));
+ SVN_ERR(svn_wc__wq_build_file_remove(&cleanup_work_item, eb->db,
+ local_abspath, install_from,
+ scratch_pool, scratch_pool));
record_fileinfo = FALSE;
}
else
{
- install_from = NULL;
+ SVN_ERR(svn_wc__textbase_setaside_wq(&install_from,
+ &cleanup_work_item,
+ eb->db, local_abspath, NULL,
+ eb->cancel_func, eb->cancel_baton,
+ scratch_pool, scratch_pool));
record_fileinfo = TRUE;
}
@@ -4908,15 +4950,7 @@ update_keywords_after_switch_cb(void *ba
eb->use_commit_times,
record_fileinfo,
scratch_pool, scratch_pool));
- if (install_from)
- {
- svn_skel_t *work_item;
-
- SVN_ERR(svn_wc__wq_build_file_remove(&work_item, eb->db,
- local_abspath, install_from,
- 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);
SVN_ERR(svn_wc__db_wq_add(eb->db, local_abspath, work_items,
scratch_pool));
@@ -5605,33 +5639,39 @@ svn_wc_add_repos_file4(svn_wc_context_t
entry_props, pool, pool));
}
+ {
+ const char *tmp_dir_abspath;
+
+ SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&tmp_dir_abspath,
+ db, dir_abspath,
+ scratch_pool, scratch_pool));
+
+ SVN_ERR(svn_stream_open_unique(&tmp_base_contents, &tmp_text_base_abspath,
+ tmp_dir_abspath, svn_io_file_del_none,
+ scratch_pool, scratch_pool));
+ }
+
/* Copy NEW_BASE_CONTENTS into a temporary file so our log can refer to
it, and set TMP_TEXT_BASE_ABSPATH to its path. Compute its
NEW_TEXT_BASE_MD5_CHECKSUM and NEW_TEXT_BASE_SHA1_CHECKSUM as we copy. */
if (copyfrom_url)
{
- SVN_ERR(svn_wc__db_pristine_prepare_install(&tmp_base_contents,
- &install_data,
- &new_text_base_sha1_checksum,
- &new_text_base_md5_checksum,
- wc_ctx->db, local_abspath,
- scratch_pool, scratch_pool));
+ svn_stream_t *install_stream;
+
+ SVN_ERR(svn_wc__textbase_prepare_install(&install_stream,
+ &install_data,
+ &new_text_base_sha1_checksum,
+ &new_text_base_md5_checksum,
+ wc_ctx->db, local_abspath,
+ copyfrom_url != NULL,
+ scratch_pool, scratch_pool));
+
+ tmp_base_contents = svn_stream_tee(install_stream,
+ tmp_base_contents,
+ scratch_pool);
}
else
{
- const char *tmp_dir_abspath;
-
- /* We are not installing a PRISTINE file, but we use the same code to
- create whatever we want to install */
-
- SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&tmp_dir_abspath,
- db, dir_abspath,
- scratch_pool, scratch_pool));
-
- SVN_ERR(svn_stream_open_unique(&tmp_base_contents, &tmp_text_base_abspath,
- tmp_dir_abspath, svn_io_file_del_none,
- scratch_pool, scratch_pool));
-
new_text_base_sha1_checksum = NULL;
new_text_base_md5_checksum = NULL;
}
@@ -5654,6 +5694,10 @@ svn_wc_add_repos_file4(svn_wc_context_t
SVN_ERR(svn_stream_copy3(new_contents, tmp_contents,
cancel_func, cancel_baton, pool));
}
+ else
+ {
+ source_abspath = tmp_text_base_abspath;
+ }
/* Install new text base for copied files. Added files do NOT have a
text base. */
@@ -5689,42 +5733,20 @@ svn_wc_add_repos_file4(svn_wc_context_t
new_text_base_md5_checksum = NULL;
}
- /* For added files without NEW_CONTENTS, then generate the working file
- from the provided "pristine" contents. */
- if (new_contents == NULL && copyfrom_url == NULL)
- source_abspath = tmp_text_base_abspath;
-
- {
- svn_boolean_t record_fileinfo;
+ /* Install the working copy file (with appropriate translation) from
+ the provided temporary file at SOURCE_ABSPATH. */
+ SVN_ERR(svn_wc__wq_build_file_install(&work_item,
+ db, local_abspath,
+ source_abspath,
+ FALSE /* use_commit_times */,
+ TRUE /* record_fileinfo */,
+ pool, pool));
+ all_work_items = svn_wc__wq_merge(all_work_items, work_item, pool);
- /* If new contents were provided, then we do NOT want to record the
- file information. We assume the new contents do not match the
- "proper" values for RECORDED_SIZE and RECORDED_TIME. */
- record_fileinfo = (new_contents == NULL);
-
- /* Install the working copy file (with appropriate translation) from
- the appropriate source. SOURCE_ABSPATH will be NULL, indicating an
- installation from the pristine (available for copied/moved files),
- or it will specify a temporary file where we placed a "pristine"
- (for an added file) or a detranslated local-mods file. */
- SVN_ERR(svn_wc__wq_build_file_install(&work_item,
- db, local_abspath,
- source_abspath,
- FALSE /* use_commit_times */,
- record_fileinfo,
- pool, pool));
- all_work_items = svn_wc__wq_merge(all_work_items, work_item, pool);
-
- /* If we installed from somewhere besides the official pristine, then
- it is a temporary file, which needs to be removed. */
- if (source_abspath != NULL)
- {
- SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db, local_abspath,
- source_abspath,
- pool, pool));
- all_work_items = svn_wc__wq_merge(all_work_items, work_item, pool);
- }
- }
+ SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db, local_abspath,
+ source_abspath,
+ pool, pool));
+ all_work_items = svn_wc__wq_merge(all_work_items, work_item, pool);
SVN_ERR(svn_wc__db_op_copy_file(db, local_abspath,
new_base_props,
Modified: subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/upgrade.c
URL: http://svn.apache.org/viewvc/subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/upgrade.c?rev=1897946&r1=1897945&r2=1897946&view=diff
==============================================================================
--- subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/upgrade.c (original)
+++ subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/upgrade.c Thu Feb 10 20:04:43 2022
@@ -1078,6 +1078,7 @@ migrate_text_bases(apr_hash_t **text_bas
SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, iterpool));
SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, md5_checksum, iterpool));
SVN_ERR(svn_sqlite__bind_int64(stmt, 3, finfo.size));
+ SVN_ERR(svn_sqlite__bind_int(stmt, 4, TRUE));
SVN_ERR(svn_sqlite__insert(NULL, stmt));
SVN_ERR(svn_wc__db_pristine_get_future_path(&pristine_path,
Modified: subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/util.c?rev=1897946&r1=1897945&r2=1897946&view=diff
==============================================================================
--- subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/util.c (original)
+++ subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/util.c Thu Feb 10 20:04:43 2022
@@ -37,6 +37,7 @@
#include "wc.h" /* just for prototypes of things in this .c file */
#include "entries.h"
+#include "textbase.h"
#include "private/svn_wc_private.h"
#include "svn_private_config.h"
@@ -505,8 +506,9 @@ svn_wc__fetch_base_func(const char **fil
return SVN_NO_ERROR;
}
- SVN_ERR(svn_wc__db_pristine_get_path(filename, sfb->db, local_abspath,
- checksum, scratch_pool, scratch_pool));
+ SVN_ERR(svn_wc__textbase_setaside(filename, sfb->db, local_abspath,
+ checksum, NULL, NULL,
+ result_pool, scratch_pool));
return SVN_NO_ERROR;
}
Modified: subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/wc-metadata.sql
URL: http://svn.apache.org/viewvc/subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/wc-metadata.sql?rev=1897946&r1=1897945&r2=1897946&view=diff
==============================================================================
--- subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/wc-metadata.sql (original)
+++ subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/wc-metadata.sql Thu Feb 10 20:04:43 2022
@@ -570,6 +570,7 @@ CREATE UNIQUE INDEX I_EXTERNALS_DEFINED
def_local_relpath,
local_relpath);
+/* ------------------------------------------------------------------------- */
/* Identify the WC format corresponding to the schema we have created. */
PRAGMA user_version =
@@ -706,12 +707,84 @@ WHERE l.op_depth = 0
AND ((l.repos_id IS NOT r.repos_id)
OR (l.repos_path IS NOT RELPATH_SKIP_JOIN(r.local_relpath, r.repos_path, l.local_relpath)))
-
/* ------------------------------------------------------------------------- */
-/* Format 32 .... */
+
+/* Format 32 adds support for optional text-base contents with the
+ following schema changes:
+ - Add the 'hydrated' column to the PRISTINE table.
+ - Add the I_PRISTINE_UNREFERENCED index.
+ - Add the TEXTBASE_REFS table. */
-- STMT_UPGRADE_TO_32
+/* True iff the pristine contents are currently available on disk. */
+ALTER TABLE PRISTINE ADD COLUMN hydrated INTEGER NOT NULL DEFAULT 1;
+
+ /* Note: we use checksums to detect if the file contents have been modified
+ in textbase.c and in the svn_wc__internal_file_modified_p() function.
+
+ The new working copy format SHOULD incorporate a switch to a different
+ checksum type without known collisions.
+
+ For the updated pristine table schema, we MAY want to add a new column
+ containing a checksum of the first 8KB of the file to allow saying that
+ the file is modified without reading all its content. That could speed
+ up the check for large modified files whose size did not change, for
+ example if they are allocated in certain extents.
+ */
+
+CREATE INDEX I_PRISTINE_UNREFERENCED ON PRISTINE (refcount, refcount=0);
+
+/* This table contains references to the on disk text-base contents.
+ Every row corresponds to a row in NODES table with the same key.
+ While a row is present is this table, the contents identified by the
+ corresponding NODES.checksum cannot be dehydrated from the pristine store.
+ */
+CREATE TABLE TEXTBASE_REFS (
+ /* Same key columns as in the NODES table */
+ wc_id INTEGER NOT NULL,
+ local_relpath TEXT NOT NULL,
+ op_depth INTEGER NOT NULL,
+
+ PRIMARY KEY (wc_id, local_relpath, op_depth)
+ );
+
+DROP TRIGGER nodes_delete_trigger;
+
+CREATE TRIGGER nodes_delete_trigger
+AFTER DELETE ON nodes
+WHEN OLD.checksum IS NOT NULL
+BEGIN
+ UPDATE pristine SET refcount = refcount - 1
+ WHERE checksum = OLD.checksum;
+ DELETE FROM textbase_refs
+ WHERE wc_id = OLD.wc_id
+ AND local_relpath = OLD.local_relpath
+ AND op_depth = OLD.op_depth;
+END;
+
+DROP TRIGGER nodes_update_checksum_trigger;
+
+CREATE TRIGGER nodes_update_checksum_trigger
+AFTER UPDATE OF checksum ON nodes
+WHEN NEW.checksum IS NOT OLD.checksum
+ /* AND (NEW.checksum IS NOT NULL OR OLD.checksum IS NOT NULL) */
+BEGIN
+ UPDATE pristine SET refcount = refcount + 1
+ WHERE checksum = NEW.checksum;
+ UPDATE pristine SET refcount = refcount - 1
+ WHERE checksum = OLD.checksum;
+ DELETE FROM textbase_refs
+ WHERE wc_id = OLD.wc_id
+ AND local_relpath = OLD.local_relpath
+ AND op_depth = OLD.op_depth;
+END;
+
PRAGMA user_version = 32;
+/* ------------------------------------------------------------------------- */
+/* Format 33 .... */
+/* -- STMT_UPGRADE_TO_33
+PRAGMA user_version = 33; */
+
/* ------------------------------------------------------------------------- */
Modified: subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/wc-queries.sql?rev=1897946&r1=1897945&r2=1897946&view=diff
==============================================================================
--- subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/wc-queries.sql Thu Feb 10 20:04:43 2022
@@ -884,23 +884,22 @@ SELECT id, work FROM work_queue ORDER BY
DELETE FROM work_queue WHERE id = ?1
-- STMT_INSERT_OR_IGNORE_PRISTINE
-INSERT OR IGNORE INTO pristine (checksum, md5_checksum, size, refcount)
-VALUES (?1, ?2, ?3, 0)
+INSERT OR IGNORE INTO pristine (checksum, md5_checksum, size, refcount, hydrated)
+VALUES (?1, ?2, ?3, 0, ?4)
--- STMT_INSERT_PRISTINE
-INSERT INTO pristine (checksum, md5_checksum, size, refcount)
-VALUES (?1, ?2, ?3, 0)
+-- STMT_UPSERT_PRISTINE
+/* ### Probably need to bump the minimum SQLite version for UPSERT support
+ https://www.sqlite.org/lang_UPSERT.html
+ */
+INSERT INTO pristine (checksum, md5_checksum, size, refcount, hydrated)
+VALUES (?1, ?2, ?3, 0, ?4)
+ON CONFLICT(checksum) DO UPDATE SET size=?3, hydrated=?4
-- STMT_SELECT_PRISTINE
-SELECT md5_checksum
+SELECT md5_checksum, size, hydrated
FROM pristine
WHERE checksum = ?1
--- STMT_SELECT_PRISTINE_SIZE
-SELECT size
-FROM pristine
-WHERE checksum = ?1 LIMIT 1
-
-- STMT_SELECT_PRISTINE_BY_MD5
SELECT checksum
FROM pristine
@@ -917,7 +916,7 @@ WHERE checksum = ?1 AND refcount = 0
-- STMT_SELECT_COPY_PRISTINES
/* For the root itself */
-SELECT n.checksum, md5_checksum, size
+SELECT n.checksum, md5_checksum, size, p.hydrated
FROM nodes_current n
LEFT JOIN pristine p ON n.checksum = p.checksum
WHERE wc_id = ?1
@@ -925,7 +924,7 @@ WHERE wc_id = ?1
AND n.checksum IS NOT NULL
UNION ALL
/* And all descendants */
-SELECT n.checksum, md5_checksum, size
+SELECT n.checksum, md5_checksum, size, p.hydrated
FROM nodes n
LEFT JOIN pristine p ON n.checksum = p.checksum
WHERE wc_id = ?1
@@ -934,6 +933,10 @@ WHERE wc_id = ?1
(SELECT MAX(op_depth) FROM nodes WHERE wc_id = ?1 AND local_relpath = ?2)
AND n.checksum IS NOT NULL
+-- STMT_UPDATE_PRISTINE_HYDRATED
+UPDATE pristine SET hydrated = ?2
+WHERE checksum = ?1
+
-- STMT_VACUUM
VACUUM
@@ -1812,6 +1815,53 @@ SELECT lock_token, lock_owner, lock_comm
FROM lock
WHERE repos_id = ?1 AND (repos_relpath = ?2)
+-- STMT_TEXTBASE_ADD_REF
+INSERT OR IGNORE INTO textbase_refs (wc_id, local_relpath, op_depth)
+VALUES (?1, ?2, ?3)
+
+-- STMT_TEXTBASE_REMOVE_REF
+DELETE FROM textbase_refs
+WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?3
+
+-- STMT_TEXTBASE_WALK
+SELECT refs.wc_id IS NOT NULL,
+ nodes.local_relpath, nodes.op_depth,
+ nodes.checksum, nodes.properties,
+ nodes.translated_size, nodes.last_mod_time,
+ (SELECT properties FROM ACTUAL_NODE a
+ WHERE a.wc_id = ?1
+ AND a.local_relpath = nodes.local_relpath
+ LIMIT 1),
+ (SELECT MAX(op_depth)
+ FROM NODES w
+ WHERE w.wc_id = ?1
+ AND w.local_relpath = nodes.local_relpath)
+FROM nodes
+LEFT OUTER JOIN textbase_refs refs ON nodes.wc_id = refs.wc_id
+ AND nodes.local_relpath = refs.local_relpath
+ AND nodes.op_depth = refs.op_depth
+WHERE nodes.wc_id = ?1
+ AND (nodes.local_relpath = ?2
+ OR IS_STRICT_DESCENDANT_OF(nodes.local_relpath, ?2))
+ AND nodes.checksum IS NOT NULL
+
+-- STMT_TEXTBASE_SYNC
+SELECT pristine.checksum,
+ MIN(pristine.hydrated != 0),
+ MAX(refs.wc_id IS NOT NULL),
+ nodes.repos_path, nodes.repos_id, nodes.revision
+FROM nodes
+JOIN pristine ON nodes.wc_id = ?1
+ AND nodes.checksum = pristine.checksum
+ AND (nodes.local_relpath = ?2
+ OR IS_STRICT_DESCENDANT_OF(nodes.local_relpath, ?2))
+LEFT OUTER JOIN textbase_refs refs ON nodes.wc_id = refs.wc_id
+ AND nodes.local_relpath = refs.local_relpath
+ AND nodes.op_depth = refs.op_depth
+GROUP BY pristine.checksum
+UNION ALL
+SELECT pristine.checksum, pristine.hydrated, 0, NULL, NULL, NULL
+FROM pristine WHERE refcount = 0
/* ------------------------------------------------------------------------- */
Modified: subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/wc_db.h?rev=1897946&r1=1897945&r2=1897946&view=diff
==============================================================================
--- subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/wc_db.h Thu Feb 10 20:04:43 2022
@@ -927,21 +927,6 @@ svn_wc__db_base_get_lock_tokens_recursiv
@{
*/
-/* Set *PRISTINE_ABSPATH to the path to the pristine text file
- identified by SHA1_CHECKSUM. Error if it does not exist.
-
- ### This is temporary - callers should not be looking at the file
- directly.
-
- Allocate the path in RESULT_POOL. */
-svn_error_t *
-svn_wc__db_pristine_get_path(const char **pristine_abspath,
- svn_wc__db_t *db,
- const char *wri_abspath,
- const svn_checksum_t *checksum,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool);
-
/* Set *PRISTINE_ABSPATH to the path under WCROOT_ABSPATH that will be
used by the pristine text identified by SHA1_CHECKSUM. The file
need not exist.
@@ -986,6 +971,8 @@ typedef struct svn_wc__db_install_data_t
set to the MD-5 and SHA-1 checksums respectively of that file.
MD5_CHECKSUM and/or SHA1_CHECKSUM may be NULL if not wanted.
+ If HYDRATED is true, the contents of the pristine will be saved to disk.
+
Allocate the new stream, path and checksums in RESULT_POOL.
*/
svn_error_t *
@@ -995,6 +982,7 @@ svn_wc__db_pristine_prepare_install(svn_
svn_checksum_t **md5_checksum,
svn_wc__db_t *db,
const char *wri_abspath,
+ svn_boolean_t hydrated,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
@@ -1077,14 +1065,26 @@ svn_wc__db_pristine_cleanup(svn_wc__db_t
/* Set *PRESENT to true if the pristine store for WRI_ABSPATH in DB contains
a pristine text with SHA-1 checksum SHA1_CHECKSUM, and to false otherwise.
-*/
+ If the pristine is present, set *HYDRATED to true if its contents are
+ currently available on disk, and to false otherwise. If the pristine
+ is not present, set *HYDRATED to false. */
svn_error_t *
svn_wc__db_pristine_check(svn_boolean_t *present,
+ svn_boolean_t *hydrated,
svn_wc__db_t *db,
const char *wri_abspath,
const svn_checksum_t *sha1_checksum,
apr_pool_t *scratch_pool);
+/* If the pristine store for WRI_ABSPATH in DB contains a pristine text with
+ SHA-1 checksum SHA1_CHECKSUM with its content available on disk, remove
+ that content and mark the pristine entry as "dehydrated". */
+svn_error_t *
+svn_wc__db_pristine_dehydrate(svn_wc__db_t *db,
+ const char *wri_abspath,
+ const svn_checksum_t *sha1_checksum,
+ apr_pool_t *scratch_pool);
+
/* @defgroup svn_wc__db_external External management
@{ */
@@ -3121,6 +3121,77 @@ svn_wc__db_wclock_owns_lock(svn_boolean_
svn_boolean_t exact,
apr_pool_t *scratch_pool);
+/* @} */
+
+
+/* @defgroup svn_wc__db_textbase Working with text-bases
+ @{
+*/
+
+/* The callback invoked by svn_wc__db_textbase_walk(). */
+typedef svn_error_t * (*svn_wc__db_textbase_walk_cb_t)(
+ svn_boolean_t *referenced_p,
+ void *baton,
+ const char *local_abspath,
+ int op_depth,
+ const svn_checksum_t *checksum,
+ svn_boolean_t have_props,
+ svn_boolean_t props_mod,
+ svn_filesize_t recorded_size,
+ apr_time_t recorded_time,
+ int max_op_depth,
+ apr_pool_t *scratch_pool);
+
+/* Walk the text-bases referenced by the nodes in the LOCAL_ABSPATH
+ tree, invoking the CALLBACK with information about each text-base
+ for a node.
+
+ If the callback sets *REFERENCED_P to true, ensure that a text-base
+ reference exists for the node. If the callback sets *REFERENCED_P to
+ false, ensure that a text-base reference does not exist for the node.
+
+ See the description of the `TEXTBASE_REFS` table in the schema.
+ */
+svn_error_t *
+svn_wc__db_textbase_walk(svn_wc__db_t *db,
+ const char *local_abspath,
+ svn_wc__db_textbase_walk_cb_t callback,
+ void *callback_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool);
+
+/* The callback invoked by svn_wc__db_textbase_sync(). */
+typedef svn_error_t * (*svn_wc__db_textbase_hydrate_cb_t)(
+ void *baton,
+ const char *repos_root_url,
+ const char *repos_relpath,
+ svn_revnum_t revision,
+ svn_stream_t *contents,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool);
+
+/* Synchronize the state of the text-bases in DB.
+
+ If ALLOW_HYDRATE is true, fetch the referenced but missing text-base
+ contents using the provided HYDRATE_CALLBACK and HYDRATE_BATON.
+ If ALLOW_DEHYDRATE is true, remove the on disk text-base contents
+ that is no longer referenced.
+ */
+svn_error_t *
+svn_wc__db_textbase_sync(svn_wc__db_t *db,
+ const char *local_abspath,
+ svn_boolean_t allow_hydrate,
+ svn_boolean_t allow_dehydrate,
+ svn_wc__db_textbase_hydrate_cb_t hydrate_callback,
+ void *hydrate_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool);
+
+
+/* @} */
/* @defgroup svn_wc__db_temp Various temporary functions during transition
Modified: subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/wc_db_pristine.c
URL: http://svn.apache.org/viewvc/subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/wc_db_pristine.c?rev=1897946&r1=1897945&r2=1897946&view=diff
==============================================================================
--- subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/wc_db_pristine.c (original)
+++ subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/wc_db_pristine.c Thu Feb 10 20:04:43 2022
@@ -94,50 +94,6 @@ get_pristine_fname(const char **pristine
svn_error_t *
-svn_wc__db_pristine_get_path(const char **pristine_abspath,
- svn_wc__db_t *db,
- const char *wri_abspath,
- const svn_checksum_t *sha1_checksum,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- svn_wc__db_wcroot_t *wcroot;
- const char *local_relpath;
- svn_boolean_t present;
-
- SVN_ERR_ASSERT(pristine_abspath != NULL);
- SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
- SVN_ERR_ASSERT(sha1_checksum != NULL);
- /* ### Transitional: accept MD-5 and look up the SHA-1. Return an error
- * if the pristine text is not in the store. */
- if (sha1_checksum->kind != svn_checksum_sha1)
- SVN_ERR(svn_wc__db_pristine_get_sha1(&sha1_checksum, db, wri_abspath,
- sha1_checksum,
- scratch_pool, scratch_pool));
- SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
-
- SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath,
- db, wri_abspath,
- scratch_pool, scratch_pool));
- VERIFY_USABLE_WCROOT(wcroot);
-
- SVN_ERR(svn_wc__db_pristine_check(&present, db, wri_abspath, sha1_checksum,
- scratch_pool));
- if (! present)
- return svn_error_createf(SVN_ERR_WC_DB_ERROR, NULL,
- _("The pristine text with checksum '%s' was "
- "not found"),
- svn_checksum_to_cstring_display(sha1_checksum,
- scratch_pool));
-
- SVN_ERR(get_pristine_fname(pristine_abspath, wcroot->abspath,
- sha1_checksum,
- result_pool, scratch_pool));
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
svn_wc__db_pristine_get_future_path(const char **pristine_abspath,
const char *wcroot_abspath,
const svn_checksum_t *sha1_checksum,
@@ -152,9 +108,10 @@ svn_wc__db_pristine_get_future_path(cons
/* Set *CONTENTS to a readable stream from which the pristine text
* identified by SHA1_CHECKSUM and PRISTINE_ABSPATH can be read from the
- * pristine store of WCROOT. If SIZE is not null, set *SIZE to the size
- * in bytes of that text. If that text is not in the pristine store,
- * return an error.
+ * pristine store of WCROOT. If the pristine contents are currently not
+ * available on disk, set *CONTENTS to NULL. If SIZE is not null, set
+ * *SIZE to the size in bytes of that text. If that text is not in
+ * the pristine store, return an error.
*
* Even if the pristine text is removed from the store while it is being
* read, the stream will remain valid and readable until it is closed.
@@ -176,16 +133,18 @@ pristine_read_txn(svn_stream_t **content
{
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
+ svn_boolean_t hydrated;
/* Check that this pristine text is present in the store. (The presence
* of the file is not sufficient.) */
- SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_SELECT_PRISTINE_SIZE));
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_PRISTINE));
SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
if (size)
- *size = svn_sqlite__column_int64(stmt, 0);
+ *size = svn_sqlite__column_int64(stmt, 1);
+
+ hydrated = svn_sqlite__column_boolean(stmt, 2);
SVN_ERR(svn_sqlite__reset(stmt));
if (! have_row)
@@ -196,19 +155,27 @@ pristine_read_txn(svn_stream_t **content
sha1_checksum, scratch_pool));
}
- /* Open the file as a readable stream. It will remain readable even when
- * deleted from disk; APR guarantees that on Windows as well as Unix.
- *
- * We also don't enable APR_BUFFERED on this file to maximize throughput
- * e.g. for fulltext comparison. As we use SVN__STREAM_CHUNK_SIZE buffers
- * where needed in streams, there is no point in having another layer of
- * buffers. */
if (contents)
{
- apr_file_t *file;
- SVN_ERR(svn_io_file_open(&file, pristine_abspath, APR_READ,
- APR_OS_DEFAULT, result_pool));
- *contents = svn_stream_from_aprfile2(file, FALSE, result_pool);
+ if (hydrated)
+ {
+ /* Open the file as a readable stream. It will remain readable even when
+ * deleted from disk; APR guarantees that on Windows as well as Unix.
+ *
+ * We also don't enable APR_BUFFERED on this file to maximize throughput
+ * e.g. for fulltext comparison. As we use SVN__STREAM_CHUNK_SIZE buffers
+ * where needed in streams, there is no point in having another layer of
+ * buffers. */
+
+ apr_file_t *file;
+ SVN_ERR(svn_io_file_open(&file, pristine_abspath, APR_READ,
+ APR_OS_DEFAULT, result_pool));
+ *contents = svn_stream_from_aprfile2(file, FALSE, result_pool);
+ }
+ else
+ {
+ *contents = NULL;
+ }
}
return SVN_NO_ERROR;
@@ -256,6 +223,53 @@ svn_wc__db_pristine_read(svn_stream_t **
}
+struct svn_wc__db_install_data_t
+{
+ svn_wc__db_wcroot_t *wcroot;
+ svn_stream_t *inner_stream;
+ apr_off_t size;
+};
+
+static svn_error_t *
+install_stream_write_fn(void *baton, const char *data, apr_size_t *len)
+{
+ svn_wc__db_install_data_t *install_data = baton;
+
+ if (install_data->inner_stream)
+ SVN_ERR(svn_stream_write(install_data->inner_stream, data, len));
+
+ install_data->size += *len;
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+install_stream_seek_fn(void *baton, const svn_stream_mark_t *mark)
+{
+ svn_wc__db_install_data_t *install_data = baton;
+
+ if (!mark)
+ return svn_error_create(SVN_ERR_STREAM_SEEK_NOT_SUPPORTED, NULL, NULL);
+
+ if (install_data->inner_stream)
+ SVN_ERR(svn_stream_reset(install_data->inner_stream));
+
+ install_data->size = 0;
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+install_stream_close_fn(void *baton)
+{
+ svn_wc__db_install_data_t *install_data = baton;
+
+ if (install_data->inner_stream)
+ SVN_ERR(svn_stream_close(install_data->inner_stream));
+
+ return SVN_NO_ERROR;
+}
+
/* Return the absolute path to the temporary directory for pristine text
files within WCROOT. */
static char *
@@ -268,9 +282,8 @@ pristine_get_tempdir(svn_wc__db_wcroot_t
PRISTINE_TEMPDIR_RELPATH, SVN_VA_NULL);
}
-/* Install the pristine text described by BATON into the pristine store of
- * SDB. If it is already stored then just delete the new file
- * BATON->tempfile_abspath.
+/* Install the pristine text described by INSTALL_DATA into the pristine store
+ * of SDB.
*
* This function expects to be executed inside a SQLite txn that has already
* acquired a 'RESERVED' lock.
@@ -279,8 +292,7 @@ pristine_get_tempdir(svn_wc__db_wcroot_t
*/
static svn_error_t *
pristine_install_txn(svn_sqlite__db_t *sdb,
- /* The path to the source file that is to be moved into place. */
- svn_stream_t *install_stream,
+ svn_wc__db_install_data_t *install_data,
/* The target path for the file (within the pristine store). */
const char *pristine_abspath,
/* The pristine text's SHA-1 checksum. */
@@ -289,85 +301,73 @@ pristine_install_txn(svn_sqlite__db_t *s
const svn_checksum_t *md5_checksum,
apr_pool_t *scratch_pool)
{
+ svn_stream_t *install_stream = install_data->inner_stream;
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
+ svn_boolean_t hydrated;
- /* If this pristine text is already present in the store, just keep it:
- * delete the new one and return. */
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_PRISTINE));
SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
- SVN_ERR(svn_sqlite__reset(stmt));
if (have_row)
+ hydrated = svn_sqlite__column_boolean(stmt, 2);
+ else
+ hydrated = FALSE;
+
+ SVN_ERR(svn_sqlite__reset(stmt));
+
+ if (have_row && hydrated)
{
-#ifdef SVN_DEBUG
- /* Consistency checks. Verify both files exist and match.
- * ### We could check much more. */
- {
- apr_finfo_t finfo;
- apr_off_t size;
-
- SVN_ERR(svn_stream__install_finalize(NULL, &size, install_stream,
- scratch_pool));
-
- SVN_ERR(svn_io_stat(&finfo, pristine_abspath, APR_FINFO_SIZE,
- scratch_pool));
- if (size != finfo.size)
- {
- return svn_error_createf(
- SVN_ERR_WC_CORRUPT_TEXT_BASE, NULL,
- _("New pristine text '%s' has different size: %s versus %s"),
- svn_checksum_to_cstring_display(sha1_checksum, scratch_pool),
- apr_off_t_toa(scratch_pool, size),
- apr_off_t_toa(scratch_pool, finfo.size));
- }
- }
-#endif
+ /* For now, ensure that we do not inadvertently dehydrate an existing
+ * hydrated entry, as there could be references to its content. */
+
+ if (install_stream)
+ SVN_ERR(svn_stream__install_delete(install_stream, scratch_pool));
- /* Remove the temp file: it's already there */
- SVN_ERR(svn_stream__install_delete(install_stream, scratch_pool));
return SVN_NO_ERROR;
}
- /* Move the file to its target location. (If it is already there, it is
- * an orphan file and it doesn't matter if we overwrite it.) */
- {
- apr_off_t size;
+ if (install_stream)
+ {
+ /* Move the file to its target location. (If it is already there, it is
+ * an orphan file and it doesn't matter if we overwrite it.) */
- svn_stream__install_set_read_only(install_stream, TRUE);
+ svn_stream__install_set_read_only(install_stream, TRUE);
- SVN_ERR(svn_stream__install_finalize(NULL, &size, install_stream,
- scratch_pool));
- SVN_ERR(svn_stream__install_stream(install_stream, pristine_abspath,
- TRUE, scratch_pool));
-
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_INSERT_PRISTINE));
- SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
- SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, md5_checksum, scratch_pool));
- SVN_ERR(svn_sqlite__bind_int64(stmt, 3, size));
- SVN_ERR(svn_sqlite__insert(NULL, stmt));
- }
+ SVN_ERR(svn_stream__install_finalize(NULL, NULL, install_stream,
+ scratch_pool));
+ SVN_ERR(svn_stream__install_stream(install_stream, pristine_abspath,
+ TRUE, scratch_pool));
+ }
+ else
+ {
+ SVN_ERR(svn_io_remove_file2(pristine_abspath, TRUE, scratch_pool));
+ }
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_UPSERT_PRISTINE));
+ SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
+ SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, md5_checksum, scratch_pool));
+ SVN_ERR(svn_sqlite__bind_int64(stmt, 3, install_data->size));
+ SVN_ERR(svn_sqlite__bind_int(stmt, 4, install_stream != NULL));
+ SVN_ERR(svn_sqlite__insert(NULL, stmt));
return SVN_NO_ERROR;
}
-struct svn_wc__db_install_data_t
-{
- svn_wc__db_wcroot_t *wcroot;
- svn_stream_t *inner_stream;
-};
-
svn_error_t *
-svn_wc__db_pristine_prepare_install(svn_stream_t **stream,
- svn_wc__db_install_data_t **install_data,
- svn_checksum_t **sha1_checksum,
- svn_checksum_t **md5_checksum,
+svn_wc__db_pristine_prepare_install(svn_stream_t **stream_p,
+ svn_wc__db_install_data_t **install_data_p,
+ svn_checksum_t **sha1_checksum_p,
+ svn_checksum_t **md5_checksum_p,
svn_wc__db_t *db,
const char *wri_abspath,
+ svn_boolean_t hydrated,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
+ svn_stream_t *stream;
+ svn_wc__db_install_data_t *install_data;
svn_wc__db_wcroot_t *wcroot;
const char *local_relpath;
const char *temp_dir_abspath;
@@ -380,22 +380,37 @@ svn_wc__db_pristine_prepare_install(svn_
temp_dir_abspath = pristine_get_tempdir(wcroot, scratch_pool, scratch_pool);
- *install_data = apr_pcalloc(result_pool, sizeof(**install_data));
- (*install_data)->wcroot = wcroot;
+ install_data = apr_pcalloc(result_pool, sizeof(*install_data));
+ install_data->wcroot = wcroot;
+
+ if (hydrated)
+ {
+ SVN_ERR_W(svn_stream__create_for_install(&install_data->inner_stream,
+ temp_dir_abspath,
+ result_pool, scratch_pool),
+ _("Unable to create pristine install stream"));
+ }
+ else
+ {
+ install_data->inner_stream = NULL;
+ }
+
+ install_data->size = 0;
+
+ stream = svn_stream_create(install_data, result_pool);
+ svn_stream_set_write(stream, install_stream_write_fn);
+ svn_stream_set_seek(stream, install_stream_seek_fn);
+ svn_stream_set_close(stream, install_stream_close_fn);
+
+ if (md5_checksum_p)
+ stream = svn_stream_checksummed2(stream, NULL, md5_checksum_p,
+ svn_checksum_md5, FALSE, result_pool);
+ if (sha1_checksum_p)
+ stream = svn_stream_checksummed2(stream, NULL, sha1_checksum_p,
+ svn_checksum_sha1, FALSE, result_pool);
- SVN_ERR_W(svn_stream__create_for_install(stream,
- temp_dir_abspath,
- result_pool, scratch_pool),
- _("Unable to create pristine install stream"));
-
- (*install_data)->inner_stream = *stream;
-
- if (md5_checksum)
- *stream = svn_stream_checksummed2(*stream, NULL, md5_checksum,
- svn_checksum_md5, FALSE, result_pool);
- if (sha1_checksum)
- *stream = svn_stream_checksummed2(*stream, NULL, sha1_checksum,
- svn_checksum_sha1, FALSE, result_pool);
+ *stream_p = stream;
+ *install_data_p = install_data;
return SVN_NO_ERROR;
}
@@ -422,7 +437,7 @@ svn_wc__db_pristine_install(svn_wc__db_i
* at the disk, to ensure no concurrent pristine install/delete txn. */
SVN_SQLITE__WITH_IMMEDIATE_TXN(
pristine_install_txn(wcroot->sdb,
- install_data->inner_stream, pristine_abspath,
+ install_data, pristine_abspath,
sha1_checksum, md5_checksum,
scratch_pool),
wcroot->sdb);
@@ -434,8 +449,12 @@ svn_error_t *
svn_wc__db_pristine_install_abort(svn_wc__db_install_data_t *install_data,
apr_pool_t *scratch_pool)
{
- return svn_error_trace(svn_stream__install_delete(install_data->inner_stream,
- scratch_pool));
+ if (install_data->inner_stream)
+ SVN_ERR(svn_stream__install_delete(install_data->inner_stream, scratch_pool));
+
+ install_data->size = 0;
+
+ return SVN_NO_ERROR;
}
@@ -516,84 +535,91 @@ svn_wc__db_pristine_get_sha1(const svn_c
}
/* Handle the moving of a pristine from SRC_WCROOT to DST_WCROOT. The existing
- pristine in SRC_WCROOT is described by CHECKSUM, MD5_CHECKSUM and SIZE */
+ pristine in SRC_WCROOT is described by CHECKSUM, MD5_CHECKSUM, SIZE and
+ HYDRATED. */
static svn_error_t *
maybe_transfer_one_pristine(svn_wc__db_wcroot_t *src_wcroot,
svn_wc__db_wcroot_t *dst_wcroot,
const svn_checksum_t *checksum,
const svn_checksum_t *md5_checksum,
apr_int64_t size,
+ svn_boolean_t hydrated,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *scratch_pool)
{
- const char *pristine_abspath;
svn_sqlite__stmt_t *stmt;
- svn_stream_t *src_stream;
- svn_stream_t *dst_stream;
- const char *tmp_abspath;
- const char *src_abspath;
int affected_rows;
- svn_error_t *err;
SVN_ERR(svn_sqlite__get_statement(&stmt, dst_wcroot->sdb,
STMT_INSERT_OR_IGNORE_PRISTINE));
SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, checksum, scratch_pool));
SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, md5_checksum, scratch_pool));
SVN_ERR(svn_sqlite__bind_int64(stmt, 3, size));
+ SVN_ERR(svn_sqlite__bind_int(stmt, 4, hydrated));
SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
if (affected_rows == 0)
return SVN_NO_ERROR;
- SVN_ERR(svn_stream_open_unique(&dst_stream, &tmp_abspath,
- pristine_get_tempdir(dst_wcroot,
- scratch_pool,
- scratch_pool),
- svn_io_file_del_on_pool_cleanup,
- scratch_pool, scratch_pool));
+ if (hydrated)
+ {
+ const char *pristine_abspath;
+ svn_stream_t *src_stream;
+ svn_stream_t *dst_stream;
+ const char *tmp_abspath;
+ const char *src_abspath;
+ svn_error_t *err;
- SVN_ERR(get_pristine_fname(&src_abspath, src_wcroot->abspath, checksum,
- scratch_pool, scratch_pool));
+ SVN_ERR(svn_stream_open_unique(&dst_stream, &tmp_abspath,
+ pristine_get_tempdir(dst_wcroot,
+ scratch_pool,
+ scratch_pool),
+ svn_io_file_del_on_pool_cleanup,
+ scratch_pool, scratch_pool));
- SVN_ERR(svn_stream_open_readonly(&src_stream, src_abspath,
- scratch_pool, scratch_pool));
+ SVN_ERR(get_pristine_fname(&src_abspath, src_wcroot->abspath, checksum,
+ scratch_pool, scratch_pool));
- /* ### Should we verify the SHA1 or MD5 here, or is that too expensive? */
- SVN_ERR(svn_stream_copy3(src_stream, dst_stream,
- cancel_func, cancel_baton,
- scratch_pool));
+ SVN_ERR(svn_stream_open_readonly(&src_stream, src_abspath,
+ scratch_pool, scratch_pool));
- SVN_ERR(get_pristine_fname(&pristine_abspath, dst_wcroot->abspath, checksum,
- scratch_pool, scratch_pool));
+ /* ### Should we verify the SHA1 or MD5 here, or is that too expensive? */
+ SVN_ERR(svn_stream_copy3(src_stream, dst_stream,
+ cancel_func, cancel_baton,
+ scratch_pool));
- /* Move the file to its target location. (If it is already there, it is
- * an orphan file and it doesn't matter if we overwrite it.) */
- err = svn_io_file_rename2(tmp_abspath, pristine_abspath, FALSE,
- scratch_pool);
-
- /* Maybe the directory doesn't exist yet? */
- if (err && APR_STATUS_IS_ENOENT(err->apr_err))
- {
- svn_error_t *err2;
-
- err2 = svn_io_dir_make(svn_dirent_dirname(pristine_abspath,
- scratch_pool),
- APR_OS_DEFAULT, scratch_pool);
-
- if (err2)
- /* Creating directory didn't work: Return all errors */
- return svn_error_trace(svn_error_compose_create(err, err2));
- else
- /* We could create a directory: retry install */
- svn_error_clear(err);
+ SVN_ERR(get_pristine_fname(&pristine_abspath, dst_wcroot->abspath, checksum,
+ scratch_pool, scratch_pool));
- SVN_ERR(svn_io_file_rename2(tmp_abspath, pristine_abspath, FALSE,
- scratch_pool));
+ /* Move the file to its target location. (If it is already there, it is
+ * an orphan file and it doesn't matter if we overwrite it.) */
+ err = svn_io_file_rename2(tmp_abspath, pristine_abspath, FALSE,
+ scratch_pool);
+
+ /* Maybe the directory doesn't exist yet? */
+ if (err && APR_STATUS_IS_ENOENT(err->apr_err))
+ {
+ svn_error_t *err2;
+
+ err2 = svn_io_dir_make(svn_dirent_dirname(pristine_abspath,
+ scratch_pool),
+ APR_OS_DEFAULT, scratch_pool);
+
+ if (err2)
+ /* Creating directory didn't work: Return all errors */
+ return svn_error_trace(svn_error_compose_create(err, err2));
+ else
+ /* We could create a directory: retry install */
+ svn_error_clear(err);
+
+ SVN_ERR(svn_io_file_rename2(tmp_abspath, pristine_abspath, FALSE,
+ scratch_pool));
+ }
+ else
+ SVN_ERR(err);
}
- else
- SVN_ERR(err);
return SVN_NO_ERROR;
}
@@ -625,6 +651,7 @@ pristine_transfer_txn(svn_wc__db_wcroot_
const svn_checksum_t *checksum;
const svn_checksum_t *md5_checksum;
apr_int64_t size;
+ svn_boolean_t hydrated;
svn_error_t *err;
svn_pool_clear(iterpool);
@@ -632,9 +659,11 @@ pristine_transfer_txn(svn_wc__db_wcroot_
SVN_ERR(svn_sqlite__column_checksum(&checksum, stmt, 0, iterpool));
SVN_ERR(svn_sqlite__column_checksum(&md5_checksum, stmt, 1, iterpool));
size = svn_sqlite__column_int64(stmt, 2);
+ hydrated = svn_sqlite__column_boolean(stmt, 3);
err = maybe_transfer_one_pristine(src_wcroot, dst_wcroot,
checksum, md5_checksum, size,
+ hydrated,
cancel_func, cancel_baton,
iterpool);
@@ -714,19 +743,7 @@ pristine_remove_if_unreferenced_txn(svn_
/* If we removed the DB row, then remove the file. */
if (affected_rows > 0)
- {
- /* If the file is not present, something has gone wrong, but at this
- * point it no longer matters. In a debug build, raise an error, but
- * in a release build, it is more helpful to ignore it and continue. */
-#ifdef SVN_DEBUG
- svn_boolean_t ignore_enoent = FALSE;
-#else
- svn_boolean_t ignore_enoent = TRUE;
-#endif
-
- SVN_ERR(svn_io_remove_file2(pristine_abspath, ignore_enoent,
- scratch_pool));
- }
+ SVN_ERR(svn_io_remove_file2(pristine_abspath, TRUE, scratch_pool));
return SVN_NO_ERROR;
}
@@ -887,6 +904,7 @@ svn_wc__db_pristine_cleanup(svn_wc__db_t
svn_error_t *
svn_wc__db_pristine_check(svn_boolean_t *present,
+ svn_boolean_t *hydrated,
svn_wc__db_t *db,
const char *wri_abspath,
const svn_checksum_t *sha1_checksum,
@@ -903,6 +921,9 @@ svn_wc__db_pristine_check(svn_boolean_t
if (sha1_checksum->kind != svn_checksum_sha1)
{
*present = FALSE;
+ if (hydrated)
+ *hydrated = FALSE;
+
return SVN_NO_ERROR;
}
@@ -910,46 +931,50 @@ svn_wc__db_pristine_check(svn_boolean_t
wri_abspath, scratch_pool, scratch_pool));
VERIFY_USABLE_WCROOT(wcroot);
- /* A filestat is much cheaper than a sqlite transaction especially on NFS,
- so first check if there is a pristine file and then if we are allowed
- to use it. */
- {
- const char *pristine_abspath;
- svn_node_kind_t kind_on_disk;
- svn_error_t *err;
-
- SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
- sha1_checksum, scratch_pool, scratch_pool));
- err = svn_io_check_path(pristine_abspath, &kind_on_disk, scratch_pool);
-#ifdef WIN32
- if (err && err->apr_err == APR_FROM_OS_ERROR(ERROR_ACCESS_DENIED))
- {
- svn_error_clear(err);
- /* Possible race condition: The filename is locked, but there is no
- file or dir with this name. Let's fall back on checking the DB.
-
- This case is triggered by the pristine store tests on deleting
- a file that is still open via another handle, where this other
- handle has a FILE_SHARE_DELETE share mode.
- */
- }
- else
-#endif
- if (err)
- return svn_error_trace(err);
- else if (kind_on_disk != svn_node_file)
- {
- *present = FALSE;
- return SVN_NO_ERROR;
- }
- }
-
/* Check that there is an entry in the PRISTINE table. */
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_PRISTINE));
SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+ if (hydrated)
+ *hydrated = svn_sqlite__column_boolean(stmt, 2);
+
SVN_ERR(svn_sqlite__reset(stmt));
*present = have_row;
return SVN_NO_ERROR;
}
+
+
+svn_error_t *
+svn_wc__db_pristine_dehydrate(svn_wc__db_t *db,
+ const char *wri_abspath,
+ const svn_checksum_t *sha1_checksum,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_wcroot_t *wcroot;
+ const char *local_relpath;
+ const char *pristine_abspath;
+ svn_sqlite__stmt_t *stmt;
+
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
+ SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
+
+ SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
+ wri_abspath, scratch_pool, scratch_pool));
+ VERIFY_USABLE_WCROOT(wcroot);
+
+ SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
+ sha1_checksum,
+ scratch_pool, scratch_pool));
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_UPDATE_PRISTINE_HYDRATED));
+ SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
+ SVN_ERR(svn_sqlite__bind_int(stmt, 2, FALSE));
+ SVN_ERR(svn_sqlite__update(NULL, stmt));
+
+ SVN_ERR(svn_io_remove_file2(pristine_abspath, TRUE, scratch_pool));
+
+ return SVN_NO_ERROR;
+}