1251881Speter/* 2251881Speter * cleanup.c: handle cleaning up workqueue items 3251881Speter * 4251881Speter * ==================================================================== 5251881Speter * Licensed to the Apache Software Foundation (ASF) under one 6251881Speter * or more contributor license agreements. See the NOTICE file 7251881Speter * distributed with this work for additional information 8251881Speter * regarding copyright ownership. The ASF licenses this file 9251881Speter * to you under the Apache License, Version 2.0 (the 10251881Speter * "License"); you may not use this file except in compliance 11251881Speter * with the License. You may obtain a copy of the License at 12251881Speter * 13251881Speter * http://www.apache.org/licenses/LICENSE-2.0 14251881Speter * 15251881Speter * Unless required by applicable law or agreed to in writing, 16251881Speter * software distributed under the License is distributed on an 17251881Speter * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18251881Speter * KIND, either express or implied. See the License for the 19251881Speter * specific language governing permissions and limitations 20251881Speter * under the License. 21251881Speter * ==================================================================== 22251881Speter */ 23251881Speter 24251881Speter 25251881Speter 26251881Speter#include <string.h> 27251881Speter 28251881Speter#include "svn_wc.h" 29251881Speter#include "svn_error.h" 30251881Speter#include "svn_pools.h" 31251881Speter#include "svn_io.h" 32251881Speter#include "svn_dirent_uri.h" 33251881Speter 34251881Speter#include "wc.h" 35251881Speter#include "adm_files.h" 36251881Speter#include "lock.h" 37251881Speter#include "workqueue.h" 38251881Speter 39251881Speter#include "private/svn_wc_private.h" 40251881Speter#include "svn_private_config.h" 41251881Speter 42251881Speter 43251881Speter/*** Recursively do log things. ***/ 44251881Speter 45251881Speter/* */ 46251881Speterstatic svn_error_t * 47251881Spetercan_be_cleaned(int *wc_format, 48251881Speter svn_wc__db_t *db, 49251881Speter const char *local_abspath, 50251881Speter apr_pool_t *scratch_pool) 51251881Speter{ 52251881Speter SVN_ERR(svn_wc__internal_check_wc(wc_format, db, 53251881Speter local_abspath, FALSE, scratch_pool)); 54251881Speter 55251881Speter /* a "version" of 0 means a non-wc directory */ 56251881Speter if (*wc_format == 0) 57251881Speter return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL, 58251881Speter _("'%s' is not a working copy directory"), 59251881Speter svn_dirent_local_style(local_abspath, 60251881Speter scratch_pool)); 61251881Speter 62251881Speter if (*wc_format < SVN_WC__WC_NG_VERSION) 63251881Speter return svn_error_create(SVN_ERR_WC_UNSUPPORTED_FORMAT, NULL, 64251881Speter _("Log format too old, please use " 65251881Speter "Subversion 1.6 or earlier")); 66251881Speter 67251881Speter return SVN_NO_ERROR; 68251881Speter} 69251881Speter 70289166Speter/* Dummy svn_wc_status_func4_t implementation */ 71251881Speterstatic svn_error_t * 72289166Speterstatus_dummy_callback(void *baton, 73289166Speter const char *local_abspath, 74289166Speter const svn_wc_status3_t *status, 75289166Speter apr_pool_t *scratch_pool) 76251881Speter{ 77251881Speter return SVN_NO_ERROR; 78251881Speter} 79251881Speter 80251881Speter/* */ 81251881Speterstatic svn_error_t * 82251881Spetercleanup_internal(svn_wc__db_t *db, 83251881Speter const char *dir_abspath, 84299742Sdim svn_boolean_t break_locks, 85299742Sdim svn_boolean_t fix_recorded_timestamps, 86299742Sdim svn_boolean_t vacuum_pristines, 87251881Speter svn_cancel_func_t cancel_func, 88251881Speter void *cancel_baton, 89251881Speter apr_pool_t *scratch_pool) 90251881Speter{ 91251881Speter int wc_format; 92251881Speter svn_boolean_t is_wcroot; 93251881Speter const char *lock_abspath; 94251881Speter 95251881Speter /* Can we even work with this directory? */ 96251881Speter SVN_ERR(can_be_cleaned(&wc_format, db, dir_abspath, scratch_pool)); 97251881Speter 98251881Speter /* We cannot obtain a lock on a directory that's within a locked 99251881Speter subtree, so always run cleanup from the lock owner. */ 100251881Speter SVN_ERR(svn_wc__db_wclock_find_root(&lock_abspath, db, dir_abspath, 101251881Speter scratch_pool, scratch_pool)); 102251881Speter if (lock_abspath) 103251881Speter dir_abspath = lock_abspath; 104299742Sdim SVN_ERR(svn_wc__db_wclock_obtain(db, dir_abspath, -1, break_locks, scratch_pool)); 105251881Speter 106251881Speter /* Run our changes before the subdirectories. We may not have to recurse 107251881Speter if we blow away a subdir. */ 108251881Speter if (wc_format >= SVN_WC__HAS_WORK_QUEUE) 109251881Speter SVN_ERR(svn_wc__wq_run(db, dir_abspath, cancel_func, cancel_baton, 110251881Speter scratch_pool)); 111251881Speter 112251881Speter SVN_ERR(svn_wc__db_is_wcroot(&is_wcroot, db, dir_abspath, scratch_pool)); 113251881Speter 114251881Speter#ifdef SVN_DEBUG 115251881Speter SVN_ERR(svn_wc__db_verify(db, dir_abspath, scratch_pool)); 116251881Speter#endif 117251881Speter 118251881Speter /* Perform these operations if we lock the entire working copy. 119251881Speter Note that we really need to check a wcroot value and not 120251881Speter svn_wc__check_wcroot() as that function, will just return true 121251881Speter once we start sharing databases with externals. 122251881Speter */ 123299742Sdim if (is_wcroot && vacuum_pristines) 124251881Speter { 125251881Speter /* Cleanup the tmp area of the admin subdir, if running the log has not 126251881Speter removed it! The logs have been run, so anything left here has no hope 127251881Speter of being useful. */ 128251881Speter SVN_ERR(svn_wc__adm_cleanup_tmp_area(db, dir_abspath, scratch_pool)); 129251881Speter 130251881Speter /* Remove unreferenced pristine texts */ 131251881Speter SVN_ERR(svn_wc__db_pristine_cleanup(db, dir_abspath, scratch_pool)); 132251881Speter } 133251881Speter 134299742Sdim if (fix_recorded_timestamps) 135299742Sdim { 136299742Sdim /* Instead of implementing a separate repair step here, use the standard 137299742Sdim status walker's optimized implementation, which performs repairs when 138299742Sdim there is a lock. */ 139299742Sdim SVN_ERR(svn_wc__internal_walk_status(db, dir_abspath, svn_depth_infinity, 140299742Sdim FALSE /* get_all */, 141299742Sdim FALSE /* no_ignore */, 142299742Sdim FALSE /* ignore_text_mods */, 143299742Sdim NULL /* ignore patterns */, 144299742Sdim status_dummy_callback, NULL, 145299742Sdim cancel_func, cancel_baton, 146299742Sdim scratch_pool)); 147299742Sdim } 148251881Speter 149251881Speter /* All done, toss the lock */ 150251881Speter SVN_ERR(svn_wc__db_wclock_release(db, dir_abspath, scratch_pool)); 151251881Speter 152251881Speter return SVN_NO_ERROR; 153251881Speter} 154251881Speter 155251881Spetersvn_error_t * 156299742Sdimsvn_wc_cleanup4(svn_wc_context_t *wc_ctx, 157251881Speter const char *local_abspath, 158299742Sdim svn_boolean_t break_locks, 159299742Sdim svn_boolean_t fix_recorded_timestamps, 160299742Sdim svn_boolean_t clear_dav_cache, 161299742Sdim svn_boolean_t vacuum_pristines, 162251881Speter svn_cancel_func_t cancel_func, 163251881Speter void *cancel_baton, 164299742Sdim svn_wc_notify_func2_t notify_func, 165299742Sdim void *notify_baton, 166251881Speter apr_pool_t *scratch_pool) 167251881Speter{ 168251881Speter svn_wc__db_t *db; 169251881Speter 170251881Speter SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath)); 171299742Sdim SVN_ERR_ASSERT(wc_ctx != NULL); 172251881Speter 173299742Sdim if (break_locks) 174299742Sdim { 175299742Sdim /* We'll handle everything manually. */ 176251881Speter 177299742Sdim /* Close the existing database (if any) to avoid problems with 178299742Sdim exclusive database usage */ 179299742Sdim SVN_ERR(svn_wc__db_drop_root(wc_ctx->db, local_abspath, 180299742Sdim scratch_pool)); 181299742Sdim 182299742Sdim SVN_ERR(svn_wc__db_open(&db, 183299742Sdim NULL /* ### config */, FALSE, FALSE, 184299742Sdim scratch_pool, scratch_pool)); 185299742Sdim } 186299742Sdim else 187299742Sdim db = wc_ctx->db; 188299742Sdim 189299742Sdim SVN_ERR(cleanup_internal(db, local_abspath, 190299742Sdim break_locks, 191299742Sdim fix_recorded_timestamps, 192299742Sdim vacuum_pristines, 193299742Sdim cancel_func, cancel_baton, 194251881Speter scratch_pool)); 195251881Speter 196251881Speter /* The DAV cache suffers from flakiness from time to time, and the 197251881Speter pre-1.7 prescribed workarounds aren't as user-friendly in WC-NG. */ 198299742Sdim if (clear_dav_cache) 199299742Sdim SVN_ERR(svn_wc__db_base_clear_dav_cache_recursive(db, local_abspath, 200299742Sdim scratch_pool)); 201251881Speter 202299742Sdim if (vacuum_pristines) 203299742Sdim SVN_ERR(svn_wc__db_vacuum(db, local_abspath, scratch_pool)); 204251881Speter 205251881Speter /* We're done with this DB, so proactively close it. */ 206299742Sdim if (break_locks) 207299742Sdim SVN_ERR(svn_wc__db_close(db)); 208251881Speter 209251881Speter return SVN_NO_ERROR; 210251881Speter} 211