diff --git a/src/kiosvn/kiosvn.cpp b/src/kiosvn/kiosvn.cpp index 12e1b1e8..b79887d4 100644 --- a/src/kiosvn/kiosvn.cpp +++ b/src/kiosvn/kiosvn.cpp @@ -1,1133 +1,1134 @@ /*************************************************************************** * 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); } 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); } 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); svn::InfoEntries e; e = m_pData->m_Svnclient->info(_url, svn::DepthEmpty, rev, rev); if (!e.isEmpty()) { totalSize(e.at(0).size()); } m_pData->m_Svnclient->cat(dstream, _url, 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()); } 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))); } 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); } 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); 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())); 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); } 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)); } 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())); 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)); 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 { m_pData->resetListener(); if (url.isEmpty() || !url.isLocalFile()) { 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); } 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 { const QString scheme = svn::Url::transformProtokoll(url.scheme()); if (scheme == QLatin1String("file") && check_Wc) { if (checkWc(url)) { return 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; } 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); 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); } 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); } 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); QTemporaryDir tdir; qCDebug(KDESVN_LOG) << "kio_ksvn::diff : " << u1 << " at revision " << r1.toString() << " with " << u2 << " 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()); 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 QString path = wc.path(); m_pData->m_Svnclient->import(svn::Path(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/svnfrontend/svnitem.cpp b/src/svnfrontend/svnitem.cpp index f32e565c..c877b0e0 100644 --- a/src/svnfrontend/svnitem.cpp +++ b/src/svnfrontend/svnitem.cpp @@ -1,631 +1,631 @@ /*************************************************************************** * 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 "svnitem.h" #include "svnactions.h" #include "kdesvn_part.h" #include "settings/kdesvnsettings.h" #include "svnqt/status.h" #include "svnqt/url.h" #include "helpers/ktranslateurl.h" #include "helpers/kdesvn_debug.h" #include #include #include #include #include #include #include #include #include #include #include class SvnItem_p { public: SvnItem_p(); explicit SvnItem_p(const svn::StatusPtr &); KFileItem &createItem(const svn::Revision &peg); QUrl &kdeName(const svn::Revision &); QMimeType mimeType(bool dir); svn::StatusPtr m_Stat; void init(); QUrl m_url; QString m_full, m_short; QUrl m_kdename; QDateTime m_fullDate; QString m_infoText; KFileItem m_fitem; bool isWc; svn::Revision lRev; QMimeType m_mimeType; QMutex _infoTextMutex; }; SvnItem_p::SvnItem_p() : m_Stat(new svn::Status()) { init(); } SvnItem_p::SvnItem_p(const svn::StatusPtr &aStat) : m_Stat(aStat) { init(); } void SvnItem_p::init() { isWc = false; m_full = m_Stat->path(); m_kdename.clear(); m_mimeType = QMimeType(); lRev = svn::Revision::UNDEFINED; while (m_full.endsWith(QLatin1Char('/'))) { /* dir name possible */ m_full.chop(1); } int p = m_full.lastIndexOf(QLatin1Char('/')); if (p > -1) { ++p; m_short = m_full.right(m_full.length() - p); } else { m_short = m_full; } m_url = m_Stat->entry().url(); m_fullDate = m_Stat->entry().cmtDate().toQDateTime(); m_infoText.clear(); } QMimeType SvnItem_p::mimeType(bool dir) { if (!m_mimeType.isValid() || m_kdename.isEmpty()) { if (m_kdename.isEmpty()) { kdeName(svn::Revision::UNDEFINED); } QMimeDatabase db; if (dir) { m_mimeType = db.mimeTypeForName(QLatin1String("inode/directory")); } else { m_mimeType = db.mimeTypeForUrl(m_kdename); } } return m_mimeType; } QUrl &SvnItem_p::kdeName(const svn::Revision &r) { isWc = !svn::Url::isValid(m_Stat->path()); if (!(r == lRev) || m_kdename.isEmpty()) { lRev = r; if (!isWc) { m_kdename = m_Stat->entry().url(); QString proto = helpers::KTranslateUrl::makeKdeUrl(m_kdename.scheme()); m_kdename.setScheme(proto); QString revstr = lRev.toString(); if (!revstr.isEmpty()) { - m_kdename.setQuery(QStringLiteral("?rev=") + revstr); + m_kdename.setQuery(QStringLiteral("rev=") + revstr); } } else { // Working copy path() is local file m_kdename = QUrl::fromLocalFile(m_Stat->path()); } } return m_kdename; } KFileItem &SvnItem_p::createItem(const svn::Revision &peg) { if (m_fitem.isNull() || !(peg == lRev)) { m_fitem = KFileItem(kdeName(peg)); } return m_fitem; } SvnItem::SvnItem() : m_overlaycolor(false) , m_bgColor(NONE) , p_Item(new SvnItem_p()) { } SvnItem::SvnItem(const svn::StatusPtr &aStat) : m_overlaycolor(false) , m_bgColor(NONE) , p_Item(new SvnItem_p(aStat)) { } SvnItem::~SvnItem() { } void SvnItem::setStat(const svn::StatusPtr &aStat) { m_overlaycolor = false; p_Item.reset(new SvnItem_p(aStat)); SvnActions *wrap = getWrapper(); if (isChanged() || isConflicted()) { wrap->addModifiedCache(aStat); } else { wrap->deleteFromModifiedCache(fullName()); } } const QString &SvnItem::fullName()const { return (p_Item->m_full); } const QString &SvnItem::shortName()const { return (p_Item->m_short); } const QUrl &SvnItem::Url()const { return (p_Item->m_url); } bool SvnItem::isDir()const { if (p_Item->m_Stat->entry().isValid() || isRemoteAdded()) { if (p_Item->m_Stat->entry().kind() != svn_node_unknown) { return p_Item->m_Stat->entry().kind() == svn_node_dir; } } /* must be a local file */ QFileInfo f(fullName()); return f.isDir(); } const QDateTime &SvnItem::fullDate()const { return (p_Item->m_fullDate); } QPixmap SvnItem::internalTransform(const QPixmap &first, int size) { if (first.isNull()) { return QPixmap(); } QPixmap _p = first.scaled(QSize(size, size), Qt::KeepAspectRatio); if (_p.width() == size && _p.height() == size) { return _p; } QPixmap result(size, size); result.fill(Qt::transparent); QPainter pa; pa.begin(&result); int w = _p.width() > size ? size : _p.width(); int h = _p.height() > size ? size : _p.height(); pa.drawPixmap(0, 0, _p, 0, 0, w, h); pa.end(); return result; } QPixmap SvnItem::getPixmap(const QPixmap &_p, int size, bool overlay) { if (!isVersioned()) { m_bgColor = NOTVERSIONED; } else if (isRealVersioned()) { SvnActions *wrap = getWrapper(); bool mod = false; QPixmap p2; if (p_Item->m_Stat->nodeStatus() == svn_wc_status_conflicted) { m_bgColor = CONFLICT; if (overlay) { p2 = KIconLoader::global()->loadIcon(QStringLiteral("kdesvnconflicted"), KIconLoader::Desktop, size); } } else if (p_Item->m_Stat->nodeStatus() == svn_wc_status_missing) { m_bgColor = MISSING; } else if (isLocked() || (wrap && wrap->checkReposLockCache(fullName()))) { if (overlay) { p2 = KIconLoader::global()->loadIcon(QStringLiteral("kdesvnlocked"), KIconLoader::Desktop, size); } m_bgColor = LOCKED; } else if (Kdesvnsettings::check_needslock() && !isRemoteAdded() && wrap && wrap->isLockNeeded(this, svn::Revision::UNDEFINED)) { if (overlay) { p2 = KIconLoader::global()->loadIcon(QStringLiteral("kdesvnneedlock"), KIconLoader::Desktop, size); } m_bgColor = NEEDLOCK; } else if (wrap && wrap->isUpdated(p_Item->m_Stat->path())) { if (overlay) { p2 = KIconLoader::global()->loadIcon(QStringLiteral("kdesvnupdates"), KIconLoader::Desktop, size); } m_bgColor = UPDATES; } else if (p_Item->m_Stat->nodeStatus() == svn_wc_status_deleted) { if (overlay) { p2 = KIconLoader::global()->loadIcon(QStringLiteral("kdesvndeleted"), KIconLoader::Desktop, size); } m_bgColor = DELETED; } else if (p_Item->m_Stat->nodeStatus() == svn_wc_status_added) { if (overlay) { p2 = KIconLoader::global()->loadIcon(QStringLiteral("kdesvnadded"), KIconLoader::Desktop, size); } m_bgColor = ADDED; } else if (isModified()) { mod = true; } else if (isDir() && wrap) { if (isRemoteAdded() || wrap->checkUpdateCache(fullName())) { if (overlay) { p2 = KIconLoader::global()->loadIcon(QStringLiteral("kdesvnupdates"), KIconLoader::Desktop, size); } m_bgColor = UPDATES; } else if (wrap->checkConflictedCache(fullName())) { m_bgColor = CONFLICT; if (overlay) { p2 = KIconLoader::global()->loadIcon(QStringLiteral("kdesvnconflicted"), KIconLoader::Desktop, size); } } else { mod = wrap->checkModifiedCache(fullName()); } } if (mod) { m_bgColor = MODIFIED; if (overlay) { p2 = KIconLoader::global()->loadIcon(QStringLiteral("kdesvnmodified"), KIconLoader::Desktop, size); } } if (!p2.isNull()) { QPixmap p; if (_p.width() != size || _p.height() != size) { p = internalTransform(_p, size); } else { p = _p; } if (p2.width() != size || p2.height() != size) { p2 = internalTransform(p2, size); } m_overlaycolor = true; QImage i1(p.toImage()); QImage i2(p2.toImage()); KIconEffect::overlay(i1, i2); return QPixmap::fromImage(i1); } } return _p; } QPixmap SvnItem::getPixmap(int size, bool overlay) { QPixmap p; m_overlaycolor = false; m_bgColor = NONE; /* yes - different way to "isDir" above 'cause here we try to use the mime-features of KDE on ALL not just unversioned entries. */ #ifdef DEBUG_TIMER QTime _counttime; _counttime.start(); #endif if (svn::Url::isValid(p_Item->m_Stat->path())) { /* remote access */ p = KIconLoader::global()->loadMimeTypeIcon(p_Item->mimeType(isDir()).iconName(), KIconLoader::Desktop, size, KIconLoader::DefaultState); if (isLocked()) { m_bgColor = LOCKED; if (overlay) { QPixmap p2 = KIconLoader::global()->loadIcon(QStringLiteral("kdesvnlocked"), KIconLoader::Desktop, size); if (!p2.isNull()) { QImage i1; i1 = p.toImage(); QImage i2; i2 = p2.toImage(); KIconEffect::overlay(i1, i2); p.fromImage(i1); } } } } else { if (isRemoteAdded()) { if (isDir()) { p = KIconLoader::global()->loadIcon(QStringLiteral("folder"), KIconLoader::Desktop, size); } else { p = KIconLoader::global()->loadIcon(QStringLiteral("unknown"), KIconLoader::Desktop, size); } } else { // local access const QUrl uri(QUrl::fromLocalFile(fullName())); QMimeDatabase db; const QMimeType mimeType(db.mimeTypeForUrl(uri)); p = KIconLoader::global()->loadMimeTypeIcon(mimeType.iconName(), KIconLoader::Desktop, size); p = getPixmap(p, size, overlay); } } #ifdef DEBUG_TIMER //qCDebug(KDESVN_LOG)<<"Time getting icon: "<<_counttime.elapsed(); #endif return p; } bool SvnItem::isVersioned()const { return p_Item->m_Stat->isVersioned(); } bool SvnItem::isValid()const { if (isVersioned()) { return true; } QFileInfo f(fullName()); return f.exists(); } bool SvnItem::isRealVersioned()const { return p_Item->m_Stat->isRealVersioned(); } bool SvnItem::isIgnored()const { return p_Item->m_Stat->nodeStatus() == svn_wc_status_ignored; } bool SvnItem::isRemoteAdded()const { return getWrapper()->isUpdated(p_Item->m_Stat->path()) && p_Item->m_Stat->validReposStatus() && !p_Item->m_Stat->validLocalStatus(); } bool SvnItem::isLocalAdded()const { return p_Item->m_Stat->nodeStatus() == svn_wc_status_added; } QString SvnItem::infoText()const { QString info_text; if (!isVersioned()) { info_text = i18n("Not versioned"); } else if (getWrapper()->isUpdated(p_Item->m_Stat->path())) { if (p_Item->m_Stat->validReposStatus() && !p_Item->m_Stat->validLocalStatus()) { info_text = i18n("Added in repository"); } else { info_text = i18n("Needs update"); } } else { switch (p_Item->m_Stat->nodeStatus()) { case svn_wc_status_none: case svn_wc_status_normal: break; case svn_wc_status_unversioned: info_text = i18n("Not versioned"); break; case svn_wc_status_modified: { if (p_Item->m_Stat->textStatus() == svn_wc_status_modified) info_text = i18n("Locally modified"); else info_text = i18n("Property modified"); break; } case svn_wc_status_added: info_text = i18n("Locally added"); break; case svn_wc_status_missing: info_text = i18n("Missing"); break; case svn_wc_status_deleted: info_text = i18n("Deleted"); break; case svn_wc_status_replaced: info_text = i18n("Replaced"); break; case svn_wc_status_ignored: info_text = i18n("Ignored"); break; case svn_wc_status_external: info_text = i18n("External"); break; case svn_wc_status_conflicted: { if (p_Item->m_Stat->textStatus() == svn_wc_status_conflicted) info_text = i18n("Conflict"); else info_text = i18n("Property conflicted"); break; } case svn_wc_status_merged: info_text = i18n("Merged"); break; case svn_wc_status_incomplete: info_text = i18n("Incomplete"); break; case svn_wc_status_obstructed: info_text = i18n("Obstructed"); break; } } return info_text; } QString SvnItem::cmtAuthor()const { return p_Item->m_Stat->entry().cmtAuthor(); } long int SvnItem::cmtRev()const { return p_Item->m_Stat->entry().cmtRev(); } bool SvnItem::isLocked()const { return p_Item->m_Stat->entry().lockEntry().Locked(); } QString SvnItem::lockOwner()const { if (p_Item->m_Stat->entry().lockEntry().Locked()) { return p_Item->m_Stat->entry().lockEntry().Owner(); } svn::StatusPtr tmp; if (getWrapper()->checkReposLockCache(fullName(), tmp) && tmp) { return tmp->lockEntry().Owner(); } return QString(); } /*! \fn SvnItem::isModified() */ bool SvnItem::isModified()const { return p_Item->m_Stat->nodeStatus() == svn_wc_status_modified || p_Item->m_Stat->nodeStatus() == svn_wc_status_replaced; } bool SvnItem::isChanged()const { return isRealVersioned() && (isModified() || isDeleted() || isLocalAdded()); } bool SvnItem::isChildModified()const { return getWrapper()->checkModifiedCache(fullName()); } const svn::StatusPtr &SvnItem::stat()const { return p_Item->m_Stat; } /*! \fn SvnItem::isNormal()const */ bool SvnItem::isNormal()const { return p_Item->m_Stat->nodeStatus() == svn_wc_status_normal; } bool SvnItem::isMissing()const { return p_Item->m_Stat->nodeStatus() == svn_wc_status_missing; } bool SvnItem::isDeleted()const { return p_Item->m_Stat->nodeStatus() == svn_wc_status_deleted; } bool SvnItem::isConflicted()const { return p_Item->m_Stat->nodeStatus() == svn_wc_status_conflicted; } bool SvnItem::hasToolTipText() { QMutexLocker ml(&(p_Item->_infoTextMutex)); return !p_Item->m_infoText.isNull(); } svn::Revision SvnItem::revision() const { if (isRealVersioned() && !p_Item->m_Stat->entry().url().isEmpty()) { return p_Item->m_Stat->entry().revision(); } return svn::Revision::UNDEFINED; } /*! \fn SvnItem::getToolTipText() */ const QString &SvnItem::getToolTipText() { if (!hasToolTipText()) { qCDebug(KDESVN_LOG) << "Try getting text" << endl; QString text; if (isRealVersioned() && !p_Item->m_Stat->entry().url().isEmpty()) { SvnActions *wrap = getWrapper(); svn::Revision peg(svn_opt_revision_unspecified); svn::Revision rev(svn_opt_revision_unspecified); if (svn::Url::isValid(p_Item->m_Stat->path())) { /* remote */ rev = p_Item->m_Stat->entry().revision(); peg = correctPeg(); } else { /* local */ } if (wrap) { SvnItemList lst; lst.append(this); text = wrap->getInfo(lst, rev, peg, false, false); qCDebug(KDESVN_LOG) << text << endl; // KF5: TODO /* if (!p_Item->m_fitem.isNull()) { text += p_Item->m_fitem.getToolTipText(0); } */ } } else if (!p_Item->m_fitem.isNull()) { // KF5: TODO // text = p_Item->m_fitem.getToolTipText(6); } QMutexLocker ml(&(p_Item->_infoTextMutex)); p_Item->m_infoText = text; } QMutexLocker ml(&(p_Item->_infoTextMutex)); return p_Item->m_infoText; } void SvnItem::generateToolTip(const svn::InfoEntry &entry) { QString text; if (isRealVersioned() && !p_Item->m_Stat->entry().url().isEmpty()) { SvnActions *wrap = getWrapper(); if (wrap) { svn::InfoEntries e; e.append(entry); text = wrap->getInfo(e, fullName(), false); } if (!p_Item->m_fitem.isNull()) { // KF5: TODO // text += p_Item->m_fitem.getToolTipText(0); } } else if (!p_Item->m_fitem.isNull()) { // text = p_Item->m_fitem.getToolTipText(6); } { QMutexLocker ml(&(p_Item->_infoTextMutex)); p_Item->m_infoText = text; } } KFileItem SvnItem::fileItem() { return p_Item->createItem(correctPeg()); } const QUrl &SvnItem::kdeName(const svn::Revision &r) { return p_Item->kdeName(r); } QMimeType SvnItem::mimeType() { return p_Item->mimeType(isDir()); }