diff options
author | Petar Perisin <petar.perisin@gmail.com> | 2013-01-11 00:02:08 +0100 |
---|---|---|
committer | Tobias Hunger <tobias.hunger@digia.com> | 2013-01-21 10:41:01 +0100 |
commit | 65aef73ec4d6ff8f6752f83571c9310f8c6d793b (patch) | |
tree | cfad1907765bdeca9fa5b021f11c346198540815 /src/plugins/git | |
parent | 8f4da818c8a7184ffdf0268e652d2dcf867dffa9 (diff) | |
download | qt-creator-65aef73ec4d6ff8f6752f83571c9310f8c6d793b.tar.gz |
Git: Added Revert and cherry-pick
Change-Id: Ic8ba7434e79b12eca680a67c2845c82915dc0088
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
Reviewed-by: Tobias Hunger <tobias.hunger@digia.com>
Diffstat (limited to 'src/plugins/git')
-rw-r--r-- | src/plugins/git/gitclient.cpp | 21 | ||||
-rw-r--r-- | src/plugins/git/gitclient.h | 4 | ||||
-rw-r--r-- | src/plugins/git/gitplugin.cpp | 60 | ||||
-rw-r--r-- | src/plugins/git/gitplugin.h | 7 | ||||
-rw-r--r-- | src/plugins/git/mergetool.cpp | 51 | ||||
-rw-r--r-- | src/plugins/git/mergetool.h | 4 |
6 files changed, 132 insertions, 15 deletions
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index a873f19873..98cc48ce4c 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -2119,7 +2119,8 @@ bool GitClient::executeAndHandleConflicts(const QString &workingDirectory, const const bool ok = resp.result == Utils::SynchronousProcessResponse::Finished; if (ok) GitPlugin::instance()->gitVersionControl()->emitRepositoryChanged(workingDirectory); - else if (resp.stdOut.contains(QLatin1String("CONFLICT"))) + else if (resp.stdOut.contains(QLatin1String("CONFLICT")) + || resp.stdErr.contains(QLatin1String("conflict"))) handleMergeConflicts(workingDirectory, abortCommand); return ok; } @@ -2248,6 +2249,24 @@ bool GitClient::synchronousRebase(const QString &workingDirectory, const QString return executeAndHandleConflicts(workingDirectory, arguments, command); } +bool GitClient::revertCommit(const QString &workingDirectory, const QString &commit) +{ + QStringList arguments; + QString command = QLatin1String("revert"); + arguments << command << QLatin1String("--no-edit") << commit; + + return executeAndHandleConflicts(workingDirectory, arguments, command); +} + +bool GitClient::cherryPickCommit(const QString &workingDirectory, const QString &commit) +{ + QStringList arguments; + QString command = QLatin1String("cherry-pick"); + arguments << command << commit; + + return executeAndHandleConflicts(workingDirectory, arguments, command); +} + QString GitClient::msgNoChangedFiles() { return tr("There are no modified files."); diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h index f0e36309a6..72e8c74dd5 100644 --- a/src/plugins/git/gitclient.h +++ b/src/plugins/git/gitclient.h @@ -184,6 +184,9 @@ public: bool synchronousRebase(const QString &workingDirectory, const QString &baseBranch, const QString &topicBranch = QString()); + bool revertCommit(const QString &workingDirectory, const QString &commit); + bool cherryPickCommit(const QString &workingDirectory, const QString &commit); + void synchronousAbortCommand(const QString &workingDir, const QString &abortCommand); // git svn support (asynchronous). void synchronousSubversionFetch(const QString &workingDirectory); @@ -303,7 +306,6 @@ private: void connectRepositoryChanged(const QString & repository, VcsBase::Command *cmd); bool executeAndHandleConflicts(const QString &workingDirectory, const QStringList &arguments, const QString &abortCommand = QString()); - void synchronousAbortCommand(const QString &workingDir, const QString &abortCommand); void handleMergeConflicts(const QString &workingDir, const QString &abortCommand); bool tryLauchingGitK(const QProcessEnvironment &env, const QString &workingDirectory, diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp index e97b78a4c1..8951ffe088 100644 --- a/src/plugins/git/gitplugin.cpp +++ b/src/plugins/git/gitplugin.cpp @@ -425,11 +425,21 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *errorMessage) createRepositoryAction(localRepositoryMenu, tr("Amend Last Commit..."), Core::Id("Git.AmendCommit"), globalcontext, true, SLOT(startAmendCommit())); + // -------------- + localRepositoryMenu->addSeparator(globalcontext); createRepositoryAction(localRepositoryMenu, tr("Reset..."), Core::Id("Git.Reset"), globalcontext, false, SLOT(resetRepository())); + createRepositoryAction(localRepositoryMenu, + tr("Revert Single Commit..."), Core::Id("Git.Revert"), + globalcontext, true, SLOT(startRevertCommit())); + + createRepositoryAction(localRepositoryMenu, + tr("Cherry-Pick Commit..."), Core::Id("Git.CherryPick"), + globalcontext, true, SLOT(startCherryPickCommit())); + // -------------- localRepositoryMenu->addSeparator(globalcontext); @@ -704,6 +714,56 @@ void GitPlugin::resetRepository() } } + +void GitPlugin::startRevertCommit() +{ + startRevertOrCherryPick(true); +} + +void GitPlugin::startCherryPickCommit() +{ + startRevertOrCherryPick(false); +} + +void GitPlugin::startRevertOrCherryPick(bool isRevert) +{ + 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: + return; + } + + QString workingDirectory; + if (state.hasFile()) + workingDirectory = state.currentFileDirectory(); + else if (state.hasTopLevel()) + workingDirectory = state.topLevel(); + else + 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); +} + void GitPlugin::stageFile() { const VcsBase::VcsBasePluginState state = currentState(); diff --git a/src/plugins/git/gitplugin.h b/src/plugins/git/gitplugin.h index 1d8d1f7241..a02d428df1 100644 --- a/src/plugins/git/gitplugin.h +++ b/src/plugins/git/gitplugin.h @@ -100,6 +100,9 @@ public: GitClient *gitClient() const; +public slots: + void startCommit(); + private slots: void diffCurrentFile(); void diffCurrentProject(); @@ -113,6 +116,9 @@ private slots: void undoFileChanges(bool revertStaging = true); void undoUnstagedFileChanges(); void resetRepository(); + void startRevertCommit(); + void startCherryPickCommit(); + void startRevertOrCherryPick(bool isRevert); void stageFile(); void unstageFile(); void gitkForCurrentFile(); @@ -124,7 +130,6 @@ private slots: void gitClientMemberFuncRepositoryAction(); void showCommit(); - void startCommit(); void startAmendCommit(); void stash(); void stashSnapshot(); diff --git a/src/plugins/git/mergetool.cpp b/src/plugins/git/mergetool.cpp index 86713de89c..d7b42a70b5 100644 --- a/src/plugins/git/mergetool.cpp +++ b/src/plugins/git/mergetool.cpp @@ -72,7 +72,8 @@ private: MergeTool::MergeTool(QObject *parent) : QObject(parent), - m_process(0) + m_process(0), + m_gitClient(GitPlugin::instance()->gitClient()) { } @@ -85,9 +86,8 @@ bool MergeTool::start(const QString &workingDirectory, const QStringList &files) { QStringList arguments; arguments << QLatin1String("mergetool") << QLatin1String("-y"); - GitClient *client = GitPlugin::instance()->gitClient(); if (!files.isEmpty()) { - if (client->gitVersion() < 0x010708) { + if (m_gitClient->gitVersion() < 0x010708) { QMessageBox::warning(0, tr("Error"), tr("Files input for mergetool requires git >= 1.7.8")); return false; } @@ -95,7 +95,7 @@ bool MergeTool::start(const QString &workingDirectory, const QStringList &files) } m_process = new MergeToolProcess(this); m_process->setWorkingDirectory(workingDirectory); - const QString binary = client->gitBinaryPath(); + const QString binary = m_gitClient->gitBinaryPath(); VcsBase::VcsBaseOutputWindow::instance()->appendCommand(workingDirectory, binary, arguments); m_process->start(binary, arguments); if (m_process->waitForStarted()) { @@ -255,21 +255,48 @@ void MergeTool::readData() } } +void MergeTool::continuePreviousGitCommand(const QString &msgBoxTitle, const QString &msgBoxText, + const QString &buttonName, const QString &gitCommand) +{ + QString workingDirectory = m_process->workingDirectory(); + QMessageBox msgBox; + QPushButton *commandButton = msgBox.addButton(buttonName, QMessageBox::AcceptRole); + QPushButton *abortButton = msgBox.addButton(QMessageBox::Abort); + msgBox.addButton(QMessageBox::Ignore); + msgBox.setIcon(QMessageBox::Question); + msgBox.setWindowTitle(msgBoxTitle); + msgBox.setText(msgBoxText); + msgBox.exec(); + + if (msgBox.clickedButton() == commandButton) { // Continue + if (gitCommand == QLatin1String("rebase")) + m_gitClient->synchronousCommandContinue(workingDirectory, gitCommand); + else + GitPlugin::instance()->startCommit(); + } else if (msgBox.clickedButton() == abortButton) { // Abort + m_gitClient->synchronousAbortCommand(workingDirectory, gitCommand); + } +} + void MergeTool::done() { VcsBase::VcsBaseOutputWindow *outputWindow = VcsBase::VcsBaseOutputWindow::instance(); int exitCode = m_process->exitCode(); if (!exitCode) { outputWindow->append(tr("Merge tool process finished successully")); - QString workingDirectory = m_process->workingDirectory(); - GitClient *client = GitPlugin::instance()->gitClient(); - QString gitDir = client->findGitDirForRepository(workingDirectory); + QString gitDir = m_gitClient->findGitDirForRepository(m_process->workingDirectory()); + if (QFile::exists(gitDir + QLatin1String("/rebase-apply/rebasing"))) { - if (QMessageBox::question(0, tr("Continue Rebase"), - tr("Continue rebase?"), - QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) { - client->synchronousCommandContinue(workingDirectory, QLatin1String("rebase")); - } + continuePreviousGitCommand(tr("Continue Rebase"), tr("Continue rebase?"), + tr("Continue"), QLatin1String("rebase")); + } else if (QFile::exists(gitDir + QLatin1String("/REVERT_HEAD"))) { + continuePreviousGitCommand(tr("Continue Revert"), + tr("You need to commit changes to finish revert.\nCommit now?"), + tr("Commit"), QLatin1String("revert")); + } else if (QFile::exists(gitDir + QLatin1String("/CHERRY_PICK_HEAD"))) { + continuePreviousGitCommand(tr("Continue Cherry-Pick"), + tr("You need to commit changes to finish cherry-pick.\nCommit now?"), + tr("Commit"), QLatin1String("cherry-pick")); } } else { outputWindow->append(tr("Merge tool process terminated with exit code %1").arg(exitCode)); diff --git a/src/plugins/git/mergetool.h b/src/plugins/git/mergetool.h index d91876be5e..37fbe75fb8 100644 --- a/src/plugins/git/mergetool.h +++ b/src/plugins/git/mergetool.h @@ -41,6 +41,7 @@ namespace Git { namespace Internal { class MergeToolProcess; +class GitClient; class MergeTool : public QObject { @@ -77,6 +78,8 @@ private: QString stateName(FileState state, const QString &extraInfo); void chooseAction(); void addButton(QMessageBox *msgBox, const QString &text, char key); + void continuePreviousGitCommand(const QString &msgBoxTitle, const QString &msgBoxText, + const QString &buttonName, const QString &gitCommand); MergeToolProcess *m_process; MergeType m_mergeType; @@ -85,6 +88,7 @@ private: QString m_localInfo; FileState m_remoteState; QString m_remoteInfo; + GitClient *m_gitClient; bool m_merging; }; |