Git: Speed up the unmanagedFiles() function

Given a list of files, we should not call git for every single one of
them to figure out which ones are part of the repository, because this
job can be done with a single call.
As a test case, I added my whole ~/dev directory with ca 600,000 source
files to a generic project. With this patch, the time spent on
retrieving the list of unmanaged files went down from nine hours to
seven seconds.

Task-number: QTCREATORBUG-20652
Change-Id: Ic04a2b973e14eff549a2642bde7bc269df069fd1
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
Christian Kandeler
2019-11-14 13:29:48 +01:00
parent bb5727de17
commit b7395e97f3
4 changed files with 26 additions and 0 deletions

View File

@@ -823,6 +823,24 @@ bool GitClient::managesFile(const QString &workingDirectory, const QString &file
== SynchronousProcessResponse::Finished;
}
QStringList GitClient::unmanagedFiles(const QString &workingDirectory,
const QStringList &filePaths) const
{
QStringList args({"ls-files", "-z"});
QDir wd(workingDirectory);
args << transform(filePaths, [&wd](const QString &fp) { return wd.relativeFilePath(fp); });
const SynchronousProcessResponse response
= vcsFullySynchronousExec(workingDirectory, args, Core::ShellCommand::NoOutput);
if (response.result != SynchronousProcessResponse::Finished)
return filePaths;
const QStringList managedFilePaths
= transform(response.stdOut().split('\0', QString::SkipEmptyParts),
[&wd](const QString &fp) { return wd.absoluteFilePath(fp); });
return filtered(filePaths, [&managedFilePaths](const QString &fp) {
return !managedFilePaths.contains(fp);
});
}
QTextCodec *GitClient::codecFor(GitClient::CodecType codecType, const QString &source) const
{
if (codecType == CodecSource) {

View File

@@ -133,6 +133,7 @@ public:
QString findRepositoryForDirectory(const QString &directory) const;
QString findGitDirForRepository(const QString &repositoryDir) const;
bool managesFile(const QString &workingDirectory, const QString &fileName) const;
QStringList unmanagedFiles(const QString &workingDirectory, const QStringList &filePaths) const;
void diffFile(const QString &workingDirectory, const QString &fileName) const;
void diffFiles(const QString &workingDirectory,

View File

@@ -190,6 +190,12 @@ bool GitVersionControl::managesFile(const QString &workingDirectory, const QStri
return m_client->managesFile(workingDirectory, fileName);
}
QStringList GitVersionControl::unmanagedFiles(const QString &workingDir,
const QStringList &filePaths) const
{
return m_client->unmanagedFiles(workingDir, filePaths);
}
bool GitVersionControl::vcsAnnotate(const QString &file, int line)
{
const QFileInfo fi(file);

View File

@@ -46,6 +46,7 @@ public:
bool managesDirectory(const QString &directory, QString *topLevel) const final;
bool managesFile(const QString &workingDirectory, const QString &fileName) const final;
QStringList unmanagedFiles(const QString &workingDir, const QStringList &filePaths) const final;
bool isConfigured() const final;
bool supportsOperation(Operation operation) const final;