File indexing completed on 2024-04-28 05:42:11
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 https://commits.kde.org/kdesvn. * 0023 ***************************************************************************/ 0024 #include "svnqt/repositorydata.h" 0025 #include "svnqt/exception.h" 0026 #include "svnqt/repoparameter.h" 0027 #include "svnqt/repositorylistener.h" 0028 #include "svnqt/reposnotify.h" 0029 #include "svnqt/svnfilestream.h" 0030 #include "svnqt/svnqt_defines.h" 0031 0032 #include <QCoreApplication> 0033 #include <svn_config.h> 0034 #include <svn_dirent_uri.h> 0035 #include <svn_fs.h> 0036 #include <svn_path.h> 0037 #include <svn_version.h> 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, APR_HASH_KEY_STRING, (params.bdbnosync() ? "1" : "0")); 0167 apr_hash_set(fs_config, SVN_FS_CONFIG_BDB_LOG_AUTOREMOVE, APR_HASH_KEY_STRING, (params.bdbautologremove() ? "1" : "0")); 0168 apr_hash_set(fs_config, SVN_FS_CONFIG_FS_TYPE, APR_HASH_KEY_STRING, _type); 0169 0170 if (params.pre15_compat()) { 0171 apr_hash_set(fs_config, SVN_FS_CONFIG_PRE_1_5_COMPATIBLE, APR_HASH_KEY_STRING, "1"); 0172 } 0173 if (params.pre16_compat()) { 0174 apr_hash_set(fs_config, SVN_FS_CONFIG_PRE_1_6_COMPATIBLE, APR_HASH_KEY_STRING, "1"); 0175 } 0176 #if SVN_API_VERSION >= SVN_VERSION_CHECK(1, 8, 0) 0177 if (params.pre18_compat()) { 0178 apr_hash_set(fs_config, SVN_FS_CONFIG_PRE_1_8_COMPATIBLE, APR_HASH_KEY_STRING, "1"); 0179 } 0180 #endif 0181 0182 /// @todo config as extra parameter? Meanwhile default config only 0183 /// (see svn::ContextData) 0184 SVN_ERR(svn_config_get_config(&config, nullptr, m_Pool)); 0185 const char *repository_path = apr_pstrdup(m_Pool, params.path().toUtf8()); 0186 0187 repository_path = svn_dirent_internal_style(repository_path, m_Pool); 0188 0189 if (svn_path_is_url(repository_path)) { 0190 return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, 0191 nullptr, 0192 QCoreApplication::translate("svnqt", "'%1' is an URL when it should be a path").arg(params.path()).toUtf8()); 0193 } 0194 SVN_ERR(svn_repos_create(&m_Repository, repository_path, nullptr, nullptr, config, fs_config, m_Pool)); 0195 0196 svn_fs_set_warning_func(svn_repos_fs(m_Repository), RepositoryData::warning_func, this); 0197 0198 return SVN_NO_ERROR; 0199 } 0200 0201 /*! 0202 \fn svn::RepositoryData::dump(const QString&output,const svn::Revision&start,const svn::Revision&end, bool incremental, bool use_deltas) 0203 */ 0204 svn_error_t *RepositoryData::dump(const QString &output, const svn::Revision &start, const svn::Revision &end, bool incremental, bool use_deltas) 0205 { 0206 if (!m_Repository) { 0207 return svn_error_create(SVN_ERR_CANCELLED, nullptr, QCoreApplication::translate("svnqt", "No repository selected.").toUtf8()); 0208 } 0209 Pool pool; 0210 svn::stream::SvnFileOStream out(output); 0211 svn_revnum_t _s, _e; 0212 _s = start.revnum(); 0213 _e = end.revnum(); 0214 0215 SVN_ERR(svn_repos_dump_fs3(m_Repository, 0216 out, 0217 _s, 0218 _e, 0219 incremental, 0220 use_deltas, 0221 RepositoryData::repo_notify_func, 0222 this, 0223 RepositoryData::cancel_func, 0224 m_Listener, 0225 pool)); 0226 return SVN_NO_ERROR; 0227 } 0228 0229 svn_error_t * 0230 RepositoryData::loaddump(const QString &dump, svn_repos_load_uuid uuida, const QString &parentFolder, bool usePre, bool usePost, bool validateProps) 0231 { 0232 if (!m_Repository) { 0233 return svn_error_create(SVN_ERR_CANCELLED, nullptr, QCoreApplication::translate("svnqt", "No repository selected.").toUtf8()); 0234 } 0235 svn::stream::SvnFileIStream infile(dump); 0236 RepoOutStream backstream(this); 0237 Pool pool; 0238 const char *src_path = apr_pstrdup(pool, dump.toUtf8()); 0239 const char *dest_path; 0240 if (parentFolder.isEmpty()) { 0241 dest_path = nullptr; 0242 } else { 0243 dest_path = apr_pstrdup(pool, parentFolder.toUtf8()); 0244 } 0245 src_path = svn_path_internal_style(src_path, pool); 0246 0247 // todo svn 1.8: svn_repos_load_fs4 0248 SVN_ERR(svn_repos_load_fs3(m_Repository, 0249 infile, 0250 uuida, 0251 dest_path, 0252 usePre ? 1 : 0, 0253 usePost ? 1 : 0, 0254 validateProps ? 1 : 0, 0255 RepositoryData::repo_notify_func, 0256 this, 0257 RepositoryData::cancel_func, 0258 m_Listener, 0259 pool)); 0260 return SVN_NO_ERROR; 0261 } 0262 0263 svn_error_t *RepositoryData::hotcopy(const QString &src, const QString &dest, bool cleanlogs) 0264 { 0265 Pool pool; 0266 const char *src_path = apr_pstrdup(pool, src.toUtf8()); 0267 const char *dest_path = apr_pstrdup(pool, dest.toUtf8()); 0268 src_path = svn_dirent_internal_style(src_path, pool); 0269 dest_path = svn_dirent_internal_style(dest_path, pool); 0270 // todo svn 1.8: svn_repos_hotcopy2 0271 SVN_ERR(svn_repos_hotcopy(src_path, dest_path, cleanlogs ? 1 : 0, pool)); 0272 return SVN_NO_ERROR; 0273 } 0274 0275 } 0276 0277 }