1 /*
2     SPDX-FileCopyrightText: 2011 Vishesh Yadav <vishesh3y@gmail.com>
3 
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "servewrapper.h"
8 #include "hgwrapper.h"
9 
10 #include <QTextCodec>
11 
12 HgServeWrapper *HgServeWrapper::m_instance = nullptr;
13 
HgServeWrapper(QObject * parent)14 HgServeWrapper::HgServeWrapper(QObject *parent) :
15     QObject(parent)
16 {
17 }
18 
~HgServeWrapper()19 HgServeWrapper::~HgServeWrapper()
20 {
21     QMutableHashIterator<QString, ServerProcessType*> it(m_serverList);
22     while (it.hasNext()) {
23         it.next();
24         ///terminate server if not terminated already
25         if (it.value()->process.state() != QProcess::NotRunning) {
26             it.value()->process.terminate();
27         }
28         it.value()->deleteLater();
29         it.remove();
30     }
31 }
32 
instance()33 HgServeWrapper *HgServeWrapper::instance()
34 {
35     if (m_instance == nullptr) {
36         m_instance = new HgServeWrapper;
37     }
38     return m_instance;
39 }
40 
startServer(const QString & repoLocation,int portNumber)41 void HgServeWrapper::startServer(const QString &repoLocation, int portNumber)
42 {
43     ServerProcessType *server = m_serverList.value(repoLocation, nullptr);
44     if (server != nullptr) {
45         m_serverList.remove(repoLocation);
46         server->deleteLater();
47     }
48     server = new ServerProcessType;
49     m_serverList.insert(repoLocation, server);
50     server->port = portNumber;
51     server->process.setWorkingDirectory(HgWrapper::instance()->getBaseDir());
52 
53     connect(&server->process, &QProcess::started,
54             this, &HgServeWrapper::started);
55     connect(&server->process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
56             this, &HgServeWrapper::slotFinished);
57     connect(server, &ServerProcessType::readyReadLine,
58             this, &HgServeWrapper::readyReadLine);
59 
60     QStringList args;
61     args << QLatin1String("-oL");
62     args << QLatin1String("hg");
63     args << QLatin1String("serve");
64     args << QLatin1String("--port");
65     args << QString::number(portNumber);
66     server->process.start(QLatin1String("stdbuf"), args);
67     Q_EMIT readyReadLine(repoLocation,
68             i18n("## Starting Server ##"));
69     Q_EMIT readyReadLine(repoLocation,
70             QString("% hg serve --port %1").arg(portNumber));
71 }
72 
stopServer(const QString & repoLocation)73 void HgServeWrapper::stopServer(const QString &repoLocation)
74 {
75     ServerProcessType *server = m_serverList.value(repoLocation, nullptr);
76     if (server == nullptr) {
77         return;
78     }
79     server->process.terminate();
80 }
81 
running(const QString & repoLocation)82 bool HgServeWrapper::running(const QString &repoLocation)
83 {
84     ServerProcessType *server = m_serverList.value(repoLocation, nullptr);
85     if (server == nullptr) {
86         return false;
87     }
88     return ( server->process.state() == QProcess::Running ||
89              server->process.state() == QProcess::Starting);
90 }
91 
slotFinished(int exitCode,QProcess::ExitStatus status)92 void HgServeWrapper::slotFinished(int exitCode, QProcess::ExitStatus status)
93 {
94     if (exitCode == 0 && status == QProcess::NormalExit) {
95         Q_EMIT finished();
96     }
97     else {
98         Q_EMIT error();
99     }
100 }
101 
errorMessage(const QString & repoLocation)102 QString HgServeWrapper::errorMessage(const QString &repoLocation)
103 {
104     ServerProcessType *server = m_serverList.value(repoLocation, nullptr);
105     if (server == nullptr) {
106         return QString();
107     }
108     return QTextCodec::codecForLocale()->toUnicode(server->process.readAllStandardError());
109 }
110 
normalExit(const QString & repoLocation)111 bool HgServeWrapper::normalExit(const QString &repoLocation)
112 {
113     ServerProcessType *server = m_serverList.value(repoLocation, nullptr);
114     if (server == nullptr) {
115         return true;
116     }
117 
118     return (server->process.exitStatus() == QProcess::NormalExit &&
119             server->process.exitCode() == 0);
120 }
121 
cleanUnused()122 void HgServeWrapper::cleanUnused()
123 {
124     QMutableHashIterator<QString, ServerProcessType*> it(m_serverList);
125     while (it.hasNext()) {
126         it.next();
127         if (it.value()->process.state() == QProcess::NotRunning) {
128             it.value()->deleteLater();
129             it.remove();
130         }
131     }
132 }
133 
134 
135