File indexing completed on 2024-04-28 05:42:08
0001 /* 0002 * Port for usage with qt-framework and development for kdesvn 0003 * Copyright (C) 2005-2009 by Rajko Albrecht (ral@alwins-world.de) 0004 * https://kde.org/applications/development/org.kde.kdesvn 0005 */ 0006 /* 0007 * ==================================================================== 0008 * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. 0009 * dev@rapidsvn.tigris.org 0010 * 0011 * This library is free software; you can redistribute it and/or 0012 * modify it under the terms of the GNU Lesser General Public 0013 * License as published by the Free Software Foundation; either 0014 * version 2.1 of the License, or (at your option) any later version. 0015 * 0016 * This library is distributed in the hope that it will be useful, 0017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0019 * Lesser General Public License for more details. 0020 * 0021 * You should have received a copy of the GNU Lesser General Public 0022 * License along with this library (in the file LGPL.txt); if not, 0023 * write to the Free Software Foundation, Inc., 51 Franklin St, 0024 * Fifth Floor, Boston, MA 02110-1301 USA 0025 * 0026 * This software consists of voluntary contributions made by many 0027 * individuals. For exact contribution history, see the revision 0028 * history and logs, available at http://rapidsvn.tigris.org/. 0029 * ==================================================================== 0030 */ 0031 #if defined(_MSC_VER) && _MSC_VER <= 1200 0032 #pragma warning(disable : 4786) // debug symbol truncated 0033 #endif 0034 // svncpp 0035 #include "svnqt/client_impl.h" 0036 0037 // subversion api 0038 #include "svn_client.h" 0039 0040 #include "svnqt/client_commit_parameter.h" 0041 #include "svnqt/client_parameter.h" 0042 #include "svnqt/client_update_parameter.h" 0043 #include "svnqt/exception.h" 0044 #include "svnqt/pool.h" 0045 #include "svnqt/stringarray.h" 0046 #include "svnqt/svnqt_defines.h" 0047 #include "svnqt/targets.h" 0048 #include "svnqt/url.h" 0049 0050 #include "svnqt/helper.h" 0051 0052 #include <QCoreApplication> 0053 0054 namespace svn 0055 { 0056 struct mBaton { 0057 mBaton() 0058 : m_context() 0059 , m_revision(Revision::UNDEFINED) 0060 , m_date() 0061 , author() 0062 , commit_error() 0063 , repos_root() 0064 { 0065 } 0066 ContextWP m_context; 0067 svn::Revision m_revision; 0068 QString m_date, author, commit_error, repos_root; 0069 }; 0070 0071 static svn_error_t *commit_callback2(const svn_commit_info_t *commit_info, void *baton, apr_pool_t *pool) 0072 { 0073 Q_UNUSED(pool); 0074 mBaton *m_baton = (mBaton *)baton; 0075 ContextP m_context = m_baton->m_context; 0076 if (!m_context) { 0077 return svn_error_create(SVN_ERR_CANCELLED, nullptr, QCoreApplication::translate("svnqt", "Cancelled by user.").toUtf8()); 0078 } 0079 svn_client_ctx_t *ctx = m_context->ctx(); 0080 if (ctx && ctx->cancel_func) { 0081 SVN_ERR(ctx->cancel_func(ctx->cancel_baton)); 0082 } 0083 m_baton->author = QString::fromUtf8(commit_info->author); 0084 m_baton->commit_error = QString::fromUtf8(commit_info->post_commit_err); 0085 m_baton->m_date = QString::fromUtf8(commit_info->date); 0086 m_baton->repos_root = QString::fromUtf8(commit_info->repos_root); 0087 m_baton->m_revision = commit_info->revision; 0088 return SVN_NO_ERROR; 0089 } 0090 0091 Revision Client_impl::checkout(const CheckoutParameter ¶meters) 0092 { 0093 Pool subPool; 0094 svn_revnum_t revnum = 0; 0095 svn_error_t *error = nullptr; 0096 error = svn_client_checkout3(&revnum, 0097 parameters.moduleName().cstr(), 0098 parameters.destination().cstr(), 0099 parameters.peg().revision(), 0100 parameters.revision().revision(), 0101 internal::DepthToSvn(parameters.depth()), 0102 parameters.ignoreExternals(), 0103 parameters.overWrite(), 0104 *m_context, 0105 subPool); 0106 if (error != nullptr) { 0107 throw ClientException(error); 0108 } 0109 return Revision(revnum); 0110 } 0111 0112 Revision Client_impl::remove(const Targets &targets, bool force, bool keep_local, const PropertiesMap &revProps) 0113 { 0114 Pool pool; 0115 svn_error_t *error; 0116 0117 mBaton _baton; 0118 _baton.m_context = m_context; 0119 error = svn_client_delete4(targets.array(pool), force, keep_local, map2hash(revProps, pool), commit_callback2, &_baton, *m_context, pool); 0120 0121 if (error != nullptr) { 0122 throw ClientException(error); 0123 } 0124 return _baton.m_revision; 0125 } 0126 0127 void Client_impl::revert(const Targets &targets, Depth depth, const StringArray &changelist) 0128 { 0129 Pool pool; 0130 0131 svn_error_t *error = svn_client_revert2((targets.array(pool)), internal::DepthToSvn(depth), changelist.array(pool), *m_context, pool); 0132 if (error != nullptr) { 0133 throw ClientException(error); 0134 } 0135 } 0136 0137 void Client_impl::add(const Path &path, svn::Depth depth, bool force, bool no_ignore, bool add_parents) 0138 { 0139 Pool pool; 0140 // todo svn 1.8: svn_client_add5 0141 svn_error_t *error = svn_client_add4(path.cstr(), internal::DepthToSvn(depth), force, no_ignore, add_parents, *m_context, pool); 0142 if (error != nullptr) { 0143 throw ClientException(error); 0144 } 0145 } 0146 0147 Revisions Client_impl::update(const UpdateParameter ¶ms) 0148 { 0149 Pool pool; 0150 Revisions resulting; 0151 svn_error_t *error; 0152 0153 apr_pool_t *apr_pool = pool.pool(); 0154 apr_array_header_t *apr_revisions = apr_array_make(apr_pool, params.targets().size(), sizeof(svn_revnum_t)); 0155 error = svn_client_update4(&apr_revisions, 0156 params.targets().array(pool), 0157 params.revision(), 0158 internal::DepthToSvn(params.depth()), 0159 params.sticky_depth(), 0160 params.ignore_externals(), 0161 params.allow_unversioned(), 0162 params.add_as_modification(), 0163 params.make_parents(), 0164 *m_context, 0165 pool); 0166 0167 if (error != nullptr) { 0168 throw ClientException(error); 0169 } 0170 for (int i = 0; i < apr_revisions->nelts; ++i) { 0171 svn_revnum_t *_rev = &APR_ARRAY_IDX(apr_revisions, i, svn_revnum_t); 0172 0173 resulting.push_back((*_rev)); 0174 } 0175 return resulting; 0176 } 0177 0178 svn::Revision Client_impl::commit(const CommitParameter ¶meters) 0179 { 0180 Pool pool; 0181 0182 mBaton _baton; 0183 _baton.m_context = m_context; 0184 m_context->setLogMessage(parameters.message()); 0185 svn_error_t *error = 0186 #if SVN_API_VERSION >= SVN_VERSION_CHECK(1, 8, 0) 0187 svn_client_commit6( 0188 #else 0189 svn_client_commit5( 0190 #endif 0191 parameters.targets().array(pool), 0192 internal::DepthToSvn(parameters.depth()), 0193 parameters.keepLocks(), 0194 parameters.keepChangeList(), 0195 parameters.commitAsOperations(), 0196 #if SVN_API_VERSION >= SVN_VERSION_CHECK(1, 8, 0) 0197 false, /* file externals */ 0198 false, /* dir externals */ 0199 #endif 0200 parameters.changeList().array(pool), 0201 map2hash(parameters.revisionProperties(), pool), 0202 commit_callback2, 0203 &_baton, 0204 *m_context, 0205 pool); 0206 0207 if (error != nullptr) { 0208 throw ClientException(error); 0209 } 0210 return _baton.m_revision; 0211 } 0212 0213 Revision Client_impl::copy(const CopyParameter ¶meter) 0214 { 0215 if (parameter.srcPath().size() < 1) { 0216 throw ClientException("Wrong size of sources."); 0217 } 0218 0219 Pool pool; 0220 apr_array_header_t *sources = apr_array_make(pool, parameter.srcPath().size(), sizeof(svn_client_copy_source_t *)); 0221 // not using .array() 'cause some extra information is needed for copy 0222 for (const Path &path : parameter.srcPath().targets()) { 0223 svn_client_copy_source_t *source = (svn_client_copy_source_t *)apr_palloc(pool, sizeof(svn_client_copy_source_t)); 0224 source->path = apr_pstrdup(pool, path.path().toUtf8()); 0225 source->revision = parameter.srcRevision().revision(); 0226 source->peg_revision = parameter.pegRevision().revision(); 0227 APR_ARRAY_PUSH(sources, svn_client_copy_source_t *) = source; 0228 } 0229 mBaton _baton; 0230 _baton.m_context = m_context; 0231 0232 svn_error_t *error = svn_client_copy6(sources, 0233 parameter.destination().cstr(), 0234 parameter.asChild(), 0235 parameter.makeParent(), 0236 parameter.ignoreExternal(), 0237 map2hash(parameter.properties(), pool), 0238 commit_callback2, 0239 &_baton, 0240 *m_context, 0241 pool); 0242 0243 if (error != nullptr) { 0244 throw ClientException(error); 0245 } 0246 return _baton.m_revision; 0247 } 0248 0249 Revision Client_impl::copy(const Path &srcPath, const Revision &srcRevision, const Path &destPath) 0250 { 0251 return copy(CopyParameter(srcPath, destPath).srcRevision(srcRevision).asChild(true).makeParent(false)); 0252 } 0253 0254 svn::Revision Client_impl::move(const CopyParameter ¶meter) 0255 { 0256 Pool pool; 0257 0258 // todo svn 1.8: svn_client_move7 0259 mBaton _baton; 0260 _baton.m_context = m_context; 0261 svn_error_t *error = svn_client_move6(parameter.srcPath().array(pool), 0262 parameter.destination().cstr(), 0263 parameter.asChild(), 0264 parameter.makeParent(), 0265 map2hash(parameter.properties(), pool), 0266 commit_callback2, 0267 &_baton, 0268 *m_context, 0269 pool); 0270 0271 if (error != nullptr) { 0272 throw ClientException(error); 0273 } 0274 return _baton.m_revision; 0275 } 0276 0277 svn::Revision Client_impl::mkdir(const Targets &targets, const QString &msg, bool makeParent, const PropertiesMap &revProps) 0278 { 0279 Pool pool; 0280 m_context->setLogMessage(msg); 0281 0282 svn_error_t *error = nullptr; 0283 mBaton _baton; 0284 _baton.m_context = m_context; 0285 error = svn_client_mkdir4(const_cast<apr_array_header_t *>(targets.array(pool)), 0286 makeParent, 0287 map2hash(revProps, pool), 0288 commit_callback2, 0289 &_baton, 0290 *m_context, 0291 pool); 0292 /* important! otherwise next op on repository uses that logmessage again! */ 0293 m_context->setLogMessage(QString()); 0294 0295 if (error != nullptr) { 0296 throw ClientException(error); 0297 } 0298 0299 return _baton.m_revision; 0300 } 0301 0302 void Client_impl::cleanup(const Path &path) 0303 { 0304 Pool subPool; 0305 apr_pool_t *apr_pool = subPool.pool(); 0306 0307 svn_error_t *error = svn_client_cleanup(path.cstr(), *m_context, apr_pool); 0308 0309 if (error != nullptr) { 0310 throw ClientException(error); 0311 } 0312 } 0313 0314 void Client_impl::resolve(const Path &path, Depth depth, const ConflictResult &resolution) 0315 { 0316 Pool pool; 0317 const svn_wc_conflict_result_t *aResult = resolution.result(pool); 0318 svn_error_t *error = svn_client_resolve(path.cstr(), internal::DepthToSvn(depth), aResult->choice, *m_context, pool); 0319 0320 if (error != nullptr) { 0321 throw ClientException(error); 0322 } 0323 } 0324 0325 Revision Client_impl::doExport(const CheckoutParameter ¶ms) 0326 { 0327 Pool pool; 0328 svn_revnum_t revnum = 0; 0329 QByteArray _neolBA; 0330 const char *_neol; 0331 if (params.nativeEol().isNull()) { 0332 _neol = nullptr; 0333 } else { 0334 _neolBA = params.nativeEol().toUtf8(); 0335 _neol = _neolBA.constData(); 0336 } 0337 svn_error_t *error = svn_client_export5(&revnum, 0338 params.moduleName().cstr(), 0339 params.destination().cstr(), 0340 params.peg().revision(), 0341 params.revision().revision(), 0342 params.overWrite(), 0343 params.ignoreExternals(), 0344 params.ignoreKeywords(), 0345 internal::DepthToSvn(params.depth()), 0346 _neol, 0347 *m_context, 0348 pool); 0349 if (error != nullptr) { 0350 throw ClientException(error); 0351 } 0352 return Revision(revnum); 0353 } 0354 0355 Revision Client_impl::doSwitch(const Path &path, 0356 const Url &url, 0357 const Revision &revision, 0358 Depth depth, 0359 const Revision &peg, 0360 bool sticky_depth, 0361 bool ignore_externals, 0362 bool allow_unversioned, 0363 bool ignore_ancestry) 0364 { 0365 Pool pool; 0366 svn_revnum_t revnum = 0; 0367 svn_error_t *error = svn_client_switch3(&revnum, 0368 path.cstr(), 0369 url.cstr(), 0370 peg.revision(), 0371 revision.revision(), 0372 internal::DepthToSvn(depth), 0373 sticky_depth, 0374 ignore_externals, 0375 allow_unversioned, 0376 ignore_ancestry, 0377 *m_context, 0378 pool); 0379 if (error != nullptr) { 0380 throw ClientException(error); 0381 } 0382 return Revision(revnum); 0383 } 0384 0385 Revision Client_impl::import(const Path &path, 0386 const Url &importRepository, 0387 const QString &message, 0388 svn::Depth depth, 0389 bool no_ignore, 0390 bool no_unknown_nodetype, 0391 const PropertiesMap &revProps) 0392 0393 { 0394 Pool pool; 0395 0396 m_context->setLogMessage(message); 0397 // todo svn 1.8: svn_client_import5 0398 mBaton _baton; 0399 _baton.m_context = m_context; 0400 svn_error_t *error = svn_client_import4(path.cstr(), 0401 importRepository.cstr(), 0402 internal::DepthToSvn(depth), 0403 no_ignore, 0404 no_unknown_nodetype, 0405 map2hash(revProps, pool), 0406 commit_callback2, 0407 &_baton, 0408 *m_context, 0409 pool); 0410 0411 /* important! otherwise next op on repository uses that logmessage again! */ 0412 m_context->setLogMessage(QString()); 0413 0414 if (error != nullptr) { 0415 throw ClientException(error); 0416 } 0417 return _baton.m_revision; 0418 } 0419 0420 void Client_impl::relocate(const Path &path, const Url &from_url, const Url &to_url, bool recurse, bool ignore_externals) 0421 { 0422 Q_UNUSED(recurse); 0423 Pool pool; 0424 svn_error_t *error = svn_client_relocate2(path.cstr(), from_url.cstr(), to_url.cstr(), ignore_externals, *m_context, pool); 0425 0426 if (error != nullptr) { 0427 throw ClientException(error); 0428 } 0429 } 0430 0431 } 0432 0433 /* ----------------------------------------------------------------- 0434 * local variables: 0435 * eval: (load-file "../../rapidsvn-dev.el") 0436 * end: 0437 */