RPM/rpmvercmp
Структура
В общем виде
NAME#[EPOCH:]VERSION-RELEASE[:DISTTAG]@BUILDTIME
В квадратных скобках указаны опциональные параметры.
Символы #, :, - и @ используются как разделители.
Здесь:
Name: имя пакета. Может состоять из латинских букв, цифр и разделителей-,.,_,+Epoch: опциональный параметр. Представляет из себя натуральное число. Это наиболее приоритетная часть версии, используется для того, чтобы переопределить порядок сортировки версий.Version: версия пакета. Может состоять из латинских букв, цифр, особого символа~и разделителей.,_,+(среди них нет-). Подробнее об использовании - Spec#VersionRelease: релиз пакета. Символы те же, что уVersion. Подробнее об использовании - Spec#ReleaseDisttag: поле, позволяющее различать разные сборки пакета. Формируется автоматически на сборочнице. В локально собранных пакетах этого поля нет. Значение дисттэга доступно при сборке через макрос%disttag. Расшифровка:названия_бранча+номер_задания.подзадание.итерация.попытка.BUILDTIME: время сборки пакета. Формируется автоматически, значение - натуральное число (unixtime).
На примерах
Полная версия пакета kernel-image-std-def-debuginfo-6.1.33-alt1.x86_64.rpm может выглядеть так:
kernel-image-std-def-debuginfo#2:6.1.33-alt1:sisyphus+322849.100.1.1@1686572661
kernel-image-std-def-debuginfo-NAME. Содержит в себе компонент (debuginfo)2-EPOCH6.1.33-VERSIONalt1-RELEASEsisyphus+322849.100.1.1-DISTTAG1686572661-BUILDTIME(в unixtime)
Важно отметить
- Cтрока
[EPOCH:]VERSION-RELEASEназывается EVR. - При локальной сборке DISTTAG отсутствует (его выставляет только сборочница).
- В названии файла и в имени пакета, в том виде, как его выводит
rpm -q, указаны толькоVERSION-RELEASE. Остальные поля отсутствуют (они носят служебный характер и интересны мейнтейнеру, а не конечному пользователю). VERSIONиRELEASEне содержат символов-. Поэтому их можно легко выделить, взяв два последних компонента строки, разделенных дефисами.- Полная версия из примера получена следующей командой:
rpm -q --qf "%{NAME}#%{EPOCH}:%{VERSION}-%{RELEASE}:%{DISTTAG}@%{BUILDTIME}\n"
Сравнение версий пакетов
Реализации
rpmvercmp
Утилита rpmvercmp сравнивает только версию (’‘’VERSION’’’) без релиза и пр.
rpmevrcmp
Утилита rpmevrcmp сравнивает только эпоху:версию-релиз (’‘’EVR’’’) без дисттэга.
python
Метод rpm.versionCompare() модуля rpm. Но, нужно учесть, что в качестве аргументов он требует объекты hdr, а не строки.
Так же пример использования rpm.labelCompare() есть в скрипте /usr/bin/rpmdev-vercmp (однако rpm.labelCompare() в Альт-RPM не работает - как и сам скрипт)
Алгоритмы
Сравнение полных версий
Поля сравниваются последовательно:
- Эпохи (как числа)
- Версии (по алгоритму rpmvercmp)
- Релизы (по алгоритму rpmvercmp)
- Дисттэги (по алгоритму rpmvercmp)
- Время сборки (как числа)
Переход к следующему пункту происходит только при равенстве значений на текущем.
rpmvercmp
Для того, чтобы сравнить две строки (версии, релиза, дисттэга) используется следующий алгоритм:
Порядок действий
- Cтроки разбиваются на сегменты - числовые, строчные и тильду. Используются следующие правила:
- Если встречается цифра, то собирается числовой сегмент (до следующей не цифры).
- Если встречается буква, то собирается строчный сегмент (до следующей не буквы).
- Тильда образует собственный сегмент.
- Разделители пропускаются.
- Правила сравнения сегментов следующие:
- Числовые сравниваются как числа. (
000123и123- два одинаковых сегмента). - Строчные сравниваются в лексикографическом порядке.
- Строчные всегда больше чем числовые.
- Тильда всегда меньше чем любые другие сегменты.
- Тильда равна тильде.
- Числовые сравниваются как числа. (
- Пошаговый проход через сегменты, с попарным сравнением.
- Остановка происходит на первых неравных сегментах. Возвращается результат сравнения сегментов.
- Если сегменты в одной из строк закончились, и
- во второй строке сегменты тоже кончились. В этом случае строки равны.
- во второй строке следующий сегмент это тильда. В этом случае первая строка (без тильды) больше.
- во второй строке есть ещё минимум один числовой или строчный сегмент. В этом случае первая строка (закончившаяся) меньше.
Результат сравнения
Алгоритм возвращает:
- -1, если A < B
- 0, если A == B
- 1, если A > B
Примеры
Неравные числовые версии
1.0 vs 1.0.1
Сравнение:
- 1 == 1
- 0 == 0
- Пустой сегмент < 1
Результат: A < B
Равные числовые версии
1.02 vs 1.2
- 1 == 1
- 02 == 2
Результат: A == B
Поведение тильды
1.0~beta vs 1.0
- 1 == 1
- 0 == 0
- ~ < Пустой сегмент
- beta игнорируется
Результат: A < B
Строки против чисел
1.a vs 1.0
- 1 == 1
- “a” > 0
Результат: A < B
Строки против строк
1.alpha vs 1.beta
- 1 == 1
- “alpha” < “beta” (‘a’ < ‘b’)
A > B
Строчно-числовое разделение
alpha1 vs alpha2
- “alpha” == “alpha”
- 1 < 2
A < B
Сплошные разделители
+.+ vs ____
- Разделители пропускаются
- Пустой сегмент == Пустой сегмент
A == B
Мир тильд
1.0~~ vs 1.0~~~
- 1 == 1
- 0 == 0
- ~ == ~
- ~ == ~
- Пустой сегмент > ~
A > B