From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Date: Sun, 16 Nov 2003 17:58:30 +0300 From: Alexey Tourbin To: devel@altlinux.ru Message-ID: <20031116145830.GC1863@julia.office.altlinux.ru> Mail-Followup-To: devel@altlinux.ru Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="76DTJ5CE0DCVQemd" Content-Disposition: inline Subject: [devel] packagereq/buildreq proposal X-BeenThere: devel@altlinux.ru X-Mailman-Version: 2.1.3 Precedence: list Reply-To: ALT Devel discussion list List-Id: ALT Devel discussion list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 16 Nov 2003 14:58:31 -0000 Archived-At: List-Archive: List-Post: --76DTJ5CE0DCVQemd Content-Type: multipart/mixed; boundary="8X7/QrJGcKSMr1RN" Content-Disposition: inline Content-Transfer-Encoding: 8bit --8X7/QrJGcKSMr1RN Content-Type: text/plain; charset=koi8-r Content-Disposition: inline Content-Transfer-Encoding: 8bit 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 --8X7/QrJGcKSMr1RN Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="rpm.pl" #!/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; } --8X7/QrJGcKSMr1RN-- --76DTJ5CE0DCVQemd Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.3 (GNU/Linux) iD8DBQE/t5CWfBKgtDjnu0YRAn3+AJ432ZhqIOY8NsskoyEfnhocdGYtOgCeLMyG Cz9TDGEMAdd8ZWLx4qGk/mA= =qlMq -----END PGP SIGNATURE----- --76DTJ5CE0DCVQemd--