# 8. Патчи для пакетов

Sometimes, Ubuntu package maintainers have to change the upstream source code in order to make it work properly on Ubuntu. Examples include, patches to upstream that haven’t yet made it into a released version, or changes to the upstream’s build system needed only for building it on Ubuntu. We could change the upstream source code directly, but doing this makes it more difficult to remove the patches later when upstream has incorporated them, or extract the change to submit to the upstream project. Instead, we keep these changes as separate patches, in the form of diff files.

Существуют различные способы работы с патчами для пакетов Debian. К счастью, мы остановимся на одной системе, Quilt, которая сейчас используется большинством пакетов.

Let’s look at an example package, `kamoso` in Trusty:

    $ bzr branch ubuntu:trusty/kamoso

Патчи хранятся в `debian/patches`. Для этого пакета имеется один патч `kubuntu_01_fix_qmax_on_armel.diff` для исправления ошибки компиляции на платформе ARM. Этому патчу присвоено имя, описывающее, что он делает, номер патча по порядку (чтобы избежать путаницы, если два патча имеют одинаковое имя) и, в данном случае, команда Kubuntu добавила свой собственный префикс, чтобы показать, что патч исходит от них, а не от Debian.

Порядок применения патчей хранится в `debian/patches/series`.

## 8.1. Патчи с помощью Quilt

Перед работой с Quilt нужно указать этой системе, где искать патчи. Добавьте в `~/.bashrc` следующее:

    export QUILT_PATCHES=debian/patches

And source the file to apply the new export:

    $ . ~/.bashrc

По умолчанию все патчи применяются уже с UDD извлечений или загружаемых пакетов. Вы можете проверить это с помощью:

    $ quilt applied
    kubuntu_01_fix_qmax_on_armel.diff

Если вы хотите удалить патч, нужно выполнить `pop`:

    $ quilt pop
    Removing patch kubuntu_01_fix_qmax_on_armel.diff
    Restoring src/kamoso.cpp

    No patches applied

А чтобы применить патч, используйте `push`:

    $ quilt push
    Applying patch kubuntu_01_fix_qmax_on_armel.diff
    patching file src/kamoso.cpp

    Now at patch kubuntu_01_fix_qmax_on_armel.diff

## 8.2. Добавление нового патча

Для добавления нового патча нужно указать Quilt создать новый патч, сообщить ему, какие файлы этот патч должен изменить, отредактировать файлы, а затем обновить патч:

    $ quilt new kubuntu_02_program_description.diff
    Patch kubuntu_02_program_description.diff is now on top
    $ quilt add src/main.cpp
    File src/main.cpp added to patch kubuntu_02_program_description.diff
    $ sed -i "s,Webcam picture retriever,Webcam snapshot program,"
    src/main.cpp
    $ quilt refresh
    Refreshed patch kubuntu_02_program_description.diff

Шаг `quilt add` важен: если вы забудете его сделать, файлы не попадут в патч.

Теперь изменения будут в `debian/patches/kubuntu_02_program_description.diff`, а в файл `series` будет добавлена информация о новом патче. Вы должны добавить новый файл в исходные файлы для пакета:

    $ bzr add debian/patches/kubuntu_02_program_description.diff
    $ bzr add .pc/*
    $ dch -i "Add patch kubuntu_02_program_description.diff to improve the program description"
    $ bzr commit

Quilt keeps its metadata in the `.pc/` directory, so currently you need to add that to the packaging too. This should be improved in future.

Как правило, следует проявлять осторожность при добавлении патчей к программам, если они исходят не из апстрима. Часто имеется веская причина, по которой изменения ещё не были сделаны. В рассмотренном выше примере изменяется строка в пользовательском интерфейсе, так что это может поломать все переводы. Если сомневаетесь, спросите автора из апстрима перед тем, как добавить патч.

## 8.3. Patch Headers

We recommend that you tag every patch with DEP-3 headers by putting them at the top of patch file. Here are some headers that you can use:

Description: | Description of what the patch does. It is formatted like `Description` field in `debian/control`: first line is short description, starting with lowercase letter, the next lines are long description, indented with a space.
Author: | Кто написал патч (например, “Jane Doe <packager@example.com>”).
Origin: | Откуда пришёл этот патч (например, “upstream”), если заголовок Author отсутствует.
Bug-Ubuntu: | Ссылка на информацию об ошибке на Launchpad, предпочтительно, в краткой форме (наподобие https://bugs.launchpad.net/bugs/XXXXXXX). Если также имеются отчёты об ошибках в апстриме или системах отслеживания ошибок Debian, добавьте заголовки Bug или Bug-Debian.
Forwarded: | Whether the patch was forwarded upstream. Either “yes”, “no” or “not-needed”.
Last-Update: | Дата последней ревизии (в форме “ГГГГ-ММ-ДД”).

## 8.4. Обновление до новых версий из апстрима

Чтобы выполнить обновление до последней версии, вы можете использовать команду `bzr merge-upstream`:

    $ bzr merge-upstream --version 2.0.2 https://launchpad.net/ubuntu/+archive/primary/+files/kamoso_2.0.2.orig.tar.bz2

When you run this command, all patches will be unapplied, because they can become out of date. They might need to be refreshed to match the new upstream source or they might need to be removed altogether. To check for problems, apply the patches one at a time:

    $ quilt push
    Applying patch kubuntu_01_fix_qmax_on_armel.diff
    patching file src/kamoso.cpp
    Hunk #1 FAILED at 398.
    1 out of 1 hunk FAILED -- rejects in file src/kamoso.cpp
    Patch kubuntu_01_fix_qmax_on_armel.diff can be reverse-applied

Если для патча указано `it can be reverse-applied`, значит патч уже был применён апстримом, так что мы можем удалить этот патч:

    $ quilt delete kubuntu_01_fix_qmax_on_armel
    Removed patch kubuntu_01_fix_qmax_on_armel.diff

Затем продолжайте:

    $ quilt push
    Applied kubuntu_02_program_description.diff

Неплохой мыслью будет выполнить refresh, это обновит патч относительно изменений исходного кода в апстриме:

    $ quilt refresh
    Refreshed patch kubuntu_02_program_description.diff

Затем выполните фиксацию, как обычно:

    $ bzr commit -m "new upstream version"

## 8.5. Создание пакета с использованием Quilt

Modern packages use Quilt by default, it is built into the packaging format. Check in `debian/source/format` to ensure it says `3.0 (quilt)`.

Для более старых пакетов, использующих формат 1.0, необходимо использовать Quilt явно, обычно с помощью включения make-фала в `debian/rules`.

## 8.6. Конфигурирование Quilt

Вы можете воспользоваться файлом `~/.quiltrc` для конфигурирования quilt. Вот несколько опций, которые могут быть полезны при использовании quilt с пакетами Debian:

    # Set the patches directory
    QUILT_PATCHES="debian/patches"
    # Remove all useless formatting from the patches
    QUILT_REFRESH_ARGS="-p ab --no-timestamps --no-index"
    # The same for quilt diff command, and use colored output
    QUILT_DIFF_ARGS="-p ab --no-timestamps --no-index --color=auto"

## 8.7. Другие системы управления патчами

Other patch systems used by packages include `dpatch` and `cdbs simple-patchsys`, these work similarly to Quilt by keeping patches in `debian/patches` but have different commands to apply, un-apply or create patches. You can find out which patch system is used by a package by using the `what-patch` command (from the `ubuntu-dev-tools` package). You can use `edit-patch`, shown in previous chapters, as a reliable way to work with all systems.

In even older packages changes will be included directly to sources and kept in the `diff.gz` source file. This makes it hard to upgrade to new upstream versions or differentiate between patches and is best avoided.

Не изменяйте систему патчей, не обсудив это с сопровождающим Debian или имеющей отношение к делу командой Ubuntu. Если существующей системы патчей нет, можете добавить Quilt.