diff --git a/src/plugins/coreplugin/coreplugin.pro b/src/plugins/coreplugin/coreplugin.pro index d38f93fbe61..f00e51df820 100644 --- a/src/plugins/coreplugin/coreplugin.pro +++ b/src/plugins/coreplugin/coreplugin.pro @@ -97,7 +97,8 @@ SOURCES += mainwindow.cpp \ iversioncontrol.cpp \ dialogs/addtovcsdialog.cpp \ icorelistener.cpp \ - ioutputpane.cpp + ioutputpane.cpp \ + patchtool.cpp HEADERS += mainwindow.h \ editmode.h \ @@ -194,7 +195,8 @@ HEADERS += mainwindow.h \ textdocument.h \ documentmanager.h \ removefiledialog.h \ - dialogs/addtovcsdialog.h + dialogs/addtovcsdialog.h \ + patchtool.h FORMS += dialogs/newdialog.ui \ dialogs/saveitemsdialog.ui \ diff --git a/src/plugins/coreplugin/coreplugin.qbs b/src/plugins/coreplugin/coreplugin.qbs index 5220e3464e8..340541f1f94 100644 --- a/src/plugins/coreplugin/coreplugin.qbs +++ b/src/plugins/coreplugin/coreplugin.qbs @@ -75,6 +75,7 @@ QtcPlugin { "outputpane.cpp", "outputpane.h", "outputpanemanager.cpp", "outputpanemanager.h", "outputwindow.cpp", "outputwindow.h", + "patchtool.cpp" "patchtool.h" "plugindialog.cpp", "plugindialog.h", "removefiledialog.cpp", "removefiledialog.h", "removefiledialog.ui", "rightpane.cpp", "rightpane.h", diff --git a/src/plugins/coreplugin/generalsettings.cpp b/src/plugins/coreplugin/generalsettings.cpp index f1f3fe46258..0e8e9c187aa 100644 --- a/src/plugins/coreplugin/generalsettings.cpp +++ b/src/plugins/coreplugin/generalsettings.cpp @@ -31,6 +31,8 @@ #include "coreconstants.h" #include "icore.h" #include "infobar.h" +#include "patchtool.h" +#include "vcsmanager.h" #include "editormanager/editormanager.h" #include @@ -38,6 +40,7 @@ #include #include #include +#include #include @@ -136,6 +139,12 @@ QWidget *GeneralSettings::widget() m_page->helpExternalFileBrowserButton->hide(); } + const QString patchToolTip = tr("Command used for reverting diff chunks."); + m_page->patchCommandLabel->setToolTip(patchToolTip); + m_page->patchChooser->setToolTip(patchToolTip); + m_page->patchChooser->setExpectedKind(Utils::PathChooser::ExistingCommand); + m_page->patchChooser->setHistoryCompleter(QLatin1String("General.PatchCommand.History")); + m_page->patchChooser->setPath(Core::PatchTool::patchCommand()); m_page->autoSaveCheckBox->setChecked(EditorManager::autoSaveEnabled()); m_page->autoSaveInterval->setValue(EditorManager::autoSaveInterval()); m_page->resetWarningsButton->setEnabled(Core::InfoBar::anyGloballySuppressed() @@ -153,6 +162,11 @@ QWidget *GeneralSettings::widget() this, SLOT(showHelpForFileBrowser())); } } + + updatePath(); + + connect(Core::VcsManager::instance(), SIGNAL(configurationChanged(const IVersionControl*)), + this, SLOT(updatePath())); } return m_widget; } @@ -174,6 +188,7 @@ void GeneralSettings::apply() m_page->externalFileBrowserEdit->text()); } } + Core::PatchTool::setPatchCommand(m_page->patchChooser->path()); EditorManager::setAutoSaveEnabled(m_page->autoSaveCheckBox->isChecked()); EditorManager::setAutoSaveInterval(m_page->autoSaveInterval->value()); } @@ -211,6 +226,13 @@ void GeneralSettings::resetFileBrowser() m_page->externalFileBrowserEdit->setText(UnixUtils::defaultFileBrowser()); } +void GeneralSettings::updatePath() +{ + Utils::Environment env = Utils::Environment::systemEnvironment(); + QStringList toAdd = Core::VcsManager::additionalToolsPath(); + env.appendOrSetPath(toAdd.join(QString(Utils::HostOsInfo::pathListSeparator()))); + m_page->patchChooser->setEnvironment(env); +} void GeneralSettings::variableHelpDialogCreator(const QString &helpText) { diff --git a/src/plugins/coreplugin/generalsettings.h b/src/plugins/coreplugin/generalsettings.h index dd3186df2b4..e6d81c43286 100644 --- a/src/plugins/coreplugin/generalsettings.h +++ b/src/plugins/coreplugin/generalsettings.h @@ -60,6 +60,7 @@ private slots: void showHelpForFileBrowser(); void resetFileBrowser(); void resetTerminal(); + void updatePath(); private: void variableHelpDialogCreator(const QString &helpText); diff --git a/src/plugins/coreplugin/generalsettings.ui b/src/plugins/coreplugin/generalsettings.ui index 562fa3d784e..33651b785b2 100644 --- a/src/plugins/coreplugin/generalsettings.ui +++ b/src/plugins/coreplugin/generalsettings.ui @@ -181,7 +181,17 @@ - + + + + Patch command: + + + + + + + @@ -227,7 +237,7 @@ - + @@ -314,6 +324,16 @@ QToolButton
utils/qtcolorbutton.h
+ + Utils::PathChooser + QWidget +
utils/pathchooser.h
+ 1 + + editingFinished() + browsingFinished() + +
diff --git a/src/plugins/coreplugin/patchtool.cpp b/src/plugins/coreplugin/patchtool.cpp new file mode 100644 index 00000000000..90c38d7102e --- /dev/null +++ b/src/plugins/coreplugin/patchtool.cpp @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "patchtool.h" +#include "messagemanager.h" +#include "icore.h" +#include + +#include +#include +#include + +static const char settingsGroupC[] = "General"; +static const char legacySettingsGroupC[] = "VCS"; +static const char patchCommandKeyC[] = "PatchCommand"; +static const char patchCommandDefaultC[] = "patch"; + +namespace Core { + +static QString readLegacyCommand() +{ + QSettings *s = Core::ICore::settings(); + + s->beginGroup(QLatin1String(legacySettingsGroupC)); + const bool legacyExists = s->contains(QLatin1String(patchCommandKeyC)); + const QString legacyCommand = s->value(QLatin1String(patchCommandKeyC), QLatin1String(patchCommandDefaultC)).toString(); + if (legacyExists) + s->remove(QLatin1String(patchCommandKeyC)); + s->endGroup(); + + if (legacyExists && legacyCommand != QLatin1String(patchCommandDefaultC)) + PatchTool::setPatchCommand(legacyCommand); + + return legacyCommand; +} + +QString PatchTool::patchCommand() +{ + QSettings *s = Core::ICore::settings(); + + const QString defaultCommand = readLegacyCommand(); // replace it with QLatin1String(patchCommandDefaultC) when dropping legacy stuff + + s->beginGroup(QLatin1String(settingsGroupC)); + const QString command = s->value(QLatin1String(patchCommandKeyC), defaultCommand).toString(); + s->endGroup(); + + return command; +} + +void PatchTool::setPatchCommand(const QString &newCommand) +{ + QSettings *s = Core::ICore::settings(); + s->beginGroup(QLatin1String(settingsGroupC)); + s->setValue(QLatin1String(patchCommandKeyC), newCommand); + s->endGroup(); +} + +bool PatchTool::runPatch(const QByteArray &input, const QString &workingDirectory, + int strip, bool reverse) +{ + const QString patch = patchCommand(); + if (patch.isEmpty()) { + MessageManager::write(QApplication::translate("Core::PatchTool", "There is no patch-command configured in the general \"Environment\" settings.")); + return false; + } + + QProcess patchProcess; + if (!workingDirectory.isEmpty()) + patchProcess.setWorkingDirectory(workingDirectory); + QStringList args(QLatin1String("-p") + QString::number(strip)); + if (reverse) + args << QLatin1String("-R"); + MessageManager::write(QApplication::translate("Core::PatchTool", "Executing in %1: %2 %3"). + arg(QDir::toNativeSeparators(workingDirectory), + QDir::toNativeSeparators(patch), args.join(QLatin1String(" ")))); + patchProcess.start(patch, args); + if (!patchProcess.waitForStarted()) { + MessageManager::write(QApplication::translate("Core::PatchTool", "Unable to launch \"%1\": %2").arg(patch, patchProcess.errorString())); + return false; + } + patchProcess.write(input); + patchProcess.closeWriteChannel(); + QByteArray stdOut; + QByteArray stdErr; + if (!Utils::SynchronousProcess::readDataFromProcess(patchProcess, 30000, &stdOut, &stdErr, true)) { + Utils::SynchronousProcess::stopProcess(patchProcess); + MessageManager::write(QApplication::translate("Core::PatchTool", "A timeout occurred running \"%1\"").arg(patch)); + return false; + + } + if (!stdOut.isEmpty()) + MessageManager::write(QString::fromLocal8Bit(stdOut)); + if (!stdErr.isEmpty()) + MessageManager::write(QString::fromLocal8Bit(stdErr)); + + if (patchProcess.exitStatus() != QProcess::NormalExit) { + MessageManager::write(QApplication::translate("Core::PatchTool", "\"%1\" crashed.").arg(patch)); + return false; + } + if (patchProcess.exitCode() != 0) { + MessageManager::write(QApplication::translate("Core::PatchTool", "\"%1\" failed (exit code %2).").arg(patch).arg(patchProcess.exitCode())); + return false; + } + return true; +} + + +} // namespace Core diff --git a/src/plugins/coreplugin/patchtool.h b/src/plugins/coreplugin/patchtool.h new file mode 100644 index 00000000000..30c3b7bfe98 --- /dev/null +++ b/src/plugins/coreplugin/patchtool.h @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef CORE_PATCHTOOL_H +#define CORE_PATCHTOOL_H + +#include "coreplugin/core_global.h" + +#include + +namespace Core { + +class CORE_EXPORT PatchTool +{ +public: + static QString patchCommand(); + static void setPatchCommand(const QString &newCommand); + + // Utility to run the 'patch' command + static bool runPatch(const QByteArray &input, const QString &workingDirectory = QString(), + int strip = 0, bool reverse = false); +}; + +} // namespace Core + +#endif // CORE_PATCHTOOL_H diff --git a/src/plugins/vcsbase/commonsettingspage.cpp b/src/plugins/vcsbase/commonsettingspage.cpp index 2ac0c6af3b1..9923833ddac 100644 --- a/src/plugins/vcsbase/commonsettingspage.cpp +++ b/src/plugins/vcsbase/commonsettingspage.cpp @@ -58,11 +58,6 @@ CommonSettingsWidget::CommonSettingsWidget(QWidget *parent) : m_ui->nickNameMailMapChooser->setHistoryCompleter(QLatin1String("Vcs.NickMap.History")); m_ui->sshPromptChooser->setExpectedKind(Utils::PathChooser::ExistingCommand); m_ui->sshPromptChooser->setHistoryCompleter(QLatin1String("Vcs.SshPrompt.History")); - const QString patchToolTip = tr("Command used for reverting diff chunks."); - m_ui->patchCommandLabel->setToolTip(patchToolTip); - m_ui->patchChooser->setToolTip(patchToolTip); - m_ui->patchChooser->setExpectedKind(Utils::PathChooser::ExistingCommand); - m_ui->patchChooser->setHistoryCompleter(QLatin1String("Vcs.PatchCommand.History")); updatePath(); @@ -84,7 +79,6 @@ CommonVcsSettings CommonSettingsWidget::settings() const rc.lineWrap= m_ui->lineWrapCheckBox->isChecked(); rc.lineWrapWidth = m_ui->lineWrapSpinBox->value(); rc.sshPasswordPrompt = m_ui->sshPromptChooser->path(); - rc.patchCommand = m_ui->patchChooser->path(); return rc; } @@ -96,21 +90,6 @@ void CommonSettingsWidget::setSettings(const CommonVcsSettings &s) m_ui->lineWrapCheckBox->setChecked(s.lineWrap); m_ui->lineWrapSpinBox->setValue(s.lineWrapWidth); m_ui->sshPromptChooser->setPath(s.sshPasswordPrompt); - m_ui->patchChooser->setPath(s.patchCommand); -} - -QString CommonSettingsWidget::searchKeyWordMatchString() const -{ - const QChar blank = QLatin1Char(' '); - QString rc = m_ui->lineWrapCheckBox->text() - + blank + m_ui->submitMessageCheckScriptLabel->text() - + blank + m_ui->nickNameMailMapLabel->text() - + blank + m_ui->nickNameFieldsFileLabel->text() - + blank + m_ui->sshPromptLabel->text() - + blank + m_ui->patchCommandLabel->text() - ; - rc.remove(QLatin1Char('&')); // Strip buddy markers. - return rc; } void CommonSettingsWidget::updatePath() @@ -118,7 +97,6 @@ void CommonSettingsWidget::updatePath() Utils::Environment env = Utils::Environment::systemEnvironment(); QStringList toAdd = Core::VcsManager::additionalToolsPath(); env.appendOrSetPath(toAdd.join(QString(Utils::HostOsInfo::pathListSeparator()))); - m_ui->patchChooser->setEnvironment(env); m_ui->sshPromptChooser->setEnvironment(env); } diff --git a/src/plugins/vcsbase/commonsettingspage.h b/src/plugins/vcsbase/commonsettingspage.h index 67e5428f52b..291f6f02c5a 100644 --- a/src/plugins/vcsbase/commonsettingspage.h +++ b/src/plugins/vcsbase/commonsettingspage.h @@ -53,8 +53,6 @@ public: CommonVcsSettings settings() const; void setSettings(const CommonVcsSettings &s); - QString searchKeyWordMatchString() const; - private slots: void updatePath(); diff --git a/src/plugins/vcsbase/commonsettingspage.ui b/src/plugins/vcsbase/commonsettingspage.ui index 99b43c85947..b0c2d6f07bb 100644 --- a/src/plugins/vcsbase/commonsettingspage.ui +++ b/src/plugins/vcsbase/commonsettingspage.ui @@ -119,19 +119,6 @@ should a repository require SSH-authentication (see documentation on SSH and the - - - - &Patch command: - - - patchChooser - - - - - -
diff --git a/src/plugins/vcsbase/commonvcssettings.cpp b/src/plugins/vcsbase/commonvcssettings.cpp index a93cd7827cc..e439e012a9e 100644 --- a/src/plugins/vcsbase/commonvcssettings.cpp +++ b/src/plugins/vcsbase/commonvcssettings.cpp @@ -41,8 +41,6 @@ static const char submitMessageCheckScriptKeyC[] = "SubmitMessageCheckScript"; static const char lineWrapKeyC[] = "LineWrap"; static const char lineWrapWidthKeyC[] = "LineWrapWidth"; static const char sshPasswordPromptKeyC[] = "SshPasswordPrompt"; -static const char patchCommandKeyC[] = "PatchCommand"; -static const char patchCommandDefaultC[] = "patch"; static const int lineWrapWidthDefault = 72; static const bool lineWrapDefault = true; @@ -63,7 +61,6 @@ namespace Internal { CommonVcsSettings::CommonVcsSettings() : sshPasswordPrompt(sshPasswordPromptDefault()), - patchCommand(QLatin1String(patchCommandDefaultC)), lineWrap(lineWrapDefault), lineWrapWidth(lineWrapWidthDefault) { @@ -77,7 +74,6 @@ void CommonVcsSettings::toSettings(QSettings *s) const s->setValue(QLatin1String(submitMessageCheckScriptKeyC), submitMessageCheckScript); s->setValue(QLatin1String(lineWrapKeyC), lineWrap); s->setValue(QLatin1String(lineWrapWidthKeyC), lineWrapWidth); - s->setValue(QLatin1String(patchCommandKeyC), patchCommand); // Do not store the default setting to avoid clobbering the environment. if (sshPasswordPrompt != sshPasswordPromptDefault()) s->setValue(QLatin1String(sshPasswordPromptKeyC), sshPasswordPrompt); @@ -95,7 +91,6 @@ void CommonVcsSettings::fromSettings(QSettings *s) lineWrap = s->value(QLatin1String(lineWrapKeyC), lineWrapDefault).toBool(); lineWrapWidth = s->value(QLatin1String(lineWrapWidthKeyC), lineWrapWidthDefault).toInt(); sshPasswordPrompt = s->value(QLatin1String(sshPasswordPromptKeyC), sshPasswordPromptDefault()).toString(); - patchCommand = s->value(QLatin1String(patchCommandKeyC), QLatin1String(patchCommandDefaultC)).toString(); s->endGroup(); } @@ -106,8 +101,7 @@ bool CommonVcsSettings::equals(const CommonVcsSettings &rhs) const && nickNameMailMap == rhs.nickNameMailMap && nickNameFieldListFile == rhs.nickNameFieldListFile && submitMessageCheckScript == rhs.submitMessageCheckScript - && sshPasswordPrompt == rhs.sshPasswordPrompt - && patchCommand == rhs.patchCommand; + && sshPasswordPrompt == rhs.sshPasswordPrompt; } QDebug operator<<(QDebug d,const CommonVcsSettings& s) @@ -118,7 +112,6 @@ QDebug operator<<(QDebug d,const CommonVcsSettings& s) << "' nickNameFieldListFile='" << s.nickNameFieldListFile << "'submitMessageCheckScript='" << s.submitMessageCheckScript << "'sshPasswordPrompt='" << s.sshPasswordPrompt - << "'patchCommand='" << s.patchCommand << "'\n"; return d; } diff --git a/src/plugins/vcsbase/commonvcssettings.h b/src/plugins/vcsbase/commonvcssettings.h index 380711acd2d..4f11c37b0ed 100644 --- a/src/plugins/vcsbase/commonvcssettings.h +++ b/src/plugins/vcsbase/commonvcssettings.h @@ -54,8 +54,6 @@ public: // Executable run to graphically prompt for a SSH-password. QString sshPasswordPrompt; - QString patchCommand; - bool lineWrap; int lineWrapWidth; diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp index 92c90b3bf93..dedad678ae5 100644 --- a/src/plugins/vcsbase/vcsbaseeditor.cpp +++ b/src/plugins/vcsbase/vcsbaseeditor.cpp @@ -36,6 +36,7 @@ #include #include +#include #include #include #include @@ -1449,7 +1450,7 @@ bool VcsBaseEditorWidget::canApplyDiffChunk(const DiffChunk &dc) const // (passing '-R' for revert), assuming we got absolute paths from the VCS plugins. bool VcsBaseEditorWidget::applyDiffChunk(const DiffChunk &dc, bool revert) const { - return VcsBasePlugin::runPatch(dc.asPatch(d->m_workingDirectory), + return Core::PatchTool::runPatch(dc.asPatch(d->m_workingDirectory), d->m_workingDirectory, 0, revert); } diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp index 8448d6838f2..49042f71d54 100644 --- a/src/plugins/vcsbase/vcsbaseplugin.cpp +++ b/src/plugins/vcsbase/vcsbaseplugin.cpp @@ -784,54 +784,6 @@ SynchronousProcessResponse VcsBasePlugin::runVcs(const QString &workingDir, return command.runVcs(arguments, timeOutMS); } -bool VcsBasePlugin::runPatch(const QByteArray &input, const QString &workingDirectory, - int strip, bool reverse) -{ - VcsBaseOutputWindow *ow = VcsBaseOutputWindow::instance(); - const QString patch = Internal::VcsPlugin::instance()->settings().patchCommand; - if (patch.isEmpty()) { - ow->appendError(tr("There is no patch-command configured in the common 'Version Control' settings.")); - return false; - } - - QProcess patchProcess; - if (!workingDirectory.isEmpty()) - patchProcess.setWorkingDirectory(workingDirectory); - QStringList args(QLatin1String("-p") + QString::number(strip)); - if (reverse) - args << QLatin1String("-R"); - ow->appendCommand(workingDirectory, patch, args); - patchProcess.start(patch, args); - if (!patchProcess.waitForStarted()) { - ow->appendError(tr("Unable to launch \"%1\": %2").arg(patch, patchProcess.errorString())); - return false; - } - patchProcess.write(input); - patchProcess.closeWriteChannel(); - QByteArray stdOut; - QByteArray stdErr; - if (!SynchronousProcess::readDataFromProcess(patchProcess, 30000, &stdOut, &stdErr, true)) { - SynchronousProcess::stopProcess(patchProcess); - ow->appendError(tr("A timeout occurred running \"%1\"").arg(patch)); - return false; - - } - if (!stdOut.isEmpty()) - ow->append(QString::fromLocal8Bit(stdOut)); - if (!stdErr.isEmpty()) - ow->appendError(QString::fromLocal8Bit(stdErr)); - - if (patchProcess.exitStatus() != QProcess::NormalExit) { - ow->appendError(tr("\"%1\" crashed.").arg(patch)); - return false; - } - if (patchProcess.exitCode() != 0) { - ow->appendError(tr("\"%1\" failed (exit code %2).").arg(patch).arg(patchProcess.exitCode())); - return false; - } - return true; -} - } // namespace VcsBase #include "vcsbaseplugin.moc" diff --git a/src/plugins/vcsbase/vcsbaseplugin.h b/src/plugins/vcsbase/vcsbaseplugin.h index 9f5f23442be..bd5c241da08 100644 --- a/src/plugins/vcsbase/vcsbaseplugin.h +++ b/src/plugins/vcsbase/vcsbaseplugin.h @@ -187,10 +187,6 @@ public: QTextCodec *outputCodec = 0, const QProcessEnvironment &env = QProcessEnvironment()); - // Utility to run the 'patch' command - static bool runPatch(const QByteArray &input, const QString &workingDirectory = QString(), - int strip = 0, bool reverse = false); - public slots: // Convenience slot for "Delete current file" action. Prompts to // delete the file via VcsManager.