summaryrefslogtreecommitdiff
path: root/src/plugins/mercurial/mercurialjobrunner.cpp
diff options
context:
space:
mode:
authorBrian McGillion <brian.mcgillion@flander.com>2009-09-15 13:03:13 +0300
committerBrian McGillion <brian.mcgillion@flander.com>2009-09-21 12:29:31 +0300
commit989e1b5acfb2c97ceb9dc38f6f1d795362924a6c (patch)
treeb1c8baf0106bac117c83c764833eca87bf806106 /src/plugins/mercurial/mercurialjobrunner.cpp
parent0915342d15b55b611c80993d524a91920255b436 (diff)
downloadqt-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.cpp176
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);
+}