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"
29 #include "svn_dirent_uri.h"
33 #include "wc-queries.h"
34 #include "wc_db_private.h"
36 #define PRISTINE_STORAGE_EXT ".svn-base"
37 #define PRISTINE_STORAGE_RELPATH "pristine"
38 #define PRISTINE_TEMPDIR_RELPATH "tmp"
42 /* Returns in PRISTINE_ABSPATH a new string allocated from RESULT_POOL,
43 holding the local absolute path to the file location that is dedicated
44 to hold CHECKSUM's pristine file, relating to the pristine store
45 configured for the working copy indicated by PDH. The returned path
46 does not necessarily currently exist.
48 Any other allocations are made in SCRATCH_POOL. */
50 get_pristine_fname(const char **pristine_abspath,
51 const char *wcroot_abspath,
52 const svn_checksum_t *sha1_checksum,
53 apr_pool_t *result_pool,
54 apr_pool_t *scratch_pool)
56 const char *base_dir_abspath;
57 const char *hexdigest = svn_checksum_to_cstring(sha1_checksum, scratch_pool);
60 /* ### code is in transition. make sure we have the proper data. */
61 SVN_ERR_ASSERT(pristine_abspath != NULL);
62 SVN_ERR_ASSERT(svn_dirent_is_absolute(wcroot_abspath));
63 SVN_ERR_ASSERT(sha1_checksum != NULL);
64 SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
66 base_dir_abspath = svn_dirent_join_many(scratch_pool,
68 svn_wc_get_adm_dir(scratch_pool),
69 PRISTINE_STORAGE_RELPATH,
72 /* We should have a valid checksum and (thus) a valid digest. */
73 SVN_ERR_ASSERT(hexdigest != NULL);
75 /* Get the first two characters of the digest, for the subdir. */
76 subdir[0] = hexdigest[0];
77 subdir[1] = hexdigest[1];
80 hexdigest = apr_pstrcat(scratch_pool, hexdigest, PRISTINE_STORAGE_EXT,
83 /* The file is located at DIR/.svn/pristine/XX/XXYYZZ...svn-base */
84 *pristine_abspath = svn_dirent_join_many(result_pool,
94 svn_wc__db_pristine_get_path(const char **pristine_abspath,
96 const char *wri_abspath,
97 const svn_checksum_t *sha1_checksum,
98 apr_pool_t *result_pool,
99 apr_pool_t *scratch_pool)
101 svn_wc__db_wcroot_t *wcroot;
102 const char *local_relpath;
103 svn_boolean_t present;
105 SVN_ERR_ASSERT(pristine_abspath != NULL);
106 SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
107 SVN_ERR_ASSERT(sha1_checksum != NULL);
108 /* ### Transitional: accept MD-5 and look up the SHA-1. Return an error
109 * if the pristine text is not in the store. */
110 if (sha1_checksum->kind != svn_checksum_sha1)
111 SVN_ERR(svn_wc__db_pristine_get_sha1(&sha1_checksum, db, wri_abspath,
113 scratch_pool, scratch_pool));
114 SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
116 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath,
118 scratch_pool, scratch_pool));
119 VERIFY_USABLE_WCROOT(wcroot);
121 SVN_ERR(svn_wc__db_pristine_check(&present, db, wri_abspath, sha1_checksum,
124 return svn_error_createf(SVN_ERR_WC_DB_ERROR, NULL,
125 _("The pristine text with checksum '%s' was "
127 svn_checksum_to_cstring_display(sha1_checksum,
130 SVN_ERR(get_pristine_fname(pristine_abspath, wcroot->abspath,
132 result_pool, scratch_pool));
138 svn_wc__db_pristine_get_future_path(const char **pristine_abspath,
139 const char *wcroot_abspath,
140 const svn_checksum_t *sha1_checksum,
141 apr_pool_t *result_pool,
142 apr_pool_t *scratch_pool)
144 SVN_ERR(get_pristine_fname(pristine_abspath, wcroot_abspath,
146 result_pool, scratch_pool));
150 /* Set *CONTENTS to a readable stream from which the pristine text
151 * identified by SHA1_CHECKSUM and PRISTINE_ABSPATH can be read from the
152 * pristine store of WCROOT. If SIZE is not null, set *SIZE to the size
153 * in bytes of that text. If that text is not in the pristine store,
156 * Even if the pristine text is removed from the store while it is being
157 * read, the stream will remain valid and readable until it is closed.
159 * Allocate the stream in RESULT_POOL.
161 * This function expects to be executed inside a SQLite txn.
163 * Implements 'notes/wc-ng/pristine-store' section A-3(d).
166 pristine_read_txn(svn_stream_t **contents,
167 svn_filesize_t *size,
168 svn_wc__db_wcroot_t *wcroot,
169 const svn_checksum_t *sha1_checksum,
170 const char *pristine_abspath,
171 apr_pool_t *result_pool,
172 apr_pool_t *scratch_pool)
174 svn_sqlite__stmt_t *stmt;
175 svn_boolean_t have_row;
177 /* Check that this pristine text is present in the store. (The presence
178 * of the file is not sufficient.) */
179 SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
180 STMT_SELECT_PRISTINE_SIZE));
181 SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
182 SVN_ERR(svn_sqlite__step(&have_row, stmt));
185 *size = svn_sqlite__column_int64(stmt, 0);
187 SVN_ERR(svn_sqlite__reset(stmt));
190 return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
191 _("Pristine text '%s' not present"),
192 svn_checksum_to_cstring_display(
193 sha1_checksum, scratch_pool));
196 /* Open the file as a readable stream. It will remain readable even when
197 * deleted from disk; APR guarantees that on Windows as well as Unix. */
199 SVN_ERR(svn_stream_open_readonly(contents, pristine_abspath,
200 result_pool, scratch_pool));
205 svn_wc__db_pristine_read(svn_stream_t **contents,
206 svn_filesize_t *size,
208 const char *wri_abspath,
209 const svn_checksum_t *sha1_checksum,
210 apr_pool_t *result_pool,
211 apr_pool_t *scratch_pool)
213 svn_wc__db_wcroot_t *wcroot;
214 const char *local_relpath;
215 const char *pristine_abspath;
217 SVN_ERR_ASSERT(contents != NULL);
218 SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
220 /* Some 1.6-to-1.7 wc upgrades created rows without checksums and
221 updating such a row passes NULL here. */
223 return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
224 _("Can't read '%s' from pristine store "
225 "because no checksum supplied"),
226 svn_dirent_local_style(wri_abspath, scratch_pool));
228 SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
230 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
231 wri_abspath, scratch_pool, scratch_pool));
232 VERIFY_USABLE_WCROOT(wcroot);
234 SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
236 scratch_pool, scratch_pool));
238 pristine_read_txn(contents, size,
239 wcroot, sha1_checksum, pristine_abspath,
240 result_pool, scratch_pool),
247 /* Return the absolute path to the temporary directory for pristine text
248 files within WCROOT. */
250 pristine_get_tempdir(svn_wc__db_wcroot_t *wcroot,
251 apr_pool_t *result_pool,
252 apr_pool_t *scratch_pool)
254 return svn_dirent_join_many(result_pool, wcroot->abspath,
255 svn_wc_get_adm_dir(scratch_pool),
256 PRISTINE_TEMPDIR_RELPATH, (char *)NULL);
260 svn_wc__db_pristine_get_tempdir(const char **temp_dir_abspath,
262 const char *wri_abspath,
263 apr_pool_t *result_pool,
264 apr_pool_t *scratch_pool)
266 svn_wc__db_wcroot_t *wcroot;
267 const char *local_relpath;
269 SVN_ERR_ASSERT(temp_dir_abspath != NULL);
270 SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
272 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
273 wri_abspath, scratch_pool, scratch_pool));
274 VERIFY_USABLE_WCROOT(wcroot);
276 *temp_dir_abspath = pristine_get_tempdir(wcroot, result_pool, scratch_pool);
281 /* Install the pristine text described by BATON into the pristine store of
282 * SDB. If it is already stored then just delete the new file
283 * BATON->tempfile_abspath.
285 * This function expects to be executed inside a SQLite txn that has already
286 * acquired a 'RESERVED' lock.
288 * Implements 'notes/wc-ng/pristine-store' section A-3(a).
291 pristine_install_txn(svn_sqlite__db_t *sdb,
292 /* The path to the source file that is to be moved into place. */
293 const char *tempfile_abspath,
294 /* The target path for the file (within the pristine store). */
295 const char *pristine_abspath,
296 /* The pristine text's SHA-1 checksum. */
297 const svn_checksum_t *sha1_checksum,
298 /* The pristine text's MD-5 checksum. */
299 const svn_checksum_t *md5_checksum,
300 apr_pool_t *scratch_pool)
303 svn_sqlite__stmt_t *stmt;
304 svn_boolean_t have_row;
307 /* If this pristine text is already present in the store, just keep it:
308 * delete the new one and return. */
309 SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_PRISTINE));
310 SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
311 SVN_ERR(svn_sqlite__step(&have_row, stmt));
312 SVN_ERR(svn_sqlite__reset(stmt));
316 /* Consistency checks. Verify both files exist and match.
317 * ### We could check much more. */
319 apr_finfo_t finfo1, finfo2;
320 SVN_ERR(svn_io_stat(&finfo1, tempfile_abspath, APR_FINFO_SIZE,
322 SVN_ERR(svn_io_stat(&finfo2, pristine_abspath, APR_FINFO_SIZE,
324 if (finfo1.size != finfo2.size)
326 return svn_error_createf(
327 SVN_ERR_WC_CORRUPT_TEXT_BASE, NULL,
328 _("New pristine text '%s' has different size: %ld versus %ld"),
329 svn_checksum_to_cstring_display(sha1_checksum, scratch_pool),
330 (long int)finfo1.size, (long int)finfo2.size);
335 /* Remove the temp file: it's already there */
336 SVN_ERR(svn_io_remove_file2(tempfile_abspath,
337 FALSE /* ignore_enoent */, scratch_pool));
341 /* Move the file to its target location. (If it is already there, it is
342 * an orphan file and it doesn't matter if we overwrite it.) */
343 err = svn_io_file_rename(tempfile_abspath, pristine_abspath,
346 /* Maybe the directory doesn't exist yet? */
347 if (err && APR_STATUS_IS_ENOENT(err->apr_err))
351 err2 = svn_io_dir_make(svn_dirent_dirname(pristine_abspath,
353 APR_OS_DEFAULT, scratch_pool);
356 /* Creating directory didn't work: Return all errors */
357 return svn_error_trace(svn_error_compose_create(err, err2));
359 /* We could create a directory: retry install */
360 svn_error_clear(err);
362 SVN_ERR(svn_io_file_rename(tempfile_abspath, pristine_abspath,
368 SVN_ERR(svn_io_stat(&finfo, pristine_abspath, APR_FINFO_SIZE,
371 SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
372 STMT_INSERT_PRISTINE));
373 SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
374 SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, md5_checksum, scratch_pool));
375 SVN_ERR(svn_sqlite__bind_int64(stmt, 3, finfo.size));
376 SVN_ERR(svn_sqlite__insert(NULL, stmt));
383 svn_wc__db_pristine_install(svn_wc__db_t *db,
384 const char *tempfile_abspath,
385 const svn_checksum_t *sha1_checksum,
386 const svn_checksum_t *md5_checksum,
387 apr_pool_t *scratch_pool)
389 svn_wc__db_wcroot_t *wcroot;
390 const char *local_relpath;
391 const char *wri_abspath;
392 const char *pristine_abspath;
394 SVN_ERR_ASSERT(svn_dirent_is_absolute(tempfile_abspath));
395 SVN_ERR_ASSERT(sha1_checksum != NULL);
396 SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
397 SVN_ERR_ASSERT(md5_checksum != NULL);
398 SVN_ERR_ASSERT(md5_checksum->kind == svn_checksum_md5);
400 /* ### this logic assumes that TEMPFILE_ABSPATH follows this pattern:
401 ### WCROOT_ABSPATH/COMPONENT/COMPONENT/TEMPFNAME
402 ### if we change this (see PRISTINE_TEMPDIR_RELPATH), then this
403 ### logic should change. */
404 wri_abspath = svn_dirent_dirname(
406 svn_dirent_dirname(tempfile_abspath, scratch_pool),
410 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
411 wri_abspath, scratch_pool, scratch_pool));
412 VERIFY_USABLE_WCROOT(wcroot);
414 SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
416 scratch_pool, scratch_pool));
418 /* Ensure the SQL txn has at least a 'RESERVED' lock before we start looking
419 * at the disk, to ensure no concurrent pristine install/delete txn. */
420 SVN_SQLITE__WITH_IMMEDIATE_TXN(
421 pristine_install_txn(wcroot->sdb,
422 tempfile_abspath, pristine_abspath,
423 sha1_checksum, md5_checksum,
432 svn_wc__db_pristine_get_md5(const svn_checksum_t **md5_checksum,
434 const char *wri_abspath,
435 const svn_checksum_t *sha1_checksum,
436 apr_pool_t *result_pool,
437 apr_pool_t *scratch_pool)
439 svn_wc__db_wcroot_t *wcroot;
440 const char *local_relpath;
441 svn_sqlite__stmt_t *stmt;
442 svn_boolean_t have_row;
444 SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
445 SVN_ERR_ASSERT(sha1_checksum != NULL);
446 SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
448 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
449 wri_abspath, scratch_pool, scratch_pool));
450 VERIFY_USABLE_WCROOT(wcroot);
452 SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_PRISTINE));
453 SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
454 SVN_ERR(svn_sqlite__step(&have_row, stmt));
456 return svn_error_createf(SVN_ERR_WC_DB_ERROR, svn_sqlite__reset(stmt),
457 _("The pristine text with checksum '%s' was "
459 svn_checksum_to_cstring_display(sha1_checksum,
462 SVN_ERR(svn_sqlite__column_checksum(md5_checksum, stmt, 0, result_pool));
463 SVN_ERR_ASSERT((*md5_checksum)->kind == svn_checksum_md5);
465 return svn_error_trace(svn_sqlite__reset(stmt));
470 svn_wc__db_pristine_get_sha1(const svn_checksum_t **sha1_checksum,
472 const char *wri_abspath,
473 const svn_checksum_t *md5_checksum,
474 apr_pool_t *result_pool,
475 apr_pool_t *scratch_pool)
477 svn_wc__db_wcroot_t *wcroot;
478 const char *local_relpath;
479 svn_sqlite__stmt_t *stmt;
480 svn_boolean_t have_row;
482 SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
483 SVN_ERR_ASSERT(sha1_checksum != NULL);
484 SVN_ERR_ASSERT(md5_checksum->kind == svn_checksum_md5);
486 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
487 wri_abspath, scratch_pool, scratch_pool));
488 VERIFY_USABLE_WCROOT(wcroot);
490 SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
491 STMT_SELECT_PRISTINE_BY_MD5));
492 SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, md5_checksum, scratch_pool));
493 SVN_ERR(svn_sqlite__step(&have_row, stmt));
495 return svn_error_createf(SVN_ERR_WC_DB_ERROR, svn_sqlite__reset(stmt),
496 _("The pristine text with MD5 checksum '%s' was "
498 svn_checksum_to_cstring_display(md5_checksum,
501 SVN_ERR(svn_sqlite__column_checksum(sha1_checksum, stmt, 0, result_pool));
502 SVN_ERR_ASSERT((*sha1_checksum)->kind == svn_checksum_sha1);
504 return svn_error_trace(svn_sqlite__reset(stmt));
507 /* Handle the moving of a pristine from SRC_WCROOT to DST_WCROOT. The existing
508 pristine in SRC_WCROOT is described by CHECKSUM, MD5_CHECKSUM and SIZE */
510 maybe_transfer_one_pristine(svn_wc__db_wcroot_t *src_wcroot,
511 svn_wc__db_wcroot_t *dst_wcroot,
512 const svn_checksum_t *checksum,
513 const svn_checksum_t *md5_checksum,
515 svn_cancel_func_t cancel_func,
517 apr_pool_t *scratch_pool)
519 const char *pristine_abspath;
520 svn_sqlite__stmt_t *stmt;
521 svn_stream_t *src_stream;
522 svn_stream_t *dst_stream;
523 const char *tmp_abspath;
524 const char *src_abspath;
528 SVN_ERR(svn_sqlite__get_statement(&stmt, dst_wcroot->sdb,
529 STMT_INSERT_OR_IGNORE_PRISTINE));
530 SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, checksum, scratch_pool));
531 SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, md5_checksum, scratch_pool));
532 SVN_ERR(svn_sqlite__bind_int64(stmt, 3, size));
534 SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
536 if (affected_rows == 0)
539 SVN_ERR(svn_stream_open_unique(&dst_stream, &tmp_abspath,
540 pristine_get_tempdir(dst_wcroot,
543 svn_io_file_del_on_pool_cleanup,
544 scratch_pool, scratch_pool));
546 SVN_ERR(get_pristine_fname(&src_abspath, src_wcroot->abspath, checksum,
547 scratch_pool, scratch_pool));
549 SVN_ERR(svn_stream_open_readonly(&src_stream, src_abspath,
550 scratch_pool, scratch_pool));
552 /* ### Should we verify the SHA1 or MD5 here, or is that too expensive? */
553 SVN_ERR(svn_stream_copy3(src_stream, dst_stream,
554 cancel_func, cancel_baton,
557 SVN_ERR(get_pristine_fname(&pristine_abspath, dst_wcroot->abspath, checksum,
558 scratch_pool, scratch_pool));
560 /* Move the file to its target location. (If it is already there, it is
561 * an orphan file and it doesn't matter if we overwrite it.) */
562 err = svn_io_file_rename(tmp_abspath, pristine_abspath, scratch_pool);
564 /* Maybe the directory doesn't exist yet? */
565 if (err && APR_STATUS_IS_ENOENT(err->apr_err))
569 err2 = svn_io_dir_make(svn_dirent_dirname(pristine_abspath,
571 APR_OS_DEFAULT, scratch_pool);
574 /* Creating directory didn't work: Return all errors */
575 return svn_error_trace(svn_error_compose_create(err, err2));
577 /* We could create a directory: retry install */
578 svn_error_clear(err);
580 SVN_ERR(svn_io_file_rename(tmp_abspath, pristine_abspath, scratch_pool));
588 /* Transaction implementation of svn_wc__db_pristine_transfer().
589 We have a lock on DST_WCROOT.
592 pristine_transfer_txn(svn_wc__db_wcroot_t *src_wcroot,
593 svn_wc__db_wcroot_t *dst_wcroot,
594 const char *src_relpath,
595 svn_cancel_func_t cancel_func,
597 apr_pool_t *scratch_pool)
599 svn_sqlite__stmt_t *stmt;
600 svn_boolean_t got_row;
601 apr_pool_t *iterpool = svn_pool_create(scratch_pool);
603 SVN_ERR(svn_sqlite__get_statement(&stmt, src_wcroot->sdb,
604 STMT_SELECT_COPY_PRISTINES));
605 SVN_ERR(svn_sqlite__bindf(stmt, "is", src_wcroot->wc_id, src_relpath));
607 /* This obtains an sqlite read lock on src_wcroot */
608 SVN_ERR(svn_sqlite__step(&got_row, stmt));
612 const svn_checksum_t *checksum;
613 const svn_checksum_t *md5_checksum;
617 svn_pool_clear(iterpool);
619 SVN_ERR(svn_sqlite__column_checksum(&checksum, stmt, 0, iterpool));
620 SVN_ERR(svn_sqlite__column_checksum(&md5_checksum, stmt, 1, iterpool));
621 size = svn_sqlite__column_int64(stmt, 2);
623 err = maybe_transfer_one_pristine(src_wcroot, dst_wcroot,
624 checksum, md5_checksum, size,
625 cancel_func, cancel_baton,
629 return svn_error_trace(svn_error_compose_create(
631 svn_sqlite__reset(stmt)));
633 SVN_ERR(svn_sqlite__step(&got_row, stmt));
635 SVN_ERR(svn_sqlite__reset(stmt));
637 svn_pool_destroy(iterpool);
643 svn_wc__db_pristine_transfer(svn_wc__db_t *db,
644 const char *src_local_abspath,
645 const char *dst_wri_abspath,
646 svn_cancel_func_t cancel_func,
648 apr_pool_t *scratch_pool)
650 svn_wc__db_wcroot_t *src_wcroot, *dst_wcroot;
651 const char *src_relpath, *dst_relpath;
653 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&src_wcroot, &src_relpath,
654 db, src_local_abspath,
655 scratch_pool, scratch_pool));
656 VERIFY_USABLE_WCROOT(src_wcroot);
657 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&dst_wcroot, &dst_relpath,
659 scratch_pool, scratch_pool));
660 VERIFY_USABLE_WCROOT(dst_wcroot);
662 if (src_wcroot == dst_wcroot
663 || src_wcroot->sdb == dst_wcroot->sdb)
665 return SVN_NO_ERROR; /* Nothing to transfer */
669 pristine_transfer_txn(src_wcroot, dst_wcroot, src_relpath,
670 cancel_func, cancel_baton, scratch_pool),
679 /* Remove the file at FILE_ABSPATH in such a way that we could re-create a
680 * new file of the same name at any time thereafter.
682 * On Windows, the file will not disappear immediately from the directory if
683 * it is still being read so the best thing to do is first rename it to a
686 remove_file(const char *file_abspath,
687 svn_wc__db_wcroot_t *wcroot,
688 svn_boolean_t ignore_enoent,
689 apr_pool_t *scratch_pool)
693 const char *temp_abspath;
694 const char *temp_dir_abspath
695 = pristine_get_tempdir(wcroot, scratch_pool, scratch_pool);
697 /* To rename the file to a unique name in the temp dir, first create a
698 * uniquely named file in the temp dir and then overwrite it. */
699 SVN_ERR(svn_io_open_unique_file3(NULL, &temp_abspath, temp_dir_abspath,
700 svn_io_file_del_none,
701 scratch_pool, scratch_pool));
702 err = svn_io_file_rename(file_abspath, temp_abspath, scratch_pool);
703 if (err && ignore_enoent && APR_STATUS_IS_ENOENT(err->apr_err))
704 svn_error_clear(err);
707 file_abspath = temp_abspath;
710 SVN_ERR(svn_io_remove_file2(file_abspath, ignore_enoent, scratch_pool));
715 /* If the pristine text referenced by SHA1_CHECKSUM in WCROOT/SDB, whose path
716 * within the pristine store is PRISTINE_ABSPATH, has a reference count of
717 * zero, delete it (both the database row and the disk file).
719 * This function expects to be executed inside a SQLite txn that has already
720 * acquired a 'RESERVED' lock.
723 pristine_remove_if_unreferenced_txn(svn_sqlite__db_t *sdb,
724 svn_wc__db_wcroot_t *wcroot,
725 const svn_checksum_t *sha1_checksum,
726 const char *pristine_abspath,
727 apr_pool_t *scratch_pool)
729 svn_sqlite__stmt_t *stmt;
732 /* Remove the DB row, if refcount is 0. */
733 SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
734 STMT_DELETE_PRISTINE_IF_UNREFERENCED));
735 SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
736 SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
738 /* If we removed the DB row, then remove the file. */
739 if (affected_rows > 0)
741 /* If the file is not present, something has gone wrong, but at this
742 * point it no longer matters. In a debug build, raise an error, but
743 * in a release build, it is more helpful to ignore it and continue. */
745 svn_boolean_t ignore_enoent = FALSE;
747 svn_boolean_t ignore_enoent = TRUE;
750 SVN_ERR(remove_file(pristine_abspath, wcroot, ignore_enoent,
757 /* If the pristine text referenced by SHA1_CHECKSUM in WCROOT has a
758 * reference count of zero, delete it (both the database row and the disk
761 * Implements 'notes/wc-ng/pristine-store' section A-3(b). */
763 pristine_remove_if_unreferenced(svn_wc__db_wcroot_t *wcroot,
764 const svn_checksum_t *sha1_checksum,
765 apr_pool_t *scratch_pool)
767 const char *pristine_abspath;
769 SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
770 sha1_checksum, scratch_pool, scratch_pool));
772 /* Ensure the SQL txn has at least a 'RESERVED' lock before we start looking
773 * at the disk, to ensure no concurrent pristine install/delete txn. */
774 SVN_SQLITE__WITH_IMMEDIATE_TXN(
775 pristine_remove_if_unreferenced_txn(
776 wcroot->sdb, wcroot, sha1_checksum, pristine_abspath, scratch_pool),
783 svn_wc__db_pristine_remove(svn_wc__db_t *db,
784 const char *wri_abspath,
785 const svn_checksum_t *sha1_checksum,
786 apr_pool_t *scratch_pool)
788 svn_wc__db_wcroot_t *wcroot;
789 const char *local_relpath;
791 SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
792 SVN_ERR_ASSERT(sha1_checksum != NULL);
793 /* ### Transitional: accept MD-5 and look up the SHA-1. Return an error
794 * if the pristine text is not in the store. */
795 if (sha1_checksum->kind != svn_checksum_sha1)
796 SVN_ERR(svn_wc__db_pristine_get_sha1(&sha1_checksum, db, wri_abspath,
798 scratch_pool, scratch_pool));
799 SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
801 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
802 wri_abspath, scratch_pool, scratch_pool));
803 VERIFY_USABLE_WCROOT(wcroot);
805 /* If the work queue is not empty, don't delete any pristine text because
806 * the work queue may contain a reference to it. */
808 svn_sqlite__stmt_t *stmt;
809 svn_boolean_t have_row;
811 SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_LOOK_FOR_WORK));
812 SVN_ERR(svn_sqlite__step(&have_row, stmt));
813 SVN_ERR(svn_sqlite__reset(stmt));
819 /* If not referenced, remove the PRISTINE table row and the file. */
820 SVN_ERR(pristine_remove_if_unreferenced(wcroot, sha1_checksum, scratch_pool));
827 pristine_cleanup_wcroot(svn_wc__db_wcroot_t *wcroot,
828 apr_pool_t *scratch_pool)
830 svn_sqlite__stmt_t *stmt;
831 svn_error_t *err = NULL;
833 /* Find each unreferenced pristine in the DB and remove it. */
834 SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
835 STMT_SELECT_UNREFERENCED_PRISTINES));
838 svn_boolean_t have_row;
839 const svn_checksum_t *sha1_checksum;
841 SVN_ERR(svn_sqlite__step(&have_row, stmt));
845 SVN_ERR(svn_sqlite__column_checksum(&sha1_checksum, stmt, 0,
847 err = pristine_remove_if_unreferenced(wcroot, sha1_checksum,
851 return svn_error_trace(
852 svn_error_compose_create(err, svn_sqlite__reset(stmt)));
856 svn_wc__db_pristine_cleanup(svn_wc__db_t *db,
857 const char *wri_abspath,
858 apr_pool_t *scratch_pool)
860 svn_wc__db_wcroot_t *wcroot;
861 const char *local_relpath;
863 SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
865 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
866 wri_abspath, scratch_pool, scratch_pool));
867 VERIFY_USABLE_WCROOT(wcroot);
869 SVN_ERR(pristine_cleanup_wcroot(wcroot, scratch_pool));
876 svn_wc__db_pristine_check(svn_boolean_t *present,
878 const char *wri_abspath,
879 const svn_checksum_t *sha1_checksum,
880 apr_pool_t *scratch_pool)
882 svn_wc__db_wcroot_t *wcroot;
883 const char *local_relpath;
884 svn_sqlite__stmt_t *stmt;
885 svn_boolean_t have_row;
887 SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
888 SVN_ERR_ASSERT(sha1_checksum != NULL);
890 if (sha1_checksum->kind != svn_checksum_sha1)
896 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
897 wri_abspath, scratch_pool, scratch_pool));
898 VERIFY_USABLE_WCROOT(wcroot);
900 /* A filestat is much cheaper than a sqlite transaction especially on NFS,
901 so first check if there is a pristine file and then if we are allowed
904 const char *pristine_abspath;
905 svn_node_kind_t kind_on_disk;
907 SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
908 sha1_checksum, scratch_pool, scratch_pool));
909 SVN_ERR(svn_io_check_path(pristine_abspath, &kind_on_disk, scratch_pool));
910 if (kind_on_disk != svn_node_file)
917 /* Check that there is an entry in the PRISTINE table. */
918 SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_PRISTINE));
919 SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
920 SVN_ERR(svn_sqlite__step(&have_row, stmt));
921 SVN_ERR(svn_sqlite__reset(stmt));