1251881Speter/* 2251881Speter * revert.c: wrapper around wc revert functionality. 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 27251881Speter 28251881Speter/*** Includes. ***/ 29251881Speter 30251881Speter#include "svn_path.h" 31251881Speter#include "svn_wc.h" 32251881Speter#include "svn_client.h" 33251881Speter#include "svn_dirent_uri.h" 34251881Speter#include "svn_hash.h" 35251881Speter#include "svn_pools.h" 36251881Speter#include "svn_error.h" 37251881Speter#include "svn_time.h" 38251881Speter#include "svn_config.h" 39251881Speter#include "client.h" 40251881Speter#include "private/svn_wc_private.h" 41251881Speter 42251881Speter#include "svn_private_config.h" 43251881Speter 44251881Speter 45251881Speter/*** Code. ***/ 46251881Speter 47251881Speterstruct revert_with_write_lock_baton { 48251881Speter const char *local_abspath; 49251881Speter svn_depth_t depth; 50251881Speter svn_boolean_t use_commit_times; 51251881Speter const apr_array_header_t *changelists; 52299742Sdim svn_boolean_t clear_changelists; 53299742Sdim svn_boolean_t metadata_only; 54251881Speter svn_client_ctx_t *ctx; 55251881Speter}; 56251881Speter 57251881Speter/* (Note: All arguments are in the baton above.) 58251881Speter 59251881Speter Attempt to revert LOCAL_ABSPATH. 60251881Speter 61251881Speter If DEPTH is svn_depth_empty, revert just the properties on the 62251881Speter directory; else if svn_depth_files, revert the properties and any 63251881Speter files immediately under the directory; else if 64251881Speter svn_depth_immediates, revert all of the preceding plus properties 65251881Speter on immediate subdirectories; else if svn_depth_infinity, revert 66251881Speter path and everything under it fully recursively. 67251881Speter 68251881Speter CHANGELISTS is an array of const char * changelist names, used as a 69251881Speter restrictive filter on items reverted; that is, don't revert any 70251881Speter item unless it's a member of one of those changelists. If 71251881Speter CHANGELISTS is empty (or altogether NULL), no changelist filtering occurs. 72251881Speter 73251881Speter Consult CTX to determine whether or not to revert timestamp to the 74251881Speter time of last commit ('use-commit-times = yes'). 75251881Speter 76251881Speter If PATH is unversioned, return SVN_ERR_UNVERSIONED_RESOURCE. */ 77251881Speterstatic svn_error_t * 78251881Speterrevert(void *baton, apr_pool_t *result_pool, apr_pool_t *scratch_pool) 79251881Speter{ 80251881Speter struct revert_with_write_lock_baton *b = baton; 81251881Speter svn_error_t *err; 82251881Speter 83299742Sdim err = svn_wc_revert5(b->ctx->wc_ctx, 84251881Speter b->local_abspath, 85251881Speter b->depth, 86251881Speter b->use_commit_times, 87251881Speter b->changelists, 88299742Sdim b->clear_changelists, 89299742Sdim b->metadata_only, 90251881Speter b->ctx->cancel_func, b->ctx->cancel_baton, 91251881Speter b->ctx->notify_func2, b->ctx->notify_baton2, 92251881Speter scratch_pool); 93251881Speter 94251881Speter if (err) 95251881Speter { 96251881Speter /* If target isn't versioned, just send a 'skip' 97251881Speter notification and move on. */ 98251881Speter if (err->apr_err == SVN_ERR_ENTRY_NOT_FOUND 99251881Speter || err->apr_err == SVN_ERR_UNVERSIONED_RESOURCE 100251881Speter || err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) 101251881Speter { 102251881Speter if (b->ctx->notify_func2) 103299742Sdim { 104299742Sdim svn_wc_notify_t *notify; 105299742Sdim 106299742Sdim notify = svn_wc_create_notify(b->local_abspath, 107299742Sdim svn_wc_notify_skip, 108299742Sdim scratch_pool); 109299742Sdim 110299742Sdim notify->err = err; 111299742Sdim 112299742Sdim b->ctx->notify_func2(b->ctx->notify_baton2, 113299742Sdim notify, scratch_pool); 114299742Sdim } 115251881Speter svn_error_clear(err); 116251881Speter } 117251881Speter else 118251881Speter return svn_error_trace(err); 119251881Speter } 120251881Speter 121251881Speter return SVN_NO_ERROR; 122251881Speter} 123251881Speter 124251881Speter 125251881Spetersvn_error_t * 126299742Sdimsvn_client_revert3(const apr_array_header_t *paths, 127251881Speter svn_depth_t depth, 128251881Speter const apr_array_header_t *changelists, 129299742Sdim svn_boolean_t clear_changelists, 130299742Sdim svn_boolean_t metadata_only, 131251881Speter svn_client_ctx_t *ctx, 132251881Speter apr_pool_t *pool) 133251881Speter{ 134299742Sdim apr_pool_t *iterpool; 135251881Speter svn_error_t *err = SVN_NO_ERROR; 136251881Speter int i; 137251881Speter svn_config_t *cfg; 138251881Speter svn_boolean_t use_commit_times; 139251881Speter struct revert_with_write_lock_baton baton; 140251881Speter 141251881Speter /* Don't even attempt to modify the working copy if any of the 142251881Speter * targets look like URLs. URLs are invalid input. */ 143251881Speter for (i = 0; i < paths->nelts; i++) 144251881Speter { 145251881Speter const char *path = APR_ARRAY_IDX(paths, i, const char *); 146251881Speter 147251881Speter if (svn_path_is_url(path)) 148251881Speter return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, 149251881Speter _("'%s' is not a local path"), path); 150251881Speter } 151251881Speter 152251881Speter cfg = ctx->config 153251881Speter ? svn_hash_gets(ctx->config, SVN_CONFIG_CATEGORY_CONFIG) 154251881Speter : NULL; 155251881Speter 156251881Speter SVN_ERR(svn_config_get_bool(cfg, &use_commit_times, 157251881Speter SVN_CONFIG_SECTION_MISCELLANY, 158251881Speter SVN_CONFIG_OPTION_USE_COMMIT_TIMES, 159251881Speter FALSE)); 160251881Speter 161299742Sdim iterpool = svn_pool_create(pool); 162251881Speter 163251881Speter for (i = 0; i < paths->nelts; i++) 164251881Speter { 165251881Speter const char *path = APR_ARRAY_IDX(paths, i, const char *); 166251881Speter const char *local_abspath, *lock_target; 167251881Speter svn_boolean_t wc_root; 168251881Speter 169299742Sdim svn_pool_clear(iterpool); 170251881Speter 171251881Speter /* See if we've been asked to cancel this operation. */ 172251881Speter if ((ctx->cancel_func) 173251881Speter && ((err = ctx->cancel_func(ctx->cancel_baton)))) 174251881Speter goto errorful; 175251881Speter 176299742Sdim err = svn_dirent_get_absolute(&local_abspath, path, iterpool); 177251881Speter if (err) 178251881Speter goto errorful; 179251881Speter 180251881Speter baton.local_abspath = local_abspath; 181251881Speter baton.depth = depth; 182251881Speter baton.use_commit_times = use_commit_times; 183251881Speter baton.changelists = changelists; 184299742Sdim baton.clear_changelists = clear_changelists; 185299742Sdim baton.metadata_only = metadata_only; 186251881Speter baton.ctx = ctx; 187251881Speter 188299742Sdim err = svn_wc__is_wcroot(&wc_root, ctx->wc_ctx, local_abspath, iterpool); 189251881Speter if (err) 190251881Speter goto errorful; 191251881Speter lock_target = wc_root ? local_abspath 192251881Speter : svn_dirent_dirname(local_abspath, pool); 193251881Speter err = svn_wc__call_with_write_lock(revert, &baton, ctx->wc_ctx, 194299742Sdim lock_target, FALSE, 195299742Sdim iterpool, iterpool); 196251881Speter if (err) 197251881Speter goto errorful; 198251881Speter } 199251881Speter 200251881Speter errorful: 201251881Speter 202251881Speter { 203251881Speter /* Sleep to ensure timestamp integrity. */ 204251881Speter const char *sleep_path = NULL; 205251881Speter 206251881Speter /* Only specify a path if we are certain all paths are on the 207251881Speter same filesystem */ 208251881Speter if (paths->nelts == 1) 209251881Speter sleep_path = APR_ARRAY_IDX(paths, 0, const char *); 210251881Speter 211299742Sdim svn_io_sleep_for_timestamps(sleep_path, iterpool); 212251881Speter } 213251881Speter 214299742Sdim svn_pool_destroy(iterpool); 215251881Speter 216251881Speter return svn_error_trace(err); 217251881Speter} 218