跳至內容
出自 Arch Linux 中文维基
Arch 打包準則

32 位CLRCMakeDKMSEclipseElectronFree PascalGNOMEGoHaskellJava交叉編譯工具KDELispMesonMinGW內核模塊Node.jsNonfreeOCamlPerlPHPPythonRRubyRustVCSWebWine字體

版本控制系統可用於獲取常規靜態版本軟體包的原始碼,以及開發分支的最新(主幹)版本。

提示:使用 pacman 軟體包提供的 /usr/share/pacman/PKGBUILD-vcs.proto 原型文件。

包名

除非軟體包獲取的是特定發布版本,否則應添加後綴 -bzr-cvs-darcs-git-hg-svn 等。

版本

若因修改依賴關係、URL 或原始碼導致生成的軟體包發生變化,請將 pkgver 更新至最新版本。若自上次更新 PKGBUILD 以來 pkgver 未發生變化,則應遞增 pkgrel 的值。

建議採用以下版本格式:發行(release).r修訂(revision),其中 修訂 是唯一標識原始碼樹的單調遞增數字(VCS 修訂號即符合此特性)。若無公開發行版本且倉庫無標籤,可用 0 作為發行版本號,或完全省略 發行 部分直接使用形如 r修訂 的版本號。若有公開發行版本但倉庫未打標籤,開發者需通過解析項目文件等方式獲取發行版本號。

修訂號分隔符(修訂 之前的 r)至關重要,可避免上游首次發布版本或使用不同組件數量的版本時出現的問題。例如,若在修訂版 455 時上游決定發布 0.1 版本,修訂號分隔符能保持版本單調性:0.1.r456 > r454。若無分隔符將導致單調性失效:0.1.456 < 454

提示:可使用 --holdver 選項阻止 makepkg 更新 pkgver,詳見 makepkg(8)

衝突、提供與依賴

  • 明確聲明軟體包衝突與提供,例如 fluxbox-gitAUR 應包含:
conflicts=('fluxbox')
provides=("fluxbox=${pkgver}")
注意:關於版本控制的通用建議(尤其適用於 VCS 軟體包),請參閱 PKGBUILD#provides
  • replaces=() 通常會引起不必要的問題,應避免使用。
  • makedepends=() 中包含對應的版本控制工具⸺cvssubversiongit 等。

認證與安全

  • 使用 cvsroot 時,優先採用 anonymous:@ 而非 anonymous@,以避免輸入空密碼;若必須提供密碼則使用 anonymous:password@
  • 由於原始碼並非靜態文件,需在 sha256sums=() 中通過添加 'SKIP' 跳過硬校驗。

VCS 原始碼

注意:Arch 官方不支持使用稀疏克隆(sparse clone)或淺克隆(shallow clone),相關討論參見 FS#34677郵件列表

VCS 原始碼需在 source 數組中指定,其處理方式與其他類型原始碼相同。makepkg 會將倉庫克隆/檢出/分支(clone/checkout/branch)到 $SRCDEST 目錄(若未在 makepkg.conf(5) 中設置,則默認使用 $startdir),然後以特定於各 VCS 的方式將其複製到 $srcdir。本地倉庫不會被修改,因此無需使用 -build 目錄。

source 數組的通用格式為:

source=('[folder::][vcs+]url[#fragment]')
  • folder(可選)——文件夾名稱,用於將默認倉庫名稱更改為更具意義的名稱(例如替代 trunk),或保留先前原始碼路徑
  • vcs+——當 URL 未體現 VCS 類型時需要添加,例如 git+https://some_repo
  • url——遠程或本地倉庫的 URL
  • #fragment(可選)——片段,用於拉取特定分支或提交。各 VCS 支持的片段格式請參閱 PKGBUILD(5) § USING VCS SOURCES

使用 Git 時的 source 數組示例:

source=('project_name::git+https://project_url#branch=project_branch')
警告:請勿在 folder 欄位中使用 pkgver 變量,因為該變量可能在 pkgver() 函數調用時被修改,導致後續函數無法訪問已創建的文件夾。

pkgver() 函數

通過專用的 pkgver() 函數可實現自動版本更新。這種方式能更精細地控制版本號,維護者應儘量採用有意義的版本格式。使用該函數時,仍需預先聲明更改 PKGBUILD 時最新的 pkgver 變量值,makepkg 工具會自動調用 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"
  # 移除Git标签中的'foo-'前缀
  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 哈希,僅保留版本號與修訂號(注意此時若版本號混亂,將無法快速定位到具體修訂版本):

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

可組合使用兩種方法以支持開始無標籤、後期添加標籤的倉庫(使用了 bash 特性):

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  # 存在標籤時
r1581.2b039da       # 無標籤時回退方案

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 +%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"
        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 fetch network-origin
  git lfs checkout
}

這在子模塊中使用 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 fetch network-origin
  git -C libs/libdep lfs checkout
}

Git 校驗和

當通過 git+https://domain.invalid/repository.git#tag=v1.0.0 引用穩定的 Git 標籤作為源時,可以在 PKGBUILD 中指定校驗和。只需使用 makepkg -gupdatepkgsums 生成校驗和,操作方式與其他非 Git 源相同。