aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndre Hartmann <[email protected]>2025-03-07 12:09:01 +0100
committerAndrĂ© Hartmann <[email protected]>2025-05-11 16:01:48 +0000
commitb4b16a137f46dd6535bda75accf9b3a64a4e1895 (patch)
tree47c0f5d38fa3005bd482bc1cb35774eef7a3a32b /src
parentfc8ce74f8aa781a9f996814abd29b5164e311c4a (diff)
Git: Add applying patches from clipboardHEADmaster
Create a temporary patch file with normalized line endings and provide that to git. Change-Id: Ic9eaf7970e5d27dab0fe7b436b03f1995ea5cc45 Reviewed-by: Orgad Shaneh <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/git/CMakeLists.txt1
-rw-r--r--src/plugins/git/git.qbs2
-rw-r--r--src/plugins/git/gitclient.cpp13
-rw-r--r--src/plugins/git/gitplugin.cpp21
-rw-r--r--src/plugins/git/temporarypatchfile.cpp29
-rw-r--r--src/plugins/git/temporarypatchfile.h18
6 files changed, 75 insertions, 9 deletions
diff --git a/src/plugins/git/CMakeLists.txt b/src/plugins/git/CMakeLists.txt
index dfe6a9c05f1..742843b4058 100644
--- a/src/plugins/git/CMakeLists.txt
+++ b/src/plugins/git/CMakeLists.txt
@@ -37,4 +37,5 @@ add_qtc_plugin(Git
remotedialog.cpp remotedialog.h
remotemodel.cpp remotemodel.h
stashdialog.cpp stashdialog.h
+ temporarypatchfile.cpp temporarypatchfile.h
)
diff --git a/src/plugins/git/git.qbs b/src/plugins/git/git.qbs
index 1379de7d670..4a9c70f1b8b 100644
--- a/src/plugins/git/git.qbs
+++ b/src/plugins/git/git.qbs
@@ -61,6 +61,8 @@ QtcPlugin {
"remotemodel.h",
"stashdialog.cpp",
"stashdialog.h",
+ "temporarypatchfile.cpp",
+ "temporarypatchfile.h",
]
Group {
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index 1560536b58d..27631b1ffdc 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -11,6 +11,7 @@
#include "gittr.h"
#include "gitutils.h"
#include "mergetool.h"
+#include "temporarypatchfile.h"
#include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/editormanager.h>
@@ -109,21 +110,15 @@ static QString branchesDisplay(const QString &prefix, QStringList *branches, boo
static void stage(DiffEditorController *diffController, const QString &patch, bool revert)
{
- TemporaryFile patchFile("git-patchfile");
- if (!patchFile.open())
+ if (patch.isEmpty())
return;
-
+ TemporaryPatchFile patchFile(patch);
const FilePath baseDir = diffController->workingDirectory();
- QTextCodec *codec = EditorManager::defaultTextCodec();
- const QByteArray patchData = codec ? codec->fromUnicode(patch) : patch.toLocal8Bit();
- patchFile.write(patchData);
- patchFile.close();
-
QStringList args = {"--cached"};
if (revert)
args << "--reverse";
QString errorMessage;
- if (gitClient().synchronousApplyPatch(baseDir, patchFile.fileName(),
+ if (gitClient().synchronousApplyPatch(baseDir, patchFile.filePath().toUrlishString(),
&errorMessage, args)) {
if (errorMessage.isEmpty()) {
if (revert)
diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp
index 05bf7016857..1de69e521a3 100644
--- a/src/plugins/git/gitplugin.cpp
+++ b/src/plugins/git/gitplugin.cpp
@@ -18,6 +18,7 @@
#include "logchangedialog.h"
#include "remotedialog.h"
#include "stashdialog.h"
+#include "temporarypatchfile.h"
#include "gerrit/gerritplugin.h"
@@ -66,6 +67,7 @@
#include <QAction>
#include <QApplication>
+#include <QClipboard>
#include <QDebug>
#include <QDir>
#include <QFileDialog>
@@ -244,6 +246,7 @@ public:
void cleanRepository();
void updateSubmodules();
void applyCurrentFilePatch();
+ void applyClipboardPatch();
void promptApplyPatch();
void stash(bool unstagedOnly = false);
@@ -840,6 +843,10 @@ GitPluginPrivate::GitPluginPrivate()
Tr::tr("Apply from Editor"), Tr::tr("Apply \"%1\""),
"Git.ApplyCurrentFilePatch",
context, true, std::bind(&GitPluginPrivate::applyCurrentFilePatch, this));
+
+ createRepositoryAction(patchMenu, Tr::tr("Apply from Clipboard"), "Git.ApplyClipboardPatch",
+ context, true, std::bind(&GitPluginPrivate::applyClipboardPatch, this));
+
createRepositoryAction(patchMenu, Tr::tr("Apply from File..."), "Git.ApplyPatch",
context, true, std::bind(&GitPluginPrivate::promptApplyPatch, this));
@@ -1588,6 +1595,20 @@ void GitPluginPrivate::applyCurrentFilePatch()
applyPatch(state.topLevel(), patchFile);
}
+void GitPluginPrivate::applyClipboardPatch()
+{
+ const VcsBasePluginState state = currentState();
+ QTC_ASSERT(state.hasTopLevel(), return);
+
+ QClipboard *clipboard = QApplication::clipboard();
+ const QString patch = clipboard->text();
+ if (patch.isEmpty())
+ return;
+
+ const TemporaryPatchFile patchFile(patch);
+ applyPatch(state.topLevel(), patchFile.filePath().toUrlishString());
+}
+
void GitPluginPrivate::promptApplyPatch()
{
const VcsBasePluginState state = currentState();
diff --git a/src/plugins/git/temporarypatchfile.cpp b/src/plugins/git/temporarypatchfile.cpp
new file mode 100644
index 00000000000..eed28ee2ab9
--- /dev/null
+++ b/src/plugins/git/temporarypatchfile.cpp
@@ -0,0 +1,29 @@
+// Copyright (C) 2025 Andre Hartmann <[email protected]>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "temporarypatchfile.h"
+
+#include <coreplugin/editormanager/editormanager.h>
+
+#include <QTextCodec>
+
+using namespace Utils;
+
+TemporaryPatchFile::TemporaryPatchFile(const QString &patch)
+ : patchFile(new Utils::TemporaryFile("git-patchfile"))
+{
+ if (!patchFile->open())
+ return;
+
+ QString normalized = patch;
+ normalized.replace("\r\n", "\n").replace('\r', '\n');
+ QTextCodec *codec = Core::EditorManager::defaultTextCodec();
+ const QByteArray patchData = codec ? codec->fromUnicode(normalized) : normalized.toLocal8Bit();
+ patchFile->write(patchData);
+ patchFile->close();
+}
+
+Utils::FilePath TemporaryPatchFile::filePath() const
+{
+ return Utils::FilePath::fromString(patchFile->fileName());
+}
diff --git a/src/plugins/git/temporarypatchfile.h b/src/plugins/git/temporarypatchfile.h
new file mode 100644
index 00000000000..d933b5ed169
--- /dev/null
+++ b/src/plugins/git/temporarypatchfile.h
@@ -0,0 +1,18 @@
+// Copyright (C) 2025 Andre Hartmann <[email protected]>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#pragma once
+
+#include <utils/filepath.h>
+#include <utils/temporaryfile.h>
+
+class TemporaryPatchFile
+{
+public:
+ TemporaryPatchFile(const QString &patch);
+
+ Utils::FilePath filePath() const;
+
+private:
+ std::unique_ptr<Utils::TemporaryFile> patchFile;
+};