[neon/kde/kate/Neon/stable] debian/patches: Revert "CVE-2022-23853"

Jonathan Esk-Riddell null at kde.org
Mon Jan 31 15:27:08 GMT 2022


Git commit d4e15cc31004d98ad1deaaf55f9b2214858b1712 by Jonathan Esk-Riddell.
Committed on 31/01/2022 at 15:27.
Pushed by jriddell into branch 'Neon/stable'.

Revert "CVE-2022-23853"

This reverts commit 115bcfcf534f30c76c9bfa1edca9e33f265833ca.

D  +0    -73   debian/patches/361dd43e42994829dbdb35e78fb7698d27cbb0e2.diff
D  +0    -58   debian/patches/6fc3bf6e5bd540e842e32c4a959c2158c8573be5.diff
D  +0    -882  debian/patches/7e08a58fb50d28ba96aedd5f5cd79a9479b4a0ad.diff
D  +0    -22   debian/patches/92a9c65e30b4b63b8b116eb5c8dcb1e1a2d867bc.diff
D  +0    -108  debian/patches/c5d66f3b70ae4778d6162564309aee95f643e7c9.diff
D  +0    -5    debian/patches/series

https://invent.kde.org/neon/kde/kate/commit/d4e15cc31004d98ad1deaaf55f9b2214858b1712

diff --git a/debian/patches/361dd43e42994829dbdb35e78fb7698d27cbb0e2.diff b/debian/patches/361dd43e42994829dbdb35e78fb7698d27cbb0e2.diff
deleted file mode 100644
index aee97fe..0000000
--- a/debian/patches/361dd43e42994829dbdb35e78fb7698d27cbb0e2.diff
+++ /dev/null
@@ -1,73 +0,0 @@
-diff --git a/addons/lspclient/lspclientprotocol.h b/addons/lspclient/lspclientprotocol.h
-index 0fb7f4485e6a6e819e1065882f021cb2bb2649d8..9de0ec5115567975ad57f92adebeb0ebe35d4c0e 100644
---- a/addons/lspclient/lspclientprotocol.h
-+++ b/addons/lspclient/lspclientprotocol.h
-@@ -21,6 +21,8 @@
- #include <KTextEditor/Cursor>
- #include <KTextEditor/Range>
- 
-+#include <optional>
-+
- // Following types roughly follow the types/interfaces as defined in LSP protocol spec
- // although some deviation may arise where it has been deemed useful
- // Moreover, to avoid introducing a custom 'optional' type, absence of an optional
-@@ -51,6 +53,16 @@ struct LSPResponseError {
- 
- enum class LSPDocumentSyncKind { None = 0, Full = 1, Incremental = 2 };
- 
-+struct LSPSaveOptions {
-+    bool includeText = false;
-+};
-+
-+// only used parts for now
-+struct LSPTextDocumentSyncOptions {
-+    LSPDocumentSyncKind change = LSPDocumentSyncKind::None;
-+    std::optional<LSPSaveOptions> save;
-+};
-+
- struct LSPCompletionOptions {
-     bool provider = false;
-     bool resolveProvider = false;
-@@ -81,7 +93,7 @@ struct LSPWorkspaceFoldersServerCapabilities {
- };
- 
- struct LSPServerCapabilities {
--    LSPDocumentSyncKind textDocumentSync = LSPDocumentSyncKind::None;
-+    LSPTextDocumentSyncOptions textDocumentSync;
-     bool hoverProvider = false;
-     LSPCompletionOptions completionProvider;
-     LSPSignatureHelpOptions signatureHelpProvider;
-diff --git a/addons/lspclient/lspclientserver.cpp b/addons/lspclient/lspclientserver.cpp
-index 8739d46c918d0d2b5bdff9f997434f13a0277404..a7094fde22e11ff8a138f7a634a90a45a2cbf38e 100644
---- a/addons/lspclient/lspclientserver.cpp
-+++ b/addons/lspclient/lspclientserver.cpp
-@@ -344,8 +344,15 @@ static void from_json(LSPServerCapabilities &caps, const QJsonObject &json)
-     };
- 
-     auto sync = json.value(QStringLiteral("textDocumentSync"));
--    caps.textDocumentSync = static_cast<LSPDocumentSyncKind>(
-+    caps.textDocumentSync.change = static_cast<LSPDocumentSyncKind>(
-         (sync.isObject() ? sync.toObject().value(QStringLiteral("change")) : sync).toInt(static_cast<int>(LSPDocumentSyncKind::None)));
-+    if (sync.isObject()) {
-+        auto syncObject = sync.toObject();
-+        auto save = syncObject.value(QStringLiteral("save"));
-+        if (save.isObject() || save.toBool()) {
-+            caps.textDocumentSync.save = {save.toObject().value(QStringLiteral("includeText")).toBool()};
-+        }
-+    }
-     caps.hoverProvider = toBoolOrObject(json.value(QStringLiteral("hoverProvider")));
-     from_json(caps.completionProvider, json.value(QStringLiteral("completionProvider")));
-     from_json(caps.signatureHelpProvider, json.value(QStringLiteral("signatureHelpProvider")));
-diff --git a/addons/lspclient/lspclientservermanager.cpp b/addons/lspclient/lspclientservermanager.cpp
-index 1fbcf928f45337d564253e14870bc339a1155d2a..1e03801ea0609a2accf6e3fc181c0f1e627fe1bd 100644
---- a/addons/lspclient/lspclientservermanager.cpp
-+++ b/addons/lspclient/lspclientservermanager.cpp
-@@ -931,7 +931,7 @@ private:
-         auto it = m_docs.find(doc);
-         if (it != m_docs.end() && it->server) {
-             const auto &caps = it->server->capabilities();
--            if (caps.textDocumentSync == LSPDocumentSyncKind::Incremental) {
-+            if (caps.textDocumentSync.change == LSPDocumentSyncKind::Incremental) {
-                 return &(*it);
-             }
-         }
diff --git a/debian/patches/6fc3bf6e5bd540e842e32c4a959c2158c8573be5.diff b/debian/patches/6fc3bf6e5bd540e842e32c4a959c2158c8573be5.diff
deleted file mode 100644
index 5ca3c0f..0000000
--- a/debian/patches/6fc3bf6e5bd540e842e32c4a959c2158c8573be5.diff
+++ /dev/null
@@ -1,58 +0,0 @@
-diff --git a/addons/lspclient/lspclientserver.cpp b/addons/lspclient/lspclientserver.cpp
-index a7094fde22e11ff8a138f7a634a90a45a2cbf38e..9fb5844cdd456b91978ebfc9261b067c0921140b 100644
---- a/addons/lspclient/lspclientserver.cpp
-+++ b/addons/lspclient/lspclientserver.cpp
-@@ -1255,7 +1255,8 @@ private:
-                                             {QStringLiteral("documentSymbol"), QJsonObject{{QStringLiteral("hierarchicalDocumentSymbolSupport"), true}} },
-                                             {QStringLiteral("publishDiagnostics"), QJsonObject{{QStringLiteral("relatedInformation"), true}}},
-                                             {QStringLiteral("codeAction"), codeAction},
--                                            {QStringLiteral("semanticTokens"), semanticTokens}
-+                                            {QStringLiteral("semanticTokens"), semanticTokens},
-+                                            {QStringLiteral("synchronization"), QJsonObject{{QStringLiteral("didSave"), true}}},
-                                         },
-                                   },
-                                   {QStringLiteral("window"),
-@@ -1475,7 +1476,9 @@ public:
-     void didSave(const QUrl &document, const QString &text)
-     {
-         auto params = textDocumentParams(document);
--        params[QStringLiteral("text")] = text;
-+        if (!text.isNull()) {
-+            params[QStringLiteral("text")] = text;
-+        }
-         send(init_request(QStringLiteral("textDocument/didSave"), params));
-     }
- 
-diff --git a/addons/lspclient/lspclientservermanager.cpp b/addons/lspclient/lspclientservermanager.cpp
-index 1e03801ea0609a2accf6e3fc181c0f1e627fe1bd..551926e23175560f912e9a9de86f1a8cf58e7e05 100644
---- a/addons/lspclient/lspclientservermanager.cpp
-+++ b/addons/lspclient/lspclientservermanager.cpp
-@@ -833,6 +833,7 @@ private:
-             connect(doc, &KTextEditor::Document::aboutToClose, this, &self_type::untrack, Qt::UniqueConnection);
-             connect(doc, &KTextEditor::Document::destroyed, this, &self_type::untrack, Qt::UniqueConnection);
-             connect(doc, &KTextEditor::Document::textChanged, this, &self_type::onTextChanged, Qt::UniqueConnection);
-+            connect(doc, &KTextEditor::Document::documentSavedOrUploaded, this, &self_type::onDocumentSaved, Qt::UniqueConnection);
-             // in case of incremental change
-             connect(doc, &KTextEditor::Document::textInserted, this, &self_type::onTextInserted, Qt::UniqueConnection);
-             connect(doc, &KTextEditor::Document::textRemoved, this, &self_type::onTextRemoved, Qt::UniqueConnection);
-@@ -976,6 +977,20 @@ private:
-         }
-     }
- 
-+    void onDocumentSaved(KTextEditor::Document *doc, bool saveAs)
-+    {
-+        if (!saveAs) {
-+            auto it = m_docs.find(doc);
-+            if (it != m_docs.end() && it->server) {
-+                auto server = it->server;
-+                const auto &saveOptions = server->capabilities().textDocumentSync.save;
-+                if (saveOptions) {
-+                    server->didSave(doc->url(), saveOptions->includeText ? doc->text() : QString());
-+                }
-+            }
-+        }
-+    }
-+
-     void onMessage(bool isLog, const LSPLogMessageParams &params)
-     {
-         // determine server description
diff --git a/debian/patches/7e08a58fb50d28ba96aedd5f5cd79a9479b4a0ad.diff b/debian/patches/7e08a58fb50d28ba96aedd5f5cd79a9479b4a0ad.diff
deleted file mode 100644
index 2bd8cd1..0000000
--- a/debian/patches/7e08a58fb50d28ba96aedd5f5cd79a9479b4a0ad.diff
+++ /dev/null
@@ -1,882 +0,0 @@
-diff --git a/addons/compiler-explorer/compiledbreader.cpp b/addons/compiler-explorer/compiledbreader.cpp
-index 74e83638e356f9b9820be1ea2e9d0c0a02201e05..ab9ebc48373b974ade28c34a2b4a51ff58d0656d 100644
---- a/addons/compiler-explorer/compiledbreader.cpp
-+++ b/addons/compiler-explorer/compiledbreader.cpp
-@@ -21,7 +21,9 @@ std::optional<QString> getDotGitPath(const QString &repo)
- {
-     /* This call is intentionally blocking because we need git path for everything else */
-     QProcess git;
--    setupGitProcess(git, repo, {QStringLiteral("rev-parse"), QStringLiteral("--absolute-git-dir")});
-+    if (!setupGitProcess(git, repo, {QStringLiteral("rev-parse"), QStringLiteral("--absolute-git-dir")})) {
-+        return std::nullopt;
-+    }
-     git.start(QProcess::ReadOnly);
-     if (git.waitForStarted() && git.waitForFinished(-1)) {
-         if (git.exitStatus() != QProcess::NormalExit || git.exitCode() != 0) {
-diff --git a/addons/externaltools/katetoolrunner.cpp b/addons/externaltools/katetoolrunner.cpp
-index 10a5d722626c50e02ec39b09549288329bc4bf77..e14940ad7ed827c7da2b960081c2fe31b7d0c316 100644
---- a/addons/externaltools/katetoolrunner.cpp
-+++ b/addons/externaltools/katetoolrunner.cpp
-@@ -14,6 +14,7 @@
- #include <KTextEditor/View>
- #include <QFileInfo>
- #include <QRegularExpression>
-+#include <QStandardPaths>
- 
- KateToolRunner::KateToolRunner(std::unique_ptr<KateExternalTool> tool, KTextEditor::View *view, QObject *parent)
-     : QObject(parent)
-@@ -40,6 +41,12 @@ KateExternalTool *KateToolRunner::tool() const
- 
- void KateToolRunner::run()
- {
-+    // always only execute the tool from PATH
-+    const auto fullExecutable = QStandardPaths::findExecutable(m_tool->executable);
-+    if (fullExecutable.isEmpty()) {
-+        return;
-+    }
-+
-     if (!m_tool->workingDir.isEmpty()) {
-         m_process->setWorkingDirectory(m_tool->workingDir);
-     } else if (m_view) {
-@@ -72,7 +79,7 @@ void KateToolRunner::run()
-     });
- 
-     const QStringList args = KShell::splitArgs(m_tool->arguments);
--    m_process->start(m_tool->executable, args);
-+    m_process->start(fullExecutable, args);
- }
- 
- void KateToolRunner::waitForFinished()
-diff --git a/addons/gdbplugin/debugview.cpp b/addons/gdbplugin/debugview.cpp
-index 9505daa25bb346a99ab3383e2f33663d31a32f27..d8c868d7aeb3466cec7f83a8c3925ecedff32960 100644
---- a/addons/gdbplugin/debugview.cpp
-+++ b/addons/gdbplugin/debugview.cpp
-@@ -12,7 +12,9 @@
- #include "debugview.h"
- 
- #include <QFile>
-+#include <QFileInfo>
- #include <QRegularExpression>
-+#include <QStandardPaths>
- #include <QTimer>
- 
- #include <KLocalizedString>
-@@ -48,7 +50,20 @@ void DebugView::runDebugger(const GDBTargetConf &conf, const QStringList &ioFifo
-     if (conf.executable.isEmpty()) {
-         return;
-     }
-+
-     m_targetConf = conf;
-+
-+    // no chance if no debugger configured
-+    if (m_targetConf.gdbCmd.isEmpty()) {
-+        return;
-+    }
-+
-+    // only run debugger from PATH or the absolute executable path we specified
-+    const auto fullExecutable = QFileInfo(m_targetConf.gdbCmd).isAbsolute() ? m_targetConf.gdbCmd : QStandardPaths::findExecutable(m_targetConf.gdbCmd);
-+    if (fullExecutable.isEmpty()) {
-+        return;
-+    }
-+
-     if (ioFifos.size() == 3) {
-         m_ioPipeString = QStringLiteral("< %1 1> %2 2> %3").arg(ioFifos[0], ioFifos[1], ioFifos[2]);
-     }
-@@ -69,7 +84,7 @@ void DebugView::runDebugger(const GDBTargetConf &conf, const QStringList &ioFifo
- 
-         connect(&m_debugProcess, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), this, &DebugView::slotDebugFinished);
- 
--        m_debugProcess.start(m_targetConf.gdbCmd, QStringList());
-+        m_debugProcess.start(fullExecutable, QStringList());
- 
-         m_nextCommands << QStringLiteral("set pagination off");
-         m_state = ready;
-diff --git a/addons/git-blame/commitfilesview.cpp b/addons/git-blame/commitfilesview.cpp
-index 26e484a4a44bd2db1f110cce3fb944e9a474b504..667b423b256a1988fa8826a1a3186579ef71d210 100644
---- a/addons/git-blame/commitfilesview.cpp
-+++ b/addons/git-blame/commitfilesview.cpp
-@@ -263,7 +263,9 @@ static void createFileTree(QStandardItem *parent, const QString &basePath, const
- static std::optional<QString> getGitCmdOutput(const QString &workDir, const QStringList &args)
- {
-     QProcess git;
--    setupGitProcess(git, workDir, args);
-+    if (!setupGitProcess(git, workDir, args)) {
-+        return {};
-+    }
-     git.start(QProcess::ReadOnly);
-     if (git.waitForStarted() && git.waitForFinished(-1)) {
-         if (git.exitStatus() != QProcess::NormalExit || git.exitCode() != 0) {
-@@ -365,9 +367,12 @@ void CommitDiffTreeView::openCommit(const QString &hash, const QString &filePath
-     m_commitHash = hash;
- 
-     QProcess *git = new QProcess(this);
--    setupGitProcess(*git,
--                    QFileInfo(filePath).absolutePath(),
--                    {QStringLiteral("show"), hash, QStringLiteral("--numstat"), QStringLiteral("--pretty=oneline"), QStringLiteral("-z")});
-+    if (!setupGitProcess(*git,
-+                         QFileInfo(filePath).absolutePath(),
-+                         {QStringLiteral("show"), hash, QStringLiteral("--numstat"), QStringLiteral("--pretty=oneline"), QStringLiteral("-z")})) {
-+        delete git;
-+        return;
-+    }
-     connect(git, &QProcess::finished, this, [this, git, filePath](int e, QProcess::ExitStatus s) {
-         git->deleteLater();
-         if (e != 0 || s != QProcess::NormalExit) {
-@@ -440,7 +445,9 @@ void CommitDiffTreeView::showDiff(const QModelIndex &idx)
- {
-     const QString file = idx.data(FileItem::Path).toString();
-     QProcess git;
--    setupGitProcess(git, m_gitDir, {QStringLiteral("show"), m_commitHash, QStringLiteral("--"), file});
-+    if (!setupGitProcess(git, m_gitDir, {QStringLiteral("show"), m_commitHash, QStringLiteral("--"), file})) {
-+        return;
-+    }
-     git.start(QProcess::ReadOnly);
- 
-     if (git.waitForStarted() && git.waitForFinished(-1)) {
-diff --git a/addons/git-blame/kategitblameplugin.cpp b/addons/git-blame/kategitblameplugin.cpp
-index d0354cc759b5054fca0a0d275ba29baf9d0bee7e..ae0f8c10664533720bf3bef648dd7558b0ffd0dc 100644
---- a/addons/git-blame/kategitblameplugin.cpp
-+++ b/addons/git-blame/kategitblameplugin.cpp
-@@ -255,7 +255,9 @@ void KateGitBlamePluginView::startBlameProcess(const QUrl &url)
-     QDir dir{url.toLocalFile()};
-     dir.cdUp();
- 
--    setupGitProcess(m_blameInfoProc, dir.absolutePath(), {QStringLiteral("blame"), QStringLiteral("-p"), QStringLiteral("./%1").arg(fileName)});
-+    if (!setupGitProcess(m_blameInfoProc, dir.absolutePath(), {QStringLiteral("blame"), QStringLiteral("-p"), QStringLiteral("./%1").arg(fileName)})) {
-+        return;
-+    }
-     m_blameInfoProc.start(QIODevice::ReadOnly);
-     m_blameUrl = url;
- }
-@@ -270,7 +272,9 @@ void KateGitBlamePluginView::startShowProcess(const QUrl &url, const QString &ha
-     QDir dir{url.toLocalFile()};
-     dir.cdUp();
- 
--    setupGitProcess(m_showProc, dir.absolutePath(), {QStringLiteral("show"), hash, QStringLiteral("--numstat")});
-+    if (!setupGitProcess(m_showProc, dir.absolutePath(), {QStringLiteral("show"), hash, QStringLiteral("--numstat")})) {
-+        return;
-+    }
-     m_showProc.start(QIODevice::ReadOnly);
- }
- 
-diff --git a/addons/kate-ctags/gotosymbolmodel.cpp b/addons/kate-ctags/gotosymbolmodel.cpp
-index 6c547e3795a42612afb6031b68887fae3d8385ea..0c116090fe106996599c7f33cf2942a503877435 100644
---- a/addons/kate-ctags/gotosymbolmodel.cpp
-+++ b/addons/kate-ctags/gotosymbolmodel.cpp
-@@ -8,6 +8,7 @@
- #include <KLocalizedString>
- #include <QDebug>
- #include <QProcess>
-+#include <QStandardPaths>
- 
- GotoSymbolModel::GotoSymbolModel(QObject *parent)
-     : QAbstractTableModel(parent)
-@@ -58,16 +59,24 @@ void GotoSymbolModel::refresh(const QString &filePath)
-     m_rows.clear();
-     endResetModel();
- 
-+    // only use ctags from PATH
-+    static const auto fullExecutablePath = QStandardPaths::findExecutable(QStringLiteral("ctags"));
-+    if (fullExecutablePath.isEmpty()) {
-+        beginResetModel();
-+        m_rows.append(SymbolItem{i18n("CTags executable not found."), -1, QIcon()});
-+        endResetModel();
-+        return;
-+    }
-+
-     QProcess p;
--    p.start(QStringLiteral("ctags"), {QStringLiteral("-x"), QStringLiteral("--_xformat=%{name}%{signature}\t%{kind}\t%{line}"), filePath});
-+    p.start(fullExecutablePath, {QStringLiteral("-x"), QStringLiteral("--_xformat=%{name}%{signature}\t%{kind}\t%{line}"), filePath});
- 
-     QByteArray out;
-     if (p.waitForFinished()) {
-         out = p.readAllStandardOutput();
-     } else {
--        qWarning() << "Ctags failed";
-         beginResetModel();
--        m_rows.append(SymbolItem{i18n("CTags executable not found."), -1, QIcon()});
-+        m_rows.append(SymbolItem{i18n("CTags executable failed to execute."), -1, QIcon()});
-         endResetModel();
-         return;
-     }
-diff --git a/addons/project/comparebranchesview.cpp b/addons/project/comparebranchesview.cpp
-index 48d1d26339e1b58c69483d7f8f13dbe7c056e8e0..7cf585f66bacc5ec028399c7f37f3ebac0c4d096 100644
---- a/addons/project/comparebranchesview.cpp
-+++ b/addons/project/comparebranchesview.cpp
-@@ -158,7 +158,9 @@ void CompareBranchesView::showDiff(const QModelIndex &idx)
- {
-     auto file = idx.data(Qt::UserRole).toString().remove(m_gitDir + QLatin1Char('/'));
-     QProcess git;
--    setupGitProcess(git, m_gitDir, {QStringLiteral("diff"), QStringLiteral("%1...%2").arg(m_fromBr).arg(m_toBr), QStringLiteral("--"), file});
-+    if (!setupGitProcess(git, m_gitDir, {QStringLiteral("diff"), QStringLiteral("%1...%2").arg(m_fromBr).arg(m_toBr), QStringLiteral("--"), file})) {
-+        return;
-+    }
-     git.start(QProcess::ReadOnly);
- 
-     if (git.waitForStarted() && git.waitForFinished(-1)) {
-diff --git a/addons/project/filehistorywidget.cpp b/addons/project/filehistorywidget.cpp
-index 626016a6b8556d5a3e3b86141990c06d7d406edb..14857e17847dceafe6db06b9b46cc1e56f5f0b35 100644
---- a/addons/project/filehistorywidget.cpp
-+++ b/addons/project/filehistorywidget.cpp
-@@ -231,9 +231,12 @@ FileHistoryWidget::~FileHistoryWidget()
- // git log --format=%H%n%aN%n%aE%n%at%n%ct%n%P%n%B --author-date-order
- void FileHistoryWidget::getFileHistory(const QString &file)
- {
--    setupGitProcess(m_git,
--                    QFileInfo(file).absolutePath(),
--                    {QStringLiteral("log"), QStringLiteral("--format=%H%n%aN%n%aE%n%at%n%ct%n%P%n%B"), QStringLiteral("-z"), file});
-+    if (!setupGitProcess(m_git,
-+                         QFileInfo(file).absolutePath(),
-+                         {QStringLiteral("log"), QStringLiteral("--format=%H%n%aN%n%aE%n%at%n%ct%n%P%n%B"), QStringLiteral("-z"), file})) {
-+        Q_EMIT errorMessage(i18n("Failed to get file history: git executable not found in PATH"), true);
-+        return;
-+    }
- 
-     connect(&m_git, &QProcess::readyReadStandardOutput, this, [this] {
-         auto commits = parseCommits(m_git.readAllStandardOutput().split(0x00));
-@@ -258,7 +261,10 @@ void FileHistoryWidget::itemClicked(const QModelIndex &idx)
- 
-     const auto commit = idx.data(CommitListModel::CommitRole).value<Commit>();
- 
--    setupGitProcess(git, fi.absolutePath(), {QStringLiteral("show"), QString::fromUtf8(commit.hash), QStringLiteral("--"), m_file});
-+    if (!setupGitProcess(git, fi.absolutePath(), {QStringLiteral("show"), QString::fromUtf8(commit.hash), QStringLiteral("--"), m_file})) {
-+        return;
-+    }
-+
-     git.start(QProcess::ReadOnly);
-     if (git.waitForStarted() && git.waitForFinished(-1)) {
-         if (git.exitStatus() != QProcess::NormalExit || git.exitCode() != 0) {
-diff --git a/addons/project/git/gitutils.cpp b/addons/project/git/gitutils.cpp
-index ea8dd8823e640a409821fe8afbe27a7d5ea7cd46..8b494c16f1b7a368de58ae5a8a545eb2701a7327 100644
---- a/addons/project/git/gitutils.cpp
-+++ b/addons/project/git/gitutils.cpp
-@@ -15,7 +15,10 @@
- bool GitUtils::isGitRepo(const QString &repo)
- {
-     QProcess git;
--    setupGitProcess(git, repo, {QStringLiteral("rev-parse"), QStringLiteral("--is-inside-work-tree")});
-+    if (!setupGitProcess(git, repo, {QStringLiteral("rev-parse"), QStringLiteral("--is-inside-work-tree")})) {
-+        return false;
-+    }
-+
-     git.start(QProcess::ReadOnly);
-     if (git.waitForStarted() && git.waitForFinished(-1)) {
-         return git.readAll().trimmed() == "true";
-@@ -27,7 +30,10 @@ std::optional<QString> GitUtils::getDotGitPath(const QString &repo)
- {
-     /* This call is intentionally blocking because we need git path for everything else */
-     QProcess git;
--    setupGitProcess(git, repo, {QStringLiteral("rev-parse"), QStringLiteral("--absolute-git-dir")});
-+    if (!setupGitProcess(git, repo, {QStringLiteral("rev-parse"), QStringLiteral("--absolute-git-dir")})) {
-+        return std::nullopt;
-+    }
-+
-     git.start(QProcess::ReadOnly);
-     if (git.waitForStarted() && git.waitForFinished(-1)) {
-         if (git.exitStatus() != QProcess::NormalExit || git.exitCode() != 0) {
-@@ -57,7 +63,10 @@ QString GitUtils::getCurrentBranchName(const QString &repo)
- 
-     for (int i = 0; i < 3; ++i) {
-         QProcess git;
--        setupGitProcess(git, repo, argsList[i]);
-+        if (!setupGitProcess(git, repo, argsList[i])) {
-+            return QString();
-+        }
-+
-         git.start(QProcess::ReadOnly);
-         if (git.waitForStarted() && git.waitForFinished(-1)) {
-             if (git.exitStatus() == QProcess::NormalExit && git.exitCode() == 0) {
-@@ -73,7 +82,10 @@ QString GitUtils::getCurrentBranchName(const QString &repo)
- GitUtils::CheckoutResult GitUtils::checkoutBranch(const QString &repo, const QString &branch)
- {
-     QProcess git;
--    setupGitProcess(git, repo, {QStringLiteral("checkout"), branch});
-+    if (!setupGitProcess(git, repo, {QStringLiteral("checkout"), branch})) {
-+        return CheckoutResult{};
-+    }
-+
-     git.start(QProcess::ReadOnly);
-     CheckoutResult res;
-     res.branch = branch;
-@@ -91,7 +103,11 @@ GitUtils::CheckoutResult GitUtils::checkoutNewBranch(const QString &repo, const
-     if (!fromBranch.isEmpty()) {
-         args.append(fromBranch);
-     }
--    setupGitProcess(git, repo, args);
-+
-+    if (!setupGitProcess(git, repo, args)) {
-+        return CheckoutResult{};
-+    }
-+
-     git.start(QProcess::ReadOnly);
-     CheckoutResult res;
-     res.branch = newBranch;
-@@ -132,7 +148,10 @@ QVector<GitUtils::Branch> GitUtils::getAllBranchesAndTags(const QString &repo, R
-         args.append(QStringLiteral("--sort=-taggerdate"));
-     }
- 
--    setupGitProcess(git, repo, args);
-+    if (!setupGitProcess(git, repo, args)) {
-+        return {};
-+    }
-+
-     git.start(QProcess::ReadOnly);
-     QVector<Branch> branches;
-     if (git.waitForStarted() && git.waitForFinished(-1)) {
-@@ -166,7 +185,10 @@ std::pair<QString, QString> GitUtils::getLastCommitMessage(const QString &repo)
- {
-     // git log -1 --pretty=%B
-     QProcess git;
--    setupGitProcess(git, repo, {QStringLiteral("log"), QStringLiteral("-1"), QStringLiteral("--pretty=%B")});
-+    if (!setupGitProcess(git, repo, {QStringLiteral("log"), QStringLiteral("-1"), QStringLiteral("--pretty=%B")})) {
-+        return {};
-+    }
-+
-     git.start(QProcess::ReadOnly);
-     if (git.waitForStarted() && git.waitForFinished(-1)) {
-         if (git.exitCode() != 0 || git.exitStatus() != QProcess::NormalExit) {
-@@ -197,7 +219,10 @@ GitUtils::Result GitUtils::deleteBranches(const QStringList &branches, const QSt
-     args << branches;
- 
-     QProcess git;
--    setupGitProcess(git, repo, args);
-+    if (!setupGitProcess(git, repo, args)) {
-+        return {};
-+    }
-+
-     git.start(QProcess::ReadOnly);
-     if (git.waitForStarted() && git.waitForFinished(-1)) {
-         QString out = QString::fromLatin1(git.readAllStandardError()) + QString::fromLatin1(git.readAllStandardOutput());
-diff --git a/addons/project/gitwidget.cpp b/addons/project/gitwidget.cpp
-index 2b19781c064b9f37f418da53ef911e53740189d4..77499dad8c64ad93e5b7b1016ce59850bc8c2171 100644
---- a/addons/project/gitwidget.cpp
-+++ b/addons/project/gitwidget.cpp
-@@ -514,8 +514,9 @@ void GitWidget::launchExternalDiffTool(const QString &file, bool staged)
-     args.append(file);
- 
-     QProcess git;
--    setupGitProcess(git, m_gitPath, args);
--    git.startDetached();
-+    if (setupGitProcess(git, m_gitPath, args)) {
-+        git.startDetached();
-+    }
- }
- 
- void GitWidget::commitChanges(const QString &msg, const QString &desc, bool signOff, bool amend)
-@@ -745,7 +746,12 @@ void GitWidget::branchCompareFiles(const QString &from, const QString &to)
-     auto args = QStringList{QStringLiteral("diff"), QStringLiteral("%1...%2").arg(from).arg(to), QStringLiteral("--name-status")};
- 
-     QProcess git;
--    setupGitProcess(git, m_gitPath, args);
-+
-+    // early out if we can't find git
-+    if (!setupGitProcess(git, m_gitPath, args)) {
-+        return;
-+    }
-+
-     git.start(QProcess::ReadOnly);
-     if (git.waitForStarted() && git.waitForFinished(-1)) {
-         if (git.exitStatus() != QProcess::NormalExit || git.exitCode() != 0) {
-@@ -767,7 +773,12 @@ void GitWidget::branchCompareFiles(const QString &from, const QString &to)
- 
-     // get --num-stat
-     args = QStringList{QStringLiteral("diff"), QStringLiteral("%1...%2").arg(from).arg(to), QStringLiteral("--numstat"), QStringLiteral("-z")};
--    setupGitProcess(git, m_gitPath, args);
-+
-+    // early out if we can't find git
-+    if (!setupGitProcess(git, m_gitPath, args)) {
-+        return;
-+    }
-+
-     git.start(QProcess::ReadOnly);
-     if (git.waitForStarted() && git.waitForFinished(-1)) {
-         if (git.exitStatus() != QProcess::NormalExit || git.exitCode() != 0) {
-diff --git a/addons/project/kateprojectindex.cpp b/addons/project/kateprojectindex.cpp
-index a7d9ec9c1fbbfe550af0c2961f8c405524021c61..9fc5b64cb7daeedaee7709dae679d4d498b36653 100644
---- a/addons/project/kateprojectindex.cpp
-+++ b/addons/project/kateprojectindex.cpp
-@@ -9,6 +9,7 @@
- 
- #include <QDir>
- #include <QProcess>
-+#include <QStandardPaths>
- 
- /**
-  * include ctags reading
-@@ -73,6 +74,12 @@ void KateProjectIndex::loadCtags(const QStringList &files, const QVariantMap &ct
-      */
-     m_ctagsIndexFile->close();
- 
-+    // only use ctags from PATH
-+    static const auto fullExecutablePath = QStandardPaths::findExecutable(QStringLiteral("ctags"));
-+    if (fullExecutablePath.isEmpty()) {
-+        return;
-+    }
-+
-     /**
-      * try to run ctags for all files in this project
-      * output to our ctags index file
-@@ -85,7 +92,7 @@ void KateProjectIndex::loadCtags(const QStringList &files, const QVariantMap &ct
-     for (const QVariant &optVariant : opts) {
-         args << optVariant.toString();
-     }
--    ctags.start(QStringLiteral("ctags"), args);
-+    ctags.start(fullExecutablePath, args);
-     if (!ctags.waitForStarted()) {
-         return;
-     }
-diff --git a/addons/project/kateprojectinfoviewcodeanalysis.cpp b/addons/project/kateprojectinfoviewcodeanalysis.cpp
-index 21cd26a84de7b37533f6511a4b0eec2f69777f69..23b82c45e746e6b0485b83d27ce04ea984d55ea7 100644
---- a/addons/project/kateprojectinfoviewcodeanalysis.cpp
-+++ b/addons/project/kateprojectinfoviewcodeanalysis.cpp
-@@ -13,6 +13,7 @@
- 
- #include <QFileInfo>
- #include <QHBoxLayout>
-+#include <QStandardPaths>
- #include <QToolTip>
- #include <QVBoxLayout>
- 
-@@ -134,14 +135,18 @@ void KateProjectInfoViewCodeAnalysis::slotStartStopClicked()
-     connect(m_analyzer, &QProcess::readyRead, this, &KateProjectInfoViewCodeAnalysis::slotReadyRead);
-     connect(m_analyzer, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), this, &KateProjectInfoViewCodeAnalysis::finished);
- 
--    m_analyzer->start(m_analysisTool->path(), m_analysisTool->arguments());
-+    // ensure we only run the code analyzer from PATH
-+    const QString fullExecutable = QStandardPaths::findExecutable(m_analysisTool->path());
-+    if (!fullExecutable.isEmpty()) {
-+        m_analyzer->start(fullExecutable, m_analysisTool->arguments());
-+    }
- 
-     if (m_messageWidget) {
-         delete m_messageWidget;
-         m_messageWidget = nullptr;
-     }
- 
--    if (!m_analyzer->waitForStarted()) {
-+    if (fullExecutable.isEmpty() || !m_analyzer->waitForStarted()) {
-         m_messageWidget = new KMessageWidget(this);
-         m_messageWidget->setCloseButtonVisible(true);
-         m_messageWidget->setMessageType(KMessageWidget::Warning);
-diff --git a/addons/project/kateprojectworker.cpp b/addons/project/kateprojectworker.cpp
-index d1979d1ec1c8f08aa1dd3163bd34fbec6f27af18..831dae89b9974e7e0b8ea320544fde815226d4a0 100644
---- a/addons/project/kateprojectworker.cpp
-+++ b/addons/project/kateprojectworker.cpp
-@@ -18,6 +18,7 @@
- #include <QRegularExpression>
- #include <QSet>
- #include <QSettings>
-+#include <QStandardPaths>
- #include <QThread>
- #include <QTime>
- #include <QtConcurrent>
-@@ -442,10 +443,12 @@ QVector<QString> KateProjectWorker::filesFromGit(const QDir &dir, bool recursive
- 
- QVector<QString> KateProjectWorker::gitFiles(const QDir &dir, bool recursive, const QStringList &args)
- {
-+    QVector<QString> files;
-     QProcess git;
--    setupGitProcess(git, dir.absolutePath(), args);
-+    if (!setupGitProcess(git, dir.absolutePath(), args)) {
-+        return files;
-+    }
-     git.start(QProcess::ReadOnly);
--    QVector<QString> files;
-     if (!git.waitForStarted() || !git.waitForFinished(-1)) {
-         return files;
-     }
-@@ -466,13 +469,18 @@ QVector<QString> KateProjectWorker::gitFiles(const QDir &dir, bool recursive, co
- 
- QVector<QString> KateProjectWorker::filesFromMercurial(const QDir &dir, bool recursive)
- {
-+    // only use version control from PATH
-     QVector<QString> files;
-+    static const auto fullExecutablePath = QStandardPaths::findExecutable(QStringLiteral("hg"));
-+    if (fullExecutablePath.isEmpty()) {
-+        return files;
-+    }
- 
-     QProcess hg;
-     hg.setWorkingDirectory(dir.absolutePath());
-     QStringList args;
-     args << QStringLiteral("manifest") << QStringLiteral(".");
--    hg.start(QStringLiteral("hg"), args, QProcess::ReadOnly);
-+    hg.start(fullExecutablePath, args, QProcess::ReadOnly);
-     if (!hg.waitForStarted() || !hg.waitForFinished(-1)) {
-         return files;
-     }
-@@ -493,7 +501,12 @@ QVector<QString> KateProjectWorker::filesFromMercurial(const QDir &dir, bool rec
- 
- QVector<QString> KateProjectWorker::filesFromSubversion(const QDir &dir, bool recursive)
- {
-+    // only use version control from PATH
-     QVector<QString> files;
-+    static const auto fullExecutablePath = QStandardPaths::findExecutable(QStringLiteral("svn"));
-+    if (fullExecutablePath.isEmpty()) {
-+        return files;
-+    }
- 
-     QProcess svn;
-     svn.setWorkingDirectory(dir.absolutePath());
-@@ -504,7 +517,7 @@ QVector<QString> KateProjectWorker::filesFromSubversion(const QDir &dir, bool re
-     } else {
-         args << QStringLiteral("--depth=files");
-     }
--    svn.start(QStringLiteral("svn"), args, QProcess::ReadOnly);
-+    svn.start(fullExecutablePath, args, QProcess::ReadOnly);
-     if (!svn.waitForStarted() || !svn.waitForFinished(-1)) {
-         return files;
-     }
-@@ -555,18 +568,21 @@ QVector<QString> KateProjectWorker::filesFromSubversion(const QDir &dir, bool re
- 
- QVector<QString> KateProjectWorker::filesFromDarcs(const QDir &dir, bool recursive)
- {
-+    // only use version control from PATH
-     QVector<QString> files;
-+    static const auto fullExecutablePath = QStandardPaths::findExecutable(QStringLiteral("darcs"));
-+    if (fullExecutablePath.isEmpty()) {
-+        return files;
-+    }
- 
--    const QString cmd = QStringLiteral("darcs");
-     QString root;
--
-     {
-         QProcess darcs;
-         darcs.setWorkingDirectory(dir.absolutePath());
-         QStringList args;
-         args << QStringLiteral("list") << QStringLiteral("repo");
- 
--        darcs.start(cmd, args, QProcess::ReadOnly);
-+        darcs.start(fullExecutablePath, args, QProcess::ReadOnly);
- 
-         if (!darcs.waitForStarted() || !darcs.waitForFinished(-1)) {
-             return files;
-@@ -590,7 +606,7 @@ QVector<QString> KateProjectWorker::filesFromDarcs(const QDir &dir, bool recursi
-         darcs.setWorkingDirectory(dir.absolutePath());
-         args << QStringLiteral("list") << QStringLiteral("files") << QStringLiteral("--no-directories") << QStringLiteral("--pending");
- 
--        darcs.start(cmd, args, QProcess::ReadOnly);
-+        darcs.start(fullExecutablePath, args, QProcess::ReadOnly);
- 
-         if (!darcs.waitForStarted() || !darcs.waitForFinished(-1)) {
-             return files;
-diff --git a/addons/project/stashdialog.cpp b/addons/project/stashdialog.cpp
-index c623182a8d0b7b9ece763e110ecb598682a0f7a0..bddedf709839fd824694de756fb333cc8b58367b 100644
---- a/addons/project/stashdialog.cpp
-+++ b/addons/project/stashdialog.cpp
-@@ -32,6 +32,8 @@
- 
- #include <kfts_fuzzy_match.h>
- 
-+#include <gitprocess.h>
-+
- constexpr int StashIndexRole = Qt::UserRole + 2;
- 
- class StashFilterModel final : public QSortFilterProxyModel
-@@ -218,11 +220,10 @@ void StashDialog::slotReturnPressed()
-     hide();
- }
- 
--QProcess *StashDialog::gitp()
-+QProcess *StashDialog::gitp(const QStringList &arguments)
- {
-     auto git = new QProcess(this);
--    git->setProgram(QStringLiteral("git"));
--    git->setWorkingDirectory(m_gitPath);
-+    setupGitProcess(*git, m_gitPath, arguments);
-     return git;
- }
- 
-@@ -242,7 +243,7 @@ void StashDialog::stash(bool keepIndex, bool includeUntracked)
-         args.append(m_lineEdit.text());
-     }
- 
--    auto git = gitp();
-+    auto git = gitp(args);
-     connect(git, &QProcess::finished, this, [this, git](int exitCode, QProcess::ExitStatus es) {
-         if (es != QProcess::NormalExit || exitCode != 0) {
-             qWarning() << git->errorString();
-@@ -253,14 +254,12 @@ void StashDialog::stash(bool keepIndex, bool includeUntracked)
-         Q_EMIT done();
-         git->deleteLater();
-     });
--    git->setArguments(args);
-     git->start(QProcess::ReadOnly);
- }
- 
- void StashDialog::getStashList()
- {
--    auto git = gitp();
--    git->setArguments({QStringLiteral("stash"), QStringLiteral("list")});
-+    auto git = gitp({QStringLiteral("stash"), QStringLiteral("list")});
-     git->start(QProcess::ReadOnly);
- 
-     QList<QByteArray> stashList;
-@@ -293,11 +292,11 @@ void StashDialog::getStashList()
- 
- void StashDialog::popStash(const QByteArray &index, const QString &command)
- {
--    auto git = gitp();
-     QStringList args{QStringLiteral("stash"), command};
-     if (!index.isEmpty()) {
-         args.append(QString::fromUtf8(index));
-     }
-+    auto git = gitp(args);
- 
-     connect(git, &QProcess::finished, this, [this, command, git](int exitCode, QProcess::ExitStatus es) {
-         if (es != QProcess::NormalExit || exitCode != 0) {
-@@ -320,7 +319,6 @@ void StashDialog::popStash(const QByteArray &index, const QString &command)
-         Q_EMIT done();
-         git->deleteLater();
-     });
--    git->setArguments(args);
-     git->start(QProcess::ReadOnly);
- }
- 
-@@ -339,9 +337,8 @@ void StashDialog::showStash(const QByteArray &index)
-     if (index.isEmpty()) {
-         return;
-     }
--    auto git = gitp();
- 
--    QStringList args{QStringLiteral("stash"), QStringLiteral("show"), QStringLiteral("-p"), QString::fromUtf8(index)};
-+    auto git = gitp({QStringLiteral("stash"), QStringLiteral("show"), QStringLiteral("-p"), QString::fromUtf8(index)});
- 
-     connect(git, &QProcess::finished, this, [this, git](int exitCode, QProcess::ExitStatus es) {
-         if (es != QProcess::NormalExit || exitCode != 0) {
-@@ -353,6 +350,5 @@ void StashDialog::showStash(const QByteArray &index)
-         git->deleteLater();
-     });
- 
--    git->setArguments(args);
-     git->start(QProcess::ReadOnly);
- }
-diff --git a/addons/project/stashdialog.h b/addons/project/stashdialog.h
-index a18d42ab935db03b0e6d1ae920ab1b61ff4175a4..41769075779fc254bb833b70afa24bbdaef832b8 100644
---- a/addons/project/stashdialog.h
-+++ b/addons/project/stashdialog.h
-@@ -56,7 +56,7 @@ protected Q_SLOTS:
-     void slotReturnPressed() override;
- 
- private:
--    QProcess *gitp();
-+    QProcess *gitp(const QStringList &arguments);
-     void stash(bool keepIndex, bool includeUntracked);
-     void getStashList();
-     void popStash(const QByteArray &index, const QString &command = QStringLiteral("pop"));
-diff --git a/addons/replicode/replicodeview.cpp b/addons/replicode/replicodeview.cpp
-index 0199f46ce90585e915b06bafefa05a3304859167..7f70ee1eab92f63aadca792df7bbec5e46d97f55 100644
---- a/addons/replicode/replicodeview.cpp
-+++ b/addons/replicode/replicodeview.cpp
-@@ -8,7 +8,9 @@
- 
- #include "replicodeconfig.h"
- #include "replicodesettings.h"
-+
- #include <QPushButton>
-+#include <QStandardPaths>
- #include <QTemporaryFile>
- #include <QtGlobal>
- 
-@@ -116,7 +118,14 @@ void ReplicodeView::runReplicode()
-     }
- 
-     KConfigGroup config(KSharedConfig::openConfig(), QStringLiteral("Replicode"));
-+
-     QString executorPath = config.readEntry<QString>("replicodePath", QString());
-+
-+    // ensure we only call replicode from PATH if not given as absolute path already
-+    if (!executorPath.isEmpty() && !QFileInfo(executorPath).isAbsolute()) {
-+        executorPath = QStandardPaths::findExecutable(executorPath);
-+    }
-+
-     if (executorPath.isEmpty()) {
-         QMessageBox::warning(m_mainWindow->window(),
-                              i18nc("@title:window", "Replicode Executable Not Found"),
-diff --git a/addons/xmlcheck/plugin_katexmlcheck.cpp b/addons/xmlcheck/plugin_katexmlcheck.cpp
-index f1d52f3a7e184dcee612a25d34e26a644565eab6..3971550cd5785d31d07239e5b97eac21c2515246 100644
---- a/addons/xmlcheck/plugin_katexmlcheck.cpp
-+++ b/addons/xmlcheck/plugin_katexmlcheck.cpp
-@@ -304,10 +304,18 @@ bool PluginKateXMLCheckView::slotValidate()
-     s << kv->document()->text();
-     s.flush();
- 
-+    // ensure we only execute xmllint from PATH or application package
-     QString exe = QStandardPaths::findExecutable(QStringLiteral("xmllint"));
-     if (exe.isEmpty()) {
-         exe = QStandardPaths::locate(QStandardPaths::ApplicationsLocation, QStringLiteral("xmllint"));
-     }
-+    if (exe.isEmpty()) {
-+        KMessageBox::error(nullptr,
-+                           i18n("<b>Error:</b> Failed to find xmllint. Please make "
-+                                "sure that xmllint is installed. It is part of libxml2."));
-+        return false;
-+    }
-+
-     // qDebug() << "exe=" <<exe;
-     // 	// use catalogs for KDE docbook:
-     // 	if( ! getenv("XML_CATALOG_FILES") ) {
-diff --git a/kate/katefileactions.cpp b/kate/katefileactions.cpp
-index c56c7e1c81b3e771f19163c43b56b8c2ebbd6d15..09a23686c600a9569c9bda69c40e8d53cb1f3f5b 100644
---- a/kate/katefileactions.cpp
-+++ b/kate/katefileactions.cpp
-@@ -23,6 +23,7 @@
- #include <QDebug>
- #include <QInputDialog>
- #include <QProcess>
-+#include <QStandardPaths>
- #include <QUrl>
- 
- void KateFileActions::copyFilePathToClipboard(KTextEditor::Document *doc)
-@@ -137,17 +138,13 @@ void KateFileActions::deleteDocumentFile(QWidget *parent, KTextEditor::Document
-     }
- }
- 
--QStringList KateFileActions::supportedDiffTools()
-+QVector<std::pair<QString, QString>> KateFileActions::supportedDiffTools()
- {
--    // LATER: check for program existence and set some boolean value accordingly
--    // Can this be even done in an easy way when we don't use the absolute path to the executable?
--    // See https://stackoverflow.com/questions/42444055/how-to-check-if-a-program-exists-in-path-using-qt
--
--    QStringList resultList;
--    resultList.push_back(QStringLiteral("kdiff3"));
--    resultList.push_back(QStringLiteral("kompare"));
--    resultList.push_back(QStringLiteral("meld"));
--
-+    // query once if the tools are there in the path and store that
-+    // we will disable the actions for the tools not found
-+    static QVector<std::pair<QString, QString>> resultList{{QStringLiteral("kdiff3"), QStandardPaths::findExecutable(QStringLiteral("kdiff3"))},
-+                                                           {QStringLiteral("kompare"), QStandardPaths::findExecutable(QStringLiteral("kompare"))},
-+                                                           {QStringLiteral("meld"), QStandardPaths::findExecutable(QStringLiteral("meld"))}};
-     return resultList;
- }
- 
-diff --git a/kate/katefileactions.h b/kate/katefileactions.h
-index 524d810975e5f57c4351e1e91568734585f41ca3..77cc5b0bffefe263ea494aafb5fe8c6c03927775 100644
---- a/kate/katefileactions.h
-+++ b/kate/katefileactions.h
-@@ -51,9 +51,9 @@ void openFilePropertiesDialog(KTextEditor::Document *document);
- void deleteDocumentFile(QWidget *parent, KTextEditor::Document *document);
- 
- /**
-- * @returns a list of supported diff tools (names of the executables)
-+ * @returns a list of supported diff tools (names of the executables + paths to them, empty if not found in PATH)
-  */
--QStringList supportedDiffTools();
-+QVector<std::pair<QString, QString>> supportedDiffTools();
- 
- /**
-  * Runs an external program to compare the underlying files of two given documents.
-diff --git a/kate/katemwmodonhddialog.cpp b/kate/katemwmodonhddialog.cpp
-index e0041d858de473df737e8c33c60933a039d5d350..d7c79e4d48c2009dbf52415ca82e4f1f5ea77120 100644
---- a/kate/katemwmodonhddialog.cpp
-+++ b/kate/katemwmodonhddialog.cpp
-@@ -22,6 +22,7 @@
- #include <QHeaderView>
- #include <QLabel>
- #include <QPushButton>
-+#include <QStandardPaths>
- #include <QStyle>
- #include <QTemporaryFile>
- #include <QTextStream>
-@@ -52,6 +53,7 @@ public:
- 
- KateMwModOnHdDialog::KateMwModOnHdDialog(DocVector docs, QWidget *parent, const char *name)
-     : QDialog(parent)
-+    , m_fullDiffPath(QStandardPaths::findExecutable(QStringLiteral("diff")))
-     , m_proc(nullptr)
-     , m_diffFile(nullptr)
-     , m_blockAddDocument(false)
-@@ -108,6 +110,7 @@ KateMwModOnHdDialog::KateMwModOnHdDialog(DocVector docs, QWidget *parent, const
-              "file for the selected document, and shows the difference with the "
-              "default application. Requires diff(1)."));
-     hb->addWidget(btnDiff);
-+    btnDiff->setEnabled(!m_fullDiffPath.isEmpty());
-     connect(btnDiff, &QPushButton::clicked, this, &KateMwModOnHdDialog::slotDiff);
- 
-     // Dialog buttons
-@@ -288,9 +291,10 @@ void KateMwModOnHdDialog::slotDiff()
-     m_diffFile->open();
- 
-     // Start a KProcess that creates a diff
-+    // We use the full path to don't launch some random "diff" in current working directory
-     m_proc = new KProcess(this);
-     m_proc->setOutputChannelMode(KProcess::MergedChannels);
--    *m_proc << QStringLiteral("diff") << QStringLiteral("-ub") << QStringLiteral("-") << doc->url().toLocalFile();
-+    *m_proc << m_fullDiffPath << QStringLiteral("-ub") << QStringLiteral("-") << doc->url().toLocalFile();
-     connect(m_proc, &KProcess::readyRead, this, &KateMwModOnHdDialog::slotDataAvailable);
-     connect(m_proc, static_cast<void (KProcess::*)(int, QProcess::ExitStatus)>(&KProcess::finished), this, &KateMwModOnHdDialog::slotPDone);
- 
-diff --git a/kate/katemwmodonhddialog.h b/kate/katemwmodonhddialog.h
-index 11c09eab7284be885aaee62f6108958c54dd9e3a..6fa2457269e819dca9a900b6f9d6e08e25893f9d 100644
---- a/kate/katemwmodonhddialog.h
-+++ b/kate/katemwmodonhddialog.h
-@@ -51,6 +51,7 @@ private:
-     class QTreeWidget *twDocuments;
-     class QDialogButtonBox *dlgButtons;
-     class QPushButton *btnDiff;
-+    QString m_fullDiffPath;
-     KProcess *m_proc;
-     QTemporaryFile *m_diffFile;
-     QStringList m_stateTexts;
-diff --git a/kate/kateviewspace.cpp b/kate/kateviewspace.cpp
-index dba2fb973d20e02fb7c84fff72208b682a96aa8c..af3bb8d34ffed3ebd8c80be0b4966cc7865f58dc 100644
---- a/kate/kateviewspace.cpp
-+++ b/kate/kateviewspace.cpp
-@@ -678,8 +678,11 @@ void KateViewSpace::showContextMenu(int idx, const QPoint &globalPos)
- 
-     if (mCompareWithActive->isEnabled()) {
-         for (auto &&diffTool : KateFileActions::supportedDiffTools()) {
--            QAction *compareAction = mCompareWithActive->addAction(diffTool);
--            compareAction->setData(diffTool);
-+            QAction *compareAction = mCompareWithActive->addAction(diffTool.first);
-+
-+            // we use the full path to safely execute the tool, disable action if no full path => tool not found
-+            compareAction->setData(diffTool.second);
-+            compareAction->setEnabled(!diffTool.second.isEmpty());
-         }
-     }
- 
-diff --git a/shared/gitprocess.h b/shared/gitprocess.h
-index 47b98b69605feb9fd7287dfd2df0de16276ad362..b0d79fac639dd1c76cb79074ebe004e9b0bf583d 100644
---- a/shared/gitprocess.h
-+++ b/shared/gitprocess.h
-@@ -7,6 +7,7 @@
- #pragma once
- 
- #include <QProcess>
-+#include <QStandardPaths>
- 
- /**
-  * small helper function to setup a QProcess based "git" command.
-@@ -17,10 +18,20 @@
-  * @param process process to setup for git
-  * @param workingDirectory working directory to use for process
-  * @param arguments arguments to pass to git
-+ * @return could set setup the process or did that fail, e.g. because the git executable is not available?
-  */
--inline void setupGitProcess(QProcess &process, const QString &workingDirectory, const QStringList &arguments)
-+inline bool setupGitProcess(QProcess &process, const QString &workingDirectory, const QStringList &arguments)
- {
--    process.setProgram(QStringLiteral("git"));
-+    // only use git from PATH
-+    static const auto gitExecutable = QStandardPaths::findExecutable(QStringLiteral("git"));
-+    if (gitExecutable.isEmpty()) {
-+        // ensure we have no valid QProcess setup
-+        process.setProgram(QString());
-+        return false;
-+    }
-+
-+    // setup program and arguments, ensure we do run git in the right working directory
-+    process.setProgram(gitExecutable);
-     process.setWorkingDirectory(workingDirectory);
-     process.setArguments(arguments);
- 
-@@ -37,4 +48,5 @@ inline void setupGitProcess(QProcess &process, const QString &workingDirectory,
-     QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
-     env.insert(QStringLiteral("GIT_OPTIONAL_LOCKS"), QStringLiteral("0"));
-     process.setProcessEnvironment(env);
-+    return true;
- }
diff --git a/debian/patches/92a9c65e30b4b63b8b116eb5c8dcb1e1a2d867bc.diff b/debian/patches/92a9c65e30b4b63b8b116eb5c8dcb1e1a2d867bc.diff
deleted file mode 100644
index 3a89452..0000000
--- a/debian/patches/92a9c65e30b4b63b8b116eb5c8dcb1e1a2d867bc.diff
+++ /dev/null
@@ -1,22 +0,0 @@
-diff --git a/addons/lspclient/lspclientservermanager.cpp b/addons/lspclient/lspclientservermanager.cpp
-index 551926e23175560f912e9a9de86f1a8cf58e7e05..24e3f275bee7014e400f71cb9f36d2ed56996d20 100644
---- a/addons/lspclient/lspclientservermanager.cpp
-+++ b/addons/lspclient/lspclientservermanager.cpp
-@@ -737,13 +737,13 @@ private:
-                 server.reset(new LSPClientServer(cmdline, root, realLangId, serverConfig.value(QStringLiteral("initializationOptions")), folders));
-                 connect(server.data(), &LSPClientServer::stateChanged, this, &self_type::onStateChanged, Qt::UniqueConnection);
-                 if (!server->start()) {
--                    QString errorMessage = i18n("Failed to start server: %1", cmdline.join(QLatin1Char(' ')));
-+                    QString message = i18n("Failed to start server: %1", cmdline.join(QLatin1Char(' ')));
-                     const auto url = serverConfig.value(QStringLiteral("url")).toString();
-                     if (!url.isEmpty()) {
--                        errorMessage += QStringLiteral("\n") + i18n("Please check your PATH for the binary");
--                        errorMessage += QStringLiteral("\n") + i18n("See also %1 for installation or details", url);
-+                        message += QStringLiteral("\n") + i18n("Please check your PATH for the binary");
-+                        message += QStringLiteral("\n") + i18n("See also %1 for installation or details", url);
-                     }
--                    showMessage(errorMessage, KTextEditor::Message::Error);
-+                    showMessage(message, KTextEditor::Message::Warning);
-                 } else {
-                     showMessage(i18n("Started server %2: %1", cmdline.join(QLatin1Char(' ')), serverDescription(server.data())),
-                                 KTextEditor::Message::Positive);
diff --git a/debian/patches/c5d66f3b70ae4778d6162564309aee95f643e7c9.diff b/debian/patches/c5d66f3b70ae4778d6162564309aee95f643e7c9.diff
deleted file mode 100644
index 09e9919..0000000
--- a/debian/patches/c5d66f3b70ae4778d6162564309aee95f643e7c9.diff
+++ /dev/null
@@ -1,108 +0,0 @@
-diff --git a/addons/lspclient/lspclientservermanager.cpp b/addons/lspclient/lspclientservermanager.cpp
-index 24e3f275bee7014e400f71cb9f36d2ed56996d20..e78b4aa2d91c35ddcb883aba9037683318170a2a 100644
---- a/addons/lspclient/lspclientservermanager.cpp
-+++ b/addons/lspclient/lspclientservermanager.cpp
-@@ -707,52 +707,67 @@ private:
-             }
- 
-             if (cmdline.length() > 0) {
-+                // ensure we always only take the server executable from the PATH or user defined paths
-+                // QProcess will take the executable even just from current working directory without this => BAD
-+                auto cmd = QStandardPaths::findExecutable(cmdline[0]);
-+
-                 // optionally search in supplied path(s)
--                auto vpath = serverConfig.value(QStringLiteral("path")).toArray();
--                if (vpath.size() > 0) {
--                    auto cmd = QStandardPaths::findExecutable(cmdline[0]);
--                    if (cmd.isEmpty()) {
--                        // collect and expand in case home dir or other (environment) variable reference is used
--                        QStringList path;
--                        for (const auto &e : vpath) {
--                            auto p = e.toString();
--                            editor->expandText(p, view, p);
--                            path.push_back(p);
--                        }
--                        cmd = QStandardPaths::findExecutable(cmdline[0], path);
--                        if (!cmd.isEmpty()) {
--                            cmdline[0] = cmd;
--                        }
-+                const auto vpath = serverConfig.value(QStringLiteral("path")).toArray();
-+                if (cmd.isEmpty() && !vpath.isEmpty()) {
-+                    // collect and expand in case home dir or other (environment) variable reference is used
-+                    QStringList path;
-+                    for (const auto &e : vpath) {
-+                        auto p = e.toString();
-+                        editor->expandText(p, view, p);
-+                        path.push_back(p);
-                     }
-+                    cmd = QStandardPaths::findExecutable(cmdline[0], path);
-                 }
--                // an empty list is always passed here (or null)
--                // the initial list is provided/updated using notification after start
--                // since that is what a server is more aware of
--                // and should support if it declares workspace folder capable
--                // (as opposed to the new initialization property)
--                LSPClientServer::FoldersType folders;
--                if (useWorkspace) {
--                    folders = QList<LSPWorkspaceFolder>();
--                }
--                server.reset(new LSPClientServer(cmdline, root, realLangId, serverConfig.value(QStringLiteral("initializationOptions")), folders));
--                connect(server.data(), &LSPClientServer::stateChanged, this, &self_type::onStateChanged, Qt::UniqueConnection);
--                if (!server->start()) {
--                    QString message = i18n("Failed to start server: %1", cmdline.join(QLatin1Char(' ')));
-+
-+                // we can only start the stuff if we did find the binary in the paths
-+                if (!cmd.isEmpty()) {
-+                    // use full path to avoid security issues
-+                    cmdline[0] = cmd;
-+
-+                    // an empty list is always passed here (or null)
-+                    // the initial list is provided/updated using notification after start
-+                    // since that is what a server is more aware of
-+                    // and should support if it declares workspace folder capable
-+                    // (as opposed to the new initialization property)
-+                    LSPClientServer::FoldersType folders;
-+                    if (useWorkspace) {
-+                        folders = QList<LSPWorkspaceFolder>();
-+                    }
-+                    server.reset(new LSPClientServer(cmdline, root, realLangId, serverConfig.value(QStringLiteral("initializationOptions")), folders));
-+                    connect(server.data(), &LSPClientServer::stateChanged, this, &self_type::onStateChanged, Qt::UniqueConnection);
-+                    if (!server->start()) {
-+                        QString message = i18n("Failed to start server: %1", cmdline.join(QLatin1Char(' ')));
-+                        const auto url = serverConfig.value(QStringLiteral("url")).toString();
-+                        if (!url.isEmpty()) {
-+                            message += QStringLiteral("\n") + i18n("Please check your PATH for the binary");
-+                            message += QStringLiteral("\n") + i18n("See also %1 for installation or details", url);
-+                        }
-+                        showMessage(message, KTextEditor::Message::Warning);
-+                    } else {
-+                        showMessage(i18n("Started server %2: %1", cmdline.join(QLatin1Char(' ')), serverDescription(server.data())),
-+                                    KTextEditor::Message::Positive);
-+                        using namespace std::placeholders;
-+                        server->connect(server.data(), &LSPClientServer::logMessage, this, std::bind(&self_type::onMessage, this, true, _1));
-+                        server->connect(server.data(), &LSPClientServer::showMessage, this, std::bind(&self_type::onMessage, this, false, _1));
-+                        server->connect(server.data(), &LSPClientServer::workDoneProgress, this, &self_type::onWorkDoneProgress);
-+                        server->connect(server.data(), &LSPClientServer::workspaceFolders, this, &self_type::onWorkspaceFolders, Qt::UniqueConnection);
-+                    }
-+                } else {
-+                    // we didn't find the server binary at all!
-+                    QString message = i18n("Failed to find server binary: %1", cmdline[0]);
-                     const auto url = serverConfig.value(QStringLiteral("url")).toString();
-                     if (!url.isEmpty()) {
-                         message += QStringLiteral("\n") + i18n("Please check your PATH for the binary");
-                         message += QStringLiteral("\n") + i18n("See also %1 for installation or details", url);
-                     }
-                     showMessage(message, KTextEditor::Message::Warning);
--                } else {
--                    showMessage(i18n("Started server %2: %1", cmdline.join(QLatin1Char(' ')), serverDescription(server.data())),
--                                KTextEditor::Message::Positive);
--                    using namespace std::placeholders;
--                    server->connect(server.data(), &LSPClientServer::logMessage, this, std::bind(&self_type::onMessage, this, true, _1));
--                    server->connect(server.data(), &LSPClientServer::showMessage, this, std::bind(&self_type::onMessage, this, false, _1));
--                    server->connect(server.data(), &LSPClientServer::workDoneProgress, this, &self_type::onWorkDoneProgress);
--                    server->connect(server.data(), &LSPClientServer::workspaceFolders, this, &self_type::onWorkspaceFolders, Qt::UniqueConnection);
-                 }
-+
-                 serverinfo.settings = serverConfig.value(QStringLiteral("settings"));
-                 serverinfo.started = QTime::currentTime();
-                 serverinfo.url = serverConfig.value(QStringLiteral("url")).toString();
diff --git a/debian/patches/series b/debian/patches/series
deleted file mode 100644
index 4fe0009..0000000
--- a/debian/patches/series
+++ /dev/null
@@ -1,5 +0,0 @@
-361dd43e42994829dbdb35e78fb7698d27cbb0e2.diff
-6fc3bf6e5bd540e842e32c4a959c2158c8573be5.diff
-92a9c65e30b4b63b8b116eb5c8dcb1e1a2d867bc.diff
-c5d66f3b70ae4778d6162564309aee95f643e7c9.diff
-7e08a58fb50d28ba96aedd5f5cd79a9479b4a0ad.diff


More information about the Neon-commits mailing list