Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dev-docs: document patching conventions #742

Merged
merged 1 commit into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions dev-docs/patches.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# Working with patches

## Patches in Nix

There are two common ways to apply patches in Nix:

- Use the `patches` attribute of a builder ([manual](https://nixos.org/manual/nixpkgs/unstable/#var-stdenv-patches)):

```nix
stdenv.mkDerivation {
# ...
patches = [
./0001-first-change.patch
./0002-another-change.patch
]
# ...
}
```
This is most commonly used and can be encountered nearly everywhere upstream in nixpkgs.

- Use the `applyPatches` function ([noogle](https://noogle.dev/f/pkgs/applyPatches)) to patch an existing source and derive a new source:

```nix
stdenv.mkDerivation {
# ...
src = applyPatches {
src = fetchFromGuiHub { /* ... */ }
patches = [
./0001-first-change.patch
./0002-another-change.patch
]
# ...
}
```

This is useful in situations where the patches sources should also be used by other consumers, as the
patched source can inherited, but `patches` aren't part of the output set.

Patches can either be consumed from a local file or pulled from remote:

```nix
patches = [
(fetchpatch {
url = "https://github.com/...";
stripLen = 2; # Sometimes the patch strip level must be configured
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
})
];
```

If there aren't any changes needed to an upstream patch, it's good practice to fetch the patch from remote.
The patch should come from a stable ref in this case, like from a persistent upstream branch or an open pull request.
If the changes to upstream patches are needed or patches aren't available upstream, the
*full patch set* should be vendored (don't mix `fetchpatch` and local patches on the same target), so it can easily be worked with.

## Patch set development flow

For a smooth development experience, we only use `git format-patch` format for patches. This enables us
to apply the changes to the source, work on it and sync back.

Given a package with some existing patches in `pkgDir` (for example `packages/by-name/contrast`).

Clone the source and checkout the `rev` currently used in the package `src` (the commit or tag):

```sh
git clone $url
git checkout $rev
```

Apply the existing patch set:

```sh
git am -3 $pkgDir/*.patch
```

This will apply and commit each patch on top of `rev`.

You can then place new commits on top or modify existing commits. Remember to keep the git history clean.

When updating a package, you might need to rebase the current patch set.

When done, recreate the patch set:

```sh
git format-patch -o $pkgDir $rev
```

# Patch documentation conventions

Patches need thorough documentation. Each reference of a patch must have a comment:

```nix
patches = [
# Document things about the patch here
./0001-first-change.patch
]
```

Notice that this is in addition to writing a sensible commit message in case you create
a commit specifically for a patch. In many cases, commit message of a patch will come from
original patch author, so all the meta goes where the patch is referenced.

The comment should answer the following questions:

- Why is the patch needed?
- Is the patch already merged? -> Make a note that the patch can be removed on next update.
- Is the patch part of an open upstream PR? -> Link to the upstream PR.
- If it's an upstream patch, was the patch modified? If yes, what was changed and why?
- If the patch has no upstream PR, why can't we upstream the change?
4 changes: 4 additions & 0 deletions tools/vale/styles/config/vocabularies/edgeless/accept.txt
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,7 @@ WireGuard
Xeon
xsltproc
Zipkin
vendored
noogle
nixpkgs
rebase