File indexing completed on 2024-05-19 16:47: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 * http://kdesvn.alwins-world.de 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/exception.h" 0041 #include "svnqt/pool.h" 0042 #include "svnqt/targets.h" 0043 #include "svnqt/svnqt_defines.h" 0044 #include "svnqt/stringarray.h" 0045 #include "svnqt/client_parameter.h" 0046 #include "svnqt/client_commit_parameter.h" 0047 #include "svnqt/client_update_parameter.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(): m_context(), m_revision(Revision::UNDEFINED), m_date(), author(), commit_error(), repos_root() {} 0058 ContextWP m_context; 0059 svn::Revision m_revision; 0060 QString m_date, author, commit_error, repos_root; 0061 }; 0062 0063 static svn_error_t *commit_callback2(const svn_commit_info_t *commit_info, void *baton, apr_pool_t *pool) 0064 { 0065 Q_UNUSED(pool); 0066 mBaton *m_baton = (mBaton *)baton; 0067 ContextP m_context = m_baton->m_context; 0068 if (!m_context) { 0069 return svn_error_create(SVN_ERR_CANCELLED, nullptr, QCoreApplication::translate("svnqt", "Cancelled by user.").toUtf8()); 0070 } 0071 svn_client_ctx_t *ctx = m_context->ctx(); 0072 if (ctx && ctx->cancel_func) { 0073 SVN_ERR(ctx->cancel_func(ctx->cancel_baton)); 0074 } 0075 m_baton->author = QString::fromUtf8(commit_info->author); 0076 m_baton->commit_error = QString::fromUtf8(commit_info->post_commit_err); 0077 m_baton->m_date = QString::fromUtf8(commit_info->date); 0078 m_baton->repos_root = QString::fromUtf8(commit_info->repos_root); 0079 m_baton->m_revision = commit_info->revision; 0080 return SVN_NO_ERROR; 0081 } 0082 0083 Revision 0084 Client_impl::checkout(const CheckoutParameter ¶meters) 0085 { 0086 Pool subPool; 0087 svn_revnum_t revnum = 0; 0088 svn_error_t *error = nullptr; 0089 error = svn_client_checkout3(&revnum, 0090 parameters.moduleName().cstr(), 0091 parameters.destination().cstr(), 0092 parameters.peg().revision(), 0093 parameters.revision().revision(), 0094 internal::DepthToSvn(parameters.depth()), 0095 parameters.ignoreExternals(), 0096 parameters.overWrite(), 0097 *m_context, 0098 subPool); 0099 if (error != nullptr) { 0100 throw ClientException(error); 0101 } 0102 return Revision(revnum); 0103 } 0104 0105 Revision 0106 Client_impl::remove(const Targets &targets, 0107 bool force, 0108 bool keep_local, 0109 const PropertiesMap &revProps 0110 ) 0111 { 0112 Pool pool; 0113 svn_error_t *error; 0114 0115 mBaton _baton; 0116 _baton.m_context = m_context; 0117 error = svn_client_delete4( 0118 targets.array(pool), 0119 force, 0120 keep_local, 0121 map2hash(revProps, pool), 0122 commit_callback2, 0123 &_baton, 0124 *m_context, 0125 pool 0126 ); 0127 0128 if (error != nullptr) { 0129 throw ClientException(error); 0130 } 0131 return _baton.m_revision; 0132 } 0133 0134 void 0135 Client_impl::revert(const Targets &targets, 0136 Depth depth, 0137 const StringArray &changelist 0138 ) 0139 { 0140 Pool pool; 0141 0142 svn_error_t *error = 0143 svn_client_revert2((targets.array(pool)), 0144 internal::DepthToSvn(depth), 0145 changelist.array(pool), 0146 *m_context, 0147 pool); 0148 if (error != nullptr) { 0149 throw ClientException(error); 0150 } 0151 } 0152 0153 void 0154 Client_impl::add(const Path &path, 0155 svn::Depth depth, bool force, bool no_ignore, bool add_parents) 0156 { 0157 Pool pool; 0158 // todo svn 1.8: svn_client_add5 0159 svn_error_t *error = 0160 svn_client_add4(path.cstr(), 0161 internal::DepthToSvn(depth), 0162 force, 0163 no_ignore, 0164 add_parents, 0165 *m_context, 0166 pool); 0167 if (error != nullptr) { 0168 throw ClientException(error); 0169 } 0170 } 0171 0172 Revisions 0173 Client_impl::update(const UpdateParameter ¶ms) 0174 { 0175 Pool pool; 0176 Revisions resulting; 0177 svn_error_t *error; 0178 0179 apr_pool_t *apr_pool = pool.pool(); 0180 apr_array_header_t *apr_revisions = apr_array_make(apr_pool, 0181 params.targets().size(), 0182 sizeof(svn_revnum_t)); 0183 error = svn_client_update4(&apr_revisions, params.targets().array(pool), params.revision(), 0184 internal::DepthToSvn(params.depth()), params.sticky_depth(), 0185 params.ignore_externals(), params.allow_unversioned(), 0186 params.add_as_modification(), params.make_parents(), 0187 *m_context, pool 0188 ); 0189 0190 if (error != nullptr) { 0191 throw ClientException(error); 0192 } 0193 for (int i = 0; i < apr_revisions->nelts; ++i) { 0194 svn_revnum_t *_rev = 0195 &APR_ARRAY_IDX(apr_revisions, i, svn_revnum_t); 0196 0197 resulting.push_back((*_rev)); 0198 } 0199 return resulting; 0200 } 0201 0202 svn::Revision 0203 Client_impl::commit(const CommitParameter ¶meters) 0204 { 0205 Pool pool; 0206 0207 mBaton _baton; 0208 _baton.m_context = m_context; 0209 m_context->setLogMessage(parameters.message()); 0210 svn_error_t *error = 0211 #if SVN_API_VERSION >= SVN_VERSION_CHECK(1,8,0) 0212 svn_client_commit6( 0213 #else 0214 svn_client_commit5( 0215 #endif 0216 parameters.targets().array(pool), 0217 internal::DepthToSvn(parameters.depth()), 0218 parameters.keepLocks(), 0219 parameters.keepChangeList(), 0220 parameters.commitAsOperations(), 0221 #if SVN_API_VERSION >= SVN_VERSION_CHECK(1,8,0) 0222 false, /* file externals */ 0223 false, /* dir externals */ 0224 #endif 0225 parameters.changeList().array(pool), 0226 map2hash(parameters.revisionProperties(), pool), 0227 commit_callback2, 0228 &_baton, 0229 *m_context, 0230 pool 0231 ); 0232 0233 if (error != nullptr) { 0234 throw ClientException(error); 0235 } 0236 return _baton.m_revision; 0237 } 0238 0239 Revision 0240 Client_impl::copy(const CopyParameter ¶meter) 0241 { 0242 if (parameter.srcPath().size() < 1) { 0243 throw ClientException("Wrong size of sources."); 0244 } 0245 0246 Pool pool; 0247 apr_array_header_t *sources = apr_array_make(pool, parameter.srcPath().size(), sizeof(svn_client_copy_source_t *)); 0248 // not using .array() 'cause some extra information is needed for copy 0249 for (const Path &path : parameter.srcPath().targets()) { 0250 svn_client_copy_source_t *source = (svn_client_copy_source_t *)apr_palloc(pool, sizeof(svn_client_copy_source_t)); 0251 source->path = apr_pstrdup(pool, path.path().toUtf8()); 0252 source->revision = parameter.srcRevision().revision(); 0253 source->peg_revision = parameter.pegRevision().revision(); 0254 APR_ARRAY_PUSH(sources, svn_client_copy_source_t *) = source; 0255 } 0256 mBaton _baton; 0257 _baton.m_context = m_context; 0258 0259 svn_error_t *error = 0260 svn_client_copy6( 0261 sources, 0262 parameter.destination().cstr(), 0263 parameter.asChild(), parameter.makeParent(), parameter.ignoreExternal(), 0264 map2hash(parameter.properties(), pool), 0265 commit_callback2, &_baton, 0266 *m_context, pool); 0267 0268 if (error != nullptr) { 0269 throw ClientException(error); 0270 } 0271 return _baton.m_revision; 0272 } 0273 0274 Revision 0275 Client_impl::copy(const Path &srcPath, 0276 const Revision &srcRevision, 0277 const Path &destPath) 0278 { 0279 return copy(CopyParameter(srcPath, destPath).srcRevision(srcRevision).asChild(true).makeParent(false)); 0280 } 0281 0282 svn::Revision Client_impl::move(const CopyParameter ¶meter) 0283 { 0284 Pool pool; 0285 0286 // todo svn 1.8: svn_client_move7 0287 mBaton _baton; 0288 _baton.m_context = m_context; 0289 svn_error_t *error = svn_client_move6( 0290 parameter.srcPath().array(pool), 0291 parameter.destination().cstr(), 0292 parameter.asChild(), 0293 parameter.makeParent(), 0294 map2hash(parameter.properties(), pool), 0295 commit_callback2, 0296 &_baton, 0297 *m_context, 0298 pool 0299 ); 0300 0301 if (error != nullptr) { 0302 throw ClientException(error); 0303 } 0304 return _baton.m_revision; 0305 0306 } 0307 0308 svn::Revision 0309 Client_impl::mkdir(const Targets &targets, 0310 const QString &msg, 0311 bool makeParent, 0312 const PropertiesMap &revProps 0313 ) 0314 { 0315 Pool pool; 0316 m_context->setLogMessage(msg); 0317 0318 0319 0320 svn_error_t *error = nullptr; 0321 mBaton _baton; 0322 _baton.m_context = m_context; 0323 error = svn_client_mkdir4 0324 ( 0325 const_cast<apr_array_header_t *>(targets.array(pool)), 0326 makeParent, 0327 map2hash(revProps, pool), 0328 commit_callback2, &_baton, 0329 *m_context, pool 0330 ); 0331 /* important! otherwise next op on repository uses that logmessage again! */ 0332 m_context->setLogMessage(QString()); 0333 0334 if (error != nullptr) { 0335 throw ClientException(error); 0336 } 0337 0338 return _baton.m_revision; 0339 } 0340 0341 void 0342 Client_impl::cleanup(const Path &path) 0343 { 0344 Pool subPool; 0345 apr_pool_t *apr_pool = subPool.pool(); 0346 0347 svn_error_t *error = 0348 svn_client_cleanup(path.cstr(), *m_context, apr_pool); 0349 0350 if (error != nullptr) { 0351 throw ClientException(error); 0352 } 0353 } 0354 0355 void Client_impl::resolve(const Path &path, Depth depth, const ConflictResult &resolution) 0356 { 0357 Pool pool; 0358 const svn_wc_conflict_result_t *aResult = resolution.result(pool); 0359 svn_error_t *error = svn_client_resolve(path.cstr(), internal::DepthToSvn(depth), aResult->choice, *m_context, pool); 0360 0361 if (error != nullptr) { 0362 throw ClientException(error); 0363 } 0364 } 0365 0366 Revision 0367 Client_impl::doExport(const CheckoutParameter ¶ms) 0368 { 0369 Pool pool; 0370 svn_revnum_t revnum = 0; 0371 QByteArray _neolBA; 0372 const char *_neol; 0373 if (params.nativeEol().isNull()) { 0374 _neol = nullptr; 0375 } else { 0376 _neolBA = params.nativeEol().toUtf8(); 0377 _neol = _neolBA.constData(); 0378 } 0379 svn_error_t *error = 0380 svn_client_export5( 0381 &revnum, 0382 params.moduleName().cstr(), 0383 params.destination().cstr(), 0384 params.peg().revision(), 0385 params.revision().revision(), 0386 params.overWrite(), 0387 params.ignoreExternals(), 0388 params.ignoreKeywords(), 0389 internal::DepthToSvn(params.depth()), 0390 _neol, 0391 *m_context, 0392 pool); 0393 if (error != nullptr) { 0394 throw ClientException(error); 0395 } 0396 return Revision(revnum); 0397 } 0398 0399 Revision 0400 Client_impl::doSwitch( 0401 const Path &path, 0402 const Url &url, 0403 const Revision &revision, 0404 Depth depth, 0405 const Revision &peg, 0406 bool sticky_depth, 0407 bool ignore_externals, 0408 bool allow_unversioned, 0409 bool ignore_ancestry 0410 ) 0411 { 0412 Pool pool; 0413 svn_revnum_t revnum = 0; 0414 svn_error_t *error = svn_client_switch3( 0415 &revnum, 0416 path.cstr(), 0417 url.cstr(), 0418 peg.revision(), 0419 revision.revision(), 0420 internal::DepthToSvn(depth), 0421 sticky_depth, 0422 ignore_externals, 0423 allow_unversioned, 0424 ignore_ancestry, 0425 *m_context, 0426 pool 0427 ); 0428 if (error != nullptr) { 0429 throw ClientException(error); 0430 } 0431 return Revision(revnum); 0432 } 0433 0434 Revision 0435 Client_impl::import(const Path &path, 0436 const Url &importRepository, 0437 const QString &message, 0438 svn::Depth depth, 0439 bool no_ignore, bool no_unknown_nodetype, 0440 const PropertiesMap &revProps 0441 ) 0442 0443 { 0444 Pool pool; 0445 0446 m_context->setLogMessage(message); 0447 // todo svn 1.8: svn_client_import5 0448 mBaton _baton; 0449 _baton.m_context = m_context; 0450 svn_error_t *error = 0451 svn_client_import4(path.cstr(), 0452 importRepository.cstr(), 0453 internal::DepthToSvn(depth), no_ignore, no_unknown_nodetype, 0454 map2hash(revProps, pool), 0455 commit_callback2, &_baton, 0456 *m_context, pool); 0457 0458 /* important! otherwise next op on repository uses that logmessage again! */ 0459 m_context->setLogMessage(QString()); 0460 0461 if (error != nullptr) { 0462 throw ClientException(error); 0463 } 0464 return _baton.m_revision; 0465 } 0466 0467 void 0468 Client_impl::relocate(const Path &path, 0469 const Url &from_url, 0470 const Url &to_url, 0471 bool recurse, 0472 bool ignore_externals) 0473 { 0474 Q_UNUSED(recurse); 0475 Pool pool; 0476 svn_error_t *error = 0477 svn_client_relocate2(path.cstr(), 0478 from_url.cstr(), 0479 to_url.cstr(), 0480 ignore_externals, 0481 *m_context, 0482 pool); 0483 0484 if (error != nullptr) { 0485 throw ClientException(error); 0486 } 0487 } 0488 0489 } 0490 0491 /* ----------------------------------------------------------------- 0492 * local variables: 0493 * eval: (load-file "../../rapidsvn-dev.el") 0494 * end: 0495 */