[devel] packagereq/buildreq proposal
Alexey Tourbin
=?iso-8859-1?q?at_=CE=C1_altlinux=2Eru?=
Вс Ноя 16 17:58:30 MSK 2003
Greetings!
Дано: имеется список пакетов, полученный packagereq, БЕЗ учета текущей
оптимизации. Список пакетов вычисляется на основе вывода strace и
получается очень большим. Некоторая часть этого списка не содержит
полезной информации. Задача: оптимизировать список пакетов.
Анализ текущего алгоритма оптимизации: если в списке есть пакеты с
названиями %name и %name-foo, то пакет %name удаляется из списка.
Если в списке есть пакеты с названиями lib%name и %name, то пакет
lib%name удаляется из списка. Удаляются также все пакеты из списка
essential.
Недостатки текущего алгоритма: алгоритм не учитывает зависимости между
пакетами. В результате 1) список пакетов остается перегруженным; 2)
алгоритм делает ошибки, если структура зависимостей не соответствует
описанным допущениям.
Примеры, которые демонстрируют недостатоки алгоритма:
$ packagereq -o /dev/stdout -- sh -c 'cat `rpm -ql perl-DBD-mysql libMySQL` &>/dev/null ||:'
packagereq: building requires list: libMySQL perl-DBD-mysql
libMySQL perl-DBD-mysql
$
Сейчас в сизифе есть два пакета с libmysqlclient.so. perl-DBD-mysql
собран с одной из этих библиотек. Впоследствии он может быть пересобран
с другой. Зависимость в третьем пакете на libMySQL не нужна.
$ packagereq -o /dev/stdout -- sh -c 'cat `rpm -ql libpcre-devel libpcre` &>/dev/null ||:'
packagereq: building requires list: libpcre-devel libpcre-devel
$
Пакеты libpcre-devel и libpcre, увы, между собой не связаны.
Пример с пакетам ruby, который приводит к тому, что в минимальной
сборочной среде ruby отсутствует, я уже приводил.
Определения.
Прямая зависимость между пакетами: пакет A напрямую зависит от пакета B,
если на уровне RPM существует зависимость следующего типа:
%package -n A
Requires: B
Пример прямой зависимости:
$ rpm -q --requires libpcre-devel | grep pcre
libpcre3 = 4.4-alt1
$
Пакет pcre-devel напрямую зависит от libpcre3.
Прямая зависимость через виртуальный пакет: пакет A зависит от пакета B
через виртуальный пакет, если на уровне RPM существует зависимость
следующего типа:
%package -n A
Requires: package_B
%package -n B
Provides: package_B
Пример зависимости через виртуальный пакет:
$ rpm -q --requires perl-DBD-mysql | grep mysqlclient
libmysqlclient.so.12
$ rpm -q --whatprovides libmysqlclient.so.12
libMySQL-4.0.15-alt2
$
Пакет perl-DBD-mysql зависит от пакета libMySQL через виртуальный пакет
libmysqlclient.so.12.
Косвенная зависимость: любые зависимости с более сложной структурой не
рассматриваются.
Алгоритм оптимизации: из списка по очереди выбирается пакет-кандидат на
удаление. Если какой-либо пакет из оставшейся части списка зависит от
кандидата напрямую или через виртуальный пакет, кандидат удаляется.
Выполнение алгоритма продолжается на оставшемся списке.
Преимущества алгоритма: алгоритм лишен недостатков текущего алгоритма.
Недостаток алгоритма: результат зависит от порядка пакетов в списке.
Пример:
BuildRequires: XFree86-libs XFree86-devel XFree86-devel-static
^-------------' ^----------------'
Пакеты XFree86-libs и XFree86-devel будут по очереди удалены.
BuildRequires: XFree86-devel XFree86-devel-static XFree86-libs
`----------------------------^
^---------------------'
Первым будет удален пакет XFree86-devel; информация о том, что он
непосредственно зависит от XFree86-libs, будет потеряна.
Над решением этой проблемы в общем виде я не думал. В данном частном
случае, как и в некоторых других, достаточно отсортировать список по
возрастанию длины названия пакета.
Недостаток алгоритма: алгоритм не работает с виртуальными пакетами
(которые packagereq подставляет в соответствии с правилами
/etc/buildreqs/packages/substitute.d). Обсуждение на канале привело
меня к мысли, что семантика виртуальных пакетов, которые предоставляются
несколькими другими пакетами, определена недостаточно хорошо. Нужно
сформулировать правила использования виртуальных пакетов.
Прототип реализации прилагается.
Примеры работы прототипа:
$ perl rpm.pl libMySQL perl-DBD-mysql
perl-DBD-mysql requires libMySQL through libmysqlclient.so.12
libMySQL optimized out
perl-DBD-mysql
$ perl rpm.pl libpcre3 libpcre libpcre-devel
libpcre-devel requires libpcre3
libpcre3 optimized out
libpcre libpcre-devel
$ perl rpm.pl XFree86-libs XFree86-devel XFree86-devel-static
XFree86-devel requires XFree86-libs through libX11.so.6
XFree86-libs optimized out
XFree86-devel-static requires XFree86-devel
XFree86-devel optimized out
XFree86-devel-static
----------- следующая часть -----------
#!/usr/bin/perl
use RPM::Database;
use strict;
my $db = RPM::Database->new;
my %DB;
# load Requires: and Provides: from RPM database for the given packages
foreach my $pkg (@ARGV) {
my $hdr = $$db{$pkg};
unless ($hdr) {
warn "package $pkg not found\n";
next;
}
my $requires = $$hdr{REQUIRENAME};
if ($requires) {
$DB{$pkg}{req} = $requires;
} else {
warn "package $pkg requires nothing\n";
$DB{$pkg}{req} = [];
}
my $provides = $$hdr{PROVIDES};
if ($provides) {
$DB{$pkg}{prov} = $provides;
} else {
warn "package $pkg provides nothing\n";
$DB{$pkg}{prov} = [];
}
}
use sort 'stable';
# try to optimize out packages with shortest names first
# alphabetical order is also in effect
my @packages = sort { length($a) <=> length($b) } sort keys %DB;
try: while (1) {
foreach my $pkg (@packages) {
my @rest = grep { $_ ne $pkg } @packages;
if (my ($who, $what) = implies($pkg, @rest)) {
warn "\t$who requires $pkg" .
($what eq $pkg ? "\n" : " through $what\n");
warn "\t\t$pkg optimized out\n";
@packages = @rest;
next try;
}
}
last;
}
@packages = sort @packages;
print "@packages\n";
sub implies {
my ($pkg, @others) = @_;
foreach my $prov (@{$DB{$pkg}{prov}}) {
foreach my $who (@others) {
foreach my $req (@{$DB{$who}{req}}) {
return ($who, $req)
if ($req eq $prov);
}
}
}
return;
}
----------- следующая часть -----------
Было удалено вложение не в текстовом формате...
Имя : =?iso-8859-1?q?=CF=D4=D3=D5=D4=D3=D4=D7=D5=C5=D4?=
Тип : application/pgp-signature
Размер : 189 байтов
Описание: =?iso-8859-1?q?=CF=D4=D3=D5=D4=D3=D4=D7=D5=C5=D4?=
Url : <http://lists.altlinux.org/pipermail/devel/attachments/20031116/96b32f68/attachment-0001.bin>
Подробная информация о списке рассылки Devel