summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/plugins/git/gitclient.cpp9
-rw-r--r--src/plugins/git/gitclient.h2
-rw-r--r--src/plugins/git/giteditor.cpp63
-rw-r--r--src/plugins/git/giteditor.h4
-rw-r--r--src/plugins/vcsbase/vcsbaseeditor.cpp25
-rw-r--r--src/plugins/vcsbase/vcsbaseeditor.h5
6 files changed, 99 insertions, 9 deletions
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index 4de3a026d2..9a91cc7491 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -1115,6 +1115,8 @@ void GitClient::diff(const QString &workingDirectory,
workingDirectory,
argWidget);
newEditor = vcsEditor->editor();
+ connect(vcsEditor, SIGNAL(diffChunkApplied(VcsBase::DiffChunk)),
+ argWidget, SLOT(executeCommand()));
connect(vcsEditor, SIGNAL(diffChunkReverted(VcsBase::DiffChunk)),
argWidget, SLOT(executeCommand()));
}
@@ -1222,6 +1224,8 @@ void GitClient::diff(const QString &workingDirectory,
sourceFile,
argWidget);
newEditor = vcsEditor->editor();
+ connect(vcsEditor, SIGNAL(diffChunkApplied(VcsBase::DiffChunk)),
+ argWidget, SLOT(executeCommand()));
connect(vcsEditor, SIGNAL(diffChunkReverted(VcsBase::DiffChunk)),
argWidget, SLOT(executeCommand()));
}
@@ -2433,10 +2437,11 @@ bool GitClient::synchronousCleanList(const QString &workingDirectory, QStringLis
}
bool GitClient::synchronousApplyPatch(const QString &workingDirectory,
- const QString &file, QString *errorMessage)
+ const QString &file, QString *errorMessage,
+ const QStringList &arguments)
{
QStringList args;
- args << QLatin1String("apply") << QLatin1String("--whitespace=fix") << file;
+ args << QLatin1String("apply") << QLatin1String("--whitespace=fix") << arguments << file;
QByteArray outputText;
QByteArray errorText;
const bool rc = fullySynchronousGit(workingDirectory, args, &outputText, &errorText);
diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h
index 5b1631c3bd..6e4a990baf 100644
--- a/src/plugins/git/gitclient.h
+++ b/src/plugins/git/gitclient.h
@@ -182,7 +182,7 @@ public:
const QStringList &files = QStringList(),
QString *errorMessage = 0);
bool synchronousCleanList(const QString &workingDirectory, QStringList *files, QStringList *ignoredFiles, QString *errorMessage);
- bool synchronousApplyPatch(const QString &workingDirectory, const QString &file, QString *errorMessage);
+ bool synchronousApplyPatch(const QString &workingDirectory, const QString &file, QString *errorMessage, const QStringList &arguments = QStringList());
bool synchronousInit(const QString &workingDirectory);
bool synchronousCheckoutFiles(const QString &workingDirectory,
QStringList files = QStringList(),
diff --git a/src/plugins/git/giteditor.cpp b/src/plugins/git/giteditor.cpp
index 7018e51eb9..7aa36ec7fe 100644
--- a/src/plugins/git/giteditor.cpp
+++ b/src/plugins/git/giteditor.cpp
@@ -44,9 +44,12 @@
#include <QFileInfo>
#include <QRegExp>
#include <QSet>
+#include <QTemporaryFile>
+#include <QDir>
#include <QTextCursor>
#include <QTextBlock>
+#include <QMessageBox>
#define CHANGE_PATTERN "[a-f0-9]{7,40}"
@@ -223,6 +226,53 @@ void GitEditor::revertChange()
GitPlugin::instance()->gitClient()->synchronousRevert(workingDirectory, m_currentChange);
}
+void GitEditor::stageDiffChunk()
+{
+ const QAction *a = qobject_cast<QAction *>(sender());
+ QTC_ASSERT(a, return);
+ const VcsBase::DiffChunk chunk = qvariant_cast<VcsBase::DiffChunk>(a->data());
+ return applyDiffChunk(chunk, false);
+}
+
+void GitEditor::unstageDiffChunk()
+{
+ const QAction *a = qobject_cast<QAction *>(sender());
+ QTC_ASSERT(a, return);
+ const VcsBase::DiffChunk chunk = qvariant_cast<VcsBase::DiffChunk>(a->data());
+ return applyDiffChunk(chunk, true);
+}
+
+void GitEditor::applyDiffChunk(const VcsBase::DiffChunk& chunk, bool revert)
+{
+ VcsBase::VcsBaseOutputWindow *outwin = VcsBase::VcsBaseOutputWindow::instance();
+ QTemporaryFile patchFile;
+ if (!patchFile.open())
+ return;
+
+ const QString baseDir = diffBaseDirectory();
+ patchFile.write(chunk.header);
+ patchFile.write(chunk.chunk);
+ patchFile.close();
+
+ GitClient *client = GitPlugin::instance()->gitClient();
+ QStringList args = QStringList() << QLatin1String("--cached");
+ if (revert)
+ args << QLatin1String("--reverse");
+ QString errorMessage;
+ if (client->synchronousApplyPatch(baseDir, patchFile.fileName(), &errorMessage, args)) {
+ if (errorMessage.isEmpty())
+ outwin->append(tr("Chunk successfully staged"));
+ else
+ outwin->append(errorMessage);
+ if (revert)
+ emit diffChunkReverted(chunk);
+ else
+ emit diffChunkApplied(chunk);
+ } else {
+ outwin->appendError(errorMessage);
+ }
+}
+
void GitEditor::init()
{
VcsBase::VcsBaseEditorWidget::init();
@@ -233,6 +283,19 @@ void GitEditor::init()
new GitRebaseHighlighter(baseTextDocument().data());
}
+void GitEditor::addDiffActions(QMenu *menu, const VcsBase::DiffChunk &chunk)
+{
+ menu->addSeparator();
+
+ QAction *stageAction = menu->addAction(tr("Stage Chunk..."));
+ stageAction->setData(qVariantFromValue(chunk));
+ connect(stageAction, SIGNAL(triggered()), this, SLOT(stageDiffChunk()));
+
+ QAction *unstageAction = menu->addAction(tr("Unstage Chunk..."));
+ unstageAction->setData(qVariantFromValue(chunk));
+ connect(unstageAction, SIGNAL(triggered()), this, SLOT(unstageDiffChunk()));
+}
+
bool GitEditor::open(QString *errorString, const QString &fileName, const QString &realFileName)
{
bool res = VcsBaseEditorWidget::open(errorString, fileName, realFileName);
diff --git a/src/plugins/git/giteditor.h b/src/plugins/git/giteditor.h
index 648a2fa4ec..1ed80c7ccf 100644
--- a/src/plugins/git/giteditor.h
+++ b/src/plugins/git/giteditor.h
@@ -57,9 +57,13 @@ public slots:
private slots:
void cherryPickChange();
void revertChange();
+ void stageDiffChunk();
+ void unstageDiffChunk();
+ void applyDiffChunk(const VcsBase::DiffChunk& chunk, bool revert);
private:
void init();
+ void addDiffActions(QMenu *menu, const VcsBase::DiffChunk &chunk);
bool open(QString *errorString, const QString &fileName, const QString &realFileName);
QSet<QString> annotationChanges() const;
QString changeUnderCursor(const QTextCursor &) const;
diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp
index 7ded80ec7f..7171851c76 100644
--- a/src/plugins/vcsbase/vcsbaseeditor.cpp
+++ b/src/plugins/vcsbase/vcsbaseeditor.cpp
@@ -950,6 +950,8 @@ void VcsBaseEditorWidget::contextMenuEvent(QContextMenuEvent *e)
QAction *revertAction = menu->addAction(tr("Revert Chunk..."));
revertAction->setData(qVariantFromValue(Internal::DiffChunkAction(chunk, true)));
connect(revertAction, SIGNAL(triggered()), this, SLOT(slotApplyDiffChunk()));
+ // Custom diff actions
+ addDiffActions(menu, chunk);
break;
}
default:
@@ -1145,7 +1147,8 @@ DiffChunk VcsBaseEditorWidget::diffChunk(QTextCursor cursor) const
}
if (!chunkStart || !block.isValid())
return rc;
- rc.fileName = findDiffFile(fileNameFromDiffSpecification(block));
+ QString header;
+ rc.fileName = findDiffFile(fileNameFromDiffSpecification(block, &header));
if (rc.fileName.isEmpty())
return rc;
// Concatenate chunk and convert
@@ -1163,6 +1166,7 @@ DiffChunk VcsBaseEditorWidget::diffChunk(QTextCursor cursor) const
}
const QTextCodec *cd = baseTextDocument()->codec();
rc.chunk = cd ? cd->fromUnicode(unicode) : unicode.toLocal8Bit();
+ rc.header = cd ? cd->fromUnicode(header) : header.toLocal8Bit();
return rc;
}
@@ -1388,6 +1392,10 @@ QString VcsBaseEditorWidget::findDiffFile(const QString &f) const
return QString();
}
+void VcsBaseEditorWidget::addDiffActions(QMenu *, const DiffChunk &)
+{
+}
+
void VcsBaseEditorWidget::slotAnnotateRevision()
{
if (const QAction *a = qobject_cast<const QAction *>(sender()))
@@ -1430,18 +1438,25 @@ bool VcsBaseEditorWidget::applyDiffChunk(const DiffChunk &dc, bool revert) const
d->m_diffBaseDirectory, 0, revert);
}
-QString VcsBaseEditorWidget::fileNameFromDiffSpecification(const QTextBlock &inBlock) const
+QString VcsBaseEditorWidget::fileNameFromDiffSpecification(const QTextBlock &inBlock, QString *header) const
{
// Go back chunks
+ QString fileName;
for (QTextBlock block = inBlock; block.isValid(); block = block.previous()) {
const QString line = block.text();
if (d->m_diffFilePattern.indexIn(line) != -1) {
QString cap = d->m_diffFilePattern.cap(1);
- if (!cap.isEmpty())
- return findDiffFile(cap);
+ if (header)
+ header->prepend(line + QLatin1String("\n"));
+ if (fileName.isEmpty() && !cap.isEmpty())
+ fileName = cap;
+ } else if (!fileName.isEmpty()) {
+ return findDiffFile(fileName);
+ } else if (header) {
+ header->clear();
}
}
- return QString();
+ return fileName.isEmpty() ? QString() : findDiffFile(fileName);
}
void VcsBaseEditorWidget::addChangeActions(QMenu *, const QString &)
diff --git a/src/plugins/vcsbase/vcsbaseeditor.h b/src/plugins/vcsbase/vcsbaseeditor.h
index 5bbd78b4d4..b2fd845d9e 100644
--- a/src/plugins/vcsbase/vcsbaseeditor.h
+++ b/src/plugins/vcsbase/vcsbaseeditor.h
@@ -83,6 +83,7 @@ public:
QString fileName;
QByteArray chunk;
+ QByteArray header;
};
class VCSBASE_EXPORT VcsBaseEditorWidget : public TextEditor::BaseTextEditorWidget
@@ -234,6 +235,8 @@ protected:
* source and version control. */
virtual QString findDiffFile(const QString &f) const;
+ virtual void addDiffActions(QMenu *menu, const DiffChunk &chunk);
+
virtual void addChangeActions(QMenu *menu, const QString &change);
// Implement to return a set of change identifiers in
@@ -245,7 +248,7 @@ protected:
virtual BaseAnnotationHighlighter *createAnnotationHighlighter(const QSet<QString> &changes) const = 0;
// Returns a local file name from the diff file specification
// (text cursor at position above change hunk)
- QString fileNameFromDiffSpecification(const QTextBlock &inBlock) const;
+ QString fileNameFromDiffSpecification(const QTextBlock &inBlock, QString *header = 0) const;
// Implement to return decorated annotation change for "Annotate version"
virtual QString decorateVersion(const QString &revision) const;