]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/subversion/subversion/libsvn_wc/cleanup.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / subversion / subversion / libsvn_wc / cleanup.c
1 /*
2  * cleanup.c:  handle cleaning up workqueue items
3  *
4  * ====================================================================
5  *    Licensed to the Apache Software Foundation (ASF) under one
6  *    or more contributor license agreements.  See the NOTICE file
7  *    distributed with this work for additional information
8  *    regarding copyright ownership.  The ASF licenses this file
9  *    to you under the Apache License, Version 2.0 (the
10  *    "License"); you may not use this file except in compliance
11  *    with the License.  You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  *    Unless required by applicable law or agreed to in writing,
16  *    software distributed under the License is distributed on an
17  *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18  *    KIND, either express or implied.  See the License for the
19  *    specific language governing permissions and limitations
20  *    under the License.
21  * ====================================================================
22  */
23
24
25 \f
26 #include <string.h>
27
28 #include "svn_wc.h"
29 #include "svn_error.h"
30 #include "svn_pools.h"
31 #include "svn_io.h"
32 #include "svn_dirent_uri.h"
33
34 #include "wc.h"
35 #include "adm_files.h"
36 #include "lock.h"
37 #include "workqueue.h"
38
39 #include "private/svn_wc_private.h"
40 #include "svn_private_config.h"
41
42 \f
43 /*** Recursively do log things. ***/
44
45 /* */
46 static svn_error_t *
47 can_be_cleaned(int *wc_format,
48                svn_wc__db_t *db,
49                const char *local_abspath,
50                apr_pool_t *scratch_pool)
51 {
52   SVN_ERR(svn_wc__internal_check_wc(wc_format, db,
53                                     local_abspath, FALSE, scratch_pool));
54
55   /* a "version" of 0 means a non-wc directory */
56   if (*wc_format == 0)
57     return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL,
58                              _("'%s' is not a working copy directory"),
59                              svn_dirent_local_style(local_abspath,
60                                                     scratch_pool));
61
62   if (*wc_format < SVN_WC__WC_NG_VERSION)
63     return svn_error_create(SVN_ERR_WC_UNSUPPORTED_FORMAT, NULL,
64                             _("Log format too old, please use "
65                               "Subversion 1.6 or earlier"));
66
67   return SVN_NO_ERROR;
68 }
69
70 /* Do a modifed check for LOCAL_ABSPATH, and all working children, to force
71    timestamp repair. */
72 static svn_error_t *
73 repair_timestamps(svn_wc__db_t *db,
74                   const char *local_abspath,
75                   svn_cancel_func_t cancel_func,
76                   void *cancel_baton,
77                   apr_pool_t *scratch_pool)
78 {
79   svn_node_kind_t kind;
80   svn_wc__db_status_t status;
81
82   if (cancel_func)
83     SVN_ERR(cancel_func(cancel_baton));
84
85   SVN_ERR(svn_wc__db_read_info(&status, &kind,
86                                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
87                                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
88                                NULL, NULL, NULL, NULL, NULL, NULL,
89                                NULL, NULL, NULL,
90                                db, local_abspath, scratch_pool, scratch_pool));
91
92   if (status == svn_wc__db_status_server_excluded
93       || status == svn_wc__db_status_deleted
94       || status == svn_wc__db_status_excluded
95       || status == svn_wc__db_status_not_present)
96     return SVN_NO_ERROR;
97
98   if (kind == svn_node_file
99       || kind == svn_node_symlink)
100     {
101       svn_boolean_t modified;
102       SVN_ERR(svn_wc__internal_file_modified_p(&modified,
103                                                db, local_abspath, FALSE,
104                                                scratch_pool));
105     }
106   else if (kind == svn_node_dir)
107     {
108       apr_pool_t *iterpool = svn_pool_create(scratch_pool);
109       const apr_array_header_t *children;
110       int i;
111
112       SVN_ERR(svn_wc__db_read_children_of_working_node(&children, db,
113                                                        local_abspath,
114                                                        scratch_pool,
115                                                        iterpool));
116       for (i = 0; i < children->nelts; ++i)
117         {
118           const char *child_abspath;
119
120           svn_pool_clear(iterpool);
121
122           child_abspath = svn_dirent_join(local_abspath,
123                                           APR_ARRAY_IDX(children, i,
124                                                         const char *),
125                                           iterpool);
126
127           SVN_ERR(repair_timestamps(db, child_abspath,
128                                     cancel_func, cancel_baton, iterpool));
129         }
130       svn_pool_destroy(iterpool);
131     }
132
133   return SVN_NO_ERROR;
134 }
135
136 /* */
137 static svn_error_t *
138 cleanup_internal(svn_wc__db_t *db,
139                  const char *dir_abspath,
140                  svn_cancel_func_t cancel_func,
141                  void *cancel_baton,
142                  apr_pool_t *scratch_pool)
143 {
144   int wc_format;
145   svn_boolean_t is_wcroot;
146   const char *lock_abspath;
147
148   /* Can we even work with this directory?  */
149   SVN_ERR(can_be_cleaned(&wc_format, db, dir_abspath, scratch_pool));
150
151   /* We cannot obtain a lock on a directory that's within a locked
152      subtree, so always run cleanup from the lock owner. */
153   SVN_ERR(svn_wc__db_wclock_find_root(&lock_abspath, db, dir_abspath,
154                                       scratch_pool, scratch_pool));
155   if (lock_abspath)
156     dir_abspath = lock_abspath;
157   SVN_ERR(svn_wc__db_wclock_obtain(db, dir_abspath, -1, TRUE, scratch_pool));
158
159   /* Run our changes before the subdirectories. We may not have to recurse
160      if we blow away a subdir.  */
161   if (wc_format >= SVN_WC__HAS_WORK_QUEUE)
162     SVN_ERR(svn_wc__wq_run(db, dir_abspath, cancel_func, cancel_baton,
163                            scratch_pool));
164
165   SVN_ERR(svn_wc__db_is_wcroot(&is_wcroot, db, dir_abspath, scratch_pool));
166
167 #ifdef SVN_DEBUG
168   SVN_ERR(svn_wc__db_verify(db, dir_abspath, scratch_pool));
169 #endif
170
171   /* Perform these operations if we lock the entire working copy.
172      Note that we really need to check a wcroot value and not
173      svn_wc__check_wcroot() as that function, will just return true
174      once we start sharing databases with externals.
175    */
176   if (is_wcroot)
177     {
178     /* Cleanup the tmp area of the admin subdir, if running the log has not
179        removed it!  The logs have been run, so anything left here has no hope
180        of being useful. */
181       SVN_ERR(svn_wc__adm_cleanup_tmp_area(db, dir_abspath, scratch_pool));
182
183       /* Remove unreferenced pristine texts */
184       SVN_ERR(svn_wc__db_pristine_cleanup(db, dir_abspath, scratch_pool));
185     }
186
187   SVN_ERR(repair_timestamps(db, dir_abspath, cancel_func, cancel_baton,
188                             scratch_pool));
189
190   /* All done, toss the lock */
191   SVN_ERR(svn_wc__db_wclock_release(db, dir_abspath, scratch_pool));
192
193   return SVN_NO_ERROR;
194 }
195
196
197 /* ### possibly eliminate the WC_CTX parameter? callers really shouldn't
198    ### be doing anything *but* running a cleanup, and we need a special
199    ### DB anyway. ... *shrug* ... consider later.  */
200 svn_error_t *
201 svn_wc_cleanup3(svn_wc_context_t *wc_ctx,
202                 const char *local_abspath,
203                 svn_cancel_func_t cancel_func,
204                 void *cancel_baton,
205                 apr_pool_t *scratch_pool)
206 {
207   svn_wc__db_t *db;
208
209   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
210
211   /* We need a DB that allows a non-empty work queue (though it *will*
212      auto-upgrade). We'll handle everything manually.  */
213   SVN_ERR(svn_wc__db_open(&db,
214                           NULL /* ### config */, FALSE, FALSE,
215                           scratch_pool, scratch_pool));
216
217   SVN_ERR(cleanup_internal(db, local_abspath, cancel_func, cancel_baton,
218                            scratch_pool));
219
220   /* The DAV cache suffers from flakiness from time to time, and the
221      pre-1.7 prescribed workarounds aren't as user-friendly in WC-NG. */
222   SVN_ERR(svn_wc__db_base_clear_dav_cache_recursive(db, local_abspath,
223                                                     scratch_pool));
224
225   SVN_ERR(svn_wc__db_vacuum(db, local_abspath, scratch_pool));
226
227   /* We're done with this DB, so proactively close it.  */
228   SVN_ERR(svn_wc__db_close(db));
229
230   return SVN_NO_ERROR;
231 }