diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 80623839459..5ac84c5ac45 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -648,7 +648,7 @@ public: static bool gitHasRgbColors() { - const unsigned gitVersion = GitClient::instance()->gitVersion(); + const unsigned gitVersion = GitClient::instance()->gitVersion().result(); return gitVersion >= 0x020300U; } @@ -3611,36 +3611,10 @@ QString GitClient::readOneLine(const FilePath &workingDirectory, const QStringLi return proc.cleanedStdOut().trimmed(); } -// determine version as '(major << 16) + (minor << 8) + patch' or 0. -unsigned GitClient::gitVersion(QString *errorMessage) const +static unsigned parseGitVersion(const QString &output) { - const FilePath newGitBinary = vcsBinary(); - if (m_gitVersionForBinary != newGitBinary && !newGitBinary.isEmpty()) { - // Do not execute repeatedly if that fails (due to git - // not being installed) until settings are changed. - m_cachedGitVersion = synchronousGitVersion(errorMessage); - m_gitVersionForBinary = newGitBinary; - } - return m_cachedGitVersion; -} - -// determine version as '(major << 16) + (minor << 8) + patch' or 0. -unsigned GitClient::synchronousGitVersion(QString *errorMessage) const -{ - if (vcsBinary().isEmpty()) - return 0; - - // run git --version - QtcProcess proc; - vcsSynchronousExec(proc, {}, {"--version"}, silentFlags); - if (proc.result() != ProcessResult::FinishedWithSuccess) { - msgCannotRun(tr("Cannot determine Git version: %1").arg(proc.cleanedStdErr()), errorMessage); - return 0; - } - // cut 'git version 1.6.5.1.sha' // another form: 'git version 1.9.rc1' - const QString output = proc.cleanedStdOut(); const QRegularExpression versionPattern("^[^\\d]+(\\d+)\\.(\\d+)\\.(\\d+|rc\\d).*$"); QTC_ASSERT(versionPattern.isValid(), return 0); const QRegularExpressionMatch match = versionPattern.match(output); @@ -3651,6 +3625,41 @@ unsigned GitClient::synchronousGitVersion(QString *errorMessage) const return version(majorV, minorV, patchV); } +// determine version as '(major << 16) + (minor << 8) + patch' or 0. +QFuture GitClient::gitVersion() const +{ + QFutureInterface fi; + fi.reportStarted(); + + // Do not execute repeatedly if that fails (due to git + // not being installed) until settings are changed. + const FilePath newGitBinary = vcsBinary(); + const bool needToRunGit = m_gitVersionForBinary != newGitBinary && !newGitBinary.isEmpty(); + if (needToRunGit) { + auto proc = new QtcProcess(const_cast(this)); + connect(proc, &QtcProcess::done, this, [this, proc, fi, newGitBinary]() mutable { + if (proc->result() == ProcessResult::FinishedWithSuccess) { + m_cachedGitVersion = parseGitVersion(proc->cleanedStdOut()); + m_gitVersionForBinary = newGitBinary; + fi.reportResult(m_cachedGitVersion); + fi.reportFinished(); + } + proc->deleteLater(); + }); + + proc->setTimeoutS(vcsTimeoutS()); + proc->setEnvironment(processEnvironment()); + proc->setCommand({newGitBinary, {"--version"}}); + proc->start(); + } else { + // already cached + fi.reportResult(m_cachedGitVersion); + fi.reportFinished(); + } + + return fi.future(); +} + bool GitClient::StashInfo::init(const FilePath &workingDirectory, const QString &command, StashFlag flag, PushAction pushAction) { diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h index c356f79ff41..1571183d5ca 100644 --- a/src/plugins/git/gitclient.h +++ b/src/plugins/git/gitclient.h @@ -145,7 +145,7 @@ public: static GitSettings &settings(); Utils::FilePath vcsBinary() const override; - unsigned gitVersion(QString *errorMessage = nullptr) const; + QFuture gitVersion() const; VcsBase::VcsCommand *vcsExecAbortable(const Utils::FilePath &workingDirectory, const QStringList &arguments, @@ -387,9 +387,6 @@ private: const Utils::FilePath &workingDirectory, std::function factory) const; - // determine version as '(major << 16) + (minor << 8) + patch' or 0. - unsigned synchronousGitVersion(QString *errorMessage = nullptr) const; - QString readOneLine(const Utils::FilePath &workingDirectory, const QStringList &arguments) const; enum RevertResult { RevertOk, RevertUnchanged, RevertCanceled, RevertFailed }; diff --git a/src/plugins/git/gitgrep.cpp b/src/plugins/git/gitgrep.cpp index 4395c96bd12..fa2d9cdadda 100644 --- a/src/plugins/git/gitgrep.cpp +++ b/src/plugins/git/gitgrep.cpp @@ -247,10 +247,15 @@ GitGrep::GitGrep(GitClient *client) const QRegularExpression refExpression("[\\S]*"); m_treeLineEdit->setValidator(new QRegularExpressionValidator(refExpression, this)); layout->addWidget(m_treeLineEdit); - if (client->gitVersion() >= 0x021300) { - m_recurseSubmodules = new QCheckBox(tr("Recurse submodules")); - layout->addWidget(m_recurseSubmodules); - } + // asynchronously check git version, add "recurse submodules" option if available + Utils::onResultReady(client->gitVersion(), + this, + [this, pLayout = QPointer(layout)](unsigned version) { + if (version >= 0x021300 && pLayout) { + m_recurseSubmodules = new QCheckBox(tr("Recurse submodules")); + pLayout->addWidget(m_recurseSubmodules); + } + }); TextEditor::FindInFiles *findInFiles = TextEditor::FindInFiles::instance(); QTC_ASSERT(findInFiles, return); connect(findInFiles, &TextEditor::FindInFiles::pathChanged, diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp index 74faef36ddb..f007303c4d3 100644 --- a/src/plugins/git/gitplugin.cpp +++ b/src/plugins/git/gitplugin.cpp @@ -66,6 +66,7 @@ #include #include #include +#include #include #include @@ -1367,20 +1368,22 @@ void GitPluginPrivate::startCommit(CommitType commitType) void GitPluginPrivate::updateVersionWarning() { - unsigned version = m_gitClient.gitVersion(); - if (!version || version >= minimumRequiredVersion) - return; - IDocument *curDocument = EditorManager::currentDocument(); + QPointer curDocument = EditorManager::currentDocument(); if (!curDocument) return; - InfoBar *infoBar = curDocument->infoBar(); - Id gitVersionWarning("GitVersionWarning"); - if (!infoBar->canInfoBeAdded(gitVersionWarning)) - return; - infoBar->addInfo(InfoBarEntry(gitVersionWarning, - tr("Unsupported version of Git found. Git %1 or later required.") - .arg(versionString(minimumRequiredVersion)), - InfoBarEntry::GlobalSuppression::Enabled)); + Utils::onResultReady(m_gitClient.gitVersion(), this, [curDocument](unsigned version) { + if (!curDocument || !version || version >= minimumRequiredVersion) + return; + InfoBar *infoBar = curDocument->infoBar(); + Id gitVersionWarning("GitVersionWarning"); + if (!infoBar->canInfoBeAdded(gitVersionWarning)) + return; + infoBar->addInfo( + InfoBarEntry(gitVersionWarning, + tr("Unsupported version of Git found. Git %1 or later required.") + .arg(versionString(minimumRequiredVersion)), + InfoBarEntry::GlobalSuppression::Enabled)); + }); } IEditor *GitPluginPrivate::openSubmitEditor(const QString &fileName, const CommitData &cd)