VCS package guidelines - ArchWiki

Jump to content

# VCS package guidelines

3 languages

- 日本語
- Português
- 中文（简体）

From ArchWiki

Related articles

- Arch User Repository
- AUR submission guidelines
- PKGBUILD

Version control systems can be used for retrieval of source code for usual statically versioned packages, and the latest (trunk) version of a development branch.

Tip: Use `/usr/share/pacman/PKGBUILD-vcs.proto` prototype provided by the pacman package.

## Package naming

Suffix `pkgname` with `-bzr`, `-cvs`, `-darcs`, `-git`, `-hg`, `-svn`, etc., unless the package fetches a specific release.

## Versioning

If the resulting package is different after changing e.g. the dependencies, URL or sources — update `pkgver` to the latest version. If `pkgver` has not changed since the last update to the `PKGBUILD`, increase `pkgrel` instead.

It is recommended to have following version format: `RELEASE.rREVISION`, where `REVISION` is a monotonically increasing number that uniquely identifies the source tree (VCS revisions do this). If there are no public releases and no repository tags then zero could be used as a release number or you can drop `RELEASE` completely and use version number that looks like `rREVISION`. If there are public releases but repository has no tags then the developer should get the release version somehow e.g. by parsing the project files.

The revision number delimiter — `r` right before `REVISION` — is important. This delimiter allows to avoid problems in case if upstream decides to make its first release or uses versions with different number of components. E.g. if at revision `455` upstream decides to release version `0.1`, then the revision delimiter preserves version monotonicity: `0.1.r456 > r454`. Without the delimiter monotonicity fails: `0.1.456 < 454`.

Tip: `--holdver` can be used to prevent makepkg from updating the `pkgver`, see makepkg(8).

## Conflicts and dependencies

- Include what the package conflicts with and provides, e.g. for fluxbox-gitAUR:

      conflicts=('fluxbox')
      provides=("fluxbox=${pkgver}")

  Note: See PKGBUILD#provides for generic advice on versioning that is regularly relevant for VCS packages.

- `replaces=()` generally causes unnecessary problems and should be avoided.

- Include the appropriate VCS tool in `makedepends=()` — cvs, subversion, git, etc.

## Authentication and security

- When using the cvsroot, use `anonymous:@` rather than `anonymous@` to avoid having to enter a blank password or `anonymous:password@`, if one is required.
- Because the sources are not static, skip the checksum in `sha256sums=()` by adding `'SKIP'`.

## VCS sources

Note: Using sparse or shallow clones is voluntarily not supported, see FS#34677 and the mailing list.

The VCS sources should be specified in the `source` array and will be treated like any other source. makepkg will clone/checkout/branch the repository into `$SRCDEST` — same as `$startdir` if not set in makepkg.conf(5), and copy it to `$srcdir` (in a specific way to each VCS). The local repository is left untouched, thus invalidating the need for a `-build` directory.

The general format of a `source` array is:

    source=('[folder::][vcs+]url[#fragment]')

- `folder` (optional) — is used to change the default repository name to something more relevant, e.g. than `trunk`, or to preserve the previous sources.
- `vcs+` is needed for URLs that do not reflect the VCS type, e.g. `git+https://some_repo`.
- `url` is the URL to the distant or local repository.
- `#fragment` (optional) — is needed to pull a specific branch or commit. See PKGBUILD(5) § USING VCS SOURCES for a list of supported VCS and the respective fragments available.

An example Git source array:

    source=('project_name::git+https://project_url#branch=project_branch')

Warning: Make sure not to use the `pkgver` variable in the `folder` field, as the variable may be changed during the `pkgver()` function call, which will make it impossible to access the created folder in subsequent functions.

## The pkgver() function

The `pkgver` autobump is now achieved via a dedicated `pkgver()` function. This allows for better control over the `pkgver`, and maintainers should favor a `pkgver` that makes sense. To use `pkgver()`, you still need to declare the `pkgver` variable with the most recent value. makepkg will invoke function `pkgver()`, and update variable `pkgver` accordingly.

### Bazaar

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

    r830

### Git

Using the most recent annotated tag reachable from the last commit:

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

    2.0.r6.ga17a017

Using the most recent un-annotated tag reachable from the last commit:

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

    0.71.r115.gd95ee07

In case if the git-tag(1) does not contain dashes then one can use simpler sed(1) expression `sed 's/-/.r/;s/-/./'`.

If tag contains a prefix, like `v` or project name then it should be cut off:

    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

If there are no tags then use number of revisions since beginning of the history:

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

    r1142.a17a017

Version and only commit/revision number (SHA-1 omitted; however, without a SHA-1 quick referencing of an exact revision is lost if not mindful of versioning):

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

Both methods can also be combined, to support repositories that start without a tag but get tagged later on (uses a 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

Note: If the project has releases you should use them instead of the `0.`.

### Fallback

In case no satisfactory `pkgver` can be extracted from the repository, the current date(1) can be used:

    pkgver() {
      date +%Y%m%d
    }

    20130408

Note: It does not identify the source tree state uniquely, so avoid it if possible.

## Tips and tricks

### Git submodules

Git submodules are a little tricky to do. The idea is to add the URLs of the submodules themselves directly to the sources array and then reference them during `prepare()`.

Downstream project developers may not name their submodule as the same name as the upstream module's repository. To view the name of the Git submodules, go to the `.gitmodules` file in the project's repository and preview it. For example, a repository named `lib-dependency` by the upstream developers may be registered as a submodule named `libs/libdep` in `.gitmodules` downstream.

    [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 needs a bit of extra setup:

    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
    }

This also works when the LFS is used in submodules:

    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 checksums

When referencing stable git tags or specific commits as a source via `git+https://domain.invalid/repository.git#tag=v1.0.0`, it is possible to specify their checksum in the `PKGBUILD`. To do so, simply use `makepkg -g` or `updatepkgsums` to generate them as you would for any other non-git source.

Category:

- Arch package guidelines