diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index f4a0feb33e7f60ce8a56a83b794505535d9bc6f5..83dafdc1b668cdfcbb335ea1599446464f1c0ddf 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -379,6 +379,23 @@ bool GitClient::synchronousCheckout(const QString &workingDirectory, return true; } +bool GitClient::synchronousStash(const QString &workingDirectory, QString *errorMessage) +{ + if (Git::Constants::debug) + qDebug() << Q_FUNC_INFO << workingDirectory; + QByteArray outputText; + QByteArray errorText; + QStringList arguments; + arguments << QLatin1String("stash"); + const bool rc = synchronousGit(workingDirectory, arguments, &outputText, &errorText); + if (!rc) { + *errorMessage = tr("Unable stash in %1: %2").arg(workingDirectory, QString::fromLocal8Bit(errorText)); + return false; + } + return true; +} + + void GitClient::executeGit(const QString &workingDirectory, const QStringList &arguments, VCSBase::VCSBaseEditor* editor, bool outputToWindow) @@ -467,6 +484,60 @@ bool GitClient::synchronousGit(const QString &workingDirectory, return process.exitCode() == 0; } +static inline int + askWithDetailedText(QWidget *parent, + const QString &title, const QString &msg, + const QString &inf, + QMessageBox::StandardButton defaultButton, + QMessageBox::StandardButtons buttons = QMessageBox::Yes|QMessageBox::No) +{ + QMessageBox msgBox(QMessageBox::Question, title, msg, buttons, parent); + msgBox.setDetailedText(inf); + msgBox.setDefaultButton(defaultButton); + return msgBox.exec(); +} + +// Convenience that pops up an msg box. +GitClient::StashResult GitClient::ensureStash(const QString &workingDirectory) +{ + QString errorMessage; + const StashResult sr = ensureStash(workingDirectory, &errorMessage); + if (sr == StashFailed) { + m_plugin->outputWindow()->append(errorMessage); + m_plugin->outputWindow()->popup(); + } + return sr; +} + +// Ensure that changed files are stashed before a pull or similar +GitClient::StashResult GitClient::ensureStash(const QString &workingDirectory, QString *errorMessage) +{ + QString statusOutput; + switch (gitStatus(workingDirectory, false, &statusOutput, errorMessage)) { + case StatusChanged: + break; + case StatusUnchanged: + return StashUnchanged; + case StatusFailed: + return StashFailed; + } + + const int answer = askWithDetailedText(m_core->mainWindow(), tr("Changes"), + tr("You have modified files. Would you like to stash your changes?"), + statusOutput, QMessageBox::Yes, QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel); + switch (answer) { + case QMessageBox::Cancel: + return StashCanceled; + case QMessageBox::Yes: + if (!synchronousStash(workingDirectory, errorMessage)) + return StashFailed; + break; + case QMessageBox::No: // At your own risk, so. + return NotStashed; + } + + return Stashed; + } // Trim a git status file spec: "modified: foo .cpp" -> "modified: foo .cpp" static inline QString trimFileSpecification(QString fileSpec) @@ -703,18 +774,6 @@ bool GitClient::addAndCommit(const QString &repositoryDirectory, return rc; } -static inline bool askWithInformativeText(QWidget *parent, - const QString &title, - const QString &msg, - const QString &inf, - bool defaultValue) -{ - QMessageBox msgBox(QMessageBox::Question, title, msg, QMessageBox::Yes|QMessageBox::No, parent); - msgBox.setInformativeText(inf); - msgBox.setDefaultButton(defaultValue ? QMessageBox::Yes : QMessageBox::No); - return msgBox.exec() == QMessageBox::Yes; -} - /* Revert: This function can be called with a file list (to revert single * files) or a single directory (revert all). Qt Creator currently has only * 'revert single' in its VCS menus, but the code is prepared to deal with diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h index 2ae6c3f583ad02534c409f6f2546fe5f8130973e..af45bbb9a36b6ed174b4516bfec605b9d8d4bcdc 100644 --- a/src/plugins/git/gitclient.h +++ b/src/plugins/git/gitclient.h @@ -92,6 +92,7 @@ public: bool synchronousReset(const QString &workingDirectory, const QStringList &files); bool synchronousReset(const QString &workingDirectory, const QStringList &files, QString *errorMessage); bool synchronousCheckout(const QString &workingDirectory, const QStringList &files, QString *errorMessage); + bool synchronousStash(const QString &workingDirectory, QString *errorMessage); void pull(const QString &workingDirectory); void push(const QString &workingDirectory); @@ -105,6 +106,11 @@ public: QString readConfigValue(const QString &workingDirectory, const QString &configVar); + enum StashResult { StashUnchanged, StashCanceled, StashFailed, + Stashed, NotStashed /* User did not want it */ }; + StashResult ensureStash(const QString &workingDirectory, QString *errorMessage); + StashResult ensureStash(const QString &workingDirectory); + bool getCommitData(const QString &workingDirectory, QString *commitTemplate, CommitData *d, @@ -118,7 +124,7 @@ public: enum StatusResult { StatusChanged, StatusUnchanged, StatusFailed }; StatusResult gitStatus(const QString &workingDirectory, - bool untracked, + bool untracked = false, QString *output = 0, QString *errorMessage = 0); diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp index dc18fe088ed3372c36b8651ede95bae3490655dd..85af681d2091494da5798766d7778a355a589012 100644 --- a/src/plugins/git/gitplugin.cpp +++ b/src/plugins/git/gitplugin.cpp @@ -703,8 +703,17 @@ bool GitPlugin::editorAboutToClose(Core::IEditor *iEditor) void GitPlugin::pull() { const QString workingDirectory = getWorkingDirectory(); - if (!workingDirectory.isEmpty()) - m_gitClient->pull(workingDirectory); + if (workingDirectory.isEmpty()) + return; + + switch (m_gitClient->ensureStash(workingDirectory)) { + case GitClient::StashUnchanged: + case GitClient::Stashed: + case GitClient::NotStashed: + m_gitClient->pull(workingDirectory); + default: + break; + } } void GitPlugin::push() diff --git a/src/plugins/git/gitplugin.h b/src/plugins/git/gitplugin.h index 5e15a52a87a7a69939a64650a471a3f85e68dc0f..39287e1939a253c20c607c9625999b40b1e2fec1 100644 --- a/src/plugins/git/gitplugin.h +++ b/src/plugins/git/gitplugin.h @@ -97,6 +97,7 @@ public: GitOutputWindow *outputWindow() const; + GitSettings settings() const; void setSettings(const GitSettings &s);