File indexing completed on 2024-05-12 04:38:53

0001 /*
0002     This file was partly taken from KDevelop's cvs plugin
0003     SPDX-FileCopyrightText: 2002-2003 Christian Loose <christian.loose@hamburg.de>
0004     SPDX-FileCopyrightText: 2007 Robert Gruber <rgruber@users.sourceforge.net>
0005 
0006     Adapted for DVCS
0007     SPDX-FileCopyrightText: 2008 Evgeniy Ivanov <powerfox@kde.ru>
0008     SPDX-FileCopyrightText: 2010 Aleix Pol Gonzalez <aleixpol@kde.org>
0009 
0010     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0011 */
0012 
0013 
0014 #ifndef KDEVPLATFORM_DVCS_JOB_H
0015 #define KDEVPLATFORM_DVCS_JOB_H
0016 
0017 #include <QVariant>
0018 #include <KProcess>
0019 
0020 #include <vcs/vcsexport.h>
0021 #include "../vcsjob.h"
0022 
0023 class QDir;
0024 class QStringList;
0025 
0026 
0027 namespace KDevelop
0028 {
0029 class DVcsJobPrivate;
0030 
0031 /**
0032  * This class is capable of running our dvcs commands. 
0033  * Most of all DVcsJob are created in DVCS executors, but executed in DistributedVersionControlPlugin or
0034  * any managers like BranchManager.
0035  * @note Connect to KJob::result(KJob*) to be notified when the job finished.
0036  * 
0037  * How to create DVcsJob:
0038  * @code
0039  * DVcsJob* job = new DVcsJob(vcsplugin);
0040  * 
0041  * job->setDirectory(workDir);
0042  * *job << "git-rev-parse";
0043  * foreach(const QString &arg, args) // *job << args can be used instead!
0044  *     *job << arg;
0045  * return job;
0046  * 
0047  * return error_cmd(i18n("could not create the job"));
0048  * @endcode
0049  * 
0050  * Usage example 1:
0051  * @code
0052  * VcsJob* j = add(QList<QUrl>() << a << b << c, IBasicVersionControl::Recursive);
0053  * DVcsJob* job = qobject_cast<DVCSjob*>(j);
0054  * connect(job, SIGNAL(result(KJob*)),
0055  *         this, SIGNAL(jobFinished(KJob*)));
0056  * ICore::self()->runController()->registerJob(job);
0057  * @endcode
0058  * 
0059  * Usage example 2, asynchronous:
0060  * @code
0061  * DVcsJob* branchJob = d->branch(repo, baseBranch, newBranch);
0062  * 
0063  * if (job->exec() && job->status() == KDevelop::VcsJob::JobSucceeded)
0064  *     return true;
0065  * else
0066  *     //something, maybe even just
0067  *     return false
0068  * @endcode
0069  * 
0070  * @author Robert Gruber <rgruber@users.sourceforge.net>
0071  * @author Evgeniy Ivanov <powerfox@kde.ru>
0072  */
0073 class KDEVPLATFORMVCS_EXPORT DVcsJob : public KDevelop::VcsJob
0074 {
0075     Q_OBJECT
0076 public:
0077     explicit DVcsJob(const QDir& workingDir, KDevelop::IPlugin* parent=nullptr, KDevelop::OutputJob::OutputJobVerbosity verbosity = KDevelop::OutputJob::Verbose);
0078     ~DVcsJob() override;
0079 
0080     /**
0081      * Returns current working directory.
0082      */
0083     QDir directory() const;
0084 
0085     /**
0086      * Call this method to set command to execute and its arguments.
0087      * @note Don't forget <<"one two"; is not the same as <<"one"<<"two"; Use one word(command, arg) per one QString!
0088      */
0089     DVcsJob& operator<<(const QString& arg);
0090 
0091     /**
0092      * Overloaded convenience function.
0093      * @param arg command or argument as utf8-encoded string
0094      * @see operator<<(const QString& arg).
0095      */
0096     DVcsJob& operator<<(const char* arg);
0097 
0098     /**
0099      * Overloaded convenience function.
0100      * @see operator<<(const QString& arg).
0101      */
0102     DVcsJob& operator<<(const QStringList& args);
0103     
0104     /**
0105      * Overloaded operator << for url's, can be used to pass files and
0106      * makes arguments absolute to the process working directory
0107      * 
0108      * Override if you need to treat paths before adding them as parameters.
0109      */
0110     virtual DVcsJob& operator<<(const QUrl& arg);
0111     
0112     /**
0113      * @see operator<<(const QUrl& arg).
0114      */
0115     DVcsJob& operator<<(const QList<QUrl>& args);
0116 
0117     /**
0118      * Call this method to start this job.
0119      * @note Default communication mode is KProcess::AllOutput.
0120      * @see Use setCommunicationMode() to override the default communication mode.
0121      */
0122     void start() override;
0123 
0124     /**
0125      * In some cases it's needed to specify the communication mode between the
0126      * process and the job object. This is for instance done for the "git status"
0127      * command. If stdout and stderr are processed as separate streams, their signals
0128      * do not always get emitted in correct order by KProcess, which will lead to a
0129      * screwed up output.
0130      * @note Default communication mode is KProcess::SeparateChannels.
0131      */
0132     void setCommunicationMode(KProcess::OutputChannelMode comm);
0133 
0134     /**
0135      * @return The command that is executed when calling start().
0136      */
0137     QStringList dvcsCommand() const;
0138 
0139     /**
0140      * @return The whole output of the job as a string. (Might fail on binary data)
0141      */
0142     QString output() const;
0143 
0144     /**
0145      * @return The whole binary output of the job
0146      */
0147     QByteArray rawOutput() const;
0148 
0149     /**
0150      * @return The whole binary stderr output of the job.
0151      */
0152     QByteArray errorOutput() const;
0153 
0154     /**
0155      * Ignore a non-zero exit code depending on @p ignore.
0156      */
0157     void setIgnoreError(bool ignore);
0158 
0159     // Begin:  KDevelop::VcsJob
0160 
0161     /** 
0162      * Sets executions results.
0163      * In most cases this method is used by IDVCSexecutor
0164      * @see fetchResults()
0165      */
0166     virtual void setResults(const QVariant &res);
0167 
0168     /**
0169      * Returns execution results stored in QVariant.
0170      * Mostly used in vcscommitdialog.
0171      * @see setResults(const QVariant &res)
0172      */
0173     QVariant fetchResults() override;
0174 
0175     /**
0176      * Returns JobStatus
0177      * @see KDevelop::VcsJob::JobStatus
0178      */
0179     KDevelop::VcsJob::JobStatus status() const override;
0180 
0181     /**
0182      * Returns pointer to IPlugin (which was used to create a job).
0183      */
0184     KDevelop::IPlugin* vcsPlugin() const override;
0185     // End:  KDevelop::VcsJob
0186     
0187     KProcess* process() const;
0188     
0189     void displayOutput(const QString& output);
0190 
0191 public Q_SLOTS:
0192     /**
0193      * Cancel slot.
0194      */
0195     void cancel();
0196 
0197 Q_SIGNALS:
0198     void readyForParsing(KDevelop::DVcsJob *job);
0199 
0200 protected Q_SLOTS:
0201     virtual void slotProcessError( QProcess::ProcessError );
0202 
0203 private Q_SLOTS:
0204     void slotProcessExited(int exitCode, QProcess::ExitStatus exitStatus);
0205     void slotReceivedStdout();
0206 
0207 protected:
0208     bool doKill() override;
0209 
0210 private:
0211     void jobIsReady();
0212 
0213 private:
0214     const QScopedPointer<class DVcsJobPrivate> d_ptr;
0215     Q_DECLARE_PRIVATE(DVcsJob)
0216 };
0217 
0218 }
0219 
0220 #endif