DEV Community

Cover image for How to patch a package in Arch Linux
Axel Navarro for Cloud(x);

Posted on

How to patch a package in Arch Linux

This is the second entry on the series on how to create your homemade Arch Linux packages

How to patch code

The patch is an ancient Linux command to apply changes to files (text or binary), and it's commonly used by a Linux distribution to apply emergency security patches or a bug fix to a package.

Sometimes the developers have a fixed release schedule, like KDE, and the package maintainers of each Linux distribution should deliver fixes patching the latest official version (based on a git tag) in their Linux distribution.

You can apply changes to config files in your using:

patch dnscrypt-proxy.toml < dnscrypt-proxy.toml.patch

or, you can add patches in a PKGBUILD file using the prepare function, like this:

prepare() {
  # Fix crash on right-click with Qt 5.15
  patch -d "$pkgname-$pkgver" -p1 -i ../kdebug-419526.patch
}

Jackie Chan WHAT?!

Don't worry, we're going to talk about this later...

Where I can get patches?

There are two basic ways to get patch files.

The diff command

If we use an app with config files like the dnscrypt-proxy, we can clone the built-in /etc/dnscrypt-proxy/dnscrypt-proxy.toml config file into my-dnsproxy.toml:

cp dnscrypt-proxy.toml my-dnsproxy.toml

After editing my-dnsproxy.toml, I can generate a "diff" file, so I can reapply my changes, maybe for back up, or distribute custom preferences.

diff dnscrypt-proxy.toml my-dnscrypt.toml > dnscrypt-proxy.toml.patch

Now, I can use my home made patch:

patch dnscrypt-proxy.toml < dnscrypt-proxy.toml.patch

The git way

Developers use git, or some version control system, and the main platforms have an easy way to download commits with a patch compatible format.

In the previous post, I was stuck with a bug in the Konsole app, and the fix to that bug was my first contribution to KDE! 💙

Success kid

This is the approved fix: https://invent.kde.org/utilities/konsole/-/commit/0c3240a1. 😃

If you add the .diff extension to the end of the URL you will get a "diff" that can be used by the patch command to apply the fix to the source code.

https://invent.kde.org/utilities/konsole/-/commit/0c3240a1.diff

Or, if you add .patch to the URL you will get the same "diff" including git metadata: the commit SHA, the message, author and timestamp.

https://invent.kde.org/utilities/konsole/-/commit/0c3240a1.patch

or, in GitHub: https://github.com/KDE/konsole/commit/0c3240a1.patch.

You can use the first 8 chars of the commit SHA, or any length that you want, even the full SHA value. In GitHub you should use at least the first 4 chars, in GitLab it's 7. But if the platform found more than 1 commit that matches your URL you will get a 404 response.

How to patch a package

So, based on my PKGBUILD from my previous post, I can add my bug fix to my home made compilation:

pkgname=konsole
pkgver=20.04.0
pkgrel=1
arch=(x86_64)
url='https://kde.org/applications/system/konsole/'
pkgdesc="KDE's terminal emulator"
license=(GPL LGPL FDL)
groups=(kde-applications kdebase)
depends=(knotifyconfig kpty kparts kinit knewstuff)
makedepends=(extra-cmake-modules kdoctools)
optdepends=('keditbookmarks: to manage bookmarks')
source=("https://download.kde.org/stable/release-service/$pkgver/src/$pkgname-$pkgver.tar.xz"
"https://invent.kde.org/utilities/konsole/-/commit/0c3240a1.patch")
sha256sums=('SKIP' 'SKIP')

prepare() {
  # Add my patch to Konsole 20.04
  patch -d "$pkgname-$pkgver" -p1 -i ../0c3240a1.patch
  mkdir -p build
}

build() {
  cd build
  cmake ../$pkgname-$pkgver \
    -DBUILD_TESTING=OFF
  make
}

package() {
  cd build
  make DESTDIR="$pkgdir" install
}

The first step is adding your patch URL in the source variable, if you add a source, you should add a checksum in sha256sums, for this example we can use SKIP.

source=(... "https://invent.kde.org/utilities/konsole/-/commit/0c3240a1.patch")
sha256sums=('SKIP' 'SKIP')

The second step is to apply the patch to the source code:

patch -d $pkgname-$pkgver -p1 -i ../0c3240a1.patch

We need to use -d or --directory to apply the patch to a specific folder, in this example konsole-20.04.0.

The -i or --input is to use a patch file instead of the stdin. Remember that the prepare function runs over the src folder, we should rescue the patch from the parent folder using ../.

The -p1 is a little tricky. Instructs the command to strip N number of slashes from the path to the filename. We use -p1 to strip konsole-20.04.0 away.

End of Post

We learned what the diff and patch commands are, how we can back up our editions to config files using diff. How we can download patches from our repositories and an easy way to apply changes automatically to the source code without human intervention.

Discussion (0)