openSUSE:Packaging Patches guidelines

Jump to: navigation, search
Packagers deal with lots of packages, and lots of patches inside those packages. These need to be marked in the .spec files with a well-known format to be able to run automatic tools on them, in order to generate reports, patch counts and other interesting information. They also need to be named consistently.

Patch life cycle

Patches need to be added to packages for various reasons and it is important that the life cycle of a patch is well-defined. This helps in preventing that patches get "lost" and nobody knows why and when it was removed. The life cycle is defined in these simple steps:

  • Patch added to the package
  • Patch backported to the package
  • Patch is modified (functional/rebased)
  • Patch is disabled (but not deleted)
  • Patch removed from the package

The middle stages of the patch life cycle are optional and not every patch will live through them.

Any of those stages needs to be mentioned in the .changes file, including the file name of the patch. This is only for the benefit of human readers, so does not need to be in a strict machine-parseable format; here are some examples of the suggested format:

  • Add package-awesomeness.patch: Makes package awesome
  • Backport package-awesomeness.patch: From upstream to openSUSE, to fix a CVE or add a new feature.
  • Rebase package-awesomeness.patch: to apply to the new version.
  • Modify package-awesomeness.patch: to fix a imported bug or improve the original solution.
  • Disable package-awesomeness.patch: Testing if users can live without awesomeness
  • Drop package-awesomeness.patch: Upstream made it even more awesome.

Upstream policy

For the purpose of defining the upstream policy, we can divide patches into two categories:

  • upstream - upstream probably will be interested in it
  • openSUSE/SLE specific - upstream won't be interested in it

Policy for upstream patches

If you want to add a patch that can be interesting for upstream, please note that this patch must always be sent upstream. This is the only way to ensure that our fixes will be integrated upstream and we can get rid of these patches within the next upstream release. A significant advantage is also that upstream can provide you with sanity checking and a valuable feedback regarding your patch.

When to send the patch to upstream

Usually, it's useful to contact upstream before you submit the patch to OBS. You save yourself from resubmitting the patch if upstream finds an error in it. Also, some of the package maintainers may request this "upstream first" policy before such patch is to be considered for inclusion in the OBS package. Usually, there should be a mention about "upstream first" policy in the specfile of those packages (e. g. SuSEfirewall). However, sometimes upstream is not active enough and sending them the patch after you submit it to OBS is the only reasonable way.

How to find upstream

You have to dig. A good start is to check 'Url' or 'Source' tags in the specfile and visit the upstream website. Then you have to find a way upstream prefers for sending patches. It could be e. g. mail, mailing list, Bugzilla, git, ...

Policy for openSUSE/SLE specific patches

Usually, we try to add patches that can be merged upstream. However, it can happen that our package is different from the upstream and a specific patch is the only solution. Then please note that every openSUSE/SLE specific patch should be documented properly with a justification why this specific fix is needed.

Patch markup (also called "Tagging patches")

To facilitate the use of automatic tools (some day), and to help inform future packagers about the patch nature, the following categories for our patches exist:

  • Fixes: these are normal fixes and are divided into three categories:
    • Fixes for openSUSE-specific things, that upstream maintainers will not be interested in.
    • Fixes for SLE-specific things, that upstream maintainers will not be interested in and that are not needed in openSUSE.
    • Fixes for the upstream sources that should be upstreamed.
  • Features: new features added to the packages, also divided into three categories:
    • Features for openSUSE-specific things (switching the displaymanager via /etc/sysconfig, for instance) with no interest for upstream maintainers.
    • Features for SLE-specific things with no interest for upstream maintainers or openSUSE.
    • Features that should be upstreamed. Whenever we write this kind of new feature, it is important to coordinate with upstream maintainers. That way, we can develop something that will be accepted upstream without changes. Once a feature is finished, it is a lot of work to rework it to be acceptable to upstream maintainers. As such, it is better to know from the beginning exactly what upstream maintainers would expect.

There are two standards for this.

Type 1: minimal single-line comment in spec file

The minimal format consists of a comment line above a Patch: line, containing the patch category (see above), a (redundant) copy of the filename, and the rest of the line is a free-format string. Since a single line does not leave much room for words or other metadata, check also Type 2 below.

Type 1 format example:

# PATCH-FIX-OPENSUSE fix-for-opensuse-specific-things.patch bsc#123456
Patch1: fix-for-opensuse-specific-things.patch
# PATCH-FIX-SLE fix-for-sle-specific-things.patch bsc#123456
Patch2: fix-for-sle-specific-things.patch
# PATCH-FIX-UPSTREAM fix-for-upstream-sources.patch bsc#123456
Patch3: fix-for-upstream-sources.patch
# PATCH-FEATURE-OPENSUSE feature-for-opensuse-specific-things.patch bsc#123456
Patch4: feature-for-opensuse-specific-things.patch
# PATCH-FEATURE-SLE feature-for-sle-specific-things.patch bsc#123456
Patch5: feature-for-sle-specific-things.patch
# PATCH-FEATURE-UPSTREAM feature-for-upstream.patch bsc#123456
Patch6: feature-for-upstream.patch
# PATCH-FIX-UPSTREAM fix-wayland-compatibility.patch -- based on commit abc123
Patch7: https://github.com/example/project/commit/abc123.patch
# PATCH-FIX-UPSTREAM fix-wayland-compatibility.patch -- based on PR 123
Patch8: https://github.com/example/project/pull/132.patch

and later in the %prep section

%autopatch -p1 ...

or if not all patches are applicable with -p1

[...]
%patch -P 1 -P 2 -P 3 -P 5 -p1
%patch -P 6 -p0
%patch -P 7 -p2

Special case when using %patch: We often have patches that are temporarily commented out because they are not applicable to the latest sources, and the patches need to be rebased. Do not comment out the patch's declaration, but do comment out its application. When marking a patch as needing a rebase, it is a good idea to preserve its old tag.

# PATCH-NEEDS-REBASE old-patch.patch bsc#123456 -- Does something old. Was: PATCH-FEATURE-OPENSUSE
Patch7: old-patch.patch
[...]
# %patch -P 7

Finally, we include e-mail addresses so that it will be easier to figure out who wrote a patch if we have questions later, and free-form comments after " -- ".

That is:

# PATCH-{FIX|FEATURE}-{OPENSUSE|SLE|UPSTREAM} name-of-file.patch bsc#[0-9]+ you@example.com -- this patch makes things totally awesome

If there are related bugs in SUSE or other bugzillas, please add them, it will help us to get more accurate information. If there are two or more available then it's preferable to list both (or more).

In general, the bugzilla field is not required on new patches. For patches to released packages that will go out as updates, a bugzilla entry (BSC#) for the overall update in the changes file is required. If appropriate, the patch description should also include it.

The primary use case of the patch field should be references to upstream bug trackers in case of PATCH-*-UPSTREAM patches, such patches should be submitted upstream first and then referenced in the patch tag (best including a URL). That helps a lot to keep track of patches, it makes it easy to determine which patches are still needed on version updates if upstream references the bug numbers in their changelog or release notes. Of course if there is already a corresponding bsc# bug open it should be referenced as well.

You can find the current set of abbreviations at the end of this document. We can also define more abbreviations later if and when they prove necessary.

Some patches fix bugs that are not explicitly recorded anywhere. The right thing to do in this case requires some judgment on the part of the packager, but here are some ideas:

  • If a release is imminent, create a bug for it. This is usually a requirement, and even if it were not, it is still the right thing to do.
  • If a release is a long way off and the bug has already been fixed upstream, note in the comment that it is already fixed in the SVN (or wherever) and the patch will go away when we next upgrade.

Type 2: Complete Information provided in patch

The Type 1 standard lacks the most important part of a patch: a useful description why it is needed or desired in the first place, its single line format is seldomly enough to convey all the desirable information, and the state of the patch (upstream or opensuse-specific, fix or feature, etc.) is cut off from the actual patch.

The patches in the openSUSE kernel packages have traditionally used a form of tagging where metadata is directly attached to where it is needed — in the patch file itself. This facilitates submission of patches to upstream, as the description cannot be accidentally omitted, and the Git SCM (where used) knows to retain the metadata on import. Conversely, extraction of patches from Git repos also yields single files.

Patch files are to follow a scheme of "key: value" pairs and a description, optionally with a diffstat, prepended to the actual hunks. Example.

From: Random J Developer <email@example.org>
Date: 2012-07-28 01:28:22 +0200
Subject: input: add Acer Aspire 5710 to nomux blacklist
References: bnc#404881
Upstream: submitted

Acer Aspire needs to be added to nomux blacklist, otherwise the touchpad misbehaves.

---
 drivers/input/serio/i8042-x86ia64io.h |    7 +++++++
 1 file changed, 7 insertions(+)

--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -371,6 +371,13 @@ static const struct dmi_system_id __init
[...]

Use git format-patch -1 to get the patch file for the last commit. You need to add the missing keys (Subject, References, Upstream) manually.

It is advised to use e.g. Quilt which retains descriptions on refresh. quilt ref --sort --diffstat -p1 creates/refreshes such patches, sorted, with a diffstat and in the wanted -p1 format.
Common fields encountered:

  • From: shall specify the e-mail address of the original author of the patch.
  • Date: when this patch was first created. Preferably an ISO-8601 timestamp with timezone. If a new patch was just created and has none, you can use `stat your.patch` to determine a timestamp.
  • References: links to mailing list posts, bugzillas, etc. No fixed format, though URLs are preferred for they are easy to copy&paste into the browser. See the below section “#Current set of abbreviations” for details.
  • Upstream: the disposition of the patch. No fixed format, though common options are “never”/“no” (openSUSE-specific), “to be done” (tbd), “sent”/“submitted” (sent to upstream developers; provide Reference if possible), “merged” (upstream has accepted it; provide Reference if possible) and “dead” (no activity in upstream project).
  • Subject: A short one-line summary of the patch.

Patches are to provide a description. The description shall describe _why_ it is needed. Be as thorough as you like, because it will influence the decision what a different developer should do with the patch should it not apply anymore. The three questions “what command did you execute?”, “what did you observe?”, “what did you expect to see instead?” can give some guidance. If a related error message is available, e.g. when creating a patch to fix a syntactical error in a source file that causes the compilation to abort, it should be included, trimmed to the important parts. Furthermore, a summary on the how the solution is implemented can help readers grok larger patches.

Reading material (from the mailing lists) that shows the need for this kind of tagging: (1) (2) (3)

When using this format it is recommended to also supply a short type 1 style tagging which makes it easier to review patch status without the need to check each patch file individually.

Patch naming

All new patches should end with the extension '.patch'.

Whether a patch's name should start with the name of the package it applies to is a matter of debate or style. When in doubt, follow the convention used in the package you are hacking on.

Do NOT use %{version} macro in Patch: line, specify the version by hand. Using the macro:

  • causes lots of renames on version update
  • makes it easy to overlook patches that are no longer needed
  • makes it hard to determine when the patch was touch for the last time
  • makes it easy to find out when the patch broke (package archaeology)

An exception to this exists: patches that fix warnings that the compiler emits due to bogus code are frequently named abuild.patch.

The preferred patchlevel is -p1 as it makes importing using tools like quilt more straightforward.


Current set of abbreviations

To avoid confusion and double burden, referencing to other issue trackers is allowed. Here are some shortcuts for often used issue trackers, which should be added before the "#" of the issue id. Note there is no white space between the shortcut and the issue id.

NOTE: this list is not authoritative, please check with the Open Build Service how they are defined there (osc api /issue_trackers). You can also request new trackers via the OBS github project.

Shortcut Issue-Tracker-URL Example
openSUSE Bug tracker http://bugzilla.opensuse.org/show_bug.cgi?id=123456 (boo#123456)
Boost https://svn.boost.org/trac/boost/ (boost#123456)
Clutter Project Bugzilla http://bugzilla.clutter-project.org/ (bco#123)
CPAN Public Bug Tracker http://rt.cpan.org/Public/ (RT#123456)
Debian http://bugs.debian.org/ (deb#123456)
Eclipse https://bugs.eclipse.org/bugs/ (beo#123456)
freedesktop.org (bugzilla) http://bugs.freedesktop.org/ (fdo#123456)
freedesktop.org (gitlab) https://gitlab.freedesktop.org/ (glfo#<project>/<repository>#123456)
GCC http://gcc.gnu.org/bugzilla/ (GCC#123456)
Github issue trackers https://github.com/ (gh#openSUSE/open-build-service#9395) gh#project/repository#issue
GNOME (obsolete bugzilla) https://bugzilla.gnome.org/ (bgo#123456)
GNOME (gitlab) https://gitlab.gnome.org/ (glgo#GNOME/<project_name>#issue) or (glgo#GNOME/<project_name>!merge_request)
ICCULUS http://bugzilla.icculus.org/ (bio#123456)
Kernel or K http://bugzilla.kernel.org/ (bko#123456)
KDE http://bugs.kde.org/ (kde#123456)
Launchpad (Ubuntu) https://bugs.launchpad.net/ (lp#123456)
MeeGo http://bugs.meego.com (MeeGo#123456)
Mozilla http://bugzilla.mozilla.org/ (bmo#123456)
Novell https://bugzilla.novell.com/ (bnc#123456)
SUSE bugs https://bugzilla.suse.com/ (bsc#123456)
OpenLDAP http://www.openldap.org/its/ (ITS#123456)
OpenOffice.org Issuezilla (obsolete) http://qa.openoffice.org/issues/ (i#123456)
Fate (Feature tracking tool) https://fate.suse.com (fate#123456)
RedHat https://bugzilla.redhat.com/ (rh#123456)
Samba https://bugzilla.samba.org/ (bso#123456)
Sourceforge http://sf.net/support/tracker.php?aid=1234567 (sf#1234567); number is in the "aid=" part in an URL
Xamarin http://bugzilla.xamarin.com/ (bxc#4321)
CVE entries (please add the number, even if there is an additional bugzilla for it) http://cve.mitre.org (CVE-2009-0067)
Xfce https://bugzilla.xfce.org/ (bxo#123456)
OBS GitHub Issues https://api.github.com/repos/openSUSE/open-build-service/issues (obs#123)
OBS build script Issues https://api.github.com/repos/openSUSE/obs-build/issues (build#123)
OBS CLI Issues https://api.github.com/repos/openSUSE/osc/issues (osc#123)
Progress openSUSE issue https://progress.opensuse.org/issues (poo#123)
Linux Foundation https://developerbugs.linux-foundation.org/ (lf#1234)
SUSE SLE features (epic id should be always used, not dev task id) https://jira.suse.com/ (jsc#SLE-1234)
openSUSE Pagure https://code.opensuse.org/ (coo#leap/features#123) coo#<project_name>#issue or alternatively code-o-o#<project_name>#issue

For other issue ids, please use the full URL to the corresponding issue tracker at the beginning of the patch file. For example:

See also