2 * wc_db_pristine.c : Pristine ("text base") management
4 * See the spec in 'notes/wc-ng/pristine-store'.
6 * ====================================================================
7 * Licensed to the Apache Software Foundation (ASF) under one
8 * or more contributor license agreements. See the NOTICE file
9 * distributed with this work for additional information
10 * regarding copyright ownership. The ASF licenses this file
11 * to you under the Apache License, Version 2.0 (the
12 * "License"); you may not use this file except in compliance
13 * with the License. You may obtain a copy of the License at
15 * http://www.apache.org/licenses/LICENSE-2.0
17 * Unless required by applicable law or agreed to in writing,
18 * software distributed under the License is distributed on an
19 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20 * KIND, either express or implied. See the License for the
21 * specific language governing permissions and limitations
23 * ====================================================================
26 #define SVN_WC__I_AM_WC_DB
28 #include "svn_pools.h"
30 #include "svn_dirent_uri.h"
32 #include "private/svn_io_private.h"
36 #include "wc-queries.h"
37 #include "wc_db_private.h"
39 #define PRISTINE_STORAGE_EXT ".svn-base"
40 #define PRISTINE_STORAGE_RELPATH "pristine"
41 #define PRISTINE_TEMPDIR_RELPATH "tmp"
45 /* Returns in PRISTINE_ABSPATH a new string allocated from RESULT_POOL,
46 holding the local absolute path to the file location that is dedicated
47 to hold CHECKSUM's pristine file, relating to the pristine store
48 configured for the working copy indicated by PDH. The returned path
49 does not necessarily currently exist.
51 Any other allocations are made in SCRATCH_POOL. */
53 get_pristine_fname(const char **pristine_abspath,
54 const char *wcroot_abspath,
55 const svn_checksum_t *sha1_checksum,
56 apr_pool_t *result_pool,
57 apr_pool_t *scratch_pool)
59 const char *base_dir_abspath;
60 const char *hexdigest = svn_checksum_to_cstring(sha1_checksum, scratch_pool);
63 /* ### code is in transition. make sure we have the proper data. */
64 SVN_ERR_ASSERT(pristine_abspath != NULL);
65 SVN_ERR_ASSERT(svn_dirent_is_absolute(wcroot_abspath));
66 SVN_ERR_ASSERT(sha1_checksum != NULL);
67 SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
69 base_dir_abspath = svn_dirent_join_many(scratch_pool,
71 svn_wc_get_adm_dir(scratch_pool),
72 PRISTINE_STORAGE_RELPATH,
75 /* We should have a valid checksum and (thus) a valid digest. */
76 SVN_ERR_ASSERT(hexdigest != NULL);
78 /* Get the first two characters of the digest, for the subdir. */
79 subdir[0] = hexdigest[0];
80 subdir[1] = hexdigest[1];
83 hexdigest = apr_pstrcat(scratch_pool, hexdigest, PRISTINE_STORAGE_EXT,
86 /* The file is located at DIR/.svn/pristine/XX/XXYYZZ...svn-base */
87 *pristine_abspath = svn_dirent_join_many(result_pool,
97 svn_wc__db_pristine_get_path(const char **pristine_abspath,
99 const char *wri_abspath,
100 const svn_checksum_t *sha1_checksum,
101 apr_pool_t *result_pool,
102 apr_pool_t *scratch_pool)
104 svn_wc__db_wcroot_t *wcroot;
105 const char *local_relpath;
106 svn_boolean_t present;
108 SVN_ERR_ASSERT(pristine_abspath != NULL);
109 SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
110 SVN_ERR_ASSERT(sha1_checksum != NULL);
111 /* ### Transitional: accept MD-5 and look up the SHA-1. Return an error
112 * if the pristine text is not in the store. */
113 if (sha1_checksum->kind != svn_checksum_sha1)
114 SVN_ERR(svn_wc__db_pristine_get_sha1(&sha1_checksum, db, wri_abspath,
116 scratch_pool, scratch_pool));
117 SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
119 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath,
121 scratch_pool, scratch_pool));
122 VERIFY_USABLE_WCROOT(wcroot);
124 SVN_ERR(svn_wc__db_pristine_check(&present, db, wri_abspath, sha1_checksum,
127 return svn_error_createf(SVN_ERR_WC_DB_ERROR, NULL,
128 _("The pristine text with checksum '%s' was "
130 svn_checksum_to_cstring_display(sha1_checksum,
133 SVN_ERR(get_pristine_fname(pristine_abspath, wcroot->abspath,
135 result_pool, scratch_pool));
141 svn_wc__db_pristine_get_future_path(const char **pristine_abspath,
142 const char *wcroot_abspath,
143 const svn_checksum_t *sha1_checksum,
144 apr_pool_t *result_pool,
145 apr_pool_t *scratch_pool)
147 SVN_ERR(get_pristine_fname(pristine_abspath, wcroot_abspath,
149 result_pool, scratch_pool));
153 /* Set *CONTENTS to a readable stream from which the pristine text
154 * identified by SHA1_CHECKSUM and PRISTINE_ABSPATH can be read from the
155 * pristine store of WCROOT. If SIZE is not null, set *SIZE to the size
156 * in bytes of that text. If that text is not in the pristine store,
159 * Even if the pristine text is removed from the store while it is being
160 * read, the stream will remain valid and readable until it is closed.
162 * Allocate the stream in RESULT_POOL.
164 * This function expects to be executed inside a SQLite txn.
166 * Implements 'notes/wc-ng/pristine-store' section A-3(d).
169 pristine_read_txn(svn_stream_t **contents,
170 svn_filesize_t *size,
171 svn_wc__db_wcroot_t *wcroot,
172 const svn_checksum_t *sha1_checksum,
173 const char *pristine_abspath,
174 apr_pool_t *result_pool,
175 apr_pool_t *scratch_pool)
177 svn_sqlite__stmt_t *stmt;
178 svn_boolean_t have_row;
180 /* Check that this pristine text is present in the store. (The presence
181 * of the file is not sufficient.) */
182 SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
183 STMT_SELECT_PRISTINE_SIZE));
184 SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
185 SVN_ERR(svn_sqlite__step(&have_row, stmt));
188 *size = svn_sqlite__column_int64(stmt, 0);
190 SVN_ERR(svn_sqlite__reset(stmt));
193 return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
194 _("Pristine text '%s' not present"),
195 svn_checksum_to_cstring_display(
196 sha1_checksum, scratch_pool));
199 /* Open the file as a readable stream. It will remain readable even when
200 * deleted from disk; APR guarantees that on Windows as well as Unix.
202 * We also don't enable APR_BUFFERED on this file to maximize throughput
203 * e.g. for fulltext comparison. As we use SVN__STREAM_CHUNK_SIZE buffers
204 * where needed in streams, there is no point in having another layer of
209 SVN_ERR(svn_io_file_open(&file, pristine_abspath, APR_READ,
210 APR_OS_DEFAULT, result_pool));
211 *contents = svn_stream_from_aprfile2(file, FALSE, result_pool);
218 svn_wc__db_pristine_read(svn_stream_t **contents,
219 svn_filesize_t *size,
221 const char *wri_abspath,
222 const svn_checksum_t *sha1_checksum,
223 apr_pool_t *result_pool,
224 apr_pool_t *scratch_pool)
226 svn_wc__db_wcroot_t *wcroot;
227 const char *local_relpath;
228 const char *pristine_abspath;
230 SVN_ERR_ASSERT(contents != NULL);
231 SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
233 /* Some 1.6-to-1.7 wc upgrades created rows without checksums and
234 updating such a row passes NULL here. */
236 return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
237 _("Can't read '%s' from pristine store "
238 "because no checksum supplied"),
239 svn_dirent_local_style(wri_abspath, scratch_pool));
241 SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
243 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
244 wri_abspath, scratch_pool, scratch_pool));
245 VERIFY_USABLE_WCROOT(wcroot);
247 SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
249 scratch_pool, scratch_pool));
251 pristine_read_txn(contents, size,
252 wcroot, sha1_checksum, pristine_abspath,
253 result_pool, scratch_pool),
260 /* Return the absolute path to the temporary directory for pristine text
261 files within WCROOT. */
263 pristine_get_tempdir(svn_wc__db_wcroot_t *wcroot,
264 apr_pool_t *result_pool,
265 apr_pool_t *scratch_pool)
267 return svn_dirent_join_many(result_pool, wcroot->abspath,
268 svn_wc_get_adm_dir(scratch_pool),
269 PRISTINE_TEMPDIR_RELPATH, SVN_VA_NULL);
272 /* Install the pristine text described by BATON into the pristine store of
273 * SDB. If it is already stored then just delete the new file
274 * BATON->tempfile_abspath.
276 * This function expects to be executed inside a SQLite txn that has already
277 * acquired a 'RESERVED' lock.
279 * Implements 'notes/wc-ng/pristine-store' section A-3(a).
282 pristine_install_txn(svn_sqlite__db_t *sdb,
283 /* The path to the source file that is to be moved into place. */
284 svn_stream_t *install_stream,
285 /* The target path for the file (within the pristine store). */
286 const char *pristine_abspath,
287 /* The pristine text's SHA-1 checksum. */
288 const svn_checksum_t *sha1_checksum,
289 /* The pristine text's MD-5 checksum. */
290 const svn_checksum_t *md5_checksum,
291 apr_pool_t *scratch_pool)
293 svn_sqlite__stmt_t *stmt;
294 svn_boolean_t have_row;
296 /* If this pristine text is already present in the store, just keep it:
297 * delete the new one and return. */
298 SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_PRISTINE));
299 SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
300 SVN_ERR(svn_sqlite__step(&have_row, stmt));
301 SVN_ERR(svn_sqlite__reset(stmt));
306 /* Consistency checks. Verify both files exist and match.
307 * ### We could check much more. */
309 apr_finfo_t finfo1, finfo2;
311 SVN_ERR(svn_stream__install_get_info(&finfo1, install_stream, APR_FINFO_SIZE,
314 SVN_ERR(svn_io_stat(&finfo2, pristine_abspath, APR_FINFO_SIZE,
316 if (finfo1.size != finfo2.size)
318 return svn_error_createf(
319 SVN_ERR_WC_CORRUPT_TEXT_BASE, NULL,
320 _("New pristine text '%s' has different size: %ld versus %ld"),
321 svn_checksum_to_cstring_display(sha1_checksum, scratch_pool),
322 (long int)finfo1.size, (long int)finfo2.size);
327 /* Remove the temp file: it's already there */
328 SVN_ERR(svn_stream__install_delete(install_stream, scratch_pool));
332 /* Move the file to its target location. (If it is already there, it is
333 * an orphan file and it doesn't matter if we overwrite it.) */
336 SVN_ERR(svn_stream__install_get_info(&finfo, install_stream, APR_FINFO_SIZE,
338 SVN_ERR(svn_stream__install_stream(install_stream, pristine_abspath,
339 TRUE, scratch_pool));
341 SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
342 STMT_INSERT_PRISTINE));
343 SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
344 SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, md5_checksum, scratch_pool));
345 SVN_ERR(svn_sqlite__bind_int64(stmt, 3, finfo.size));
346 SVN_ERR(svn_sqlite__insert(NULL, stmt));
348 SVN_ERR(svn_io_set_file_read_only(pristine_abspath, FALSE, scratch_pool));
354 struct svn_wc__db_install_data_t
356 svn_wc__db_wcroot_t *wcroot;
357 svn_stream_t *inner_stream;
361 svn_wc__db_pristine_prepare_install(svn_stream_t **stream,
362 svn_wc__db_install_data_t **install_data,
363 svn_checksum_t **sha1_checksum,
364 svn_checksum_t **md5_checksum,
366 const char *wri_abspath,
367 apr_pool_t *result_pool,
368 apr_pool_t *scratch_pool)
370 svn_wc__db_wcroot_t *wcroot;
371 const char *local_relpath;
372 const char *temp_dir_abspath;
374 SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
376 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
377 wri_abspath, scratch_pool, scratch_pool));
378 VERIFY_USABLE_WCROOT(wcroot);
380 temp_dir_abspath = pristine_get_tempdir(wcroot, scratch_pool, scratch_pool);
382 *install_data = apr_pcalloc(result_pool, sizeof(**install_data));
383 (*install_data)->wcroot = wcroot;
385 SVN_ERR_W(svn_stream__create_for_install(stream,
387 result_pool, scratch_pool),
388 _("Unable to create pristine install stream"));
390 (*install_data)->inner_stream = *stream;
393 *stream = svn_stream_checksummed2(*stream, NULL, md5_checksum,
394 svn_checksum_md5, FALSE, result_pool);
396 *stream = svn_stream_checksummed2(*stream, NULL, sha1_checksum,
397 svn_checksum_sha1, FALSE, result_pool);
403 svn_wc__db_pristine_install(svn_wc__db_install_data_t *install_data,
404 const svn_checksum_t *sha1_checksum,
405 const svn_checksum_t *md5_checksum,
406 apr_pool_t *scratch_pool)
408 svn_wc__db_wcroot_t *wcroot = install_data->wcroot;
409 const char *pristine_abspath;
411 SVN_ERR_ASSERT(sha1_checksum != NULL);
412 SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
413 SVN_ERR_ASSERT(md5_checksum != NULL);
414 SVN_ERR_ASSERT(md5_checksum->kind == svn_checksum_md5);
416 SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
418 scratch_pool, scratch_pool));
420 /* Ensure the SQL txn has at least a 'RESERVED' lock before we start looking
421 * at the disk, to ensure no concurrent pristine install/delete txn. */
422 SVN_SQLITE__WITH_IMMEDIATE_TXN(
423 pristine_install_txn(wcroot->sdb,
424 install_data->inner_stream, pristine_abspath,
425 sha1_checksum, md5_checksum,
433 svn_wc__db_pristine_install_abort(svn_wc__db_install_data_t *install_data,
434 apr_pool_t *scratch_pool)
436 return svn_error_trace(svn_stream__install_delete(install_data->inner_stream,
442 svn_wc__db_pristine_get_md5(const svn_checksum_t **md5_checksum,
444 const char *wri_abspath,
445 const svn_checksum_t *sha1_checksum,
446 apr_pool_t *result_pool,
447 apr_pool_t *scratch_pool)
449 svn_wc__db_wcroot_t *wcroot;
450 const char *local_relpath;
451 svn_sqlite__stmt_t *stmt;
452 svn_boolean_t have_row;
454 SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
455 SVN_ERR_ASSERT(sha1_checksum != NULL);
456 SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
458 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
459 wri_abspath, scratch_pool, scratch_pool));
460 VERIFY_USABLE_WCROOT(wcroot);
462 SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_PRISTINE));
463 SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
464 SVN_ERR(svn_sqlite__step(&have_row, stmt));
466 return svn_error_createf(SVN_ERR_WC_DB_ERROR, svn_sqlite__reset(stmt),
467 _("The pristine text with checksum '%s' was "
469 svn_checksum_to_cstring_display(sha1_checksum,
472 SVN_ERR(svn_sqlite__column_checksum(md5_checksum, stmt, 0, result_pool));
473 SVN_ERR_ASSERT((*md5_checksum)->kind == svn_checksum_md5);
475 return svn_error_trace(svn_sqlite__reset(stmt));
480 svn_wc__db_pristine_get_sha1(const svn_checksum_t **sha1_checksum,
482 const char *wri_abspath,
483 const svn_checksum_t *md5_checksum,
484 apr_pool_t *result_pool,
485 apr_pool_t *scratch_pool)
487 svn_wc__db_wcroot_t *wcroot;
488 const char *local_relpath;
489 svn_sqlite__stmt_t *stmt;
490 svn_boolean_t have_row;
492 SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
493 SVN_ERR_ASSERT(sha1_checksum != NULL);
494 SVN_ERR_ASSERT(md5_checksum->kind == svn_checksum_md5);
496 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
497 wri_abspath, scratch_pool, scratch_pool));
498 VERIFY_USABLE_WCROOT(wcroot);
500 SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
501 STMT_SELECT_PRISTINE_BY_MD5));
502 SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, md5_checksum, scratch_pool));
503 SVN_ERR(svn_sqlite__step(&have_row, stmt));
505 return svn_error_createf(SVN_ERR_WC_DB_ERROR, svn_sqlite__reset(stmt),
506 _("The pristine text with MD5 checksum '%s' was "
508 svn_checksum_to_cstring_display(md5_checksum,
511 SVN_ERR(svn_sqlite__column_checksum(sha1_checksum, stmt, 0, result_pool));
512 SVN_ERR_ASSERT((*sha1_checksum)->kind == svn_checksum_sha1);
514 return svn_error_trace(svn_sqlite__reset(stmt));
517 /* Handle the moving of a pristine from SRC_WCROOT to DST_WCROOT. The existing
518 pristine in SRC_WCROOT is described by CHECKSUM, MD5_CHECKSUM and SIZE */
520 maybe_transfer_one_pristine(svn_wc__db_wcroot_t *src_wcroot,
521 svn_wc__db_wcroot_t *dst_wcroot,
522 const svn_checksum_t *checksum,
523 const svn_checksum_t *md5_checksum,
525 svn_cancel_func_t cancel_func,
527 apr_pool_t *scratch_pool)
529 const char *pristine_abspath;
530 svn_sqlite__stmt_t *stmt;
531 svn_stream_t *src_stream;
532 svn_stream_t *dst_stream;
533 const char *tmp_abspath;
534 const char *src_abspath;
538 SVN_ERR(svn_sqlite__get_statement(&stmt, dst_wcroot->sdb,
539 STMT_INSERT_OR_IGNORE_PRISTINE));
540 SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, checksum, scratch_pool));
541 SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, md5_checksum, scratch_pool));
542 SVN_ERR(svn_sqlite__bind_int64(stmt, 3, size));
544 SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
546 if (affected_rows == 0)
549 SVN_ERR(svn_stream_open_unique(&dst_stream, &tmp_abspath,
550 pristine_get_tempdir(dst_wcroot,
553 svn_io_file_del_on_pool_cleanup,
554 scratch_pool, scratch_pool));
556 SVN_ERR(get_pristine_fname(&src_abspath, src_wcroot->abspath, checksum,
557 scratch_pool, scratch_pool));
559 SVN_ERR(svn_stream_open_readonly(&src_stream, src_abspath,
560 scratch_pool, scratch_pool));
562 /* ### Should we verify the SHA1 or MD5 here, or is that too expensive? */
563 SVN_ERR(svn_stream_copy3(src_stream, dst_stream,
564 cancel_func, cancel_baton,
567 SVN_ERR(get_pristine_fname(&pristine_abspath, dst_wcroot->abspath, checksum,
568 scratch_pool, scratch_pool));
570 /* Move the file to its target location. (If it is already there, it is
571 * an orphan file and it doesn't matter if we overwrite it.) */
572 err = svn_io_file_rename(tmp_abspath, pristine_abspath, scratch_pool);
574 /* Maybe the directory doesn't exist yet? */
575 if (err && APR_STATUS_IS_ENOENT(err->apr_err))
579 err2 = svn_io_dir_make(svn_dirent_dirname(pristine_abspath,
581 APR_OS_DEFAULT, scratch_pool);
584 /* Creating directory didn't work: Return all errors */
585 return svn_error_trace(svn_error_compose_create(err, err2));
587 /* We could create a directory: retry install */
588 svn_error_clear(err);
590 SVN_ERR(svn_io_file_rename(tmp_abspath, pristine_abspath, scratch_pool));
598 /* Transaction implementation of svn_wc__db_pristine_transfer().
599 We have a lock on DST_WCROOT.
602 pristine_transfer_txn(svn_wc__db_wcroot_t *src_wcroot,
603 svn_wc__db_wcroot_t *dst_wcroot,
604 const char *src_relpath,
605 svn_cancel_func_t cancel_func,
607 apr_pool_t *scratch_pool)
609 svn_sqlite__stmt_t *stmt;
610 svn_boolean_t got_row;
611 apr_pool_t *iterpool = svn_pool_create(scratch_pool);
613 SVN_ERR(svn_sqlite__get_statement(&stmt, src_wcroot->sdb,
614 STMT_SELECT_COPY_PRISTINES));
615 SVN_ERR(svn_sqlite__bindf(stmt, "is", src_wcroot->wc_id, src_relpath));
617 /* This obtains an sqlite read lock on src_wcroot */
618 SVN_ERR(svn_sqlite__step(&got_row, stmt));
622 const svn_checksum_t *checksum;
623 const svn_checksum_t *md5_checksum;
627 svn_pool_clear(iterpool);
629 SVN_ERR(svn_sqlite__column_checksum(&checksum, stmt, 0, iterpool));
630 SVN_ERR(svn_sqlite__column_checksum(&md5_checksum, stmt, 1, iterpool));
631 size = svn_sqlite__column_int64(stmt, 2);
633 err = maybe_transfer_one_pristine(src_wcroot, dst_wcroot,
634 checksum, md5_checksum, size,
635 cancel_func, cancel_baton,
639 return svn_error_trace(svn_error_compose_create(
641 svn_sqlite__reset(stmt)));
643 SVN_ERR(svn_sqlite__step(&got_row, stmt));
645 SVN_ERR(svn_sqlite__reset(stmt));
647 svn_pool_destroy(iterpool);
653 svn_wc__db_pristine_transfer(svn_wc__db_t *db,
654 const char *src_local_abspath,
655 const char *dst_wri_abspath,
656 svn_cancel_func_t cancel_func,
658 apr_pool_t *scratch_pool)
660 svn_wc__db_wcroot_t *src_wcroot, *dst_wcroot;
661 const char *src_relpath, *dst_relpath;
663 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&src_wcroot, &src_relpath,
664 db, src_local_abspath,
665 scratch_pool, scratch_pool));
666 VERIFY_USABLE_WCROOT(src_wcroot);
667 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&dst_wcroot, &dst_relpath,
669 scratch_pool, scratch_pool));
670 VERIFY_USABLE_WCROOT(dst_wcroot);
672 if (src_wcroot == dst_wcroot
673 || src_wcroot->sdb == dst_wcroot->sdb)
675 return SVN_NO_ERROR; /* Nothing to transfer */
679 pristine_transfer_txn(src_wcroot, dst_wcroot, src_relpath,
680 cancel_func, cancel_baton, scratch_pool),
689 /* Remove the file at FILE_ABSPATH in such a way that we could re-create a
690 * new file of the same name at any time thereafter.
692 * On Windows, the file will not disappear immediately from the directory if
693 * it is still being read so the best thing to do is first rename it to a
696 remove_file(const char *file_abspath,
697 svn_wc__db_wcroot_t *wcroot,
698 svn_boolean_t ignore_enoent,
699 apr_pool_t *scratch_pool)
703 const char *temp_abspath;
704 const char *temp_dir_abspath
705 = pristine_get_tempdir(wcroot, scratch_pool, scratch_pool);
707 /* To rename the file to a unique name in the temp dir, first create a
708 * uniquely named file in the temp dir and then overwrite it. */
709 SVN_ERR(svn_io_open_unique_file3(NULL, &temp_abspath, temp_dir_abspath,
710 svn_io_file_del_none,
711 scratch_pool, scratch_pool));
712 err = svn_io_file_rename(file_abspath, temp_abspath, scratch_pool);
713 if (err && ignore_enoent && APR_STATUS_IS_ENOENT(err->apr_err))
714 svn_error_clear(err);
717 file_abspath = temp_abspath;
720 SVN_ERR(svn_io_remove_file2(file_abspath, ignore_enoent, scratch_pool));
725 /* If the pristine text referenced by SHA1_CHECKSUM in WCROOT/SDB, whose path
726 * within the pristine store is PRISTINE_ABSPATH, has a reference count of
727 * zero, delete it (both the database row and the disk file).
729 * This function expects to be executed inside a SQLite txn that has already
730 * acquired a 'RESERVED' lock.
733 pristine_remove_if_unreferenced_txn(svn_sqlite__db_t *sdb,
734 svn_wc__db_wcroot_t *wcroot,
735 const svn_checksum_t *sha1_checksum,
736 const char *pristine_abspath,
737 apr_pool_t *scratch_pool)
739 svn_sqlite__stmt_t *stmt;
742 /* Remove the DB row, if refcount is 0. */
743 SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
744 STMT_DELETE_PRISTINE_IF_UNREFERENCED));
745 SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
746 SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
748 /* If we removed the DB row, then remove the file. */
749 if (affected_rows > 0)
751 /* If the file is not present, something has gone wrong, but at this
752 * point it no longer matters. In a debug build, raise an error, but
753 * in a release build, it is more helpful to ignore it and continue. */
755 svn_boolean_t ignore_enoent = FALSE;
757 svn_boolean_t ignore_enoent = TRUE;
760 SVN_ERR(remove_file(pristine_abspath, wcroot, ignore_enoent,
767 /* If the pristine text referenced by SHA1_CHECKSUM in WCROOT has a
768 * reference count of zero, delete it (both the database row and the disk
771 * Implements 'notes/wc-ng/pristine-store' section A-3(b). */
773 pristine_remove_if_unreferenced(svn_wc__db_wcroot_t *wcroot,
774 const svn_checksum_t *sha1_checksum,
775 apr_pool_t *scratch_pool)
777 const char *pristine_abspath;
779 SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
780 sha1_checksum, scratch_pool, scratch_pool));
782 /* Ensure the SQL txn has at least a 'RESERVED' lock before we start looking
783 * at the disk, to ensure no concurrent pristine install/delete txn. */
784 SVN_SQLITE__WITH_IMMEDIATE_TXN(
785 pristine_remove_if_unreferenced_txn(
786 wcroot->sdb, wcroot, sha1_checksum, pristine_abspath, scratch_pool),
793 svn_wc__db_pristine_remove(svn_wc__db_t *db,
794 const char *wri_abspath,
795 const svn_checksum_t *sha1_checksum,
796 apr_pool_t *scratch_pool)
798 svn_wc__db_wcroot_t *wcroot;
799 const char *local_relpath;
801 SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
802 SVN_ERR_ASSERT(sha1_checksum != NULL);
803 /* ### Transitional: accept MD-5 and look up the SHA-1. Return an error
804 * if the pristine text is not in the store. */
805 if (sha1_checksum->kind != svn_checksum_sha1)
806 SVN_ERR(svn_wc__db_pristine_get_sha1(&sha1_checksum, db, wri_abspath,
808 scratch_pool, scratch_pool));
809 SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
811 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
812 wri_abspath, scratch_pool, scratch_pool));
813 VERIFY_USABLE_WCROOT(wcroot);
815 /* If the work queue is not empty, don't delete any pristine text because
816 * the work queue may contain a reference to it. */
818 svn_sqlite__stmt_t *stmt;
819 svn_boolean_t have_row;
821 SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_LOOK_FOR_WORK));
822 SVN_ERR(svn_sqlite__step(&have_row, stmt));
823 SVN_ERR(svn_sqlite__reset(stmt));
829 /* If not referenced, remove the PRISTINE table row and the file. */
830 SVN_ERR(pristine_remove_if_unreferenced(wcroot, sha1_checksum, scratch_pool));
836 /* Remove all unreferenced pristines in the WC DB in WCROOT.
838 * Look for pristine texts whose 'refcount' in the DB is zero, and remove
839 * them from the 'pristine' table and from disk.
841 * TODO: At least check that any zero refcount is really correct, before
842 * using it. See dev@ email thread "Pristine text missing - cleanup
843 * doesn't work", <http://svn.haxx.se/dev/archive-2013-04/0426.shtml>.
845 * TODO: Ideas for possible extra clean-up operations:
847 * * Check and correct all the refcounts. Identify any rows missing
848 * from the 'pristine' table. (Create a temporary index for speed
851 * * Check the checksums. (Very expensive to check them all, so find
852 * a way to not check them all.)
854 * * Check for pristine files missing from disk but referenced in the
857 * * Repair any pristine files missing from disk and/or rows missing
858 * from the 'pristine' table and/or bad checksums. Generally
859 * requires contacting the server, so requires support at a higher
860 * level than this function.
862 * * Identify any pristine text files on disk that are not referenced
863 * in the DB, and delete them.
865 * TODO: Provide feedback about any errors found and any corrections made.
868 pristine_cleanup_wcroot(svn_wc__db_wcroot_t *wcroot,
869 apr_pool_t *scratch_pool)
871 svn_sqlite__stmt_t *stmt;
872 svn_error_t *err = NULL;
873 apr_pool_t *iterpool = svn_pool_create(scratch_pool);
875 /* Find each unreferenced pristine in the DB and remove it. */
876 SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
877 STMT_SELECT_UNREFERENCED_PRISTINES));
880 svn_boolean_t have_row;
881 const svn_checksum_t *sha1_checksum;
883 svn_pool_clear(iterpool);
885 SVN_ERR(svn_sqlite__step(&have_row, stmt));
889 SVN_ERR(svn_sqlite__column_checksum(&sha1_checksum, stmt, 0,
891 err = pristine_remove_if_unreferenced(wcroot, sha1_checksum,
895 svn_pool_destroy(iterpool);
897 return svn_error_trace(
898 svn_error_compose_create(err, svn_sqlite__reset(stmt)));
902 svn_wc__db_pristine_cleanup(svn_wc__db_t *db,
903 const char *wri_abspath,
904 apr_pool_t *scratch_pool)
906 svn_wc__db_wcroot_t *wcroot;
907 const char *local_relpath;
909 SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
911 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
912 wri_abspath, scratch_pool, scratch_pool));
913 VERIFY_USABLE_WCROOT(wcroot);
915 SVN_ERR(pristine_cleanup_wcroot(wcroot, scratch_pool));
922 svn_wc__db_pristine_check(svn_boolean_t *present,
924 const char *wri_abspath,
925 const svn_checksum_t *sha1_checksum,
926 apr_pool_t *scratch_pool)
928 svn_wc__db_wcroot_t *wcroot;
929 const char *local_relpath;
930 svn_sqlite__stmt_t *stmt;
931 svn_boolean_t have_row;
933 SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
934 SVN_ERR_ASSERT(sha1_checksum != NULL);
936 if (sha1_checksum->kind != svn_checksum_sha1)
942 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
943 wri_abspath, scratch_pool, scratch_pool));
944 VERIFY_USABLE_WCROOT(wcroot);
946 /* A filestat is much cheaper than a sqlite transaction especially on NFS,
947 so first check if there is a pristine file and then if we are allowed
950 const char *pristine_abspath;
951 svn_node_kind_t kind_on_disk;
953 SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
954 sha1_checksum, scratch_pool, scratch_pool));
955 SVN_ERR(svn_io_check_path(pristine_abspath, &kind_on_disk, scratch_pool));
956 if (kind_on_disk != svn_node_file)
963 /* Check that there is an entry in the PRISTINE table. */
964 SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_PRISTINE));
965 SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
966 SVN_ERR(svn_sqlite__step(&have_row, stmt));
967 SVN_ERR(svn_sqlite__reset(stmt));