Patching packages: Difference between revisions
(→Applying patches: add example with --directory for patch) |
(→Applying patches: add style flag) |
||
(14 intermediate revisions by 9 users not shown) | |||
Line 4: | Line 4: | ||
[[zh-hans:Patching packages]] | [[zh-hans:Patching packages]] | ||
{{Related articles start}} | {{Related articles start}} | ||
{{Related|Arch | {{Related|Arch build system}} | ||
{{Related articles end}} | {{Related articles end}} | ||
This article covers how to create and how to apply patches to packages in the [[Arch | This article covers how to create and how to apply patches to packages in the [[Arch build system]] (ABS). | ||
A [[Wikipedia:Patch (computing)|patch]] describes a set of line changes for one or multiple files. Patches are typically used to automate the changing of source code. | A [[Wikipedia:Patch (computing)|patch]] describes a set of line changes for one or multiple files. Patches are typically used to automate the changing of source code. | ||
Line 15: | Line 15: | ||
{{Note|If you only need to change one or two lines, you might want to use [[sed]] instead.}} | {{Note|If you only need to change one or two lines, you might want to use [[sed]] instead.}} | ||
The ''diff'' tool compares files line by line. If you save its output you have | The ''diff'' tool compares files line by line. If you save its output you have a patch, e.g. {{ic|diff --unified --recursive --text foo bar > foobar.patch}}. If you pass directories ''diff'' will compare the files they contain. | ||
# Delete the {{ic|src}} directory if you have already built the package. | # Delete the {{ic|src}} directory if you have already built the package. | ||
Line 23: | Line 23: | ||
# Run {{ic|diff --unified --recursive --text package.orig package.new --color}} and check if the patch looks good. | # Run {{ic|diff --unified --recursive --text package.orig package.new --color}} and check if the patch looks good. | ||
# Run {{ic|diff --unified --recursive --text package.orig package.new > package.patch}} to create the patch. | # Run {{ic|diff --unified --recursive --text package.orig package.new > package.patch}} to create the patch. | ||
# Change into the {{ic|package.orig}} directory and apply the patch using {{ic|1= patch --strip=1 < ../package.patch}}. Verify that the patch is working by building and installing the modified package with {{ic|makepkg --noextract --install}}. | # Change into the initial {{ic|package.orig}} directory from which you made copies and apply the patch using {{ic|1= patch --strip=1 < ../package.patch}}. Verify that the patch is working by building and installing the modified package with {{ic|makepkg --noextract --install}}. | ||
{{Note|You can also create patches with [[Git]] using {{ic|git diff}} or {{ic|git format-patch}} [https://stackoverflow.com/questions/6658313/generate-a-git-patch-for-a-specific-commit].}} | {{Note|You can also create patches with [[Git]] using {{ic|git diff}} or {{ic|git format-patch}} [https://stackoverflow.com/questions/6658313/generate-a-git-patch-for-a-specific-commit].}} | ||
See {{man|1|diff}} and {{man|1|git-diff}} for more info. | See {{man|1|diff}} and {{man|1|git-diff}} for more info. | ||
{{Tip| Most git hosting platforms (such as GitHub or GitLab) allow to generate patches for a specific commit or a specific merge/pull request by appending {{ic|.patch}} to their URL.}} | |||
== Applying patches == | == Applying patches == | ||
{{Style|1=Showing long options is not practical, 99% of the real PKGBUILDs use short options like {{ic|patch -d $pkgname-$pkgver -Np1 -i ../eject.patch}}. These were on this page [https://wiki.archlinux.org/index.php?title=Patching_packages&diff=prev&oldid=567733 before 2019].}} | |||
This section outlines how to apply patches you created or downloaded from the Internet from within a {{ic|PKGBUILD}}'s {{ic|prepare()}} function. Follow these steps: | This section outlines how to apply patches you created or downloaded from the Internet from within a {{ic|PKGBUILD}}'s {{ic|prepare()}} function. Follow these steps: | ||
Line 36: | Line 40: | ||
# Then use {{ic|makepkg -g >> PKGBUILD}} or {{ic|updpkgsums}} (from {{Pkg|pacman-contrib}}) to update the {{ic|sha512sums}} array. Or manually add an entry to the {{ic|sha512sums}} array; you can generate the sum of your patch using ''sha512sum'' tool. | # Then use {{ic|makepkg -g >> PKGBUILD}} or {{ic|updpkgsums}} (from {{Pkg|pacman-contrib}}) to update the {{ic|sha512sums}} array. Or manually add an entry to the {{ic|sha512sums}} array; you can generate the sum of your patch using ''sha512sum'' tool. | ||
# Create the {{ic|prepare()}} function in the {{ic|PKGBUILD}} if one is not already present. | # Create the {{ic|prepare()}} function in the {{ic|PKGBUILD}} if one is not already present. | ||
# The first step is to change into the directory that needs to be patched (in the {{ic|prepare()}} function, not on your terminal! You want to automate the process of applying the patch). You can do this with something like {{ic|cd | # The first step is to change into the directory that needs to be patched (in the {{ic|prepare()}} function, not on your terminal! You want to automate the process of applying the patch). You can do this with something like {{ic|cd $pkgname-$pkgver}}. {{ic|$pkgname-$pkgver}} is often the name of a directory created by untarring a downloaded source file, but not in all cases. | ||
# Now you simply need to apply the patch from within this directory. This is very simply done by adding {{ic|1= patch --strip=1 --input=''pkgname''.patch}} to your {{ic|prepare()}} function, changing {{ic|''pkgname''.patch}} to the name of the file containing the diff (the file that was automatically copied into your {{ic|src}} directory because it was in the {{ic|source}} array of the {{ic|PKGBUILD}} file). | # Now you simply need to apply the patch from within this directory. This is very simply done by adding {{ic|1= patch --strip=1 --input=''pkgname''.patch}} to your {{ic|prepare()}} function, changing {{ic|''pkgname''.patch}} to the name of the file containing the diff (the file that was automatically copied into your {{ic|src}} directory because it was in the {{ic|source}} array of the {{ic|PKGBUILD}} file). | ||
Line 43: | Line 47: | ||
{{bc|1= | {{bc|1= | ||
prepare() { | prepare() { | ||
cd | cd $pkgname-$pkgver | ||
patch --forward --strip=1 --input= | patch --forward --strip=1 --input=../eject.patch | ||
} | } | ||
}} | }} | ||
Line 52: | Line 56: | ||
{{bc|1= | {{bc|1= | ||
prepare() { | prepare() { | ||
patch --directory= | patch --directory=$pkgname-$pkgver --forward --strip=1 --input=../eject.patch | ||
} | } | ||
}} | }} |
Latest revision as of 05:56, 18 April 2024
This article covers how to create and how to apply patches to packages in the Arch build system (ABS).
A patch describes a set of line changes for one or multiple files. Patches are typically used to automate the changing of source code.
Creating patches
The diff tool compares files line by line. If you save its output you have a patch, e.g. diff --unified --recursive --text foo bar > foobar.patch
. If you pass directories diff will compare the files they contain.
- Delete the
src
directory if you have already built the package. - Run
makepkg --nobuild
which will download and extract the source files, specified inPKGBUILD
, but not build them. If the system you are making the patch on does not have the required dependencies, you may have to runmakepkg --nobuild --nodeps
instead. - Create two copies of the extracted directory in the
src
directory, one as a pristine copy and one for your altered version. We will call thempackage.orig
andpackage.new
. - Make your changes in the
package.new
directory. - Run
diff --unified --recursive --text package.orig package.new --color
and check if the patch looks good. - Run
diff --unified --recursive --text package.orig package.new > package.patch
to create the patch. - Change into the initial
package.orig
directory from which you made copies and apply the patch usingpatch --strip=1 < ../package.patch
. Verify that the patch is working by building and installing the modified package withmakepkg --noextract --install
.
See diff(1) and git-diff(1) for more info.
.patch
to their URL.Applying patches
This section outlines how to apply patches you created or downloaded from the Internet from within a PKGBUILD
's prepare()
function. Follow these steps:
- Add an entry to the
source
array of thePKGBUILD
for the patch file, separated from the original source url by a space. If the file is available online, you can provide the full URL and it will automatically be downloaded and placed in thesrc
directory. If it is a patch you created yourself, or is otherwise not available, you should place the patch file in the same directory as thePKGBUILD
file, and just add the name of the file to the source array so that it is copied into thesrc
directory. If you redistribute thePKGBUILD
, you should, of course, include the patch with thePKGBUILD
. - Then use
makepkg -g >> PKGBUILD
orupdpkgsums
(from pacman-contrib) to update thesha512sums
array. Or manually add an entry to thesha512sums
array; you can generate the sum of your patch using sha512sum tool. - Create the
prepare()
function in thePKGBUILD
if one is not already present. - The first step is to change into the directory that needs to be patched (in the
prepare()
function, not on your terminal! You want to automate the process of applying the patch). You can do this with something likecd $pkgname-$pkgver
.$pkgname-$pkgver
is often the name of a directory created by untarring a downloaded source file, but not in all cases. - Now you simply need to apply the patch from within this directory. This is very simply done by adding
patch --strip=1 --input=pkgname.patch
to yourprepare()
function, changingpkgname.patch
to the name of the file containing the diff (the file that was automatically copied into yoursrc
directory because it was in thesource
array of thePKGBUILD
file).
An example prepare-function:
prepare() { cd $pkgname-$pkgver patch --forward --strip=1 --input=../eject.patch }
Alternatively, you can use the --directory
flag of patch
without having to cd first. The example above would then become:
prepare() { patch --directory=$pkgname-$pkgver --forward --strip=1 --input=../eject.patch }
Run makepkg
(from the terminal now). If all goes well, the patch will be automatically applied, and your new package will contain whatever changes were included in the patch. If not, you may have to experiment with the --strip
option of patch. While experimenting, you might find --dry-run
, --reverse
or --verbose
options usable. Read patch(1) for more information.
Basically it works as follows. If the diff file was created to apply patches to files in myversion/
, the diff files will be applied to myversion/file
. You are running it from within the yourversion/
directory (because you would cd into that directory in the PKGBUILD
), so when patch applies the file, you want it to apply it to the file file
, taking off the myversion/
part. --strip=1
does this, by removing one directory from the path. However, if the developer patched in myfiles/myversion
, you need to remove two directories, so you use --strip=2
.
If you do not apply a --strip
option, it will take off all directory structure. This is OK if all the files are in the base directory, but if the patch was created on myversion/
and one of the edited files was myversion/src/file
, and you run the patch without a --strip
option from within yourversion
, it will try to patch a file named yourversion/file
.
Most developers create patches from the parent directory of the directory that is being patched, so --strip=1
will usually be right.
Using quilt
A simpler way to create patches is using quilt which provides better support for managing many patches, such as applying patches, refreshing patches, and reverting patched files to original state. quilt is used on Debian to manage their patches. See Using Quilt for basic information about basic quilt usage to generate, apply patches, and reverting patched files.
See also
- http://www.kegel.com/academy/opensource.html — Useful information on patching files