创建 Alpine 软件包

来自 Alpine Linux

此页面记录了在 Alpine Linux 中创建和提交新软件包的步骤。

概述

这是在 Alpine Linux 中创建和提交新软件包的简要步骤列表。请参阅本 wiki 的其余部分以了解步骤的详细信息。

  1. https://gitlab.alpinelinux.org 上创建一个账户
  2. 设置构建环境.
  3. Fork aports 仓库克隆你的 fork
  4. 设置 git pull.rebase=true,配置你的 git 用户名和电子邮件
  5. 创建并切换到一个新分支(不要使用 master)。
  6. 在 testing 下添加一个新目录,作为你的新软件包名称。
  7. 添加你的 APKBUILD 文件。
  8. 运行 abuild checksum
  9. 确保你运行了 apkbuild-lint 和 aport -r,并且没有警告。
  10. 提交你的 APKBUILD,提交信息为:'testing/packagename: new aport'
  11. 将你的更改推送到你在 https://gitlab.alpinelinux.org/alpine 上的 fork。
  12. 创建一个合并请求。

要求

设置你的系统和账户 以在 Alpine Linux 中构建软件包。如果你还没有 Alpine Linux,请参考 设置构建环境

获取帮助

abuild 软件包提供了为 Alpine Linux 创建软件包所需的脚本。它实现了构建软件包的功能,以及用于软件包维护的附加命令和选项。明智的做法是从检查 abuild 程序可以/不能做什么开始。

abuild -h

如需实时帮助,你也可以访问 IRC 上的 #alpine-devel。

APKBUILD 文件的参考文档可以在 APKBUILD 参考 wiki 页面或 abuild-doc 软件包中的 man 页面中找到

man APKBUILD

创建 APKBUILD 文件

APKBUILD 示例 页面列出了许多 APKBUILD 示例,范围从 简单 APKBUILD子软件包 以及各种 应用程序特定示例。这些示例将帮助你理解如何创建 APKBUILD,并提供可在你自己的 APKBUILD 文件中使用的代码片段。

使用模板 APKBUILD

Alpine Linux 提供了以下工具来创建模板 APKBUILD 文件。

newapkbuild

newapkbuild 工具作为 abuild 软件包的一部分安装,可以生成一个新的 APKBUILD 模板作为起点。手册页(可通过 man newapkbuild 获得)描述了 newapkbuild 的所有选项。

如果你不确定你的软件包属于哪个仓库,你可以安全地使用 testing。在你的 aports/testing 目录中构建软件包不是强制性的,但这样软件包就已经在正确的位置了。

提示: 在选择 packagename 时,请遵循 软件包策略 中提到的软件包命名约定。

以下命令将创建一个以给定软件包名称命名的目录,在该目录中放置一个示例/模板 APKBUILD 文件,并在提供的情况下填充一些变量。

newapkbuild packagename

如果你正在创建一个需要 initd 脚本的守护程序软件包,你可以添加 -c 选项,如下所示

newapkbuild -c packagename

这将复制示例 initdconfd 文件到构建目录。第三个文件 sample.install 文件也将被复制(我们稍后会讨论这个)。

apkbuild-cpan

Comprehensive Perl Archive Network (CPAN) 提供了大量的 perl 软件和文档。apkbuild-cpan有助于为来自 CPAN 的 perl 模块创建 APKBUILD。

apkbuild-cpan [create <Module::Name> | check | recreate | update | upgrade]

此命令由 apkbuild-cpan 软件包提供。

apkbuild-pypi

Python Package Index (PyPi) 是 Python 编程语言的软件和库的仓库。apkbuild-pypi 命令有助于为托管在 PyPI 上的 python 软件包创建 APKBUILD。

apkbuild-pypi [create <package> | check | recreate | update | upgrade

此命令由 apkbuild-pypi 软件包提供。

修改你的 APKBUILD

编辑 APKBUILD 并填写所需信息(特别是 pkgname、pkgver、pkgdesc、url、license、depends 和 source)。

如果你要使用任何目录变量,如 $pkgdir,请始终确保它们用双引号括起来,例如

"$pkgdir"/somedir

这将防止将来出现空格/特殊字符问题。

注意: 如果你喜欢语法高亮,我们建议你安装 vim。我们已将 vim 设置为将 APKBUILD 文件识别为 bash 脚本,以便更容易阅读。

APKBUILD 变量/函数

source

source 变量不仅用于列出要获取的远程源文件,还用于列出 abuild 构建 apk 所需的本地文件。此类本地文件的示例包括:init.d 文件、conf.d 文件、install 文件(参见 install 变量)、补丁和所有其他必要文件。

以下是一些注意事项

  • 当你完成向 source 添加本地和/或远程文件后,你可以执行以下命令将它们的校验和添加到 APKBUILD 文件

abuild checksum

注意: 当稍后更新 source 的内容,或更新 source 中列出的文件时,你还必须使用相同的命令再次更新它们的校验和。
  • 当远程文件托管在 SourceForge 上时,最好指定 SourceForge 使用的特殊镜像链接
http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz
(或类似的,取决于软件包)。
  • 当 URI 中未指定远程文件名时(即,不以 '/software-1.0.tar.gz' 结尾),例如
http://oss.example.org/?get=software&ver=1.0
你必须将 '${pkgname}-${pkgver}.tar.gz::' 前置到协议,如下所示
source="${pkgname}-${pkgver}.tar.gz::http://oss.example.org/?get=software&ver=1.0"
这会导致文件保存为 software-1.0.tar.gz,abuild 可以使用它,而不是 ?get=software&ver=1.0,abuild 无法使用它。
  • 有些项目没有提供发布 tarball。请注意,某些 git 服务(gitweg、cgit、…?)不提供稳定的 tarball,因此当你将 source 指向类似这样的 tarball 时https://repo.or.cz/w/gitstats.git/snapshot/ad7efbb9399e60cee6cb217c6b47e604174a8093.tar.gz,那么你将遇到问题,因为在构建系统上下载时校验和会更改。这在 GitHub、GitLab 和其他体面的服务提供商上不是问题,它们提供稳定的 tarball。
  • abuild 当前支持以下用于远程文件检索的协议
    • http
    • https
    • ftp
  • abuild 当前支持以下存档类型/存档文件扩展名
    • .tar
    • .tar.gz / .tgz
    • .tar.bz2
    • .tar.lz(仅在 Alpine >=3.7 中)
    • .tar.lzma
    • .tar.xz
    • .zip

depends & makedepends

Depends 是软件包运行时需要的实际运行依赖项。Makedepends 仅在构建软件包时需要。如果你在 depends 中设置了一个软件包,则无需将其添加到 makedepends 中。找出软件包的 depends 和 makedepends 的最佳方法是 RTFM

不开玩笑,许多重要信息可以在软件包的 INSTALL 和 README 文件(或类似文件)中找到。另一种好方法是从源目录运行 ./configure --help,以查看完成配置而不会出错需要哪些选项。如果你还没有源目录,你可以使用以下命令创建一个

abuild unpack

运行 configure 还会显示你如何禁用此软件包的特定选项。例如,一个很好的例子是 "--disable-nls",它将禁用本地语言支持,因此不依赖于 gettext(libiconv、glib 等)。

Alpine 喜欢保持小巧,因此我们尝试尽可能多地禁用,而不会丢失太多功能。确切的禁用/启用选项由软件包构建者决定,但请尽量遵循 Alpine 的设计理念。

快速找出软件包的构建信息的简单方法是查看 Arch Linux(Alpine 软件包管理和构建脚本类似)或 Gentoo Linux ebuilds(Alpine 的早期版本基于 Gentoo)。

license

license 标签必须反映源代码的许可证。请检查源 tarball 中是否有 COPYING、LICENSE 或其他名称表明它包含许可信息的文件。除了许可证文件外,大多数开发者还在源代码文件中包含带有许可详细信息的标头。

如果许可证在 SPDX 许可证列表SPDX 许可证例外 中,请使用 SPDX 指定的标识符。

请注意,某些许可证有应遵守的附加要求。例如,MIT 许可证有以下要求

上述版权声明和此许可声明(包括下一段)应包含在软件的所有副本或主要部分中。

这意味着我们需要包含项目附带的许可证。

需要此操作的已知许可证

  • MIT
  • ISC

如果软件包具有特殊/自定义许可证或未列为 OSI 批准,请使用标识符 "custom"。在这种情况下,我们也需要提供软件包的许可证文件。

因为我们想节省空间并且不喜欢我们的系统到处都是许可证,所以我们决定将许可证包含在 doc 子软件包中。请按照以下指南添加正确的许可证。找到源软件包内的许可证文件。将 doc 子软件包添加到 $subpackages 变量,如下所示

subpackages="$pkgname-doc"

根据许可证描述文件,将以下类似行添加到你的 package() 函数中

install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING

如果你按照这些步骤操作,abuild 将会自动将许可证添加到 package-doc apk 中。

警告: 打包具有 "unknown" 许可证的软件是不可接受的!如果你找不到源代码的许可证,请联系作者并要求他们指定许可证。


arch

要构建的软件包架构。可以是:x86、x86_64、allnoarch,其中 all 表示所有架构,noarch 表示它与架构无关(例如,纯 Python 软件包)。

提示: 要确定你的 APKBUILD 是否可以使用 noarch,请为你的架构构建软件包,然后从 APKBUILD 所在的目录运行 "scanelf -R pkg",以便扫描 ./pkg 目录中的 ELF 文件。如果你没有得到任何输出,则可以使用 noarch

url

程序的网站地址。这在以后查找文档或有关软件包的其他信息时很有用。

pkgdesc

软件包功能的简短单行描述。对软件包管理系统很有用。它应以大写字母开头,并且以句点结尾。

这是 OpenSSH 客户端软件包的 apk_info 中的一个示例

pkgdesc="Port of OpenBSD's free SSH release - client"

pkgver

提供你正在构建的软件包的发布版本号。

pkgrel

$pkgrel 版本控制是为了如果你在不更改实际 $pkgver 的情况下更改 APKBUILD 文件中的某些内容,你可以递增 pkgrel,以便 apk 工具将其检测为更新。例如,如果你忘记添加依赖项,你可以在之后添加它,并且可以 +1 pkgver,以便 apk 找到此更新并添加缺少的依赖项。当上游版本更改时,我们将 pkgrel 重置为 0。

pkgname

你正在创建的软件包的基本名称。对于 Freeswitch 1.0.6,你将使用 "freeswitch"

install

有 6 种不同的安装脚本。每个脚本都使用 $pkgname.<action> 调用,其中 <action> 是以下之一

$pkgname.pre-install
此脚本在安装软件包之前执行。典型用途是软件包需要创建组和用户时。例如
#!/bin/sh

addgroup -S clamav 2>/dev/null
adduser -S -D -H -s /bin/false -G clamav -g clamav clamav 2>/dev/null

exit 0

注意末尾的 exit 0。如果脚本以失败退出(如果用户已存在),则软件包将不会安装,并且 apk add 将以失败退出。

$pkgname.post-install
此脚本在软件包安装后执行。
$pkgname.pre-upgrade
与 pre-install 相同,但在升级/降级/重新安装已安装的软件包之前执行。请注意,以失败退出不会导致 apk 以失败退出,但会将软件包标记为损坏。
$pkgname.post-upgrade
与 post-install 相同,但在升级/降级/重新安装已安装的软件包之后执行。
$pkgname.pre-deinstall
此脚本在卸载软件包之前执行。如果脚本以失败退出,apk 将不会卸载软件包。
$pkgname.post-deinstall
此脚本在软件包卸载后执行。例如,可用于恢复 busybox 链接
#!/bin/sh
busybox --install -s

如果软件包具有 pre-install 和 post-install 脚本,则 APKBUILD 应定义 install 变量

...
install="$pkgname.pre-install $pkgname.post-install"

...

subpackages

提示: 参考 子软件包 示例,以帮助你理解如何创建它们。

$subpackages 用于将正常的 "make install" 分割成单独的软件包。我们最常用的子软件包是 doc 和 dev。因为我们喜欢保持目标系统的小巧,所以我们将文档和开发文件(仅在构建软件包时需要)移动到单独的软件包中。要使用特定程序,用户只需安装基本 apk,而无需 package-doc 或 package-dev,但如果他想阅读手册,则需要安装 package-doc。

找出是否需要使用 -dev 和 -doc 的最简单方法是首先在不设置这些选项的情况下构建软件包,并等待构建完成。完成后,你应该有一个 pkg 目录,它是伪根目录。在此目录中,你将看到它将如何安装在目标系统上的 / 中的结构。

要查看是否需要 -dev 软件包,你可以运行以下 cmd

find pkg/usr/ -name '*.[acho]' -o -name '*.la'

如果这返回任何文件,则你需要包含 -dev 软件包。


要查看是否需要 -doc 软件包,你可以运行以下 cmd

find pkg/usr/share -name doc -o -name man -o -name info -o -name html -o -name sgml -o -name licenses

如果这返回任何目录,则你需要包含 -doc 软件包。

自定义子软件包

某些软件还具有非必要文件,这些文件不属于文档或开发内容。这些文件应放置在它们自己的专用子软件包中。某些软件包包含大型测试套件,这些测试套件仅在特定情况下需要,或者包含我们不希望安装的依赖项的二进制文件。为了处理这些情况,我们创建了自己的软件包/函数。在下面的 APKBUILD 中的 build() 函数之后,我们创建另一个函数

test() {
       mkdir -p "$subpkgdir"/usr
       mv "$pkgdir"/usr/package-test "$subpkgdir"/usr/
       # or amove usr/package-test
}

我们还需要将软件包信息添加到 $subpackages 变量

subpackages="$pkgname-doc $pkgname-dev $pkgname-test"

在我们完成构建软件包后,你应该看到另一个名为 packagename-test.apk 的 apk,其中包含我们移动到 $subpkgdir 目录的文件。

上述变量也可以在我们的自定义函数中使用。例如,如果我们想使用 perl 支持构建 test() 函数,我们将添加

depends="perl"
makedepends="perl-dev"

如果我们安装基本软件包,它将不会安装 perl,但如果我们安装 package-test 软件包,它将会安装。

补丁

注意: 在创建补丁时,请遵循 编码风格

请确保你始终提交人类可读的补丁。创建它们的方法有

进行目录比较

diff -Nurp original_directory new_directory > filename.patch

进行文件比较

diff -up original.file new.file > filename.patch

如果补丁包含一个全新的文件,但没有 *.rej 或 *.orig 文件,则需要向 diff 添加 -N 选项,但你可能需要使用 --exclude PATTERN 添加排除项,以免意外添加文件。你可能需要在补丁文件中手动删除不需要的文件。

由于多个补丁可以修补同一个文件,它们可能会更改后续补丁所需的偏移量。为了确保我们始终以特定的方式修补,我们应该按如下方式编号补丁

10-patch1.patch 20-patch2.patch 30-patch3.patch

这样我们始终可以确保首先应用补丁 1,如果我们想在它们之间添加其他补丁,我们可以使用适当的索引(例如 11、12、21、22)。

将补丁文件的名称添加到 source 变量。如果你尚未声明自定义 prepare 函数,则无需进一步操作。否则,请确保在你的 prepare 函数中调用 default_prepare。例如

prepare() {
	default_prepare

	# do your stuff
}

注意:一些较旧的软件包在 prepare 函数中包含一个 for 循环来应用补丁。这不再需要,因为补丁由 default_prepare 处理。

在 Alpine >=3.4 中,你可以定义 patch_args 来提供补丁级别。这仅在所有补丁都具有相同的补丁级别时才有效。如果有很多来自不同来源的补丁,则很可能你需要编辑它们,如下所述。

要自动修补软件包(仅在 Alpine >=3.4 中可用),如果它使用非默认 (-p1) 的补丁级别 (-pX),你需要仔细修改补丁。首先,你需要一个不会自动在 Windows 和 Unix 换行符之间转换的文本编辑器(或者,禁用此功能),以便它保留旧代码。接下来你需要做的是修改 .patch 文件中 "+++" 和 "---" 行上的路径。你可以像下面显示的那样以 a/ 和 b/ 开头路径。接下来,你需要调整路径,使相对基本路径来自 $builddir 内部。任何位于 $builddir 左侧的内容,包括 $builddir 本身,都需要从路径中删除。因此,如果 $builddir 是 /home/USER/aports/community/chromium/src/chromium-65,则需要在 "+++" 和 "---" 行上将其删除。在 chromium-65 文件夹中,你可以看到一个 src 文件夹,它有一个后代 3rdparty。如果补丁最初具有更深的补丁级别,则可能需要填写路径的缺失部分。例如,使用 find . -name "Assertions.cpp" 命令查找相对于基础文件的完整路径。

example.patch 的内容

作者:John Doe <johndoe@mail.com> URL: http://..... 摘要:修复 musl 兼容性 ---- --- a/src/3rdparty/chromium/third_party/WebKit/Source/wtf/Assertions.cpp.orig +++ b/src/3rdparty/chromium/third_party/WebKit/Source/wtf/Assertions.cpp @@ -142,7 +142,7 @@ }; FrameToNameScope::FrameToNameScope(void* addr) : m_name(0), m_cxaDemangled(0) { -#if OS(MACOSX) || (OS(LINUX) && !defined(__UCLIBC__)) +#if OS(MACOSX) || (OS(LINUX) && defined(__GLIBC__)) Dl_info info; if (!dladdr(addr, &info) || !info.dli_sname) return;

补丁的某些部分可能已过时、完全删除(如在源代码文件中完全删除)或移动或重命名文件。你需要删除补丁的那部分,或找到代码更改的位置并重新 diff 它。

在顶部注明出处以及你最初找到它们的位置,并附上注释是一种良好的礼仪。

在 Alpine 上,不提供使用类似于 patch_opts 的全局变量排除补丁的功能。要排除补丁,你需要创建自己的自定义 prepare()。

如果你有一个包含大量补丁的整体补丁,你可以使用 filterdiff,它在 patchutils 软件包中可用。

只需执行类似的操作

makedepends="patchutils"

prepare() {
  ...
  cd "$builddir"
  filterdiff -x '*drivers/video/logo*' "$srcdir"/original.patch > "$builddir"/modified.patch
  patch -p1 -i "$builddir"/modified.patch
}

你需要将通配符模式放在单引号中才能使其工作。

配置选项

Alpine 具有一些我们默认设置的默认配置选项。我们使用 /usr 作为前缀,以确保所有内容都安装在 /usr 前面。如果你注意到任何内容安装在错误的目录中,请运行

./configure --help

并查看是否可以设置正确的位置。

我们在这里不讨论依赖项开关,我们已经在依赖项部分中讨论过这一点。

Make 选项

如果你在编译或使用 make/make install 安装软件包时发现奇怪的问题,你可以尝试禁用并行构建/安装。正常的 make 行是

make

要禁用并行,我们使用

make -j1

我们可以对 make install 使用相同的方法。

因为我们不想将软件包安装在我们的构建环境中,但我们想将其安装在伪根目录中,所以我们需要告诉 'make install' 使用另一个目标目录而不是 '/'。我们通过在执行 make install 时设置一个变量来做到这一点,如下所示

make DESTDIR="$pkgdir" install

请注意,某些 Makefile 不支持此变量,并且始终将软件安装在 '/' 中。为确保你不会搞砸你的构建系统,永远不要以 root 用户身份运行你的构建系统,而始终使用自定义用户并在需要时使用 doas。如果意外地 Makefile 不支持 DESTDIR 变量,它将无法安装在我们的构建系统系统目录中。

builddir

如果你使用newapkbuild创建你的 APKBUILD 文件,你必须指定解压缩的源的路径。在 prepare/build/install 过程中的各个部分,都使用了 builddir。大多数情况下,$srcdir$pkgname-$pkgver 的组合将起作用。如果不起作用,请检查 /src 目录或源 tarball 以查找正确的字符串。特别是当你使用自动生成的 tarball(例如来自 github 和 gitorious)时,这需要调整。

builddir="$srcdir"/$pkgname-$pkgver

附加文件

如果你想要/需要安装上面未提及的其他文件,你可以使用以下 cmd(这是一个 conf 文件的示例)

install -Dm644 doc/$pkgname.conf "$pkgdir"/etc/$pkgname.conf

构建软件包

如果你尚未创建如上所述的校验和,你现在可以这样做

cd $pkgname abuild checksum

现在是构建我们的软件包的时候了。因为构建系统永远不应安装所有软件包,以防止链接到我们不希望它链接的软件包,所以我们递归地使用 abuild 和 -r 开关。它将从你的仓库安装所有依赖项并构建它,之后它将再次卸载所有这些依赖软件包。

abuild -r

在本地测试软件包

完成后,你的软件包将在 ~/packages 的子文件夹中找到。你可能想在你的机器上测试它,但前提是该软件包不是关键的系统软件包,例如 musl 或 apk-tools 软件包。为了避免破坏你的系统(例如使其无法使用 apk add 或恢复系统和编译器工具链),对于关键系统软件包,你应该首先在 chroot 上进行测试,然后再在实际系统中使用它。

在本地测试软件包的最佳方法是修改你的 /etc/apk/repositories,以便它包含指向本地构建的软件包的索引 - 包含 ARCH/APKINDEX.tar.gz 的目录。例如,下面的 /etc/apk/repositories 包括 testing、community 和 main 中本地构建的软件包。要使用此示例,请将 USER 更改为你的登录名。

/etc/apk/repositories 的内容

/home/USER/packages/testing/ /home/USER/packages/main/ /home/USER/packages/community/ https://dl-cdn.alpinelinux.org/alpine/edge/main https://dl-cdn.alpinelinux.org/alpine/edge/community https://dl-cdn.alpinelinux.org/alpine/edge/testing

如果你希望在不更改任何其他配置的情况下测试软件包,你可以使用 apk-X, --repository 选项

doas apk add --repository /home/USER/packages/testing $pkgname

代码审查

为了使您的软件包成功通过代码审查员的审查(截至 2018 年 2 月 18 日,GitHub 上的审查员是 nmeum 和 jirutka),并可能提高接受度,需要遵循以下参考资料中列出的约定。

注意: atools 软件包运行 linter 工具 apkbuild-lint$ apkbuild-lint APKBUILD
  1. 自定义全局变量应以下划线 (_) 为前缀。
  2. 精简代码,如合并命令、删除未使用的变量、删除由 abuild 自动处理的重复功能函数。
  3. 版本控制应正确完成。有关详细信息,请参阅 APKBUILD_Reference#pkgver
  4. 许可应正确完成。删除不必要的已获 OSI 批准的许可复制。
  5. 非官方变量的命名约定规则,例如 _gitrev 优于 commit。
  6. 使用制表符而不是空格进行缩进。
  7. 删除显式的 return 1。(如果您正在学习,仍然可以在旧的 APKBUILD 文件中找到它们,但现在强烈不建议使用。)
  8. 禁用 check() 需要满足以下任一条件:(1) 在 options="!check" 旁边添加注释 (#) 说明没有测试套件/单元测试,或者 (2) 正常工作的 check() 函数。
  9. 必须使用显式调用 subpackages="$pkgname-doc" 来代替显式 gzip man page 压缩。
  10. 理想情况下,行宽应不超过 80 列

提交您的工作

在您成功构建软件包并正确遵循代码审查部分的约定和要求后,您可以将您的 APKBUILD 提交到 Alpine 的 git 存储库。

在添加新文件之前,更新您的 git 仓库

cd $aportsdir git pull

这应该将其他人所做的所有更改拉取到您的本地 git 仓库中。

当您认为准备就绪时,您可以将您的文件添加到 git

注意:当使用我们的 Gitlab 实例时,您可以为每个软件包创建 MR。请将与同一软件包相关的所有提交合并为一个 MR。

cd $aportsdir git add testing/$pkgdir (包括构建所需的任何其他文件;$pkgname.install...) git commit

对于新的 aports,请使用以下提交消息模板(不包括注释)

内容为template

testing/$pkgname: new aport # 这将是主题行 # 空行 $url # 项目主页 $pkgdesc # 一行描述

或者您可以添加以下内容并 chmod +x ports/.git/hooks/prepare-commit-msg 以自动生成提交消息,而默认的 aports/.githooks/ 不会这样做

内容为aports/.git/hooks/prepare-commit-msg

#!/bin/sh case "$2,$3" in ,|template,) if git diff-index --diff-filter=A --name-only --cached HEAD \ | grep -q '/APKBUILD$'; then meta() { git diff --staged | grep "^+$1" | sed 's/.*="\?//;s/"$//';} printf 'testing/%s: new aport\n\n%s\n%s\n' "$(meta pkgname)" \ "$(meta url)" "$(meta pkgdesc)" "$(cat $1)" > "$1" else printf '%s\n\n%s' `git diff-index --name-only --cached HEAD \ | sed -n 's/\/APKBUILD$//p;q'` "$(cat $1)" > "$1" fi;; esac

现在您的更改仅在本地存储库中可用。

由于您没有 Alpine aports 存储库的推送权限,因此您需要创建一个合并请求到 Alpine 的 GitLab 实例

或者,您也可以创建您所做更改的 diff(补丁),并将此补丁发送到 alpine-aports 邮件列表

要创建 diff 补丁

git format-patch HEAD^

或者,如果您有 sprunge,您可以创建一个指向您的补丁的链接,以方便使用

git format-patch HEAD^ --stdout | sprunge

自动标记过时端口

考虑将您的端口添加到 Anitya,以便在上游发布新的稳定版本后,它会立即被标记为过时。

另请参阅