How to patch a package in Arch Linux
Tags: archlinux, linux, git, github
Published: 2020-07-27 12:33:49

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](https://community.kde.org/Schedules), 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:

```bash
patch dnscrypt-proxy.toml < dnscrypt-proxy.toml.patch
```

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

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

![Jackie Chan WHAT?!](https://dev-to-uploads.s3.amazonaws.com/i/vcm07a6nonjc4kpno5d6.jpg)

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`:

```bash
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.

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

Now, I can use my home made patch:

```bash
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](https://dev-to-uploads.s3.amazonaws.com/i/0k29fml6078tzbk5myyd.jpg)

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:

```bash
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`.

```bash
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:

```bash
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.