forked from qt-creator/qt-creator
Git: Make git show more async
git describe --tags can take very long when there are many tags. Run all the describe commands in parallel, and let the user work while they are running. Change-Id: Iee56a5d51f93e9c799521bb0b06ba08bb45cb237 Reviewed-by: Eike Ziller <eike.ziller@qt.io> Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: hjk <hjk@qt.io> Reviewed-by: André Hartmann <aha_1980@gmx.de>
This commit is contained in:
committed by
Orgad Shaneh
parent
5d14d127d7
commit
78b08f57a2
@@ -465,20 +465,32 @@ public:
|
||||
setStartupFile(VcsBase::source(this->document()));
|
||||
});
|
||||
}
|
||||
~ShowController()
|
||||
{
|
||||
abortCommands();
|
||||
}
|
||||
|
||||
void processCommandOutput(const QString &output) override;
|
||||
|
||||
private:
|
||||
void processDescription(const QString &output);
|
||||
void updateDescription();
|
||||
void abortCommands();
|
||||
const QString m_id;
|
||||
enum State { Idle, GettingDescription, GettingDiff };
|
||||
State m_state;
|
||||
QString m_header;
|
||||
QString m_body;
|
||||
QString m_precedes;
|
||||
QStringList m_follows;
|
||||
QList<QPointer<VcsCommand>> m_commands;
|
||||
};
|
||||
|
||||
void ShowController::processCommandOutput(const QString &output)
|
||||
{
|
||||
QTC_ASSERT(m_state != Idle, return);
|
||||
if (m_state == GettingDescription) {
|
||||
setDescription(m_instance->extendedShowDescription(workingDirectory(), output));
|
||||
processDescription(output);
|
||||
// stage 2
|
||||
m_state = GettingDiff;
|
||||
const QStringList args = {"show", "--format=format:", // omit header, already generated
|
||||
@@ -490,6 +502,68 @@ void ShowController::processCommandOutput(const QString &output)
|
||||
}
|
||||
}
|
||||
|
||||
void ShowController::processDescription(const QString &output)
|
||||
{
|
||||
abortCommands();
|
||||
if (!output.startsWith("commit ")) {
|
||||
setDescription(output);
|
||||
return;
|
||||
}
|
||||
QString modText = output;
|
||||
int lastHeaderLine = modText.indexOf("\n\n") + 1;
|
||||
m_header = output.left(lastHeaderLine) + Constants::EXPAND_BRANCHES + '\n';
|
||||
m_body = output.mid(lastHeaderLine + 1);
|
||||
m_precedes = tr("<resolving>");
|
||||
m_follows.append(m_precedes);
|
||||
updateDescription();
|
||||
const QString commit = modText.mid(7, 8);
|
||||
m_commands.append(m_instance->execBgCommand(
|
||||
workingDirectory(), {"describe", "--contains", commit},
|
||||
[this](const QString &text) {
|
||||
m_precedes = text.trimmed();
|
||||
const int tilde = m_precedes.indexOf('~');
|
||||
if (tilde != -1)
|
||||
m_precedes.truncate(tilde);
|
||||
if (m_precedes.endsWith("^0"))
|
||||
m_precedes.chop(2);
|
||||
updateDescription();
|
||||
}));
|
||||
QStringList parents;
|
||||
QString errorMessage;
|
||||
m_instance->synchronousParentRevisions(workingDirectory(), commit, &parents, &errorMessage);
|
||||
m_follows.resize(parents.size());
|
||||
for (int i = 0, total = parents.size(); i < total; ++i) {
|
||||
m_commands.append(m_instance->execBgCommand(
|
||||
workingDirectory(), {"describe", "--tags", "--abbrev=0", parents[i]},
|
||||
[this, i](const QString &text) {
|
||||
m_follows[i] = text.trimmed();
|
||||
updateDescription();
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
void ShowController::updateDescription()
|
||||
{
|
||||
QString desc = m_header;
|
||||
if (!m_precedes.isEmpty())
|
||||
desc.append("Precedes: " + m_precedes + '\n');
|
||||
QStringList follows = Utils::filtered(m_follows, &QString::size);
|
||||
if (!follows.isEmpty())
|
||||
desc.append("Follows: " + follows.join(", ") + '\n');
|
||||
desc.append('\n' + m_body);
|
||||
|
||||
setDescription(desc);
|
||||
}
|
||||
|
||||
void ShowController::abortCommands()
|
||||
{
|
||||
for (QPointer<VcsCommand> command : m_commands) {
|
||||
if (command)
|
||||
command->abort();
|
||||
}
|
||||
m_commands.clear();
|
||||
}
|
||||
|
||||
///////////////////////////////
|
||||
|
||||
class BaseGitDiffArgumentsWidget : public VcsBaseEditorConfig
|
||||
@@ -1798,35 +1872,6 @@ QString GitClient::synchronousTopRevision(const FilePath &workingDirectory, QDat
|
||||
return output.first();
|
||||
}
|
||||
|
||||
void GitClient::synchronousTagsForCommit(const FilePath &workingDirectory, const QString &revision,
|
||||
QString &precedes, QString &follows) const
|
||||
{
|
||||
QtcProcess proc1;
|
||||
vcsFullySynchronousExec(proc1, workingDirectory, {"describe", "--contains", revision}, silentFlags);
|
||||
precedes = proc1.stdOut();
|
||||
int tilde = precedes.indexOf('~');
|
||||
if (tilde != -1)
|
||||
precedes.truncate(tilde);
|
||||
else
|
||||
precedes = precedes.trimmed();
|
||||
|
||||
QStringList parents;
|
||||
QString errorMessage;
|
||||
synchronousParentRevisions(workingDirectory, revision, &parents, &errorMessage);
|
||||
for (const QString &p : qAsConst(parents)) {
|
||||
QtcProcess proc2;
|
||||
vcsFullySynchronousExec(proc2,
|
||||
workingDirectory, {"describe", "--tags", "--abbrev=0", p}, silentFlags);
|
||||
QString pf = proc2.stdOut();
|
||||
pf.truncate(pf.lastIndexOf('\n'));
|
||||
if (!pf.isEmpty()) {
|
||||
if (!follows.isEmpty())
|
||||
follows += ", ";
|
||||
follows += pf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GitClient::isRemoteCommit(const FilePath &workingDirectory, const QString &commit)
|
||||
{
|
||||
QtcProcess proc;
|
||||
@@ -2478,28 +2523,6 @@ void GitClient::continuePreviousGitCommand(const FilePath &workingDirectory,
|
||||
}
|
||||
}
|
||||
|
||||
QString GitClient::extendedShowDescription(const FilePath &workingDirectory, const QString &text) const
|
||||
{
|
||||
if (!text.startsWith("commit "))
|
||||
return text;
|
||||
QString modText = text;
|
||||
QString precedes, follows;
|
||||
int lastHeaderLine = modText.indexOf("\n\n") + 1;
|
||||
const QString commit = modText.mid(7, 8);
|
||||
synchronousTagsForCommit(workingDirectory, commit, precedes, follows);
|
||||
if (!precedes.isEmpty())
|
||||
modText.insert(lastHeaderLine, "Precedes: " + precedes + '\n');
|
||||
if (!follows.isEmpty())
|
||||
modText.insert(lastHeaderLine, "Follows: " + follows + '\n');
|
||||
|
||||
// Empty line before headers and commit message
|
||||
const int emptyLine = modText.indexOf("\n\n");
|
||||
if (emptyLine != -1)
|
||||
modText.insert(emptyLine, QString('\n') + Constants::EXPAND_BRANCHES);
|
||||
|
||||
return modText;
|
||||
}
|
||||
|
||||
// Quietly retrieve branch list of remote repository URL
|
||||
//
|
||||
// The branch HEAD is pointing to is always returned first.
|
||||
|
@@ -266,8 +266,6 @@ public:
|
||||
bool synchronousRevParseCmd(const Utils::FilePath &workingDirectory, const QString &ref,
|
||||
QString *output, QString *errorMessage = nullptr) const;
|
||||
QString synchronousTopRevision(const Utils::FilePath &workingDirectory, QDateTime *dateTime = nullptr);
|
||||
void synchronousTagsForCommit(const Utils::FilePath &workingDirectory, const QString &revision,
|
||||
QString &precedes, QString &follows) const;
|
||||
bool isRemoteCommit(const Utils::FilePath &workingDirectory, const QString &commit);
|
||||
bool isFastForwardMerge(const Utils::FilePath &workingDirectory, const QString &branch);
|
||||
|
||||
@@ -332,8 +330,6 @@ public:
|
||||
|
||||
void continueCommandIfNeeded(const Utils::FilePath &workingDirectory, bool allowContinue = true);
|
||||
|
||||
QString extendedShowDescription(const Utils::FilePath &workingDirectory, const QString &text) const;
|
||||
|
||||
void launchGitK(const Utils::FilePath &workingDirectory, const QString &fileName) const;
|
||||
void launchGitK(const Utils::FilePath &workingDirectory) const { launchGitK(workingDirectory, QString()); }
|
||||
bool launchGitGui(const Utils::FilePath &workingDirectory);
|
||||
|
Reference in New Issue
Block a user