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 
0032 // svncpp
0033 #include "client_impl.h"
0034 
0035 // subversion api
0036 #include <svn_client.h>
0037 #include <svn_path.h>
0038 
0039 #include "client_parameter.h"
0040 #include "exception.h"
0041 #include "helper.h"
0042 #include "path.h"
0043 #include "pool.h"
0044 #include "revision.h"
0045 #include "svnqt_defines.h"
0046 #include <QCoreApplication>
0047 #include <QDir>
0048 
0049 namespace svn
0050 {
0051 
0052 struct ProplistBaton {
0053     ContextWP m_context;
0054     PathPropertiesMapListPtr resultlist;
0055 };
0056 
0057 static svn_error_t *ProplistReceiver(void *baton, const char *path, apr_hash_t *prop_hash, apr_pool_t *pool)
0058 {
0059     ProplistBaton *_baton = static_cast<ProplistBaton *>(baton);
0060     PathPropertiesMapListPtr mapList = _baton->resultlist;
0061 
0062     ContextP l_context = _baton->m_context;
0063     if (!l_context) {
0064         return svn_error_create(SVN_ERR_CANCELLED, nullptr, QCoreApplication::translate("svnqt", "Cancelled by user.").toUtf8());
0065     }
0066     svn_client_ctx_t *ctx = l_context->ctx();
0067     if (ctx && ctx->cancel_func) {
0068         SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
0069     }
0070 
0071     mapList->push_back(PathPropertiesMapEntry(QString::fromUtf8(path), svn::internal::Hash2Map(prop_hash, pool)));
0072     return SVN_NO_ERROR;
0073 }
0074 
0075 PathPropertiesMapListPtr Client_impl::proplist(const Path &path, const Revision &revision, const Revision &peg, Depth depth, const StringArray &changelists)
0076 {
0077     Pool pool;
0078 
0079     PathPropertiesMapListPtr path_prop_map_list = PathPropertiesMapListPtr(new PathPropertiesMapList);
0080 
0081     ProplistBaton baton;
0082     baton.m_context = m_context;
0083     baton.resultlist = path_prop_map_list;
0084     // todo svn 1.8: svn_client_proplist4
0085     svn_error_t *error = svn_client_proplist3(path.cstr(),
0086                                               peg.revision(),
0087                                               revision.revision(),
0088                                               internal::DepthToSvn(depth),
0089                                               changelists.array(pool),
0090                                               ProplistReceiver,
0091                                               &baton,
0092                                               *m_context,
0093                                               pool);
0094     if (error != nullptr) {
0095         throw ClientException(error);
0096     }
0097 
0098     return path_prop_map_list;
0099 }
0100 
0101 QPair<qlonglong, PathPropertiesMapList>
0102 Client_impl::propget(const QString &propName, const Path &path, const Revision &revision, const Revision &peg, Depth depth, const StringArray &changelists)
0103 {
0104     Pool pool;
0105 
0106     apr_hash_t *props;
0107     svn_revnum_t actual = svn_revnum_t(-1);
0108     // todo svn 1.8: svn_client_propget5
0109     svn_error_t *error = svn_client_propget4(&props,
0110                                              propName.toUtf8(),
0111                                              path.cstr(),
0112                                              peg.revision(),
0113                                              revision.revision(),
0114                                              &actual,
0115                                              internal::DepthToSvn(depth),
0116                                              changelists.array(pool),
0117                                              *m_context,
0118                                              pool,
0119                                              pool);
0120 
0121     if (error != nullptr) {
0122         throw ClientException(error);
0123     }
0124 
0125     PathPropertiesMapList path_prop_map_list;
0126 
0127     apr_hash_index_t *hi;
0128     for (hi = apr_hash_first(pool, props); hi; hi = apr_hash_next(hi)) {
0129         PropertiesMap prop_map;
0130 
0131         const void *key;
0132         void *val;
0133 
0134         apr_hash_this(hi, &key, nullptr, &val);
0135         prop_map[propName] = QString::fromUtf8(((const svn_string_t *)val)->data);
0136         QString filename = QString::fromUtf8((const char *)key);
0137         path_prop_map_list.push_back(PathPropertiesMapEntry(filename, prop_map));
0138     }
0139 
0140     return QPair<qlonglong, PathPropertiesMapList>(actual, path_prop_map_list);
0141 }
0142 
0143 void Client_impl::propset(const PropertiesParameter &params)
0144 {
0145     Pool pool;
0146     const svn_string_t *propval;
0147 
0148     if (params.propertyValue().isNull()) {
0149         propval = nullptr;
0150     } else {
0151         propval = svn_string_create(params.propertyValue().toUtf8(), pool);
0152     }
0153 
0154     svn_error_t *error = nullptr;
0155     const QByteArray tgtTmp = params.path().cstr();
0156     if (svn_path_is_url(tgtTmp)) {
0157         error = svn_client_propset_remote(params.propertyName().toUtf8(),
0158                                           propval,
0159                                           tgtTmp,
0160                                           params.skipCheck(),
0161                                           params.revision(),
0162                                           map2hash(params.revisionProperties(), pool),
0163                                           nullptr, // we don't need a commit info - ignore
0164                                           nullptr,
0165                                           *m_context,
0166                                           pool);
0167     } else {
0168         apr_array_header_t *targets = apr_array_make(pool, 1, sizeof(const char *));
0169         APR_ARRAY_PUSH(targets, const char *) = tgtTmp;
0170         error = svn_client_propset_local(params.propertyName().toUtf8(),
0171                                          propval,
0172                                          targets,
0173                                          internal::DepthToSvn(params.depth()),
0174                                          params.skipCheck(),
0175                                          params.changeList().array(pool),
0176                                          *m_context,
0177                                          pool);
0178     }
0179 
0180     if (error != nullptr) {
0181         throw ClientException(error);
0182     }
0183 }
0184 
0185 //--------------------------------------------------------------------------------
0186 //
0187 //    revprop functions
0188 //
0189 //--------------------------------------------------------------------------------
0190 /**
0191  * lists revision properties in @a path no matter whether local or
0192  * repository
0193  *
0194  * @param path
0195  * @param revision
0196  * @param recurse
0197  * @return PropertiesList
0198  */
0199 QPair<qlonglong, PropertiesMap> Client_impl::revproplist(const Path &path, const Revision &revision)
0200 {
0201     Pool pool;
0202 
0203     apr_hash_t *props;
0204     svn_revnum_t revnum;
0205     svn_error_t *error = svn_client_revprop_list(&props, path.cstr(), revision.revision(), &revnum, *m_context, pool);
0206     if (error != nullptr) {
0207         throw ClientException(error);
0208     }
0209 
0210     PropertiesMap prop_map;
0211 
0212     apr_hash_index_t *hi;
0213     for (hi = apr_hash_first(pool, props); hi; hi = apr_hash_next(hi)) {
0214         const void *key;
0215         void *val;
0216 
0217         apr_hash_this(hi, &key, nullptr, &val);
0218         prop_map[QString::fromUtf8((const char *)key)] = QString::fromUtf8(((const svn_string_t *)val)->data);
0219     }
0220 
0221     return QPair<qlonglong, PropertiesMap>(revnum, prop_map);
0222 }
0223 
0224 /**
0225  * lists one revision property in @a path no matter whether local or
0226  * repository
0227  *
0228  * @param path
0229  * @param revision
0230  * @param recurse
0231  * @return PropertiesList
0232  */
0233 
0234 QPair<qlonglong, QString> Client_impl::revpropget(const QString &propName, const Path &path, const Revision &revision)
0235 {
0236     Pool pool;
0237 
0238     svn_string_t *propval;
0239     svn_revnum_t revnum;
0240     svn_error_t *error = svn_client_revprop_get(propName.toUtf8(), &propval, path.cstr(), revision.revision(), &revnum, *m_context, pool);
0241     if (error != nullptr) {
0242         throw ClientException(error);
0243     }
0244 
0245     // if the property does not exist NULL is returned
0246     if (propval == nullptr) {
0247         return QPair<qlonglong, QString>(0, QString());
0248     }
0249 
0250     return QPair<qlonglong, QString>(revnum, QString::fromUtf8(propval->data));
0251 }
0252 
0253 qlonglong Client_impl::revpropset(const PropertiesParameter &param)
0254 {
0255     Pool pool;
0256 
0257     const svn_string_t *propval = param.propertyValue().isNull() ? nullptr : svn_string_create(param.propertyValue().toUtf8(), pool);
0258 
0259     svn_revnum_t revnum;
0260 
0261     const svn_string_t *oldpropval = param.propertyOriginalValue().isNull() ? nullptr : svn_string_create(param.propertyOriginalValue().toUtf8(), pool);
0262     svn_error_t *error = svn_client_revprop_set2(param.propertyName().toUtf8(),
0263                                                  propval,
0264                                                  oldpropval,
0265                                                  param.path().cstr(),
0266                                                  param.revision().revision(),
0267                                                  &revnum,
0268                                                  param.force(),
0269                                                  *m_context,
0270                                                  pool);
0271 
0272     if (error != nullptr) {
0273         throw ClientException(error);
0274     }
0275 
0276     return revnum;
0277 }
0278 
0279 qlonglong Client_impl::revpropdel(const QString &propName, const Path &path, const Revision &revision)
0280 {
0281     Pool pool;
0282 
0283     svn_revnum_t revnum;
0284     svn_error_t *error = svn_client_revprop_set2(propName.toUtf8(),
0285                                                  nullptr, // value = NULL
0286                                                  nullptr,
0287                                                  path.cstr(),
0288                                                  revision.revision(),
0289                                                  &revnum,
0290                                                  false,
0291                                                  *m_context,
0292                                                  pool);
0293 
0294     if (error != nullptr) {
0295         throw ClientException(error);
0296     }
0297 
0298     return revnum;
0299 }
0300 
0301 }
0302 
0303 /* -----------------------------------------------------------------
0304  * local variables:
0305  * eval: (load-file "../../rapidsvn-dev.el")
0306  * end:
0307  */