summaryrefslogtreecommitdiff
path: root/src/plugins/git
diff options
context:
space:
mode:
authorPetar Perisin <petar.perisin@gmail.com>2013-01-11 00:02:08 +0100
committerTobias Hunger <tobias.hunger@digia.com>2013-01-21 10:41:01 +0100
commit65aef73ec4d6ff8f6752f83571c9310f8c6d793b (patch)
treecfad1907765bdeca9fa5b021f11c346198540815 /src/plugins/git
parent8f4da818c8a7184ffdf0268e652d2dcf867dffa9 (diff)
downloadqt-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.cpp21
-rw-r--r--src/plugins/git/gitclient.h4
-rw-r--r--src/plugins/git/gitplugin.cpp60
-rw-r--r--src/plugins/git/gitplugin.h7
-rw-r--r--src/plugins/git/mergetool.cpp51
-rw-r--r--src/plugins/git/mergetool.h4
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;
};