RPM/rpmvercmp

Материал из ALT Linux Wiki
< RPM

Структура

В общем виде

NAME#[EPOCH:]VERSION-RELEASE[:DISTTAG]@BUILDTIME

В квадратных скобках указаны опциональные параметры.

Символы #, :, - и @ используются как разделители.

Здесь:

  • Name: имя пакета. Может состоять из латинских букв, цифр и разделителей -, ., _, +
  • Epoch: опциональный параметр. Представляет из себя натуральное число. Это наиболее приоритетная часть версии, используется для того, чтобы переопределить порядок сортировки версий.
  • Version: версия пакета. Может состоять из латинских букв, цифр, особого символа ~ и разделителей ., _, + (среди них нет -). Подробнее об использовании - Spec#Version
  • Release: релиз пакета. Символы те же, что у Version. Подробнее об использовании - Spec#Release
  • Disttag: поле, позволяющее различать разные сборки пакета. Формируется автоматически на сборочнице. В локально собранных пакетах этого поля нет. Значение дисттэга доступно при сборке через макрос %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 - EPOCH
  • 6.1.33 - VERSION
  • alt1 - RELEASE
  • sisyphus+322849.100.1.1 - DISTTAG
  • 1686572661 - 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 не работает - как и сам скрипт)

Алгоритмы

Сравнение полных версий

Поля сравниваются последовательно:

  1. Эпохи (как числа)
  2. Версии (по алгоритму rpmvercmp)
  3. Релизы (по алгоритму rpmvercmp)
  4. Дисттэги (по алгоритму rpmvercmp)
  5. Время сборки (как числа)

Переход к следующему пункту происходит только при равенстве значений на текущем.

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