Update mime database from Qt

qtbase/1f0bc1ade316547d01100dcca4f3f7187485f917
  QMimeDatabase: fix glob-deleteall support for the binary providers

And integrate Qt Creator's own override mechanism into the introduced
filter function.

Change-Id: I7c75a9830e263273af7ea3bfe35fc728e8421862
Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
This commit is contained in:
Eike Ziller
2024-08-29 15:37:10 +02:00
parent c713a28c43
commit f39ef79210
5 changed files with 53 additions and 95 deletions

View File

@@ -196,18 +196,12 @@ void MimeDatabasePrivate::loadProviders()
} }
} }
// Handle mimetypes with glob-deleteall tags (from XML providers)
auto it = m_providers.begin(); auto it = m_providers.begin();
(*it)->setOverrideProvider(nullptr);
++it;
const auto end = m_providers.end(); const auto end = m_providers.end();
for (;it != end; ++it) { for (; it != end; ++it)
const QStringList &list = (*it)->m_mimeTypesWithDeletedGlobs; (*it)->setOverrideProvider((it - 1)->get());
if (list.isEmpty())
continue;
// Each Provider affects Providers with lower precedence
auto nextIt = it + 1;
for (; nextIt != end; ++nextIt)
(*nextIt)->excludeMimeTypeGlobs(list);
}
updateOverriddenMimeTypes(m_providers); updateOverriddenMimeTypes(m_providers);
} }

View File

@@ -221,14 +221,11 @@ void MimeAllGlobPatterns::removeMimeType(const QString &mimeType)
m_lowWeightGlobs.removeMimeType(mimeType); m_lowWeightGlobs.removeMimeType(mimeType);
} }
void MimeGlobPatternList::match(MimeGlobMatchResult &result, void MimeGlobPatternList::match(MimeGlobMatchResult &result, const QString &fileName,
const QString &fileName, const AddMatchFilterFunc &filterFunc) const
const QSet<QString> &ignoreMimeTypes) const
{ {
for (const MimeGlobPattern &glob : *this) { for (const MimeGlobPattern &glob : *this) {
if (ignoreMimeTypes.contains(glob.mimeType())) if (glob.matchFileName(fileName) && filterFunc(glob.mimeType())) {
continue;
if (glob.matchFileName(fileName)) {
const QString pattern = glob.pattern(); const QString pattern = glob.pattern();
const qsizetype suffixLen = isSimplePattern(pattern) ? pattern.size() - strlen("*.") : 0; const qsizetype suffixLen = isSimplePattern(pattern) ? pattern.size() - strlen("*.") : 0;
result.addMatch(glob.mimeType(), glob.weight(), pattern, suffixLen); result.addMatch(glob.mimeType(), glob.weight(), pattern, suffixLen);
@@ -236,12 +233,11 @@ void MimeGlobPatternList::match(MimeGlobMatchResult &result,
} }
} }
void MimeAllGlobPatterns::matchingGlobs(const QString &fileName, void MimeAllGlobPatterns::matchingGlobs(const QString &fileName, MimeGlobMatchResult &result,
MimeGlobMatchResult &result, const AddMatchFilterFunc &filterFunc) const
const QSet<QString> &ignoreMimeTypes) const
{ {
// First try the high weight matches (>50), if any. // First try the high weight matches (>50), if any.
m_highWeightGlobs.match(result, fileName, ignoreMimeTypes); m_highWeightGlobs.match(result, fileName, filterFunc);
// Now use the "fast patterns" dict, for simple *.foo patterns with weight 50 // Now use the "fast patterns" dict, for simple *.foo patterns with weight 50
// (which is most of them, so this optimization is definitely worth it) // (which is most of them, so this optimization is definitely worth it)
@@ -254,15 +250,16 @@ void MimeAllGlobPatterns::matchingGlobs(const QString &fileName,
const QStringList matchingMimeTypes = m_fastPatterns.value(simpleExtension); const QStringList matchingMimeTypes = m_fastPatterns.value(simpleExtension);
const QString simplePattern = "*."_L1 + simpleExtension; const QString simplePattern = "*."_L1 + simpleExtension;
for (const QString &mime : matchingMimeTypes) { for (const QString &mime : matchingMimeTypes) {
if (!ignoreMimeTypes.contains(mime)) if (filterFunc(mime)) {
result.addMatch(mime, 50, simplePattern, simpleExtension.size()); result.addMatch(mime, 50, simplePattern, simpleExtension.size());
} }
}
// Can't return yet; *.tar.bz2 has to win over *.bz2, so we need the low-weight mimetypes anyway, // Can't return yet; *.tar.bz2 has to win over *.bz2, so we need the low-weight mimetypes anyway,
// at least those with weight 50. // at least those with weight 50.
} }
// Finally, try the low weight matches (<=50) // Finally, try the low weight matches (<=50)
m_lowWeightGlobs.match(result, fileName, ignoreMimeTypes); m_lowWeightGlobs.match(result, fileName, filterFunc);
} }
void MimeAllGlobPatterns::clear() void MimeAllGlobPatterns::clear()

View File

@@ -81,6 +81,8 @@ private:
PatternType m_patternType; PatternType m_patternType;
}; };
using AddMatchFilterFunc = std::function<bool(const QString &)>;
class MimeGlobPatternList : public QList<MimeGlobPattern> class MimeGlobPatternList : public QList<MimeGlobPattern>
{ {
public: public:
@@ -105,9 +107,8 @@ public:
erase(std::remove_if(begin(), end(), isMimeTypeEqual), end()); erase(std::remove_if(begin(), end(), isMimeTypeEqual), end());
} }
void match(MimeGlobMatchResult &result, void match(MimeGlobMatchResult &result, const QString &fileName,
const QString &fileName, const AddMatchFilterFunc &filterFunc) const;
const QSet<QString> &ignoreMimeTypes) const;
}; };
/*! /*!
@@ -124,9 +125,8 @@ public:
void addGlob(const MimeGlobPattern &glob); void addGlob(const MimeGlobPattern &glob);
void removeMimeType(const QString &mimeType); void removeMimeType(const QString &mimeType);
void matchingGlobs(const QString &fileName, void matchingGlobs(const QString &fileName, MimeGlobMatchResult &result,
MimeGlobMatchResult &result, const AddMatchFilterFunc &filterFunc) const;
const QSet<QString> &ignoreMimeTypes) const;
void clear(); void clear();
PatternsMap m_fastPatterns; // example: "doc" -> "application/msword", "text/plain" PatternsMap m_fastPatterns; // example: "doc" -> "application/msword", "text/plain"

View File

@@ -62,6 +62,25 @@ MimeProviderBase::MimeProviderBase(MimeDatabasePrivate *db, const QString &direc
{ {
} }
MimeProviderBase *MimeProviderBase::overrideProvider() const
{
return m_overrideProvider;
}
void MimeProviderBase::setOverrideProvider(MimeProviderBase *provider)
{
m_overrideProvider = provider;
}
bool MimeProviderBase::isMimeTypeGlobsExcluded(const QString &name) const
{
if (m_overrideProvider) {
if (m_overrideProvider->hasGlobDeleteAll(name))
return true;
return m_overrideProvider->isMimeTypeGlobsExcluded(name);
}
return false;
}
MimeBinaryProvider::MimeBinaryProvider(MimeDatabasePrivate *db, const QString &directory) MimeBinaryProvider::MimeBinaryProvider(MimeDatabasePrivate *db, const QString &directory)
: MimeProviderBase(db, directory), m_mimetypeListLoaded(false) : MimeProviderBase(db, directory), m_mimetypeListLoaded(false)
@@ -223,17 +242,6 @@ void MimeBinaryProvider::addFileNameMatches(const QString &fileName, MimeGlobMat
fileName); fileName);
} }
bool MimeBinaryProvider::isMimeTypeGlobsExcluded(const char *mimeTypeName)
{
return m_mimeTypesWithExcludedGlobs.contains(QLatin1StringView(mimeTypeName));
}
void MimeBinaryProvider::excludeMimeTypeGlobs(const QStringList &toExclude)
{
for (const auto &mt : toExclude)
appendIfNew(m_mimeTypesWithExcludedGlobs, mt);
}
int MimeBinaryProvider::matchGlobList(MimeGlobMatchResult &result, CacheFile *cacheFile, int off, int MimeBinaryProvider::matchGlobList(MimeGlobMatchResult &result, CacheFile *cacheFile, int off,
const QString &fileName) const QString &fileName)
{ {
@@ -249,7 +257,7 @@ int MimeBinaryProvider::matchGlobList(MimeGlobMatchResult &result, CacheFile *ca
const Qt::CaseSensitivity qtCaseSensitive = caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive; const Qt::CaseSensitivity qtCaseSensitive = caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
const QString pattern = QLatin1StringView(cacheFile->getCharStar(globOffset)); const QString pattern = QLatin1StringView(cacheFile->getCharStar(globOffset));
const char *mimeType = cacheFile->getCharStar(mimeTypeOffset); const QLatin1StringView mimeType(cacheFile->getCharStar(mimeTypeOffset));
if (m_overriddenMimeTypes.contains(QLatin1String(mimeType))) if (m_overriddenMimeTypes.contains(QLatin1String(mimeType)))
continue; continue;
//qDebug() << pattern << mimeType << weight << caseSensitive; //qDebug() << pattern << mimeType << weight << caseSensitive;
@@ -258,7 +266,7 @@ int MimeBinaryProvider::matchGlobList(MimeGlobMatchResult &result, CacheFile *ca
MimeGlobPattern glob(pattern, QString() /*unused*/, weight, qtCaseSensitive); MimeGlobPattern glob(pattern, QString() /*unused*/, weight, qtCaseSensitive);
if (glob.matchFileName(fileName)) { if (glob.matchFileName(fileName)) {
result.addMatch(QLatin1StringView(mimeType), weight, pattern); result.addMatch(mimeType, weight, pattern);
++numMatches; ++numMatches;
} }
} }
@@ -304,7 +312,7 @@ bool MimeBinaryProvider::matchSuffixTree(MimeGlobMatchResult &result,
if (mch != 0) if (mch != 0)
break; break;
const int mimeTypeOffset = cacheFile->getUint32(childOff + 4); const int mimeTypeOffset = cacheFile->getUint32(childOff + 4);
const char *mimeType = cacheFile->getCharStar(mimeTypeOffset); const QLatin1StringView mimeType(cacheFile->getCharStar(mimeTypeOffset));
if (isMimeTypeGlobsExcluded(mimeType)) if (isMimeTypeGlobsExcluded(mimeType))
continue; continue;
if (m_overriddenMimeTypes.contains(QLatin1String(mimeType))) if (m_overriddenMimeTypes.contains(QLatin1String(mimeType)))
@@ -313,8 +321,8 @@ bool MimeBinaryProvider::matchSuffixTree(MimeGlobMatchResult &result,
const int weight = flagsAndWeight & 0xff; const int weight = flagsAndWeight & 0xff;
const bool caseSensitive = flagsAndWeight & 0x100; const bool caseSensitive = flagsAndWeight & 0x100;
if (caseSensitiveCheck || !caseSensitive) { if (caseSensitiveCheck || !caseSensitive) {
result.addMatch(QLatin1StringView(mimeType), weight, result.addMatch(mimeType, weight,
u'*' + QStringView{fileName}.mid(charPos + 1), u'*' + QStringView{ fileName }.mid(charPos + 1),
fileName.size() - charPos - 2); fileName.size() - charPos - 2);
success = true; success = true;
} }
@@ -733,7 +741,10 @@ bool MimeXMLProvider::knowsMimeType(const QString &name)
void MimeXMLProvider::addFileNameMatches(const QString &fileName, MimeGlobMatchResult &result) void MimeXMLProvider::addFileNameMatches(const QString &fileName, MimeGlobMatchResult &result)
{ {
m_mimeTypeGlobs.matchingGlobs(fileName, result, m_overriddenMimeTypes); auto filterFunc = [this](const QString &name) {
return !isMimeTypeGlobsExcluded(name) && !m_overriddenMimeTypes.contains(name);
};
m_mimeTypeGlobs.matchingGlobs(fileName, result, filterFunc);
} }
void MimeXMLProvider::findByMagic(const QByteArray &data, int *accuracyPtr, QString *candidate) void MimeXMLProvider::findByMagic(const QByteArray &data, int *accuracyPtr, QString *candidate)
@@ -770,7 +781,6 @@ void MimeXMLProvider::ensureLoaded()
m_parents.clear(); m_parents.clear();
m_mimeTypeGlobs.clear(); m_mimeTypeGlobs.clear();
m_magicMatchers.clear(); m_magicMatchers.clear();
m_mimeTypesWithDeletedGlobs.clear();
//qDebug() << "Loading" << m_allFiles; //qDebug() << "Loading" << m_allFiles;
@@ -846,29 +856,9 @@ void MimeXMLProvider::addGlobPattern(const MimeGlobPattern &glob)
void MimeXMLProvider::addMimeType(const MimeTypeXMLData &mt) void MimeXMLProvider::addMimeType(const MimeTypeXMLData &mt)
{ {
if (mt.hasGlobDeleteAll)
appendIfNew(m_mimeTypesWithDeletedGlobs, mt.name);
m_nameMimeTypeMap.insert(mt.name, mt); m_nameMimeTypeMap.insert(mt.name, mt);
} }
/*
\a toExclude is a list of mime type names that should have the the glob patterns
associated with them cleared (because there are mime types with the same names
in a higher precedence Provider that have glob-deleteall tags).
This method is called from QMimeDatabasePrivate::loadProviders() to exclude mime
type glob patterns in lower precedence Providers.
*/
void MimeXMLProvider::excludeMimeTypeGlobs(const QStringList &toExclude)
{
for (const auto &mt : toExclude) {
auto it = m_nameMimeTypeMap.find(mt);
if (it != m_nameMimeTypeMap.end())
it->globPatterns.clear();
m_mimeTypeGlobs.removeMimeType(mt);
}
}
void MimeXMLProvider::addParents(const QString &mime, QStringList &result) void MimeXMLProvider::addParents(const QString &mime, QStringList &result)
{ {
for (const QString &parent : m_parents.value(mime)) { for (const QString &parent : m_parents.value(mime)) {

View File

@@ -26,6 +26,7 @@ namespace Utils {
class MimeMagicRuleMatcher; class MimeMagicRuleMatcher;
class MimeTypeXMLData; class MimeTypeXMLData;
class MimeProviderBase;
class MimeProviderBase class MimeProviderBase
{ {
@@ -50,10 +51,13 @@ public:
virtual QString icon(const QString &name) = 0; virtual QString icon(const QString &name) = 0;
virtual QString genericIcon(const QString &name) = 0; virtual QString genericIcon(const QString &name) = 0;
virtual void ensureLoaded() { } virtual void ensureLoaded() { }
virtual void excludeMimeTypeGlobs(const QStringList &) { }
QString directory() const { return m_directory; } QString directory() const { return m_directory; }
MimeProviderBase *overrideProvider() const;
void setOverrideProvider(MimeProviderBase *provider);
bool isMimeTypeGlobsExcluded(const QString &name) const;
// added for Qt Creator // added for Qt Creator
virtual bool hasMimeTypeForName(const QString &name) = 0; virtual bool hasMimeTypeForName(const QString &name) = 0;
virtual QStringList allMimeTypeNames() = 0; virtual QStringList allMimeTypeNames() = 0;
@@ -66,31 +70,7 @@ public:
MimeDatabasePrivate *m_db; MimeDatabasePrivate *m_db;
QString m_directory; QString m_directory;
/* MimeProviderBase *m_overrideProvider = nullptr; // more "local" than this one
MimeTypes with "glob-deleteall" tags are handled differently by each provider
sub-class:
- QMimeBinaryProvider parses glob-deleteall tags lazily, i.e. only when hasGlobDeleteAll()
is called, and clears the glob patterns associated with mimetypes that have this tag
- QMimeXMLProvider parses glob-deleteall from the start, i.e. when a XML file is
parsed with QMimeTypeParser
The two lists below are used to let both provider types (XML and Binary) communicate
about mimetypes with glob-deleteall.
*/
/*
List of mimetypes in _this_ Provider that have a "glob-deleteall" tag,
glob patterns for those mimetypes should be ignored in all _other_ lower
precedence Providers.
*/
QStringList m_mimeTypesWithDeletedGlobs;
/*
List of mimetypes with glob patterns that are "overwritten" in _this_ Provider,
by a "glob-deleteall" tag in a mimetype definition in a _higher precedence_
Provider. With QMimeBinaryProvider, we can't change the data in the binary mmap'ed
file, hence the need for this list.
*/
QStringList m_mimeTypesWithExcludedGlobs;
// for Qt Creator // for Qt Creator
QSet<QString> m_overriddenMimeTypes; QSet<QString> m_overriddenMimeTypes;
@@ -120,7 +100,6 @@ public:
QString icon(const QString &name) override; QString icon(const QString &name) override;
QString genericIcon(const QString &name) override; QString genericIcon(const QString &name) override;
void ensureLoaded() override; void ensureLoaded() override;
void excludeMimeTypeGlobs(const QStringList &toExclude) override;
// added for Qt Creator // added for Qt Creator
bool hasMimeTypeForName(const QString &name) override; bool hasMimeTypeForName(const QString &name) override;
@@ -142,7 +121,6 @@ private:
const QString &fileName, const QString &fileName,
qsizetype charPos, qsizetype charPos,
bool caseSensitiveCheck); bool caseSensitiveCheck);
bool isMimeTypeGlobsExcluded(const char *name);
bool matchMagicRule(CacheFile *cacheFile, int numMatchlets, int firstOffset, bool matchMagicRule(CacheFile *cacheFile, int numMatchlets, int firstOffset,
const QByteArray &data); const QByteArray &data);
QLatin1StringView iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime); QLatin1StringView iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime);
@@ -203,7 +181,6 @@ public:
// Called by the mimetype xml parser // Called by the mimetype xml parser
void addMimeType(const MimeTypeXMLData &mt); void addMimeType(const MimeTypeXMLData &mt);
void excludeMimeTypeGlobs(const QStringList &toExclude) override;
void addGlobPattern(const MimeGlobPattern &glob); void addGlobPattern(const MimeGlobPattern &glob);
void addParent(const QString &child, const QString &parent); void addParent(const QString &child, const QString &parent);
void addAlias(const QString &alias, const QString &name); void addAlias(const QString &alias, const QString &name);