Commit 8695fe6d authored by Orgad Shaneh's avatar Orgad Shaneh Committed by Orgad Shaneh

Git: Implement "Fixup previous commit"

Change-Id: Ia2584ff975ed0db614dc878a70ce4adbd5c3ba67
Reviewed-by: default avatarTobias Hunger <tobias.hunger@digia.com>
parent 5d325f6b
......@@ -437,7 +437,8 @@ GitClient::GitClient(GitSettings *settings) :
m_cachedGitVersion(0),
m_msgWait(tr("Waiting for data...")),
m_repositoryChangedSignalMapper(0),
m_settings(settings)
m_settings(settings),
m_disableEditor(false)
{
QTC_CHECK(settings);
connect(Core::ICore::instance(), SIGNAL(saveSettingsRequested()), this, SLOT(saveSettings()));
......@@ -1701,7 +1702,7 @@ QProcessEnvironment GitClient::processEnvironment() const
&& settings()->boolValue(GitSettings::winSetHomeEnvironmentKey)) {
environment.insert(QLatin1String("HOME"), QDir::toNativeSeparators(QDir::homePath()));
}
environment.insert(QLatin1String("GIT_EDITOR"), m_gitQtcEditor);
environment.insert(QLatin1String("GIT_EDITOR"), m_disableEditor ? QLatin1String("true") : m_gitQtcEditor);
// Set up SSH and C locale (required by git using perl).
VcsBase::VcsBasePlugin::setProcessEnvironment(&environment, false);
return environment;
......@@ -2139,6 +2140,8 @@ bool GitClient::getCommitData(const QString &workingDirectory,
}
break;
}
case FixupCommit:
break;
}
return true;
}
......@@ -2155,12 +2158,12 @@ static inline QString msgCommitted(const QString &amendSHA1, int fileCount)
bool GitClient::addAndCommit(const QString &repositoryDirectory,
const GitSubmitEditorPanelData &data,
CommitType commitType,
const QString &amendSHA1,
const QString &messageFile,
VcsBase::SubmitFileModel *model)
{
const QString renameSeparator = QLatin1String(" -> ");
const bool amend = !amendSHA1.isEmpty();
QStringList filesToAdd;
QStringList filesToRemove;
......@@ -2218,15 +2221,19 @@ bool GitClient::addAndCommit(const QString &repositoryDirectory,
// Do the final commit
QStringList args;
args << QLatin1String("commit")
<< QLatin1String("-F") << QDir::toNativeSeparators(messageFile);
if (amend)
args << QLatin1String("commit");
if (commitType == FixupCommit) {
args << QLatin1String("--fixup") << amendSHA1;
} else {
args << QLatin1String("-F") << QDir::toNativeSeparators(messageFile);
if (commitType == AmendCommit)
args << QLatin1String("--amend");
const QString &authorString = data.authorString();
if (!authorString.isEmpty())
args << QLatin1String("--author") << authorString;
if (data.bypassHooks)
args << QLatin1String("--no-verify");
}
QByteArray outputText;
QByteArray errorText;
......@@ -2544,11 +2551,16 @@ bool GitClient::synchronousCherryPick(const QString &workingDirectory, const QSt
}
void GitClient::interactiveRebase(const QString &workingDirectory, const QString &commit,
StashGuard &stashGuard)
StashGuard &stashGuard, bool fixup)
{
QStringList arguments;
arguments << QLatin1String("rebase") << QLatin1String("-i") << commit + QLatin1Char('^');
arguments << QLatin1String("rebase") << QLatin1String("-i");
if (fixup)
arguments << QLatin1String("--autosquash");
arguments << commit + QLatin1Char('^');
outputWindow()->appendCommand(workingDirectory, settings()->stringValue(GitSettings::binaryPathKey), arguments);
if (fixup)
m_disableEditor = true;
VcsBase::Command *command = createCommand(workingDirectory, 0, true);
command->addJob(arguments, -1);
command->execute();
......@@ -2557,6 +2569,8 @@ void GitClient::interactiveRebase(const QString &workingDirectory, const QString
connect(command, SIGNAL(errorText(QString)), rebaseManager, SLOT(readStdErr(QString)));
connect(command, SIGNAL(finished(bool,int,QVariant)),
rebaseManager, SLOT(finished(bool,int,QVariant)));
if (fixup)
m_disableEditor = false;
}
QString GitClient::msgNoChangedFiles()
......
......@@ -238,7 +238,7 @@ public:
bool synchronousRevert(const QString &workingDirectory, const QString &commit);
bool synchronousCherryPick(const QString &workingDirectory, const QString &commit);
void interactiveRebase(const QString &workingDirectory, const QString &commit,
StashGuard &stashGuard);
StashGuard &stashGuard, bool fixup);
void synchronousAbortCommand(const QString &workingDir, const QString &abortCommand);
// git svn support (asynchronous).
......@@ -267,6 +267,7 @@ public:
bool addAndCommit(const QString &workingDirectory,
const GitSubmitEditorPanelData &data,
CommitType commitType,
const QString &amendSHA1,
const QString &messageFile,
VcsBase::SubmitFileModel *model);
......@@ -376,6 +377,7 @@ private:
QSignalMapper *m_repositoryChangedSignalMapper;
GitSettings *m_settings;
QString m_gitQtcEditor;
bool m_disableEditor;
};
} // namespace Internal
......
......@@ -424,6 +424,10 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *errorMessage)
createRepositoryAction(localRepositoryMenu,
tr("Amend Last Commit..."), Core::Id("Git.AmendCommit"),
globalcontext, true, SLOT(startAmendCommit()));
createRepositoryAction(localRepositoryMenu,
tr("Fixup Previous Commit..."), Core::Id("Git.FixupCommit"),
globalcontext, true, SLOT(startFixupCommit()));
// --------------
localRepositoryMenu->addSeparator(globalcontext);
......@@ -769,7 +773,7 @@ void GitPlugin::startRebase()
return;
const QString change = dialog.commit();
if (!change.isEmpty())
m_gitClient->interactiveRebase(workingDirectory, change, *stashGuard.take());
m_gitClient->interactiveRebase(workingDirectory, change, *stashGuard.take(), false);
}
void GitPlugin::startChangeRelatedAction()
......@@ -879,6 +883,11 @@ void GitPlugin::startAmendCommit()
startCommit(AmendCommit);
}
void GitPlugin::startFixupCommit()
{
startCommit(FixupCommit);
}
void GitPlugin::startCommit()
{
startCommit(SimpleCommit);
......@@ -906,7 +915,6 @@ void GitPlugin::startCommit(CommitType commitType)
// Store repository for diff and the original list of
// files to be able to unstage files the user unchecks
m_submitRepository = data.panelInfo.repository;
m_commitAmendSHA1 = data.amendSHA1;
// Start new temp file with message template
Utils::TempFileSaver saver;
......@@ -1009,18 +1017,30 @@ bool GitPlugin::submitEditorAboutToClose()
// Go ahead!
VcsBase::SubmitFileModel *model = qobject_cast<VcsBase::SubmitFileModel *>(editor->fileModel());
bool closeEditor = true;
if (model->hasCheckedFiles() || !m_commitAmendSHA1.isEmpty()) {
CommitType commitType = editor->commitType();
QString amendSHA1 = editor->amendSHA1();
if (model->hasCheckedFiles() || !amendSHA1.isEmpty()) {
// get message & commit
if (!Core::DocumentManager::saveDocument(editorDocument))
return false;
closeEditor = m_gitClient->addAndCommit(m_submitRepository, editor->panelData(),
m_commitAmendSHA1, m_commitMessageFileName, model);
commitType, amendSHA1,
m_commitMessageFileName, model);
}
if (closeEditor) {
cleanCommitMessageFile();
if (commitType == FixupCommit) {
QScopedPointer<GitClient::StashGuard> stashGuard(
new GitClient::StashGuard(m_submitRepository, QLatin1String("Rebase-fixup"),
NoPrompt));
if (stashGuard->stashingFailed())
return false;
m_gitClient->interactiveRebase(m_submitRepository, amendSHA1, *stashGuard.take(), true);
} else {
m_gitClient->continueCommandIfNeeded(m_submitRepository);
}
}
return closeEditor;
}
......
......@@ -131,6 +131,7 @@ private slots:
void gitClientMemberFuncRepositoryAction();
void startAmendCommit();
void startFixupCommit();
void stash();
void stashSnapshot();
void branchList();
......@@ -231,7 +232,6 @@ private:
QPointer<RemoteDialog> m_remoteDialog;
QString m_submitRepository;
QString m_commitMessageFileName;
QString m_commitAmendSHA1;
bool m_submitActionTriggered;
GitSettings m_settings;
......
......@@ -38,7 +38,8 @@ namespace Internal {
enum CommitType
{
SimpleCommit,
AmendCommit
AmendCommit,
FixupCommit
};
// Todo: Add user name and password?
......
......@@ -103,14 +103,17 @@ const GitSubmitEditorWidget *GitSubmitEditor::submitEditorWidget() const
void GitSubmitEditor::setCommitData(const CommitData &d)
{
m_commitEncoding = d.commitEncoding;
m_workingDirectory = d.panelInfo.repository;
m_commitType = d.commitType;
m_amendSHA1 = d.amendSHA1;
GitSubmitEditorWidget *w = submitEditorWidget();
w->initialize(m_commitType, m_workingDirectory);
w->setPanelData(d.panelData);
w->setPanelInfo(d.panelInfo);
w->setHasUnmerged(false);
m_commitEncoding = d.commitEncoding;
m_workingDirectory = d.panelInfo.repository;
m_commitType = d.commitType;
setEmptyFileListEnabled(m_commitType == AmendCommit); // Allow for just correcting the message
m_model = new GitSubmitFileModel(this);
......@@ -178,6 +181,12 @@ GitSubmitEditorPanelData GitSubmitEditor::panelData() const
return submitEditorWidget()->panelData();
}
QString GitSubmitEditor::amendSHA1() const
{
QString commit = submitEditorWidget()->amendSHA1();
return commit.isEmpty() ? m_amendSHA1 : commit;
}
QByteArray GitSubmitEditor::fileContents() const
{
const QString &text = submitEditorWidget()->descriptionText();
......
......@@ -56,6 +56,8 @@ public:
void setCommitData(const CommitData &);
GitSubmitEditorPanelData panelData() const;
bool forceClose() const { return m_forceClose; }
CommitType commitType() const { return m_commitType; }
QString amendSHA1() const;
signals:
void diff(const QStringList &unstagedFiles, const QStringList &stagedFiles);
......@@ -75,6 +77,7 @@ private:
VcsBase::SubmitFileModel *m_model;
QString m_commitEncoding;
CommitType m_commitType;
QString m_amendSHA1;
bool m_forceClose;
QString m_workingDirectory;
};
......
......@@ -29,6 +29,7 @@
#include "gitsubmiteditorwidget.h"
#include "commitdata.h"
#include "logchangedialog.h"
#include <texteditor/texteditorsettings.h>
#include <texteditor/fontsettings.h>
......@@ -40,7 +41,9 @@
#include <QDebug>
#include <QDir>
#include <QGroupBox>
#include <QRegExp>
#include <QVBoxLayout>
namespace Git {
namespace Internal {
......@@ -120,10 +123,11 @@ void GitSubmitHighlighter::highlightBlock(const QString &text)
GitSubmitEditorWidget::GitSubmitEditorWidget(QWidget *parent) :
VcsBase::SubmitEditorWidget(parent),
m_gitSubmitPanel(new QWidget),
m_hasUnmerged(false)
m_logChangeWidget(0),
m_hasUnmerged(false),
m_isInitialized(false)
{
m_gitSubmitPanelUi.setupUi(m_gitSubmitPanel);
insertTopWidget(m_gitSubmitPanel);
new GitSubmitHighlighter(descriptionEdit());
m_emailValidator = new QRegExpValidator(QRegExp(QLatin1String("[^@ ]+@[^@ ]+\\.[a-zA-Z]+")), this);
......@@ -144,11 +148,35 @@ void GitSubmitEditorWidget::setPanelInfo(const GitSubmitEditorPanelInfo &info)
m_gitSubmitPanelUi.branchLabel->setText(info.branch);
}
QString GitSubmitEditorWidget::amendSHA1() const
{
return m_logChangeWidget ? m_logChangeWidget->commit() : QString();
}
void GitSubmitEditorWidget::setHasUnmerged(bool e)
{
m_hasUnmerged = e;
}
void GitSubmitEditorWidget::initialize(CommitType commitType, const QString &repository)
{
if (m_isInitialized)
return;
m_isInitialized = true;
if (commitType == FixupCommit) {
QGroupBox *logChangeGroupBox = new QGroupBox(tr("Select Change"));
QVBoxLayout *logChangeLayout = new QVBoxLayout;
logChangeGroupBox->setLayout(logChangeLayout);
m_logChangeWidget = new LogChangeWidget;
m_logChangeWidget->init(repository);
logChangeLayout->addWidget(m_logChangeWidget);
insertTopWidget(logChangeGroupBox);
m_gitSubmitPanelUi.editGroup->hide();
hideDescription();
}
insertTopWidget(m_gitSubmitPanel);
}
GitSubmitEditorPanelData GitSubmitEditorWidget::panelData() const
{
GitSubmitEditorPanelData rc;
......
......@@ -31,6 +31,7 @@
#define GITSUBMITEDITORWIDGET_H
#include "ui_gitsubmitpanel.h"
#include "gitsettings.h"
#include <vcsbase/submiteditorwidget.h>
......@@ -43,6 +44,7 @@ namespace Internal {
struct GitSubmitEditorPanelInfo;
struct GitSubmitEditorPanelData;
class LogChangeWidget;
/* Submit editor widget with 2 additional panes:
* 1) Info with branch, description, etc
......@@ -62,7 +64,9 @@ public:
GitSubmitEditorPanelData panelData() const;
void setPanelData(const GitSubmitEditorPanelData &data);
void setPanelInfo(const GitSubmitEditorPanelInfo &info);
QString amendSHA1() const;
void setHasUnmerged(bool e);
void initialize(CommitType commitType, const QString &repository);
protected:
bool canSubmit() const;
......@@ -75,9 +79,11 @@ private:
bool emailIsValid() const;
QWidget *m_gitSubmitPanel;
LogChangeWidget *m_logChangeWidget;
Ui::GitSubmitPanel m_gitSubmitPanelUi;
QValidator *m_emailValidator;
bool m_hasUnmerged;
bool m_isInitialized;
};
} // namespace Internal
......
......@@ -534,6 +534,12 @@ void SubmitEditorWidget::insertTopWidget(QWidget *w)
d->m_ui.vboxLayout->insertWidget(0, w);
}
void SubmitEditorWidget::hideDescription()
{
d->m_ui.descriptionBox->hide();
setDescriptionMandatory(false);
}
void SubmitEditorWidget::descriptionTextChanged()
{
#if QT_VERSION < 0x050000 // Fix Qt-Bug, see QTCREATORBUG-5633 && QTCREATORBUG-6082
......
......@@ -122,6 +122,7 @@ protected:
virtual void changeEvent(QEvent *e);
virtual QString commitName() const;
void insertTopWidget(QWidget *w);
void hideDescription();
protected slots:
void descriptionTextChanged();
......
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