Теория: патчи, форматы и применение
На этой странице
Когда нужны патчи
Типичные ситуации
-
Ошибка компиляции на новом компилятор. Upstream писал код под GCC 12, а в ROSA стоит GCC 14, который стал строже. Код не компилируется из-за нового предупреждения с
-Werror. -
Дистрибутив-специфичные пути. Программа ищет конфиг в
/etc/htop/htoprc, а в ROSA принято хранить в/etc/htoprc. Нужно поменять путь. -
Безопасность (CVE). Найдена уязвимость, upstream выпустил фикс, но новая версия ещё не вышла. Нужно взять конкретный коммит.
-
Бэкпорт исправления бага. В upstream уже починили баг, но мы не можем обновиться на новую версию (слишком много изменений). Забираем только нужный коммит.
-
Интеграция с дистрибутивом. Добавление desktop-файла, иконок, AppStream-метаданных, systemd-юнитов.
Принцип: минимальный патч
Патч должен быть минимальным. Не меняйте форматирование кода, не исправляйте стилистику, не добавляйте несвязанные изменения. Один патч — одно логическое изменение. Это упрощает ревью и обновление на новую версию.
diff -u vs git format-patch
Способ 1: diff -u (классический)
diff -u файл_оригинал файл_изменённый > my.patch
Или для целого каталога:
diff -ruN каталог_оригинал/ каталог_изменённый/ > my.patch
Флаги:
-r— рекурсивно (все файлы в подкаталогах)-u— unified формат (с контекстом---/+++)-N— включать новые файлы (которых нет в оригинале)
Когда использовать: если у вас нет git (редко) или нужен простой одиночный diff между двумя файлами.
Способ 2: git format-patch (рекомендуемый)
git format-patch -1 # создать патч из последнего коммита
git format-patch -1 --stdout > my.patch # вывести в файл
git format-patch -3 # три последних коммита → три файла
Преимущества:
- Включает метаданные: автор, дата, описание коммита
- Номерация (
0001-,0002-) — порядок применения очевиден - Формат совместим с
git am— можно применить обратно в git - Проще всего создавать из upstream-коммитов
Когда использовать: почти всегда. Это стандарт в мире RPM-пакетирования.
Уровни патча (-p0, -p1, -p2)
Патч содержит пути к файлам. Уровень -p определяет, сколько компонентов
пути отрезать при применении.
Допустим, в патче написано:
--- a/src/htop.c
+++ b/src/htop.c
| Уровень | Что отрезается | Результат | Когда использовать |
|---|---|---|---|
-p0 | Ничего | Ищет файл a/src/htop.c | diff -ruN old/ new/ |
-p1 | Первый компонент (a/) | Ищет файл src/htop.c | git format-patch (стандарт) |
-p2 | Два компонента (a/src/) | Ищет файл htop.c | Редко |
Правило: git format-patch всегда создаёт пути с a/ и b/ префиксами,
поэтому для git-патчей всегда нужен -p1.
%autosetup vs %setup + %patch
Современный способ: %autosetup (рекомендуется)
Patch0: htop-disable-werror.patch
Patch1: htop-fix-build.patch
%prep
%autosetup -p1
%autosetup -p1 делает всё за вас:
- Распаковывает архив (как
%setup) - Применяет все патчи (
Patch0,Patch1, …) с уровнем-p1 - В правильном порядке (по номерам)
Устаревший способ: %setup + %patch
Patch0: htop-disable-werror.patch
Patch1: htop-fix-build.patch
%prep
%setup -q
%patch0 -p1
%patch1 -p1
Здесь каждый патч применяется отдельной командой. Это даёт больше контроля
(разные -p уровни для разных патчей), но громоздко.
Рекомендация: используйте %autosetup -p1, если все патчи с одинаковым
уровнем. Это проще и современнее.
Где применяются патчи
Патчи применяются к распакованным исходникам в каталоге:
~/rpmbuild/BUILD/htop-3.3.0/
Это каталог, куда %autosetup распаковал архив. Все пути в патче
отсчитываются от этого каталога (после отрезания -p уровня).