forked from qt-creator/qt-creator
Git: Interactive rebase
Change-Id: I3d106ce5b071df4a7a3d77be43e7c24bd7c91dfa Reviewed-by: Tobias Hunger <tobias.hunger@digia.com>
This commit is contained in:
committed by
Orgad Shaneh
parent
8705862786
commit
56881e3179
@@ -340,6 +340,37 @@ private:
|
||||
QString m_commit;
|
||||
};
|
||||
|
||||
class RebaseManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RebaseManager(QObject *parent) : QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
public slots:
|
||||
void readStdErr(const QString &error)
|
||||
{
|
||||
// rebase conflict is output to stdOut
|
||||
QRegExp conflictedCommit(QLatin1String("Could not apply ([^\\n]*)"));
|
||||
conflictedCommit.indexIn(error);
|
||||
m_commit = conflictedCommit.cap(1);
|
||||
}
|
||||
|
||||
void finished(bool ok, int exitCode, const QVariant &workingDirectory)
|
||||
{
|
||||
Q_UNUSED(ok);
|
||||
if (exitCode != 0 && !m_commit.isEmpty()) {
|
||||
GitPlugin::instance()->gitClient()->handleMergeConflicts(
|
||||
workingDirectory.toString(), m_commit, QLatin1String("rebase"));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
QString m_commit;
|
||||
};
|
||||
|
||||
Core::IEditor *locateEditor(const char *property, const QString &entry)
|
||||
{
|
||||
foreach (Core::IEditor *ed, Core::ICore::editorManager()->openedEditors())
|
||||
@@ -434,7 +465,7 @@ QString GitClient::findRepositoryForDirectory(const QString &dir)
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString GitClient::findGitDirForRepository(const QString &repositoryDir)
|
||||
QString GitClient::findGitDirForRepository(const QString &repositoryDir) const
|
||||
{
|
||||
static QHash<QString, QString> repoDirCache;
|
||||
QString &res = repoDirCache[repositoryDir];
|
||||
@@ -2335,6 +2366,19 @@ bool GitClient::synchronousMerge(const QString &workingDirectory, const QString
|
||||
return executeAndHandleConflicts(workingDirectory, arguments, command);
|
||||
}
|
||||
|
||||
bool GitClient::canRebase(const QString &workingDirectory) const
|
||||
{
|
||||
const QString gitDir = findGitDirForRepository(workingDirectory);
|
||||
if (QFileInfo(gitDir + QLatin1String("/rebase-apply")).exists()
|
||||
|| QFileInfo(gitDir + QLatin1String("/rebase-merge")).exists()) {
|
||||
VcsBase::VcsBaseOutputWindow::instance()->appendError(
|
||||
tr("Rebase, merge or am is in progress. Please finish "
|
||||
"or abort it then try again"));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GitClient::synchronousRebase(const QString &workingDirectory, const QString &baseBranch,
|
||||
const QString &topicBranch)
|
||||
{
|
||||
@@ -2366,6 +2410,21 @@ bool GitClient::cherryPickCommit(const QString &workingDirectory, const QString
|
||||
return executeAndHandleConflicts(workingDirectory, arguments, command);
|
||||
}
|
||||
|
||||
void GitClient::interactiveRebase(const QString &workingDirectory, const QString &commit)
|
||||
{
|
||||
QStringList arguments;
|
||||
arguments << QLatin1String("rebase") << QLatin1String("-i") << commit;
|
||||
outputWindow()->appendCommand(workingDirectory, settings()->stringValue(GitSettings::binaryPathKey), arguments);
|
||||
VcsBase::Command *command = createCommand(workingDirectory, 0, true);
|
||||
command->addJob(arguments, -1);
|
||||
command->execute();
|
||||
command->setCookie(workingDirectory);
|
||||
RebaseManager *rebaseManager = new RebaseManager(command);
|
||||
connect(command, SIGNAL(errorText(QString)), rebaseManager, SLOT(readStdErr(QString)));
|
||||
connect(command, SIGNAL(finished(bool,int,QVariant)),
|
||||
rebaseManager, SLOT(finished(bool,int,QVariant)));
|
||||
}
|
||||
|
||||
QString GitClient::msgNoChangedFiles()
|
||||
{
|
||||
return tr("There are no modified files.");
|
||||
|
||||
@@ -111,7 +111,7 @@ public:
|
||||
unsigned gitVersion(QString *errorMessage = 0) const;
|
||||
|
||||
QString findRepositoryForDirectory(const QString &dir);
|
||||
QString findGitDirForRepository(const QString &repositoryDir);
|
||||
QString findGitDirForRepository(const QString &repositoryDir) const;
|
||||
|
||||
void diff(const QString &workingDirectory, const QStringList &diffArgs, const QString &fileName);
|
||||
void diff(const QString &workingDirectory, const QStringList &diffArgs,
|
||||
@@ -199,11 +199,13 @@ public:
|
||||
bool synchronousPull(const QString &workingDirectory, bool rebase);
|
||||
bool synchronousPush(const QString &workingDirectory, const QString &remote = QString());
|
||||
bool synchronousMerge(const QString &workingDirectory, const QString &branch);
|
||||
bool canRebase(const QString &workingDirectory) const;
|
||||
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 interactiveRebase(const QString &workingDirectory, const QString &commit);
|
||||
void synchronousAbortCommand(const QString &workingDir, const QString &abortCommand);
|
||||
|
||||
// git svn support (asynchronous).
|
||||
|
||||
@@ -435,6 +435,10 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *errorMessage)
|
||||
tr("Reset..."), Core::Id("Git.Reset"),
|
||||
globalcontext, false, SLOT(resetRepository()));
|
||||
|
||||
createRepositoryAction(localRepositoryMenu,
|
||||
tr("Interactive Rebase..."), Core::Id("Git.Rebase"),
|
||||
globalcontext, true, SLOT(startRebase()));
|
||||
|
||||
createRepositoryAction(localRepositoryMenu,
|
||||
tr("Revert Single Commit..."), Core::Id("Git.Revert"),
|
||||
globalcontext, true, SLOT(startRevertCommit()));
|
||||
@@ -719,6 +723,24 @@ void GitPlugin::resetRepository()
|
||||
}
|
||||
}
|
||||
|
||||
void GitPlugin::startRebase()
|
||||
{
|
||||
QString workingDirectory = currentState().currentDirectoryOrTopLevel();
|
||||
if (workingDirectory.isEmpty() || !m_gitClient->canRebase(workingDirectory))
|
||||
return;
|
||||
GitClient::StashGuard stashGuard(workingDirectory, QLatin1String("Rebase-i"));
|
||||
if (stashGuard.stashingFailed(true))
|
||||
return;
|
||||
stashGuard.preventPop();
|
||||
LogChangeDialog dialog(false);
|
||||
dialog.setWindowTitle(tr("Interactive Rebase"));
|
||||
if (!dialog.runDialog(workingDirectory))
|
||||
return;
|
||||
const QString change = dialog.commit();
|
||||
if (!change.isEmpty())
|
||||
m_gitClient->interactiveRebase(workingDirectory, change);
|
||||
}
|
||||
|
||||
void GitPlugin::startRevertCommit()
|
||||
{
|
||||
const VcsBase::VcsBasePluginState state = currentState();
|
||||
|
||||
@@ -116,6 +116,7 @@ private slots:
|
||||
void undoFileChanges(bool revertStaging = true);
|
||||
void undoUnstagedFileChanges();
|
||||
void resetRepository();
|
||||
void startRebase();
|
||||
void startRevertCommit();
|
||||
void startCherryPickCommit();
|
||||
void stageFile();
|
||||
|
||||
Reference in New Issue
Block a user