Compare commits

...

21 Commits

Author SHA1 Message Date
Jelle van der Waa
ee31351914 Merge branch 'support-offline-builds' into 'master'
Draft: PoC: build offline support

See merge request archlinux/devtools!207
2025-08-09 16:55:12 +00:00
Jakub Klinkovský
fc56ebedf3 fix(completion): fix bash completion for the license subcommand
Signed-off-by: Jakub Klinkovský <lahwaacz@archlinux.org>
2025-08-05 17:48:12 +02:00
Christian Heusel
01757e6904 fix(commitpkg): Quiet git ls-files output
So far all files in `needsversioning=(...)` have been printed to the
command line if they were found, which is not useful, especially now
that we have more files present there.

It makes sense however to keep the standard error output, as this gives
a actionable suggestion what one should to to fix the issue:

    > error: pathspec 'PKGBUILD' did not match any file(s) known to git
    > Did you forget to 'git add'?

Fixes #281

Signed-off-by: Christian Heusel <christian@heusel.eu>
2025-08-01 11:26:57 +02:00
Daniel M. Capella
c5fe8ff3e6 feat(license): Extend matches for sysusers/tmpfiles configs
Eg. to match:
- sysusers.conf
- $pkgname.sysusers
- $pkgname.sysusers.conf
2025-07-28 23:38:32 -04:00
Christian Heusel
ad7dd50bf3 chore(release): version v1.4.0 2025-07-25 09:04:45 +02:00
Jakub Klinkovský
5a381835e8 feat(config): set default build flags for Fortran
This implements RFC 54: https://rfc.archlinux.page/0054-fortran-flags/
2025-07-25 08:54:49 +02:00
Sven-Hendrik Haase
b8c475b3f4 feat(commitpkg): Integrate with pkgctl license
This will check for license compliance before committing.
2025-07-22 20:27:54 +02:00
Sven-Hendrik Haase
74cd46f092 feat(license): Add subcommand to check and setup licenses
This implements a part of RFC52. The new pkgctl license check subcommand calls reuse lint on
the provided directories while pkgctl license setup tries to make packages compliant with RFC40
by adding a LICENSE file and by generating a REUSE.toml.

Component: pkgctl license
2025-07-22 20:27:46 +02:00
Bert Peters
40f31f98a3 fix(autocomplete): don't add extra = for message 2025-05-12 22:49:22 +02:00
Jan Alexander Steffens (heftig)
c6f5d72708 fix(common): Fix diffoscope looking at remote debug info
readelf will pull in remote debug info if allowed to. This is not really
what we expect for diffoscope diffs, especially when our server only has
debug info for one side of the diff.
2025-04-23 01:13:46 +02:00
Jakub Klinkovský
b4a5e5dbd9 fix(build): sync command description with the man page
The original wording sounded like `pkgctl build` by default updates the
checksums whenever `pkgver` is changed in PKGBUILD.
2025-04-18 15:56:51 +02:00
Levente Polyak
4926d9d8c5 chore(release): version v1.3.2 2025-02-25 22:05:15 +01:00
Levente Polyak
7165e0d73e chore(conf): add whitespace to RUSTFLAGS option for unified style 2025-02-25 21:51:37 +01:00
Levente Polyak
8776dd39e8 chore(makerepropkg): unify indention style of the file 2025-02-25 21:32:14 +01:00
Levente Polyak
fb4bf96d24 feat(makerepropkg): support conf.d makepkg config files from buildtool
Previously we have only copied the passed makepkg.conf file into the
chroot, which misses build flags for additional language specific files
that makepkg supports. Fix this by extracting all conf.d makepkg config
files from the detected devtools archive.

Component: makerepropkg
Co-authored-by: Christian Heusel <christian@heusel.eu>
2025-02-25 21:32:06 +01:00
Levente Polyak
96eff02801 feat(arch-nspawn): support conf.d makepkg config files
Previously we have only copied the passed makepkg.conf file into the
chroot, which misses build flags for additional language specific files
that makepkg supports. Fix this by also copying all config files that
match the `<file>.d/*.conf` glob.

Fixes #244

Component: arch-nspawn
Suggested-by: Rein Fernhout (Levitating) <me@levitati.ng>
Co-authored-by: Christian Heusel <christian@heusel.eu>
2025-02-25 21:20:31 +01:00
Levente Polyak
79c3162112 feat(config): provide vendored language specific makepkg.conf files
Vendor all language related makepkg.conf files which are also shipped by
makepkg itself. This makes sure we always have full control over the
build flags inside devtools and overlay any by the vendored config we
maintain in devtools.

Component: archbuild
Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
2025-02-15 11:43:14 +01:00
Levente Polyak
43cd68d73e feat(archbuild): automatically recreate chroot on version mismatch
For our own archbuild script which is used for package building from a
template chroot, automatically handle the case where the template root
is out of date. Check the version and enable the clean flag by default
in case a mismatch is detected.

Component: archbuild
Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
2025-02-15 11:43:14 +01:00
Levente Polyak
5c1948a357 chore(archroot): bump version to ensure fresh roots after config changes
We are currently facing reproducible builds issues as the
makepkg.conf.d/rust.conf file in the root chroot was leading to pacnew
files, which means the chroot did not use configs as expected from a
clean state. Work around this problem by bumping the chroot version and
ensure we get fresh chroots with expected configs

Component: archroot
Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
2025-02-15 11:24:31 +01:00
Bert Peters
acd6bda3ed Don't add extra "=" to repo completion 2025-02-01 15:45:36 +01:00
Jelle van der Waa
a0c0c63a85 PoC: build offline support 2024-10-10 19:35:42 +02:00
29 changed files with 888 additions and 27 deletions

View File

@@ -1,6 +1,6 @@
SHELL=/bin/bash -o pipefail
V=1.3.1
V=1.4.0
BUILDTOOLVER ?= $(V)
PREFIX = /usr/local
@@ -19,6 +19,7 @@ PACMAN_CONFIGS=$(wildcard config/pacman/*)
GIT_CONFIGS = $(wildcard config/git/*)
SETARCH_ALIASES = $(wildcard config/setarch-aliases.d/*)
MANS = $(addprefix $(BUILDDIR)/,$(patsubst %.asciidoc,%,$(wildcard doc/man/*.asciidoc)))
DATA_FILES = $(wildcard data/*)
COMMITPKG_LINKS = \
core-testingpkg \
@@ -59,7 +60,7 @@ BATS_ARGS ?= --jobs $(JOBS) $(BATS_EXTRA_ARGS) --verbose-run
COVERAGE_DIR ?= $(BUILDDIR)/coverage
all: binprogs library conf completion man
all: binprogs library conf completion man data
binprogs: $(BINPROGS)
library: $(LIBRARY)
completion: $(COMPLETIONS)
@@ -106,12 +107,16 @@ $(BUILDDIR)/doc/man/%: doc/man/%.asciidoc doc/man/include/footer.asciidoc
conf:
@install -d $(BUILDDIR)/makepkg.conf.d
@cp -a $(MAKEPKG_CONFIGS) $(BUILDDIR)/makepkg.conf.d
@cp -ra $(MAKEPKG_CONFIGS) $(BUILDDIR)/makepkg.conf.d
@install -d $(BUILDDIR)/pacman.conf.d
@cp -a $(PACMAN_CONFIGS) $(BUILDDIR)/pacman.conf.d
@install -d $(BUILDDIR)/git.conf.d
@cp -a $(GIT_CONFIGS) $(BUILDDIR)/git.conf.d
data:
@install -d $(BUILDDIR)/data
@cp -ra $(DATA_FILES) $(BUILDDIR)/data
clean:
rm -rf $(BUILDDIR)
@@ -122,9 +127,11 @@ install: all
install -dm0755 $(DESTDIR)$(DATADIR)/pacman.conf.d
install -m0755 ${BINPROGS} $(DESTDIR)$(PREFIX)/bin
install -dm0755 $(DESTDIR)$(DATADIR)/lib
install -dm0755 $(DESTDIR)$(DATADIR)/data
cp -ra $(BUILDDIR)/lib/* $(DESTDIR)$(DATADIR)/lib
cp -a $(BUILDDIR)/git.conf.d -t $(DESTDIR)$(DATADIR)
for conf in $(notdir $(MAKEPKG_CONFIGS)); do install -Dm0644 $(BUILDDIR)/makepkg.conf.d/$$conf $(DESTDIR)$(DATADIR)/makepkg.conf.d/$${conf##*/}; done
cp -ra $(BUILDDIR)/makepkg.conf.d -t $(DESTDIR)$(DATADIR)
cp -ra $(BUILDDIR)/data -t $(DESTDIR)$(DATADIR)
for conf in $(notdir $(PACMAN_CONFIGS)); do install -Dm0644 $(BUILDDIR)/pacman.conf.d/$$conf $(DESTDIR)$(DATADIR)/pacman.conf.d/$${conf##*/}; done
for a in ${SETARCH_ALIASES}; do install -m0644 $$a -t $(DESTDIR)$(DATADIR)/setarch-aliases.d; done
for l in ${COMMITPKG_LINKS}; do ln -sf commitpkg $(DESTDIR)$(PREFIX)/bin/$$l; done
@@ -142,7 +149,8 @@ uninstall:
for f in $(notdir $(LIBRARY)); do rm -f $(DESTDIR)$(DATADIR)/lib/$$f; done
rm -rf $(DESTDIR)$(DATADIR)/lib
rm -rf $(DESTDIR)$(DATADIR)/git.conf.d
for conf in $(notdir $(MAKEPKG_CONFIGS)); do rm -f $(DESTDIR)$(DATADIR)/makepkg.conf.d/$${conf##*/}; done
rm -rf $(DESTDIR)$(DATADIR)/makepkg.conf.d
rm -rf $(DESTDIR)$(DATADIR)/data
for conf in $(notdir $(PACMAN_CONFIGS)); do rm -f $(DESTDIR)$(DATADIR)/pacman.conf.d/$${conf##*/}; done
for f in $(notdir $(SETARCH_ALIASES)); do rm -f $(DESTDIR)$(DATADIR)/setarch-aliases.d/$$f; done
for l in ${COMMITPKG_LINKS}; do rm -f $(DESTDIR)$(PREFIX)/bin/$$l; done
@@ -154,7 +162,6 @@ uninstall:
for manfile in $(notdir $(MANS)); do rm -f $(DESTDIR)$(MANDIR)/man$${manfile##*.}/$${manfile}; done;
rmdir --ignore-fail-on-non-empty \
$(DESTDIR)$(DATADIR)/setarch-aliases.d \
$(DESTDIR)$(DATADIR)/makepkg.conf.d \
$(DESTDIR)$(DATADIR)/pacman.conf.d \
$(DESTDIR)$(DATADIR)
@@ -187,5 +194,5 @@ coverage: binprogs library conf completion man
check: $(BINPROGS_SRC) $(LIBRARY_SRC) contrib/completion/bash/devtools.in config/makepkg/x86_64.conf contrib/makepkg/PKGBUILD.proto
shellcheck $^
.PHONY: all binprogs library completion conf man clean install uninstall tag dist upload test coverage check
.PHONY: all binprogs library completion conf man data clean install uninstall tag dist upload test coverage check
.DELETE_ON_ERROR:

View File

@@ -94,6 +94,7 @@ Component: pkgctl db remove
- bat (pretty printing)
- nvchecker (version checking)
- reuse (license compliance)
### Development Dependencies

View File

@@ -2,6 +2,7 @@
/src
/*/
!/keys/
!/LICENSES/
/*.log
/*.tar.*

View File

@@ -0,0 +1,22 @@
#!/hint/bash
# shellcheck disable=2034
#
# /etc/makepkg.conf.d/fortran.conf
#
#########################################################################
# FORTRAN LANGUAGE SUPPORT
#########################################################################
# Flags used for the Fortran compiler, similar in spirit to CFLAGS. Read
# linkman:gfortran[1] for more details on the available flags.
FFLAGS="-march=x86-64 -mtune=generic -O2 -pipe -fno-plt \
-Wp,-D_FORTIFY_SOURCE=3 -fstack-clash-protection -fcf-protection \
-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer"
FCFLAGS="$FFLAGS"
# Additional compiler flags appended to `FFLAGS` and `FCFLAGS` for use in debugging. Usually
# this would include: ``-g''. Read linkman:gfortran[1] for more details on the wide
# variety of compiler flags available.
DEBUG_FFLAGS="-g"

View File

@@ -0,0 +1,19 @@
#!/hint/bash
# shellcheck disable=2034
#
# /etc/makepkg.conf.d/rust.conf
#
#########################################################################
# RUST LANGUAGE SUPPORT
#########################################################################
# Flags used for the Rust compiler, similar in spirit to CFLAGS. Read
# linkman:rustc[1] for more details on the available flags.
RUSTFLAGS="-C force-frame-pointers=yes"
# Additional compiler flags appended to `RUSTFLAGS` for use in debugging.
# Usually this would include: ``-C debuginfo=2''. Read linkman:rustc[1] for
# more details on the available flags.
DEBUG_RUSTFLAGS="-C debuginfo=2"

View File

@@ -0,0 +1 @@
../conf.d/fortran.conf

View File

@@ -0,0 +1 @@
../conf.d/rust.conf

View File

@@ -0,0 +1 @@
../conf.d/fortran.conf

View File

@@ -0,0 +1 @@
../conf.d/rust.conf

View File

@@ -150,6 +150,7 @@ _pkgctl_cmds=(
db
diff
issue
license
release
repo
search
@@ -367,6 +368,25 @@ _pkgctl_repo_switch_opts() {
fi
}
_pkgctl_license_cmds=(
check
setup
)
_pkgctl_license_check_args=(
-h --help
)
_pkgctl_license_check_opts() { _filedir -d; }
_pkgctl_license_setup_args=(
--no-check
-f --force
-h --help
)
_pkgctl_license_setup_opts() { _filedir -d; }
_pkgctl_version_cmds=(
check
setup

View File

@@ -61,7 +61,7 @@ _pkgctl_build_args=(
'--update-checksums[Force computation and update of the checksums (disables auto-detection)]'
'(-e --edit)'{-e,--edit}'[Edit the PKGBUILD before building]'
'(-r --release)'{-r,--release}'[Automatically commit, tag and release after building]'
'(-m --message=)'{-m,--message=}"[Use the given <msg> as the commit message]:message:"
'(-m --message)'{-m,--message}"[Use the given <msg> as the commit message]:message:"
'(-u --db-update)'{-u,--db-update}'[Automatically update the pacman database as last action]'
'(-h --help)'{-h,--help}'[Display usage]'
'*:git_dir:_files -/'
@@ -201,8 +201,8 @@ _pkgctl_issue_view_args=(
)
_pkgctl_release_args=(
'(-m --message=)'{-m,--message=}"[Use the given <msg> as the commit message]:message:"
'(-r --repo=)'{-r,--repo=}"[Specify a target repository for new packages]:repo:($DEVTOOLS_VALID_REPOS[*])"
'(-m --message)'{-m,--message}"[Use the given <msg> as the commit message]:message:"
'(-r --repo)'{-r,--repo}"[Specify a target repository for new packages]:repo:($DEVTOOLS_VALID_REPOS[*])"
'(-s --staging)'{-s,--staging}'[Release to the staging counterpart of the auto-detected repo]'
'(-t --testing)'{-t,--testing}'[Release to the testing counterpart of the auto-detected repo]'
'(-u --db-update)'{-u,--db-update}'[Automatically update the pacman database after uploading]'
@@ -399,6 +399,7 @@ _pkgctl_cmds=(
"db[Pacman database modification for package update, move etc]"
"diff[Compare package files using different modes]"
"issue[Work with GitLab packaging issues]"
"license[Check and manage package license compliance]"
"release[Release step to commit, tag and upload build artifacts]"
"repo[Manage Git packaging repositories and their configuration]"
"search[Search for an expression across the GitLab packaging group]"
@@ -410,6 +411,24 @@ _pkgctl_args=(
'(-h --help)'{-h,--help}'[Display usage]'
)
_pkgctl_license_cmds=(
"pkgctl license command"
"check[Checks package licensing compliance using REUSE]"
"setup[Automatically detect and setup a basic REUSE config]"
)
_pkgctl_license_check_args=(
'(-h --help)'{-h,--help}'[Display usage]'
'*:git_dir:_files -/'
)
_pkgctl_license_setup_args=(
'(-f --force)'{-f,--force}'[Overwrite existing REUSE config]'
'--no-check[Do not run license check after setup]'
'(-h --help)'{-h,--help}'[Display usage]'
'*:git_dir:_files -/'
)
_pkgctl_version_cmds=(
"pkgctl version command"
"check[Compares local package versions against upstream versions]"

12
data/LICENSE Normal file
View File

@@ -0,0 +1,12 @@
Copyright Arch Linux Contributors
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE
FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View File

@@ -23,7 +23,8 @@ Options
Location of a pacman config file
*-M* <file>::
Location of a makepkg config file
Location of a makepkg config file. Specific additions (e.g. build flags for
additional languages) can be placed in '<file>.d/*.conf'.
*-c* <dir>::
Set pacman cache, if no directory is specified the passed pacman.conf's cachedir is used with a fallback to '/etc/pacman.conf'

View File

@@ -49,7 +49,8 @@ Options
Set the pacman cache directory.
*-M* <file>::
Location of a makepkg config file.
Location of a makepkg config file. Specific additions (e.g. build flags for
additional languages) can be placed in '<file>.d/*.conf'.
*-l* <chroot>::
The directory name to use as the chroot namespace

View File

@@ -0,0 +1,54 @@
pkgctl-license-check(1)
=======================
Name
----
pkgctl-license-check - Checks package licensing compliance using REUSE
Synopsis
--------
pkgctl license check [OPTIONS] [PKGBASE...]
Description
-----------
Checks package licensing compliance using REUSE and also verifies whether
a LICENSE file with the expected Arch Linux-specific 0BSD license text exists.
Configuration
-------------
Uses reuse(1) and a `REUSE.toml` file located alongside the PKGBUILD(5). Refer
to the configuration section in pkgctl-license(1).
If no `PKGBASE` is specified, the command defaults to using the current working
directory.
Options
-------
*-h, --help*::
Show a help text
Exit Codes
----------
On exit, return one of the following codes:
*0*::
Normal exit condition, all checked packages are compliant
*1*::
Unknown cause of failure
*2*::
Normal exit condition, but some packages are not compliant
See Also
--------
pkgctl-license(1)
reuse(1)
PKGBUILD(5)
include::include/footer.asciidoc[]

View File

@@ -0,0 +1,55 @@
pkgctl-license-setup(1)
=======================
Name
----
pkgctl-license-setup - Automatically detect and setup a basic REUSE
configuration
Synopsis
--------
pkgctl license setup [OPTIONS] [PKGBASE...]
Description
-----------
This subcommand automates the creation of the Arch Linux 0BSD package license
file as well as a basic reuse(1) configuration by applying simple heuristics.
It comes in especially handy when initially setting up licensing for a package
without the need to manually write a `REUSE.toml` file.
If any `.patch` files are detected and the PKGBUILD(5) has only a single entry
in the `license=()` array, this subcommand assumes the patches are licensed
under that license and generates annotations for them.
In case there are no patches, no additional annotations are generated.
Manual annotations are necessary in case the subcommand can't generate a
configuration that accounts for all files. In this case, `reuse lint` will fail
with a descriptive error of which files are missing an annotation.
If no `PKGBASE` is specified, the command defaults to using the current working
directory.
Options
-------
*-f, --force*::
Overwrite existing reuse(1) configuration
*--no-check*::
Do not run pkgctl-license-check(1) after setup
*-h, --help*::
Show a help text
See Also
--------
pkgctl-license(1)
pkgctl-license-check(1)
reuse(1)
PKGBUILD(5)
include::include/footer.asciidoc[]

View File

@@ -0,0 +1,54 @@
pkgctl-license(1)
=================
Name
----
pkgctl-license - Check and manage package license compliance
Synopsis
--------
pkgctl license [OPTIONS] [SUBCOMMAND]
Description
-----------
Commands related to package licenses, including checks for compliance.
Uses reuse(1) and a `REUSE.toml` file located alongside the PKGBUILD(5).
Configuration
-------------
The `REUSE.toml` file must contain annotations for all regular files expected
to be present in an Arch Linux package repository.
Use pkgctl-license-setup(1) to automatically detect and setup a basic REUSE
config file based on the files in the package repository.
For detailed information on the various configuration options available for the
`REUSE.toml` file, refer to the REUSE Specification (https://reuse.software/spec).
Options
-------
*-h, --help*::
Show a help text
Subcommands
-----------
pkgctl license check::
Checks package licensing compliance using REUSE
pkgctl license setup::
Automatically detect and setup a basic REUSE config
See Also
--------
pkgctl-license-check(1)
pkgctl-license-setup(1)
reuse(1)
PKGBUILD(5)
include::include/footer.asciidoc[]

View File

@@ -112,7 +112,13 @@ copy_hostconf () {
[[ -n $host_cachemirrors ]] && printf 'CacheServer = %s\n' "${host_cachemirrors[@]}" >>"$working_dir/etc/pacman.d/mirrorlist"
[[ -n $pac_conf ]] && cp "$pac_conf" "$working_dir/etc/pacman.conf"
[[ -n $makepkg_conf ]] && cp "$makepkg_conf" "$working_dir/etc/makepkg.conf"
if [[ -n $makepkg_conf ]]; then
cp "$makepkg_conf" "$working_dir/etc/makepkg.conf"
if [[ -d "${makepkg_conf}.d" ]] && is_globfile "${makepkg_conf}.d"/*.conf; then
mkdir --parents "$working_dir/etc/makepkg.conf.d/"
cp "${makepkg_conf}.d/"*.conf "$working_dir/etc/makepkg.conf.d/"
fi
fi
local file
for file in "${files[@]}"; do

View File

@@ -79,6 +79,13 @@ check_root SOURCE_DATE_EPOCH,SRCDEST,SRCPKGDEST,PKGDEST,LOGDEST,MAKEFLAGS,PACKAG
# Pass all arguments after -- right to makepkg
makechrootpkg_args+=("${@:$OPTIND}")
# Automatically recreate the root chroot if a version mismatch is detected
CURRENT_CHROOT_VERSION=$(cat "${chroots}/${repo}-${arch}/root/.arch-chroot")
if [[ -f "${chroots}/${repo}-${arch}/root/.arch-chroot" ]] && [[ "$CURRENT_CHROOT_VERSION" != "$CHROOT_VERSION" ]]; then
warning "Recreating chroot '%s' (%s) as it is not at version %s" "${chroots}/${repo}-${arch}/root" "$CURRENT_CHROOT_VERSION" "$CHROOT_VERSION"
clean_first=true
fi
if ${clean_first} || [[ ! -d "${chroots}/${repo}-${arch}" ]]; then
msg "Creating chroot for [%s] (%s)..." "${repo}" "${arch}"

View File

@@ -120,8 +120,20 @@ if (( ${#validpgpkeys[@]} != 0 )); then
git add --force -- keys/pgp/*
fi
needsversioning=()
if [[ ! -e REUSE.toml || ! -e LICENSE || ! -d LICENSES ]]; then
# TODO: Make this a hard failure in the future after packagers have had
# some time to add licenses to all packages.
warning "package doesn't have proper licensing information, set it up using:"
msg2 'pkgctl license setup'
else
pkgctl license check
needsversioning+=(REUSE.toml LICENSE LICENSES/*)
fi
# find files which should be under source control
needsversioning=(PKGBUILD)
needsversioning+=(PKGBUILD)
for s in "${source[@]}"; do
[[ $s != *://* ]] && needsversioning+=("$s")
done
@@ -143,7 +155,7 @@ if (( ${#needsversioning[*]} )); then
if [[ ! -f "${file}" ]]; then
continue
fi
if ! git ls-files --error-unmatch "$file"; then
if ! git ls-files --error-unmatch "$file" >/dev/null; then
die "%s is not under version control" "$file"
fi
done

View File

@@ -4,7 +4,7 @@
:
# shellcheck disable=2034
CHROOT_VERSION='v5'
CHROOT_VERSION='v6'
##
# usage : check_root $keepenv

View File

@@ -42,10 +42,10 @@ pkgctl_build_usage() {
Build packages inside a clean chroot
When a new pkgver is set using the appropriate PKGBUILD options the
checksums are automatically updated.
Build packages in clean chroot environment, offering various options
and functionalities to customize the package building process.
TODO
By default, chroot environments are located in /var/lib/archbuild/.
BUILD OPTIONS
--arch ARCH Specify architectures to build for (disables auto-detection)
@@ -55,6 +55,7 @@ pkgctl_build_usage() {
-o, --offload Build on a remote server and transfer artifacts afterwards
-c, --clean Recreate the chroot before building
--inspect WHEN Spawn an interactive shell to inspect the chroot (never, always, failure)
--offline MODE Run a part of the build process offline (build, check)
-w, --worker SLOT Name of the worker slot, useful for concurrent builds (disables automatic names)
--nocheck Do not run the check() function in the PKGBUILD
@@ -198,6 +199,10 @@ pkgctl_build() {
EDIT=1
shift
;;
--offline)
MAKECHROOT_OPTIONS+=("-o" "$2")
shift 2
;;
-o|--offload)
OFFLOAD=1
shift

View File

@@ -18,6 +18,9 @@ export LANG=C.UTF-8
# Avoid systemd trying to color the terminal on systemd-nspawn
export SYSTEMD_TINT_BACKGROUND=no
# Avoid diffoscope looking at remote debug info through readelf
unset DEBUGINFOD_URLS
# Set buildtool properties
export BUILDTOOL=devtools
export BUILDTOOLVER=@buildtoolver@

66
src/lib/license.sh Normal file
View File

@@ -0,0 +1,66 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_LICENSE_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_LICENSE_SH=1
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
set -e
pkgctl_license_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [COMMAND] [OPTIONS]
Check and manage package license compliance.
COMMANDS
check Check package license compliance
setup Automatically detect and setup a basic REUSE config
OPTIONS
-h, --help Show this help text
EXAMPLES
$ ${COMMAND} check libfoo linux libbar
$ ${COMMAND} setup libfoo
_EOF_
}
pkgctl_license() {
if (( $# < 1 )); then
pkgctl_license_usage
exit 0
fi
while (( $# )); do
case $1 in
-h|--help)
pkgctl_license_usage
exit 0
;;
check)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/license/check.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/license/check.sh
pkgctl_license_check "$@"
exit $?
;;
setup)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/license/setup.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/license/setup.sh
pkgctl_license_setup "$@"
exit 0
;;
*)
die "invalid argument: %s" "$1"
;;
esac
done
}

147
src/lib/license/check.sh Normal file
View File

@@ -0,0 +1,147 @@
#!/bin/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
[[ -z ${DEVTOOLS_INCLUDE_LICENSE_CHECK_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_LICENSE_CHECK_SH=1
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
# shellcheck source=src/lib/common.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
source /usr/share/makepkg/util/message.sh
set -eo pipefail
readonly PKGCTL_LICENSE_CHECK_EXIT_COMPLIANT=0
export PKGCTL_LICENSE_CHECK_EXIT_COMPLIANT
readonly PKGCTL_LICENSE_CHECK_EXIT_FAILURE=2
export PKGCTL_LICENSE_CHECK_EXIT_FAILURE
pkgctl_license_check_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS] [PKGBASE]...
Checks package licensing compliance using REUSE and also verifies
whether a LICENSE file with the expected Arch Linux-specific 0BSD
license text exists.
Upon execution, it runs 'reuse lint'.
OPTIONS
-h, --help Show this help text
EXAMPLES
$ ${COMMAND} neovim vim
_EOF_
}
pkgctl_license_check() {
local pkgbases=()
local verbose=0
local license_text
license_text=$(< "${_DEVTOOLS_LIBRARY_DIR}"/data/LICENSE)
local exit_code=${PKGCTL_LICENSE_CHECK_EXIT_COMPLIANT}
while (( $# )); do
case $1 in
-h|--help)
pkgctl_license_check_usage
exit 0
;;
--)
shift
break
;;
-*)
die "invalid argument: %s" "$1"
;;
*)
pkgbases=("$@")
break
;;
esac
done
if ! command -v reuse &>/dev/null; then
die "The \"$_DEVTOOLS_COMMAND\" command requires the 'reuse' CLI tool"
fi
# Check if used without pkgbases in a packaging directory
if (( ${#pkgbases[@]} == 0 )); then
if [[ -f PKGBUILD ]]; then
pkgbases=(".")
else
pkgctl_license_check_usage
exit 1
fi
fi
# enable verbose mode when we only have a single item to check
if (( ${#pkgbases[@]} == 1 )); then
verbose=1
fi
for path in "${pkgbases[@]}"; do
# skip paths that are not directories
if [[ ! -d "${path}" ]]; then
continue
fi
pushd "${path}" >/dev/null
if [[ ! -f PKGBUILD ]]; then
msg_error "${BOLD}${pkgbase}:${ALL_OFF} no PKGBUILD found"
return 1
fi
# reset common PKGBUILD variables
unset pkgbase
# shellcheck source=contrib/makepkg/PKGBUILD.proto
if ! . ./PKGBUILD; then
msg_error "${BOLD}${pkgbase}:${ALL_OFF} failed to source PKGBUILD"
return 1
fi
pkgbase=${pkgbase:-$pkgname}
if [[ ! -e LICENSE ]]; then
msg_error "${BOLD}${pkgbase}:${ALL_OFF} is missing the LICENSE file"
return "${PKGCTL_LICENSE_CHECK_EXIT_FAILURE}"
fi
if [[ ! -L LICENSES/0BSD.txt ]]; then
msg_error "${BOLD}${pkgbase}:${ALL_OFF} LICENSES/0BSD should be a symlink to LICENSE but it isn't"
return "${PKGCTL_LICENSE_CHECK_EXIT_FAILURE}"
fi
# Check if the local LICENSE file mismatches our expectations
if [[ $license_text != $(< LICENSE) ]]; then
msg_error "${BOLD}${pkgbase}:${ALL_OFF} LICENSE file doesn't have the expected Arch Linux-specific license text"
return "${PKGCTL_LICENSE_CHECK_EXIT_FAILURE}"
fi
# Check for REUSE compliance
if ! reuse lint --json | jq --exit-status '.summary.compliant' &>/dev/null; then
msg_error "${BOLD}${pkgbase}:${ALL_OFF} repository is not REUSE compliant"
exit_code=${PKGCTL_LICENSE_CHECK_EXIT_FAILURE}
# re-execute reuse lint for human readable output
if (( verbose )); then
reuse lint
fi
popd >/dev/null
continue
fi
msg_success "${BOLD}${pkgbase}:${ALL_OFF} repository is REUSE compliant"
popd >/dev/null
done
# return status based on results
return "${exit_code}"
}

271
src/lib/license/setup.sh Normal file
View File

@@ -0,0 +1,271 @@
#!/bin/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
[[ -z ${DEVTOOLS_INCLUDE_LICENSE_SETUP_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_LICENSE_SETUP_SH=1
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
# shellcheck source=src/lib/common.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
# shellcheck source=src/lib/license/check.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/license/check.sh
source /usr/share/makepkg/util/message.sh
set -eo pipefail
shopt -s nullglob
pkgctl_license_setup_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS] [PKGBASE]...
Automate the creation of a basic REUSE configuration by analyzing the
license array specified in the PKGBUILD file of a package.
If no PKGBASE is specified, the command defaults to using the current
working directory.
OPTIONS
-f, --force Overwrite existing REUSE configuration
-h, --help Show this help text
--no-check Do not run license check after setup
EXAMPLES
$ ${COMMAND} neovim vim
_EOF_
}
pkgctl_license_setup() {
local pkgbases=()
local force=0
local run_check=1
local path exit_code
local checks=()
while (( $# )); do
case $1 in
-h|--help)
pkgctl_license_setup_usage
exit 0
;;
-f|--force)
force=1
shift
;;
--no-check)
run_check=0
shift
;;
--)
shift
break
;;
-*)
die "invalid argument: %s" "$1"
;;
*)
pkgbases=("$@")
break
;;
esac
done
if ! command -v reuse &>/dev/null; then
die "The \"$_DEVTOOLS_COMMAND\" command requires the 'reuse' CLI tool"
fi
# Check if used without pkgbases in a packaging directory
if (( ${#pkgbases[@]} == 0 )); then
if [[ -f PKGBUILD ]]; then
pkgbases=(".")
else
pkgctl_license_setup_usage
exit 1
fi
fi
exit_code=0
for path in "${pkgbases[@]}"; do
# skip paths that are not directories
if [[ ! -d "${path}" ]]; then
continue
fi
pushd "${path}" >/dev/null
if license_setup "${path}" "${force}"; then
checks+=("${path}")
else
exit_code=1
fi
popd >/dev/null
done
# run checks on the setup targets
if (( run_check )) && (( ${#checks[@]} >= 1 )); then
echo
echo 📡 Running checks...
pkgctl_license_check "${checks[@]}" || true
fi
return "$exit_code"
}
license_setup() {
local path=$1
local force=$2
local pkgbase pkgname license
if [[ ! -f PKGBUILD ]]; then
msg_error "${BOLD}${path}:${ALL_OFF} no PKGBUILD found"
return 1
fi
# shellcheck source=contrib/makepkg/PKGBUILD.proto
if ! . ./PKGBUILD; then
msg_error "${BOLD}${path}:${ALL_OFF} failed to source PKGBUILD"
return 1
fi
pkgbase=${pkgbase:-$pkgname}
# setup LICENSE file
if ! license_file_setup "${pkgbase}" "${force}"; then
return 1
fi
# setup REUSE.toml
if ! reuse_setup "${pkgbase}" "${force}" "${license[@]}"; then
return 1
fi
}
is_valid_license() {
local license_name=$1
local supported_licenses
supported_licenses=$(reuse supported-licenses | awk '{print $1}')
if grep --quiet "^${license_name}$" <<< "$supported_licenses"; then
return 0
else
return 1
fi
}
license_file_setup() {
local pkgbase=$1
local force=$2
local license_text
license_text=$(< "${_DEVTOOLS_LIBRARY_DIR}"/data/LICENSE)
# Write LICENSE file, or check if it mismatches
if (( force )) || [[ ! -f LICENSE ]]; then
printf "%s\n" "${license_text}" > LICENSE
msg_success "${BOLD}${pkgbase}:${ALL_OFF} successfully configured LICENSE"
elif [[ -f LICENSE ]]; then
# if there is a license file, check whether it has the text we expect
existing_license="$(< LICENSE)"
if [[ "${license_text}" != "${existing_license}" ]]; then
msg_error "${BOLD}${pkgbase}:${ALL_OFF} existing LICENSE file doesn't have expected content, use --force to overwrite"
return 1
fi
fi
# make sure the LICENSE file is found by REUSE
mkdir --parents LICENSES
ln --symbolic --force ../LICENSE LICENSES/0BSD.txt
}
reuse_default_annotations() {
cat << EOF
version = 1
[[annotations]]
path = [
"PKGBUILD",
"README.md",
"keys/**",
".SRCINFO",
".nvchecker.toml",
"*.install",
"*.sysusers",
"*sysusers.conf",
"*.tmpfiles",
"*tmpfiles.conf",
"*.logrotate",
"*.pam",
"*.service",
"*.socket",
"*.timer",
"*.desktop",
"*.hook",
]
SPDX-FileCopyrightText = "Arch Linux contributors"
SPDX-License-Identifier = "0BSD"
EOF
}
reuse_setup() {
local pkgbase=$1
local force=$2
shift 2
local license=("$@")
# Check if REUSE.toml already exists
if (( ! force )) && [[ -f REUSE.toml ]]; then
msg_error "${BOLD}${pkgbase}:${ALL_OFF} REUSE.toml already exists, use --force to overwrite"
return 1
fi
reuse_default_annotations > REUSE.toml
local warning_occurred=0
local patches=(*.patch)
# If there are patches and there's only a single well-known license listed in the package,
# we can generate the annotations for the patches, otherwise we will fail to do so and warn
# the user.
if (( ${#patches} )); then
# If there are multiple licenses, we can't make a good guess about which license the
# patches should have. In case the first element contains a space, we are dealing with
# a complex SPDX license identifier.
if (( ${#license[@]} > 1 )) || [[ ${license[0]} =~ [[:space:]] ]]; then
msg_warn "${BOLD}${pkgbase}:${ALL_OFF} .patch files were found but couldn't automatically guess a suitable license because PKGBUILD has multiple licenses"
patch_annotations "${pkgbase}" "TODO-Choose-a-license" "${patches[@]}" >> REUSE.toml
warning_occurred=1
elif ! is_valid_license "${license[0]}"; then
msg_warn "${BOLD}${pkgbase}:${ALL_OFF} .patch files were found but couldn't automatically guess a suitable license because the PKGBUILD license '${license[0]}' is not a recognized SPDX license"
patch_annotations "${pkgbase}" "TODO-Choose-a-license" "${patches[@]}" >> REUSE.toml
warning_occurred=1
else
patch_annotations "${pkgbase}" "${license[0]}" "${patches[@]}" >> REUSE.toml
fi
fi
if (( warning_occurred )); then
msg_warn "${BOLD}${pkgbase}:${ALL_OFF} configured REUSE but a warning occurred, manually edit and fix REUSE.toml"
return 1
else
reuse download --all
msg_success "${BOLD}${pkgbase}:${ALL_OFF} successfully configured REUSE.toml"
fi
}
patch_annotations() {
local pkgbase=$1
local license_identifier=$2
shift 2
local patches=("$@")
local annotations
annotations+="\n[[annotations]]\n"
annotations+="path = [\n"
for patch in "${patches[@]}"; do
annotations+=" \"$(basename "${patch}")\",\n"
done
annotations+="]\n"
annotations+="SPDX-FileCopyrightText = \"${pkgbase} contributors\"\n"
annotations+="SPDX-License-Identifier = \"${license_identifier}\""
echo -e "${annotations}"
}

View File

@@ -40,6 +40,8 @@ bindmounts_ro=()
bindmounts_rw=()
bindmounts_tmpfs=()
offline_options=()
copy=$USER
[[ -n ${SUDO_USER:-} ]] && copy=$SUDO_USER
[[ -z "$copy" || $copy = root ]] && copy=copy
@@ -80,6 +82,7 @@ usage() {
echo ' Useful for maintaining multiple copies'
echo " Default: $copy"
echo '-n Run namcap on the package'
echo '-o Run given step offline'
echo '-C Run checkpkg on the package'
echo '-T Build in a temporary directory'
echo '-U Run makepkg as a specified user'
@@ -203,6 +206,7 @@ EOF
declare -p SOURCE_DATE_EPOCH 2>/dev/null || true
declare -p BUILDTOOL 2>/dev/null
declare -p BUILDTOOLVER 2>/dev/null
declare -p offline_options
printf '_chrootbuild "$@" || exit\n'
if (( run_namcap )); then
@@ -222,14 +226,52 @@ _chrootbuild() {
# shellcheck source=/dev/null
. /etc/profile
# for in_array
. /usr/share/makepkg/util.sh
# Beware, there are some stupid arbitrary rules on how you can
# use "$" in arguments to commands with "sudo -i". ${foo} or
# ${1} is OK, but $foo or $1 isn't.
# https://bugzilla.sudo.ws/show_bug.cgi?id=765
# Run prepare
sudo --preserve-env=SOURCE_DATE_EPOCH \
--preserve-env=BUILDTOOL \
--preserve-env=BUILDTOOLVER \
-iu builduser bash -c 'cd /startdir; makepkg "$@"' -bash "$@"
-iu builduser bash -c 'cd /startdir; makepkg --nobuild "$@"' -bash "$@"
if in_array "build" "${offline_options[@]}"; then
msg "building offline"
# Build offline
unshare -n -- sudo --preserve-env=SOURCE_DATE_EPOCH \
--preserve-env=BUILDTOOL \
--preserve-env=BUILDTOOLVER \
-iu builduser \
bash -c 'cd /startdir; makepkg --noprepare --noextract --nocheck "$@"' -bash "$@"
else
sudo --preserve-env=SOURCE_DATE_EPOCH \
--preserve-env=BUILDTOOL \
--preserve-env=BUILDTOOLVER \
-iu builduser \
bash -c 'cd /startdir; makepkg --noprepare --noextract --nocheck "$@"' -bash "$@"
fi
if in_array "check" "${offline_options[@]}"; then
msg "check offline"
# Run tests online
unshare -n -- sudo --preserve-env=SOURCE_DATE_EPOCH \
--preserve-env=BUILDTOOL \
--preserve-env=BUILDTOOLVER \
-iu builduser \
bash -c 'cd /startdir; makepkg --noprepare --noextract --nobuild "$@"' -bash "$@"
else
sudo --preserve-env=SOURCE_DATE_EPOCH \
--preserve-env=BUILDTOOL \
--preserve-env=BUILDTOOLVER \
-iu builduser \
bash -c 'cd /startdir; makepkg --noprepare --noextract --nobuild "$@"' -bash "$@"
fi
ret=$?
case $ret in
0|14)
@@ -293,7 +335,7 @@ move_products() {
}
# }}}
while getopts 'hcur:I:l:nCTD:d:U:x:t:' arg; do
while getopts 'hcur:I:l:nCTD:o:d:U:x:t:' arg; do
case "$arg" in
c) clean_first=1 ;;
D) bindmounts_ro+=("--bind-ro=$OPTARG") ;;
@@ -304,6 +346,7 @@ while getopts 'hcur:I:l:nCTD:d:U:x:t:' arg; do
I) install_pkgs+=("$OPTARG") ;;
l) copy="$OPTARG" ;;
n) run_namcap=1; makepkg_args+=(--install) ;;
o) offline_options+=("$OPTARG") ;;
C) run_checkpkg=1 ;;
T) temp_chroot=1; copy+="-$$" ;;
U) makepkg_user="$OPTARG" ;;

View File

@@ -93,14 +93,36 @@ get_makepkg_conf() {
local fname=${1}
local arch="${2}"
local makepkg_conf="${3}"
if ! buildtool_file=$(get_pkgfile "${fname}"); then
error "failed to retrieve ${fname}"
error "failed to retrieve ${fname}"
return 1
fi
buildtool_file="${buildtool_file/file:\/\//}"
msg "using makepkg.conf from ${fname}"
# try to handle config of legacy devtools
if bsdtar --list --file "${buildtool_file}" "usr/share/devtools/makepkg-${arch}.conf" &>/dev/null; then
bsdtar --extract --to-stdout --fast-read --file "${buildtool_file}" "usr/share/devtools/makepkg-${arch}.conf" > "${makepkg_conf}"
return $?
fi
msg2 "extracting ${arch}.conf from devtools archive"
if ! bsdtar --extract --to-stdout --fast-read --file "${buildtool_file}" "usr/share/devtools/makepkg.conf.d/${arch}.conf" > "${makepkg_conf}"; then
error "failed to extract 'usr/share/devtools/makepkg.conf.d/${arch}.conf' from devtools archive"
return 1
fi
msg2 "using makepkg.conf from ${fname}"
if ! bsdtar xOqf "${buildtool_file/file:\/\//}" "usr/share/devtools/makepkg.conf.d/${arch}.conf" > "${makepkg_conf}"; then
bsdtar xOqf "${buildtool_file/file:\/\//}" "usr/share/devtools/makepkg-${arch}.conf" > "${makepkg_conf}"
fi
mkdir --parents "${makepkg_conf}.d"
if bsdtar --list --file "${buildtool_file}" "usr/share/devtools/makepkg.conf.d/conf.d" &>/dev/null; then
msg2 "extracting conf.d from devtools archive"
bsdtar --extract --file "${buildtool_file}" --cd "${makepkg_conf}.d" --strip-components 4 "usr/share/devtools/makepkg.conf.d/conf.d"
fi
if bsdtar --list --file "${buildtool_file}" "usr/share/devtools/makepkg.conf.d/${arch}.conf.d" &>/dev/null; then
msg2 "extracting ${arch}.conf.d from devtools archive"
bsdtar --extract --file "${buildtool_file}" --cd "${makepkg_conf}.d" --strip-components 4 "usr/share/devtools/makepkg.conf.d/${arch}.conf.d"
fi
return 0
}
@@ -186,7 +208,7 @@ for f in "${splitpkgs[@]}"; do
done
if (( ${#cache_dirs[@]} == 0 )); then
mapfile -t cache_dirs < <(pacman-conf CacheDir)
mapfile -t cache_dirs < <(pacman-conf CacheDir)
fi
ORIG_HOME=${HOME}

View File

@@ -25,6 +25,7 @@ usage() {
db Pacman database modification for package update, move etc
diff Compare package files using different modes
issue Work with GitLab packaging issues
license Check and manage package licenses
release Release step to commit, tag and upload build artifacts
repo Manage Git packaging repositories and their configuration
search Search for an expression across the GitLab packaging group
@@ -113,6 +114,14 @@ while (( $# )); do
pkgctl_issue "$@"
exit 0
;;
license)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/license.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/license.sh
pkgctl_license "$@"
exit 0
;;
release)
_DEVTOOLS_COMMAND+=" $1"
shift