В альтовых репозиториях заведомо есть лишние зависимости (в основном видов Conflicts: да Obsoletes:, но могут быть и Provides:), которые увеличивают объём графа для разбора apt'ом. Хорошо бы до них добраться и потихоньку начать собирать список на вычистку -- например, в branding-* такие зависимости генерируются десятками (в т.ч. на design-*, которые не используются со времён p6), но точно бывают не только там. При этом к Provides: стоит относится внимательней -- в идеале бы простроить базу если не по архиву сизифа, то как минимум по всем (в т.ч. старым) стабильным веткам с тем, чтобы была возможность различить Provides:, появившийся при переименовании альтового пакета (или для другого альтового пакета, который мог дожить или не дожить до нынешних пор), и Provides:, вписанный для совместимости с чем-то вне альтовых репозиториев (таковы, например, пакеты *-preinstall). Польза от расчистки зависимостей в плане сокращения времени работы apt ожидается весьма умеренная, но может оказаться даже измеримой (а сборка чрутов у нас задача очень частая на одной только сборочнице); `apt-cache pkgnames` сейчас по p10 насчитывает порядка 260 тыс. строк, из них более двухсот тысяч -- виртуальные Provides: (со скобками). Количество Conflicts:/Obsoletes: сходу оценить не могу, но не удивлюсь, если окажется в районе тысяч/десятков тысяч (возможно, такие оценки делал msp@ в рамках работ по deepsolver).
То есть хочется запрос, который для определенного репозитория выводит все зависимости (Requires/Provides/Conflicts/Obsoletes), которые не сопоставляются для заданного репозитория? Например, A замещает (Obsoletes) B, но B при этом на текущий момент в репозитории никем не предоставляется (Provides) => такая B - зависимость для зачистки. Я правильно понимаю? Насчёт Provides: я так понимаю, необходимо определить те зависимости (Provides), которые когда-то были кому-то нужны, но эти "кто-то" уже отсутствуют в заданном репозитории? А что если такие провайды используются где-нибудь при сборке образов (в таком случае можно случайно (или не совсем) сломать сборку образа)?
Прошу прощения, был в отпуске, сейчас вспомнил. (Ответ для Anton Zhukharev на комментарий #1) > То есть хочется запрос, который для определенного репозитория выводит > все зависимости (Requires/Provides/Conflicts/Obsoletes), которые не > сопоставляются для заданного репозитория? Лучше бы не для данного, а со временнОй отсечкой (скажем, для сизифа это может быть пять лет или два бранча -- если что-то с конфликтом на него было в p8 и пропало в p9, к p11 можно считать такое нерелевантным, т.к. обновление с p8 должно проходить через _два_ бранча, где такого уже нет). > Например, A замещает (Obsoletes) B, но B при этом на текущий момент > в репозитории никем не предоставляется (Provides) => такая B - зависимость > для зачистки. Я правильно понимаю? По сути да -- с учётом того, что пакет B также предоставляет самого себя (B). > Насчёт Provides: я так понимаю, необходимо определить те зависимости > (Provides), которые когда-то были кому-то нужны, но эти "кто-то" уже > отсутствуют в заданном репозитории? А что если такие провайды используются > где-нибудь при сборке образов (в таком случае можно случайно (или не совсем) > сломать сборку образа)? По части Provides: всё в принципе сложней, поскольку они бывают и для внешних потребителей (например, совместимости с чем-нить для редхата или сузи), и для применения в дистрибутивных профилях. Я бы тут начинал именно с Conflicts: и Obsoletes:, а к более нетехнически сложным Provides: переходил уже после решения задачи попроще (которая с учётом желательности именно временной отсечки сама по себе не особо тривиальна). Полуавтоматизировать тут разве что кластеризацией результатов получится, поскольку нужные ручные обычно точечные, но не массовые (хотя и такое исключить нельзя). Можно забрать условный http://ftp.altlinux.org/pub/distributions/archive/sisyphus/task/archive/_207/212240/daily/ той самой пятилетней давности и часть достоверных сведений вида "было, но пропало" получить из него (это не закроет ещё более древних "потеряшек", которых не было уже и тогда, но конфликты на которые стоят до сих пор -- например, design-graphics-education). В принципе можно и все (или ежемесячные) daily/{x86_64,noarch}/base/pkglist.classic.xz позабирать да поразбирать, но мне кажется, что для такой задачки не в математическом, а в инженерном варианте решения это слишком. И на самом деле может иметь смысл не городить итеративный огород, а предпринять единоразовый набег на конкретно взятый сизиф (в идеале до p11) и в дальнейшем подвязав к удалению пакета проверку на наличие Obsoletes:/Conflicts: на порождаемые из него бинарные подпакеты с уведомлением майнтейнеров тех пакетов, где эти O:/C: станут мусором (лишь бы эти уведомления не оказались спамом в плане частоты/многочисленности).
Не могу сказать, что мне полностью понятна цель и смысл расчистки "висячих/мёртвых" зависимостей пакетов в репозитории. В БД мы храним метаинформацию извлекаемую из пакетов репозиториев, т.е. всё что есть в хэдереах .rpm. У нас уже реализованы механизмы поиска и разрешения зависимостей пакетов для аналитических запросов и отображения этой информации на packages.altlinux.org. При реализации этого функционала используется непосредственно часть функций из librpm (в части сравнения версий при разрешении зависимостей) и в определённых местах мы вынуждены были повторить поведение apt для получения результатов аналогичных таковым в работе с пакетами на реальной системе. Тут главный момент, что apt при разрешении зависимостей помимо метаинформации из хэдеров rpm-пакетов использует ещё и свои индексные файлы, в частности для разрешения файловых зависимостей. По моему скромному мнению, решать озвученную задачу (если я правильно понял, что собственно планируется сделать) нужно именно с использованием непосредственно функционала apt и rpm на каком то конкретном консистентном состоянии репозитория. По поводу удаления Conflicts и Obsoletes - не случится ли так, что после "расчистки" это доставит массу радости пользователям, которые давно не обновлялись либо по какой-то причине сохраняют установленными в системе пакеты, которые уже удалены из текущего состояния репозитория? Относительно удаления Provides, которые никто не хочет - а что будет, когда в репозиторий попадут новые пакеты или новые версии пакетов, которые зависят от "расчищенных" ранее зависимостей? Ну и к цифрам: какое количество зависимостей из условны 250-300 тысяч таким образом удастся убрать? Есть какие то оценки результата, хотя бы примерные?
Created attachment 14340 [details] pkglist-query.cc им. glebfm@ Спасибо за вопросы! Постараюсь кратенько зафиксировать частичную выжимку сегодняшнего общения с практикантами по теме. Из замеченных интересных особых случаев -- zoneminder: >3000 перловых Provides:, причём похоже на то, что нужны они только ему самому (похоже, надо AutoProv: no или как минимум noperl добавить). (Ответ для Danil Shein на комментарий #3) > Не могу сказать, что мне полностью понятна цель и смысл расчистки > "висячих/мёртвых" зависимостей пакетов в репозитории. Ускорение работы apt в первую очередь (в т.ч. для hasher => сборочницы, множитель -- _минимум_ сотни тысяч запусков; тут и секунда уже выгода). > В БД мы храним метаинформацию извлекаемую из пакетов репозиториев, > т.е. всё что есть в хэдереах .rpm. Про pkglist.classic и pkglist-query в курсе, кстати? (прилагаю) Или забираете инкрементально из заданий? Это сводка заголовков пакетов из конкретного состояния репозитория. > При реализации этого функционала используется непосредственно часть функций > из librpm (в части сравнения версий при разрешении зависимостей) и в > определённых местах мы вынуждены были повторить поведение apt для получения > результатов аналогичных таковым в работе с пакетами на реальной системе. Метаданные каждый раз поднимаете из файликов? Посмотрите apt-pipe, когда-то Большаков писал, помнится -- его можно инициализировать при переходе на конкретное задание, дальше гонять команды по уже горячему состоянию. > По моему скромному мнению, решать озвученную задачу (если я правильно понял, > что собственно планируется сделать) нужно именно с использованием > непосредственно функционала apt и rpm на каком то конкретном консистентном > состоянии репозитория. В целом да; об этом тоже сегодня поговорили с ребятами. > По поводу удаления Conflicts и Obsoletes - не случится ли так, что после > "расчистки" это доставит массу радости пользователям, которые давно не > обновлялись либо по какой-то причине сохраняют установленными в системе > пакеты, которые уже удалены из текущего состояния репозитория? Вот потому и уточнил в comment 2 насчёт отсечки в пару бранчей; цитирую выработанную сегодня формулировку: --- по тому, что точно было, но уже отсутствует: возьмите http://ftp.altlinux.org/pub/distributions/ALTLinux/{4.0,4.1,p{5,6,7,8}}/branch/{noarch,x86_64}/base/pkglist.classic.xz и дёрните из них %name (возможно, и [%{providename}], но это уже по вкусу) — вычтя из этого сизифные [%{name}] и соотв. провайдесы, получите список того, что ГАРАНТИРОВАННО было И исчезло. соответственно то, что C: или O: имя из такого списка — ГАРАНТИРОВАННО* "наш клиент" --- То, чего _никогда_ не было -- скорее всего, или ошибка в спеке, или Provides: для внешнего пакета, которого в сизифе никогда не было и обычно никогда не будет (для _строгого_ ответа на этот вопрос надо разобрать метаданные всех заданий плюс все известные состояния репозиториев до транзакционной сборочницы, но математическая точность нам и не требуется покрмере на данном этапе). Что до пользователей, которые давно не обновлялись (скажем, до сих пор на p7): так им сперва понадобится обновиться до промежуточных стабильных репозиториев, где эти C:/O: в наличии => вынос устаревших пакетов произойдёт на этой стадии, потому и предложен зазор в _два_ бранча (он останется неплохим даже после свежеответвлённого p11). > Относительно удаления Provides, которые никто не хочет - а что будет, когда > в репозиторий попадут новые пакеты или новые версии пакетов, которые зависят > от "расчищенных" ранее зависимостей? И как они попадут, если при этом будет попытка сгенерировать unmet? Понятно, что количество "глупых" циклов "убрали-вернули" надо свести к минимуму, но у меня сходу даже иллюстрации рабочей к Вашему примеру подобрать не вышло. > Ну и к цифрам: какое количество зависимостей из условны 250-300 тысяч таким > образом удастся убрать? Есть какие то оценки результата, хотя бы примерные? Порядка 1% даёт один zoneminder... помножьте на кол-во собираемых заданий (и ещё учтите, что в каждом из них сейчас минимум три запуска apt для хотя бы одного собираемого, а не удаляемого, пакета: hsh --query-repackage, собственно hsh и installcheck; может, и больше, но эти сходу вспомнил). Думаю, несколько тысяч. В плохом случае -- несколько десятков тысяч (это если майнтейнеры расслабились и генерят ненужные provides оптом, есть одна подозрительная на сей счёт подсистема).
С zoneminder и его provides всё в порядке. Возможно это надо вынести в отдельные перловые подпакеты, но это не вопрос этой задачи.
и ответ Шигорину Мише на вопрос как кто и что грузит - там есть информация, про pkglist мы естественно в курсе: https://git.altlinux.org/people/dshein/public/?p=altrepodb.git
В целом задача выглядит странно я бы точно ей не советовал заниматься на этапе JOIN. Думаю что мы не будем делать такой функционал, т.к. всё это на усмотрение ментейнера и зависит от массы факторов, в том числе времени жизни такой "лишней" зависимости.