diff --git a/src/plugins/git/branchdialog.cpp b/src/plugins/git/branchdialog.cpp index 453b9df1ef8..a32ae4d210f 100644 --- a/src/plugins/git/branchdialog.cpp +++ b/src/plugins/git/branchdialog.cpp @@ -188,7 +188,8 @@ void BranchDialog::checkout() QString stashMessage; if (branchCheckoutDialog.makeStashOfCurrentBranch() || branchCheckoutDialog.moveLocalChangesToNextBranch()) { - gitClient->ensureStash(m_repository, currentBranch + QLatin1String("-AutoStash"), false, &stashMessage); + gitClient->ensureStash(m_repository, currentBranch + QLatin1String("-AutoStash"), + NoPrompt, &stashMessage); } else if (branchCheckoutDialog.discardLocalChanges()) { gitClient->synchronousReset(m_repository); } @@ -287,7 +288,7 @@ void BranchDialog::merge() QTC_CHECK(idx != m_model->currentBranch()); // otherwise the button would not be enabled! const QString branch = m_model->branchName(idx); - GitClient::StashGuard stashGuard(m_repository, QLatin1String("merge"), false); + GitClient::StashGuard stashGuard(m_repository, QLatin1String("merge"), AllowUnstashed); if (!GitPlugin::instance()->gitClient()->synchronousMerge(m_repository, branch)) stashGuard.preventPop(); } @@ -299,7 +300,7 @@ void BranchDialog::rebase() QTC_CHECK(idx != m_model->currentBranch()); // otherwise the button would not be enabled! const QString baseBranch = m_model->branchName(idx); - GitClient::StashGuard stashGuard(m_repository, QLatin1String("rebase"), false); + GitClient::StashGuard stashGuard(m_repository, QLatin1String("rebase")); if (!GitPlugin::instance()->gitClient()->synchronousRebase(m_repository, baseBranch)) stashGuard.preventPop(); } diff --git a/src/plugins/git/branchmodel.cpp b/src/plugins/git/branchmodel.cpp index c3321c533a0..034c93e72ad 100644 --- a/src/plugins/git/branchmodel.cpp +++ b/src/plugins/git/branchmodel.cpp @@ -470,10 +470,8 @@ void BranchModel::checkoutBranch(const QModelIndex &idx) if (branch.isEmpty()) return; - GitClient::StashGuard stashGuard(m_workingDirectory, QLatin1String("Branch-Checkout")); - if (stashGuard.stashingFailed(false)) - return; - stashGuard.preventPop(); + // No StashGuard since this function for now is only used with clean working dir. + // If it is ever used from another place, please add StashGuard here QString errorMessage; if (m_client->synchronousCheckout(m_workingDirectory, branch, &errorMessage)) { if (errorMessage.isEmpty()) { diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 85a2d557706..b496734f340 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -1765,22 +1765,10 @@ bool GitClient::fullySynchronousGit(const QString &workingDirectory, logCommandToWindow); } -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(); -} - // Ensure that changed files are stashed before a pull or similar GitClient::StashResult GitClient::ensureStash(const QString &workingDirectory, const QString &keyword, - bool askUser, + StashFlag flag, QString *message, QString *errorMessage) { @@ -1795,17 +1783,41 @@ GitClient::StashResult GitClient::ensureStash(const QString &workingDirectory, return StashFailed; } - if (askUser) { - const int answer = askWithDetailedText(Core::ICore::mainWindow(), tr("Changes"), - tr("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::No: // At your own risk, so. + if (!(flag & NoPrompt)) { + QPointer msgBox = new QMessageBox(QMessageBox::Question, + tr("Uncommited changes found"), + tr("What would you like to do with local changes?"), + QMessageBox::NoButton, Core::ICore::mainWindow()); + + msgBox->setDetailedText(statusOutput); + + QPushButton *stashButton = msgBox->addButton(tr("Stash"), QMessageBox::AcceptRole); + stashButton->setToolTip(tr("Stash local changes and continue")); + + QPushButton *discardButton = msgBox->addButton(tr("Discard"), QMessageBox::AcceptRole); + discardButton->setToolTip(tr("Discard (reset) local changes and continue")); + + QPushButton *ignoreButton = 0; + if (flag & AllowUnstashed) { + ignoreButton = msgBox->addButton(QMessageBox::Ignore); + ignoreButton->setToolTip(tr("Continue with local changes in working directory")); + } + + QPushButton *cancelButton = msgBox->addButton(QMessageBox::Cancel); + cancelButton->setToolTip(tr("Cancel current command")); + + msgBox->exec(); + if (msgBox.isNull()) + return StashFailed; + + if (msgBox->clickedButton() == discardButton) { + if (!synchronousReset(workingDirectory, QStringList(), errorMessage)) + return StashFailed; + return StashUnchanged; + } else if (msgBox->clickedButton() == ignoreButton) { // At your own risk, so. return NotStashed; - default: - break; + } else if (msgBox->clickedButton() == cancelButton) { + return StashCanceled; } } const QString stashMessage = creatorStashMessage(keyword); @@ -2871,13 +2883,15 @@ unsigned GitClient::synchronousGitVersion(QString *errorMessage) const return version(major, minor, patch); } -GitClient::StashGuard::StashGuard(const QString &workingDirectory, const QString &keyword, bool askUser) : +GitClient::StashGuard::StashGuard(const QString &workingDirectory, const QString &keyword, + StashFlag flag) : pop(true), - workingDir(workingDirectory) + workingDir(workingDirectory), + flags(flag) { client = GitPlugin::instance()->gitClient(); QString errorMessage; - stashResult = client->ensureStash(workingDir, keyword, askUser, &message, &errorMessage); + stashResult = client->ensureStash(workingDir, keyword, flags, &message, &errorMessage); if (stashResult == GitClient::StashFailed) VcsBase::VcsBaseOutputWindow::instance()->appendError(errorMessage); } @@ -2896,14 +2910,14 @@ void GitClient::StashGuard::preventPop() pop = false; } -bool GitClient::StashGuard::stashingFailed(bool includeNotStashed) const +bool GitClient::StashGuard::stashingFailed() const { switch (stashResult) { case GitClient::StashCanceled: case GitClient::StashFailed: return true; case GitClient::NotStashed: - return includeNotStashed; + return !(flags & AllowUnstashed); default: return false; } diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h index 4e4f8dffe2a..5cacc82f143 100644 --- a/src/plugins/git/gitclient.h +++ b/src/plugins/git/gitclient.h @@ -76,6 +76,12 @@ enum StatusMode NoSubmodules = 2 }; +enum StashFlag { + Default = 0x00, /* Prompt and do not allow unstashed */ + AllowUnstashed = 0x01, + NoPrompt = 0x02 +}; + class GitClient : public QObject { Q_OBJECT @@ -87,12 +93,14 @@ public: class StashGuard { public: - StashGuard(const QString &workingDirectory, const QString &keyword, bool askUser = true); + StashGuard(const QString &workingDirectory, const QString &keyword, + StashFlag flag = Default); ~StashGuard(); void preventPop(); - bool stashingFailed(bool includeNotStashed) const; + bool stashingFailed() const; StashResult result() const { return stashResult; } + QString stashMessage() const { return message; } private: bool pop; @@ -100,6 +108,7 @@ public: QString message; QString workingDir; GitClient *client; + StashFlag flags; }; static const char *stashNamePrefix; @@ -250,8 +259,8 @@ public: QString readConfigValue(const QString &workingDirectory, const QString &configVar) const; - StashResult ensureStash(const QString &workingDirectory, const QString &keyword, bool askUser, - QString *message, QString *errorMessage = 0); + StashResult ensureStash(const QString &workingDirectory, const QString &keyword, + StashFlag flag, QString *message, QString *errorMessage = 0); bool getCommitData(const QString &workingDirectory, bool amend, QString *commitTemplate, CommitData *commitData, diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp index 0c957ceba4e..3dce0b7cf04 100644 --- a/src/plugins/git/gitplugin.cpp +++ b/src/plugins/git/gitplugin.cpp @@ -724,7 +724,7 @@ void GitPlugin::startRebase() if (workingDirectory.isEmpty() || !m_gitClient->canRebase(workingDirectory)) return; GitClient::StashGuard stashGuard(workingDirectory, QLatin1String("Rebase-i")); - if (stashGuard.stashingFailed(true)) + if (stashGuard.stashingFailed()) return; stashGuard.preventPop(); LogChangeDialog dialog(false); @@ -778,7 +778,7 @@ void GitPlugin::startChangeRelatedAction() } GitClient::StashGuard stashGuard(workingDirectory, command); - if (stashGuard.stashingFailed(true)) + if (stashGuard.stashingFailed()) return; if (!(m_gitClient->*commandFunction)(workingDirectory, change)) @@ -1009,8 +1009,9 @@ void GitPlugin::pull() } } - GitClient::StashGuard stashGuard(topLevel, QLatin1String("Pull")); - if (stashGuard.stashingFailed(false) || (rebase && (stashGuard.result() == GitClient::NotStashed))) + GitClient::StashGuard stashGuard(topLevel, QLatin1String("Pull"), + rebase ? Default : AllowUnstashed); + if (stashGuard.stashingFailed()) return; if (!m_gitClient->synchronousPull(topLevel, rebase)) stashGuard.preventPop(); @@ -1137,8 +1138,8 @@ void GitPlugin::promptApplyPatch() void GitPlugin::applyPatch(const QString &workingDirectory, QString file) { // Ensure user has been notified about pending changes - GitClient::StashGuard stashGuard(workingDirectory, QLatin1String("Apply-Patch")); - if (stashGuard.stashingFailed(false)) + GitClient::StashGuard stashGuard(workingDirectory, QLatin1String("Apply-Patch"), AllowUnstashed); + if (stashGuard.stashingFailed()) return; // Prompt for file if (file.isEmpty()) { @@ -1168,7 +1169,7 @@ void GitPlugin::stash() const VcsBase::VcsBasePluginState state = currentState(); QTC_ASSERT(state.hasTopLevel(), return); QString id; - gitClient()->ensureStash(state.topLevel(), QString(), false, &id); + gitClient()->ensureStash(state.topLevel(), QString(), NoPrompt, &id); if (!id.isEmpty() && m_stashDialog) m_stashDialog->refresh(state.topLevel(), true); }