]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/subversion/subversion/libsvn_wc/wc_db_pristine.c
Update svn-1.9.7 to 1.10.0.
[FreeBSD/FreeBSD.git] / contrib / subversion / subversion / libsvn_wc / wc_db_pristine.c
1 /*
2  * wc_db_pristine.c :  Pristine ("text base") management
3  *
4  * See the spec in 'notes/wc-ng/pristine-store'.
5  *
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
14  *
15  *      http://www.apache.org/licenses/LICENSE-2.0
16  *
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  * ====================================================================
24  */
25
26 #define SVN_WC__I_AM_WC_DB
27
28 #include "svn_pools.h"
29 #include "svn_io.h"
30 #include "svn_dirent_uri.h"
31
32 #include "private/svn_io_private.h"
33
34 #include "wc.h"
35 #include "wc_db.h"
36 #include "wc-queries.h"
37 #include "wc_db_private.h"
38
39 #define PRISTINE_STORAGE_EXT ".svn-base"
40 #define PRISTINE_STORAGE_RELPATH "pristine"
41 #define PRISTINE_TEMPDIR_RELPATH "tmp"
42
43
44
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.
50
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)
58 {
59   const char *base_dir_abspath;
60   const char *hexdigest = svn_checksum_to_cstring(sha1_checksum, scratch_pool);
61   char subdir[3];
62
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);
68
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);
74
75   /* We should have a valid checksum and (thus) a valid digest. */
76   SVN_ERR_ASSERT(hexdigest != NULL);
77
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';
82
83   hexdigest = apr_pstrcat(scratch_pool, hexdigest, PRISTINE_STORAGE_EXT,
84                           SVN_VA_NULL);
85
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;
93 }
94
95
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)
103 {
104   svn_wc__db_wcroot_t *wcroot;
105   const char *local_relpath;
106   svn_boolean_t present;
107
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);
118
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);
123
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));
132
133   SVN_ERR(get_pristine_fname(pristine_abspath, wcroot->abspath,
134                              sha1_checksum,
135                              result_pool, scratch_pool));
136
137   return SVN_NO_ERROR;
138 }
139
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)
146 {
147   SVN_ERR(get_pristine_fname(pristine_abspath, wcroot_abspath,
148                              sha1_checksum,
149                              result_pool, scratch_pool));
150   return SVN_NO_ERROR;
151 }
152
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.
158  *
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.
161  *
162  * Allocate the stream in RESULT_POOL.
163  *
164  * This function expects to be executed inside a SQLite txn.
165  *
166  * Implements 'notes/wc-ng/pristine-store' section A-3(d).
167  */
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)
176 {
177   svn_sqlite__stmt_t *stmt;
178   svn_boolean_t have_row;
179
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));
186
187   if (size)
188     *size = svn_sqlite__column_int64(stmt, 0);
189
190   SVN_ERR(svn_sqlite__reset(stmt));
191   if (! have_row)
192     {
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));
197     }
198
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.
201    *
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)
207     {
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);
212     }
213
214   return SVN_NO_ERROR;
215 }
216
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)
225 {
226   svn_wc__db_wcroot_t *wcroot;
227   const char *local_relpath;
228   const char *pristine_abspath;
229
230   SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
231
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));
239
240   SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
241
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);
245
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);
254
255   return SVN_NO_ERROR;
256 }
257
258
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)
265 {
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);
269 }
270
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.
274  *
275  * This function expects to be executed inside a SQLite txn that has already
276  * acquired a 'RESERVED' lock.
277  *
278  * Implements 'notes/wc-ng/pristine-store' section A-3(a).
279  */
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)
291 {
292   svn_sqlite__stmt_t *stmt;
293   svn_boolean_t have_row;
294
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));
301
302   if (have_row)
303     {
304 #ifdef SVN_DEBUG
305       /* Consistency checks.  Verify both files exist and match.
306        * ### We could check much more. */
307       {
308         apr_finfo_t finfo1, finfo2;
309
310         SVN_ERR(svn_stream__install_get_info(&finfo1, install_stream, APR_FINFO_SIZE,
311                                              scratch_pool));
312
313         SVN_ERR(svn_io_stat(&finfo2, pristine_abspath, APR_FINFO_SIZE,
314                             scratch_pool));
315         if (finfo1.size != finfo2.size)
316           {
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));
323           }
324       }
325 #endif
326
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;
330     }
331
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.) */
334   {
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));
340
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));
346
347     SVN_ERR(svn_io_set_file_read_only(pristine_abspath, FALSE, scratch_pool));
348   }
349
350   return SVN_NO_ERROR;
351 }
352
353 struct svn_wc__db_install_data_t
354 {
355   svn_wc__db_wcroot_t *wcroot;
356   svn_stream_t *inner_stream;
357 };
358
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)
368 {
369   svn_wc__db_wcroot_t *wcroot;
370   const char *local_relpath;
371   const char *temp_dir_abspath;
372
373   SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
374
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);
378
379   temp_dir_abspath = pristine_get_tempdir(wcroot, scratch_pool, scratch_pool);
380
381   *install_data = apr_pcalloc(result_pool, sizeof(**install_data));
382   (*install_data)->wcroot = wcroot;
383
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"));
388
389   (*install_data)->inner_stream = *stream;
390
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);
397
398   return SVN_NO_ERROR;
399 }
400
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)
406 {
407   svn_wc__db_wcroot_t *wcroot = install_data->wcroot;
408   const char *pristine_abspath;
409
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);
414
415   SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
416                              sha1_checksum,
417                              scratch_pool, scratch_pool));
418
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);
427
428   return SVN_NO_ERROR;
429 }
430
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)
434 {
435   return svn_error_trace(svn_stream__install_delete(install_data->inner_stream,
436                                                     scratch_pool));
437 }
438
439
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)
447 {
448   svn_wc__db_wcroot_t *wcroot;
449   const char *local_relpath;
450   svn_sqlite__stmt_t *stmt;
451   svn_boolean_t have_row;
452
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);
456
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);
460
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));
470
471   SVN_ERR(svn_sqlite__column_checksum(md5_checksum, stmt, 0, result_pool));
472   SVN_ERR_ASSERT((*md5_checksum)->kind == svn_checksum_md5);
473
474   return svn_error_trace(svn_sqlite__reset(stmt));
475 }
476
477
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)
485 {
486   svn_wc__db_wcroot_t *wcroot;
487   const char *local_relpath;
488   svn_sqlite__stmt_t *stmt;
489   svn_boolean_t have_row;
490
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);
494
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);
498
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));
509
510   SVN_ERR(svn_sqlite__column_checksum(sha1_checksum, stmt, 0, result_pool));
511   SVN_ERR_ASSERT((*sha1_checksum)->kind == svn_checksum_sha1);
512
513   return svn_error_trace(svn_sqlite__reset(stmt));
514 }
515
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)
527 {
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;
536
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));
542
543   SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
544
545   if (affected_rows == 0)
546     return SVN_NO_ERROR;
547
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));
554
555   SVN_ERR(get_pristine_fname(&src_abspath, src_wcroot->abspath, checksum,
556                              scratch_pool, scratch_pool));
557
558   SVN_ERR(svn_stream_open_readonly(&src_stream, src_abspath,
559                                    scratch_pool, scratch_pool));
560
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));
565
566   SVN_ERR(get_pristine_fname(&pristine_abspath, dst_wcroot->abspath, checksum,
567                              scratch_pool, scratch_pool));
568
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);
573
574   /* Maybe the directory doesn't exist yet? */
575   if (err && APR_STATUS_IS_ENOENT(err->apr_err))
576     {
577       svn_error_t *err2;
578
579       err2 = svn_io_dir_make(svn_dirent_dirname(pristine_abspath,
580                                                 scratch_pool),
581                              APR_OS_DEFAULT, scratch_pool);
582
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);
589
590       SVN_ERR(svn_io_file_rename2(tmp_abspath, pristine_abspath, FALSE,
591                                   scratch_pool));
592     }
593   else
594     SVN_ERR(err);
595
596   return SVN_NO_ERROR;
597 }
598
599 /* Transaction implementation of svn_wc__db_pristine_transfer().
600    We have a lock on DST_WCROOT.
601  */
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)
609 {
610   svn_sqlite__stmt_t *stmt;
611   svn_boolean_t got_row;
612   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
613
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));
617
618   /* This obtains an sqlite read lock on src_wcroot */
619   SVN_ERR(svn_sqlite__step(&got_row, stmt));
620
621   while (got_row)
622     {
623       const svn_checksum_t *checksum;
624       const svn_checksum_t *md5_checksum;
625       apr_int64_t size;
626       svn_error_t *err;
627
628       svn_pool_clear(iterpool);
629
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);
633
634       err = maybe_transfer_one_pristine(src_wcroot, dst_wcroot,
635                                         checksum, md5_checksum, size,
636                                         cancel_func, cancel_baton,
637                                         iterpool);
638
639       if (err)
640         return svn_error_trace(svn_error_compose_create(
641                                     err,
642                                     svn_sqlite__reset(stmt)));
643
644       SVN_ERR(svn_sqlite__step(&got_row, stmt));
645     }
646   SVN_ERR(svn_sqlite__reset(stmt));
647
648   svn_pool_destroy(iterpool);
649
650   return SVN_NO_ERROR;
651 }
652
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)
660 {
661   svn_wc__db_wcroot_t *src_wcroot, *dst_wcroot;
662   const char *src_relpath, *dst_relpath;
663
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);
672
673   if (src_wcroot == dst_wcroot
674       || src_wcroot->sdb == dst_wcroot->sdb)
675     {
676       return SVN_NO_ERROR; /* Nothing to transfer */
677     }
678
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);
683
684   return SVN_NO_ERROR;
685 }
686
687
688
689
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).
693  *
694  * This function expects to be executed inside a SQLite txn that has already
695  * acquired a 'RESERVED' lock.
696  */
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)
703 {
704   svn_sqlite__stmt_t *stmt;
705   int affected_rows;
706
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));
712
713   /* If we removed the DB row, then remove the file. */
714   if (affected_rows > 0)
715     {
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
724
725       SVN_ERR(svn_io_remove_file2(pristine_abspath, ignore_enoent,
726                                   scratch_pool));
727     }
728
729   return SVN_NO_ERROR;
730 }
731
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).
735  *
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)
741 {
742   const char *pristine_abspath;
743
744   SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
745                              sha1_checksum, scratch_pool, scratch_pool));
746
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);
753
754   return SVN_NO_ERROR;
755 }
756
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)
762 {
763   svn_wc__db_wcroot_t *wcroot;
764   const char *local_relpath;
765
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);
775
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);
779
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. */
782   {
783     svn_sqlite__stmt_t *stmt;
784     svn_boolean_t have_row;
785
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));
789
790     if (have_row)
791       return SVN_NO_ERROR;
792   }
793
794   /* If not referenced, remove the PRISTINE table row and the file. */
795   SVN_ERR(pristine_remove_if_unreferenced(wcroot, sha1_checksum, scratch_pool));
796
797   return SVN_NO_ERROR;
798 }
799
800
801 /* Remove all unreferenced pristines in the WC DB in WCROOT.
802  *
803  * Look for pristine texts whose 'refcount' in the DB is zero, and remove
804  * them from the 'pristine' table and from disk.
805  *
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>.
809  *
810  * TODO: Ideas for possible extra clean-up operations:
811  *
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?)
815  *
816  *       * Check the checksums.  (Very expensive to check them all, so find
817  *         a way to not check them all.)
818  *
819  *       * Check for pristine files missing from disk but referenced in the
820  *         'pristine' table.
821  *
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.
826  *
827  *       * Identify any pristine text files on disk that are not referenced
828  *         in the DB, and delete them.
829  *
830  * TODO: Provide feedback about any errors found and any corrections made.
831  */
832 static svn_error_t *
833 pristine_cleanup_wcroot(svn_wc__db_wcroot_t *wcroot,
834                         apr_pool_t *scratch_pool)
835 {
836   svn_sqlite__stmt_t *stmt;
837   svn_error_t *err = NULL;
838   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
839
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)
844     {
845       svn_boolean_t have_row;
846       const svn_checksum_t *sha1_checksum;
847
848       svn_pool_clear(iterpool);
849
850       SVN_ERR(svn_sqlite__step(&have_row, stmt));
851       if (! have_row)
852         break;
853
854       SVN_ERR(svn_sqlite__column_checksum(&sha1_checksum, stmt, 0,
855                                           iterpool));
856       err = pristine_remove_if_unreferenced(wcroot, sha1_checksum,
857                                             iterpool);
858     }
859
860   svn_pool_destroy(iterpool);
861
862   return svn_error_trace(
863       svn_error_compose_create(err, svn_sqlite__reset(stmt)));
864 }
865
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)
870 {
871   svn_wc__db_wcroot_t *wcroot;
872   const char *local_relpath;
873
874   SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
875
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);
879
880   SVN_ERR(pristine_cleanup_wcroot(wcroot, scratch_pool));
881
882   return SVN_NO_ERROR;
883 }
884
885
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)
892 {
893   svn_wc__db_wcroot_t *wcroot;
894   const char *local_relpath;
895   svn_sqlite__stmt_t *stmt;
896   svn_boolean_t have_row;
897
898   SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
899   SVN_ERR_ASSERT(sha1_checksum != NULL);
900
901   if (sha1_checksum->kind != svn_checksum_sha1)
902     {
903       *present = FALSE;
904       return SVN_NO_ERROR;
905     }
906
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);
910
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. */
914   {
915     const char *pristine_abspath;
916     svn_node_kind_t kind_on_disk;
917     svn_error_t *err;
918
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))
924       {
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.
928
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.
932          */
933       }
934     else
935 #endif
936     if (err)
937       return svn_error_trace(err);
938     else if (kind_on_disk != svn_node_file)
939       {
940         *present = FALSE;
941         return SVN_NO_ERROR;
942       }
943   }
944
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));
950
951   *present = have_row;
952   return SVN_NO_ERROR;
953 }