File indexing completed on 2025-01-05 05:14:49

0001 /*
0002 SPDX-FileCopyrightText: 2021 Hamed Masafi <hamed.masfi@gmail.com>
0003 
0004 SPDX-License-Identifier: GPL-3.0-or-later
0005 */
0006 
0007 #include "runnerdialog.h"
0008 
0009 #include "gitmanager.h"
0010 
0011 #include <KLocalizedString>
0012 #include <KMessageBox>
0013 #include <QInputDialog>
0014 
0015 #include "libkommitwidgets_appdebug.h"
0016 
0017 RunnerDialog::RunnerDialog(Git::Manager *git, QWidget *parent)
0018     : AppDialog(parent)
0019     , mGitProcess(new QProcess{this})
0020     , mGit(git)
0021 {
0022     setupUi(this);
0023 
0024     mGitProcess->setProgram(QStringLiteral("git"));
0025     mGitProcess->setWorkingDirectory(git->path());
0026 
0027     connect(mGitProcess, &QProcess::readyReadStandardOutput, this, &RunnerDialog::git_readyReadStandardOutput);
0028     connect(mGitProcess, &QProcess::readyReadStandardError, this, &RunnerDialog::git_readyReadStandardError);
0029     connect(pushButtonStop, &QAbstractButton::clicked, this, &RunnerDialog::slotPushButtonStopClicked);
0030     connect(pushButtonClose, &QAbstractButton::clicked, this, &RunnerDialog::slotPushButtonCloseClicked);
0031 
0032     connect(mGitProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &RunnerDialog::git_finished);
0033 
0034     pushButtonStop->hide();
0035     pushButtonClose->show();
0036 }
0037 
0038 void RunnerDialog::run(const QStringList &args)
0039 {
0040     progressBar->hide();
0041     mMode = RunByArgs;
0042     lineEditCommand->setText(QStringLiteral("git ") + args.join(QLatin1Char(' ')));
0043     textBrowser->append(lineEditCommand->text());
0044 
0045     textBrowser->append(QStringLiteral("$ ") + lineEditCommand->text());
0046     mGitProcess->setArguments(args);
0047     mGitProcess->start();
0048 
0049     pushButtonStop->show();
0050     pushButtonClose->hide();
0051 }
0052 
0053 void RunnerDialog::run(Git::AbstractCommand *command)
0054 {
0055     mMode = RunByCommand;
0056     if (command->supportWidget()) {
0057         auto w = command->createWidget();
0058         tabWidget->insertTab(0, w, i18n("View"));
0059         tabWidget->setCurrentIndex(0);
0060     }
0061 
0062     const auto args = command->generateArgs();
0063     lineEditCommand->setText(QStringLiteral("git ") + args.join(QLatin1Char(' ')));
0064 
0065     textBrowser->append(lineEditCommand->text());
0066     if (command->supportProgress()) {
0067         progressBar->show();
0068         connect(command, &Git::AbstractCommand::progressChanged, progressBar, &QProgressBar::setValue);
0069     } else {
0070         progressBar->hide();
0071     }
0072     mGitProcess->setArguments(args);
0073     mGitProcess->start();
0074     mCmd = command;
0075 
0076     mTimer.start();
0077 
0078     pushButtonStop->show();
0079     pushButtonClose->hide();
0080 }
0081 
0082 void RunnerDialog::git_readyReadStandardOutput()
0083 {
0084     const auto buffer = mGitProcess->readAllStandardOutput();
0085     mErrorOutput.append(buffer);
0086     textBrowser->append(buffer);
0087 
0088     if (mCmd && mCmd->supportProgress())
0089         mCmd->parseOutputSection(buffer, QByteArray());
0090 
0091     QRegularExpression r{"Username for '.*': "};
0092 
0093     if (r.match(buffer).hasMatch()) {
0094         QInputDialog::getText(this, buffer, "Username:");
0095     }
0096 }
0097 
0098 void RunnerDialog::git_readyReadStandardError()
0099 {
0100     const auto buffer = mGitProcess->readAllStandardError();
0101     mStandardOutput.append(buffer);
0102     textBrowser->append(buffer);
0103 
0104     if (mCmd && mCmd->supportProgress())
0105         mCmd->parseOutputSection(QByteArray(), buffer);
0106 }
0107 
0108 void RunnerDialog::git_finished(int exitCode, QProcess::ExitStatus exitStatus)
0109 {
0110     Q_UNUSED(exitCode)
0111     pushButtonStop->hide();
0112     pushButtonClose->show();
0113 
0114     if (mCmd)
0115         mCmd->parseOutputSection(mStandardOutput, mErrorOutput);
0116 
0117     bool isSuccessful;
0118     if (mCmd)
0119         isSuccessful = mCmd->parseOutput(mStandardOutput, mErrorOutput);
0120     else
0121         isSuccessful = exitStatus == QProcess::NormalExit;
0122 
0123     QString exitMessage;
0124 
0125     if (isSuccessful) {
0126         exitMessage = i18n("Process finished");
0127     } else {
0128         if (mCmd)
0129             KMessageBox::error(this, mCmd->errorMessage());
0130         else
0131             KMessageBox::error(this, i18n("The git process crashed"));
0132         exitMessage = i18n("Process finished with error");
0133     }
0134 
0135     textBrowser->append(
0136         QStringLiteral("%1: (Elapsed time: %2)").arg(exitMessage, QTime::fromMSecsSinceStartOfDay(mTimer.elapsed()).toString(QStringLiteral("HH:mm:ss"))));
0137 
0138     if (mAutoClose) {
0139         if (isSuccessful)
0140             accept();
0141         else
0142             setResult(QDialog::Rejected);
0143     }
0144 }
0145 
0146 void RunnerDialog::slotPushButtonCloseClicked()
0147 {
0148     close();
0149 }
0150 
0151 void RunnerDialog::slotPushButtonStopClicked()
0152 {
0153     if (mGitProcess->isOpen())
0154         mGitProcess->kill();
0155     close();
0156 }
0157 
0158 bool RunnerDialog::autoClose() const
0159 {
0160     return mAutoClose;
0161 }
0162 
0163 void RunnerDialog::setAutoClose(bool newAutoClose)
0164 {
0165     mAutoClose = newAutoClose;
0166 }
0167 
0168 #include "moc_runnerdialog.cpp"