Hatred's Log Place

DON'T PANIC!

Jul 12, 2019 - 4 minute read - programming linux

QtC: ошибка при попытке сделать коммит в Git репозиторий

Буквально вчера столкнулся с таким вот поведением QtC:

С учётом того, что я собираю QtC из исходников master-ветки репозитория, первая мысль была: что-то поломали, нужно по быстрому разобраться и откатить. Но всё оказалось чуточку интереснее. Кому интересно - добро пожаловать под кат.

На видео я обратил внимание на диалог ошибки, в котором видно, что пытается открыться временный файл, но не получается определить редактор для него (это уже мне поверьте на слово) и что тип файла… пустой!

Первая мысль была: поломали базу MIME.

Да только код, который работает с ней, не менялся уже года два.

И вот тут, если бы были скачаны исходники стабильных версий QtC и собраны на системе, то проблема бы тоже проявилась.

Поэтому следующей мыслью было: Manjaro, недавно обновлялось Qt, а судя по коду - путь к файлу MIME базы уже менялся. Вдруг что и сейчас произошло.

Посмотрел исходники qt5-base и практически ничего не поменялось, кроме двух файлов, относительно недавно - 4 месяца назад (на момент написания блогозаметки). Хм… Оказывается, в 5.13 они ввели опцию, которая позволяет отключить встроенную базу данных MIME типов:

dist/changes-5.13.0
 - QMimeDatabase:
   * Added configure option -no-mimetype-database that tells Qt not to
     bundle its own copy of the XDG MIME database. If this option is
     passed, QMimeDatabase will only work if there's a system copy in
     $XDG_DATA_DIRS/mime. This option is useful for Linux distributions
     that ensure the data is always present.

Судя по тому, что имя и расположение самой базы не поменялось, а найти её не получается, значит маинтейнеры ArchLinux/Manjaro задействовали эту опцию. Действительно, их понять можно - база и так предоставляется пакетом shared-mime-info и раполагается по пути /usr/share/mime/packages/freedesktop.org.xml. Как минимум это правильно - иметь возможность обновить базу, без необходимости переставлять Qt, это очень хорошо для всяких домашних систем, особенно тех, которые обновляются не регулярно, типа Debian.

Погодите, а собственно… Какого чёрта! Выходит, что хотя код работы с MIME базой в QtC не менялся, косякопоры - они. Обновление системы и действия маинтейнеров ArchLinux просто вскрыли проблему.

И правда, изучая код mimeprovider.cpp поражаешься количеству закомментированного кода и в функции MimeXMLProvider::ensureLoaded() быстро находишь суть проблемы: вариант для поиска подобающей базы, просто выключен и оставлен на потом.

Маинтейнеры ArchLinux сделали патч для релизной версии QtC, поставляемой в дистрибутиве, с небольшими адаптациями, он ложится на master-бранч:

diff --git a/src/libs/utils/mimetypes/mimeprovider.cpp b/src/libs/utils/mimetypes/mimeprovider.cpp
index 46d3eb71bd..ce94215d9f 100644
--- a/src/libs/utils/mimetypes/mimeprovider.cpp
+++ b/src/libs/utils/mimetypes/mimeprovider.cpp
@@ -784,28 +784,25 @@ void MimeXMLProvider::ensureLoaded()
 {
     if (!m_loaded /*|| shouldCheck()*/) {
         m_loaded = true;
-//        bool fdoXmlFound = false;
-        QStringList allFiles;
-
-//        const QStringList packageDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/packages"), QStandardPaths::LocateDirectory);
-//        //qDebug() << "packageDirs=" << packageDirs;
-//        for (const QString &packageDir : packageDirs) {
-//            QDir dir(packageDir);
-//            const QStringList files = dir.entryList(QDir::Files | QDir::NoDotAndDotDot);
-//            //qDebug() << static_cast<const void *>(this) << packageDir << files;
-//            if (!fdoXmlFound)
-//                fdoXmlFound = files.contains(QLatin1String("freedesktop.org.xml"));
-//            QStringList::const_iterator endIt(files.constEnd());
-//            for (QStringList::const_iterator it(files.constBegin()); it != endIt; ++it) {
-//                allFiles.append(packageDir + QLatin1Char('/') + *it);
-//            }
-//        }
-
-//        if (!fdoXmlFound) {
-//            // We could instead install the file as part of installing Qt?
-              const char freedesktopOrgXml[] = ":/qt-project.org/qmime/packages/freedesktop.org.xml";
-            allFiles.prepend(QLatin1String(freedesktopOrgXml));
-//        }
+        QStringList allFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation,
+                                                         QStringLiteral("mime/packages/freedesktop.org.xml"),
+                                                         QStandardPaths::LocateFile);
+
+        if (allFiles.isEmpty()) {
+            // System freedsktop.org.xml file not found, try to use the one in QtCore.
+            // This is private API and has changed in the past:
+            // - Qt 5.11 added "package" subdir in 7a5644d6481a3c1a7416772998ca4e60c977bfbd
+            // - Qt 5.13 added an option to not bundle it at all
+            const QString fdoXml5_11 = QStringLiteral(":/qt-project.org/qmime/packages/freedesktop.org.xml");
+            const QString fdoXmlPre5_11 = QStringLiteral(":/qt-project.org/qmime/freedesktop.org.xml");
+            if (QFile::exists(fdoXml5_11))
+                allFiles << fdoXml5_11;
+            else if (QFile::exists(fdoXmlPre5_11))
+                allFiles << fdoXmlPre5_11;
+            else
+                qFatal("Utils::MimeXMLProvider: could not find the system freedesktop.org.xml file "
+                       "and QtCore does not have an accessible copy.");
+        }
 
         m_nameMimeTypeMap.clear();
         m_aliases.clear();

Кстати, закомменченый код (как и корни проблемы) тянутся с версии 3.4.0-beta1 к коммита 4f5f5d75b45ec9db97377485af08d113ec8197f4 от 2015-02-18:

    MimeDatabase: Never use installed mime data.
    
    It gets in the way, e.g. "No plugin can open project type "application/
    x-kicad-project"" when trying to open .pro files.
    
    Change-Id: I5d8dcb52b65b1e617fe0c6dfcdc94e2cf8fc5f5d
    Reviewed-by: Tim Sander <tim@krieglstein.org>
    Reviewed-by: Eike Ziller <eike.ziller@theqtcompany.com>

Новое ревью: https://codereview.qt-project.org/c/qt-creator/qt-creator/+/267723, посмотрим, что предложат.