File indexing completed on 2024-05-05 04:41:00

0001 /*
0002     SPDX-FileCopyrightText: 2007 Andreas Pakulat <apaku@gmx.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "svnblamejob.h"
0008 
0009 #include "svnblamejob_p.h"
0010 
0011 #include <QMutexLocker>
0012 
0013 #include <KLocalizedString>
0014 
0015 #include "svnclient.h"
0016 #include <QDateTime>
0017 
0018 SvnInternalBlameJob::SvnInternalBlameJob( SvnJobBase* parent )
0019     : SvnInternalJobBase( parent )
0020 {
0021     m_startRevision.setRevisionValue(QVariant::fromValue(KDevelop::VcsRevision::Start),
0022                                     KDevelop::VcsRevision::Special );
0023     m_endRevision.setRevisionValue(QVariant::fromValue(KDevelop::VcsRevision::Head),
0024                                     KDevelop::VcsRevision::Special );
0025 }
0026 
0027 void SvnInternalBlameJob::run(ThreadWeaver::JobPointer /*self*/, ThreadWeaver::Thread* /*thread*/)
0028 {
0029     initBeforeRun();
0030 
0031     QByteArray ba = location().toString( QUrl::PreferLocalFile | QUrl::StripTrailingSlash ).toUtf8();
0032 
0033     svn::Client cli(m_ctxt);
0034     svn::AnnotatedFile* file;
0035     try
0036     {
0037         file = cli.annotate( ba.data(),
0038                              createSvnCppRevisionFromVcsRevision( startRevision() ),
0039                              createSvnCppRevisionFromVcsRevision( endRevision() ) );
0040     }catch( const svn::ClientException& ce )
0041     {
0042         qCDebug(PLUGIN_SVN) << "Exception while blaming file: "
0043                 << location()
0044                 << QString::fromUtf8( ce.message() );
0045         setErrorMessage( QString::fromUtf8( ce.message() ) );
0046         m_success = false;
0047         return;
0048     }
0049     svn_revnum_t minrev = -1, maxrev = -1;
0050     for (const auto& line : *file) {
0051         const svn_revnum_t lineRevision = line.revision();
0052         if (lineRevision < minrev || minrev == -1) {
0053             minrev = lineRevision;
0054         }
0055         if (lineRevision > maxrev || maxrev == -1 ) {
0056             maxrev = lineRevision;
0057         }
0058     }
0059     QHash<svn_revnum_t,QString> commitMessages;
0060     try
0061     {
0062         const svn::LogEntries* entries = cli.log( ba.data(), svn::Revision(minrev), svn::Revision(maxrev), false, false );
0063         for (const auto& entry : *entries) {
0064             commitMessages[entry.revision] = QString::fromUtf8(entry.message.c_str() );
0065         }
0066     }catch( const svn::ClientException& ce )
0067     {
0068         qCDebug(PLUGIN_SVN) << "Exception while fetching log messages for blame: "
0069                      << location()
0070                      << QString::fromUtf8( ce.message() );
0071         setErrorMessage( QString::fromUtf8( ce.message() ) );
0072         m_success = false;
0073     }
0074     for (const auto& svnLine : *file) {
0075         KDevelop::VcsAnnotationLine line;
0076         line.setAuthor(QString::fromUtf8(svnLine.author().c_str()));
0077         line.setDate(QDateTime::fromString(QString::fromUtf8(svnLine.date().c_str()), Qt::ISODate));
0078         line.setText(QString::fromUtf8(svnLine.line().c_str()));
0079         KDevelop::VcsRevision rev;
0080         rev.setRevisionValue(QVariant(qlonglong(svnLine.revision())), KDevelop::VcsRevision::GlobalNumber);
0081         line.setRevision( rev );
0082         line.setLineNumber(svnLine.lineNumber());
0083         line.setCommitMessage(commitMessages[svnLine.revision()]);
0084         emit blameLine( line );
0085     }
0086 }
0087 
0088 void SvnInternalBlameJob::setLocation( const QUrl &url )
0089 {
0090     QMutexLocker l( &m_mutex );
0091     m_location = url;
0092 }
0093 
0094 QUrl SvnInternalBlameJob::location() const
0095 {
0096     QMutexLocker l( &m_mutex );
0097     return m_location;
0098 }
0099 
0100 KDevelop::VcsRevision SvnInternalBlameJob::startRevision() const
0101 {
0102     QMutexLocker l( &m_mutex );
0103     return m_startRevision;
0104 }
0105 
0106 KDevelop::VcsRevision SvnInternalBlameJob::endRevision() const
0107 {
0108     QMutexLocker l( &m_mutex );
0109     return m_endRevision;
0110 }
0111 
0112 void SvnInternalBlameJob::setStartRevision( const KDevelop::VcsRevision& rev )
0113 {
0114     QMutexLocker l( &m_mutex );
0115     m_startRevision = rev;
0116 }
0117 
0118 void SvnInternalBlameJob::setEndRevision( const KDevelop::VcsRevision& rev )
0119 {
0120     QMutexLocker l( &m_mutex );
0121     m_endRevision = rev;
0122 }
0123 
0124 SvnBlameJob::SvnBlameJob( KDevSvnPlugin* parent )
0125     : SvnJobBaseImpl( parent, KDevelop::OutputJob::Silent )
0126 {
0127     setType( KDevelop::VcsJob::Annotate );
0128     connect(m_job.data(), &SvnInternalBlameJob::blameLine,
0129             this, &SvnBlameJob::blameLineReceived);
0130     setObjectName(i18n("Subversion Annotate"));
0131 }
0132 
0133 QVariant SvnBlameJob::fetchResults()
0134 {
0135     QList<QVariant> results = m_annotations;
0136     m_annotations.clear();
0137     return results;
0138 }
0139 
0140 void SvnBlameJob::start()
0141 {
0142     if ( !m_job->location().isValid() ) {
0143         internalJobFailed();
0144         setErrorText( i18n( "Not enough information to blame location" ) );
0145     } else {
0146         qCDebug(PLUGIN_SVN) << "blaming url:" << m_job->location();
0147         startInternalJob();
0148     }
0149 }
0150 
0151 void SvnBlameJob::setLocation( const QUrl &url )
0152 {
0153     if( status() == KDevelop::VcsJob::JobNotStarted )
0154         m_job->setLocation( url );
0155 }
0156 
0157 void SvnBlameJob::setStartRevision( const KDevelop::VcsRevision& rev )
0158 {
0159     if( status() == KDevelop::VcsJob::JobNotStarted )
0160         m_job->setStartRevision( rev );
0161 }
0162 
0163 void SvnBlameJob::setEndRevision( const KDevelop::VcsRevision& rev )
0164 {
0165     if( status() == KDevelop::VcsJob::JobNotStarted )
0166         m_job->setEndRevision( rev );
0167 }
0168 
0169 void SvnBlameJob::blameLineReceived( const KDevelop::VcsAnnotationLine& line )
0170 {
0171     m_annotations.append(QVariant::fromValue(line));
0172     emit resultsReady( this );
0173 }
0174 
0175 #include "moc_svnblamejob_p.cpp"
0176 #include "moc_svnblamejob.cpp"