revert.c revision 362181
1/* 2 * revert.c: wrapper around wc revert functionality. 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 26 27 28/*** Includes. ***/ 29 30#include "svn_path.h" 31#include "svn_wc.h" 32#include "svn_client.h" 33#include "svn_dirent_uri.h" 34#include "svn_hash.h" 35#include "svn_pools.h" 36#include "svn_error.h" 37#include "svn_time.h" 38#include "svn_config.h" 39#include "client.h" 40#include "private/svn_wc_private.h" 41 42#include "svn_private_config.h" 43 44 45/*** Code. ***/ 46 47struct revert_with_write_lock_baton { 48 const char *local_abspath; 49 svn_depth_t depth; 50 svn_boolean_t use_commit_times; 51 const apr_array_header_t *changelists; 52 svn_boolean_t clear_changelists; 53 svn_boolean_t metadata_only; 54 svn_boolean_t added_keep_local; 55 svn_client_ctx_t *ctx; 56}; 57 58/* (Note: All arguments are in the baton above.) 59 60 Attempt to revert LOCAL_ABSPATH by calling svn_wc_revert6(), which 61 see for further details. 62 63 If the target isn't versioned, send a 'skip' notification and return 64 no error. 65 */ 66static svn_error_t * 67revert(void *baton, apr_pool_t *result_pool, apr_pool_t *scratch_pool) 68{ 69 struct revert_with_write_lock_baton *b = baton; 70 svn_error_t *err; 71 72 err = svn_wc_revert6(b->ctx->wc_ctx, 73 b->local_abspath, 74 b->depth, 75 b->use_commit_times, 76 b->changelists, 77 b->clear_changelists, 78 b->metadata_only, 79 b->added_keep_local, 80 b->ctx->cancel_func, b->ctx->cancel_baton, 81 b->ctx->notify_func2, b->ctx->notify_baton2, 82 scratch_pool); 83 84 if (err) 85 { 86 /* If target isn't versioned, just send a 'skip' 87 notification and move on. */ 88 if (err->apr_err == SVN_ERR_ENTRY_NOT_FOUND 89 || err->apr_err == SVN_ERR_UNVERSIONED_RESOURCE 90 || err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) 91 { 92 if (b->ctx->notify_func2) 93 { 94 svn_wc_notify_t *notify; 95 96 notify = svn_wc_create_notify(b->local_abspath, 97 svn_wc_notify_skip, 98 scratch_pool); 99 100 notify->err = err; 101 102 b->ctx->notify_func2(b->ctx->notify_baton2, 103 notify, scratch_pool); 104 } 105 svn_error_clear(err); 106 } 107 else 108 return svn_error_trace(err); 109 } 110 111 return SVN_NO_ERROR; 112} 113 114 115svn_error_t * 116svn_client_revert4(const apr_array_header_t *paths, 117 svn_depth_t depth, 118 const apr_array_header_t *changelists, 119 svn_boolean_t clear_changelists, 120 svn_boolean_t metadata_only, 121 svn_boolean_t added_keep_local, 122 svn_client_ctx_t *ctx, 123 apr_pool_t *pool) 124{ 125 apr_pool_t *iterpool; 126 svn_error_t *err = SVN_NO_ERROR; 127 int i; 128 svn_config_t *cfg; 129 svn_boolean_t use_commit_times; 130 struct revert_with_write_lock_baton baton; 131 132 /* Don't even attempt to modify the working copy if any of the 133 * targets look like URLs. URLs are invalid input. */ 134 for (i = 0; i < paths->nelts; i++) 135 { 136 const char *path = APR_ARRAY_IDX(paths, i, const char *); 137 138 if (svn_path_is_url(path)) 139 return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, 140 _("'%s' is not a local path"), path); 141 } 142 143 cfg = ctx->config 144 ? svn_hash_gets(ctx->config, SVN_CONFIG_CATEGORY_CONFIG) 145 : NULL; 146 147 SVN_ERR(svn_config_get_bool(cfg, &use_commit_times, 148 SVN_CONFIG_SECTION_MISCELLANY, 149 SVN_CONFIG_OPTION_USE_COMMIT_TIMES, 150 FALSE)); 151 152 iterpool = svn_pool_create(pool); 153 154 for (i = 0; i < paths->nelts; i++) 155 { 156 const char *path = APR_ARRAY_IDX(paths, i, const char *); 157 const char *local_abspath, *lock_target; 158 svn_boolean_t wc_root; 159 160 svn_pool_clear(iterpool); 161 162 /* See if we've been asked to cancel this operation. */ 163 if ((ctx->cancel_func) 164 && ((err = ctx->cancel_func(ctx->cancel_baton)))) 165 goto errorful; 166 167 err = svn_dirent_get_absolute(&local_abspath, path, iterpool); 168 if (err) 169 goto errorful; 170 171 baton.local_abspath = local_abspath; 172 baton.depth = depth; 173 baton.use_commit_times = use_commit_times; 174 baton.changelists = changelists; 175 baton.clear_changelists = clear_changelists; 176 baton.metadata_only = metadata_only; 177 baton.added_keep_local = added_keep_local; 178 baton.ctx = ctx; 179 180 err = svn_wc__is_wcroot(&wc_root, ctx->wc_ctx, local_abspath, iterpool); 181 if (err) 182 goto errorful; 183 lock_target = wc_root ? local_abspath 184 : svn_dirent_dirname(local_abspath, pool); 185 err = svn_wc__call_with_write_lock(revert, &baton, ctx->wc_ctx, 186 lock_target, FALSE, 187 iterpool, iterpool); 188 if (err) 189 goto errorful; 190 } 191 192 errorful: 193 194 { 195 /* Sleep to ensure timestamp integrity. */ 196 const char *sleep_path = NULL; 197 198 /* Only specify a path if we are certain all paths are on the 199 same filesystem */ 200 if (paths->nelts == 1) 201 sleep_path = APR_ARRAY_IDX(paths, 0, const char *); 202 203 svn_io_sleep_for_timestamps(sleep_path, iterpool); 204 } 205 206 svn_pool_destroy(iterpool); 207 208 return svn_error_trace(err); 209} 210