diff options
Diffstat (limited to 'subversion/libsvn_wc/wc_db_pristine.c')
-rw-r--r-- | subversion/libsvn_wc/wc_db_pristine.c | 409 |
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; } |