Commit 65aef73e authored by Petar Perisin's avatar Petar Perisin Committed by Tobias Hunger
Browse files

Git: Added Revert and cherry-pick



Change-Id: Ic8ba7434e79b12eca680a67c2845c82915dc0088
Reviewed-by: Orgad Shaneh's avatarOrgad Shaneh <orgads@gmail.com>
Reviewed-by: default avatarTobias Hunger <tobias.hunger@digia.com>
parent 8f4da818
......@@ -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.");
......
......@@ -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,
......
......@@ -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();
......
......@@ -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();
......
......@@ -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));
......
......@@ -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;
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment