VCS 軟體打包準則 - Arch Linux 中文维基

跳至內容

# VCS 軟體打包準則

出自 Arch Linux 中文维基
翻譯狀態：

- 本文（或部分內容）譯自 VCS package guidelines，最近一次同步於 2025-08-31，若英文版本有所更改，則您可以幫助同步與翻譯更改的內容。
- 您可以在 ArchWiki 的對應頁面找到本文翻譯的原始修訂歷史。
- 本文可能與英文原文存在出入。

Arch 打包準則

32 位 – 安全 – CLR – CMake – DKMS – Eclipse – Electron – Free Pascal – GNOME – Go – Haskell – Java – 交叉編譯工具 – KDE – Lisp – Meson – MinGW – 內核模塊 – Node.js – Nonfree – OCaml – Perl – PHP – Python – R – Ruby – Rust – Shell – VCS – Web – Wine – 字體

相關文章

- Arch 用戶軟體倉庫 (AUR)
- AUR 提交準則
- PKGBUILD

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

提示：使用 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=()` 中包含對應的版本控制工具⸺cvs包、subversion包、git包 等。

## 認證與安全

- 使用 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 -g` 或 `updatepkgsums` 生成校驗和，操作方式與其他非 Git 源相同。

分類：​

- Arch 打包準則

VCS 軟體打包準則
新增話題