diff options
author | Brian McGillion <brian.mcgillion@flander.com> | 2009-09-15 13:03:13 +0300 |
---|---|---|
committer | Brian McGillion <brian.mcgillion@flander.com> | 2009-09-21 12:29:31 +0300 |
commit | 989e1b5acfb2c97ceb9dc38f6f1d795362924a6c (patch) | |
tree | b1c8baf0106bac117c83c764833eca87bf806106 /src/plugins/mercurial/mercurialjobrunner.cpp | |
parent | 0915342d15b55b611c80993d524a91920255b436 (diff) | |
download | qt-creator-989e1b5acfb2c97ceb9dc38f6f1d795362924a6c.tar.gz |
Mercurial plugin, merge request with suggested fixes.
Diffstat (limited to 'src/plugins/mercurial/mercurialjobrunner.cpp')
-rw-r--r-- | src/plugins/mercurial/mercurialjobrunner.cpp | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/src/plugins/mercurial/mercurialjobrunner.cpp b/src/plugins/mercurial/mercurialjobrunner.cpp new file mode 100644 index 0000000000..2a3671f9fc --- /dev/null +++ b/src/plugins/mercurial/mercurialjobrunner.cpp @@ -0,0 +1,176 @@ +#include "mercurialjobrunner.h" +#include "mercurialplugin.h" +#include "mercurialoutputwindow.h" +#include "constants.h" +#include "mercurialsettings.h" + +#include <vcsbase/vcsbaseeditor.h> + +#include <QtCore/QProcess> +#include <QtCore/QTime> +#include <QtCore/QString> +#include <QtCore/QSettings> + +using namespace Mercurial::Internal; +using namespace Mercurial; + +HgTask::HgTask(const QString &repositoryRoot, QStringList &arguments, bool emitRaw) + : m_repositoryRoot(repositoryRoot), + arguments(arguments), + emitRaw(emitRaw), + editor(0) +{ +} + +HgTask::HgTask(const QString &repositoryRoot, QStringList &arguments, VCSBase::VCSBaseEditor *editor) + : m_repositoryRoot(repositoryRoot), + arguments(arguments), + emitRaw(false), + editor(editor) + +{ + +} + + +MercurialJobRunner::MercurialJobRunner() + : keepRunning(true) +{ + plugin = MercurialPlugin::instance(); + connect(this, SIGNAL(error(const QByteArray &)), plugin->outputPane(), SLOT(append(const QByteArray &))); + connect(this, SIGNAL(info(const QString &)), plugin->outputPane(), SLOT(append(const QString &))); +} + +MercurialJobRunner::~MercurialJobRunner() +{ + stop(); +} + +void MercurialJobRunner::stop() +{ + mutex.lock(); + keepRunning = false; + //Create a dummy task to break the cycle + QSharedPointer<HgTask> job(0); + jobs.enqueue(job); + waiter.wakeAll(); + mutex.unlock(); + + wait(); +} + +void MercurialJobRunner::restart() +{ + stop(); + mutex.lock(); + keepRunning = true; + mutex.unlock(); + start(); +} + +void MercurialJobRunner::getSettings() +{ + MercurialSettings *settings = MercurialPlugin::instance()->settings(); + binary = settings->binary(); + timeout = settings->timeout(); + standardArguments = settings->standardArguments(); +} + +void MercurialJobRunner::enqueueJob(QSharedPointer<HgTask> &job) +{ + mutex.lock(); + jobs.enqueue(job); + waiter.wakeAll(); + mutex.unlock(); +} + +void MercurialJobRunner::run() +{ + getSettings(); + forever { + mutex.lock(); + while (jobs.count() == 0) + waiter.wait(&mutex); + + if (!keepRunning) { + jobs.clear(); + mutex.unlock(); + return; + } + + QSharedPointer<HgTask> job = jobs.dequeue(); + mutex.unlock(); + + task(job); + } +} + +void MercurialJobRunner::task(QSharedPointer<HgTask> &job) +{ + HgTask *taskData = job.data(); + + if (taskData->shouldEmit()) + //Call the job's signal so the Initator of the job can process the data + //Because the QSharedPointer that holds the HgTask will go out of scope and hence be deleted + //we have to block and wait until the signal is delivered + connect(this, SIGNAL(output(const QByteArray&)), taskData, SIGNAL(rawData(const QByteArray&)), + Qt::BlockingQueuedConnection); + else if (taskData->displayEditor()) + //An editor has been created to display the data so send it there + connect(this, SIGNAL(output(const QByteArray&)), taskData->displayEditor(), SLOT(setPlainTextData(const QByteArray&))); + else + //Just output the data to the Mercurial output window + connect(this, SIGNAL(output(const QByteArray &)), plugin->outputPane(), SLOT(append(const QByteArray &))); + + QString time = QTime::currentTime().toString(QLatin1String("HH:mm")); + QString starting = tr("%1 Calling: %2 %3\n").arg(time, "hg", taskData->args().join(" ")); + + //infom the user of what we are going to try and perform + emit info(starting); + + if (Constants::debug) + qDebug() << Q_FUNC_INFO << "Repository root is " << taskData->repositoryRoot(); + + QProcess hgProcess; + hgProcess.setWorkingDirectory(taskData->repositoryRoot()); + + QStringList args = standardArguments; + args << taskData->args(); + + hgProcess.start(binary, args); + + if (!hgProcess.waitForStarted()) { + QByteArray errorArray(Constants::ERRORSTARTING); + emit error(errorArray); + return; + } + + hgProcess.closeWriteChannel(); + + if (!hgProcess.waitForFinished(timeout)) { + hgProcess.terminate(); + QByteArray errorArray(Constants::TIMEDOUT); + emit error(errorArray); + return; + } + + if ((hgProcess.exitStatus() == QProcess::NormalExit) && (hgProcess.exitCode() == 0)) { + QByteArray stdout = hgProcess.readAllStandardOutput(); + /* + * sometimes success means output is actually on error channel (stderr) + * e.g. "hg revert" outputs "no changes needed to 'file'" on stderr if file has not changed + * from revision specified + */ + if (stdout == "") + stdout = hgProcess.readAllStandardError(); + emit output(stdout); + } else { + QByteArray stderr = hgProcess.readAllStandardError(); + emit error(stderr); + } + + hgProcess.close(); + //the signal connection is to last only for the duration of a job/task. next time a new + //output signal connection must be made + disconnect(this, SIGNAL(output(const QByteArray &)), 0, 0); +} |