File indexing completed on 2024-05-12 17:16:25
0001 /*************************************************************************** 0002 * Copyright (C) 2006-2009 by Rajko Albrecht * 0003 * ral@alwins-world.de * 0004 * * 0005 * This program is free software; you can redistribute it and/or * 0006 * modify it under the terms of the GNU Lesser General Public * 0007 * License as published by the Free Software Foundation; either * 0008 * version 2.1 of the License, or (at your option) any later version. * 0009 * * 0010 * This program is distributed in the hope that it will be useful, * 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 0013 * Lesser General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU Lesser General Public * 0016 * License along with this program (in the file LGPL.txt); if not, * 0017 * write to the Free Software Foundation, Inc., 51 Franklin St, * 0018 * Fifth Floor, Boston, MA 02110-1301 USA * 0019 * * 0020 * This software consists of voluntary contributions made by many * 0021 * individuals. For exact contribution history, see the revision * 0022 * history and logs, available at http://kdesvn.alwins-world.de. * 0023 ***************************************************************************/ 0024 #include "svnqt/repositorydata.h" 0025 #include "svnqt/svnqt_defines.h" 0026 #include "svnqt/exception.h" 0027 #include "svnqt/repositorylistener.h" 0028 #include "svnqt/svnfilestream.h" 0029 #include "svnqt/repoparameter.h" 0030 #include "svnqt/reposnotify.h" 0031 0032 #include <svn_fs.h> 0033 #include <svn_path.h> 0034 #include <svn_config.h> 0035 #include <svn_dirent_uri.h> 0036 #include <svn_version.h> 0037 #include <QCoreApplication> 0038 0039 namespace svn 0040 { 0041 0042 namespace repository 0043 { 0044 0045 class SVNQT_NOEXPORT RepoOutStream: public stream::SvnStream 0046 { 0047 public: 0048 RepoOutStream(RepositoryData *); 0049 0050 bool isOk() const override 0051 { 0052 return true; 0053 } 0054 long write(const char *data, const unsigned long max) override; 0055 0056 protected: 0057 RepositoryData *m_Back; 0058 }; 0059 0060 RepoOutStream::RepoOutStream(RepositoryData *aBack) 0061 : SvnStream(false, true) 0062 { 0063 m_Back = aBack; 0064 } 0065 0066 long RepoOutStream::write(const char *data, const unsigned long max) 0067 { 0068 if (m_Back) { 0069 QString msg = QString::fromUtf8(data, max); 0070 m_Back->reposFsWarning(msg); 0071 } 0072 return max; 0073 } 0074 0075 RepositoryData::RepositoryData(RepositoryListener *aListener) 0076 { 0077 m_Repository = nullptr; 0078 m_Listener = aListener; 0079 } 0080 0081 RepositoryData::~RepositoryData() 0082 { 0083 } 0084 0085 void RepositoryData::warning_func(void *baton, svn_error_t *err) 0086 { 0087 RepositoryData *_r = (RepositoryData *)baton; 0088 0089 if (_r) { 0090 QString msg = svn::Exception::error2msg(err); 0091 svn_error_clear(err); 0092 _r->reposFsWarning(msg); 0093 } 0094 } 0095 0096 void RepositoryData::repo_notify_func(void *baton, const svn_repos_notify_t *notify, apr_pool_t *scratch_pool) 0097 { 0098 Q_UNUSED(scratch_pool) 0099 RepositoryData *_r = (RepositoryData *)baton; 0100 if (!notify || !_r) { 0101 return; 0102 } 0103 ReposNotify _rn(notify); 0104 QString msg = _rn; 0105 0106 if (msg.length() > 0) { 0107 _r->reposFsWarning(msg); 0108 } 0109 } 0110 0111 void RepositoryData::reposFsWarning(const QString &msg) 0112 { 0113 if (m_Listener) { 0114 m_Listener->sendWarning(msg); 0115 } 0116 } 0117 0118 svn_error_t *RepositoryData::cancel_func(void *baton) 0119 { 0120 RepositoryListener *m_L = (RepositoryListener *)baton; 0121 if (m_L && m_L->isCanceld()) { 0122 return svn_error_create(SVN_ERR_CANCELLED, nullptr, QCoreApplication::translate("svnqt", "Cancelled by user.").toUtf8()); 0123 } 0124 return SVN_NO_ERROR; 0125 } 0126 0127 /*! 0128 \fn svn::RepositoryData::close() 0129 */ 0130 void RepositoryData::Close() 0131 { 0132 m_Pool.renew(); 0133 m_Repository = nullptr; 0134 } 0135 0136 /*! 0137 \fn svn::RepositoryData::Open(const QString&) 0138 */ 0139 svn_error_t *RepositoryData::Open(const QString &path) 0140 { 0141 Close(); 0142 svn_error_t *error = svn_repos_open2(&m_Repository, path.toUtf8(), nullptr, m_Pool); 0143 if (error != nullptr) { 0144 m_Repository = nullptr; 0145 return error; 0146 } 0147 svn_fs_set_warning_func(svn_repos_fs(m_Repository), RepositoryData::warning_func, this); 0148 return SVN_NO_ERROR; 0149 } 0150 0151 /*! 0152 \fn svn::RepositoryData::CreateOpen(const QString&path, const QString&fstype, bool _bdbnosync = false, bool _bdbautologremove = true, bool nosvn1diff=false) 0153 */ 0154 svn_error_t *RepositoryData::CreateOpen(const CreateRepoParameter ¶ms) 0155 { 0156 Close(); 0157 const char *_type; 0158 if (params.fstype().compare(QLatin1String("bdb"), Qt::CaseInsensitive) == 0) { 0159 _type = "bdb"; 0160 } else { 0161 _type = "fsfs"; 0162 } 0163 apr_hash_t *config; 0164 apr_hash_t *fs_config = apr_hash_make(m_Pool); 0165 0166 apr_hash_set(fs_config, SVN_FS_CONFIG_BDB_TXN_NOSYNC, 0167 APR_HASH_KEY_STRING, 0168 (params.bdbnosync() ? "1" : "0")); 0169 apr_hash_set(fs_config, SVN_FS_CONFIG_BDB_LOG_AUTOREMOVE, 0170 APR_HASH_KEY_STRING, 0171 (params.bdbautologremove() ? "1" : "0")); 0172 apr_hash_set(fs_config, SVN_FS_CONFIG_FS_TYPE, 0173 APR_HASH_KEY_STRING, 0174 _type); 0175 0176 if (params.pre15_compat()) { 0177 apr_hash_set(fs_config, SVN_FS_CONFIG_PRE_1_5_COMPATIBLE, 0178 APR_HASH_KEY_STRING, "1"); 0179 } 0180 if (params.pre16_compat()) { 0181 apr_hash_set(fs_config, SVN_FS_CONFIG_PRE_1_6_COMPATIBLE, 0182 APR_HASH_KEY_STRING, "1"); 0183 } 0184 #if SVN_API_VERSION >= SVN_VERSION_CHECK(1,8,0) 0185 if (params.pre18_compat()) { 0186 apr_hash_set(fs_config, SVN_FS_CONFIG_PRE_1_8_COMPATIBLE, 0187 APR_HASH_KEY_STRING, "1"); 0188 } 0189 #endif 0190 0191 /// @todo config as extra parameter? Meanwhile default config only 0192 /// (see svn::ContextData) 0193 SVN_ERR(svn_config_get_config(&config, nullptr, m_Pool)); 0194 const char *repository_path = apr_pstrdup(m_Pool, params.path().toUtf8()); 0195 0196 repository_path = svn_dirent_internal_style(repository_path, m_Pool); 0197 0198 if (svn_path_is_url(repository_path)) { 0199 return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, nullptr, 0200 QCoreApplication::translate("svnqt", "'%1' is an URL when it should be a path").arg(params.path()).toUtf8()); 0201 } 0202 SVN_ERR(svn_repos_create(&m_Repository, repository_path, 0203 nullptr, nullptr, config, fs_config, m_Pool)); 0204 0205 svn_fs_set_warning_func(svn_repos_fs(m_Repository), RepositoryData::warning_func, this); 0206 0207 return SVN_NO_ERROR; 0208 } 0209 0210 /*! 0211 \fn svn::RepositoryData::dump(const QString&output,const svn::Revision&start,const svn::Revision&end, bool incremental, bool use_deltas) 0212 */ 0213 svn_error_t *RepositoryData::dump(const QString &output, const svn::Revision &start, const svn::Revision &end, bool incremental, bool use_deltas) 0214 { 0215 if (!m_Repository) { 0216 return svn_error_create(SVN_ERR_CANCELLED, nullptr, QCoreApplication::translate("svnqt", "No repository selected.").toUtf8()); 0217 } 0218 Pool pool; 0219 svn::stream::SvnFileOStream out(output); 0220 svn_revnum_t _s, _e; 0221 _s = start.revnum(); 0222 _e = end.revnum(); 0223 0224 SVN_ERR(svn_repos_dump_fs3(m_Repository, 0225 out, _s, _e, incremental, use_deltas, 0226 RepositoryData::repo_notify_func, 0227 this, 0228 RepositoryData::cancel_func, 0229 m_Listener, 0230 pool)); 0231 return SVN_NO_ERROR; 0232 } 0233 0234 svn_error_t *RepositoryData::loaddump(const QString &dump, svn_repos_load_uuid uuida, const QString &parentFolder, bool usePre, bool usePost, bool validateProps) 0235 { 0236 if (!m_Repository) { 0237 return svn_error_create(SVN_ERR_CANCELLED, nullptr, QCoreApplication::translate("svnqt", "No repository selected.").toUtf8()); 0238 } 0239 svn::stream::SvnFileIStream infile(dump); 0240 RepoOutStream backstream(this); 0241 Pool pool; 0242 const char *src_path = apr_pstrdup(pool, dump.toUtf8()); 0243 const char *dest_path; 0244 if (parentFolder.isEmpty()) { 0245 dest_path = nullptr; 0246 } else { 0247 dest_path = apr_pstrdup(pool, parentFolder.toUtf8()); 0248 } 0249 src_path = svn_path_internal_style(src_path, pool); 0250 0251 // todo svn 1.8: svn_repos_load_fs4 0252 SVN_ERR(svn_repos_load_fs3(m_Repository, infile, uuida, dest_path, usePre ? 1 : 0, usePost ? 1 : 0, validateProps ? 1 : 0, 0253 RepositoryData::repo_notify_func, 0254 this, RepositoryData::cancel_func, m_Listener, pool)); 0255 return SVN_NO_ERROR; 0256 } 0257 0258 svn_error_t *RepositoryData::hotcopy(const QString &src, const QString &dest, bool cleanlogs) 0259 { 0260 Pool pool; 0261 const char *src_path = apr_pstrdup(pool, src.toUtf8()); 0262 const char *dest_path = apr_pstrdup(pool, dest.toUtf8()); 0263 src_path = svn_dirent_internal_style(src_path, pool); 0264 dest_path = svn_dirent_internal_style(dest_path, pool); 0265 // todo svn 1.8: svn_repos_hotcopy2 0266 SVN_ERR(svn_repos_hotcopy(src_path, dest_path, cleanlogs ? 1 : 0, pool)); 0267 return SVN_NO_ERROR; 0268 } 0269 0270 } 0271 0272 }