Em pacotes Debian nunca devemos modificar diretamente o conteúdo dos arquivos providos pelo upstream. Entretanto, há casos onde aplicar alterações em arquivos do upstream é necessário. Nesses casos, utilizamos patches para aplicar tais modificações antes da construção do pacote e remoção assim que o processo é finalizado. Dessa forma, garantimos que antes e depois da construção do pacote os arquivos providos pelo upstream são os mesmos.
Existem diferentes formas de criar/gerenciar patches em pacotes Debian. As ferramentas mais conhecidas quando se trata de empacotamento Debian são git-buildpackage patch-queue
(a.k.a. gbp-pq
) e quilt
. Vamos apresentar como utilizar essas duas ferramentas a seguir.
git-buildpackage
é uma ferramenta onde se utiliza de fluxos de trabalho comumente usados em repositórios git
para manter pacotes Debian. Uma de suas principais funcionalidades é chamada de patch-queue
, que em uma tradução literal poderia ser chamada de "fila de patches". Funciona da seguinte forma:
debian/patches
. Basicamente, significa a criação de uma branch chamada patch-queue/<branch-de-empacotamento>
idêntica a branch base de empacotamento (de onde a importação dos patches for feita) e a adição de commits no topo, onde cada um representa um arquivo de patch (na ordem listada no arquivo debian/patches/series
). Nesse momento, temos uma relação de 1:1 entre arquivos de patch e commits. Caso o pacote não tenha nada em debian/patches
(o diretório pode nem existir), a branch patch-queue será idêntica à branch base de empacotamento.git
para gerenciar os patches. A criação de um novo patch nada mais é do que a adição de um novo commit. A remoção de um patch é igual a remoção de um commit. A edição de um patch seria a atualização de algum commit. Para o gerenciamento dessa fila de patches, um comando que irá te auxiliar bastante é o rebase interativo do git (git rebase -i <refencia_pro_commit_até_onde_deseja_modificar>
).debian/patches
na branch base de empacotamento.Exemplificando o fluxo acima com comandos:
$ git branch
* master
pristine-tar
upstream
$ ls debian/patches/
996145-fix-tests-with-ruby3.patch series
$ gbp pq import
gbp:info: Trying to apply patches at 'cb025e7c73fa82df961826f9d2fc97cf721afef1'
gbp:info: 1 patches listed in 'debian/patches/series' imported on 'patch-queue/master'
$ git branch
master
* patch-queue/master
pristine-tar
upstream
$ git log -1
commit 986ef9ca34f33854a28d46454fe0aa2b142bdcf2 (HEAD -> patch-queue/master)
Author: Daniel Leidert <dleidert@debian.org>
Date: Mon Nov 1 12:48:58 2021 +0100
Run exe/byebug with correct ruby version during tests
When just running exe/byebug by setting the Gem load paths to a ruby 3.0
environment, the script itself will still be run by ruby 2 and thus leading to
> Ignoring byebug-11.1.3 because its extensions are not built. Try: gem pristine byebug --version 11.1.3
Debian-Bug: https://bugs.debian.org/996145
Forwarded: no
Gbp-Pq: Name 996145-fix-tests-with-ruby3.patch
Como podem ver no exemplo acima, a branch patch-queue/master
foi criada a partir da branch master
(empacotamento), e o patch 996145-fix-tests-with-ruby3.patch
se transformou no commit not top da branch patch-queue.
$ git branch
master
* patch-queue/master
pristine-tar
upstream
$ echo "Testing patch queue" >> README.md
$ git diff
diff --git a/README.md b/README.md
index a8e2046..7f2f721 100644
--- a/README.md
+++ b/README.md
@@ -197,3 +197,4 @@ software, especially:
[Tidelift for enterprise]: https://tidelift.com/subscription/pkg/rubygems-byebug?utm_source=rubygems-byebug&utm_medium=referral&utm_campaign=github&utm_content=enterprise
[Tidelift support]: https://tidelift.com/subscription/pkg/rubygems-byebug?utm_source=rubygems-byebug&utm_medium=referral&utm_campaign=github&utm_content=support
[report a security vulnerability]: https://tidelift.com/security
+Testing patch queue
$ git add README.md
$ git commit -m'Improve README.md'
[patch-queue/master 05d5726] Improve README.md
1 file changed, 1 insertion(+)
$ git log -2
commit 05d5726f678f55a6a77f64ef4dcf09551177f116 (HEAD -> patch-queue/master)
Author: Lucas Kanashiro <lucas.kanashiro@canonical.com>
Date: Tue Apr 23 22:52:25 2024 -0300
Improve README.md
commit 986ef9ca34f33854a28d46454fe0aa2b142bdcf2
Author: Daniel Leidert <dleidert@debian.org>
Date: Mon Nov 1 12:48:58 2021 +0100
Run exe/byebug with correct ruby version during tests
When just running exe/byebug by setting the Gem load paths to a ruby 3.0
environment, the script itself will still be run by ruby 2 and thus leading to
> Ignoring byebug-11.1.3 because its extensions are not built. Try: gem pristine byebug --version 11.1.3
Debian-Bug: https://bugs.debian.org/996145
Forwarded: no
Gbp-Pq: Name 996145-fix-tests-with-ruby3.patch
Acima podemos ver que um novo commit melhorando o arquivo README.md
do upstream foi criado. É importante dizer que os cabeçalhos DEP-3 podem ser adicionados no corpo da mensagem no commit, no geral adicionamos no final, separado da descrição do patch (i.e. os campos Debian-Bug
e Forwarded
no commit representando o patch já existente).
Nesse exemplo, estamos apenas adicionando um novo commit/patch, mas poderíamos editar o já existente, ou fazer um cherry-pick
de algum commit upstream (basta adicionar o repositório remoto do upstream e executar git fetch <remoto_upstream> && git cherry-pick <hash_commit>
), ou qualquer outra coisa que o git
te permita fazer. Lembrando que aqui modificamos apenas os commits que representam os patches, os commits que já estavam presentes na branch base de empacotamento não devem ser modificados.
$ git branch
master
* patch-queue/master
pristine-tar
upstream
$ gbp pq export
gbp:info: On 'patch-queue/master', switching to 'master'
gbp:info: Generating patches from git (master..patch-queue/master)
$ git branch
* master
patch-queue/master
pristine-tar
upstream
$ git status
No ramo master
Seu ramo está à frente de 'origin/master' por 1 submissão.
(use "git push" to publish your local commits)
Changes not staged for commit:
(utilize "git add <arquivo>..." para atualizar o que será submetido)
(use "git restore <file>..." to discard changes in working directory)
modified: debian/patches/series
Arquivos não monitorados:
(utilize "git add <arquivo>..." para incluir o que será submetido)
debian/patches/0002-Improve-README.md.patch
nenhuma modificação adicionada à submissão (utilize "git add" e/ou "git commit -a")
$ cat debian/patches/0002-Improve-README.md.patch
From: Lucas Kanashiro <lucas.kanashiro@canonical.com>
Date: Tue, 23 Apr 2024 22:52:25 -0300
Subject: Improve README.md
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index a8e2046..7f2f721 100644
--- a/README.md
+++ b/README.md
@@ -197,3 +197,4 @@ software, especially:
[Tidelift for enterprise]: https://tidelift.com/subscription/pkg/rubygems-byebug?utm_source=rubygems-byebug&utm_medium=referral&utm_campaign=github&utm_content=enterprise
[Tidelift support]: https://tidelift.com/subscription/pkg/rubygems-byebug?utm_source=rubygems-byebug&utm_medium=referral&utm_campaign=github&utm_content=support
[report a security vulnerability]: https://tidelift.com/security
+Testing patch queue
$ git add debian/patches/
$ git commit -m'Add patch improving README.md'
[master 7b32e3f] Add patch improving README.md
2 files changed, 18 insertions(+)
create mode 100644 debian/patches/0002-Improve-README.md.patch
Pronto! Exportamos o novo commit como um novo patch em debian/patches
na branch base de empacotamento. Dessa forma, podemos commitar esse novo patch e seguir trabalhando normalmente na branch de empacotamento.
O quilt
é uma ferramenta feita para trabalhar com uma série de patches, independente do uso de controle de versão ou não. Ele rastreia mudanças nos arquivos monitorados e faz a gestão dos patches em forma de pilha (push
/pop
).
Vamos tentar aplicar o mesmo patch feito no exemplo com gbp-pq
só que agora usando o quilt
. Vamos seguir os seguintes passos:
$ quilt applied
No patches applied
$ quilt series
996145-fix-tests-with-ruby3.patch
$ quilt push -a
Applying patch 996145-fix-tests-with-ruby3.patch
patching file test/support/utils.rb
Now at patch 996145-fix-tests-with-ruby3.patch
0002-Improve-README.md.patch
:$ quilt new 0002-Improve-README.md.patch
Patch 0002-Improve-README.md.patch is now on top
$ quilt add README.md
File README.md added to patch 0002-Improve-README.md.patch
$ echo "Testing patch queue" >> README.md
$ quilt refresh
Refreshed patch 0002-Improve-README.md.patch
debian/patches
e a série de patches:$ ls debian/patches/
0002-Improve-README.md.patch 996145-fix-tests-with-ruby3.patch series
$ quilt series
996145-fix-tests-with-ruby3.patch
0002-Improve-README.md.patch
$ quilt applied
996145-fix-tests-with-ruby3.patch
0002-Improve-README.md.patch
$ quilt pop -a
Removing patch 0002-Improve-README.md.patch
Restoring README.md
Removing patch 996145-fix-tests-with-ruby3.patch
Restoring test/support/utils.rb
No patches applied
Agora os patches podem ser adicionados ao repositório git
em forma de commit. Usando esse fluxo de trabalho se torna menos necessário um conhecimento mais aprofundado de git
, entretanto, em alguns cenários usar git
pode facilitar bastante a sua vida