Вопрос или проблема
Вопрос:
Что мне нужно указать в файле foo.spec, чтобы RPM удалял предыдущий RPM перед установкой?
Описание:
Я создал файл спецификаций, который создает RPM для нескольких пакетов, использующих один и тот же источник и предоставляющих одну и ту же услугу, каждый с немного другой конфигурацией. Например, они все предоставляют одну и ту же “возможность”.
Вот пример основных элементов моего .spec файла:
%define version 1234
%define name foo
%define release 1
%define pkgname %{name}-%{version}-%{release}
Name: %{name}
Version: %{version}
Release: %{release}
Provides: %{name}
%package one
Summary: Резюме для foo-one
Group: %{group}
Obsoletes: %{name} <= %{version}
Provides: %{name} = %{version}
%description one
Бла бла бла
%package two
Summary: Резюме для foo-two
Group: %{group}
Obsoletes: %{name} <= %{version}
Provides: %{name} = %{version}
%description two
Бла бла бла
# %prep, %install, %build и %clean довольно просты
# и опущены здесь ради краткости
%files one
%defattr(-,root,root,-)
%{_prefix}/%{pkgname}
%files two
%defattr(-,root,root,-)
%{_prefix}/%{pkgname}
Когда я устанавливаю первый, он устанавливается нормально. Затем я удаляю первый, а затем устанавливаю второй, это тоже работает нормально.
Затем я устанавливаю первый, сразу же за ним устанавливаю второй, и они оба устанавливаются, один поверх другого, но я ожидал, что второй будет удален перед установкой второго.
Пример сеанса:
# rpmbuild foo и копирование rpm в yum репозиторий
$ yum install foo-one
...
$ yum list installed|grep foo
foo-one.noarch 1234-1 @myrepo
$ yum install foo-two
...[Должно сказать, что он удаляет foo-one, но не говорит]...
$ yum list installed|grep foo
foo-one.noarch 1234-1 @myrepo
foo-two.noarch 1234-1 @myrepo
$ rpm -q --provides foo-one
foo = 1234
foo-one = 1234-1
$ rpm -q --provides foo-two
foo = 1234
foo-two = 1234-1
Что мне нужно указать в файле foo.spec, чтобы RPM удалял предыдущий RPM перед установкой?
Вы хотите сделать так, чтобы эти пакеты конфликтовали друг с другом, чтобы yum знал, что их нельзя устанавливать одновременно.
%package one
Summary: Резюме для foo-one
Group: %{group}
Obsoletes: %{name} <= %{version}
Provides: %{name} = %{version}
Conflicts: %{name}-two
Ответ или решение
Чтобы обеспечить удаление предыдущего RPM перед установкой нового пакета в вашем проекте, необходимо использовать директиву Conflicts
в вашем файле спецификации .spec
. Эта директива сообщает менеджеру пакетов, что указанные пакеты не могут существовать одновременно.
Ниже описывается, как это сделать на практике, используя ваш пример:
Обновленная структура spec-файла
Ваш текущий foo.spec
файл может быть модифицирован следующим образом:
%define version 1234
%define name foo
%define release 1
%define pkgname %{name}-%{version}-%{release}
Name: %{name}
Version: %{version}
Release: %{release}
Provides: %{name}
%package one
Summary: Summary for foo-one
Group: %{group}
Obsoletes: %{name} < %{version}
Provides: %{name} = %{version}
Conflicts: %{name} two
%description one
Blah blah blah
%package two
Summary: Summary for foo-two
Group: %{group}
Obsoletes: %{name} < %{version}
Provides: %{name} = %{version}
Conflicts: %{name} one
%description two
Blah blah blah
# %prep, %install, %build и %clean опущены для краткости
%files one
%defattr(-,root,root,-)
%{_prefix}/%{pkgname}
%files two
%defattr(-,root,root,-)
%{_prefix}/%{pkgname}
Пояснение изменений
-
Директива
Conflicts
:- Для каждого пакета (
one
иtwo
) добавьте директивуConflicts
, которая указывает на противоположный пакет. Это позволяет системе установки (например,yum
) выяснить, что оба пакета не могут быть установлены одновременно. Conflicts: %{name} two
означает, что если установленfoo-two
, то перед установкойfoo-one
,foo-two
будет удалён.
- Для каждого пакета (
-
Директива
Obsoletes
:- Использование директивы
Obsoletes
позволяет удостовериться, что при установке нового пакета системы могу удалять более старые версии или пакеты, которые предоставляют аналогичную функциональность.
- Использование директивы
Пример установки
Теперь, когда вы установите foo-one
, а затем попытаетесь установить foo-two
, система сообщит вам, что foo-one
будет удалён, что соответствует желаемой логике:
$ yum install foo-one
...
$ yum install foo-two
...
Removing foo-one because it conflicts with foo-two
Заключение
С помощью директив Conflicts
и Obsoletes
вы сможете контролировать порядок установки и обеспечивать, чтобы только одна версия пакета была установлена в любой момент времени. Эти изменения сделают ваши RPM-пакеты более управляемыми и предотвратят множественные установки, что также уменьшит потенциальные конфликты конфигураций и зависимостей на стороне конечного пользователя.