Win32: fix an incorrect error status being propagated to the caller in case
[svn/apache.git] / subversion / libsvn_wc / wc_db_pristine.c
blob90b35774df485d0849dbd2d4f6f97f842bb1796c
1 /*
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
22 * under the License.
23 * ====================================================================
26 #define SVN_WC__I_AM_WC_DB
28 #include "svn_pools.h"
29 #include "svn_io.h"
30 #include "svn_dirent_uri.h"
32 #include "private/svn_io_private.h"
34 #include "wc.h"
35 #include "wc_db.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. */
52 static svn_error_t *
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);
61 char subdir[3];
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,
70 wcroot_abspath,
71 svn_wc_get_adm_dir(scratch_pool),
72 PRISTINE_STORAGE_RELPATH,
73 SVN_VA_NULL);
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];
81 subdir[2] = '\0';
83 hexdigest = apr_pstrcat(scratch_pool, hexdigest, PRISTINE_STORAGE_EXT,
84 SVN_VA_NULL);
86 /* The file is located at DIR/.svn/pristine/XX/XXYYZZ...svn-base */
87 *pristine_abspath = svn_dirent_join_many(result_pool,
88 base_dir_abspath,
89 subdir,
90 hexdigest,
91 SVN_VA_NULL);
92 return SVN_NO_ERROR;
96 svn_error_t *
97 svn_wc__db_pristine_get_path(const char **pristine_abspath,
98 svn_wc__db_t *db,
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,
115 sha1_checksum,
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,
120 db, wri_abspath,
121 scratch_pool, scratch_pool));
122 VERIFY_USABLE_WCROOT(wcroot);
124 SVN_ERR(svn_wc__db_pristine_check(&present, db, wri_abspath, sha1_checksum,
125 scratch_pool));
126 if (! present)
127 return svn_error_createf(SVN_ERR_WC_DB_ERROR, NULL,
128 _("The pristine text with checksum '%s' was "
129 "not found"),
130 svn_checksum_to_cstring_display(sha1_checksum,
131 scratch_pool));
133 SVN_ERR(get_pristine_fname(pristine_abspath, wcroot->abspath,
134 sha1_checksum,
135 result_pool, scratch_pool));
137 return SVN_NO_ERROR;
140 svn_error_t *
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,
148 sha1_checksum,
149 result_pool, scratch_pool));
150 return SVN_NO_ERROR;
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,
157 * return an error.
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).
168 static svn_error_t *
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));
187 if (size)
188 *size = svn_sqlite__column_int64(stmt, 0);
190 SVN_ERR(svn_sqlite__reset(stmt));
191 if (! have_row)
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
205 * buffers. */
206 if (contents)
208 apr_file_t *file;
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);
214 return SVN_NO_ERROR;
217 svn_error_t *
218 svn_wc__db_pristine_read(svn_stream_t **contents,
219 svn_filesize_t *size,
220 svn_wc__db_t *db,
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(svn_dirent_is_absolute(wri_abspath));
232 /* Some 1.6-to-1.7 wc upgrades created rows without checksums and
233 updating such a row passes NULL here. */
234 if (!sha1_checksum)
235 return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
236 _("Can't read '%s' from pristine store "
237 "because no checksum supplied"),
238 svn_dirent_local_style(wri_abspath, scratch_pool));
240 SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
242 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
243 wri_abspath, scratch_pool, scratch_pool));
244 VERIFY_USABLE_WCROOT(wcroot);
246 SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
247 sha1_checksum,
248 scratch_pool, scratch_pool));
249 SVN_WC__DB_WITH_TXN(
250 pristine_read_txn(contents, size,
251 wcroot, sha1_checksum, pristine_abspath,
252 result_pool, scratch_pool),
253 wcroot);
255 return SVN_NO_ERROR;
259 /* Return the absolute path to the temporary directory for pristine text
260 files within WCROOT. */
261 static char *
262 pristine_get_tempdir(svn_wc__db_wcroot_t *wcroot,
263 apr_pool_t *result_pool,
264 apr_pool_t *scratch_pool)
266 return svn_dirent_join_many(result_pool, wcroot->abspath,
267 svn_wc_get_adm_dir(scratch_pool),
268 PRISTINE_TEMPDIR_RELPATH, SVN_VA_NULL);
271 /* Install the pristine text described by BATON into the pristine store of
272 * SDB. If it is already stored then just delete the new file
273 * BATON->tempfile_abspath.
275 * This function expects to be executed inside a SQLite txn that has already
276 * acquired a 'RESERVED' lock.
278 * Implements 'notes/wc-ng/pristine-store' section A-3(a).
280 static svn_error_t *
281 pristine_install_txn(svn_sqlite__db_t *sdb,
282 /* The path to the source file that is to be moved into place. */
283 svn_stream_t *install_stream,
284 /* The target path for the file (within the pristine store). */
285 const char *pristine_abspath,
286 /* The pristine text's SHA-1 checksum. */
287 const svn_checksum_t *sha1_checksum,
288 /* The pristine text's MD-5 checksum. */
289 const svn_checksum_t *md5_checksum,
290 apr_pool_t *scratch_pool)
292 svn_sqlite__stmt_t *stmt;
293 svn_boolean_t have_row;
295 /* If this pristine text is already present in the store, just keep it:
296 * delete the new one and return. */
297 SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_PRISTINE));
298 SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
299 SVN_ERR(svn_sqlite__step(&have_row, stmt));
300 SVN_ERR(svn_sqlite__reset(stmt));
302 if (have_row)
304 #ifdef SVN_DEBUG
305 /* Consistency checks. Verify both files exist and match.
306 * ### We could check much more. */
308 apr_finfo_t finfo1, finfo2;
310 SVN_ERR(svn_stream__install_get_info(&finfo1, install_stream, APR_FINFO_SIZE,
311 scratch_pool));
313 SVN_ERR(svn_io_stat(&finfo2, pristine_abspath, APR_FINFO_SIZE,
314 scratch_pool));
315 if (finfo1.size != finfo2.size)
317 return svn_error_createf(
318 SVN_ERR_WC_CORRUPT_TEXT_BASE, NULL,
319 _("New pristine text '%s' has different size: %s versus %s"),
320 svn_checksum_to_cstring_display(sha1_checksum, scratch_pool),
321 apr_off_t_toa(scratch_pool, finfo1.size),
322 apr_off_t_toa(scratch_pool, finfo2.size));
325 #endif
327 /* Remove the temp file: it's already there */
328 SVN_ERR(svn_stream__install_delete(install_stream, scratch_pool));
329 return SVN_NO_ERROR;
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.) */
335 apr_finfo_t finfo;
336 SVN_ERR(svn_stream__install_get_info(&finfo, install_stream,
337 APR_FINFO_SIZE, scratch_pool));
338 SVN_ERR(svn_stream__install_stream(install_stream, pristine_abspath,
339 TRUE, scratch_pool));
341 SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_INSERT_PRISTINE));
342 SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
343 SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, md5_checksum, scratch_pool));
344 SVN_ERR(svn_sqlite__bind_int64(stmt, 3, finfo.size));
345 SVN_ERR(svn_sqlite__insert(NULL, stmt));
347 SVN_ERR(svn_io_set_file_read_only(pristine_abspath, FALSE, scratch_pool));
350 return SVN_NO_ERROR;
353 struct svn_wc__db_install_data_t
355 svn_wc__db_wcroot_t *wcroot;
356 svn_stream_t *inner_stream;
359 svn_error_t *
360 svn_wc__db_pristine_prepare_install(svn_stream_t **stream,
361 svn_wc__db_install_data_t **install_data,
362 svn_checksum_t **sha1_checksum,
363 svn_checksum_t **md5_checksum,
364 svn_wc__db_t *db,
365 const char *wri_abspath,
366 apr_pool_t *result_pool,
367 apr_pool_t *scratch_pool)
369 svn_wc__db_wcroot_t *wcroot;
370 const char *local_relpath;
371 const char *temp_dir_abspath;
373 SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
375 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
376 wri_abspath, scratch_pool, scratch_pool));
377 VERIFY_USABLE_WCROOT(wcroot);
379 temp_dir_abspath = pristine_get_tempdir(wcroot, scratch_pool, scratch_pool);
381 *install_data = apr_pcalloc(result_pool, sizeof(**install_data));
382 (*install_data)->wcroot = wcroot;
384 SVN_ERR_W(svn_stream__create_for_install(stream,
385 temp_dir_abspath,
386 result_pool, scratch_pool),
387 _("Unable to create pristine install stream"));
389 (*install_data)->inner_stream = *stream;
391 if (md5_checksum)
392 *stream = svn_stream_checksummed2(*stream, NULL, md5_checksum,
393 svn_checksum_md5, FALSE, result_pool);
394 if (sha1_checksum)
395 *stream = svn_stream_checksummed2(*stream, NULL, sha1_checksum,
396 svn_checksum_sha1, FALSE, result_pool);
398 return SVN_NO_ERROR;
401 svn_error_t *
402 svn_wc__db_pristine_install(svn_wc__db_install_data_t *install_data,
403 const svn_checksum_t *sha1_checksum,
404 const svn_checksum_t *md5_checksum,
405 apr_pool_t *scratch_pool)
407 svn_wc__db_wcroot_t *wcroot = install_data->wcroot;
408 const char *pristine_abspath;
410 SVN_ERR_ASSERT(sha1_checksum != NULL);
411 SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
412 SVN_ERR_ASSERT(md5_checksum != NULL);
413 SVN_ERR_ASSERT(md5_checksum->kind == svn_checksum_md5);
415 SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
416 sha1_checksum,
417 scratch_pool, scratch_pool));
419 /* Ensure the SQL txn has at least a 'RESERVED' lock before we start looking
420 * at the disk, to ensure no concurrent pristine install/delete txn. */
421 SVN_SQLITE__WITH_IMMEDIATE_TXN(
422 pristine_install_txn(wcroot->sdb,
423 install_data->inner_stream, pristine_abspath,
424 sha1_checksum, md5_checksum,
425 scratch_pool),
426 wcroot->sdb);
428 return SVN_NO_ERROR;
431 svn_error_t *
432 svn_wc__db_pristine_install_abort(svn_wc__db_install_data_t *install_data,
433 apr_pool_t *scratch_pool)
435 return svn_error_trace(svn_stream__install_delete(install_data->inner_stream,
436 scratch_pool));
440 svn_error_t *
441 svn_wc__db_pristine_get_md5(const svn_checksum_t **md5_checksum,
442 svn_wc__db_t *db,
443 const char *wri_abspath,
444 const svn_checksum_t *sha1_checksum,
445 apr_pool_t *result_pool,
446 apr_pool_t *scratch_pool)
448 svn_wc__db_wcroot_t *wcroot;
449 const char *local_relpath;
450 svn_sqlite__stmt_t *stmt;
451 svn_boolean_t have_row;
453 SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
454 SVN_ERR_ASSERT(sha1_checksum != NULL);
455 SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
457 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
458 wri_abspath, scratch_pool, scratch_pool));
459 VERIFY_USABLE_WCROOT(wcroot);
461 SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_PRISTINE));
462 SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
463 SVN_ERR(svn_sqlite__step(&have_row, stmt));
464 if (!have_row)
465 return svn_error_createf(SVN_ERR_WC_DB_ERROR, svn_sqlite__reset(stmt),
466 _("The pristine text with checksum '%s' was "
467 "not found"),
468 svn_checksum_to_cstring_display(sha1_checksum,
469 scratch_pool));
471 SVN_ERR(svn_sqlite__column_checksum(md5_checksum, stmt, 0, result_pool));
472 SVN_ERR_ASSERT((*md5_checksum)->kind == svn_checksum_md5);
474 return svn_error_trace(svn_sqlite__reset(stmt));
478 svn_error_t *
479 svn_wc__db_pristine_get_sha1(const svn_checksum_t **sha1_checksum,
480 svn_wc__db_t *db,
481 const char *wri_abspath,
482 const svn_checksum_t *md5_checksum,
483 apr_pool_t *result_pool,
484 apr_pool_t *scratch_pool)
486 svn_wc__db_wcroot_t *wcroot;
487 const char *local_relpath;
488 svn_sqlite__stmt_t *stmt;
489 svn_boolean_t have_row;
491 SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
492 SVN_ERR_ASSERT(sha1_checksum != NULL);
493 SVN_ERR_ASSERT(md5_checksum->kind == svn_checksum_md5);
495 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
496 wri_abspath, scratch_pool, scratch_pool));
497 VERIFY_USABLE_WCROOT(wcroot);
499 SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
500 STMT_SELECT_PRISTINE_BY_MD5));
501 SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, md5_checksum, scratch_pool));
502 SVN_ERR(svn_sqlite__step(&have_row, stmt));
503 if (!have_row)
504 return svn_error_createf(SVN_ERR_WC_DB_ERROR, svn_sqlite__reset(stmt),
505 _("The pristine text with MD5 checksum '%s' was "
506 "not found"),
507 svn_checksum_to_cstring_display(md5_checksum,
508 scratch_pool));
510 SVN_ERR(svn_sqlite__column_checksum(sha1_checksum, stmt, 0, result_pool));
511 SVN_ERR_ASSERT((*sha1_checksum)->kind == svn_checksum_sha1);
513 return svn_error_trace(svn_sqlite__reset(stmt));
516 /* Handle the moving of a pristine from SRC_WCROOT to DST_WCROOT. The existing
517 pristine in SRC_WCROOT is described by CHECKSUM, MD5_CHECKSUM and SIZE */
518 static svn_error_t *
519 maybe_transfer_one_pristine(svn_wc__db_wcroot_t *src_wcroot,
520 svn_wc__db_wcroot_t *dst_wcroot,
521 const svn_checksum_t *checksum,
522 const svn_checksum_t *md5_checksum,
523 apr_int64_t size,
524 svn_cancel_func_t cancel_func,
525 void *cancel_baton,
526 apr_pool_t *scratch_pool)
528 const char *pristine_abspath;
529 svn_sqlite__stmt_t *stmt;
530 svn_stream_t *src_stream;
531 svn_stream_t *dst_stream;
532 const char *tmp_abspath;
533 const char *src_abspath;
534 int affected_rows;
535 svn_error_t *err;
537 SVN_ERR(svn_sqlite__get_statement(&stmt, dst_wcroot->sdb,
538 STMT_INSERT_OR_IGNORE_PRISTINE));
539 SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, checksum, scratch_pool));
540 SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, md5_checksum, scratch_pool));
541 SVN_ERR(svn_sqlite__bind_int64(stmt, 3, size));
543 SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
545 if (affected_rows == 0)
546 return SVN_NO_ERROR;
548 SVN_ERR(svn_stream_open_unique(&dst_stream, &tmp_abspath,
549 pristine_get_tempdir(dst_wcroot,
550 scratch_pool,
551 scratch_pool),
552 svn_io_file_del_on_pool_cleanup,
553 scratch_pool, scratch_pool));
555 SVN_ERR(get_pristine_fname(&src_abspath, src_wcroot->abspath, checksum,
556 scratch_pool, scratch_pool));
558 SVN_ERR(svn_stream_open_readonly(&src_stream, src_abspath,
559 scratch_pool, scratch_pool));
561 /* ### Should we verify the SHA1 or MD5 here, or is that too expensive? */
562 SVN_ERR(svn_stream_copy3(src_stream, dst_stream,
563 cancel_func, cancel_baton,
564 scratch_pool));
566 SVN_ERR(get_pristine_fname(&pristine_abspath, dst_wcroot->abspath, checksum,
567 scratch_pool, scratch_pool));
569 /* Move the file to its target location. (If it is already there, it is
570 * an orphan file and it doesn't matter if we overwrite it.) */
571 err = svn_io_file_rename2(tmp_abspath, pristine_abspath, FALSE,
572 scratch_pool);
574 /* Maybe the directory doesn't exist yet? */
575 if (err && APR_STATUS_IS_ENOENT(err->apr_err))
577 svn_error_t *err2;
579 err2 = svn_io_dir_make(svn_dirent_dirname(pristine_abspath,
580 scratch_pool),
581 APR_OS_DEFAULT, scratch_pool);
583 if (err2)
584 /* Creating directory didn't work: Return all errors */
585 return svn_error_trace(svn_error_compose_create(err, err2));
586 else
587 /* We could create a directory: retry install */
588 svn_error_clear(err);
590 SVN_ERR(svn_io_file_rename2(tmp_abspath, pristine_abspath, FALSE,
591 scratch_pool));
593 else
594 SVN_ERR(err);
596 return SVN_NO_ERROR;
599 /* Transaction implementation of svn_wc__db_pristine_transfer().
600 We have a lock on DST_WCROOT.
602 static svn_error_t *
603 pristine_transfer_txn(svn_wc__db_wcroot_t *src_wcroot,
604 svn_wc__db_wcroot_t *dst_wcroot,
605 const char *src_relpath,
606 svn_cancel_func_t cancel_func,
607 void *cancel_baton,
608 apr_pool_t *scratch_pool)
610 svn_sqlite__stmt_t *stmt;
611 svn_boolean_t got_row;
612 apr_pool_t *iterpool = svn_pool_create(scratch_pool);
614 SVN_ERR(svn_sqlite__get_statement(&stmt, src_wcroot->sdb,
615 STMT_SELECT_COPY_PRISTINES));
616 SVN_ERR(svn_sqlite__bindf(stmt, "is", src_wcroot->wc_id, src_relpath));
618 /* This obtains an sqlite read lock on src_wcroot */
619 SVN_ERR(svn_sqlite__step(&got_row, stmt));
621 while (got_row)
623 const svn_checksum_t *checksum;
624 const svn_checksum_t *md5_checksum;
625 apr_int64_t size;
626 svn_error_t *err;
628 svn_pool_clear(iterpool);
630 SVN_ERR(svn_sqlite__column_checksum(&checksum, stmt, 0, iterpool));
631 SVN_ERR(svn_sqlite__column_checksum(&md5_checksum, stmt, 1, iterpool));
632 size = svn_sqlite__column_int64(stmt, 2);
634 err = maybe_transfer_one_pristine(src_wcroot, dst_wcroot,
635 checksum, md5_checksum, size,
636 cancel_func, cancel_baton,
637 iterpool);
639 if (err)
640 return svn_error_trace(svn_error_compose_create(
641 err,
642 svn_sqlite__reset(stmt)));
644 SVN_ERR(svn_sqlite__step(&got_row, stmt));
646 SVN_ERR(svn_sqlite__reset(stmt));
648 svn_pool_destroy(iterpool);
650 return SVN_NO_ERROR;
653 svn_error_t *
654 svn_wc__db_pristine_transfer(svn_wc__db_t *db,
655 const char *src_local_abspath,
656 const char *dst_wri_abspath,
657 svn_cancel_func_t cancel_func,
658 void *cancel_baton,
659 apr_pool_t *scratch_pool)
661 svn_wc__db_wcroot_t *src_wcroot, *dst_wcroot;
662 const char *src_relpath, *dst_relpath;
664 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&src_wcroot, &src_relpath,
665 db, src_local_abspath,
666 scratch_pool, scratch_pool));
667 VERIFY_USABLE_WCROOT(src_wcroot);
668 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&dst_wcroot, &dst_relpath,
669 db, dst_wri_abspath,
670 scratch_pool, scratch_pool));
671 VERIFY_USABLE_WCROOT(dst_wcroot);
673 if (src_wcroot == dst_wcroot
674 || src_wcroot->sdb == dst_wcroot->sdb)
676 return SVN_NO_ERROR; /* Nothing to transfer */
679 SVN_WC__DB_WITH_TXN(
680 pristine_transfer_txn(src_wcroot, dst_wcroot, src_relpath,
681 cancel_func, cancel_baton, scratch_pool),
682 dst_wcroot);
684 return SVN_NO_ERROR;
690 /* If the pristine text referenced by SHA1_CHECKSUM in WCROOT/SDB, whose path
691 * within the pristine store is PRISTINE_ABSPATH, has a reference count of
692 * zero, delete it (both the database row and the disk file).
694 * This function expects to be executed inside a SQLite txn that has already
695 * acquired a 'RESERVED' lock.
697 static svn_error_t *
698 pristine_remove_if_unreferenced_txn(svn_sqlite__db_t *sdb,
699 svn_wc__db_wcroot_t *wcroot,
700 const svn_checksum_t *sha1_checksum,
701 const char *pristine_abspath,
702 apr_pool_t *scratch_pool)
704 svn_sqlite__stmt_t *stmt;
705 int affected_rows;
707 /* Remove the DB row, if refcount is 0. */
708 SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
709 STMT_DELETE_PRISTINE_IF_UNREFERENCED));
710 SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
711 SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
713 /* If we removed the DB row, then remove the file. */
714 if (affected_rows > 0)
716 /* If the file is not present, something has gone wrong, but at this
717 * point it no longer matters. In a debug build, raise an error, but
718 * in a release build, it is more helpful to ignore it and continue. */
719 #ifdef SVN_DEBUG
720 svn_boolean_t ignore_enoent = FALSE;
721 #else
722 svn_boolean_t ignore_enoent = TRUE;
723 #endif
725 SVN_ERR(svn_io_remove_file2(pristine_abspath, ignore_enoent,
726 scratch_pool));
729 return SVN_NO_ERROR;
732 /* If the pristine text referenced by SHA1_CHECKSUM in WCROOT has a
733 * reference count of zero, delete it (both the database row and the disk
734 * file).
736 * Implements 'notes/wc-ng/pristine-store' section A-3(b). */
737 static svn_error_t *
738 pristine_remove_if_unreferenced(svn_wc__db_wcroot_t *wcroot,
739 const svn_checksum_t *sha1_checksum,
740 apr_pool_t *scratch_pool)
742 const char *pristine_abspath;
744 SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
745 sha1_checksum, scratch_pool, scratch_pool));
747 /* Ensure the SQL txn has at least a 'RESERVED' lock before we start looking
748 * at the disk, to ensure no concurrent pristine install/delete txn. */
749 SVN_SQLITE__WITH_IMMEDIATE_TXN(
750 pristine_remove_if_unreferenced_txn(
751 wcroot->sdb, wcroot, sha1_checksum, pristine_abspath, scratch_pool),
752 wcroot->sdb);
754 return SVN_NO_ERROR;
757 svn_error_t *
758 svn_wc__db_pristine_remove(svn_wc__db_t *db,
759 const char *wri_abspath,
760 const svn_checksum_t *sha1_checksum,
761 apr_pool_t *scratch_pool)
763 svn_wc__db_wcroot_t *wcroot;
764 const char *local_relpath;
766 SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
767 SVN_ERR_ASSERT(sha1_checksum != NULL);
768 /* ### Transitional: accept MD-5 and look up the SHA-1. Return an error
769 * if the pristine text is not in the store. */
770 if (sha1_checksum->kind != svn_checksum_sha1)
771 SVN_ERR(svn_wc__db_pristine_get_sha1(&sha1_checksum, db, wri_abspath,
772 sha1_checksum,
773 scratch_pool, scratch_pool));
774 SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
776 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
777 wri_abspath, scratch_pool, scratch_pool));
778 VERIFY_USABLE_WCROOT(wcroot);
780 /* If the work queue is not empty, don't delete any pristine text because
781 * the work queue may contain a reference to it. */
783 svn_sqlite__stmt_t *stmt;
784 svn_boolean_t have_row;
786 SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_LOOK_FOR_WORK));
787 SVN_ERR(svn_sqlite__step(&have_row, stmt));
788 SVN_ERR(svn_sqlite__reset(stmt));
790 if (have_row)
791 return SVN_NO_ERROR;
794 /* If not referenced, remove the PRISTINE table row and the file. */
795 SVN_ERR(pristine_remove_if_unreferenced(wcroot, sha1_checksum, scratch_pool));
797 return SVN_NO_ERROR;
801 /* Remove all unreferenced pristines in the WC DB in WCROOT.
803 * Look for pristine texts whose 'refcount' in the DB is zero, and remove
804 * them from the 'pristine' table and from disk.
806 * TODO: At least check that any zero refcount is really correct, before
807 * using it. See dev@ email thread "Pristine text missing - cleanup
808 * doesn't work", <http://svn.haxx.se/dev/archive-2013-04/0426.shtml>.
810 * TODO: Ideas for possible extra clean-up operations:
812 * * Check and correct all the refcounts. Identify any rows missing
813 * from the 'pristine' table. (Create a temporary index for speed
814 * if necessary?)
816 * * Check the checksums. (Very expensive to check them all, so find
817 * a way to not check them all.)
819 * * Check for pristine files missing from disk but referenced in the
820 * 'pristine' table.
822 * * Repair any pristine files missing from disk and/or rows missing
823 * from the 'pristine' table and/or bad checksums. Generally
824 * requires contacting the server, so requires support at a higher
825 * level than this function.
827 * * Identify any pristine text files on disk that are not referenced
828 * in the DB, and delete them.
830 * TODO: Provide feedback about any errors found and any corrections made.
832 static svn_error_t *
833 pristine_cleanup_wcroot(svn_wc__db_wcroot_t *wcroot,
834 apr_pool_t *scratch_pool)
836 svn_sqlite__stmt_t *stmt;
837 svn_error_t *err = NULL;
838 apr_pool_t *iterpool = svn_pool_create(scratch_pool);
840 /* Find each unreferenced pristine in the DB and remove it. */
841 SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
842 STMT_SELECT_UNREFERENCED_PRISTINES));
843 while (! err)
845 svn_boolean_t have_row;
846 const svn_checksum_t *sha1_checksum;
848 svn_pool_clear(iterpool);
850 SVN_ERR(svn_sqlite__step(&have_row, stmt));
851 if (! have_row)
852 break;
854 SVN_ERR(svn_sqlite__column_checksum(&sha1_checksum, stmt, 0,
855 iterpool));
856 err = pristine_remove_if_unreferenced(wcroot, sha1_checksum,
857 iterpool);
860 svn_pool_destroy(iterpool);
862 return svn_error_trace(
863 svn_error_compose_create(err, svn_sqlite__reset(stmt)));
866 svn_error_t *
867 svn_wc__db_pristine_cleanup(svn_wc__db_t *db,
868 const char *wri_abspath,
869 apr_pool_t *scratch_pool)
871 svn_wc__db_wcroot_t *wcroot;
872 const char *local_relpath;
874 SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
876 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
877 wri_abspath, scratch_pool, scratch_pool));
878 VERIFY_USABLE_WCROOT(wcroot);
880 SVN_ERR(pristine_cleanup_wcroot(wcroot, scratch_pool));
882 return SVN_NO_ERROR;
886 svn_error_t *
887 svn_wc__db_pristine_check(svn_boolean_t *present,
888 svn_wc__db_t *db,
889 const char *wri_abspath,
890 const svn_checksum_t *sha1_checksum,
891 apr_pool_t *scratch_pool)
893 svn_wc__db_wcroot_t *wcroot;
894 const char *local_relpath;
895 svn_sqlite__stmt_t *stmt;
896 svn_boolean_t have_row;
898 SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
899 SVN_ERR_ASSERT(sha1_checksum != NULL);
901 if (sha1_checksum->kind != svn_checksum_sha1)
903 *present = FALSE;
904 return SVN_NO_ERROR;
907 SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
908 wri_abspath, scratch_pool, scratch_pool));
909 VERIFY_USABLE_WCROOT(wcroot);
911 /* A filestat is much cheaper than a sqlite transaction especially on NFS,
912 so first check if there is a pristine file and then if we are allowed
913 to use it. */
915 const char *pristine_abspath;
916 svn_node_kind_t kind_on_disk;
917 svn_error_t *err;
919 SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
920 sha1_checksum, scratch_pool, scratch_pool));
921 err = svn_io_check_path(pristine_abspath, &kind_on_disk, scratch_pool);
922 #ifdef WIN32
923 if (err && err->apr_err == APR_FROM_OS_ERROR(ERROR_ACCESS_DENIED))
925 svn_error_clear(err);
926 /* Possible race condition: The filename is locked, but there is no
927 file or dir with this name. Let's fall back on checking the DB.
929 This case is triggered by the pristine store tests on deleting
930 a file that is still open via another handle, where this other
931 handle has a FILE_SHARE_DELETE share mode.
934 else
935 #endif
936 if (err)
937 return svn_error_trace(err);
938 else if (kind_on_disk != svn_node_file)
940 *present = FALSE;
941 return SVN_NO_ERROR;
945 /* Check that there is an entry in the PRISTINE table. */
946 SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_PRISTINE));
947 SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
948 SVN_ERR(svn_sqlite__step(&have_row, stmt));
949 SVN_ERR(svn_sqlite__reset(stmt));
951 *present = have_row;
952 return SVN_NO_ERROR;