Напомню, что filetriggers -- это скрипты /usr/lib/rpm/*.filetrigger, которые запускаются после успешного завершения транзакции. Они получают на вход список файлов, затронутых транзакцией (построчно на stdin), то есть как бы вывод 'rpm -ql' от вновь установленных, обновлённых и удалённых пакетов. Механизм специально сделан максимально упрощенным (дополнительную информацию можно получить естественным образом -- например, чтобы определить, был ли файл добавлен/обновлен или же удалён, можно использовать простой тест типа [ -f "$f"] ). * * * Посмотрим, какой расклад мы имеем с кешем gtk2. Библиотека libgtk+2 использует кеш по умолчанию, если он существует (это ускоряет запуск приложений, а также экономит память, т.к. иконки расшариваются между приложениями). Есть стандартная программа обновления кеша gtk-update-icon-cache. Кроме библиотеки libgtk+2 этот кеш больше никто не использует. Следуя принципу правильной группировки файлов в пакетах, можно заключить, что библиотеку libgtk+2, программу gtk-update-icon-cache и триггер /usr/lib/rpm/gtk-icon-cache.filetrigger следует запаковать в один и тот же пакет (libgtk+2). Принцип правильной группировки файлов между пакетами состоит в том, что совместно используемые файлы нужно паковать в один и тот же пакет. Действительно, программа gtk-update-icon-cache сама по себе, по отдельности, имеет мало смысла (т.к. результат её работы представляет интерес только для библиотеки libgtk+2). А триггер /usr/lib/rpm/gtk-icon-cache.filetrigger, в свою очередь, сможет сделать что-либо только при наличии программы gtk-update-icon-cache. Короче, эти две программы просто "обслуживают" библиотеку libgtk+2. С другой стороны, этот принцип не является настолько однозначным, чтобы можно было применять его механически. Нужно думать. Ведь библиотека libgtk+2, хотя и использует кеш иконок по умолчанию, всё же обходится без него, если кеш отсутствует. Так что кто-то может возразить, что мы кладём в libgtk+2 лишние файлы, без которых, строго говоря, можно обойтись. На что мы можем парировать позитивной интерпретацией: кеш иконок работает "из коробки" (а в противном случае возможны проблемы с инвалидацией кеша, то есть битые иконки в приложениях). * * * Хотя принцип правильной группировки файлов не всегда можно толковать однозначно, на практике он имеет большое значение. Приведу пример пакета, в котором принцип правильной группировки файлов между пакетами явно нарушен -- это пакет libtcl. Tcl может использоваться как embedded language, т.е. приложения пишут обёртку для libtcl и дальше Tcl как язык может использоваться внутри приложения. Такие приложения получают зависимость на libtcl soname. Напишем простейшую программу, которая встраивает libtcl. $ cat test.c #include int main(int argc, char **argv) { Tcl_Main(argc,argv,Tcl_Init); return 0; } $ gcc -Wall test.c -o test -ltcl $ Теперь посмотрим, будет ли она работать в среде, где установлена одна только библиотека libtcl. $ hsh --init $ hsh-install ... $ hsh-install libtcl <13>Sep 9 23:05:07 rpmi: libtcl-8.5.4-alt1 installed $ cp -pv ./test ~tmp/build/chroot/.in/ && hsh-run ./test `./test' -> `/tmp/.private/at/build/chroot/.in/test' application-specific initialization failed: Can't find a usable init.tcl in the following directories: /usr/share/tcl/tcl8.5 /lib/tcl8.5 /lib/tcl8.5 /library /library /tcl8.5.4/library /tcl8.5.4/library This probably means that Tcl wasn't installed properly. $ Увы. Приложения, слинковавшиеся с libtcl, громко обломятся (с диагностикой "Tcl wasn't installed properly"!). Если же установить пакет tcl, то уже всё работает. $ cp -pv ./test ~tmp/build/chroot/.in/ && hsh-run ./test && echo $? `./test' -> `/tmp/.private/at/build/chroot/.in/test' 0 $ Библиотека libtcl имеет "непрозрачную" зависимость на init.tcl, этот файл загружается при инициализации библиотеки. Без init.tcl приложения, слинованные c libtcl, обламываются; а файл init.tcl имеет смысл только в связи с наличием конкретной библиотеки libtcl. Это достаточное основание для того, чтобы применить принцип правильной группировки файлов между пакетами -- файлы libtcl*so* и init.tcl должны быть запакованы в один и тот же пакет. На практике возможны два решения: либо перенести init.tcl (и, возможно, ещё некоторые файлы) из пакета tcl в пакет libtcl, либо полностью внести libtcl в tcl (то есть исключить отдельный пакет с библиотекой, если библиотека "сама по себе" не работает). * * * Вернёмся к кешу иконок libgtk+2 и его специфике. Кеш создаётся для каждой отдельной "темы" иконок, а темы раскладываются по отдельным каталогам. Для каждой темы должен существовать файл index.theme (для темы "hicolor", используемой по умолчанию, это будет /usr/share/icons/hicolor/index.theme в пакете icon-theme-hicolor). Программа gtk-update-icon-cache по умолчанию отказывается создавать кеш, если отсутствует файл index.theme. Однако пакет libgtk+2 не имеет зависимости на icon-theme-hicolor, то есть в базовой установке для дефолтной темы hicolor отсутствует файл index.theme. Хотелось бы выяснить, в какой степени файл index.theme реально необходим для использования иконок (и для создания кеша иконок). Кроме того, тема hicolor является "расширяемой", т.е. пакеты приложений кладут свои дополнительные иконки в /usr/share/icons/hicolor. Остальные темы являются как бы замкнутыми и независимыми (например, всё содержимое каталога /usr/share/icons/gnome принадлежит пакету gnome-icon-theme, а другие приложения туда иконок не кладут. Короче, для триггера возможна следующая логика обновления кеша иконок: 1) каталог /usr/share/icons/hicolor обрабатывается специально; 2) остальные темы обрабатываются по факту наличия в траназкции файла index.theme. Тогда возможна следующая реализация /usr/lib/rpm/gtk-icon-cache.filetrigger: #!/bin/sh hicolor= while read -r f; do case "$f" in /usr/share/icons/hicolor/*) hicolor=1 ;; /usr/share/icons/*/index.theme) if [ -f "$f" ]; then gtk-update-icon-cache "${f%/*}" else rm -f "${f%/*}"/icon-theme.cache fi ;; esac done if [ -n "$hicolor" ]; then gtk-update-icon-cache --ignore-theme-index /usr/share/icons/hicolor fi То есть для любых изменений в /usr/share/icons/hicolor вызывается gtk-update-icon-cache с опцией --ignore-theme-index (отключается проверка наличия index.theme). Все остальные темы обрабатываются по файлу index.theme: если он добавился или обновился, то gtk-update-icon-cache запускается обычным способом; если же файл index.theme удалился, то удаляется и соответствующий ему кеш icon-theme.cache. Мы исходили из предположения, что все остальные темы, кроме hicolor, являются замкнутыми и независимыми, поэтому обновления кеша этих тем можно привязать к соответствующему файлу index.theme. Я сейчас на всякий случай проверил, и оказалось, что предположение не всегда выполняется. $ grep /usr/share/icons/gnome/ ~tmp/build/cache/contents/contents_index_all |awk '$2!="gnome-icon-theme"' /usr/share/icons/gnome/32x32 /usr/share/icons/gnome/32x32 /usr/share/icons/gnome/32x32/apps /usr/share/icons/gnome/32x32/apps /usr/share/icons/gnome/48x48 /usr/share/icons/gnome/48x48 /usr/share/icons/gnome/48x48/apps /usr/share/icons/gnome/48x48/apps /usr/share/icons/gnome/48x48/mimetypes gdesklets /usr/share/icons/gnome/48x48/mimetypes/gnome-mime-application-x-anjuta.png anjuta2 /usr/share/icons/gnome/48x48/mimetypes/gnome-mime-application-x-codeblocks-workspace.png codeblocks /usr/share/icons/gnome/48x48/mimetypes/gnome-mime-application-x-codeblocks.png codeblocks /usr/share/icons/gnome/48x48/mimetypes/gnome-mime-application-x-gdesklets-display.png gdesklets /usr/share/icons/gnome/48x48/mimetypes/gnome-mime-application-x-littlewizard.png littlewizard /usr/share/icons/gnome/48x48/mimetypes/gnome-mime-application-x-ptoptimizer-script.png hugin /usr/share/icons/gnome/scalable/mimetypes/gnome-mime-application-x-anjuta.svg anjuta2 /usr/share/icons/gnome/scalable/mimetypes/gnome-mime-application-x-littlewizard.svg littlewizard $ То есть существуют приложения, хотя и немногочисленные, которые кладут иконки в тему "gnome". По-видимому, в таких случаях кеш темы gnome также следует обновлять; так что предложенная логика обновления дополнительных тем уже оказывается недостаточной. * * * Триггер после транзакции -- это хорошо, но нужно также рассмотреть вопрос, что происходит в самом начале и в самом конце. Когда библиотека libgtk+2 устанавливается в первый раз, некоторые темы иконок уже могут быть установлены (в более ранних транзакциях). Также, при обновлении библиотеки libgtk+2 формат кеша может измениться (более или менее совместимым образом). Короче, после установки или обновления libgtk+2 желательно обновить кеш всех существующих тем. Смотрите, как красиво это можно сделать: %post find /usr/share/icons -type f |/usr/lib/rpm/gtk-icon-cache.filetrigger То есть мы запускаем триггер от имени %post-скрипта и как бы говорим ему: "посмотри, все эти иконки как будто только что добавились". Дальше триггер уже сам решит, какие там есть темы и как обновлять кеш. А при окончательном удалении библиотеки libgtk+2 кеш иконок больше никому не нужен. Так что можно написать %postun if [ $1 = 0 ]; then rm -f /usr/share/icons/*/icon-theme.cache fi * * * Что до самой библиотеки libgtk+2, то, во-первых, недавно вышла новая версия 2.14. Во-вторых, мне не нравится существующий распил на libgtk+2 и libgtk+2-common. Может быть, вместе с триггером я бы посмотрел новую версию и попилил бы её на свой вкус.