跳转至内容

VCS 包指南

来自 ArchWiki
Arch 软件包指南

32位CLRCMake交叉编译DKMSEclipse 插件Electron字体Free PascalGNOMEGoHaskellJavaKDE内核模块LispMesonMinGWNode.js非自由应用OCamlPerlPHPPythonRRubyRust - 安全ShellVCSWeb 应用Wine

版本控制系统可用于检索常规静态版本化包的源代码,以及开发分支的最新(主干)版本。

提示 使用 pacman 包提供的 /usr/share/pacman/PKGBUILD-vcs.proto 原型。

包命名

除非包检索的是特定发布版本,否则在包名后添加 -bzr-cvs-darcs-git-hg-svn 等后缀。

版本控制

如果更改了依赖项、URL 或源等之后,最终包不同,请将 pkgver 更新到最新版本。如果上次更新 PKGBUILD 以来 pkgver 未更改,则增加 pkgrel

建议使用以下版本格式:RELEASE.rREVISION,其中 REVISION 是单调递增的数字,唯一标识源代码树(VCS 版本控制号就是这样)。如果不存在公开的发布版本且没有存储库标签,则可以使用零作为发布号,或者可以完全省略 RELEASE,使用看起来像 rREVISION 的版本号。如果存在公开的发布版本但存储库没有标签,则开发人员应以某种方式获取发布版本,例如通过解析项目文件。

修订号分隔符 — r 紧跟在 REVISION 前 — 很重要。该分隔符可以避免在上游决定发布第一个版本或使用具有不同组件数量的版本时出现问题。例如,如果修订号为 455 时,上游决定发布版本 0.1,那么修订号分隔符将保留版本单调性:0.1.r456 > r454。如果没有分隔符,单调性会失败:0.1.456 < 454

提示 --holdver 可用于防止 makepkg 更新 pkgver,请参阅 makepkg(8)

冲突与依赖

  • 包括包冲突和提供的功能,例如对于 fluxbox-gitAUR
conflicts=('fluxbox')
provides=("fluxbox=${pkgver}")
注意 有关版本控制的通用建议,请参阅 PKGBUILD#provides,这些建议通常也适用于 VCS 包。
  • replaces=() 通常会引起不必要的麻烦,应避免使用。
  • makedepends=() 中包含适当的 VCS 工具 — cvssubversiongit 等。

身份验证与安全

  • 使用 cvsroot 时,使用 anonymous:@ 而不是 anonymous@,以避免输入空白密码,或 anonymous:password@(如果需要)。
  • 由于源代码不是静态的,请通过添加 'SKIP' 来跳过 sha256sums=() 中的校验和。

VCS 源

VCS 源应在 source 数组中指定,并像其他源一样处理。*makepkg* 会将存储库克隆/检出/分支到 $SRCDEST — 如果在 makepkg.conf(5) 中未设置,则与 $startdir 相同,并将其复制到 $srcdir(以一种特定于每个 VCS 的方式)。本地存储库保持不变,因此不需要 -build 目录。

source 数组的一般格式是

source=('[folder::][vcs+]url[#fragment]')
  • folder(可选)— 用于将默认存储库名称更改为比 trunk 更相关的名称,或保留以前的源。
  • 对于不反映 VCS 类型的 URL,需要 vcs+,例如 git+https://some_repo
  • url 是远程或本地存储库的 URL。
  • #fragment(可选)— 需要提取特定分支或提交。请参阅 PKGBUILD(5) § USING VCS SOURCES 以获取支持的 VCS 列表和相应的可用片段。

一个示例 Git 源数组

source=('project_name::git+https://project_url#branch=project_branch')
警告 确保不在 folder 字段中使用 pkgver 变量,因为该变量可能在 pkgver() 函数调用期间更改,这将导致在后续函数中无法访问创建的文件夹。

pkgver() 函数

pkgver 的自动更新现在通过专用的 pkgver() 函数实现。这使得对 pkgver 的控制更加精细,维护者应倾向于使用有意义的 pkgver。要使用 pkgver(),您仍需要将 pkgver 变量声明为最新值。*makepkg* 将调用 pkgver() 函数,并相应地更新 pkgver 变量。

Bazaar

pkgver() {
  cd "$pkgname"
  printf "r%s" "$(bzr revno)"
}
r830

Git

使用从最后一个提交可达的最近带注释的标签

pkgver() {
  cd "$pkgname"
  git describe --long --abbrev=7 | sed 's/\([^-]*-g\)/r\1/;s/-/./g'
}
2.0.r6.ga17a017

使用从最后一个提交可达的最近未带注释的标签

pkgver() {
  cd "$pkgname"
  git describe --long --tags --abbrev=7 | sed 's/\([^-]*-g\)/r\1/;s/-/./g'
}
0.71.r115.gd95ee07

如果 git-tag(1) 不包含破折号,则可以使用更简单的 sed(1) 表达式 sed 's/-/.r/;s/-/./'

如果标签包含前缀,如 v 或项目名称,则应将其删除。

pkgver() {
  cd "$pkgname"
  # cutting off 'foo-' prefix that presents in the git tag
  git describe --long --abbrev=7 | sed 's/^foo-//;s/\([^-]*-g\)/r\1/;s/-/./g'
}
6.1.r3.gd77e105

如果没有标签,则使用自历史开始以来的修订次数。

pkgver() {
  cd "$pkgname"
  printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short=7 HEAD)"
}
r1142.a17a017

版本号和仅提交/修订号(省略 SHA-1;但如果没有 SHA-1,则除非注意版本控制,否则对确切修订的快速引用会丢失)。

git describe --long --abbrev=7 --tags | sed 's/\([^-]*\)-g.*/r\1/;s/-/./g'

这两种方法也可以结合使用,以支持最初没有标签但后来被打上标签的存储库(使用 bashism)。

pkgver() {
  cd "$pkgname"
  ( set -o pipefail
    git describe --long --abbrev=7 2>/dev/null | sed 's/\([^-]*-g\)/r\1/;s/-/./g' ||
    printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short=7 HEAD)"
  )
}
0.9.9.r27.g2b039da  # if tags exist
r1581.2b039da       # else fallback

Mercurial

pkgver() {
  cd "$pkgname"
  printf "r%s.%s" "$(hg identify -n)" "$(hg identify -i)"
}
r2813.75881cc5391e

Subversion

pkgver() {
  cd "$pkgname"
  local ver="$(svnversion)"
  printf "r%s" "${ver//[[:alpha:]]}"
}
r8546
注意 如果项目有发布版本,您应该使用它们而不是 0.

回退方案

如果在存储库中无法提取令人满意的 pkgver,则可以使用当前的 date(1)

pkgver() {
  date +%Y%m%d
}
20130408
注意 这不能唯一地标识源代码树状态,因此请尽量避免使用。

技巧与提示

Git 子模块

Git 子模块有点棘手。思路是将子模块本身的 URL 直接添加到 sources 数组中,然后在 prepare() 期间引用它们。

下游项目开发者可能不会将他们的子模块命名为与上游模块存储库相同的名称。要查看 Git 子模块的名称,请转到项目存储库中的 .gitmodules 文件并进行预览。例如,一个名为 lib-dependency 的存储库,在下游的 .gitmodules 中可能注册为一个名为 libs/libdep 的子模块。

[submodule "libs/libdep"]
  path = libs/libdep
  url = https://example.org/lib-dependency/lib-dependency.git
source=("git+https://example.org/main-project/main-project.git"
        "git+https://example.org/lib-dependency/lib-dependency.git")

prepare() {
  cd main-project
  git submodule init
  git config submodule.libs/libdep.url "$srcdir/lib-dependency"
  git -c protocol.file.allow=always submodule update
}

Git LFS

Git LFS 需要一些额外的设置。

makedepends=(... 'git-lfs')
prepare() {
  git lfs install --local
  git remote add network-origin https://example.org/upstream/lfs/repo
  git lfs pull network-origin
}

当 LFS 在子模块中使用时,这也有效。

prepare() {
  git submodule init
  git config submodule.libs/libdep.url "$srcdir/lib-dependency"
  git -c protocol.file.allow=always submodule update

  git -C libs/libdep lfs install --local
  git -C libs/libdep remote add network-origin https://example.org/upstream/lfs/repo
  git -C libs/libdep lfs pull network-origin
}

Git 校验和

当通过 git+https://domain.invalid/repository.git#tag=v1.0.0 引用稳定 Git 标签或特定提交作为源时,可以在 PKGBUILD 中指定它们的校验和。要做到这一点,只需使用 makepkg -gupdpkgsums 为它们生成校验和,就像为任何其他非 Git 源一样。