VCS[git], CodePaster: Add support for applying patches.

Modify CodePaster::fetch to do a mimetype detection on the
content, create a filename with the matching extension and
open that file.
This gives correct syntax highlighting  and makes "Save as"
more convenient. Keep the file around and delete on exit.

Modify patch mimetype with some content detection (higher priority
than C++).

Add a "current patch file" to the VCSBasePlugin::State. Add "Apply
patch" to git with whitespace fix.
This commit is contained in:
Friedemann Kleint
2010-03-25 16:23:37 +01:00
parent 37acb3b8d1
commit de28b61cca
9 changed files with 301 additions and 13 deletions

View File

@@ -50,6 +50,8 @@
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/filemanager.h>
#include <utils/qtcassert.h>
#include <utils/parameteraction.h>
@@ -126,6 +128,7 @@ GitPlugin::GitPlugin() :
m_undoAction(0),
m_redoAction(0),
m_menuAction(0),
m_applyCurrentFilePatchAction(0),
m_gitClient(0),
m_changeSelectionDialog(0),
m_submitActionTriggered(false)
@@ -386,6 +389,20 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *errorMessage)
tr("Log Repository"), QLatin1String("Git.LogRepository"),
globalcontext, true, &GitClient::graphLog);
// Apply current file as patch is handled specially.
parameterActionCommand =
createParameterAction(actionManager, gitContainer,
tr("Apply Patch"), tr("Apply \"%1\""),
QLatin1String("Git.ApplyCurrentFilePatch"),
globalcontext, true);
m_applyCurrentFilePatchAction = parameterActionCommand.first;
connect(m_applyCurrentFilePatchAction, SIGNAL(triggered()), this,
SLOT(applyCurrentFilePatch()));
createRepositoryAction(actionManager, gitContainer,
tr("Apply Patch..."), QLatin1String("Git.ApplyPatch"),
globalcontext, true, SLOT(promptApplyPatch()));
createRepositoryAction(actionManager, gitContainer,
tr("Undo Repository Changes"), QLatin1String("Git.UndoRepository"),
globalcontext, false, SLOT(undoRepositoryChanges()));
@@ -805,6 +822,74 @@ void GitPlugin::cleanRepository(const QString &directory)
dialog.exec();
}
// If the file is modified in an editor, make sure it is saved.
static bool ensureFileSaved(const QString &fileName)
{
const QList<Core::IEditor*> editors = Core::EditorManager::instance()->editorsForFileName(fileName);
if (editors.isEmpty())
return true;
Core::IFile *file = editors.front()->file();
if (!file || !file->isModified())
return true;
Core::FileManager *fm = Core::ICore::instance()->fileManager();
bool canceled;
QList<Core::IFile *> files;
files << file;
fm->saveModifiedFiles(files, &canceled);
return !canceled;
}
void GitPlugin::applyCurrentFilePatch()
{
const VCSBase::VCSBasePluginState state = currentState();
QTC_ASSERT(state.hasPatchFile() && state.hasTopLevel(), return);
const QString patchFile = state.currentPatchFile();
if (!ensureFileSaved(patchFile))
return;
applyPatch(state.topLevel(), patchFile);
}
void GitPlugin::promptApplyPatch()
{
const VCSBase::VCSBasePluginState state = currentState();
QTC_ASSERT(state.hasTopLevel(), return);
applyPatch(state.topLevel(), QString());
}
void GitPlugin::applyPatch(const QString &workingDirectory, QString file)
{
// Ensure user has been notified about pending changes
switch (m_gitClient->ensureStash(workingDirectory)) {
case GitClient::StashUnchanged:
case GitClient::Stashed:
case GitClient::NotStashed:
break;
default:
return;
}
// Prompt for file
if (file.isEmpty()) {
const QString filter = tr("Patches (*.patch *.diff)");
file = QFileDialog::getOpenFileName(Core::ICore::instance()->mainWindow(),
tr("Choose patch"),
QString(), filter);
if (file.isEmpty())
return;
}
// Run!
VCSBase::VCSBaseOutputWindow *outwin = VCSBase::VCSBaseOutputWindow::instance();
QString errorMessage;
if (m_gitClient->synchronousApplyPatch(workingDirectory, file, &errorMessage)) {
if (errorMessage.isEmpty()) {
outwin->append(tr("Patch %1 successfully applied to %2").arg(file, workingDirectory));
} else {
outwin->append(errorMessage);
}
} else {
outwin->appendError(errorMessage);
}
}
void GitPlugin::stash()
{
// Simple stash without prompt, reset repo.
@@ -866,6 +951,8 @@ void GitPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as)
const QString fileName = currentState().currentFileName();
foreach (Utils::ParameterAction *fileAction, m_fileActions)
fileAction->setParameter(fileName);
// If the current file looks like a patch, offer to apply
m_applyCurrentFilePatchAction->setParameter(currentState().currentPatchFileDisplayName());
const QString projectName = currentState().currentProjectName();
foreach (Utils::ParameterAction *projectAction, m_projectActions)