Git: Use a separate thread for updating commit data

Task-number: QTCREATORBUG-12449
Change-Id: I3057ca458272daac72c54abce1d6f9acf6a5d4af
Reviewed-by: Tobias Hunger <tobias.hunger@digia.com>
This commit is contained in:
Orgad Shaneh
2014-06-20 16:00:20 +03:00
committed by Orgad Shaneh
parent aaa7cd5851
commit f3106ebafe
6 changed files with 100 additions and 9 deletions

View File

@@ -3174,6 +3174,11 @@ void GitClient::handleMergeConflicts(const QString &workingDir, const QString &c
} }
} }
void GitClient::addFuture(const QFuture<void> &future)
{
m_synchronizer.addFuture(future);
}
// Subversion: git svn // Subversion: git svn
void GitClient::synchronousSubversionFetch(const QString &workingDirectory) void GitClient::synchronousSubversionFetch(const QString &workingDirectory)
{ {

View File

@@ -35,6 +35,7 @@
#include <coreplugin/editormanager/ieditor.h> #include <coreplugin/editormanager/ieditor.h>
#include <QFutureSynchronizer>
#include <QObject> #include <QObject>
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
@@ -329,6 +330,7 @@ public:
void endStashScope(const QString &workingDirectory); void endStashScope(const QString &workingDirectory);
bool isValidRevision(const QString &revision) const; bool isValidRevision(const QString &revision) const;
void handleMergeConflicts(const QString &workingDir, const QString &commit, const QStringList &files, const QString &abortCommand); void handleMergeConflicts(const QString &workingDir, const QString &commit, const QStringList &files, const QString &abortCommand);
void addFuture(const QFuture<void> &future);
static QString msgNoChangedFiles(); static QString msgNoChangedFiles();
static QString msgNoCommits(bool includeRemote); static QString msgNoCommits(bool includeRemote);
@@ -433,6 +435,7 @@ private:
int m_contextDiffFileIndex; int m_contextDiffFileIndex;
int m_contextChunkIndex; int m_contextChunkIndex;
QPointer<DiffEditor::DiffEditorController> m_contextDocument; QPointer<DiffEditor::DiffEditorController> m_contextDocument;
QFutureSynchronizer<void> m_synchronizer; // for commit updates
}; };
} // namespace Internal } // namespace Internal

View File

@@ -34,6 +34,7 @@
#include "gitsubmiteditorwidget.h" #include "gitsubmiteditorwidget.h"
#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <vcsbase/submitfilemodel.h> #include <vcsbase/submitfilemodel.h>
#include <vcsbase/vcsbaseoutputwindow.h> #include <vcsbase/vcsbaseoutputwindow.h>
@@ -41,6 +42,9 @@
#include <QDebug> #include <QDebug>
#include <QStringList> #include <QStringList>
#include <QTextCodec> #include <QTextCodec>
#include <QtConcurrentRun>
static const char TASK_UPDATE_COMMIT[] = "Git.UpdateCommit";
namespace Git { namespace Git {
namespace Internal { namespace Internal {
@@ -80,6 +84,38 @@ private:
} }
}; };
class CommitDataFetcher : public QObject
{
Q_OBJECT
public:
CommitDataFetcher(CommitType commitType, const QString &workingDirectory) :
m_commitData(commitType),
m_workingDirectory(workingDirectory)
{
}
void start()
{
GitClient *client = GitPlugin::instance()->gitClient();
QString commitTemplate;
bool success = client->getCommitData(m_workingDirectory, &commitTemplate,
m_commitData, &m_errorMessage);
emit finished(success);
}
const CommitData &commitData() const { return m_commitData; }
const QString &errorMessage() const { return m_errorMessage; }
signals:
void finished(bool result);
private:
CommitData m_commitData;
QString m_workingDirectory;
QString m_errorMessage;
};
/* The problem with git is that no diff can be obtained to for a random /* The problem with git is that no diff can be obtained to for a random
* multiselection of staged/unstaged files; it requires the --cached * multiselection of staged/unstaged files; it requires the --cached
* option for staged files. So, we sort apart the diff file lists * option for staged files. So, we sort apart the diff file lists
@@ -90,12 +126,18 @@ GitSubmitEditor::GitSubmitEditor(const VcsBase::VcsBaseSubmitEditorParameters *p
m_model(0), m_model(0),
m_commitEncoding(0), m_commitEncoding(0),
m_commitType(SimpleCommit), m_commitType(SimpleCommit),
m_firstUpdate(true) m_firstUpdate(true),
m_commitDataFetcher(0)
{ {
connect(this, SIGNAL(diffSelectedFiles(QList<int>)), this, SLOT(slotDiffSelected(QList<int>))); connect(this, SIGNAL(diffSelectedFiles(QList<int>)), this, SLOT(slotDiffSelected(QList<int>)));
connect(submitEditorWidget(), SIGNAL(show(QString)), this, SLOT(showCommit(QString))); connect(submitEditorWidget(), SIGNAL(show(QString)), this, SLOT(showCommit(QString)));
} }
GitSubmitEditor::~GitSubmitEditor()
{
resetCommitDataFetcher();
}
GitSubmitEditorWidget *GitSubmitEditor::submitEditorWidget() GitSubmitEditorWidget *GitSubmitEditor::submitEditorWidget()
{ {
return static_cast<GitSubmitEditorWidget *>(widget()); return static_cast<GitSubmitEditorWidget *>(widget());
@@ -106,6 +148,14 @@ const GitSubmitEditorWidget *GitSubmitEditor::submitEditorWidget() const
return static_cast<GitSubmitEditorWidget *>(widget()); return static_cast<GitSubmitEditorWidget *>(widget());
} }
void GitSubmitEditor::resetCommitDataFetcher()
{
if (!m_commitDataFetcher)
return;
disconnect(m_commitDataFetcher, SIGNAL(finished(bool)), this, SLOT(commitDataRetrieved(bool)));
connect(m_commitDataFetcher, SIGNAL(finished(bool)), m_commitDataFetcher, SLOT(deleteLater()));
}
void GitSubmitEditor::setCommitData(const CommitData &d) void GitSubmitEditor::setCommitData(const CommitData &d)
{ {
m_commitEncoding = d.commitEncoding; m_commitEncoding = d.commitEncoding;
@@ -181,19 +231,32 @@ void GitSubmitEditor::updateFileModel()
} }
if (m_workingDirectory.isEmpty()) if (m_workingDirectory.isEmpty())
return; return;
GitClient *client = GitPlugin::instance()->gitClient(); submitEditorWidget()->setUpdateInProgress(true);
QString errorMessage, commitTemplate; resetCommitDataFetcher();
CommitData data(m_commitType); m_commitDataFetcher = new CommitDataFetcher(m_commitType, m_workingDirectory);
if (client->getCommitData(m_workingDirectory, &commitTemplate, data, &errorMessage)) { connect(m_commitDataFetcher, SIGNAL(finished(bool)), this, SLOT(commitDataRetrieved(bool)));
setCommitData(data); QFuture<void> future = QtConcurrent::run(m_commitDataFetcher, &CommitDataFetcher::start);
Core::ProgressManager::addTask(future, tr("Refreshing Commit Data"), TASK_UPDATE_COMMIT);
GitPlugin::instance()->gitClient()->addFuture(future);
}
void GitSubmitEditor::commitDataRetrieved(bool success)
{
GitSubmitEditorWidget *w = submitEditorWidget();
w->setUpdateInProgress(false);
if (success) {
setCommitData(m_commitDataFetcher->commitData());
submitEditorWidget()->refreshLog(m_workingDirectory); submitEditorWidget()->refreshLog(m_workingDirectory);
widget()->setEnabled(true); w->setEnabled(true);
} else { } else {
// Nothing to commit left! // Nothing to commit left!
VcsBase::VcsBaseOutputWindow::instance()->appendError(errorMessage); VcsBase::VcsBaseOutputWindow::instance()->appendError(m_commitDataFetcher->errorMessage());
m_model->clear(); m_model->clear();
widget()->setEnabled(false); w->setEnabled(false);
} }
m_commitDataFetcher->deleteLater();
m_commitDataFetcher = 0;
} }
GitSubmitEditorPanelData GitSubmitEditor::panelData() const GitSubmitEditorPanelData GitSubmitEditor::panelData() const
@@ -222,3 +285,5 @@ QByteArray GitSubmitEditor::fileContents() const
} // namespace Internal } // namespace Internal
} // namespace Git } // namespace Git
#include "gitsubmiteditor.moc"

View File

@@ -43,6 +43,7 @@ namespace Internal {
class GitSubmitEditorWidget; class GitSubmitEditorWidget;
class CommitData; class CommitData;
class CommitDataFetcher;
struct GitSubmitEditorPanelData; struct GitSubmitEditorPanelData;
class GitSubmitEditor : public VcsBase::VcsBaseSubmitEditor class GitSubmitEditor : public VcsBase::VcsBaseSubmitEditor
@@ -50,6 +51,7 @@ class GitSubmitEditor : public VcsBase::VcsBaseSubmitEditor
Q_OBJECT Q_OBJECT
public: public:
explicit GitSubmitEditor(const VcsBase::VcsBaseSubmitEditorParameters *parameters, QWidget *parent); explicit GitSubmitEditor(const VcsBase::VcsBaseSubmitEditorParameters *parameters, QWidget *parent);
~GitSubmitEditor();
void setCommitData(const CommitData &); void setCommitData(const CommitData &);
GitSubmitEditorPanelData panelData() const; GitSubmitEditorPanelData panelData() const;
@@ -68,10 +70,12 @@ protected:
private slots: private slots:
void slotDiffSelected(const QList<int> &rows); void slotDiffSelected(const QList<int> &rows);
void showCommit(const QString &commit); void showCommit(const QString &commit);
void commitDataRetrieved(bool success);
private: private:
inline GitSubmitEditorWidget *submitEditorWidget(); inline GitSubmitEditorWidget *submitEditorWidget();
inline const GitSubmitEditorWidget *submitEditorWidget() const; inline const GitSubmitEditorWidget *submitEditorWidget() const;
void resetCommitDataFetcher();
VcsBase::SubmitFileModel *m_model; VcsBase::SubmitFileModel *m_model;
QTextCodec *m_commitEncoding; QTextCodec *m_commitEncoding;
@@ -79,6 +83,7 @@ private:
QString m_amendSHA1; QString m_amendSHA1;
QString m_workingDirectory; QString m_workingDirectory;
bool m_firstUpdate; bool m_firstUpdate;
CommitDataFetcher *m_commitDataFetcher;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -156,6 +156,7 @@ struct SubmitEditorWidgetPrivate
bool m_commitEnabled; bool m_commitEnabled;
bool m_ignoreChange; bool m_ignoreChange;
bool m_descriptionMandatory; bool m_descriptionMandatory;
bool m_updateInProgress;
QActionPushButton *m_submitButton; QActionPushButton *m_submitButton;
}; };
@@ -170,6 +171,7 @@ SubmitEditorWidgetPrivate::SubmitEditorWidgetPrivate() :
m_commitEnabled(false), m_commitEnabled(false),
m_ignoreChange(false), m_ignoreChange(false),
m_descriptionMandatory(true), m_descriptionMandatory(true),
m_updateInProgress(false),
m_submitButton(0) m_submitButton(0)
{ {
} }
@@ -567,12 +569,20 @@ void SubmitEditorWidget::descriptionTextChanged()
bool SubmitEditorWidget::canSubmit() const bool SubmitEditorWidget::canSubmit() const
{ {
if (d->m_updateInProgress)
return false;
if (isDescriptionMandatory() && cleanupDescription(descriptionText()).trimmed().isEmpty()) if (isDescriptionMandatory() && cleanupDescription(descriptionText()).trimmed().isEmpty())
return false; return false;
const unsigned checkedCount = checkedFilesCount(); const unsigned checkedCount = checkedFilesCount();
return d->m_emptyFileListEnabled || checkedCount > 0; return d->m_emptyFileListEnabled || checkedCount > 0;
} }
void SubmitEditorWidget::setUpdateInProgress(bool value)
{
d->m_updateInProgress = value;
updateSubmitAction();
}
QString SubmitEditorWidget::commitName() const QString SubmitEditorWidget::commitName() const
{ {
return tr("&Commit"); return tr("&Commit");

View File

@@ -104,6 +104,7 @@ public:
QList<SubmitFieldWidget *> submitFieldWidgets() const; QList<SubmitFieldWidget *> submitFieldWidgets() const;
virtual bool canSubmit() const; virtual bool canSubmit() const;
void setUpdateInProgress(bool value);
signals: signals:
void diffSelected(const QList<int> &); void diffSelected(const QList<int> &);
@@ -126,6 +127,8 @@ protected:
protected slots: protected slots:
void descriptionTextChanged(); void descriptionTextChanged();
public slots:
void updateSubmitAction(); void updateSubmitAction();
private slots: private slots: