From bcd020f38209604ed96d44613b4e1c97b09dc615 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint <Friedemann.Kleint@nokia.com> Date: Fri, 19 Mar 2010 16:07:34 +0100 Subject: [PATCH] VCS[git]: Introduce optional pull --rebase. Do 'git rebase --abort' if something fails. --- src/plugins/git/gitclient.cpp | 38 +++++++++++++++++++++++++++++--- src/plugins/git/gitclient.h | 2 ++ src/plugins/git/gitcommand.cpp | 19 +++++++++++++--- src/plugins/git/gitcommand.h | 7 ++++-- src/plugins/git/giteditor.cpp | 2 +- src/plugins/git/giteditor.h | 2 +- src/plugins/git/gitsettings.cpp | 8 ++++++- src/plugins/git/gitsettings.h | 1 + src/plugins/git/settingspage.cpp | 3 +++ src/plugins/git/settingspage.ui | 21 +++++++++++++++--- 10 files changed, 89 insertions(+), 14 deletions(-) diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 6f2a5f5c0e0..ab8094672ba 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -302,7 +302,7 @@ void GitClient::status(const QString &workingDirectory) VCSBase::VCSBaseOutputWindow *outwin = VCSBase::VCSBaseOutputWindow::instance(); outwin->setRepository(workingDirectory); GitCommand *command = executeGit(workingDirectory, statusArgs, 0, true); - connect(command, SIGNAL(finished(bool,QVariant)), outwin, SLOT(clearRepository()), + connect(command, SIGNAL(finished(bool,int,QVariant)), outwin, SLOT(clearRepository()), Qt::QueuedConnection); } @@ -985,7 +985,7 @@ GitCommand *GitClient::createCommand(const QString &workingDirectory, VCSBase::VCSBaseOutputWindow *outputWindow = VCSBase::VCSBaseOutputWindow::instance(); GitCommand* command = new GitCommand(binary(), workingDirectory, processEnvironment(), QVariant(editorLineNumber)); if (editor) - connect(command, SIGNAL(finished(bool,QVariant)), editor, SLOT(commandFinishedGotoLine(bool,QVariant))); + connect(command, SIGNAL(finished(bool,int,QVariant)), editor, SLOT(commandFinishedGotoLine(bool,int,QVariant))); if (outputToWindow) { if (editor) { // assume that the commands output is the important thing connect(command, SIGNAL(outputData(QByteArray)), outputWindow, SLOT(appendDataSilently(QByteArray))); @@ -1445,8 +1445,40 @@ void GitClient::revert(const QStringList &files) void GitClient::pull(const QString &workingDirectory) { - GitCommand *cmd = executeGit(workingDirectory, QStringList(QLatin1String("pull")), 0, true, GitCommand::ReportStderr); + pull(workingDirectory, m_settings.pullRebase); +} + +void GitClient::pull(const QString &workingDirectory, bool rebase) +{ + QStringList arguments(QLatin1String("pull")); + if (rebase) + arguments << QLatin1String("--rebase"); + GitCommand *cmd = executeGit(workingDirectory, arguments, 0, true, GitCommand::ReportStderr); connectRepositoryChanged(workingDirectory, cmd); + // Need to clean up if something goes wrong + if (rebase) { + cmd->setCookie(QVariant(workingDirectory)); + connect(cmd, SIGNAL(finished(bool,int,QVariant)), this, SLOT(slotPullRebaseFinished(bool,int,QVariant)), + Qt::QueuedConnection); + } +} + +void GitClient::slotPullRebaseFinished(bool ok, int exitCode, const QVariant &cookie) +{ + if (ok && exitCode == 0) + return; + // Abort rebase to clean if something goes wrong + VCSBase::VCSBaseOutputWindow *outwin = VCSBase::VCSBaseOutputWindow::instance(); + outwin->appendError(tr("git pull --rebase failed, aborting rebase.")); + const QString workingDir = cookie.toString(); + QStringList arguments; + arguments << QLatin1String("rebase") << QLatin1String("--abort"); + QByteArray stdOut; + QByteArray stdErr; + const bool rc = synchronousGit(workingDir, arguments, &stdOut, &stdErr, true); + outwin->append(commandOutputFromLocal8Bit(stdOut)); + if (!rc) + outwin->appendError(commandOutputFromLocal8Bit(stdErr)); } // Subversion: git svn diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h index b285cd2496a..c81347e32aa 100644 --- a/src/plugins/git/gitclient.h +++ b/src/plugins/git/gitclient.h @@ -213,6 +213,7 @@ public slots: private slots: void slotBlameRevisionRequested(const QString &source, QString change, int lineNumber); + void slotPullRebaseFinished(bool ok, int exitCode, const QVariant &cookie); private: VCSBase::VCSBaseEditor *createVCSEditor(const QString &kind, @@ -245,6 +246,7 @@ private: enum RevertResult { RevertOk, RevertUnchanged, RevertCanceled, RevertFailed }; RevertResult revertI(QStringList files, bool *isDirectory, QString *errorMessage); void connectRepositoryChanged(const QString & repository, GitCommand *cmd); + void pull(const QString &workingDirectory, bool rebase); const QString m_msgWait; GitPlugin *m_plugin; diff --git a/src/plugins/git/gitcommand.cpp b/src/plugins/git/gitcommand.cpp index 1362e0c6709..7483428eb91 100644 --- a/src/plugins/git/gitcommand.cpp +++ b/src/plugins/git/gitcommand.cpp @@ -133,6 +133,7 @@ void GitCommand::run() QString error; const int count = m_jobs.size(); + int exitCode = -1; bool ok = true; for (int j = 0; j < count; j++) { if (Git::Constants::debug) @@ -156,14 +157,15 @@ void GitCommand::run() } error += QString::fromLocal8Bit(stdErr); + exitCode = process.exitCode(); switch (m_reportTerminationMode) { case NoReport: break; case ReportStdout: - stdOut += msgTermination(process.exitCode(), m_binaryPath, m_jobs.at(j).arguments).toUtf8(); + stdOut += msgTermination(exitCode, m_binaryPath, m_jobs.at(j).arguments).toUtf8(); break; case ReportStderr: - error += msgTermination(process.exitCode(), m_binaryPath, m_jobs.at(j).arguments); + error += msgTermination(exitCode, m_binaryPath, m_jobs.at(j).arguments); break; } } @@ -183,7 +185,7 @@ void GitCommand::run() if (!error.isEmpty()) emit errorText(error); - emit finished(ok, m_cookie); + emit finished(ok, exitCode, m_cookie); if (ok) emit success(); // As it is used asynchronously, we need to delete ourselves @@ -213,5 +215,16 @@ void GitCommand::removeColorCodes(QByteArray *data) } } +void GitCommand::setCookie(const QVariant &cookie) +{ + m_cookie = cookie; +} + +QVariant GitCommand::cookie() const +{ + return m_cookie; +} + + } // namespace Internal } // namespace Git diff --git a/src/plugins/git/gitcommand.h b/src/plugins/git/gitcommand.h index 1e7dce1f248..c9cc058d019 100644 --- a/src/plugins/git/gitcommand.h +++ b/src/plugins/git/gitcommand.h @@ -72,13 +72,16 @@ public: static QString msgTimeout(int seconds); + void setCookie(const QVariant &cookie); + QVariant cookie() const; + private: void run(); Q_SIGNALS: void outputData(const QByteArray&); void errorText(const QString&); - void finished(bool ok, const QVariant &cookie); + void finished(bool ok, int exitCode, const QVariant &cookie); void success(); private: @@ -93,7 +96,7 @@ private: QStringList m_basicArguments; const QString m_workingDirectory; const QStringList m_environment; - const QVariant m_cookie; + QVariant m_cookie; QList<Job> m_jobs; TerminationReportMode m_reportTerminationMode; diff --git a/src/plugins/git/giteditor.cpp b/src/plugins/git/giteditor.cpp index 012317c3a33..bb89ffdc3c1 100644 --- a/src/plugins/git/giteditor.cpp +++ b/src/plugins/git/giteditor.cpp @@ -179,7 +179,7 @@ void GitEditor::setPlainTextDataFiltered(const QByteArray &a) } } -void GitEditor::commandFinishedGotoLine(bool ok, const QVariant &v) +void GitEditor::commandFinishedGotoLine(bool ok, int /* exitCode */, const QVariant &v) { if (ok && v.type() == QVariant::Int) { const int line = v.toInt(); diff --git a/src/plugins/git/giteditor.h b/src/plugins/git/giteditor.h index 962a05694b4..c82a501e545 100644 --- a/src/plugins/git/giteditor.h +++ b/src/plugins/git/giteditor.h @@ -52,7 +52,7 @@ public: public slots: void setPlainTextDataFiltered(const QByteArray &a); // Matches the signature of the finished signal of GitCommand - void commandFinishedGotoLine(bool ok, const QVariant &v); + void commandFinishedGotoLine(bool ok, int exitCode, const QVariant &v); private: virtual QSet<QString> annotationChanges() const; diff --git a/src/plugins/git/gitsettings.cpp b/src/plugins/git/gitsettings.cpp index b5831f5e10f..9d67fcb2b7b 100644 --- a/src/plugins/git/gitsettings.cpp +++ b/src/plugins/git/gitsettings.cpp @@ -41,13 +41,15 @@ static const char sysEnvKeyC[] = "SysEnv"; static const char pathKeyC[] = "Path"; static const char logCountKeyC[] = "LogCount"; static const char timeoutKeyC[] = "TimeOut"; +static const char pullRebaseKeyC[] = "PullRebase"; static const char promptToSubmitKeyC[] = "PromptForSubmit"; static const char omitAnnotationDateKeyC[] = "OmitAnnotationDate"; static const char spaceIgnorantBlameKeyC[] = "SpaceIgnorantBlame"; static const char diffPatienceKeyC[] = "DiffPatience"; enum { - defaultLogCount = 100 , + defaultPullRebase = 0, + defaultLogCount = 100, #ifdef Q_OS_WIN defaultTimeOut = 60 #else @@ -62,6 +64,7 @@ GitSettings::GitSettings() : adoptPath(false), logCount(defaultLogCount), timeoutSeconds(defaultTimeOut), + pullRebase(bool(defaultPullRebase)), promptToSubmit(true), omitAnnotationDate(false), spaceIgnorantBlame(true), @@ -76,6 +79,7 @@ void GitSettings::fromSettings(QSettings *settings) path = settings->value(QLatin1String(pathKeyC), QString()).toString(); logCount = settings->value(QLatin1String(logCountKeyC), defaultLogCount).toInt(); timeoutSeconds = settings->value(QLatin1String(timeoutKeyC), defaultTimeOut).toInt(); + pullRebase = settings->value(QLatin1String(pullRebaseKeyC), bool(defaultPullRebase)).toBool(); promptToSubmit = settings->value(QLatin1String(promptToSubmitKeyC), true).toBool(); omitAnnotationDate = settings->value(QLatin1String(omitAnnotationDateKeyC), false).toBool(); spaceIgnorantBlame = settings->value(QLatin1String(spaceIgnorantBlameKeyC), true).toBool(); @@ -90,6 +94,7 @@ void GitSettings::toSettings(QSettings *settings) const settings->setValue(QLatin1String(pathKeyC), path); settings->setValue(QLatin1String(logCountKeyC), logCount); settings->setValue(QLatin1String(timeoutKeyC), timeoutSeconds); + settings->setValue(QLatin1String(pullRebaseKeyC), pullRebase); settings->setValue(QLatin1String(promptToSubmitKeyC), promptToSubmit); settings->setValue(QLatin1String(omitAnnotationDateKeyC), omitAnnotationDate); settings->setValue(QLatin1String(spaceIgnorantBlameKeyC), spaceIgnorantBlame); @@ -101,6 +106,7 @@ bool GitSettings::equals(const GitSettings &s) const { return adoptPath == s.adoptPath && path == s.path && logCount == s.logCount && timeoutSeconds == s.timeoutSeconds && promptToSubmit == s.promptToSubmit + && pullRebase == s.pullRebase && omitAnnotationDate == s.omitAnnotationDate && spaceIgnorantBlame == s.spaceIgnorantBlame && diffPatience == s.diffPatience; } diff --git a/src/plugins/git/gitsettings.h b/src/plugins/git/gitsettings.h index e103ae33aee..b3c51595ab6 100644 --- a/src/plugins/git/gitsettings.h +++ b/src/plugins/git/gitsettings.h @@ -55,6 +55,7 @@ struct GitSettings QString path; int logCount; int timeoutSeconds; + bool pullRebase; bool promptToSubmit; bool omitAnnotationDate; bool spaceIgnorantBlame; diff --git a/src/plugins/git/settingspage.cpp b/src/plugins/git/settingspage.cpp index 3aa9e6c02ea..11edb065ce3 100644 --- a/src/plugins/git/settingspage.cpp +++ b/src/plugins/git/settingspage.cpp @@ -56,6 +56,7 @@ GitSettings SettingsPageWidget::settings() const rc.adoptPath = m_ui.environmentGroupBox->isChecked() && !rc.path.isEmpty(); rc.logCount = m_ui.logCountSpinBox->value(); rc.timeoutSeconds = m_ui.timeoutSpinBox->value(); + rc.pullRebase = m_ui.pullRebaseCheckBox->isChecked(); rc.promptToSubmit = m_ui.promptToSubmitCheckBox->isChecked(); rc.omitAnnotationDate = m_ui.omitAnnotationDataCheckBox->isChecked(); rc.spaceIgnorantBlame = m_ui.spaceIgnorantBlameCheckBox->isChecked(); @@ -69,6 +70,7 @@ void SettingsPageWidget::setSettings(const GitSettings &s) m_ui.pathLineEdit->setText(s.path); m_ui.logCountSpinBox->setValue(s.logCount); m_ui.timeoutSpinBox->setValue(s.timeoutSeconds); + m_ui.pullRebaseCheckBox->setChecked(s.pullRebase); m_ui.promptToSubmitCheckBox->setChecked(s.promptToSubmit); m_ui.omitAnnotationDataCheckBox->setChecked(s.omitAnnotationDate); m_ui.spaceIgnorantBlameCheckBox->setChecked(s.spaceIgnorantBlame); @@ -86,6 +88,7 @@ QString SettingsPageWidget::searchKeywords() const QTextStream(&rc) << ' ' << m_ui.pathlabel->text() << ' ' << m_ui.logCountLabel->text() << ' ' << m_ui.timeoutLabel->text() << ' ' << m_ui.promptToSubmitCheckBox->text() + << ' ' << m_ui.promptToSubmitCheckBox->text() << ' ' << m_ui.omitAnnotationDataCheckBox->text() << ' ' << m_ui.environmentGroupBox->title() << ' ' << m_ui.spaceIgnorantBlameCheckBox->text(); diff --git a/src/plugins/git/settingspage.ui b/src/plugins/git/settingspage.ui index 443a9e52b5d..159c3774f3a 100644 --- a/src/plugins/git/settingspage.ui +++ b/src/plugins/git/settingspage.ui @@ -2,6 +2,14 @@ <ui version="4.0"> <class>Git::Internal::SettingsPage</class> <widget class="QWidget" name="Git::Internal::SettingsPage"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>409</width> + <height>385</height> + </rect> + </property> <layout class="QVBoxLayout" name="verticalLayout"> <item> <widget class="QGroupBox" name="environmentGroupBox"> @@ -113,27 +121,34 @@ </property> </widget> </item> - <item row="4" column="0" colspan="2"> + <item row="5" column="0" colspan="2"> <widget class="QCheckBox" name="omitAnnotationDataCheckBox"> <property name="text"> <string>Omit date from annotation output</string> </property> </widget> </item> - <item row="5" column="0" colspan="2"> + <item row="6" column="0" colspan="2"> <widget class="QCheckBox" name="spaceIgnorantBlameCheckBox"> <property name="text"> <string>Ignore whitespace changes in annotation</string> </property> </widget> </item> - <item row="3" column="0"> + <item row="4" column="0"> <widget class="QCheckBox" name="diffPatienceCheckBox"> <property name="text"> <string>Use "patience diff" algorithm</string> </property> </widget> </item> + <item row="3" column="0" colspan="2"> + <widget class="QCheckBox" name="pullRebaseCheckBox"> + <property name="text"> + <string>Pull with rebase</string> + </property> + </widget> + </item> </layout> </widget> </item> -- GitLab