diff --git a/src/kiosvn/kiosvn.cpp b/src/kiosvn/kiosvn.cpp index b79887d4..3e4bcabd 100644 --- a/src/kiosvn/kiosvn.cpp +++ b/src/kiosvn/kiosvn.cpp @@ -1,1134 +1,1135 @@ /*************************************************************************** * Copyright (C) 2005-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "kiosvn.h" #include "kdesvn-config.h" #include "kiolistener.h" #include #include #include #include "svnqt/svnqttypes.h" #include "svnqt/dirent.h" #include "svnqt/url.h" #include "svnqt/status.h" #include "svnqt/targets.h" #include "svnqt/info_entry.h" #include "svnqt/client_parameter.h" #include "svnqt/client_commit_parameter.h" #include "svnqt/client_update_parameter.h" #include "settings/kdesvnsettings.h" #include "helpers/stringhelper.h" #include "helpers/sshagent.h" #include "helpers/kdesvn_debug.h" #include "kdesvndinterface.h" #include "kio_macros.h" #include #include #include #include #include #include #include namespace KIO { class KioSvnData { public: explicit KioSvnData(kio_svnProtocol *); ~KioSvnData(); void reInitClient(); void resetListener(); KioListener m_Listener; bool first_done; bool dispProgress; bool dispWritten; svn::ContextP m_CurrentContext; svn::ClientP m_Svnclient; svn::Revision urlToRev(const QUrl &); QTime m_last; qulonglong m_Id; }; KioSvnData::KioSvnData(kio_svnProtocol *par) : m_Listener(par) , first_done(false) , dispProgress(false) , dispWritten(false) , m_Svnclient(svn::Client::getobject(svn::ContextP())) , m_last(QTime::currentTime()) , m_Id(0) // null is an invalid id { reInitClient(); } void KioSvnData::reInitClient() { if (first_done) { return; } SshAgent ag; ag.querySshAgent(); first_done = true; m_CurrentContext = svn::ContextP(new svn::Context); m_CurrentContext->setListener(&m_Listener); m_Svnclient->setContext(m_CurrentContext); } void KioSvnData::resetListener() { if (!first_done) { reInitClient(); } m_Listener.uncancel(); } KioSvnData::~KioSvnData() { m_Listener.setCancel(true); /* wait a little bit */ sleep(1); m_CurrentContext->setListener(0L); } svn::Revision KioSvnData::urlToRev(const QUrl &url) { const QList> q = QUrlQuery(url).queryItems(); /* we try to check if it is ssh and try to get a password for it */ const QString proto = url.scheme(); if (proto.contains(QLatin1String("ssh"))) { SshAgent ag; ag.addSshIdentities(); } svn::Revision rev = svn::Revision::UNDEFINED; typedef QPair myStrPair; Q_FOREACH(const myStrPair &p, q) { if (p.first == QLatin1String("rev")) { const QString v = p.second; svn::Revision tmp; m_Svnclient->url2Revision(v, rev, tmp); } } return rev; } kio_svnProtocol::kio_svnProtocol(const QByteArray &pool_socket, const QByteArray &app_socket) : SlaveBase("kio_ksvn", pool_socket, app_socket), StreamWrittenCb() { m_pData = new KioSvnData(this); m_pData->m_Id = reinterpret_cast(this); } kio_svnProtocol::~kio_svnProtocol() { unregisterFromDaemon(); delete m_pData; } } extern "C" { Q_DECL_EXPORT int kdemain(int argc, char **argv); } int kdemain(int argc, char **argv) { QCoreApplication::setApplicationName(QLatin1String("kio_ksvn")); qCDebug(KDESVN_LOG) << "*** Starting kio_ksvn " << endl; if (argc != 4) { qCDebug(KDESVN_LOG) << "Usage: kio_ksvn protocol domain-socket1 domain-socket2" << endl; exit(-1); } KIO::kio_svnProtocol slave(argv[2], argv[3]); slave.dispatchLoop(); qCDebug(KDESVN_LOG) << "*** kio_ksvn Done" << endl; return 0; } namespace KIO { void kio_svnProtocol::listSendDirEntry(const svn::DirEntry &direntry) { const QDateTime dt(direntry.time().toQDateTime()); KIO::UDSEntry entry; if (direntry.name().isEmpty()) { qCDebug(KDESVN_LOG) << "Skipping empty entry!" << endl; return; } if (createUDSEntry(direntry.name(), direntry.lastAuthor(), direntry.size(), direntry.kind() == svn_node_dir ? true : false, dt.toTime_t(), entry)) { listEntry(entry); } } /*! \fn kio_svnProtocol::listDir (const QUrl&url) */ void kio_svnProtocol::listDir(const QUrl &url) { qCDebug(KDESVN_LOG) << "kio_svn::listDir(const QUrl& url) : " << url.url() << endl ; m_pData->resetListener(); svn::DirEntries dlist; svn::Revision rev = m_pData->urlToRev(url); if (rev == svn::Revision::UNDEFINED) { rev = svn::Revision::HEAD; } try { // we ignoring the result 'cause it is done via kiolistener for a smoother insert of items. - dlist = m_pData->m_Svnclient->list(makeSvnUrl(url), rev, rev, svn::DepthImmediates, false); + dlist = m_pData->m_Svnclient->list(makeSvnPath(url), rev, rev, svn::DepthImmediates, false); } catch (const svn::ClientException &e) { QString ex = e.msg(); qCDebug(KDESVN_LOG) << ex << endl; extraError(KIO::ERR_SLAVE_DEFINED, ex); return; } finished(); qCDebug(KDESVN_LOG) << "Listing finished" << endl; } void kio_svnProtocol::stat(const QUrl &url) { qCDebug(KDESVN_LOG) << "kio_svn::stat " << url << endl; m_pData->resetListener(); svn::Revision rev = m_pData->urlToRev(url); if (rev == svn::Revision::UNDEFINED) { rev = svn::Revision::HEAD; } svn::Revision peg = rev; bool dummy = false; svn::InfoEntries e; try { - e = m_pData->m_Svnclient->info(makeSvnUrl(url), svn::DepthEmpty, rev, peg); + e = m_pData->m_Svnclient->info(makeSvnPath(url), svn::DepthEmpty, rev, peg); } catch (const svn::ClientException &e) { QString ex = e.msg(); qCDebug(KDESVN_LOG) << ex << endl; extraError(KIO::ERR_SLAVE_DEFINED, ex); return; } if (e.isEmpty()) { dummy = true; } KIO::UDSEntry entry; if (dummy) { createUDSEntry(url.fileName(), QString(), 0, true, 0, entry); } else { const QDateTime dt(e[0].cmtDate().toQDateTime()); if (e[0].kind() == svn_node_file) { createUDSEntry(url.fileName(), QString(), 0, false, dt.toTime_t(), entry); } else { createUDSEntry(url.fileName(), QString(), 0, true, dt.toTime_t(), entry); } } statEntry(entry); finished(); } void kio_svnProtocol::get(const QUrl &url) { if (m_pData->m_Listener.contextCancel()) { finished(); return; } svn::Revision rev = m_pData->urlToRev(url); if (rev == svn::Revision::UNDEFINED) { rev = svn::Revision::HEAD; } KioByteStream dstream(this, url.fileName()); try { - QUrl _url = makeSvnUrl(url); + const svn::Path path = makeSvnPath(url); svn::InfoEntries e; - e = m_pData->m_Svnclient->info(_url, svn::DepthEmpty, rev, rev); + e = m_pData->m_Svnclient->info(path, svn::DepthEmpty, rev, rev); if (!e.isEmpty()) { totalSize(e.at(0).size()); } - m_pData->m_Svnclient->cat(dstream, _url, rev, rev); + m_pData->m_Svnclient->cat(dstream, path, rev, rev); } catch (const svn::ClientException &e) { QString ex = e.msg(); // dolphin / Konqueror try to get the content without check if it is a folder when listing a folder // which results in a lot of error messages via kio notify if (e.apr_err() != SVN_ERR_CLIENT_IS_DIRECTORY) { extraError(KIO::ERR_SLAVE_DEFINED, QStringLiteral("Subversion error ") + ex); } return; } data(QByteArray()); // empty array means we're done sending the data finished(); } void kio_svnProtocol::mkdir(const QUrl &url, int) { qCDebug(KDESVN_LOG) << "kio_svn::mkdir " << url << endl; m_pData->resetListener(); svn::Revision rev = m_pData->urlToRev(url); if (rev == svn::Revision::UNDEFINED) { rev = svn::Revision::HEAD; } if (rev != svn::Revision::HEAD) { extraError(KIO::ERR_SLAVE_DEFINED, i18n("Can only write on HEAD revision.")); return; } m_pData->m_CurrentContext->setLogMessage(getDefaultLog()); try { - svn::Path p(makeSvnUrl(url)); - m_pData->m_Svnclient->mkdir(p, getDefaultLog()); + m_pData->m_Svnclient->mkdir(makeSvnPath(url), getDefaultLog()); } catch (const svn::ClientException &e) { extraError(KIO::ERR_SLAVE_DEFINED, e.msg()); return; } finished(); } void kio_svnProtocol::mkdir(const QList &urls, int) { try { m_pData->m_Svnclient->mkdir(svn::Targets::fromUrlList(urls), getDefaultLog()); } catch (const svn::ClientException &e) { extraError(KIO::ERR_SLAVE_DEFINED, e.msg()); return; } finished(); } void kio_svnProtocol::rename(const QUrl &src, const QUrl &target, KIO::JobFlags flags) { qCDebug(KDESVN_LOG) << "kio_svn::rename " << src << " to " << target << endl; m_pData->resetListener(); Q_UNUSED(flags); //bool force = flags&KIO::Overwrite; m_pData->m_CurrentContext->setLogMessage(getDefaultLog()); try { - m_pData->m_Svnclient->move(svn::CopyParameter(svn::Path(makeSvnUrl(src)), makeSvnUrl(target))); + m_pData->m_Svnclient->move(svn::CopyParameter(makeSvnPath(src), makeSvnPath(target))); } catch (const svn::ClientException &e) { if (e.apr_err() == SVN_ERR_ENTRY_EXISTS) { error(KIO::ERR_DIR_ALREADY_EXIST, e.msg()); } else { extraError(KIO::ERR_SLAVE_DEFINED, e.msg()); } return; } notify(i18n("Renaming %1 to %2 succesfull", src.toDisplayString(), target.toDisplayString())); finished(); } void kio_svnProtocol::put(const QUrl &url, int permissions, KIO::JobFlags flags) { Q_UNUSED(permissions); m_pData->resetListener(); svn::Revision rev = m_pData->urlToRev(url); if (rev == svn::Revision::UNDEFINED) { rev = svn::Revision::HEAD; } if (rev != svn::Revision::HEAD) { extraError(KIO::ERR_SLAVE_DEFINED, i18n("Can only write on HEAD revision.")); return; } svn::Revision peg = rev; svn::InfoEntries e; bool exists = true; try { - e = m_pData->m_Svnclient->info(makeSvnUrl(url), svn::DepthEmpty, rev, peg); + e = m_pData->m_Svnclient->info(makeSvnPath(url), svn::DepthEmpty, rev, peg); } catch (const svn::ClientException &e) { if (e.apr_err() == SVN_ERR_ENTRY_NOT_FOUND || e.apr_err() == SVN_ERR_RA_ILLEGAL_URL) { exists = false; } else { extraError(KIO::ERR_SLAVE_DEFINED, e.msg()); return; } } QSharedPointer tmpfile; QSharedPointer _codir; if (exists) { if (flags & KIO::Overwrite) { if (!supportOverwrite()) { extraError(KIO::ERR_SLAVE_DEFINED, i18n("Overwriting existing items is disabled in settings.")); return; } _codir = QSharedPointer(new QTemporaryDir); _codir->setAutoRemove(true); - svn::Path path = makeSvnUrl(url); + svn::Path path = makeSvnPath(url); path.removeLast(); try { notify(i18n("Start checking out to temporary folder")); m_pData->dispWritten = true; registerToDaemon(); startOp(-1, i18n("Checking out %1", path.native())); svn::CheckoutParameter params; params.moduleName(path).destination(svn::Path(_codir->path())).revision(rev).peg(peg).depth(svn::DepthFiles); m_pData->m_Svnclient->checkout(params); } catch (const svn::ClientException &e) { extraError(KIO::ERR_SLAVE_DEFINED, e.msg()); return; } m_pData->dispWritten = false; stopOp(i18n("Temporary checkout done.")); tmpfile = QSharedPointer(new QFile(_codir->path() + url.fileName())); tmpfile->open(QIODevice::ReadWrite | QIODevice::Truncate); } else { extraError(KIO::ERR_FILE_ALREADY_EXIST, i18n("Could not write to existing item.")); return; } } else { QTemporaryFile *_tmpfile = new QTemporaryFile(); if (!_tmpfile->open()) { extraError(KIO::ERR_SLAVE_DEFINED, i18n("Could not open temporary file")); delete _tmpfile; return; } tmpfile = QSharedPointer(_tmpfile); } int result = 0; QByteArray buffer; KIO::fileoffset_t processed_size = 0; do { dataReq(); result = readData(buffer); if (result > 0) { tmpfile->write(buffer); processed_size += result; processedSize(processed_size); } buffer.clear(); } while (result > 0); tmpfile->flush(); if (result != 0) { error(KIO::ERR_ABORTED, i18n("Could not retrieve data for write.")); return; } totalSize(processed_size); written(0); m_pData->dispWritten = true; registerToDaemon(); - startOp(processed_size, i18n("Committing %1", makeSvnUrl(url).toDisplayString())); + startOp(processed_size, i18n("Committing %1", makeSvnPath(url).path())); bool err = false; if (exists) { svn::CommitParameter commit_parameters; commit_parameters.targets(svn::Targets(tmpfile->fileName())).message(getDefaultLog()).depth(svn::DepthEmpty).keepLocks(false); try { m_pData->m_Svnclient->commit(commit_parameters); } catch (const svn::ClientException &e) { extraError(KIO::ERR_SLAVE_DEFINED, e.msg()); err = true; } } else { try { - m_pData->m_Svnclient->import(tmpfile->fileName(), svn::Url(makeSvnUrl(url)), getDefaultLog(), svn::DepthEmpty, false, false); + m_pData->m_Svnclient->import(tmpfile->fileName(), svn::Url(makeSvnPath(url)), getDefaultLog(), svn::DepthEmpty, false, false); } catch (const svn::ClientException &e) { QString ex = e.msg(); extraError(KIO::ERR_SLAVE_DEFINED, e.msg()); err = true; stopOp(ex); } } m_pData->dispWritten = false; if (!err) { stopOp(i18n("Wrote %1 to repository", helpers::ByteToString(processed_size))); finished(); } } void kio_svnProtocol::copy(const QUrl &src, const QUrl &dest, int permissions, KIO::JobFlags flags) { Q_UNUSED(permissions); Q_UNUSED(flags); //bool force = flags&KIO::Overwrite; m_pData->resetListener(); qCDebug(KDESVN_LOG) << "kio_svn::copy " << src << " to " << dest << endl; svn::Revision rev = m_pData->urlToRev(src); if (rev == svn::Revision::UNDEFINED) { rev = svn::Revision::HEAD; } m_pData->dispProgress = true; m_pData->m_CurrentContext->setLogMessage(getDefaultLog()); try { - m_pData->m_Svnclient->copy(makeSvnUrl(src), rev, makeSvnUrl(dest)); + m_pData->m_Svnclient->copy(makeSvnPath(src), rev, makeSvnPath(dest)); } catch (const svn::ClientException &e) { if (e.apr_err() == SVN_ERR_ENTRY_EXISTS) { error(KIO::ERR_DIR_ALREADY_EXIST, e.msg()); } else { extraError(KIO::ERR_SLAVE_DEFINED, e.msg()); } qCDebug(KDESVN_LOG) << "kio_svn::copy aborted" << endl; return; } m_pData->dispProgress = false; qCDebug(KDESVN_LOG) << "kio_svn::copy finished" << endl; - notify(i18n("Copied %1 to %2", makeSvnUrl(src).toDisplayString(), makeSvnUrl(dest).toDisplayString())); + notify(i18n("Copied %1 to %2", makeSvnPath(src).path(), makeSvnPath(dest).path())); finished(); } void kio_svnProtocol::del(const QUrl &src, bool isfile) { Q_UNUSED(isfile); m_pData->resetListener(); qCDebug(KDESVN_LOG) << "kio_svn::del " << src << endl; //m_pData->reInitClient(); svn::Revision rev = m_pData->urlToRev(src); if (rev == svn::Revision::UNDEFINED) { rev = svn::Revision::HEAD; } if (rev != svn::Revision::HEAD) { extraError(KIO::ERR_SLAVE_DEFINED, i18n("Can only write on HEAD revision.")); return; } m_pData->m_CurrentContext->setLogMessage(getDefaultLog()); try { - svn::Targets target(makeSvnUrl(src)); + svn::Targets target(makeSvnPath(src)); m_pData->m_Svnclient->remove(target, false); } catch (const svn::ClientException &e) { extraError(KIO::ERR_SLAVE_DEFINED, e.msg()); qCDebug(KDESVN_LOG) << "kio_svn::del aborted" << endl; return; } qCDebug(KDESVN_LOG) << "kio_svn::del finished" << endl; finished(); } bool kio_svnProtocol::getLogMsg(QString &t) { svn::CommitItemList _items; return m_pData->m_Listener.contextGetLogMessage(t, _items); } -bool kio_svnProtocol::checkWc(const QUrl &url) const +bool kio_svnProtocol::checkWc(const svn::Path &localPath) const { m_pData->resetListener(); - if (url.isEmpty() || !url.isLocalFile()) { + if (!localPath.isSet()) { return false; } svn::Revision peg(svn_opt_revision_unspecified); svn::Revision rev(svn_opt_revision_unspecified); svn::InfoEntries e; try { - e = m_pData->m_Svnclient->info(svn::Path(url), svn::DepthEmpty, rev, peg); + e = m_pData->m_Svnclient->info(localPath, svn::DepthEmpty, rev, peg); } catch (const svn::ClientException &e) { if (SVN_ERR_WC_NOT_DIRECTORY == e.apr_err()) { return false; } return true; } return false; } -QUrl kio_svnProtocol::makeSvnUrl(const QUrl &url, bool check_Wc) const +svn::Path kio_svnProtocol::makeSvnPath(const QUrl &url) const { const QString scheme = svn::Url::transformProtokoll(url.scheme()); - if (scheme == QLatin1String("file") && check_Wc) { - if (checkWc(url)) { - return url; + if (scheme == QLatin1String("file")) { + const svn::Path path(url.toLocalFile()); + if (checkWc(path)) { + return path; } } + if (url.path().isEmpty()) { + throw svn::ClientException(QLatin1Char('\'') + url.url() + QLatin1String("' is not a valid subversion url")); + } + QUrl tmpUrl(url); tmpUrl.setScheme(scheme); tmpUrl.setQuery(QString()); // svn doesn't know anything about queries (e.g ?rev=X) - if (url.path().isEmpty()) { - throw svn::ClientException(QLatin1Char('\'') + url.url() + QLatin1String("' is not a valid subversion url")); - } - return tmpUrl; + return svn::Path(tmpUrl.toString(QUrl::NormalizePathSegments)); } bool kio_svnProtocol::createUDSEntry(const QString &filename, const QString &user, long long int size, bool isdir, time_t mtime, KIO::UDSEntry &entry) { entry.insert(KIO::UDSEntry::UDS_NAME, filename); entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, isdir ? S_IFDIR : S_IFREG); entry.insert(KIO::UDSEntry::UDS_SIZE, size); entry.insert(KIO::UDSEntry::UDS_MODIFICATION_TIME, mtime); entry.insert(KIO::UDSEntry::UDS_USER, user); return true; } void kio_svnProtocol::special(const QByteArray &data) { qCDebug(KDESVN_LOG) << "kio_svnProtocol::special" << endl; QByteArray tmpData(data); QDataStream stream(&tmpData, QIODevice::ReadOnly); m_pData->resetListener(); int tmp; stream >> tmp; qCDebug(KDESVN_LOG) << "kio_svnProtocol::special " << tmp << endl; switch (tmp) { case SVN_CHECKOUT: { QUrl repository, wc; int revnumber; QString revkind; stream >> repository; stream >> wc; stream >> revnumber; stream >> revkind; qCDebug(KDESVN_LOG) << "kio_svnProtocol CHECKOUT from " << repository.url() << " to " << wc.url() << " at " << revnumber << " or " << revkind << endl; checkout(repository, wc, revnumber, revkind); break; } case SVN_UPDATE: { QUrl wc; int revnumber; QString revkind; stream >> wc; stream >> revnumber; stream >> revkind; qCDebug(KDESVN_LOG) << "kio_svnProtocol UPDATE " << wc.url() << " at " << revnumber << " or " << revkind << endl; update(wc, revnumber, revkind); break; } case SVN_COMMIT: { QList wclist; while (!stream.atEnd()) { QUrl tmp; stream >> tmp; wclist << tmp; } qCDebug(KDESVN_LOG) << "kio_svnProtocol COMMIT" << endl; commit(wclist); break; } case SVN_LOG: { qCDebug(KDESVN_LOG) << "kio_svnProtocol LOG" << endl; int revstart, revend; QString revkindstart, revkindend; QList targets; stream >> revstart; stream >> revkindstart; stream >> revend; stream >> revkindend; while (!stream.atEnd()) { QUrl tmp; stream >> tmp; targets << tmp; } svnlog(revstart, revkindstart, revend, revkindend, targets); break; } case SVN_IMPORT: { QUrl wc, repos; stream >> repos; stream >> wc; qCDebug(KDESVN_LOG) << "kio_ksvnProtocol IMPORT" << endl; import(repos, wc); break; } case SVN_ADD: { QUrl wc; qCDebug(KDESVN_LOG) << "kio_ksvnProtocol ADD" << endl; stream >> wc; add(wc); break; } case SVN_DEL: { QList wclist; while (!stream.atEnd()) { QUrl tmp; stream >> tmp; wclist << tmp; } wc_delete(wclist); break; } case SVN_REVERT: { QList wclist; while (!stream.atEnd()) { QUrl tmp; stream >> tmp; wclist << tmp; } qCDebug(KDESVN_LOG) << "kio_svnProtocol REVERT" << endl; revert(wclist); break; } case SVN_STATUS: { QUrl wc; bool checkRepos = false; bool fullRecurse = false; stream >> wc; stream >> checkRepos; stream >> fullRecurse; qCDebug(KDESVN_LOG) << "kio_svnProtocol STATUS" << endl; status(wc, checkRepos, fullRecurse); break; } case SVN_MKDIR: { QList list; stream >> list; qCDebug(KDESVN_LOG) << "kio_svnProtocol MKDIR" << endl; this->mkdir(list, 0); break; } case SVN_RESOLVE: { QUrl url; bool recurse; stream >> url; stream >> recurse; qCDebug(KDESVN_LOG) << "kio_svnProtocol RESOLVE" << endl; wc_resolve(url, recurse); break; } case SVN_SWITCH: { QUrl wc, url; bool recurse; int revnumber; QString revkind; stream >> wc; stream >> url; stream >> recurse; stream >> revnumber; stream >> revkind; qCDebug(KDESVN_LOG) << "kio_svnProtocol SWITCH" << endl; wc_switch(wc, url, recurse, revnumber, revkind); break; } case SVN_DIFF: { QUrl url1, url2; int rev1, rev2; bool recurse; QString revkind1, revkind2; stream >> url1; stream >> url2; stream >> rev1; stream >> revkind1; stream >> rev2; stream >> revkind2; stream >> recurse; diff(url1, url2, rev1, revkind1, rev2, revkind2, recurse); break; } default: { qCDebug(KDESVN_LOG) << "Unknown special" << endl; } } finished(); } void kio_svnProtocol::update(const QUrl &url, int revnumber, const QString &revkind) { svn::Revision where(revnumber, revkind); m_pData->resetListener(); /* update is always local - so make a path instead URI */ svn::Path p(url.path()); try { svn::Targets pathes(p.path()); // always update externals, too. (third last parameter) // no unversioned items allowed (second last parameter) // sticky depth (last parameter) svn::UpdateParameter _params; _params.targets(p.path()).revision(revnumber).depth(svn::DepthInfinity).ignore_externals(false).allow_unversioned(false).sticky_depth(true); m_pData->m_Svnclient->update(_params); } catch (const svn::ClientException &e) { extraError(KIO::ERR_SLAVE_DEFINED, e.msg()); } } void kio_svnProtocol::status(const QUrl &wc, bool cR, bool rec) { svn::StatusEntries dlist; svn::StatusParameter params(wc.path()); m_pData->resetListener(); try { dlist = m_pData->m_Svnclient->status(params.depth(rec ? svn::DepthInfinity : svn::DepthEmpty).all(false).update(cR).noIgnore(false).revision(svn::Revision::UNDEFINED)); } catch (const svn::ClientException &e) { extraError(KIO::ERR_SLAVE_DEFINED, e.msg()); return; } qCDebug(KDESVN_LOG) << "Status got " << dlist.count() << " entries." << endl; Q_FOREACH (const svn::StatusPtr &s, dlist) { if (!s) { continue; } const QString cntStr(QString::number(m_pData->m_Listener.counter()).rightJustified(10, QLatin1Char('0'))); //QDataStream stream(params, QIODevice::WriteOnly); setMetaData(cntStr + QLatin1String("path"), s->path()); setMetaData(cntStr + QLatin1String("node"), QString::number(s->nodeStatus())); setMetaData(cntStr + QLatin1String("text"), QString::number(s->textStatus())); setMetaData(cntStr + QLatin1String("prop"), QString::number(s->propStatus())); setMetaData(cntStr + QLatin1String("reptxt"), QString::number(s->reposTextStatus())); setMetaData(cntStr + QLatin1String("repprop"), QString::number(s->reposPropStatus())); setMetaData(cntStr + QLatin1String("rev"), QString::number(s->entry().cmtRev())); m_pData->m_Listener.incCounter(); } } void kio_svnProtocol::commit(const QList &urls) { /// @todo replace with direct call to kdesvn? QString msg; CON_DBUS; QDBusReply res = kdesvndInterface.get_logmsg(); if (!res.isValid()) { qWarning() << "Unexpected reply type"; return; } QStringList lt = res; if (lt.count() != 1) { msg = i18n("Wrong or missing log (may cancel pressed)."); qCDebug(KDESVN_LOG) << msg << endl; return; } msg = lt[0]; svn::Revision nnum = svn::Revision::UNDEFINED; svn::CommitParameter commit_parameters; commit_parameters.targets(svn::Targets::fromUrlList(urls)).message(msg).depth(svn::DepthInfinity).keepLocks(false); try { nnum = m_pData->m_Svnclient->commit(commit_parameters); } catch (const svn::ClientException &e) { extraError(KIO::ERR_SLAVE_DEFINED, e.msg()); } for (long j = 0; j < urls.count(); ++j) { QString userstring; if (nnum != svn::Revision::UNDEFINED) { userstring = i18n("Committed revision %1.", nnum.toString()); } else { userstring = i18n("Nothing to commit."); } const QString num(QString::number(m_pData->m_Listener.counter()).rightJustified(10, QLatin1Char('0'))); const QString zero(QStringLiteral("0")); setMetaData(num + QLatin1String("path"), urls[j].path()); setMetaData(num + QLatin1String("action"), zero); setMetaData(num + QLatin1String("kind"), zero); setMetaData(num + QLatin1String("mime_t"), QString()); setMetaData(num + QLatin1String("content"), zero); setMetaData(num + QLatin1String("prop"), zero); setMetaData(num + QLatin1String("rev") , QString::number(nnum)); setMetaData(num + QLatin1String("string"), userstring); m_pData->m_Listener.incCounter(); } } void kio_svnProtocol::checkout(const QUrl &src, const QUrl &target, const int rev, const QString &revstring) { svn::Revision where(rev, revstring); try { svn::CheckoutParameter params; - params.moduleName(makeSvnUrl(src)).destination(target.path()).revision(where).peg(svn::Revision::UNDEFINED).depth(svn::DepthInfinity); + params.moduleName(makeSvnPath(src)).destination(target.path()).revision(where).peg(svn::Revision::UNDEFINED).depth(svn::DepthInfinity); m_pData->m_Svnclient->checkout(params); } catch (const svn::ClientException &e) { extraError(KIO::ERR_SLAVE_DEFINED, e.msg()); } } void kio_svnProtocol::svnlog(int revstart, const QString &revstringstart, int revend, const QString &revstringend, const QList &urls) { svn::Revision start(revstart, revstringstart); svn::Revision end(revend, revstringend); svn::LogParameter params; params.revisionRange(start, end).peg(svn::Revision::UNDEFINED).limit(0).discoverChangedPathes(true).strictNodeHistory(true); for (long j = 0; j < urls.count(); ++j) { svn::LogEntriesMap logs; try { - m_pData->m_Svnclient->log(params.targets(svn::Path(makeSvnUrl(urls[j]))), logs); + m_pData->m_Svnclient->log(params.targets(makeSvnPath(urls[j])), logs); } catch (const svn::ClientException &e) { extraError(KIO::ERR_SLAVE_DEFINED, e.msg()); break; } if (logs.isEmpty()) { const QString num(QString::number(m_pData->m_Listener.counter()).rightJustified(10, QLatin1Char('0'))); setMetaData(num + QStringLiteral("path"), urls[j].path()); setMetaData(num + QStringLiteral("string"), i18n("Empty logs")); m_pData->m_Listener.incCounter(); continue; } svn::LogEntriesMap::const_iterator it = logs.constBegin(); for (; it != logs.constEnd(); ++it) { const QString num(QString::number(m_pData->m_Listener.counter()).rightJustified(10, QLatin1Char('0'))); setMetaData(num + QStringLiteral("path"), urls[j].path()); setMetaData(num + QStringLiteral("rev"), QString::number((*it).revision)); setMetaData(num + QStringLiteral("author"), (*it).author); setMetaData(num + QStringLiteral("logmessage"), (*it).message); m_pData->m_Listener.incCounter(); for (long z = 0; z < (*it).changedPaths.count(); ++z) { const QString num(QString::number(m_pData->m_Listener.counter()).rightJustified(10, QLatin1Char('0'))); setMetaData(num + QStringLiteral("rev"), QString::number((*it).revision)); setMetaData(num + QStringLiteral("path"), urls[j].path()); setMetaData(num + QStringLiteral("loggedpath"), (*it).changedPaths[z].path); setMetaData(num + QStringLiteral("loggedaction"), QString(QLatin1Char((*it).changedPaths[z].action))); setMetaData(num + QStringLiteral("loggedcopyfrompath"), (*it).changedPaths[z].copyFromPath); setMetaData(num + QStringLiteral("loggedcopyfromrevision"), QString::number((*it).changedPaths[z].copyFromRevision)); m_pData->m_Listener.incCounter(); } } } } void kio_svnProtocol::revert(const QList &urls) { try { m_pData->m_Svnclient->revert(svn::Targets::fromUrlList(urls), svn::DepthEmpty); } catch (const svn::ClientException &e) { extraError(KIO::ERR_SLAVE_DEFINED, e.msg()); } } void kio_svnProtocol::wc_switch(const QUrl &wc, const QUrl &target, bool rec, int rev, const QString &revstring) { svn::Revision where(rev, revstring); svn::Path wc_path(wc.path()); try { - m_pData->m_Svnclient->doSwitch(wc_path, svn::Url(makeSvnUrl(target)), where, rec ? svn::DepthInfinity : svn::DepthFiles); + m_pData->m_Svnclient->doSwitch(wc_path, svn::Url(makeSvnPath(target)), where, rec ? svn::DepthInfinity : svn::DepthFiles); } catch (const svn::ClientException &e) { extraError(KIO::ERR_SLAVE_DEFINED, e.msg()); } } void kio_svnProtocol::diff(const QUrl &uri1, const QUrl &uri2, int rnum1, const QString &rstring1, int rnum2, const QString &rstring2, bool rec) { QByteArray ex; /// @todo read settings for diff (ignore contentype) try { const svn::Revision r1(rnum1, rstring1); const svn::Revision r2(rnum2, rstring2); - const QUrl u1 = makeSvnUrl(uri1, true); - const QUrl u2 = makeSvnUrl(uri2, true); + const svn::Path u1 = makeSvnPath(uri1); + const svn::Path u2 = makeSvnPath(uri2); QTemporaryDir tdir; - qCDebug(KDESVN_LOG) << "kio_ksvn::diff : " << u1 << " at revision " << r1.toString() << " with " - << u2 << " at revision " << r2.toString() - << endl ; + qCDebug(KDESVN_LOG) << "kio_ksvn::diff : " << u1.path() << " at revision " << r1.toString() << " with " + << u2.path() << " at revision " << r2.toString() + << endl ; svn::DiffParameter _opts; // no peg revision required _opts.path1(u1).path2(u2).tmpPath(tdir.path()). rev1(r1).rev2(r2). ignoreContentType(false).extra(svn::StringArray()).depth(rec ? svn::DepthInfinity : svn::DepthEmpty).ignoreAncestry(false).noDiffDeleted(false). - relativeTo(svn::Path((u1 == u2 ? u1 : QUrl()))).changeList(svn::StringArray()); + relativeTo((u1.path() == u2.path() ? u1 : svn::Path())).changeList(svn::StringArray()); tdir.setAutoRemove(true); ex = m_pData->m_Svnclient->diff(_opts); } catch (const svn::ClientException &e) { extraError(KIO::ERR_SLAVE_DEFINED, e.msg()); return; } QString out = QString::fromUtf8(ex); const QString num(QString::number(m_pData->m_Listener.counter()).rightJustified(10, QLatin1Char('0'))); QTextStream stream(&out); while (!stream.atEnd()) { setMetaData(num + QStringLiteral("diffresult"), stream.readLine()); m_pData->m_Listener.incCounter(); } } void kio_svnProtocol::import(const QUrl &repos, const QUrl &wc) { try { - const QUrl target = makeSvnUrl(repos); + const svn::Path target = makeSvnPath(repos); const QString path = wc.path(); - m_pData->m_Svnclient->import(svn::Path(path), svn::Url(target), QString(), svn::DepthInfinity, false, false); + m_pData->m_Svnclient->import(path, svn::Url(target), QString(), svn::DepthInfinity, false, false); } catch (const svn::ClientException &e) { extraError(KIO::ERR_SLAVE_DEFINED, e.msg()); return; } finished(); } void kio_svnProtocol::add(const QUrl &wc) { QString path = wc.path(); try { /* rec */ m_pData->m_Svnclient->add(svn::Path(path), svn::DepthInfinity); } catch (const svn::ClientException &e) { extraError(KIO::ERR_SLAVE_DEFINED, e.msg()); return; } finished(); } void kio_svnProtocol::wc_delete(const QList &urls) { try { m_pData->m_Svnclient->remove(svn::Targets::fromUrlList(urls), false); } catch (const svn::ClientException &e) { extraError(KIO::ERR_SLAVE_DEFINED, e.msg()); return; } finished(); } void kio_svnProtocol::wc_resolve(const QUrl &url, bool recurse) { try { svn::Depth depth = recurse ? svn::DepthInfinity : svn::DepthEmpty; m_pData->m_Svnclient->resolve(url.path(), depth); } catch (const svn::ClientException &e) { extraError(KIO::ERR_SLAVE_DEFINED, e.msg()); return; } finished(); } void kio_svnProtocol::streamWritten(const KIO::filesize_t current) { processedSize(current); } void kio_svnProtocol::streamSendMime(const QMimeType &mt) { if (mt.isValid()) { mimeType(mt.name()); } } void kio_svnProtocol::streamPushData(const QByteArray &streamData) { data(streamData); } void kio_svnProtocol::contextProgress(long long int current, long long int max) { if (max > -1) { totalSize(KIO::filesize_t(max)); } bool to_dbus = false; if (m_pData->dispProgress || m_pData->dispWritten || max > -1) { QTime now = QTime::currentTime(); if (m_pData->m_last.msecsTo(now) >= 90) { if (m_pData->dispProgress) { processedSize(KIO::filesize_t(current)); } else { written(current); to_dbus = useKioprogress(); } m_pData->m_last = now; } } if (to_dbus) { CON_DBUS; if (max > -1) { kdesvndInterface.maxTransferKioOperation(m_pData->m_Id, max); } kdesvndInterface.transferredKioOperation(m_pData->m_Id, current); } } bool kio_svnProtocol::supportOverwrite()const { Kdesvnsettings::self()->load(); return Kdesvnsettings::kio_can_overwrite(); } bool kio_svnProtocol::useKioprogress()const { Kdesvnsettings::self()->load(); return Kdesvnsettings::display_dockmsg(); } /*! \fn kio_svnProtocol::getDefaultLog() */ QString kio_svnProtocol::getDefaultLog() { QString res; Kdesvnsettings::self()->load(); if (Kdesvnsettings::kio_use_standard_logmsg()) { res = Kdesvnsettings::kio_standard_logmsg(); } return res; } void kio_svnProtocol::notify(const QString &text) { if (!useKioprogress()) { return; } CON_DBUS; kdesvndInterface.notifyKioOperation(text); } void kio_svnProtocol::extraError(int _errid, const QString &text) { error(_errid, text); if (!text.isNull()) { CON_DBUS; kdesvndInterface.errorKioOperation(text); } } void kio_svnProtocol::registerToDaemon() { if (!useKioprogress()) { return; } CON_DBUS; kdesvndInterface.registerKioFeedback(m_pData->m_Id); } void kio_svnProtocol::unregisterFromDaemon() { CON_DBUS; kdesvndInterface.unRegisterKioFeedback(m_pData->m_Id); } bool kio_svnProtocol::checkKioCancel()const { if (!useKioprogress()) { return false; } CON_DBUS_VAL(false); QDBusReply res = kdesvndInterface.canceldKioOperation(m_pData->m_Id); return res.isValid() ? res.value() : false; } void kio_svnProtocol::startOp(qulonglong max, const QString &title) { if (!useKioprogress()) { return; } CON_DBUS; kdesvndInterface.maxTransferKioOperation(m_pData->m_Id, max); kdesvndInterface.titleKioOperation(m_pData->m_Id, title, title); kdesvndInterface.setKioStatus(m_pData->m_Id, 1, QString()); } void kio_svnProtocol::stopOp(const QString &message) { if (!useKioprogress()) { return; } CON_DBUS; kdesvndInterface.setKioStatus(m_pData->m_Id, 0, message); unregisterFromDaemon(); } } // namespace KIO diff --git a/src/kiosvn/kiosvn.h b/src/kiosvn/kiosvn.h index e2f88bb6..e293e407 100644 --- a/src/kiosvn/kiosvn.h +++ b/src/kiosvn/kiosvn.h @@ -1,135 +1,136 @@ /*************************************************************************** * Copyright (C) 2005-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef KIOSVN_H #define KIOSVN_H #include "kiobytestream.h" #include #include #include #include namespace svn { class DirEntry; +class Path; } namespace KIO { class KioSvnData; /** @author Rajko Albrecht */ class kio_svnProtocol : public KIO::SlaveBase, public StreamWrittenCb { public: kio_svnProtocol(const QByteArray &pool_socket, const QByteArray &app_socket); virtual ~kio_svnProtocol(); // KIO::SlaveBase virtual void listDir(const QUrl &url) override; virtual void stat(const QUrl &url) override; virtual void get(const QUrl &url) override; virtual void mkdir(const QUrl &url, int permissions) override; virtual void put(const QUrl &url, int permissions, KIO::JobFlags flags) override; virtual void rename(const QUrl &src, const QUrl &target, KIO::JobFlags flags) override; virtual void del(const QUrl &url, bool isfile) override; virtual void copy(const QUrl &src, const QUrl &dest, int permissions, KIO::JobFlags flags) override; virtual void special(const QByteArray &data) override; // StreamWrittenCb virtual void streamWritten(const KIO::filesize_t current) override; virtual void streamPushData(const QByteArray &streamData) override; virtual void streamSendMime(const QMimeType &mt) override; void contextProgress(long long int current, long long int max); void listSendDirEntry(const svn::DirEntry &); bool checkKioCancel()const; protected: void checkout(const QUrl &src, const QUrl &target, const int rev, const QString &revstring); void update(const QUrl &url, int revnumber, const QString &revkind); void commit(const QList &urls); void svnlog(int revstart, const QString &revstringstart, int revend, const QString &revstringend, const QList &urls); void import(const QUrl &repos, const QUrl &wc); void add(const QUrl &wc); void wc_delete(const QList &urls); void revert(const QList &urls); void status(const QUrl &wc, bool cR, bool rec); void mkdir(const QList &urls, int permissions); void wc_resolve(const QUrl &url, bool recurse); void wc_switch(const QUrl &wc, const QUrl &target, bool rec, int rev, const QString &revstring); void diff(const QUrl &uri1, const QUrl &uri2, int rnum1, const QString &rstring1, int rnum2, const QString &rstring2, bool rec); /* looked on kio::svn from kdesdk */ enum KSVN_METHOD { /* QUrl repository, QUrl target, int revnumber, QString revkind */ SVN_CHECKOUT = 1, /* QUrl wc, int revnumber, QString revkind */ /* refkind may empty or HEAD or START, will get parsed if revnumber is -1 */ SVN_UPDATE = 2, /* QList */ SVN_COMMIT = 3, /* int revstart, QString revstartstring, int revend, QString revendstring, QList */ SVN_LOG = 4, SVN_IMPORT = 5, /* QUrl */ SVN_ADD = 6, /* QList */ SVN_DEL = 7, /* QList */ SVN_REVERT = 8, /* QUrl wc,bool checkRepos, bool recurse */ SVN_STATUS = 9, /* QList */ SVN_MKDIR = 10, /* QUrl, bool */ SVN_RESOLVE = 11, /* QUrl working copy, QUrl new_repository_url, bool recurse, int rev, QString revstring */ SVN_SWITCH = 12, /* QUrl uri1, QUrl uri2, int r1, QString rstring1, int r2, QString rstring 2, bool recursive */ SVN_DIFF = 13 }; void notify(const QString &text); void extraError(int _errid, const QString &text); private: KioSvnData *m_pData; static bool createUDSEntry(const QString &filename, const QString &user, long long int size, bool isdir, time_t mtime, KIO::UDSEntry &entry); - QUrl makeSvnUrl(const QUrl &url, bool check_wc = true) const; - bool checkWc(const QUrl &url) const; + svn::Path makeSvnPath(const QUrl &url) const; + bool checkWc(const svn::Path &localPath) const; bool getLogMsg(QString &); void registerToDaemon(); void unregisterFromDaemon(); void startOp(qulonglong max, const QString &title); void stopOp(const QString &message); protected: QString getDefaultLog(); bool supportOverwrite()const; bool useKioprogress()const; }; } #endif diff --git a/src/svnqt/path.cpp b/src/svnqt/path.cpp index 2c039f54..f5eedf32 100644 --- a/src/svnqt/path.cpp +++ b/src/svnqt/path.cpp @@ -1,196 +1,191 @@ /* * Port for usage with qt-framework and development for kdesvn * Copyright (C) 2005-2009 by Rajko Albrecht (ral@alwins-world.de) * http://kdesvn.alwins-world.de */ /* * ==================================================================== * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. * dev@rapidsvn.tigris.org * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library (in the file LGPL.txt); if not, * write to the Free Software Foundation, Inc., 51 Franklin St, * Fifth Floor, Boston, MA 02110-1301 USA * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://rapidsvn.tigris.org/. * ==================================================================== */ #include "path.h" #include "helper.h" // subversion api #include #include // apr api #include // svncpp #include "pool.h" #include "url.h" #include "svnqt_defines.h" #include "revision.h" #include "exception.h" #include #include namespace svn { Path::Path(const QString &path) { init(path); } -Path::Path(const QUrl &path) -{ - init(path.toString()); -} - void Path::init(const QString &path) { Pool pool; if (path.isEmpty()) { m_path.clear(); } else { QByteArray int_path = path.toUtf8(); if (Url::isValid(path)) { if (!svn_path_is_uri_safe(int_path)) { int_path = svn_path_uri_encode(int_path, pool); } } else { int_path = svn_dirent_internal_style(int_path, pool.pool()); } m_path = QString::fromUtf8(int_path); while (m_path.endsWith(QLatin1Char('/')) && m_path.size() > 1) { m_path.chop(1); } } } bool Path::isUrl()const { return Url::isValid(m_path); } const QString & Path::path() const { return m_path; } const QByteArray Path::cstr() const { return m_path.toUtf8(); } Path & Path::operator=(const Path &path) { if (this == &path) { return *this; } m_path = path.path(); return *this; } bool Path::isSet() const { return !m_path.isEmpty(); } void Path::addComponent(const QString &_component) { Pool pool; QString component = _component; while (component.endsWith(QLatin1Char('/'))) { component.chop(1); } if (Url::isValid(m_path)) { const char *newPath = svn_path_url_add_component2(m_path.toUtf8(), component.toUtf8(), pool); m_path = QString::fromUtf8(newPath); } else { svn_stringbuf_t *pathStringbuf = svn_stringbuf_create(m_path.toUtf8(), pool); svn_path_add_component(pathStringbuf, component.toUtf8()); m_path = QString::fromUtf8(pathStringbuf->data); } } void Path::removeLast() { Pool pool; if (m_path.length() <= 1) { m_path.clear(); } svn_stringbuf_t *pathStringbuf = svn_stringbuf_create(m_path.toUtf8(), pool); svn_path_remove_component(pathStringbuf); m_path = QString::fromUtf8(pathStringbuf->data); } void Path::parsePeg(const QString &pathorurl, Path &_path, svn::Revision &_peg) { const QByteArray _buf = pathorurl.toUtf8(); const char *truepath = 0; svn_opt_revision_t pegr; Pool pool; svn_error_t *error = svn_opt_parse_path(&pegr, &truepath, _buf, pool); if (error != 0) { throw ClientException(error); } //qDebug("Path: %s",truepath); _peg = svn::Revision(&pegr); _path = Path(QString::fromUtf8(truepath)); } unsigned int Path::length() const { return m_path.length(); } QString Path::native() const { if (isUrl()) { return m_path; } Pool pool; return QString::fromUtf8(svn_dirent_local_style(m_path.toUtf8(), pool)); } } /* ----------------------------------------------------------------- * local variables: * eval: (load-file "../../rapidsvn-dev.el") * end: */ diff --git a/src/svnqt/path.h b/src/svnqt/path.h index ddce1348..6e29b523 100644 --- a/src/svnqt/path.h +++ b/src/svnqt/path.h @@ -1,136 +1,134 @@ /* * Port for usage with qt-framework and development for kdesvn * Copyright (C) 2005-2009 by Rajko Albrecht (ral@alwins-world.de) * http://kdesvn.alwins-world.de */ /* * ==================================================================== * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. * dev@rapidsvn.tigris.org * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library (in the file LGPL.txt); if not, * write to the Free Software Foundation, Inc., 51 Franklin St, * Fifth Floor, Boston, MA 02110-1301 USA * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://rapidsvn.tigris.org/. * ==================================================================== */ #ifndef SVNQT_PATH_H #define SVNQT_PATH_H -#include #include #include #include namespace svn { /** * Encapsulation for Subversion Path handling */ class SVNQT_EXPORT Path { private: QString m_path; /** * initialize the class * * @param path Path string - when url this should NOT hold revision as @ parameter!!!!! (will filtered out) */ void init(const QString &path); public: /** * Constructor that takes a string as parameter. * The string is converted to subversion internal * representation. The string is copied. * * @param path Path string - when url this should NOT hold revision as @ parameter!!!!! (will filtered out) */ Path(const QString &path = QString()); //krazy:exclude=explicit - Path(const QUrl &url); //krazy:exclude=explicit ~Path() = default; /** * Assignment operator */ Path &operator=(const Path &); /** * @return Path string */ const QString & path() const; /** * @return Path string as c string */ const QByteArray cstr() const; /** * check whether a path is set. Right now * this checks only if the string is non- * empty. * * @return true if there is a path set */ bool isSet() const; /** * adds a new URL component to the path * * @param component new component to add */ void addComponent(const QString &component); /** Reduce path to its parent folder. * If the path length is 1 (eg., only "/") it will cleared so * path length will get zero. * @sa svn_path_remove_component */ void removeLast(); /** Parse a string for a peg revision * @param pathorurl url to parse * @param _path target to store the cleaned url * @param _peg target where to store the peg url. * @throw svn::ClientException on errors */ static void parsePeg(const QString &pathorurl, Path &_path, svn::Revision &_peg); /** return the length of the path-string */ unsigned int length() const; /** returns the path with native separators */ QString native() const; /** returns if the path is a valid url, eg. points to a remote */ bool isUrl()const; }; } #endif /* ----------------------------------------------------------------- * local variables: * eval: (load-file "../../rapidsvn-dev.el") * end: */ diff --git a/src/svnqt/targets.cpp b/src/svnqt/targets.cpp index 0b0b14ac..4f725fb0 100644 --- a/src/svnqt/targets.cpp +++ b/src/svnqt/targets.cpp @@ -1,139 +1,140 @@ /* * Port for usage with qt-framework and development for kdesvn * Copyright (C) 2005-2009 by Rajko Albrecht (ral@alwins-world.de) * http://kdesvn.alwins-world.de */ /* * ==================================================================== * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. * dev@rapidsvn.tigris.org * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library (in the file LGPL.txt); if not, * write to the Free Software Foundation, Inc., 51 Franklin St, * Fifth Floor, Boston, MA 02110-1301 USA * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://rapidsvn.tigris.org/. * ==================================================================== */ #include "targets.h" // subversion api #include // apr api #include #include // svncpp #include "path.h" #include "pool.h" #include "svnqt_defines.h" #include +#include namespace svn { Targets::Targets(const svn::Paths &targets) : m_targets(targets) { } Targets::Targets(const QString &target) { if (!target.isEmpty()) { m_targets.push_back(target); } } Targets::Targets(const Path &target) { if (!target.cstr().isEmpty()) { m_targets.push_back(target); } } apr_array_header_t * Targets::array(const Pool &pool) const { Paths::const_iterator it; apr_pool_t *apr_pool = pool.pool(); apr_array_header_t *apr_targets = apr_array_make(apr_pool, m_targets.size(), sizeof(const char *)); for (it = m_targets.begin(); it != m_targets.end(); ++it) { QByteArray s = (*it).path().toUtf8(); char *t2 = apr_pstrndup(apr_pool, s, s.size()); (*((const char **) apr_array_push(apr_targets))) = t2; } return apr_targets; } const Paths & Targets::targets() const { return m_targets; } size_t Targets::size() const { return m_targets.size(); } const Path &Targets::operator [](size_t which)const { return m_targets[which]; } const Path Targets::target(Paths::size_type which) const { if (m_targets.size() > which) { return m_targets[which]; } else { return Path(); } } svn::Targets Targets::fromStringList(const QStringList &paths) { svn::Paths ret; ret.reserve(paths.size()); Q_FOREACH(const QString &path, paths) { ret.push_back(svn::Path(path)); } return svn::Targets(ret); } svn::Targets Targets::fromUrlList(const QList &urls) { svn::Paths ret; ret.reserve(urls.size()); Q_FOREACH(const QUrl &url, urls) { ret.push_back(svn::Path(url.isLocalFile() ? url.toLocalFile() : url.url())); } return svn::Targets(ret); } } diff --git a/src/svnqt/url.cpp b/src/svnqt/url.cpp index c8f95ee1..f33e5591 100644 --- a/src/svnqt/url.cpp +++ b/src/svnqt/url.cpp @@ -1,117 +1,122 @@ /* * Port for usage with qt-framework and development for kdesvn * Copyright (C) 2005-2009 by Rajko Albrecht (ral@alwins-world.de) * http://kdesvn.alwins-world.de */ /* * ==================================================================== * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. * dev@rapidsvn.tigris.org * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library (in the file LGPL.txt); if not, * write to the Free Software Foundation, Inc., 51 Franklin St, * Fifth Floor, Boston, MA 02110-1301 USA * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://rapidsvn.tigris.org/. * ==================================================================== */ #include "url.h" // svncpp #include "pool.h" #include "svnqt_defines.h" #include "helper.h" #include #include namespace svn { Url::Url(const QUrl &url) + : m_url(url.toString(QUrl::RemoveQuery|QUrl::NormalizePathSegments)) +{ +} + +Url::Url(const svn::Path &url) : m_url(url) { } QByteArray Url::cstr() const { - return m_url.toEncoded(QUrl::FullyEncoded|QUrl::NormalizePathSegments); + return m_url.cstr(); } /* static helpers */ bool Url::isLocal(const QString &url) { static const Qt::CaseSensitivity cs = Qt::CaseInsensitive; static const QLatin1String stf("file://"); static const QLatin1String stsf("svn+file://"); static const QLatin1String stkf("ksvn+file://"); if ( url.startsWith(stf, cs) || url.startsWith(QLatin1Char('/')) || url.startsWith(stsf, cs) || url.startsWith(stkf, cs)) { return true; } return false; } bool Url::isValid(const QString &url) { static const std::vector VALID_SCHEMAS = { QLatin1String("http"), QLatin1String("https"), QLatin1String("file"), QLatin1String("svn"), QLatin1String("svn+ssh"), QLatin1String("svn+http"), QLatin1String("svn+https"), QLatin1String("svn+file"), QLatin1String("ksvn"), QLatin1String("ksvn+ssh"), QLatin1String("ksvn+http"), QLatin1String("ksvn+https"), QLatin1String("ksvn+file") }; const QString urlTest(url); for (const QLatin1String &schema : VALID_SCHEMAS) { const QStringRef urlComp = urlTest.leftRef(schema.size()); if (schema == urlComp) { return true; } } return false; } QString Url::transformProtokoll(const QString &prot) { const QString _prot = prot.toLower(); if (_prot == QLatin1String("svn+http") || _prot == QLatin1String("ksvn+http")) return QLatin1String("http"); if (_prot == QLatin1String("svn+https") || _prot == QLatin1String("ksvn+https")) return QLatin1String("https"); if (_prot == QLatin1String("svn+file") || _prot == QLatin1String("ksvn+file")) return QLatin1String("file"); if (_prot == QLatin1String("ksvn+ssh")) return QLatin1String("svn+ssh"); if (_prot == QLatin1String("ksvn")) return QLatin1String("svn"); return _prot; } } /* ----------------------------------------------------------------- * local variables: * eval: (load-file "../../rapidsvn-dev.el") * end: */ diff --git a/src/svnqt/url.h b/src/svnqt/url.h index 81198721..a2ef4568 100644 --- a/src/svnqt/url.h +++ b/src/svnqt/url.h @@ -1,84 +1,86 @@ /* * Port for usage with qt-framework and development for kdesvn * Copyright (C) 2005-2009 by Rajko Albrecht (ral@alwins-world.de) * http://kdesvn.alwins-world.de */ /* * ==================================================================== * Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved. * dev@rapidsvn.tigris.org * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library (in the file LGPL.txt); if not, * write to the Free Software Foundation, Inc., 51 Franklin St, * Fifth Floor, Boston, MA 02110-1301 USA * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://rapidsvn.tigris.org/. * ==================================================================== */ #ifndef SVNQT_URL_H #define SVNQT_URL_H #include #include +#include "path.h" namespace svn { class SVNQT_EXPORT Url { private: - QUrl m_url; + svn::Path m_url; public: /** Constructor */ Url() = default; Url(const Url &) = default; explicit Url(const QUrl &url); + explicit Url(const svn::Path &url); /** Destructor */ ~Url() = default; QByteArray cstr()const; /** * Checks if @a url is valid * * Example of a valid URL: * http://svn.collab.net/repos/svn * Example of an invalid URL: * /home/foo/bar */ static bool isValid(const QString &url); /** * Checks if @a url points to a local filesystem. * * @return true if url is accessed local without network. */ static bool isLocal(const QString &url); static QString transformProtokoll(const QString &); }; } #endif /* ----------------------------------------------------------------- * local variables: * eval: (load-file "../../rapidsvn-dev.el") * end: */