File indexing completed on 2024-05-05 04:41:00
0001 /* 0002 SPDX-FileCopyrightText: 2007 Dukju Ahn <dukjuahn@gmail.com> 0003 SPDX-FileCopyrightText: 2008 Andreas Pakulat <apaku@gmx.de> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "kdevsvnplugin.h" 0009 0010 #include <QAction> 0011 #include <QDialog> 0012 #include <QMenu> 0013 #include <QVBoxLayout> 0014 #include <QVariant> 0015 0016 #include <KFile> 0017 #include <KIO/Global> 0018 #include <KLocalizedString> 0019 #include <KMessageBox> 0020 #include <KPluginFactory> 0021 #include <KUrlRequester> 0022 #include <KUrlRequesterDialog> 0023 0024 #include <interfaces/idocument.h> 0025 #include <interfaces/icore.h> 0026 #include <interfaces/iruncontroller.h> 0027 #include <project/projectmodel.h> 0028 #include <interfaces/context.h> 0029 #include <interfaces/contextmenuextension.h> 0030 #include <vcs/vcsrevision.h> 0031 #include <vcs/vcsevent.h> 0032 #include <vcs/vcsstatusinfo.h> 0033 #include <vcs/vcsannotation.h> 0034 #include <vcs/widgets/vcsdiffwidget.h> 0035 #include <vcs/widgets/vcscommitdialog.h> 0036 0037 #include "kdevsvncpp/apr.hpp" 0038 0039 #include "svncommitjob.h" 0040 #include "svnstatusjob.h" 0041 #include "svnaddjob.h" 0042 #include "svnrevertjob.h" 0043 #include "svnremovejob.h" 0044 #include "svnupdatejob.h" 0045 #include "svninfojob.h" 0046 #include "svndiffjob.h" 0047 #include "svncopyjob.h" 0048 #include "svnmovejob.h" 0049 #include "svnlogjob.h" 0050 #include "svnblamejob.h" 0051 #include "svnimportjob.h" 0052 #include "svncheckoutjob.h" 0053 0054 #include "svnimportmetadatawidget.h" 0055 #include <vcs/vcspluginhelper.h> 0056 #include <vcs/widgets/standardvcslocationwidget.h> 0057 #include "svnlocationwidget.h" 0058 #include "debug.h" 0059 0060 K_PLUGIN_FACTORY_WITH_JSON(KDevSvnFactory, "kdevsubversion.json", registerPlugin<KDevSvnPlugin>();) 0061 0062 KDevSvnPlugin::KDevSvnPlugin(QObject *parent, const QVariantList &) 0063 : KDevelop::IPlugin(QStringLiteral("kdevsubversion"), parent) 0064 , m_common(new KDevelop::VcsPluginHelper(this, this)) 0065 , copy_action( nullptr ) 0066 , move_action( nullptr ) 0067 , m_jobQueue(new ThreadWeaver::Queue(this)) 0068 { 0069 qRegisterMetaType<KDevelop::VcsStatusInfo>(); 0070 qRegisterMetaType<SvnInfoHolder>(); 0071 qRegisterMetaType<KDevelop::VcsEvent>(); 0072 qRegisterMetaType<KDevelop::VcsRevision>(); 0073 qRegisterMetaType<KDevelop::VcsRevision::RevisionSpecialType>(); 0074 qRegisterMetaType<KDevelop::VcsAnnotation>(); 0075 qRegisterMetaType<KDevelop::VcsAnnotationLine>(); 0076 } 0077 0078 KDevSvnPlugin::~KDevSvnPlugin() 0079 { 0080 } 0081 0082 bool KDevSvnPlugin::isValidRemoteRepositoryUrl(const QUrl& remoteLocation) 0083 { 0084 const QString scheme = remoteLocation.scheme(); 0085 if (scheme == QLatin1String("svn") || 0086 scheme == QLatin1String("svn+ssh")) { 0087 return true; 0088 } 0089 return false; 0090 } 0091 0092 0093 bool KDevSvnPlugin::isVersionControlled(const QUrl &localLocation) 0094 { 0095 ///TODO: also check this in the other functions? 0096 if (!localLocation.isValid()) { 0097 return false; 0098 } 0099 0100 auto* job = new SvnInfoJob(this); 0101 0102 job->setLocation(localLocation); 0103 0104 if (job->exec()) { 0105 QVariant result = job->fetchResults(); 0106 0107 if (result.isValid()) { 0108 SvnInfoHolder h = result.value<SvnInfoHolder>(); 0109 return !h.name.isEmpty(); 0110 } 0111 } else { 0112 qCDebug(PLUGIN_SVN) << "Couldn't execute job"; 0113 } 0114 0115 return false; 0116 } 0117 0118 KDevelop::VcsJob* KDevSvnPlugin::repositoryLocation(const QUrl &localLocation) 0119 { 0120 auto* job = new SvnInfoJob(this); 0121 0122 job->setLocation(localLocation); 0123 job->setProvideInformation(SvnInfoJob::RepoUrlOnly); 0124 return job; 0125 } 0126 0127 KDevelop::VcsJob* KDevSvnPlugin::status(const QList<QUrl>& localLocations, 0128 KDevelop::IBasicVersionControl::RecursionMode mode) 0129 { 0130 auto* job = new SvnStatusJob(this); 0131 job->setLocations(localLocations); 0132 job->setRecursive((mode == KDevelop::IBasicVersionControl::Recursive)); 0133 return job; 0134 } 0135 0136 KDevelop::VcsJob* KDevSvnPlugin::add(const QList<QUrl>& localLocations, 0137 KDevelop::IBasicVersionControl::RecursionMode recursion) 0138 { 0139 auto* job = new SvnAddJob(this); 0140 job->setLocations(localLocations); 0141 job->setRecursive((recursion == KDevelop::IBasicVersionControl::Recursive)); 0142 return job; 0143 } 0144 0145 KDevelop::VcsJob* KDevSvnPlugin::remove(const QList<QUrl>& localLocations) 0146 { 0147 auto* job = new SvnRemoveJob(this); 0148 job->setLocations(localLocations); 0149 return job; 0150 } 0151 0152 KDevelop::VcsJob* KDevSvnPlugin::edit(const QUrl& /*localLocation*/) 0153 { 0154 return nullptr; 0155 } 0156 0157 KDevelop::VcsJob* KDevSvnPlugin::unedit(const QUrl& /*localLocation*/) 0158 { 0159 return nullptr; 0160 } 0161 0162 KDevelop::VcsJob* KDevSvnPlugin::localRevision(const QUrl &localLocation, KDevelop::VcsRevision::RevisionType type) 0163 { 0164 auto* job = new SvnInfoJob(this); 0165 0166 job->setLocation(localLocation); 0167 job->setProvideInformation(SvnInfoJob::RevisionOnly); 0168 job->setProvideRevisionType(type); 0169 return job; 0170 } 0171 0172 KDevelop::VcsJob* KDevSvnPlugin::copy(const QUrl &localLocationSrc, const QUrl& localLocationDstn) 0173 { 0174 auto* job = new SvnCopyJob(this); 0175 job->setSourceLocation(localLocationSrc); 0176 job->setDestinationLocation(localLocationDstn); 0177 return job; 0178 } 0179 0180 KDevelop::VcsJob* KDevSvnPlugin::move(const QUrl &localLocationSrc, const QUrl& localLocationDst) 0181 { 0182 auto* job = new SvnMoveJob(this); 0183 job->setSourceLocation(localLocationSrc); 0184 job->setDestinationLocation(localLocationDst); 0185 return job; 0186 } 0187 0188 KDevelop::VcsJob* KDevSvnPlugin::revert(const QList<QUrl>& localLocations, 0189 KDevelop::IBasicVersionControl::RecursionMode recursion) 0190 { 0191 auto* job = new SvnRevertJob(this); 0192 job->setLocations(localLocations); 0193 job->setRecursive((recursion == KDevelop::IBasicVersionControl::Recursive)); 0194 return job; 0195 } 0196 0197 KDevelop::VcsJob* KDevSvnPlugin::update(const QList<QUrl>& localLocations, 0198 const KDevelop::VcsRevision& rev, 0199 KDevelop::IBasicVersionControl::RecursionMode recursion) 0200 { 0201 auto* job = new SvnUpdateJob(this); 0202 job->setLocations(localLocations); 0203 job->setRevision(rev); 0204 job->setRecursive((recursion == KDevelop::IBasicVersionControl::Recursive)); 0205 return job; 0206 } 0207 0208 KDevelop::VcsJob* KDevSvnPlugin::commit(const QString& message, const QList<QUrl>& localLocations, 0209 KDevelop::IBasicVersionControl::RecursionMode recursion) 0210 { 0211 auto* job = new SvnCommitJob(this); 0212 qCDebug(PLUGIN_SVN) << "Committing locations:" << localLocations; 0213 job->setUrls(localLocations); 0214 job->setCommitMessage(message) ; 0215 job->setRecursive((recursion == KDevelop::IBasicVersionControl::Recursive)); 0216 return job; 0217 } 0218 0219 KDevelop::VcsJob* KDevSvnPlugin::diff(const QUrl &fileOrDirectory, 0220 const KDevelop::VcsRevision& srcRevision, 0221 const KDevelop::VcsRevision& dstRevision, 0222 KDevelop::IBasicVersionControl::RecursionMode recurse) 0223 { 0224 KDevelop::VcsLocation loc(fileOrDirectory); 0225 return diff2(loc, loc, srcRevision, dstRevision, recurse); 0226 } 0227 0228 KDevelop::VcsJob* KDevSvnPlugin::diff2(const KDevelop::VcsLocation& src, 0229 const KDevelop::VcsLocation& dst, 0230 const KDevelop::VcsRevision& srcRevision, 0231 const KDevelop::VcsRevision& dstRevision, 0232 KDevelop::IBasicVersionControl::RecursionMode recurse) 0233 { 0234 auto* job = new SvnDiffJob(this); 0235 job->setSource(src); 0236 job->setDestination(dst); 0237 job->setSrcRevision(srcRevision); 0238 job->setDstRevision(dstRevision); 0239 job->setRecursive((recurse == KDevelop::IBasicVersionControl::Recursive)); 0240 return job; 0241 } 0242 0243 KDevelop::VcsJob* KDevSvnPlugin::log(const QUrl &localLocation, const KDevelop::VcsRevision& rev, unsigned long limit) 0244 { 0245 auto* job = new SvnLogJob(this); 0246 job->setLocation(localLocation); 0247 job->setStartRevision(rev); 0248 job->setLimit(limit); 0249 return job; 0250 } 0251 0252 KDevelop::VcsJob* KDevSvnPlugin::log(const QUrl &localLocation, 0253 const KDevelop::VcsRevision& startRev, 0254 const KDevelop::VcsRevision& endRev) 0255 { 0256 auto* job = new SvnLogJob(this); 0257 job->setLocation(localLocation); 0258 job->setStartRevision(startRev); 0259 job->setEndRevision(endRev); 0260 return job; 0261 } 0262 0263 KDevelop::VcsJob* KDevSvnPlugin::annotate(const QUrl &localLocation, 0264 const KDevelop::VcsRevision& rev) 0265 { 0266 auto* job = new SvnBlameJob(this); 0267 job->setLocation(localLocation); 0268 job->setEndRevision(rev); 0269 return job; 0270 } 0271 0272 KDevelop::VcsJob* KDevSvnPlugin::merge(const KDevelop::VcsLocation& localOrRepoLocationSrc, 0273 const KDevelop::VcsLocation& localOrRepoLocationDst, 0274 const KDevelop::VcsRevision& srcRevision, 0275 const KDevelop::VcsRevision& dstRevision, 0276 const QUrl &localLocation) 0277 { 0278 // TODO implement merge 0279 Q_UNUSED(localOrRepoLocationSrc) 0280 Q_UNUSED(localOrRepoLocationDst) 0281 Q_UNUSED(srcRevision) 0282 Q_UNUSED(dstRevision) 0283 Q_UNUSED(localLocation) 0284 return nullptr; 0285 } 0286 0287 KDevelop::VcsJob* KDevSvnPlugin::resolve(const QList<QUrl>& /*localLocations*/, 0288 KDevelop::IBasicVersionControl::RecursionMode /*recursion*/) 0289 { 0290 return nullptr; 0291 } 0292 0293 KDevelop::VcsJob* KDevSvnPlugin::import(const QString & commitMessage, const QUrl &sourceDirectory, const KDevelop::VcsLocation & destinationRepository) 0294 { 0295 auto* job = new SvnImportJob(this); 0296 job->setMapping(sourceDirectory, destinationRepository); 0297 job->setMessage(commitMessage); 0298 return job; 0299 } 0300 0301 KDevelop::VcsJob* KDevSvnPlugin::createWorkingCopy(const KDevelop::VcsLocation & sourceRepository, const QUrl &destinationDirectory, KDevelop::IBasicVersionControl::RecursionMode recursion) 0302 { 0303 auto* job = new SvnCheckoutJob(this); 0304 job->setMapping(sourceRepository, destinationDirectory, recursion); 0305 return job; 0306 } 0307 0308 0309 KDevelop::ContextMenuExtension KDevSvnPlugin::contextMenuExtension(KDevelop::Context* context, QWidget* parent) 0310 { 0311 m_common->setupFromContext(context); 0312 0313 const QList<QUrl> & ctxUrlList = m_common->contextUrlList(); 0314 0315 bool hasVersionControlledEntries = false; 0316 for (const QUrl& url : ctxUrlList) { 0317 if (isVersionControlled(url) || isVersionControlled(KIO::upUrl(url))) { 0318 hasVersionControlledEntries = true; 0319 break; 0320 } 0321 } 0322 0323 qCDebug(PLUGIN_SVN) << "version controlled?" << hasVersionControlledEntries; 0324 0325 if (!hasVersionControlledEntries) 0326 return IPlugin::contextMenuExtension(context, parent); 0327 0328 0329 QMenu* svnmenu = m_common->commonActions(parent); 0330 svnmenu->addSeparator(); 0331 0332 if( !copy_action ) 0333 { 0334 copy_action = new QAction(i18nc("@action:inmenu", "Copy..."), this); 0335 connect(copy_action, &QAction::triggered, this, &KDevSvnPlugin::ctxCopy); 0336 } 0337 svnmenu->addAction(copy_action); 0338 0339 if( !move_action ) 0340 { 0341 move_action = new QAction(i18nc("@action:inmenu", "Move..."), this); 0342 connect(move_action, &QAction::triggered, this, &KDevSvnPlugin::ctxMove); 0343 } 0344 svnmenu->addAction(move_action); 0345 0346 KDevelop::ContextMenuExtension menuExt; 0347 menuExt.addAction(KDevelop::ContextMenuExtension::VcsGroup, svnmenu->menuAction()); 0348 0349 return menuExt; 0350 } 0351 0352 void KDevSvnPlugin::ctxCopy() 0353 { 0354 QList<QUrl> const & ctxUrlList = m_common->contextUrlList(); 0355 if (ctxUrlList.count() > 1) { 0356 KMessageBox::error(nullptr, i18n("Please select only one item for this operation")); 0357 return; 0358 } 0359 0360 QUrl source = ctxUrlList.first(); 0361 0362 if (source.isLocalFile()) { 0363 QUrl dir = source; 0364 bool isFile = QFileInfo(source.toLocalFile()).isFile(); 0365 0366 if (isFile) { 0367 dir = dir.adjusted(QUrl::RemoveFilename|QUrl::StripTrailingSlash); 0368 } 0369 0370 KUrlRequesterDialog dlg(dir, i18nc("@label", "Destination file/directory"), nullptr); 0371 0372 if (isFile) { 0373 dlg.urlRequester()->setMode(KFile::File | KFile::Directory | KFile::LocalOnly); 0374 } else { 0375 dlg.urlRequester()->setMode(KFile::Directory | KFile::LocalOnly); 0376 } 0377 0378 if (dlg.exec() == QDialog::Accepted) { // krazy:exclude=crashy 0379 KDevelop::ICore::self()->runController()->registerJob(copy(source, dlg.selectedUrl())); 0380 } 0381 } else { 0382 KMessageBox::error(nullptr, i18n("Copying only works on local files")); 0383 return; 0384 } 0385 0386 } 0387 0388 void KDevSvnPlugin::ctxMove() 0389 { 0390 QList<QUrl> const & ctxUrlList = m_common->contextUrlList(); 0391 if (ctxUrlList.count() != 1) { 0392 KMessageBox::error(nullptr, i18n("Please select only one item for this operation")); 0393 return; 0394 } 0395 0396 QUrl source = ctxUrlList.first(); 0397 0398 if (source.isLocalFile()) { 0399 QUrl dir = source; 0400 bool isFile = QFileInfo(source.toLocalFile()).isFile(); 0401 0402 if (isFile) { 0403 dir = source.adjusted(QUrl::RemoveFilename|QUrl::StripTrailingSlash); 0404 } 0405 0406 KUrlRequesterDialog dlg(dir, i18n("Destination file/directory"), nullptr); 0407 0408 if (isFile) { 0409 dlg.urlRequester()->setMode(KFile::File | KFile::Directory | KFile::LocalOnly); 0410 } else { 0411 dlg.urlRequester()->setMode(KFile::Directory | KFile::LocalOnly); 0412 } 0413 0414 if (dlg.exec() == QDialog::Accepted) { // krazy:exclude=crashy 0415 KDevelop::ICore::self()->runController()->registerJob(move(source, dlg.selectedUrl())); 0416 } 0417 } else { 0418 KMessageBox::error(nullptr, i18n("Moving only works on local files/dirs")); 0419 return; 0420 } 0421 } 0422 0423 QString KDevSvnPlugin::name() const 0424 { 0425 return i18n("Subversion"); 0426 } 0427 0428 KDevelop::VcsImportMetadataWidget* KDevSvnPlugin::createImportMetadataWidget(QWidget* parent) 0429 { 0430 return new SvnImportMetadataWidget(parent); 0431 } 0432 0433 KDevelop::VcsLocationWidget* KDevSvnPlugin::vcsLocation(QWidget* parent) const 0434 { 0435 return new SvnLocationWidget(parent); 0436 } 0437 0438 ThreadWeaver::Queue* KDevSvnPlugin::jobQueue() const 0439 { 0440 return m_jobQueue; 0441 } 0442 0443 #include "kdevsvnplugin.moc" 0444 #include "moc_kdevsvnplugin.cpp"