2022-08-19 15:59:36 +02:00
|
|
|
// Copyright (C) 2017 The Qt Company Ltd.
|
|
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
2017-06-30 14:50:28 +02:00
|
|
|
|
|
|
|
|
#include "vcsbasediffeditorcontroller.h"
|
2022-07-12 15:40:47 +02:00
|
|
|
#include "vcsbaseclient.h"
|
2022-08-01 10:49:13 +02:00
|
|
|
#include "vcscommand.h"
|
2022-12-12 14:40:56 +01:00
|
|
|
#include "vcsplugin.h"
|
2017-06-30 14:50:28 +02:00
|
|
|
|
|
|
|
|
#include <coreplugin/editormanager/editormanager.h>
|
|
|
|
|
#include <coreplugin/progressmanager/progressmanager.h>
|
2022-08-01 10:49:13 +02:00
|
|
|
|
2022-12-12 14:40:56 +01:00
|
|
|
#include <utils/asynctask.h>
|
2022-03-02 04:12:25 +01:00
|
|
|
#include <utils/commandline.h>
|
2021-05-04 05:54:54 +02:00
|
|
|
#include <utils/environment.h>
|
2022-12-12 14:40:56 +01:00
|
|
|
#include <utils/futuresynchronizer.h>
|
2017-06-30 14:50:28 +02:00
|
|
|
#include <utils/qtcassert.h>
|
2022-12-12 14:40:56 +01:00
|
|
|
#include <utils/qtcprocess.h>
|
2017-06-30 14:50:28 +02:00
|
|
|
#include <utils/runextensions.h>
|
|
|
|
|
|
|
|
|
|
#include <QPointer>
|
|
|
|
|
|
|
|
|
|
using namespace DiffEditor;
|
|
|
|
|
using namespace Core;
|
2021-05-04 05:54:54 +02:00
|
|
|
using namespace Utils;
|
2017-06-30 14:50:28 +02:00
|
|
|
|
|
|
|
|
namespace VcsBase {
|
|
|
|
|
|
2022-12-12 14:40:56 +01:00
|
|
|
static void readPatch(QFutureInterface<QList<FileData>> &futureInterface, const QString &patch)
|
2017-06-30 14:50:28 +02:00
|
|
|
{
|
|
|
|
|
bool ok;
|
2017-06-30 16:06:36 +02:00
|
|
|
const QList<FileData> &fileDataList = DiffUtils::readPatch(patch, &ok, &futureInterface);
|
2017-06-30 14:50:28 +02:00
|
|
|
futureInterface.reportResult(fileDataList);
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-05 16:22:10 +02:00
|
|
|
/////////////////////
|
|
|
|
|
|
2017-06-30 14:50:28 +02:00
|
|
|
class VcsBaseDiffEditorControllerPrivate
|
|
|
|
|
{
|
|
|
|
|
public:
|
2020-02-04 08:11:50 +01:00
|
|
|
VcsBaseDiffEditorControllerPrivate(VcsBaseDiffEditorController *q) : q(q) {}
|
2017-06-30 14:50:28 +02:00
|
|
|
~VcsBaseDiffEditorControllerPrivate();
|
|
|
|
|
|
|
|
|
|
void processingFinished();
|
|
|
|
|
void processDiff(const QString &patch);
|
|
|
|
|
void cancelReload();
|
|
|
|
|
void commandFinished(bool success);
|
|
|
|
|
|
|
|
|
|
VcsBaseDiffEditorController *q;
|
2021-05-04 05:54:54 +02:00
|
|
|
Environment m_processEnvironment;
|
2021-08-17 12:26:10 +02:00
|
|
|
FilePath m_vcsBinary;
|
2020-02-04 08:11:50 +01:00
|
|
|
int m_vscTimeoutS;
|
2022-08-01 10:49:13 +02:00
|
|
|
QPointer<VcsCommand> m_command;
|
2017-07-05 16:22:10 +02:00
|
|
|
QFutureWatcher<QList<FileData>> *m_processWatcher = nullptr;
|
2017-06-30 14:50:28 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VcsBaseDiffEditorControllerPrivate::~VcsBaseDiffEditorControllerPrivate()
|
|
|
|
|
{
|
2022-09-16 11:45:28 +02:00
|
|
|
delete m_command;
|
2017-06-30 14:50:28 +02:00
|
|
|
cancelReload();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VcsBaseDiffEditorControllerPrivate::processingFinished()
|
|
|
|
|
{
|
2017-07-05 16:22:10 +02:00
|
|
|
QTC_ASSERT(m_processWatcher, return);
|
|
|
|
|
|
|
|
|
|
// success is false when the user clicked the cancel micro button
|
|
|
|
|
// inside the progress indicator
|
|
|
|
|
const bool success = !m_processWatcher->future().isCanceled();
|
2017-06-30 16:06:36 +02:00
|
|
|
const QList<FileData> fileDataList = success
|
2017-07-05 16:22:10 +02:00
|
|
|
? m_processWatcher->future().result() : QList<FileData>();
|
|
|
|
|
|
|
|
|
|
// Prevent direct deletion of m_processWatcher since
|
|
|
|
|
// processingFinished() is called directly by the m_processWatcher.
|
|
|
|
|
m_processWatcher->deleteLater();
|
|
|
|
|
m_processWatcher = nullptr;
|
2017-06-30 14:50:28 +02:00
|
|
|
|
2022-12-14 22:16:49 +01:00
|
|
|
q->setDiffFiles(fileDataList);
|
2017-06-30 16:06:36 +02:00
|
|
|
q->reloadFinished(success);
|
2017-06-30 14:50:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VcsBaseDiffEditorControllerPrivate::processDiff(const QString &patch)
|
|
|
|
|
{
|
2017-07-05 16:22:10 +02:00
|
|
|
cancelReload();
|
|
|
|
|
|
|
|
|
|
m_processWatcher = new QFutureWatcher<QList<FileData>>();
|
2017-06-30 14:50:28 +02:00
|
|
|
|
2022-09-16 11:45:28 +02:00
|
|
|
QObject::connect(m_processWatcher, &QFutureWatcherBase::finished,
|
|
|
|
|
q, [this] { processingFinished(); });
|
2017-07-05 16:22:10 +02:00
|
|
|
|
|
|
|
|
m_processWatcher->setFuture(Utils::runAsync(&readPatch, patch));
|
|
|
|
|
|
|
|
|
|
ProgressManager::addTask(m_processWatcher->future(),
|
2017-10-23 13:46:26 +02:00
|
|
|
VcsBaseDiffEditorController::tr("Processing diff"), "DiffEditor");
|
2017-06-30 14:50:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VcsBaseDiffEditorControllerPrivate::cancelReload()
|
|
|
|
|
{
|
2022-09-16 11:45:28 +02:00
|
|
|
m_command.clear();
|
2017-07-05 16:22:10 +02:00
|
|
|
|
|
|
|
|
if (m_processWatcher) {
|
|
|
|
|
// Cancel the running process without the further processingFinished()
|
|
|
|
|
// notification for this process.
|
|
|
|
|
m_processWatcher->future().cancel();
|
|
|
|
|
delete m_processWatcher;
|
|
|
|
|
m_processWatcher = nullptr;
|
2017-06-30 14:50:28 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VcsBaseDiffEditorControllerPrivate::commandFinished(bool success)
|
|
|
|
|
{
|
2022-09-19 08:27:41 +02:00
|
|
|
const QString output = m_command->cleanedStdOut();
|
2022-09-16 11:45:28 +02:00
|
|
|
// Don't delete here, as it is called from command finished signal.
|
|
|
|
|
// Clear it only, as we may call runCommand() again from inside processCommandOutput overload.
|
|
|
|
|
m_command.clear();
|
2017-07-05 16:22:10 +02:00
|
|
|
|
2017-06-30 14:50:28 +02:00
|
|
|
if (!success) {
|
|
|
|
|
cancelReload();
|
|
|
|
|
q->reloadFinished(success);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-19 08:27:41 +02:00
|
|
|
q->processCommandOutput(output);
|
2017-06-30 14:50:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/////////////////////
|
|
|
|
|
|
2020-02-04 08:11:50 +01:00
|
|
|
VcsBaseDiffEditorController::VcsBaseDiffEditorController(Core::IDocument *document)
|
2017-06-30 14:50:28 +02:00
|
|
|
: DiffEditorController(document)
|
2020-02-04 08:11:50 +01:00
|
|
|
, d(new VcsBaseDiffEditorControllerPrivate(this))
|
|
|
|
|
{}
|
2017-06-30 14:50:28 +02:00
|
|
|
|
|
|
|
|
VcsBaseDiffEditorController::~VcsBaseDiffEditorController()
|
|
|
|
|
{
|
|
|
|
|
delete d;
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-12 14:40:56 +01:00
|
|
|
void VcsBaseDiffEditorController::setupCommand(QtcProcess &process, const QStringList &args) const
|
|
|
|
|
{
|
|
|
|
|
process.setEnvironment(d->m_processEnvironment);
|
|
|
|
|
process.setWorkingDirectory(workingDirectory());
|
|
|
|
|
process.setCommand({d->m_vcsBinary, args});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VcsBaseDiffEditorController::setupDiffProcessor(AsyncTask<QList<FileData>> &processor,
|
|
|
|
|
const QString &patch) const
|
|
|
|
|
{
|
|
|
|
|
processor.setAsyncCallData(readPatch, patch);
|
|
|
|
|
processor.setFutureSynchronizer(Internal::VcsPlugin::futureSynchronizer());
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-05 19:08:53 +02:00
|
|
|
void VcsBaseDiffEditorController::runCommand(const QList<QStringList> &args, RunFlags flags, QTextCodec *codec)
|
2017-06-30 14:50:28 +02:00
|
|
|
{
|
2017-07-05 16:22:10 +02:00
|
|
|
// Cancel the possible ongoing reload without the commandFinished() nor
|
|
|
|
|
// processingFinished() notifications, as right after that
|
|
|
|
|
// we re-reload it from scratch. So no intermediate "Retrieving data failed."
|
|
|
|
|
// and "Waiting for data..." will be shown.
|
2022-09-16 11:45:28 +02:00
|
|
|
delete d->m_command;
|
2017-06-30 14:50:28 +02:00
|
|
|
d->cancelReload();
|
|
|
|
|
|
2022-07-12 15:40:47 +02:00
|
|
|
d->m_command = VcsBaseClient::createVcsCommand(workingDirectory(), d->m_processEnvironment);
|
2022-12-12 14:40:56 +01:00
|
|
|
d->m_command->setDisplayName(displayName());
|
2017-06-30 14:50:28 +02:00
|
|
|
d->m_command->setCodec(codec ? codec : EditorManager::defaultTextCodec());
|
2022-09-19 12:08:38 +02:00
|
|
|
connect(d->m_command.data(), &VcsCommand::done, this, [this] {
|
|
|
|
|
d->commandFinished(d->m_command->result() == ProcessResult::FinishedWithSuccess);
|
|
|
|
|
});
|
2017-06-30 14:50:28 +02:00
|
|
|
d->m_command->addFlags(flags);
|
|
|
|
|
|
|
|
|
|
for (const QStringList &arg : args) {
|
|
|
|
|
QTC_ASSERT(!arg.isEmpty(), continue);
|
|
|
|
|
|
2020-02-04 08:11:50 +01:00
|
|
|
d->m_command->addJob({d->m_vcsBinary, arg}, d->m_vscTimeoutS);
|
2017-06-30 14:50:28 +02:00
|
|
|
}
|
|
|
|
|
|
2022-09-21 07:06:14 +02:00
|
|
|
d->m_command->start();
|
2017-06-30 14:50:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VcsBaseDiffEditorController::processCommandOutput(const QString &output)
|
|
|
|
|
{
|
|
|
|
|
d->processDiff(output);
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-04 08:11:50 +01:00
|
|
|
void VcsBaseDiffEditorController::setVcsTimeoutS(int value)
|
|
|
|
|
{
|
|
|
|
|
d->m_vscTimeoutS = value;
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-12 17:23:56 +02:00
|
|
|
void VcsBaseDiffEditorController::setVcsBinary(const FilePath &path)
|
2020-02-04 08:11:50 +01:00
|
|
|
{
|
|
|
|
|
d->m_vcsBinary = path;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-04 05:54:54 +02:00
|
|
|
void VcsBaseDiffEditorController::setProcessEnvironment(const Environment &value)
|
2020-02-04 08:11:50 +01:00
|
|
|
{
|
|
|
|
|
d->m_processEnvironment = value;
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-30 14:50:28 +02:00
|
|
|
} // namespace VcsBase
|