From 910471489aae496ffa8820884bf73322baa208d3 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Tue, 27 Aug 2024 14:43:35 +0200 Subject: [PATCH] Update mime database from Qt qtbase/9547ef58c707a11d5affcbcfa553f3aca5334087 QMimeDatabase: handle glob-deleteall tags Change-Id: I8aebb6de340a51c978730b6ca0dba2ba9ce3460f Reviewed-by: Jarek Kobus --- src/libs/utils/mimetypes2/mimedatabase.cpp | 13 ++++++ src/libs/utils/mimetypes2/mimeprovider.cpp | 46 +++++++++++++++++++- src/libs/utils/mimetypes2/mimeprovider_p.h | 33 ++++++++++++++ src/libs/utils/mimetypes2/mimetype_p.h | 1 + src/libs/utils/mimetypes2/mimetypeparser.cpp | 1 + 5 files changed, 93 insertions(+), 1 deletion(-) diff --git a/src/libs/utils/mimetypes2/mimedatabase.cpp b/src/libs/utils/mimetypes2/mimedatabase.cpp index b68f982a09b..ebba21d63a2 100644 --- a/src/libs/utils/mimetypes2/mimedatabase.cpp +++ b/src/libs/utils/mimetypes2/mimedatabase.cpp @@ -194,6 +194,19 @@ void MimeDatabasePrivate::loadProviders() } } + // Handle mimetypes with glob-deleteall tags (from XML providers) + auto it = m_providers.begin(); + const auto end = m_providers.end(); + for (;it != end; ++it) { + const QStringList &list = (*it)->m_mimeTypesWithDeletedGlobs; + 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); } diff --git a/src/libs/utils/mimetypes2/mimeprovider.cpp b/src/libs/utils/mimetypes2/mimeprovider.cpp index e2ab9ffebda..823bbfce332 100644 --- a/src/libs/utils/mimetypes2/mimeprovider.cpp +++ b/src/libs/utils/mimetypes2/mimeprovider.cpp @@ -51,6 +51,12 @@ using namespace Qt::StringLiterals; namespace Utils { +static inline void appendIfNew(QStringList &list, const QString &str) +{ + if (!list.contains(str)) + list.push_back(str); +} + MimeProviderBase::MimeProviderBase(MimeDatabasePrivate *db, const QString &directory) : m_db(db), m_directory(directory) { @@ -241,6 +247,17 @@ void MimeBinaryProvider::addFileNameMatches(const QString &fileName, MimeGlobMat matchGlobList(result, m_cacheFile, m_cacheFile->getUint32(PosGlobListOffset), 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); +} + void MimeBinaryProvider::matchGlobList(MimeGlobMatchResult &result, CacheFile *cacheFile, int off, @@ -261,8 +278,10 @@ void MimeBinaryProvider::matchGlobList(MimeGlobMatchResult &result, if (m_overriddenMimeTypes.contains(QLatin1String(mimeType))) continue; //qDebug() << pattern << mimeType << weight << caseSensitive; - MimeGlobPattern glob(pattern, QString() /*unused*/, weight, qtCaseSensitive); + if (isMimeTypeGlobsExcluded(mimeType)) + continue; + MimeGlobPattern glob(pattern, QString() /*unused*/, weight, qtCaseSensitive); if (glob.matchFileName(fileName)) result.addMatch(QLatin1StringView(mimeType), weight, pattern); } @@ -308,6 +327,8 @@ bool MimeBinaryProvider::matchSuffixTree(MimeGlobMatchResult &result, break; const int mimeTypeOffset = cacheFile->getUint32(childOff + 4); const char *mimeType = cacheFile->getCharStar(mimeTypeOffset); + if (isMimeTypeGlobsExcluded(mimeType)) + continue; if (m_overriddenMimeTypes.contains(QLatin1String(mimeType))) continue; const int flagsAndWeight = cacheFile->getUint32(childOff + 8); @@ -760,6 +781,7 @@ void MimeXMLProvider::ensureLoaded() m_parents.clear(); m_mimeTypeGlobs.clear(); m_magicMatchers.clear(); + m_mimeTypesWithDeletedGlobs.clear(); //qDebug() << "Loading" << m_allFiles; @@ -811,9 +833,31 @@ void MimeXMLProvider::addGlobPattern(const MimeGlobPattern &glob) void MimeXMLProvider::addMimeType(const MimeType &mt) { Q_ASSERT(!mt.d.data()->fromCache); + + QString name = mt.name(); + if (mt.d->hasGlobDeleteAll) + appendIfNew(m_mimeTypesWithDeletedGlobs, name); 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->d->globPatterns.clear(); + m_mimeTypeGlobs.removeMimeType(mt); + } +} + void MimeXMLProvider::addParents(const QString &mime, QStringList &result) { for (const QString &parent : m_parents.value(mime)) { diff --git a/src/libs/utils/mimetypes2/mimeprovider_p.h b/src/libs/utils/mimetypes2/mimeprovider_p.h index 03d6a2c91c2..87a28f232a5 100644 --- a/src/libs/utils/mimetypes2/mimeprovider_p.h +++ b/src/libs/utils/mimetypes2/mimeprovider_p.h @@ -45,6 +45,7 @@ public: virtual void loadIcon(MimeTypePrivate &) {} virtual void loadGenericIcon(MimeTypePrivate &) {} virtual void ensureLoaded() {} + virtual void excludeMimeTypeGlobs(const QStringList &) {} QString directory() const { return m_directory; } @@ -59,6 +60,34 @@ public: MimeDatabasePrivate *m_db; QString m_directory; + + /* + MimeTypes with "glob-deleteall" tags are handled differently by each provider + sub-class: + - QMimeBinaryProvider parses glob-deleteall tags lazily, i.e. only when loadMimeTypePrivate() + is called, and clears the glob patterns associated with mimetypes that have this tag + - QMimeXMLProvider parses glob-deleteall from the 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 QSet m_overriddenMimeTypes; }; @@ -84,6 +113,7 @@ public: void loadIcon(MimeTypePrivate &) override; void loadGenericIcon(MimeTypePrivate &) override; void ensureLoaded() override; + void excludeMimeTypeGlobs(const QStringList &toExclude) override; // added for Qt Creator bool hasMimeTypeForName(const QString &name) override; @@ -108,6 +138,7 @@ private: qsizetype charPos, bool caseSensitiveCheck); bool matchMagicRule(CacheFile *cacheFile, int numMatchlets, int firstOffset, const QByteArray &data); + bool isMimeTypeGlobsExcluded(const char *name); QLatin1StringView iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime); void loadMimeTypeList(); bool checkCacheChanged(); @@ -118,6 +149,7 @@ private: bool m_mimetypeListLoaded; struct MimeTypeExtra { + // Both retrieved on demand in loadMimeTypePrivate QHash localeComments; QStringList globPatterns; }; @@ -157,6 +189,7 @@ public: // Called by the mimetype xml parser void addMimeType(const MimeType &mt); + void excludeMimeTypeGlobs(const QStringList &toExclude) override; void addGlobPattern(const MimeGlobPattern &glob); void addParent(const QString &child, const QString &parent); void addAlias(const QString &alias, const QString &name); diff --git a/src/libs/utils/mimetypes2/mimetype_p.h b/src/libs/utils/mimetypes2/mimetype_p.h index 8ad7fbc604f..3b8d08df002 100644 --- a/src/libs/utils/mimetypes2/mimetype_p.h +++ b/src/libs/utils/mimetypes2/mimetype_p.h @@ -35,6 +35,7 @@ public: bool loaded; // QSharedData leaves a 4 byte gap, so don't put 8 byte members first bool fromCache; // true if this comes from the binary provider + bool hasGlobDeleteAll = false; // true if the mimetype has a glob-deleteall tag QString name; LocaleHash localeComments; QString genericIconName; diff --git a/src/libs/utils/mimetypes2/mimetypeparser.cpp b/src/libs/utils/mimetypes2/mimetypeparser.cpp index 12144514579..43af53e9ff7 100644 --- a/src/libs/utils/mimetypes2/mimetypeparser.cpp +++ b/src/libs/utils/mimetypes2/mimetypeparser.cpp @@ -213,6 +213,7 @@ bool MimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString break; case ParseGlobDeleteAll: data.globPatterns.clear(); + data.hasGlobDeleteAll = true; break; case ParseSubClass: { const QString inheritsFrom = atts.value(QLatin1StringView(mimeTypeAttributeC)).toString();