diff --git a/src/plugins/git/branchmodel.cpp b/src/plugins/git/branchmodel.cpp index 4a0c1af46f51aecf8cd094f9ec29eb9adc352e46..17b2376a67984cfa2dbddf2ed86fbda26eddcbbf 100644 --- a/src/plugins/git/branchmodel.cpp +++ b/src/plugins/git/branchmodel.cpp @@ -443,18 +443,11 @@ void BranchModel::checkoutBranch(const QModelIndex &idx) if (branch.isEmpty()) return; - QString errorMessage; - switch (m_client->ensureStash(m_workingDirectory, QLatin1String("Branch-Checkout"), true, 0, &errorMessage)) { - case GitClient::StashUnchanged: - case GitClient::Stashed: - case GitClient::NotStashed: - break; - case GitClient::StashCanceled: - return; - case GitClient::StashFailed: - VcsBase::VcsBaseOutputWindow::instance()->appendError(errorMessage); + GitClient::StashGuard stashGuard(m_workingDirectory, QLatin1String("Branch-Checkout")); + if (stashGuard.stashingFailed(false)) return; - } + stashGuard.preventPop(); + QString errorMessage; if (m_client->synchronousCheckoutBranch(m_workingDirectory, branch, &errorMessage)) { if (errorMessage.isEmpty()) { QModelIndex currentIdx = currentBranch(); diff --git a/src/plugins/git/changeselectiondialog.cpp b/src/plugins/git/changeselectiondialog.cpp index 55023732a219eacd7b8dc831f02b8a1fa3afc2e8..447cc38a588b8be0b251fcec839aaf9b7c7d6dd2 100644 --- a/src/plugins/git/changeselectiondialog.cpp +++ b/src/plugins/git/changeselectiondialog.cpp @@ -80,6 +80,8 @@ QString ChangeSelectionDialog::workingDirectory() const void ChangeSelectionDialog::setWorkingDirectory(const QString &s) { + if (s.isEmpty()) + return; m_ui.workingDirectoryEdit->setText(QDir::toNativeSeparators(s)); m_ui.changeNumberEdit->setFocus(Qt::ActiveWindowFocusReason); m_ui.changeNumberEdit->setText(QLatin1String("HEAD")); diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 1a82c4c4a7bb8c8bda9b453ddeb909f95cb25f02..d6a130950864cec4274ceb7ed553029d99c4ee64 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -1567,16 +1567,6 @@ static inline int askWithDetailedText(QWidget *parent, return msgBox.exec(); } -// Convenience that pops up an msg box. -GitClient::StashResult GitClient::ensureStash(const QString &workingDirectory, const QString &keyword, QString *message) -{ - QString errorMessage; - const StashResult sr = ensureStash(workingDirectory, keyword, true, message, &errorMessage); - if (sr == StashFailed) - outputWindow()->appendError(errorMessage); - return sr; -} - // Ensure that changed files are stashed before a pull or similar GitClient::StashResult GitClient::ensureStash(const QString &workingDirectory, const QString &keyword, @@ -2540,6 +2530,41 @@ unsigned GitClient::synchronousGitVersion(QString *errorMessage) const return version(major, minor, patch); } +GitClient::StashGuard::StashGuard(const QString &workingDirectory, const QString &keyword) : + pop(true), + workingDir(workingDirectory) +{ + client = GitPlugin::instance()->gitClient(); + QString errorMessage; + stashResult = client->ensureStash(workingDir, keyword, true, &message, &errorMessage); + if (stashResult == GitClient::StashFailed) + VcsBase::VcsBaseOutputWindow::instance()->appendError(errorMessage); +} + +GitClient::StashGuard::~StashGuard() +{ + if (pop && stashResult == GitClient::Stashed) + client->stashPop(workingDir, message); +} + +void GitClient::StashGuard::preventPop() +{ + pop = false; +} + +bool GitClient::StashGuard::stashingFailed(bool includeNotStashed) const +{ + switch (stashResult) { + case GitClient::StashCanceled: + case GitClient::StashFailed: + return true; + case GitClient::NotStashed: + return includeNotStashed; + default: + return false; + } +} + } // namespace Internal } // namespace Git diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h index 9e2469c5c62f66cca0d28daedfc2a610ba21e4f1..9f77b0501b03e981d989b20754bdb7ef5659fc5a 100644 --- a/src/plugins/git/gitclient.h +++ b/src/plugins/git/gitclient.h @@ -82,6 +82,27 @@ class GitClient : public QObject Q_OBJECT public: + enum StashResult { StashUnchanged, StashCanceled, StashFailed, + Stashed, NotStashed /* User did not want it */ }; + + class StashGuard + { + public: + StashGuard(const QString &workingDirectory, const QString &keyword); + ~StashGuard(); + + void preventPop(); + bool stashingFailed(bool includeNotStashed) const; + StashResult result() const { return stashResult; } + + private: + bool pop; + StashResult stashResult; + QString message; + QString workingDir; + GitClient *client; + }; + static const char *stashNamePrefix; explicit GitClient(GitSettings *settings); @@ -210,9 +231,6 @@ public: QString readConfigValue(const QString &workingDirectory, const QString &configVar) const; - enum StashResult { StashUnchanged, StashCanceled, StashFailed, - Stashed, NotStashed /* User did not want it */ }; - StashResult ensureStash(const QString &workingDirectory, const QString &keyword, QString *message = 0); StashResult ensureStash(const QString &workingDirectory, const QString &keyword, bool askUser, QString *message, QString *errorMessage = 0); diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp index 19ddd7fd33b3947bf2e1c5b238bad19e37d09000..033e9d6e1662b91eecd6d5d8f006c5a55a184d61 100644 --- a/src/plugins/git/gitplugin.cpp +++ b/src/plugins/git/gitplugin.cpp @@ -714,54 +714,40 @@ void GitPlugin::resetRepository() } } - void GitPlugin::startRevertCommit() { - startRevertOrCherryPick(true); -} + const VcsBase::VcsBasePluginState state = currentState(); + QString workingDirectory = state.currentDirectoryOrTopLevel(); + if (workingDirectory.isEmpty()) + return; + GitClient::StashGuard stashGuard(workingDirectory, QLatin1String("Revert")); + if (stashGuard.stashingFailed(true)) + return; + ChangeSelectionDialog changeSelectionDialog(workingDirectory); -void GitPlugin::startCherryPickCommit() -{ - startRevertOrCherryPick(false); + if (changeSelectionDialog.exec() != QDialog::Accepted) + return; + const QString change = changeSelectionDialog.change(); + if (!change.isEmpty() && !m_gitClient->revertCommit(workingDirectory, change)) + stashGuard.preventPop(); } -void GitPlugin::startRevertOrCherryPick(bool isRevert) +void GitPlugin::startCherryPickCommit() { const VcsBase::VcsBasePluginState state = currentState(); - - QString stashKeyword = (isRevert ? QLatin1String("Revert") : QLatin1String("Cherry-pick")); - - GitClient::StashResult stashResult = - m_gitClient->ensureStash(state.topLevel(), stashKeyword); - switch (stashResult) { - case GitClient::StashUnchanged: - case GitClient::Stashed: - break; - default: + QString workingDirectory = state.currentDirectoryOrTopLevel(); + if (workingDirectory.isEmpty()) return; - } - - QString workingDirectory; - if (state.hasFile()) - workingDirectory = state.currentFileDirectory(); - else if (state.hasTopLevel()) - workingDirectory = state.topLevel(); - else + GitClient::StashGuard stashGuard(state.topLevel(), QLatin1String("Cherry-pick")); + if (stashGuard.stashingFailed(true)) return; - ChangeSelectionDialog changeSelectionDialog(workingDirectory); if (changeSelectionDialog.exec() != QDialog::Accepted) return; const QString change = changeSelectionDialog.change(); - if (change.isEmpty()) - return; - - bool success = (isRevert ? m_gitClient->revertCommit(workingDirectory, change) : - m_gitClient->cherryPickCommit(workingDirectory, change)); - - if (success && (stashResult == GitClient::Stashed)) - m_gitClient->stashPop(workingDirectory); + if (!change.isEmpty() && !m_gitClient->cherryPickCommit(workingDirectory, change)) + stashGuard.preventPop(); } void GitPlugin::stageFile() @@ -960,20 +946,11 @@ void GitPlugin::pull() } } - GitClient::StashResult stashResult = m_gitClient->ensureStash(state.topLevel(), QLatin1String("Pull")); - switch (stashResult) { - case GitClient::StashUnchanged: - case GitClient::Stashed: - if (m_gitClient->synchronousPull(state.topLevel(), rebase) && (stashResult == GitClient::Stashed)) - m_gitClient->stashPop(state.topLevel()); - break; - case GitClient::NotStashed: - if (!rebase) - m_gitClient->synchronousPull(state.topLevel(), false); - break; - default: - break; - } + GitClient::StashGuard stashGuard(state.topLevel(), QLatin1String("Pull")); + if (stashGuard.stashingFailed(false) || (rebase && (stashGuard.result() == GitClient::NotStashed))) + return; + if (!m_gitClient->synchronousPull(state.topLevel(), false)) + stashGuard.preventPop(); } void GitPlugin::push() @@ -1090,14 +1067,9 @@ void GitPlugin::promptApplyPatch() void GitPlugin::applyPatch(const QString &workingDirectory, QString file) { // Ensure user has been notified about pending changes - switch (m_gitClient->ensureStash(workingDirectory, QLatin1String("Apply-Patch"))) { - case GitClient::StashUnchanged: - case GitClient::Stashed: - case GitClient::NotStashed: - break; - default: + GitClient::StashGuard stashGuard(workingDirectory, QLatin1String("Apply-Patch")); + if (stashGuard.stashingFailed(false)) return; - } // Prompt for file if (file.isEmpty()) { const QString filter = tr("Patches (*.patch *.diff)"); @@ -1219,10 +1191,7 @@ void GitPlugin::showCommit() if (!m_changeSelectionDialog) m_changeSelectionDialog = new ChangeSelectionDialog(); - if (state.hasFile()) - m_changeSelectionDialog->setWorkingDirectory(state.currentFileDirectory()); - else if (state.hasTopLevel()) - m_changeSelectionDialog->setWorkingDirectory(state.topLevel()); + m_changeSelectionDialog->setWorkingDirectory(state.currentDirectoryOrTopLevel()); if (m_changeSelectionDialog->exec() != QDialog::Accepted) return; diff --git a/src/plugins/git/gitplugin.h b/src/plugins/git/gitplugin.h index 8e9dd0a636d01e5e44e9eb89fcd835af083e67a2..0ff4961c06d68e18230adf5f2cd11418e6fb2b12 100644 --- a/src/plugins/git/gitplugin.h +++ b/src/plugins/git/gitplugin.h @@ -118,7 +118,6 @@ private slots: void resetRepository(); void startRevertCommit(); void startCherryPickCommit(); - void startRevertOrCherryPick(bool isRevert); void stageFile(); void unstageFile(); void gitkForCurrentFile(); diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp index 21907765e84ba94618ed864c68895bb52ee6f43f..0f3643ed3a504f021ad5b77e0741a3e4135372f6 100644 --- a/src/plugins/vcsbase/vcsbaseplugin.cpp +++ b/src/plugins/vcsbase/vcsbaseplugin.cpp @@ -409,6 +409,15 @@ QString VcsBasePluginState::topLevel() const return hasFile() ? data->m_state.currentFileTopLevel : data->m_state.currentProjectTopLevel; } +QString VcsBasePluginState::currentDirectoryOrTopLevel() const +{ + if (hasFile()) + return data->m_state.currentFileDirectory; + else if (data->m_state.hasProject()) + return data->m_state.currentProjectTopLevel; + return QString(); +} + bool VcsBasePluginState::equals(const Internal::State &rhs) const { return data->m_state.equals(rhs); diff --git a/src/plugins/vcsbase/vcsbaseplugin.h b/src/plugins/vcsbase/vcsbaseplugin.h index f2af81c08efa356967c94e4a26e73f851c535c74..01b2525abc7833edd8bff459ee3fe0ea0a160d55 100644 --- a/src/plugins/vcsbase/vcsbaseplugin.h +++ b/src/plugins/vcsbase/vcsbaseplugin.h @@ -99,6 +99,7 @@ public: // the file one. QString topLevel() const; + QString currentDirectoryOrTopLevel() const; bool equals(const VcsBasePluginState &rhs) const; friend VCSBASE_EXPORT QDebug operator<<(QDebug in, const VcsBasePluginState &state);