mirror of
				https://gitlab.archlinux.org/archlinux/devtools.git
				synced 2025-10-30 23:34:43 +01:00 
			
		
		
		
	Compare commits
	
		
			10 Commits
		
	
	
		
			morten/reu
			...
			dd458f61c9
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | dd458f61c9 | ||
|   | fc56ebedf3 | ||
|   | 01757e6904 | ||
|   | c5fe8ff3e6 | ||
|   | ad7dd50bf3 | ||
|   | 5a381835e8 | ||
|   | b8c475b3f4 | ||
|   | 74cd46f092 | ||
|   | 773f8d5c0e | ||
|   | 538604fead | 
							
								
								
									
										14
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								Makefile
									
									
									
									
									
								
							| @@ -1,6 +1,6 @@ | ||||
| SHELL=/bin/bash -o pipefail | ||||
|  | ||||
| V=1.3.2 | ||||
| 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) | ||||
| @@ -112,6 +113,10 @@ conf: | ||||
| 	@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) | ||||
| 	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 | ||||
| @@ -143,6 +150,7 @@ uninstall: | ||||
| 	rm -rf $(DESTDIR)$(DATADIR)/lib | ||||
| 	rm -rf $(DESTDIR)$(DATADIR)/git.conf.d | ||||
| 	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 | ||||
| @@ -186,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: | ||||
|   | ||||
| @@ -94,6 +94,7 @@ Component: pkgctl db remove | ||||
|  | ||||
| - bat (pretty printing) | ||||
| - nvchecker (version checking) | ||||
| - reuse (license compliance) | ||||
|  | ||||
| ### Development Dependencies | ||||
|  | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
| /src | ||||
| /*/ | ||||
| !/keys/ | ||||
| !/LICENSES/ | ||||
|  | ||||
| /*.log | ||||
| /*.tar.* | ||||
|   | ||||
| @@ -1,4 +1,6 @@ | ||||
| #!/hint/bash | ||||
| # shellcheck disable=2034 | ||||
|  | ||||
| # | ||||
| # /etc/makepkg.conf.d/fortran.conf | ||||
| # | ||||
| @@ -9,10 +11,12 @@ | ||||
|  | ||||
| # Flags used for the Fortran compiler, similar in spirit to CFLAGS. Read | ||||
| # linkman:gfortran[1] for more details on the available flags. | ||||
| #FFLAGS="-O2 -pipe" | ||||
| #FCFLAGS="$FFLAGS" | ||||
| 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" | ||||
| DEBUG_FFLAGS="-g" | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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
									
								
							
							
						
						
									
										12
									
								
								data/LICENSE
									
									
									
									
									
										Normal 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. | ||||
							
								
								
									
										54
									
								
								doc/man/pkgctl-license-check.1.asciidoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								doc/man/pkgctl-license-check.1.asciidoc
									
									
									
									
									
										Normal 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[] | ||||
							
								
								
									
										55
									
								
								doc/man/pkgctl-license-setup.1.asciidoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								doc/man/pkgctl-license-setup.1.asciidoc
									
									
									
									
									
										Normal 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[] | ||||
							
								
								
									
										54
									
								
								doc/man/pkgctl-license.1.asciidoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								doc/man/pkgctl-license.1.asciidoc
									
									
									
									
									
										Normal 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[] | ||||
| @@ -120,16 +120,20 @@ if (( ${#validpgpkeys[@]} != 0 )); then | ||||
| 	git add --force -- keys/pgp/* | ||||
| fi | ||||
|  | ||||
| # Allow us to disable REUSE | ||||
| _RUN_REUSE=${_RUN_REUSE:-1} | ||||
| if ((_RUN_REUSE)); then | ||||
| 	reuse download | ||||
| 	reuse lint | ||||
| 	git add --force -- LICENSES/* | ||||
| 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 | ||||
| @@ -151,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 | ||||
|   | ||||
							
								
								
									
										66
									
								
								src/lib/license.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/lib/license.sh
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										147
									
								
								src/lib/license/check.sh
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										271
									
								
								src/lib/license/setup.sh
									
									
									
									
									
										Normal 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}" | ||||
| } | ||||
| @@ -20,6 +20,7 @@ shopt -s nullglob | ||||
| default_makepkg_args=(--syncdeps --noconfirm --log --holdver --skipinteg) | ||||
| makepkg_args=("${default_makepkg_args[@]}") | ||||
| verifysource_args=() | ||||
| archnspawn_args=() | ||||
| chrootdir= | ||||
| passeddir= | ||||
| makepkg_user= | ||||
| @@ -80,6 +81,7 @@ usage() { | ||||
| 	echo '                  Useful for maintaining multiple copies' | ||||
| 	echo "                  Default: $copy" | ||||
| 	echo '-n                Run namcap on the package' | ||||
| 	echo "-s                Do not run setarch" | ||||
| 	echo '-C                Run checkpkg on the package' | ||||
| 	echo '-T                Build in a temporary directory' | ||||
| 	echo '-U                Run makepkg as a specified user' | ||||
| @@ -150,7 +152,7 @@ install_packages() { | ||||
| 	pkgnames=("${install_pkgs[@]##*/}") | ||||
|  | ||||
| 	cp -- "${install_pkgs[@]}" "$copydir/root/" | ||||
| 	arch-nspawn "$copydir" "${bindmounts_ro[@]}" "${bindmounts_rw[@]}" "${bindmounts_tmpfs[@]}" \ | ||||
| 	arch-nspawn "${archnspawn_args[@]}" "$copydir" "${bindmounts_ro[@]}" "${bindmounts_rw[@]}" "${bindmounts_tmpfs[@]}" \ | ||||
| 		pacman -U --noconfirm --ask=4 -- "${pkgnames[@]/#//root/}" | ||||
| 	ret=$? | ||||
| 	rm -- "${pkgnames[@]/#/$copydir/root/}" | ||||
| @@ -293,7 +295,7 @@ move_products() { | ||||
| } | ||||
| # }}} | ||||
|  | ||||
| while getopts 'hcur:I:l:nCTD:d:U:x:t:' arg; do | ||||
| while getopts 'hcur:sI:l:nCTD:d:U:x:t:' arg; do | ||||
| 	case "$arg" in | ||||
| 		c) clean_first=1 ;; | ||||
| 		D) bindmounts_ro+=("--bind-ro=$OPTARG") ;; | ||||
| @@ -301,6 +303,7 @@ while getopts 'hcur:I:l:nCTD:d:U:x:t:' arg; do | ||||
| 		t) bindmounts_tmpfs+=("--tmpfs=$OPTARG") ;; | ||||
| 		u) update_first=1 ;; | ||||
| 		r) passeddir="$OPTARG" ;; | ||||
| 		s) archnspawn_args+=("-s") ;; | ||||
| 		I) install_pkgs+=("$OPTARG") ;; | ||||
| 		l) copy="$OPTARG" ;; | ||||
| 		n) run_namcap=1; makepkg_args+=(--install) ;; | ||||
| @@ -367,7 +370,7 @@ if [[ ! -d $copydir ]] || (( clean_first )); then | ||||
| 	sync_chroot "$chrootdir" "$copydir" "$copy" | ||||
| fi | ||||
|  | ||||
| (( update_first )) && arch-nspawn "$copydir" \ | ||||
| (( update_first )) && arch-nspawn "${archnspawn_args[@]}" "$copydir" \ | ||||
| 		"${bindmounts_ro[@]}" "${bindmounts_rw[@]}" "${bindmounts_tmpfs[@]}" \ | ||||
| 		pacman -Syuu --noconfirm | ||||
|  | ||||
| @@ -396,7 +399,7 @@ nspawn_build_args=( | ||||
| 	"${bindmounts_tmpfs[@]}" | ||||
| ) | ||||
|  | ||||
| if arch-nspawn "$copydir" \ | ||||
| if arch-nspawn "${archnspawn_args[@]}" "$copydir" \ | ||||
| 	"${nspawn_build_args[@]}" \ | ||||
| 	/chrootbuild "${makepkg_args[@]}" | ||||
| then | ||||
| @@ -444,7 +447,7 @@ else | ||||
| 		for remotepkg in "${remotepkgs[@]}"; do | ||||
| 			if [[ $remotepkg != file://* ]]; then | ||||
| 				msg2 "Downloading current versions" | ||||
| 				arch-nspawn "$copydir" pacman --noconfirm -Swdd "${pkgnames[@]}" | ||||
| 				arch-nspawn "${archnspawn_args[@]}" "$copydir" pacman --noconfirm -Swdd "${pkgnames[@]}" | ||||
| 				mapfile -t remotepkgs < <(pacman --config "$copydir"/etc/pacman.conf \ | ||||
| 					--dbpath "$copydir"/var/lib/pacman \ | ||||
| 					-Sddp "${pkgnames[@]}") | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user