# Patching packages (简体中文)

From ArchWiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

相关文章

- Arch Build System

翻译状态：本文是 Patching_packages 的翻译。上次翻译日期：2021-03-30。如果英文版本有所更改，则您可以帮助同步翻译。

本文涵盖了如何在 Arch Build System (ABS) 中为软件包创建和应用补丁。

补丁 描述了一个或多个文件的行更改。补丁通常用于自动更改源代码。

## 创建补丁

注意： 如果你只是想要更改一两行，你可能会想使用 sed。

diff 工具逐行比较文件。将它的输出保存下来你就得到了一个补丁，如 `diff --unified --recursive --text foo bar > patch`， 如果你传递了目录， diff 会比较它们包含的文件。

1. 如果你已将构建了软件包，请删除 `src` 目录。
2. 运行 `makepkg --nobuild` 会下载并提取，但不会构建 `PKGBUILD` 中声明的源文件。如果你正在创建补丁的系统上没有必要的依赖，你可能需要运行 `makepkg --nobuild --nodeps` 作为替代。
3. 在 `src` 目录中创建两份提取的目录的副本，一个作为原始版本，一个作为你修改过的版本，将他们称为 `package.orig` 和 `package.new`。
4. 在 `package.new` 目录中进行你的更改。
5. 运行 `diff --unified --recursive --text package.orig package.new --color` 并检查补丁是否看起来良好。
6. 运行 `diff --unified --recursive --text package.orig package.new > package.patch` 来生成补丁。
7. 进入 `package.orig` 目录并使用 `patch --strip=1 < ../package.patch` 命令来应用补丁。运行 `makepkg --noextract --install` 命令构建并安装更改后的软件包来验证补丁是否正常工作。

注意： 你也可以使用 Git 的 `git diff` 命令或者 `git format-patch` 命令 [1]。

更多信息参见 diff(1) 和 git-diff(1)。

## 应用补丁

本节概述如何在 `PKGBUILD` 的 `prepare()` 函数中应用你创建或从网络下载的补丁。请遵循以下步骤：

1. 为补丁文件在 `PKGBUILD` 的 `source` 数组中添加一个条目，将该条目与原始源 url 之间用空格隔开。如果该文件可在网上获得，你可以提供完整的 URL ，它将被自动下载并放在 `src` 目录中。如果它是你自己创建的补丁，则应将补丁文件与 `PKGBUILD` 文件放在同一目录中，并只需将文件名添加到 `source` 数组中，以便将其复制到 `src` 目录中。如果你重新发布 `PKGBUILD`，你应该在 `PKGBUILD` 中包含补丁。
2. 然后使用 `makepkg -g >> PKGBUILD` 或者 `updpkgsums` (来自于 pacman-contrib) 来更新 `sha512sums` 数组。 或者手动添加一个条目到 `sha512sums` 数组； 你可以使用 sha512sum 工具来生成你的补丁的校验和。
3. 如果 `PKGBUILD` 还没有 `prepare()` 函数就创建它。
4. 第一步是进入到需要被打补丁的目录（在 `prepare()` 函数中，不是你的终端！你希望自动化打补丁这一过程）。 你也可以通过像 `cd "$srcdir/$pkgname-$pkgver"` 或者其他类似的命令来完成。 `$pkgname-$pkgver` 通常是解包一个下载源文件的目录名，但并不总是这样。
5. 现在你只需要从这个目录里面应用补丁。这可以通过添加 `patch --strip=1 --input=pkgname.patch` 到你的 `prepare()` 函数就能简单完成。 将 `pkgname.patch` 改成包含 diff 的文件的名字（因为在 `PKGBUILD` 的 `source` 数组中而被自动复制到 `src` 的文件）。

一个 prepare 函数示例：

    prepare() {
        cd "$pkgname-$pkgver"
        patch --forward --strip=1 --input="${srcdir}/eject.patch"
    }

从终端运行 `makepkg`， 如果一切顺利，补丁会被自动应用，并且你的新软件包会包含补丁中的更改。如果不是这样的话，你可能需要试验一下补丁的 `--strip` 选项。 在试验的时候，你会发现 `--dry-run`, `--reverse` 或者 `--verbose` 选项会有用。更多信息参见 patch(1)。

基本上它的工作原理如下。如果 diff 文件被创建来将补丁应用到 `myversion/` 中的文件，那么 diff 文件将被应用于 `myversion/file`。你正在 `yourversion/` 目录中运行它（因为你会 cd 到 `PKGBUILD` 中的目录），因此当补丁应用该文件时，你希望它将其应用到 `file` 文件，并从 `myversion/` 部分中取出。 `--strip=1` 通过从路径中删除一个目录来实现这一点。但是，如果开发者在 `myfiles/myversion` 中修补，则需要删除两个目录，因此你使用 `--strip=2`。

如果你不应用一个 `--strip` 选项，它将会去掉所有目录结构。如果所有文件都在基础目录中的时候是可以的。但是如果补丁是在 `myversion/` 上创建的，并且有一个被编辑的文件是 `myversion/src/file`，当你从 `yourversion` 目录以不带 `--strip` 参数的方式运行补丁的时候，它会尝试为一个名为 `yourversion/file` 的文件打补丁。

大多数开发者从被打补丁的目录的父目录创建补丁，因此 `--strip=1` 通常是正确的。

## 使用 quilt

一个更简单的创建补丁的方法是使用 quilt，它为管理许多补丁提供了更好的支持，例如应用补丁，刷新补丁和将打补丁的文件回退到原始状态。Debian 使用 quilt 来管理他们的补丁。quilt 生成和应用补丁、回退打补丁的文件的基本用法的基本信息可参考 使用 Quilt。

## 另见

- http://www.kegel.com/academy/opensource.html — 有关修补文件的有用信息

Category:

- Package management (简体中文)