File indexing completed on 2024-05-19 15:46:09

0001 /*
0002     SPDX-FileCopyrightText: 2018 Morten Danielsen Volden
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "perforceimportmetadatawidget.h"
0008 
0009 #include <vcslocation.h>
0010 
0011 #include <QProcess>
0012 #include <QTemporaryDir>
0013 #include <QTextStream>
0014 #include <QStandardPaths>
0015 
0016 using namespace KDevelop;
0017 
0018 PerforceImportMetadataWidget::PerforceImportMetadataWidget(QWidget* parent)
0019     : VcsImportMetadataWidget(parent)
0020     , m_ui(new Ui::PerforceImportMetadataWidget)
0021 {
0022     m_ui->setupUi(this);
0023 
0024     m_ui->executableLoc->setText(QStringLiteral("/usr/bin/p4"));
0025     m_ui->p4portEdit->setText(QStringLiteral("perforce:1666"));
0026 
0027     QProcessEnvironment curEnv = QProcessEnvironment::systemEnvironment();
0028     m_ui->p4configEdit->setText(curEnv.value(QStringLiteral("P4CONFIG")));
0029     m_ui->p4portEdit->setText(curEnv.value(QStringLiteral("P4PORT")));
0030     m_ui->p4userEdit->setText(curEnv.value(QStringLiteral("P4USER")));
0031 
0032     const auto hasP4Config = curEnv.contains(QStringLiteral("P4CONFIG"));
0033     m_ui->radioButtonConfig->setChecked(hasP4Config);
0034     m_ui->radioButtonVariables->setChecked(!hasP4Config);
0035     m_ui->p4configEdit->setEnabled(hasP4Config);
0036 
0037     m_ui->sourceLoc->setEnabled(false);
0038     m_ui->sourceLoc->setMode(KFile::Directory);
0039 
0040     m_ui->errorMsg->setTextColor(QColor(255, 0, 0));
0041     m_ui->errorMsg->setReadOnly(true);
0042 
0043     m_ui->p4clientEdit->setEditable(true);
0044 
0045     connect(m_ui->p4clientEdit, QOverload<const QString&>::of(&KComboBox::returnPressed),
0046             this, &PerforceImportMetadataWidget::changed);
0047 
0048     connect(m_ui->radioButtonConfig, &QRadioButton::clicked, m_ui->p4configEdit, &QLineEdit::setEnabled);
0049     connect(m_ui->radioButtonVariables, &QRadioButton::clicked, m_ui->p4configEdit, &QLineEdit::setDisabled);
0050 
0051     connect(m_ui->testP4setupButton, &QPushButton::pressed, this, &PerforceImportMetadataWidget::testP4setup);
0052 }
0053 
0054 QUrl PerforceImportMetadataWidget::source() const
0055 {
0056     return m_ui->sourceLoc->url();
0057 }
0058 
0059 VcsLocation PerforceImportMetadataWidget::destination() const
0060 {
0061     VcsLocation dest;
0062     dest.setRepositoryServer(m_ui->p4portEdit->text());
0063     dest.setUserData(QVariant::fromValue(m_ui->p4userEdit->text()));
0064     dest.setRepositoryBranch(m_ui->p4clientEdit->itemText(0));
0065     return dest;
0066 }
0067 
0068 QString PerforceImportMetadataWidget::message() const
0069 {
0070     return QString();
0071     //TODO: return m_ui->message->toPlainText();
0072 }
0073 
0074 void PerforceImportMetadataWidget::setSourceLocation(const VcsLocation& url)
0075 {
0076     m_ui->sourceLoc->setUrl(url.localUrl());
0077 }
0078 
0079 void PerforceImportMetadataWidget::setSourceLocationEditable(bool enable)
0080 {
0081     m_ui->sourceLoc->setEnabled(enable);
0082 }
0083 
0084 void PerforceImportMetadataWidget::setMessage(const QString& message)
0085 {
0086     Q_UNUSED(message);
0087 
0088     //FIXME: correct ui field needs to be set
0089     //m_ui->message->setText(message);
0090 }
0091 
0092 bool PerforceImportMetadataWidget::hasValidData() const
0093 {
0094     // FIXME: It has valid data if testP4setup has completed correctly. AND client name has been set to something
0095     return !m_ui->p4clientEdit->itemText(0).isEmpty();
0096 }
0097 
0098 void PerforceImportMetadataWidget::testP4setup()
0099 {
0100     m_ui->errorMsg->clear();
0101     m_ui->p4clientEdit->clear();
0102 
0103     if (!validateP4executable())
0104         return;
0105 
0106     QDir execDir(m_ui->sourceLoc->url().toLocalFile());
0107     QTemporaryDir tmpDir;
0108     if (!execDir.exists())
0109         execDir.setPath(tmpDir.path());
0110 
0111     if(!validateP4port(execDir.path()))
0112         return;
0113 
0114     if(!validateP4user(execDir.path()))
0115         return;
0116 
0117     emit changed();
0118 }
0119 
0120 bool PerforceImportMetadataWidget::validateP4executable()
0121 {
0122     if (QStandardPaths::findExecutable(m_ui->executableLoc->url().toLocalFile()).isEmpty()) {
0123         m_ui->errorMsg->setText(
0124             i18n("Unable to find perforce executable. Is it installed on the system? Is it in your PATH?"));
0125         return false;
0126     }
0127     return true;
0128 }
0129 
0130 bool PerforceImportMetadataWidget::validateP4user(const QString&  projectDir) const
0131 {
0132     QProcess exec;
0133     QProcessEnvironment p4execEnvironment;
0134     p4execEnvironment.insert(QStringLiteral("P4PORT"), m_ui->p4portEdit->displayText());
0135     exec.setWorkingDirectory(projectDir);
0136     exec.setProcessEnvironment(p4execEnvironment);
0137     exec.start(m_ui->executableLoc->url().toLocalFile(), QStringList{QStringLiteral("workspaces"),
0138         QStringLiteral("-u"), m_ui->p4userEdit->text()}
0139     );
0140     exec.waitForFinished();
0141 
0142     const auto processStdout = QString::fromUtf8(exec.readAllStandardOutput());
0143     const auto processStderr = QString::fromUtf8(exec.readAllStandardError());
0144 
0145     //     std::cout << "Exited with code: " << exec.exitCode() << std::endl;
0146     //     std::cout << "Exited with stdout" << processStdout.toStdString() << std::endl;
0147     //     std::cout << "Exited with stderr" << processStderr.toStdString() << std::endl;
0148     if (exec.exitCode() != 0) {
0149         if(!processStderr.isEmpty()) {
0150             m_ui->errorMsg->setText(processStderr);
0151         } else {
0152             m_ui->errorMsg->setText(i18n("P4 Client failed with exit code: %1", exec.exitCode()));
0153         }
0154         return false;
0155     }
0156     if(!processStdout.isEmpty()) {
0157         const auto clientCmdOutput = processStdout.splitRef(QLatin1Char('\n'), Qt::SkipEmptyParts);
0158         QStringList clientItems;
0159         clientItems.reserve(clientCmdOutput.size());
0160         for (const auto& clientLine : clientCmdOutput) {
0161             const auto wordsInLine = clientLine.split(QLatin1Char(' '));
0162             // Client mvo_testkdevinteg 2017/05/22 root C:\P4repo 'Created by mvo. ' -- Line would be expected to look like so
0163             clientItems.append(wordsInLine.at(1).toString());
0164         }
0165         m_ui->p4clientEdit->addItems(clientItems);
0166     }
0167     return true;
0168 }
0169 
0170 bool PerforceImportMetadataWidget::validateP4port(const QString&  projectDir) const
0171 {
0172     QProcess exec;
0173     QProcessEnvironment p4execEnvironment;
0174     p4execEnvironment.insert(QStringLiteral("P4PORT"), m_ui->p4portEdit->displayText());
0175     QTextStream out(stdout);
0176     const auto& env = p4execEnvironment.toStringList();
0177     for (const QString& x : env) {
0178         out << x << QLatin1Char('\n');
0179     }
0180     out.flush();
0181 
0182     exec.setWorkingDirectory(projectDir);
0183     exec.setProcessEnvironment(p4execEnvironment);
0184     exec.start(m_ui->executableLoc->url().toLocalFile(), QStringList() << QStringLiteral("info"));
0185     exec.waitForFinished();
0186     //QString processStdout(exec.readAllStandardOutput());
0187     const auto processStderr = QString::fromUtf8(exec.readAllStandardError());
0188 
0189     //std::cout << "Exited with code: " << exec.exitCode() << std::endl;
0190     //std::cout << "Exited with stdout" << processStdout.toStdString() << std::endl;
0191     //std::cout << "Exited with stderr" << processStderr.toStdString() << std::endl;
0192     if (exec.exitCode() != 0) {
0193         if(!processStderr.isEmpty()) {
0194             m_ui->errorMsg->setText(processStderr);
0195         } else {
0196             m_ui->errorMsg->setText(i18n("P4 Client failed with error code: %1", exec.exitCode()));
0197         }
0198         return false;
0199     }
0200     return true;
0201 }
0202 
0203 #include "moc_perforceimportmetadatawidget.cpp"