Skip to content

Commit

Permalink
Merge pull request #261 from laraPPr/add_patch_instructions
Browse files Browse the repository at this point in the history
Add documentation how to create patches
  • Loading branch information
boegel authored Aug 16, 2024
2 parents 008f9d9 + b3c9449 commit 86db487
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 56 deletions.
109 changes: 109 additions & 0 deletions docs/patch-files.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# Patch files

## What are patch files (patches)?

A patch file, or just *patch* for short, is a text file that can be used to modify an existing software sources.
They are often used to fix bugs, but can also be used to improve the usability or performance.

## Including patches in an easyconfig file

Patches can be provided via the `patches` easyconfig parameter (list). A
patch can be defined as:

- a `string`,
- a `tuple` of 2 elements, or
- a `dict`

The most straight-forward use-case is `string`, which contains the name
of the patch file (and must have `.patch` extension).

A `tuple` adds the possibility to specify the subdirectory in which the patch should be applied.
This is mostly needed if a patch file adds new files or it is generally
not possible to determine the appropriate directory to apply the patch in.
The first element of this tuple is
the name of patch file. The second element is either the *patch level* (as an integer value)
which is used in the patch command (`patch -p<level>`), or a directory relative to the unpacked source directory.

!!! note
`tuple` also has a special use case if the patch file has any other extension than `.patch`.
In this case, the first tuple element is the name of a file which should be
copied to the unpacked source directory, and the second element is
the target path, where the files should be copied to (relative to
the unpacked source directory). See below for an example of this use case.

A `dict` value can be used pass additional arguments to the `patch` command.
For example, the `--binary` flag may be needed for patch files
with CRLF endings. For a `dict` value the `filename` key is required.
`level` and `opts` are supported (optional) keys.

!!! note
Specifying only `filename` in `dict` is the same as using a plain `string` definition.
Specifying `filename` and `level` is same as using a `tuple`
definition.

Example:

```python
patches = [
# a simple patch file
'example.patch',

# when creating only new files by patch file, you need to specify the level:
('example-add-files.patch', 1),

# apply the patch in a (sub-)subdirectory inside the source tree
('example-subfolder.patch', 'src/subfolder'),

# copy file to target_path folder
('Makefile', 'path/to/target/'),

# specify patch file and optionally level and opts for patch command
{'filename': 'example.patch', 'level': 1, 'opts': '--binary'}
]
```

## Creating a patch file

To create a patch file to use with EasyBuild, follow the steps below.

### 1) Copy unpacked sources

Start by copying the unpacked sources, before making any changes, so we can determine which changes were made:

```bash
cp -a unpacked_sources unpacked_sources.orig

```

### 2) Make necessary changes

Make the necessary changes in the `unpacked_sources` directory.

### 3) Create patch file

Create the patch file by comparing the original sources with the modified sources using the `diff` command:

```bash
diff -ruN unpacked_sources.orig unpacked_sources > example.patch
```

The `-ruN` options here are important:

- `r` instructs the `diff` command to look for changes between the specified directories *recursively*;
- `u` indicates that `diff` should produce a *unified* diff as output;
- `N` indicates that files only found in one directory should be treated as new files;

### 4) Add description, author, reference

Please also add a description on top of the patch file, along with the author and/or reference to the source of the patch.

For example:

```diff
example of a patch description
author: John Doe (Earth University)
diff -ru unpacked_sources.orig/example.c unpacked_sources/example.c
--- unpacked_sources.orig/example.c 2011-08-05 05:08:07.000000000 +0200
+++ unpacked_sources/example.c 2024-03-14 12:31:16.218067000 +0100
...
```
57 changes: 2 additions & 55 deletions docs/writing-easyconfig-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ Remarks:
- patches need to be EasyBuild-compatible
- unified diff format (`diff -ruN`)
- patched locations relative to unpacked sources
- see [Patches][common_easyconfig_param_sources_patches] for more information on `patches`
- for more information on `patches`, see [separate page on patch files](patch-files.md)
- see [Checksums][common_easyconfig_param_sources_checksums] for more information on `checksums`
- `sources` is usually specified as a list of strings representing
filenames for source files, but other formats are supported too, see
Expand Down Expand Up @@ -162,60 +162,7 @@ checksums = ['ac7534163a09e21a5fa763e4e16dfc119bc84043f6e6a807aba666518f8df440']

#### Patches {: #common_easyconfig_param_sources_patches }

Patches can be provided via the `patches` easyconfig parameter (list). A
patch can be defined as:

- a `string`,
- a `tuple` of 2 elements, or
- a `dict`

The most straight-forward use-case is `string`, which contains the name
of the patch file (and must have `.patch` extension).

A `tuple` adds the possibility to specify where patch should be applied.
This is mostly needed if a patch file adds new files or it is generally
not possible to determine the starting directory. The first element is
the patch file and the second is either the patch level (as an integer)
which is used in the patch command (`patch -p<n>`) or a directory
relative to the unpacked source dir.

!!! note
`tuple` also has a special use case if the patch file has any other extension than `.patch`.
In this case, the first tuple argument is a file which should be
copied to the unpacked source dir and the second tuple argument is
the target path, where the files should be copied to (relative to
the unpacked source dir). See below for an example of this use case.

A `dict` adds the ability to pass the `patch` command additional
arguments. For example, the `--binary` flag is needed to patch files
with CRLF endings. The `dict` has a required `filename` key, with
`level` and `opts` being optional ones.

!!! note
Specifying only `filename` in `dict` is the same as using a plain `string` definition.
Specifying `filename` and `level` is same as using a `tuple`
definition.

Example:

``` python
patches = [
# a simple patch file
'name-versions-fix.patch',

# when creating only new files by patch file, you need to specify the level:
('name-versions-fix.patch', 1),

# apply the patch in a (sub-)subdirectory inside the source tree
('name-versions-fix.patch', 'src/subfolder'),

# copy file to target_path folder
('Makefile', 'target_path'),

# specify patch file and optionally level and opts for patch command
{'filename': 'name-versions-fix.patch', 'level': 1, 'opts': '-l'}
]
```
See [separate page dedicated to creating and using patch files](patch-files.md).

#### Checksums {: #common_easyconfig_param_sources_checksums }

Expand Down
3 changes: 2 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,9 @@ nav:
- GitHub integration: integration-with-github.md
- Implementing easyblocks: implementing-easyblocks.md
- Local variables in easyconfigs: easyconfig-files-local-variables.md
- Patch files: patch-files.md
- Unit tests: unit-tests.md
- Framework Overview: framework-overview.md
- Framework overview: framework-overview.md
- Experimental features:
- (overview): experimental-features.md
- Creating container images/recipes: containers.md
Expand Down

0 comments on commit 86db487

Please sign in to comment.