File indexing completed on 2024-05-12 17:16:22

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