summaryrefslogtreecommitdiff
path: root/subversion/libsvn_wc/wc_db_pristine.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_wc/wc_db_pristine.c')
-rw-r--r--subversion/libsvn_wc/wc_db_pristine.c409
1 files changed, 274 insertions, 135 deletions
diff --git a/subversion/libsvn_wc/wc_db_pristine.c b/subversion/libsvn_wc/wc_db_pristine.c
index 762a661..d9dc8f3 100644
--- a/subversion/libsvn_wc/wc_db_pristine.c
+++ b/subversion/libsvn_wc/wc_db_pristine.c
@@ -25,6 +25,7 @@
#define SVN_WC__I_AM_WC_DB
+#include "svn_pools.h"
#include "svn_dirent_uri.h"
#include "wc.h"
@@ -121,7 +122,10 @@ svn_wc__db_pristine_get_path(const char **pristine_abspath,
scratch_pool));
if (! present)
return svn_error_createf(SVN_ERR_WC_DB_ERROR, NULL,
- _("Pristine text not found"));
+ _("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,
@@ -143,43 +147,30 @@ svn_wc__db_pristine_get_future_path(const char **pristine_abspath,
return SVN_NO_ERROR;
}
-/* Data for pristine_read_txn(). */
-typedef struct pristine_read_baton_t
-{
- /* Where to put the result stream. */
- svn_stream_t **contents;
- /* The pristine text's SHA-1 checksum. */
- const svn_checksum_t *sha1_checksum;
- /* The path to the pristine file (within the pristine store). */
- const char *pristine_abspath;
-
- /* Pointer to where to place the size (if requested) */
- svn_filesize_t *size;
-
- /* The pool from which to allocate the result stream. */
- apr_pool_t *result_pool;
-} pristine_read_baton_t;
-
-/* Set (*BATON->contents) to a readable stream from which the pristine text
- * identified by BATON->sha1_checksum can be read from the pristine store of
- * SDB. If that text is not in the pristine store, return an error.
+/* 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.
*
* 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.
*
- * Allocate the stream in BATON->result_pool.
+ * Allocate the stream in RESULT_POOL.
*
* This function expects to be executed inside a SQLite txn.
*
* Implements 'notes/wc-ng/pristine-store' section A-3(d).
- * Implements svn_sqlite__transaction_callback_t. */
+ */
static svn_error_t *
-pristine_read_txn(void *baton,
+pristine_read_txn(svn_stream_t **contents,
+ svn_filesize_t *size,
svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath,
+ const svn_checksum_t *sha1_checksum,
+ const char *pristine_abspath,
+ apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- pristine_read_baton_t *b = baton;
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
@@ -187,11 +178,11 @@ pristine_read_txn(void *baton,
* of the file is not sufficient.) */
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_SELECT_PRISTINE_SIZE));
- SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, b->sha1_checksum, scratch_pool));
+ SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
- if (b->size)
- *b->size = svn_sqlite__column_int64(stmt, 0);
+ if (size)
+ *size = svn_sqlite__column_int64(stmt, 0);
SVN_ERR(svn_sqlite__reset(stmt));
if (! have_row)
@@ -199,14 +190,14 @@ pristine_read_txn(void *baton,
return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
_("Pristine text '%s' not present"),
svn_checksum_to_cstring_display(
- b->sha1_checksum, scratch_pool));
+ 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. */
- if (b->contents)
- SVN_ERR(svn_stream_open_readonly(b->contents, b->pristine_abspath,
- b->result_pool, scratch_pool));
+ if (contents)
+ SVN_ERR(svn_stream_open_readonly(contents, pristine_abspath,
+ result_pool, scratch_pool));
return SVN_NO_ERROR;
}
@@ -221,7 +212,7 @@ svn_wc__db_pristine_read(svn_stream_t **contents,
{
svn_wc__db_wcroot_t *wcroot;
const char *local_relpath;
- pristine_read_baton_t b;
+ const char *pristine_abspath;
SVN_ERR_ASSERT(contents != NULL);
SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
@@ -240,15 +231,14 @@ svn_wc__db_pristine_read(svn_stream_t **contents,
wri_abspath, scratch_pool, scratch_pool));
VERIFY_USABLE_WCROOT(wcroot);
- b.contents = contents;
- b.sha1_checksum = sha1_checksum;
- b.size = size;
- b.result_pool = result_pool;
- SVN_ERR(get_pristine_fname(&b.pristine_abspath, wcroot->abspath,
+ SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
sha1_checksum,
scratch_pool, scratch_pool));
- SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath, pristine_read_txn, &b,
- scratch_pool));
+ SVN_WC__DB_WITH_TXN(
+ pristine_read_txn(contents, size,
+ wcroot, sha1_checksum, pristine_abspath,
+ result_pool, scratch_pool),
+ wcroot);
return SVN_NO_ERROR;
}
@@ -288,20 +278,6 @@ svn_wc__db_pristine_get_tempdir(const char **temp_dir_abspath,
}
-/* Data for pristine_install_txn(). */
-typedef struct pristine_install_baton_t
-{
- /* The path to the source file that is to be moved into place. */
- const char *tempfile_abspath;
- /* The target path for the file (within the pristine store). */
- const char *pristine_abspath;
- /* The pristine text's SHA-1 checksum. */
- const svn_checksum_t *sha1_checksum;
- /* The pristine text's MD-5 checksum. */
- const svn_checksum_t *md5_checksum;
-} pristine_install_baton_t;
-
-
/* 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.
@@ -310,13 +286,19 @@ typedef struct pristine_install_baton_t
* acquired a 'RESERVED' lock.
*
* Implements 'notes/wc-ng/pristine-store' section A-3(a).
- * Implements svn_sqlite__transaction_callback_t. */
+ */
static svn_error_t *
-pristine_install_txn(void *baton,
- svn_sqlite__db_t *sdb,
+pristine_install_txn(svn_sqlite__db_t *sdb,
+ /* The path to the source file that is to be moved into place. */
+ const char *tempfile_abspath,
+ /* The target path for the file (within the pristine store). */
+ const char *pristine_abspath,
+ /* The pristine text's SHA-1 checksum. */
+ const svn_checksum_t *sha1_checksum,
+ /* The pristine text's MD-5 checksum. */
+ const svn_checksum_t *md5_checksum,
apr_pool_t *scratch_pool)
{
- pristine_install_baton_t *b = baton;
apr_finfo_t finfo;
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
@@ -325,7 +307,7 @@ pristine_install_txn(void *baton,
/* 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, b->sha1_checksum, scratch_pool));
+ 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)
@@ -335,30 +317,30 @@ pristine_install_txn(void *baton,
* ### We could check much more. */
{
apr_finfo_t finfo1, finfo2;
- SVN_ERR(svn_io_stat(&finfo1, b->tempfile_abspath, APR_FINFO_SIZE,
+ SVN_ERR(svn_io_stat(&finfo1, tempfile_abspath, APR_FINFO_SIZE,
scratch_pool));
- SVN_ERR(svn_io_stat(&finfo2, b->pristine_abspath, APR_FINFO_SIZE,
+ SVN_ERR(svn_io_stat(&finfo2, pristine_abspath, APR_FINFO_SIZE,
scratch_pool));
if (finfo1.size != finfo2.size)
{
return svn_error_createf(
SVN_ERR_WC_CORRUPT_TEXT_BASE, NULL,
_("New pristine text '%s' has different size: %ld versus %ld"),
- svn_checksum_to_cstring_display(b->sha1_checksum, scratch_pool),
+ svn_checksum_to_cstring_display(sha1_checksum, scratch_pool),
(long int)finfo1.size, (long int)finfo2.size);
}
}
#endif
/* Remove the temp file: it's already there */
- SVN_ERR(svn_io_remove_file2(b->tempfile_abspath,
+ SVN_ERR(svn_io_remove_file2(tempfile_abspath,
FALSE /* ignore_enoent */, 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.) */
- err = svn_io_file_rename(b->tempfile_abspath, b->pristine_abspath,
+ err = svn_io_file_rename(tempfile_abspath, pristine_abspath,
scratch_pool);
/* Maybe the directory doesn't exist yet? */
@@ -366,7 +348,7 @@ pristine_install_txn(void *baton,
{
svn_error_t *err2;
- err2 = svn_io_dir_make(svn_dirent_dirname(b->pristine_abspath,
+ err2 = svn_io_dir_make(svn_dirent_dirname(pristine_abspath,
scratch_pool),
APR_OS_DEFAULT, scratch_pool);
@@ -377,19 +359,19 @@ pristine_install_txn(void *baton,
/* We could create a directory: retry install */
svn_error_clear(err);
- SVN_ERR(svn_io_file_rename(b->tempfile_abspath, b->pristine_abspath,
+ SVN_ERR(svn_io_file_rename(tempfile_abspath, pristine_abspath,
scratch_pool));
}
else
SVN_ERR(err);
- SVN_ERR(svn_io_stat(&finfo, b->pristine_abspath, APR_FINFO_SIZE,
+ SVN_ERR(svn_io_stat(&finfo, pristine_abspath, APR_FINFO_SIZE,
scratch_pool));
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
STMT_INSERT_PRISTINE));
- SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, b->sha1_checksum, scratch_pool));
- SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, b->md5_checksum, scratch_pool));
+ 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, finfo.size));
SVN_ERR(svn_sqlite__insert(NULL, stmt));
@@ -407,7 +389,7 @@ svn_wc__db_pristine_install(svn_wc__db_t *db,
svn_wc__db_wcroot_t *wcroot;
const char *local_relpath;
const char *wri_abspath;
- struct pristine_install_baton_t b;
+ const char *pristine_abspath;
SVN_ERR_ASSERT(svn_dirent_is_absolute(tempfile_abspath));
SVN_ERR_ASSERT(sha1_checksum != NULL);
@@ -429,19 +411,18 @@ svn_wc__db_pristine_install(svn_wc__db_t *db,
wri_abspath, scratch_pool, scratch_pool));
VERIFY_USABLE_WCROOT(wcroot);
- b.tempfile_abspath = tempfile_abspath;
- b.sha1_checksum = sha1_checksum;
- b.md5_checksum = md5_checksum;
-
- SVN_ERR(get_pristine_fname(&b.pristine_abspath, wcroot->abspath,
+ SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
sha1_checksum,
scratch_pool, scratch_pool));
/* Ensure the SQL txn has at least a 'RESERVED' lock before we start looking
* at the disk, to ensure no concurrent pristine install/delete txn. */
- SVN_ERR(svn_sqlite__with_immediate_transaction(wcroot->sdb,
- pristine_install_txn, &b,
- scratch_pool));
+ SVN_SQLITE__WITH_IMMEDIATE_TXN(
+ pristine_install_txn(wcroot->sdb,
+ tempfile_abspath, pristine_abspath,
+ sha1_checksum, md5_checksum,
+ scratch_pool),
+ wcroot->sdb);
return SVN_NO_ERROR;
}
@@ -523,6 +504,177 @@ svn_wc__db_pristine_get_sha1(const svn_checksum_t **sha1_checksum,
return svn_error_trace(svn_sqlite__reset(stmt));
}
+/* 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 */
+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_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__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));
+
+ SVN_ERR(get_pristine_fname(&src_abspath, src_wcroot->abspath, checksum,
+ scratch_pool, scratch_pool));
+
+ SVN_ERR(svn_stream_open_readonly(&src_stream, src_abspath,
+ 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(get_pristine_fname(&pristine_abspath, dst_wcroot->abspath, checksum,
+ scratch_pool, 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_rename(tmp_abspath, pristine_abspath, 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_rename(tmp_abspath, pristine_abspath, scratch_pool));
+ }
+ else
+ SVN_ERR(err);
+
+ return SVN_NO_ERROR;
+}
+
+/* Transaction implementation of svn_wc__db_pristine_transfer().
+ We have a lock on DST_WCROOT.
+ */
+static svn_error_t *
+pristine_transfer_txn(svn_wc__db_wcroot_t *src_wcroot,
+ svn_wc__db_wcroot_t *dst_wcroot,
+ const char *src_relpath,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
+{
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t got_row;
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, src_wcroot->sdb,
+ STMT_SELECT_COPY_PRISTINES));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", src_wcroot->wc_id, src_relpath));
+
+ /* This obtains an sqlite read lock on src_wcroot */
+ SVN_ERR(svn_sqlite__step(&got_row, stmt));
+
+ while (got_row)
+ {
+ const svn_checksum_t *checksum;
+ const svn_checksum_t *md5_checksum;
+ apr_int64_t size;
+ svn_error_t *err;
+
+ svn_pool_clear(iterpool);
+
+ 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);
+
+ err = maybe_transfer_one_pristine(src_wcroot, dst_wcroot,
+ checksum, md5_checksum, size,
+ cancel_func, cancel_baton,
+ iterpool);
+
+ if (err)
+ return svn_error_trace(svn_error_compose_create(
+ err,
+ svn_sqlite__reset(stmt)));
+
+ SVN_ERR(svn_sqlite__step(&got_row, stmt));
+ }
+ SVN_ERR(svn_sqlite__reset(stmt));
+
+ svn_pool_destroy(iterpool);
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__db_pristine_transfer(svn_wc__db_t *db,
+ const char *src_local_abspath,
+ const char *dst_wri_abspath,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_wcroot_t *src_wcroot, *dst_wcroot;
+ const char *src_relpath, *dst_relpath;
+
+ SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&src_wcroot, &src_relpath,
+ db, src_local_abspath,
+ scratch_pool, scratch_pool));
+ VERIFY_USABLE_WCROOT(src_wcroot);
+ SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&dst_wcroot, &dst_relpath,
+ db, dst_wri_abspath,
+ scratch_pool, scratch_pool));
+ VERIFY_USABLE_WCROOT(dst_wcroot);
+
+ if (src_wcroot == dst_wcroot
+ || src_wcroot->sdb == dst_wcroot->sdb)
+ {
+ return SVN_NO_ERROR; /* Nothing to transfer */
+ }
+
+ SVN_WC__DB_WITH_TXN(
+ pristine_transfer_txn(src_wcroot, dst_wcroot, src_relpath,
+ cancel_func, cancel_baton, scratch_pool),
+ dst_wcroot);
+
+ return SVN_NO_ERROR;
+}
+
+
+
/* Remove the file at FILE_ABSPATH in such a way that we could re-create a
* new file of the same name at any time thereafter.
@@ -560,36 +712,27 @@ remove_file(const char *file_abspath,
return SVN_NO_ERROR;
}
-/* Data for pristine_remove_if_unreferenced_txn(). */
-typedef struct pristine_remove_baton_t
-{
- svn_wc__db_wcroot_t *wcroot;
- /* The pristine text's SHA-1 checksum. */
- const svn_checksum_t *sha1_checksum;
- /* The path to the pristine file (within the pristine store). */
- const char *pristine_abspath;
-} pristine_remove_baton_t;
-
-/* If the pristine text referenced by BATON in SDB has a reference count of
+/* If the pristine text referenced by SHA1_CHECKSUM in WCROOT/SDB, whose path
+ * within the pristine store is PRISTINE_ABSPATH, has a reference count of
* zero, delete it (both the database row and the disk file).
*
* This function expects to be executed inside a SQLite txn that has already
* acquired a 'RESERVED' lock.
- *
- * Implements svn_sqlite__transaction_callback_t. */
+ */
static svn_error_t *
-pristine_remove_if_unreferenced_txn(void *baton,
- svn_sqlite__db_t *sdb,
+pristine_remove_if_unreferenced_txn(svn_sqlite__db_t *sdb,
+ svn_wc__db_wcroot_t *wcroot,
+ const svn_checksum_t *sha1_checksum,
+ const char *pristine_abspath,
apr_pool_t *scratch_pool)
{
- pristine_remove_baton_t *b = baton;
svn_sqlite__stmt_t *stmt;
int affected_rows;
/* Remove the DB row, if refcount is 0. */
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
STMT_DELETE_PRISTINE_IF_UNREFERENCED));
- SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, b->sha1_checksum, scratch_pool));
+ SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
/* If we removed the DB row, then remove the file. */
@@ -604,7 +747,7 @@ pristine_remove_if_unreferenced_txn(void *baton,
svn_boolean_t ignore_enoent = TRUE;
#endif
- SVN_ERR(remove_file(b->pristine_abspath, b->wcroot, ignore_enoent,
+ SVN_ERR(remove_file(pristine_abspath, wcroot, ignore_enoent,
scratch_pool));
}
@@ -621,17 +764,17 @@ pristine_remove_if_unreferenced(svn_wc__db_wcroot_t *wcroot,
const svn_checksum_t *sha1_checksum,
apr_pool_t *scratch_pool)
{
- pristine_remove_baton_t b;
+ const char *pristine_abspath;
- b.wcroot = wcroot;
- b.sha1_checksum = sha1_checksum;
- SVN_ERR(get_pristine_fname(&b.pristine_abspath, wcroot->abspath,
+ SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
sha1_checksum, scratch_pool, scratch_pool));
/* Ensure the SQL txn has at least a 'RESERVED' lock before we start looking
* at the disk, to ensure no concurrent pristine install/delete txn. */
- SVN_ERR(svn_sqlite__with_immediate_transaction(
- wcroot->sdb, pristine_remove_if_unreferenced_txn, &b, scratch_pool));
+ SVN_SQLITE__WITH_IMMEDIATE_TXN(
+ pristine_remove_if_unreferenced_txn(
+ wcroot->sdb, wcroot, sha1_checksum, pristine_abspath, scratch_pool),
+ wcroot->sdb);
return SVN_NO_ERROR;
}
@@ -685,11 +828,12 @@ pristine_cleanup_wcroot(svn_wc__db_wcroot_t *wcroot,
apr_pool_t *scratch_pool)
{
svn_sqlite__stmt_t *stmt;
+ svn_error_t *err = NULL;
/* Find each unreferenced pristine in the DB and remove it. */
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_SELECT_UNREFERENCED_PRISTINES));
- while (1)
+ while (! err)
{
svn_boolean_t have_row;
const svn_checksum_t *sha1_checksum;
@@ -700,15 +844,14 @@ pristine_cleanup_wcroot(svn_wc__db_wcroot_t *wcroot,
SVN_ERR(svn_sqlite__column_checksum(&sha1_checksum, stmt, 0,
scratch_pool));
- SVN_ERR(pristine_remove_if_unreferenced(wcroot, sha1_checksum,
- scratch_pool));
+ err = pristine_remove_if_unreferenced(wcroot, sha1_checksum,
+ scratch_pool);
}
- SVN_ERR(svn_sqlite__reset(stmt));
- return SVN_NO_ERROR;
+ return svn_error_trace(
+ svn_error_compose_create(err, svn_sqlite__reset(stmt)));
}
-
svn_error_t *
svn_wc__db_pristine_cleanup(svn_wc__db_t *db,
const char *wri_abspath,
@@ -741,46 +884,42 @@ svn_wc__db_pristine_check(svn_boolean_t *present,
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
- SVN_ERR_ASSERT(present != 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);
+ {
+ *present = FALSE;
+ return SVN_NO_ERROR;
+ }
SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
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_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
+ sha1_checksum, scratch_pool, scratch_pool));
+ SVN_ERR(svn_io_check_path(pristine_abspath, &kind_on_disk, scratch_pool));
+ 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));
SVN_ERR(svn_sqlite__reset(stmt));
-#ifdef SVN_DEBUG
- /* Check that the pristine text file exists iff the DB says it does. */
- if (have_row)
- {
- const char *pristine_abspath;
- svn_node_kind_t kind_on_disk;
- SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
- sha1_checksum, scratch_pool, scratch_pool));
- SVN_ERR(svn_io_check_path(pristine_abspath, &kind_on_disk, scratch_pool));
-
- if (kind_on_disk != svn_node_file)
- return svn_error_createf(SVN_ERR_WC_DB_ERROR, svn_sqlite__reset(stmt),
- _("The pristine text with checksum '%s' was "
- "found in the DB but not on disk"),
- svn_checksum_to_cstring_display(sha1_checksum,
- scratch_pool));
- }
-#endif
-
*present = have_row;
return SVN_NO_ERROR;
}