Compare commits

..

1 Commits

Author SHA1 Message Date
Levente Polyak
d7c7074457 feat(release): allow releasing from unstable branch to unstable repos
This is done in order to properly support the build workflow for gnome-unstable.
If one tries to release from branch "unstable" to a regular repo an error is emitted.

Co-authored-by: Christian Heusel <christian@heusel.eu>
2023-08-09 18:10:35 +02:00
146 changed files with 361 additions and 5238 deletions

View File

@@ -8,37 +8,14 @@ build:
stage: build
needs: []
script:
- pacman -Syu --noconfirm m4 make openssh subversion rsync arch-install-scripts git bzr mercurial diffutils asciidoctor
- pacman -Syu --noconfirm m4 make openssh subversion rsync arch-install-scripts git bzr mercurial diffutils asciidoc
- make PREFIX=/usr
- make PREFIX=/usr DESTDIR=build install
lint:
check:
stage: test
needs: []
script:
- pacman -Syu --noconfirm m4 make openssh subversion rsync arch-install-scripts git bzr mercurial diffutils asciidoctor shellcheck
- pacman -Syu --noconfirm m4 make openssh subversion rsync arch-install-scripts git bzr mercurial diffutils asciidoc shellcheck
- make check || true
- SHELLCHECK_OPTS="-S error" make check
test:
stage: test
needs: []
script:
- pacman -Syu --noconfirm m4 make openssh subversion rsync arch-install-scripts git bzr mercurial diffutils coreutils asciidoctor shellcheck nvchecker bats
- make test BATS_EXTRA_ARGS='--formatter junit'
artifacts:
reports:
junit: build/coverage/bats-report.xml
coverage:
stage: test
needs: []
script:
- pacman -Syu --noconfirm m4 make openssh subversion rsync arch-install-scripts git bzr mercurial diffutils coreutils asciidoctor shellcheck nvchecker bats kcov jq
- make coverage
coverage: '/Percent covered\s+\d+\.\d+/'
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: build/coverage/bats.*/cobertura.xml

View File

@@ -1,6 +1,6 @@
SHELL=/bin/bash -o pipefail
SHELL=/bin/bash
V=1.2.0
V=1.0.3
BUILDTOOLVER ?= $(V)
PREFIX = /usr/local
@@ -16,7 +16,6 @@ LIBRARY_SRC = $(call rwildcard,src/lib,*.sh)
LIBRARY = $(addprefix $(BUILDDIR)/,$(patsubst src/%,%,$(patsubst %.in,%,$(LIBRARY_SRC))))
MAKEPKG_CONFIGS=$(wildcard config/makepkg/*)
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)))
@@ -52,13 +51,6 @@ ARCHBUILD_LINKS = \
COMPLETIONS = $(addprefix $(BUILDDIR)/,$(patsubst %.in,%,$(wildcard contrib/completion/*/*)))
CASES ?= test/case
JOBS ?= $(shell nproc)
BATS_EXTRA_ARGS ?=
BATS_ARGS ?= --jobs $(JOBS) $(BATS_EXTRA_ARGS) --verbose-run
COVERAGE_DIR ?= $(BUILDDIR)/coverage
all: binprogs library conf completion man
binprogs: $(BINPROGS)
library: $(LIBRARY)
@@ -99,18 +91,15 @@ $(eval $(call buildInScript,build/bin,src/,.in,755))
$(eval $(call buildInScript,build/lib,src/lib/,,644))
$(foreach completion,$(wildcard contrib/completion/*),$(eval $(call buildInScript,build/$(completion),$(completion)/,.in,444)))
$(BUILDDIR)/doc/man/%: doc/man/%.asciidoc doc/man/include/footer.asciidoc
$(BUILDDIR)/doc/man/%: doc/man/%.asciidoc doc/asciidoc.conf doc/man/include/footer.asciidoc
$(GEN_MSG)
@mkdir -p $(BUILDDIR)/doc/man
@asciidoctor --backend=manpage --destination-dir=$(BUILDDIR)/doc/man --attribute pkgdatadir=$(DATADIR) $<
@a2x --no-xmllint --asciidoc-opts="-f doc/asciidoc.conf" -d manpage -f manpage --destination-dir=$(BUILDDIR)/doc/man -a pkgdatadir=$(DATADIR) $<
conf:
@install -d $(BUILDDIR)/makepkg.conf.d
@install -d $(BUILDDIR)/makepkg.conf.d $(BUILDDIR)/pacman.conf.d
@cp -a $(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
clean:
rm -rf $(BUILDDIR)
@@ -123,7 +112,6 @@ install: all
install -m0755 ${BINPROGS} $(DESTDIR)$(PREFIX)/bin
install -dm0755 $(DESTDIR)$(DATADIR)/lib
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
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
@@ -141,7 +129,6 @@ uninstall:
for f in $(notdir $(BINPROGS)); do rm -f $(DESTDIR)$(PREFIX)/bin/$$f; done
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
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
@@ -159,7 +146,6 @@ uninstall:
$(DESTDIR)$(DATADIR)
tag:
git cliff --strip=all --unreleased
@echo "current version: v$(V)"
@read -r -p "tag version: v" VERSION && \
sed -E "s|^V=.+|V=$$VERSION|" -i Makefile && \
@@ -167,25 +153,14 @@ tag:
git tag --sign --message "Version v$$VERSION" v$$VERSION
release: dist
git push --tags origin master
git cliff --version >/dev/null
GITLAB_HOST=gitlab.archlinux.org glab release create v$(V) devtools-$(V).tar.gz* --milestone v$(V) --notes-file <(git cliff --strip=all --latest)
glab release create v$(V) devtools-$(V).tar.gz*
dist:
git archive --format=tar --prefix=devtools-$(V)/ v$(V) | gzip > devtools-$(V).tar.gz
gpg --detach-sign --use-agent devtools-$(V).tar.gz
test: binprogs library conf completion man
@mkdir -p $(COVERAGE_DIR)
bats $(BATS_ARGS) $(CASES) | tee $(COVERAGE_DIR)/bats-report.xml
coverage: binprogs library conf completion man
kcov --include-path=src $(COVERAGE_DIR) bats $(BATS_ARGS) $(CASES)
jq -r '. | ["Percent covered", .percent_covered], ["Covered lines", .covered_lines], ["Total lines", .total_lines], ["Percent low", .percent_low], ["Percent high", .percent_high] | @tsv' \
$(COVERAGE_DIR)/bats.*/coverage.json
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 clean install uninstall tag dist upload check
.DELETE_ON_ERROR:

View File

@@ -23,34 +23,6 @@ will automatically build the project and proxy all calls to the local build dire
./test/bin/pkgctl --help
```
### Commit messages
All commits must follow [conventional commits](https://www.conventionalcommits.org).
The following groups are allowed:
- chore
- feat
- fix
- doc
- perf
- test
To override the scope for the changelog entry use the `Component:` trailer.
Example:
```
feat(db): yay mega cool feature
Very long and useful description.
Fixes #1
Fixes #2
Component: pkgctl db remove
```
## Releasing
1. bump the version in the Makefile
@@ -69,9 +41,7 @@ Component: pkgctl db remove
- bash
- binutils
- coreutils
- curl
- diffutils
- expac
- fakeroot
- findutils
- grep
@@ -88,17 +58,11 @@ Component: pkgctl db remove
- mercurial
- subversion
### Optional Dependencies
- bat (pretty printing)
- nvchecker (version checking)
### Development Dependencies
- asciidoctor
- asciidoc
- make
- shellcheck
- bats
## License

View File

@@ -1,45 +0,0 @@
[changelog]
header = "# Changelog\n\n"
body = """
{%- if version -%}
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
{%- else -%}
## [unreleased]
{%- endif %}
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | upper_first }}
{% for commit in commits | sort(attribute="message") %}
- {% set component = commit.footers | filter(attribute="token", value="Component") | map(attribute="value") | join(sep=", ") %}
{%- if component %}{{ component }}: {% elif commit.scope %}{{ commit.scope }}: {% endif %}
{{- commit.message | upper_first }}
{%- if commit.breaking %} (breaking){% endif %}
{%- set fixes = commit.footers | filter(attribute="token", value="Fixes") %}
{%- for fix in fixes %}{% if fix.separator|trim == '#' %}{{ fix.separator }}{{ fix.value }}{% endif %}{% endfor %}
{%- endfor %}
{% endfor %}
"""
footer = ""
# remove the leading and trailing whitespaces from the template
trim = true
[git]
# allow only conventional commits
# https://www.conventionalcommits.org
conventional_commits = true
# regex for parsing and grouping commits
commit_parsers = [
{ message = "^chore\\(release\\): version", skip = true},
{ message = "^feat", group = "Features"},
{ message = "^fix", group = "Bug Fixes"},
{ message = "^doc", group = "Documentation"},
{ message = "^perf", group = "Performance"},
{ message = "^test", group = "Testing"},
{ message = "^chore", group = "Miscellaneous Tasks"},
{ body = ".*security", group = "Security"},
]
# filter out the commits that are not matched by commit parsers
filter_commits = false
# regex for matching git tags
tag_pattern = "^v[0-9]+\\.[0-9]+\\.[0-9]+.*"

View File

@@ -1 +0,0 @@
#!/bin/sh

View File

@@ -1 +0,0 @@
#!/bin/sh

View File

@@ -1 +0,0 @@
#!/bin/sh

View File

@@ -1 +0,0 @@
#!/bin/sh

View File

@@ -1 +0,0 @@
#!/bin/sh

View File

@@ -1 +0,0 @@
#!/bin/sh

View File

@@ -1 +0,0 @@
#!/bin/sh

View File

@@ -1 +0,0 @@
#!/bin/sh

View File

@@ -1 +0,0 @@
#!/bin/sh

View File

@@ -1 +0,0 @@
#!/bin/sh

View File

@@ -1 +0,0 @@
#!/bin/sh

View File

@@ -1 +0,0 @@
#!/bin/sh

View File

@@ -1,28 +0,0 @@
/pkg
/src
/*/
!/keys/
/*.log
/*.tar.*
/*.tar
/*.tgz
/*.zst
/*.gz
/*.xz
/*.bz2
/*.zip
/*.xpi
/*.jar
/*.whl
/*.war
/*.deb
/*.ttf
/*.dat
/*.iso
/*.asc
/*.sig
/*.signature
/*.sign
/*.SHA256SUMS
/*.sha256

View File

@@ -25,7 +25,7 @@ DLAGENTS=('file::/usr/bin/curl -qgC - -o %o %u'
#-- The package required by makepkg to download VCS sources
# Format: 'protocol::package'
VCSCLIENTS=('bzr::breezy'
VCSCLIENTS=('bzr::bzr'
'fossil::fossil'
'git::git'
'hg::mercurial'
@@ -41,14 +41,12 @@ CHOST="x86_64-pc-linux-gnu"
#-- Compiler and Linker Flags
#CPPFLAGS=""
CFLAGS="-march=x86-64 -mtune=generic -O2 -pipe -fno-plt -fexceptions \
-Wp,-D_FORTIFY_SOURCE=3 -Wformat -Werror=format-security \
-fstack-clash-protection -fcf-protection \
-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer"
-Wp,-D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security \
-fstack-clash-protection -fcf-protection"
CXXFLAGS="$CFLAGS -Wp,-D_GLIBCXX_ASSERTIONS"
LDFLAGS="-Wl,-O1 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro -Wl,-z,now \
-Wl,-z,pack-relative-relocs"
LDFLAGS="-Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now"
LTOFLAGS="-flto=auto"
RUSTFLAGS="-Cforce-frame-pointers=yes"
RUSTFLAGS=""
#-- Make Flags: change this for DistCC/SMP systems
#MAKEFLAGS="-j2"
#-- Debugging flags

View File

@@ -25,7 +25,7 @@ DLAGENTS=('file::/usr/bin/curl -qgC - -o %o %u'
#-- The package required by makepkg to download VCS sources
# Format: 'protocol::package'
VCSCLIENTS=('bzr::breezy'
VCSCLIENTS=('bzr::bzr'
'fossil::fossil'
'git::git'
'hg::mercurial'
@@ -41,14 +41,12 @@ CHOST="x86_64-pc-linux-gnu"
#-- Compiler and Linker Flags
#CPPFLAGS=""
CFLAGS="-march=x86-64-v3 -mtune=generic -O2 -pipe -fno-plt -fexceptions \
-Wp,-D_FORTIFY_SOURCE=3 -Wformat -Werror=format-security \
-fstack-clash-protection -fcf-protection \
-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer"
-Wp,-D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security \
-fstack-clash-protection -fcf-protection"
CXXFLAGS="$CFLAGS -Wp,-D_GLIBCXX_ASSERTIONS"
LDFLAGS="-Wl,-O1 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro -Wl,-z,now \
-Wl,-z,pack-relative-relocs"
LDFLAGS="-Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now"
LTOFLAGS="-flto=auto"
RUSTFLAGS="-Cforce-frame-pointers=yes"
RUSTFLAGS=""
#-- Make Flags: change this for DistCC/SMP systems
#MAKEFLAGS="-j2"
#-- Debugging flags

View File

@@ -1,112 +0,0 @@
#
# /etc/pacman.conf
#
# See the pacman.conf(5) manpage for option and repository directives
#
# GENERAL OPTIONS
#
[options]
# The following paths are commented out with their default values listed.
# If you wish to use different paths, uncomment and update the paths.
#RootDir = /
#DBPath = /var/lib/pacman/
#CacheDir = /var/cache/pacman/pkg/
#LogFile = /var/log/pacman.log
#GPGDir = /etc/pacman.d/gnupg/
#HookDir = /etc/pacman.d/hooks/
HoldPkg = pacman glibc
#XferCommand = /usr/bin/curl -L -C - -f -o %o %u
#XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u
#CleanMethod = KeepInstalled
Architecture = auto
# Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup
#IgnorePkg =
#IgnoreGroup =
#NoUpgrade =
#NoExtract =
# Misc options
#UseSyslog
#Color
NoProgressBar
# We cannot check disk space from within a chroot environment
#CheckSpace
VerbosePkgLists
ParallelDownloads = 5
# By default, pacman accepts packages signed by keys that its local keyring
# trusts (see pacman-key and its man page), as well as unsigned packages.
SigLevel = Required DatabaseOptional
LocalFileSigLevel = Optional
#RemoteFileSigLevel = Required
# NOTE: You must run `pacman-key --init` before first using pacman; the local
# keyring can then be populated with the keys of all official Arch Linux
# packagers with `pacman-key --populate archlinux`.
#
# REPOSITORIES
# - can be defined here or included from another file
# - pacman will search repositories in the order defined here
# - local/custom mirrors can be added here or in separate files
# - repositories listed first will take precedence when packages
# have identical names, regardless of version number
# - URLs will have $repo replaced by the name of the current repo
# - URLs will have $arch replaced by the name of the architecture
#
# Repository entries are of the format:
# [repo-name]
# Server = ServerName
# Include = IncludePath
#
# The header [repo-name] is crucial - it must be present and
# uncommented to enable the repo.
#
# The testing repositories are disabled by default. To enable, uncomment the
# repo name header and Include lines. You can add preferred servers immediately
# after the header, and they will be used before the default mirrors.
[gnome-unstable]
Include = /etc/pacman.d/mirrorlist
[kde-unstable]
Include = /etc/pacman.d/mirrorlist
[core-staging]
Include = /etc/pacman.d/mirrorlist
[core-testing]
Include = /etc/pacman.d/mirrorlist
[core]
Include = /etc/pacman.d/mirrorlist
[extra-staging]
Include = /etc/pacman.d/mirrorlist
[extra-testing]
Include = /etc/pacman.d/mirrorlist
[extra]
Include = /etc/pacman.d/mirrorlist
# If you want to run 32 bit applications on your x86_64 system,
# enable the multilib repositories as required here.
[multilib-staging]
Include = /etc/pacman.d/mirrorlist
[multilib-testing]
Include = /etc/pacman.d/mirrorlist
[multilib]
Include = /etc/pacman.d/mirrorlist
# An example of a custom package repository. See the pacman manpage for
# tips on creating your own repositories.
#[custom]
#SigLevel = Optional TrustAll
#Server = file:///home/custompkgs

View File

@@ -1,83 +0,0 @@
#
# /etc/pacman.conf
#
# See the pacman.conf(5) manpage for option and repository directives
#
# GENERAL OPTIONS
#
[options]
# The following paths are commented out with their default values listed.
# If you wish to use different paths, uncomment and update the paths.
#RootDir = /
#DBPath = /var/lib/pacman/
#CacheDir = /var/cache/pacman/pkg/
#LogFile = /var/log/pacman.log
#GPGDir = /etc/pacman.d/gnupg/
#HookDir = /etc/pacman.d/hooks/
HoldPkg = pacman glibc
#XferCommand = /usr/bin/curl -L -C - -f -o %o %u
#XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u
#CleanMethod = KeepInstalled
Architecture = auto
# Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup
#IgnorePkg =
#IgnoreGroup =
#NoUpgrade =
#NoExtract =
# Misc options
#UseSyslog
#Color
NoProgressBar
# We cannot check disk space from within a chroot environment
#CheckSpace
VerbosePkgLists
ParallelDownloads = 5
# By default, pacman accepts packages signed by keys that its local keyring
# trusts (see pacman-key and its man page), as well as unsigned packages.
SigLevel = Required DatabaseOptional
LocalFileSigLevel = Optional
#RemoteFileSigLevel = Required
# NOTE: You must run `pacman-key --init` before first using pacman; the local
# keyring can then be populated with the keys of all official Arch Linux
# packagers with `pacman-key --populate archlinux`.
#
# REPOSITORIES
# - can be defined here or included from another file
# - pacman will search repositories in the order defined here
# - local/custom mirrors can be added here or in separate files
# - repositories listed first will take precedence when packages
# have identical names, regardless of version number
# - URLs will have $repo replaced by the name of the current repo
# - URLs will have $arch replaced by the name of the architecture
#
# Repository entries are of the format:
# [repo-name]
# Server = ServerName
# Include = IncludePath
#
# The header [repo-name] is crucial - it must be present and
# uncommented to enable the repo.
#
# The testing repositories are disabled by default. To enable, uncomment the
# repo name header and Include lines. You can add preferred servers immediately
# after the header, and they will be used before the default mirrors.
[gnome-unstable]
Include = /etc/pacman.d/mirrorlist
[kde-unstable]
Include = /etc/pacman.d/mirrorlist
# An example of a custom package repository. See the pacman manpage for
# tips on creating your own repositories.
#[custom]
#SigLevel = Optional TrustAll
#Server = file:///home/custompkgs

View File

@@ -3,17 +3,12 @@
# SPDX-License-Identifier: GPL-3.0-or-later
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
# shellcheck source=src/lib/valid-build-install.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-build-install.sh
# shellcheck source=src/lib/valid-tags.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-tags.sh
# shellcheck source=src/lib/valid-repos.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-repos.sh
# shellcheck source=src/lib/valid-inspect.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-inspect.sh
# shellcheck source=src/lib/valid-search.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-search.sh
_binary_arch=${_arch[*]:0:-1}
_colors=(never always auto)
@@ -29,7 +24,6 @@ _makechrootpkg_args=(
-n
-T
-U
-x
)
_makechrootpkg_args_d_opts() { _filedir -d; }
_makechrootpkg_args_D_opts() { _filedir -d; }
@@ -37,7 +31,6 @@ _makechrootpkg_args_r_opts() { _filedir -d; }
_makechrootpkg_args_I_opts() { _filedir '*.pkg.tar.*'; }
_makechrootpkg_args_l_opts() { _filedir -d; }
_makechrootpkg_args_U_opts() { :; }
_makechrootpkg_args_x_opts() { _devtools_completions_inspect; }
_makechrootpkg() { __devtools_complete _makechrootpkg; }
complete -F _makechrootpkg makechrootpkg
@@ -45,7 +38,6 @@ complete -F _makechrootpkg makechrootpkg
_makerepropkg_args=(
-h
-d
-n
-c
-M
)
@@ -127,7 +119,7 @@ _offload_build_args=(
)
_offload_build_args__repo_opts() { _devtools_completions_build_repo; }
_offload_build_args_r_opts() { _offload_build_args__repo_opts; }
_offload_build_args__arch_opts() { _devtools_completions_binary_arch; }
_offload_build_args__arch_opts() { _devtools_completions_arch; }
_offload_build_args_a_opts() { _offload_build_args__arch_opts; }
_offload_build_args__server_opts() { :; }
_offload_build_args_s_opts() { _offload_build_args__server_opts; }
@@ -136,14 +128,12 @@ complete -F _offload_build offload-build
_pkgctl_cmds=(
aur
auth
build
db
diff
release
repo
search
version
)
_pkgctl_args=(
@@ -179,14 +169,10 @@ _pkgctl_build_args=(
-o --offload
-c --clean
-w --worker
--inspect
-I --install-to-chroot
-i --install-to-host
--pkgver
--pkgrel
--rebuild
--update-checksums
-e --edit
-r --release
@@ -195,23 +181,15 @@ _pkgctl_build_args=(
-h --help
)
_pkgctl_build_args__arch_opts() { _devtools_completions_binary_arch; }
_pkgctl_build_args__arch_opts() { _devtools_completions_arch; }
_pkgctl_build_args__repo_opts() { _devtools_completions_repo; }
_pkgctl_build_args__worker_opts() { :; }
_pkgctl_build_args_w_opts() { _pkgctl_build_args__worker_opts; }
_pkgctl_build_args__inspect_opts() { _devtools_completions_inspect; }
_pkgctl_build_args__pkgver_opts() { :; }
_pkgctl_build_args__pkgrel_opts() { :; }
_pkgctl_build_args__install_to_host_opts() { _pkgctl_build_completions_install_mode; }
_pkgctl_build_args_i_opts() { _pkgctl_build_args__install_to_host_opts; }
_pkgctl_build_args__install_to_chroot_opts() { _makechrootpkg_args_I_opts; }
_pkgctl_build_args_I_opts() { _pkgctl_build_args__install_to_chroot_opts; }
_pkgctl_build_args__message_opts() { :; }
_pkgctl_build_args_m_opts() { _pkgctl_build_args__message_opts; }
_pkgctl_build_opts() { _filedir -d; }
_pkgctl_build_completions_install_mode() {
mapfile -t COMPREPLY < <(compgen -W "${DEVTOOLS_VALID_BUILD_INSTALL[*]}" -- "$cur")
}
_pkgctl_db_cmds=(
@@ -240,13 +218,9 @@ _pkgctl_db_move_opts() {
_pkgctl_db_remove_args=(
--partial
--noconfirm
-a --arch
-h --help
)
_pkgctl_db_remove_args__arch_opts() { _devtools_completions_binary_arch; }
_pkgctl_db_remove_args_a_opts() { _pkgctl_db_remove_args__arch_opts; }
_pkgctl_db_remove_opts() {
local subcommand args
subcommand=(db remove)
@@ -279,20 +253,8 @@ _pkgctl_release_args__repo_opts() { _devtools_completions_repo; }
_pkgctl_release_args_r_opts() { _pkgctl_release_args__repo_opts; }
_pkgctl_release_opts() { _filedir -d; }
_pkgctl_aur_cmds=(
drop-from-repo
)
_pkgctl_aur_drop_from_repo_args=(
--no-disown
-f --force
-h --help
)
_pkgctl_aur_drop_from_repo_opts() { _filedir -d; }
_pkgctl_repo_cmds=(
clean
clone
configure
create
@@ -318,12 +280,6 @@ _pkgctl_repo_clone_args__jobs_opts() { :; }
_pkgctl_repo_clone_args_j_opts() { _pkgctl_repo_clone_args__jobs_opts; }
_pkgctl_repo_clone_opts() { _devtools_completions_all_packages; }
_pkgctl_repo_clean_args=(
-i --interactive
-n --dry-run
-h --help
)
_pkgctl_repo_clean_opts() { _filedir -d; }
_pkgctl_repo_configure_args=(
--protocol
@@ -341,6 +297,7 @@ _pkgctl_repo_create_args=(
-h --help
)
_pkgctl_repo_switch_args=(
--discard-changes
-f --force
@@ -358,57 +315,13 @@ _pkgctl_repo_switch_opts() {
fi
}
_pkgctl_version_cmds=(
check
setup
upgrade
)
_pkgctl_version_check_args=(
-v --verbose
-h --help
)
_pkgctl_version_check_opts() { _filedir -d; }
_pkgctl_version_setup_args=(
--prefer-platform-api
--url
--no-check
-f --force
-h --help
)
_pkgctl_version_setup_opts() { _filedir -d; }
_pkgctl_version_setup_args__url_opts() { :; }
_pkgctl_version_upgrade_args=(
--no-update-checksums
-v --verbose
-h --help
)
_pkgctl_version_upgrade_opts() { _filedir -d; }
_pkgctl_repo_web_args=(
--print
-h --help
)
_pkgctl_repo_web_opts() { _filedir -d; }
_pkgctl_search_args=(
--no-default-filter
--json
-F --format
-N --no-line-number
-h --help
)
_pkgctl_search_opts() { :; }
_pkgctl_search_args__format_opts() { _devtools_completions_search_format; }
_pkgctl_search_args_F_opts() { _devtools_completions_search_format; }
_pkgctl_diff_args=(
-l --list
-d --diffoscope
@@ -442,17 +355,14 @@ _devtools_completions_color() {
mapfile -t COMPREPLY < <(compgen -W "${_colors[*]}" -- "$cur")
}
_devtools_completions_arch() {
mapfile -t COMPREPLY < <(compgen -W "${DEVTOOLS_VALID_ARCHES[*]}" -- "$cur")
}
_devtools_completions_binary_arch() {
mapfile -t COMPREPLY < <(compgen -W "${DEVTOOLS_VALID_BINARY_ARCHES[*]}" -- "$cur")
mapfile -t COMPREPLY < <(compgen -W "${_arch[*]}" -- "$cur")
}
_devtools_completions_repo() {
local optional=${1:-}
mapfile -t COMPREPLY < <(compgen -W "${optional} ${DEVTOOLS_VALID_REPOS[*]}" -- "$cur")
mapfile -t COMPREPLY < <(compgen -W "${optional} ${_repos[*]}" -- "$cur")
}
_devtools_completions_build_repo() {
mapfile -t COMPREPLY < <(compgen -W "${DEVTOOLS_VALID_BUILDREPOS[*]}" -- "$cur")
mapfile -t COMPREPLY < <(compgen -W "${_build_repos[*]}" -- "$cur")
}
_devtools_completions_all_packages() {
mapfile -t COMPREPLY < <(compgen -W "$(pacman -Sql)" -- "$cur")
@@ -460,12 +370,6 @@ _devtools_completions_all_packages() {
_devtools_completions_protocol() {
mapfile -t COMPREPLY < <(compgen -W "https" -- "$cur")
}
_devtools_completions_inspect() {
mapfile -t COMPREPLY < <(compgen -W "${DEVTOOLS_VALID_INSPECT_MODES[*]}" -- "$cur")
}
_devtools_completions_search_format() {
mapfile -t COMPREPLY < <(compgen -W "${valid_search_output_format[*]}" -- "$cur")
}
__devtools_complete() {
local service=$1

View File

@@ -3,17 +3,12 @@
# SPDX-License-Identifier: GPL-3.0-or-later
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
# shellcheck source=src/lib/valid-build-install.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-build-install.sh
# shellcheck source=src/lib/valid-tags.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-tags.sh
# shellcheck source=src/lib/valid-repos.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-repos.sh
# shellcheck source=src/lib/valid-inspect.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-inspect.sh
# shellcheck source=src/lib/valid-search.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-search.sh
_binary_arch=${_arch[*]:0:-1}
_colors=(never always auto)
_archbuild_args=(
@@ -40,21 +35,18 @@ _pkgctl_auth_status_args=(
)
_pkgctl_build_args=(
"--arch[Specify architectures to build for (disables auto-detection)]:arch:($DEVTOOLS_VALID_BINARY_ARCHES[*])"
"--repo[Specify a target repository (disables auto-detection)]:repo:($DEVTOOLS_VALID_REPOS[*])"
"--arch=[Specify architectures to build for (disables auto-detection)]:arch:($_arch[*])"
"--repo=[Specify a target repository (disables auto-detection)]:repo:($_repos[*])"
'(-s --staging)'{-s,--staging}'[Build against the staging counterpart of the auto-detected repo]'
'(-t --testing)'{-t,--testing}'[Build against the testing counterpart of the auto-detected repo]'
'(-o --offload)'{-o,--offload}'[Build on a remote server and transfer artifacts afterwards]'
'(-c --clean)'{-c,--clean}'[Recreate the chroot before building]'
"--inspect[Spawn an interactive shell to inspect the chroot (never, always, failure)]:inspect:($DEVTOOLS_VALID_INSPECT_MODES[*])"
'*'{-I,--install-to-chroot}'[Install a package to the working copy of the chroot]:target:_files -g "*.pkg.tar.*(.)"'
'*'{-i,--install-to-host}"[Install the built packages to the host system]:mode:($DEVTOOLS_VALID_BUILD_INSTALL[*])"
'(-I --install)'{-I,--install}'[Install a package into the working copy of the chroot]:target:_files -g "*.pkg.tar.*(.)"'
'(-w --worker)'{-w,--worker}'[Name of the worker slot, useful for concurrent builds (disables auto-detection)]:slot:'
'--nocheck[Do not run the check() function in the PKGBUILD]'
'--pkgver=[Set pkgver, reset pkgrel and update checksums]:pkgver:'
'--pkgrel=[Set pkgrel to a given value]:pkgrel:'
'--rebuild[Increment the pkgrel variable]'
'--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:"
@@ -72,17 +64,15 @@ _pkgctl_db_cmds=(
_pkgctl_db_move_args=(
'(-h --help)'{-h,--help}'[Display usage]'
"1:src-repo:($DEVTOOLS_VALID_REPOS[*])"
"2:target-repo:($DEVTOOLS_VALID_REPOS[*])"
"1:src-repo:($_repos[*])"
"2:target-repo:($_repos[*])"
'*:pkgbase:_devtools_completions_all_packages'
)
_pkgctl_db_remove_args=(
'--partial[Remove only partial pkgnames from a split package]'
'--noconfirm[Bypass any confirmation messages, should only be used with caution]'
'(-a --arch)'{-a,--arch}"[Override the architecture (disables auto-detection)]:arch:($DEVTOOLS_VALID_BINARY_ARCHES[*])"
'(-a --arch=)'{-a,--arch=}"[Override the architecture (disables auto-detection)]:arch:($_arch[*])"
'(-h --help)'{-h,--help}'[Display usage]'
"1:repo:($DEVTOOLS_VALID_REPOS[*])"
"1:repo:($_repos[*])"
'*:pkgbase:_devtools_completions_all_packages'
)
@@ -92,7 +82,7 @@ _pkgctl_db_update_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[*])"
'(-r --repo=)'{-r,--repo=}"[Specify a target repository (disables auto-detection)]:repo:($_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]'
@@ -100,21 +90,8 @@ _pkgctl_release_args=(
'*:git_dir:_files -/'
)
_pkgctl_aur_cmds=(
"pkgctl aur command"
"drop-from-repo[Drop a package from the official repository to the AUR]"
)
_pkgctl_aur_drop_from_repo_args=(
'(-f --force)'{-f,--force}'[Force push to the AUR overwriting the remote repository]'
'--no-disown[Do not disown the package on the AUR]'
'(-h --help)'{-h,--help}'[Display usage]'
'*:git_dir:_files -/'
)
_pkgctl_repo_cmds=(
"pkgctl repo command"
"clean[Remove untracked files from the working tree]"
"clone[Clone a package repository]"
"configure[Configure a clone according to distro specs]"
"create[Create a new GitLab package repository]"
@@ -129,13 +106,6 @@ _pkgctl_repo_switch_args=(
'*:git_dir:_files -/'
)
_pkgctl_repo_clean_args=(
'(-i --interactive)'{-i,--interactive}'[Show what would be done and clean files interactively]'
'(-n --dry-run)'{-n,--dry-run}"[Don't remove anything, just show what would be done]"
'(-h --help)'{-h,--help}'[Display usage]'
'*:git_dir:_files -/'
)
_pkgctl_repo_clone_args=(
'(-m --maintainer=)'{-m,--maintainer=}'[Clone all packages of the named maintainer]:maintainer:'
'--protocol[Clone the repository over https]:proto:(https)'
@@ -160,25 +130,15 @@ _pkgctl_repo_create_args=(
)
_pkgctl_repo_web_args=(
'--print[Print the url instead of opening it with xdg-open]'
'(-h --help)'{-h,--help}'[Display usage]'
'*:git_dir:_files -/'
)
_pkgctl_search_args=(
'--no-default-filter[Do not apply default filter (like -path:keys/pgp/*.asc)]'
'--json[Enable printing results in JSON]'
'(-F --format)'{-F,--format}"[Controls the formatting of the results]:format:($valid_search_output_format[*])"
'(-N --no-line-number)'{-N,--no-line-number}"[Don't show line numbers when formatting results]"
'(-h --help)'{-h,--help}'[Display usage]'
'1:query'
)
_arch_nspawn_args=(
'-C[Location of a pacman config file]:pacman_config:_files -g "*.conf(.)"'
'-M[Location of a makepkg config file]:makepkg_config:_files -g "*.conf(.)"'
'*-c[Set pacman cache]:pacman_cache:_files -/'
'*-f[Copy file from the host to the chroot]:copy_file:_files'
'-c[Set pacman cache]:pacman_cache:_files -/'
'-f[Copy file from the host to the chroot]:copy_file:_files'
'-s[Do not run setarch]'
'-h[Display usage]'
'1:chroot_dir:_files -/'
@@ -186,14 +146,14 @@ _arch_nspawn_args=(
_archrelease_args=(
'-f[Force release without checks]'
"*:arch:($DEVTOOLS_VALID_TAGS[*])"
"*:arch:($_tags[*])"
)
_commitpkg_args=(
'-f[Force release without checks]'
'-s[Target repo server]'
'-l[Set bandwidth limit]:limit'
"-a[Release to a specific architecture only]:arch:($DEVTOOLS_VALID_ARCHES[*])"
"-a[Release to a specific architecture only]:arch:($_arch[*])"
'1:commit_msg'
)
@@ -220,16 +180,15 @@ _finddeps_args=(
_makechrootpkg_args=(
'-h[Display usage]'
'-c[Clean the chroot before building]'
'*-d[Bind directory into build chroot as read-write]:bind_dir_rw:_files -/'
'*-D[Bind directory into build chroot as read-only]:bind_dir_ro:_files -/'
'-d[Bind directory into build chroot as read-write]:bind_dir_rw:_files -/'
'-D[Bind directory into build chroot as read-only]:bind_dir_ro:_files -/'
'-u[Update the working copy of the chroot before building]'
'-r[The chroot dir to use]:chroot_dir:_files -/'
'*-I[Install a package into the working copy]:target:_files -g "*.pkg.tar.*(.)"'
'-I[Install a package into the working copy]:target:_files -g "*.pkg.tar.*(.)"'
'-l[The directory to use as the working copy]:copy_dir:_files -/'
'-n[Run namcap on the package]'
'-T[Build in a temporary directory]'
'-U[Run makepkg as a specified user]:makepkg_user'
"-x[Spawn an interactive shell to inspect the chroot (never, always, failure)]:inspect:($DEVTOOLS_VALID_INSPECT_MODES[*])"
)
_mkarchroot_args=(
@@ -253,20 +212,19 @@ _sogrep_args=(
'(-v --verbose)'{-v,--verbose}'[Show matched links in addition to pkgname]'
'(-r --refresh)'{-r,--refresh}'[Refresh the links databases]'
'(-h --help)'{-h,--help}'[Display usage]'
'1:repo:(all $DEVTOOLS_VALID_REPOS[*])'
'1:repo:(all $_repos[*])'
'2:libname'
)
_offload_build_args=(
'(-r --repo)'{-r,--repo}'[Build against a specific repository]:repo:($DEVTOOLS_VALID_BUILDREPOS[*])'
'(-a --arch)'{-a,--arch}'[Build against a specific architecture]:arch:(${DEVTOOLS_VALID_BINARY_ARCHES[*]})'
'(-r --repo)'{-r,--repo}'[Build against a specific repository]:repo:($_build_repos[*])'
'(-a --arch)'{-a,--arch}'[Build against a specific architecture]:arch:(${_binary_arch[*]})'
'(-s --server)'{-s,--server}'[Offload to a specific Build server]:server:'
'(-h --help)'{-h,--help}'[Display usage]'
)
_makerepropkg_args=(
'-d[Run diffoscope if the package is unreproducible]'
'-n[Do not run the check() function in the PKGBUILD]'
'-c[Set pacman cache]:pacman_cache:_files -/'
'-M[Location of a makepkg config file]:makepkg_config:_files -g "*.conf(.)"'
'-h[Display usage]'
@@ -281,15 +239,13 @@ _devtools_completions_all_packages() {
_pkgctl_cmds=(
"pkgctl command"
"aur[Interact with the Arch User Repository (AUR)]"
"auth[Authenticate with services like GitLab]"
"build[Build packages inside a clean chroot]"
"db[Pacman database modification for package update, move etc]"
"diff[Compare package files using different modes]"
"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]"
"version[Check and manage package versions against upstream]"
"version[Show pkgctl version information]"
)
_pkgctl_args=(
@@ -297,33 +253,8 @@ _pkgctl_args=(
'(-h --help)'{-h,--help}'[Display usage]'
)
_pkgctl_version_cmds=(
"pkgctl version command"
"check[Compares local package versions against upstream versions]"
"setup[Automatically detect and setup a basic nvchecker config]"
"upgrade[Adjust the PKGBUILD to match the latest upstream version]"
)
_pkgctl_version_check_args=(
'(-v --verbose)'{-v,--verbose}'[Display results including up-to-date versions]'
_pkgctl_version_args=(
'(-h --help)'{-h,--help}'[Display usage]'
'*:git_dir:_files -/'
)
_pkgctl_version_setup_args=(
'(-f --force)'{-f,--force}'[Do not prompt before overwriting]'
'--prefer-platform-api[Prefer platform specific GitHub/GitLab API for complex cases]'
'--url[Derive check target from URL instead of source array]:url:'
'--no-check[Do not run version check after setup]'
'(-h --help)'{-h,--help}'[Display usage]'
'*:git_dir:_files -/'
)
_pkgctl_version_upgrade_args=(
'--no-update-checksums[Disable computation and update of the checksums]'
'(-v --verbose)'{-v,--verbose}'[Display results including up-to-date versions]'
'(-h --help)'{-h,--help}'[Display usage]'
'*:git_dir:_files -/'
)
_pkgctl_diff_args=("${_diffpkg_args[@]}")
@@ -345,7 +276,7 @@ _handle_subcommands() {
fi
;;
args)
local service_sub=${service_name}_${line[1]//-/_}
local service_sub=${service_name}_$line[1]
if typeset -p ${service_sub}_args &> /dev/null; then
local cmd_args=${service_sub}_args[@]
_arguments -s "${(P)cmd_args}"

37
doc/asciidoc.conf Normal file
View File

@@ -0,0 +1,37 @@
## linkman: macro
# Inspired by/borrowed from the GIT source tree at Documentation/asciidoc.conf
#
# Usage: linkman:command[manpage-section]
#
# Note, {0} is the manpage section, while {target} is the command.
#
# Show man link as: <command>(<section>); if section is defined, else just show
# the command.
[macros]
(?su)[\\]?(?P<name>linkman):(?P<target>\S*?)\[(?P<attrlist>.*?)\]=
[attributes]
asterisk=&#42;
plus=&#43;
caret=&#94;
startsb=&#91;
endsb=&#93;
backslash=&#92;
tilde=&#126;
apostrophe=&#39;
backtick=&#96;
litdd=&#45;&#45;
ifdef::backend-docbook[]
[linkman-inlinemacro]
{0%{target}}
{0#<citerefentry>}
{0#<refentrytitle>{target}</refentrytitle><manvolnum>{0}</manvolnum>}
{0#</citerefentry>}
endif::backend-docbook[]
ifdef::backend-xhtml11[]
[linkman-inlinemacro]
<a href="{target}.{0}.html">{target}{0?({0})}</a>
endif::backend-xhtml11[]

View File

@@ -43,6 +43,6 @@ Options
See Also
--------
devtools(7)
linkman:devtools[7]
include::include/footer.asciidoc[]

View File

@@ -38,6 +38,6 @@ Options
See Also
--------
find-libprovides(1)
linkman:find-libprovides[1]
include::include/footer.asciidoc[]

View File

@@ -21,47 +21,47 @@ Programs
The list below gives a short overview; see the respective documentation
for details.
pkgctl(1)
linkman:pkgctl[1]
Unified command-line frontend for devtools
archbuild(1)
linkman:archbuild[1]
Build an Arch Linux package inside a clean chroot
arch-nspawn(1)
linkman:arch-nspawn[1]
Run a command or OS in a light-weight namespace container
checkpkg(1)
linkman:checkpkg[1]
Compare the current build package with the repository version
diffpkg(1)
linkman:diffpkg[1]
Compare package files using different modes
export-pkgbuild-keys(1)
linkman:export-pkgbuild-keys[1]
Export valid source signing keys from a PKGBUILD
find-libdeps(1)
linkman:find-libdeps[1]
Find soname dependencies for a package
find-libprovides(1)
linkman:find-libprovides[1]
Find soname's which are provided by a package
lddd(1)
linkman:lddd[1]
Find broken library links on your system
mkarchroot(1)
linkman:mkarchroot[1]
Creates an arch chroot in a specified location with a specified set of
packages
makechrootpkg(1)
linkman:makechrootpkg[1]
Build a PKGBUILD in a given chroot environment
makerepropkg(1)
linkman:makerepropkg[1]
Rebuild a package to see if it is reproducible
offload-build(1)
linkman:offload-build[1]
Build a PKGBUILD on a remote server using makechrootpkg
sogrep(1)
linkman:sogrep[1]
Find packages using a linked to a given shared library
include::include/footer.asciidoc[]

View File

@@ -20,6 +20,6 @@ collected data is written to a temporary directory created by mktemp.
See Also
--------
ldd(1)
linkman:ldd[1]
include::include/footer.asciidoc[]

View File

@@ -73,8 +73,4 @@ Options
*-U*::
Run makepkg as a specified user
*-x* <when>::
Inspect chroot after build, possible modes are 'never' (default), 'always' or 'failure'
include::include/footer.asciidoc[]

View File

@@ -16,7 +16,7 @@ Given the path to a built pacman package(s), attempt to rebuild it using the
PKGBUILD in the current directory. The package will be built in an environment
as closely matching the environment of the initial package as possible, by
building up a chroot to match the information exposed in the package's
BUILDINFO(5) manifest. On success, the resulting package will be
linkman:BUILDINFO[5] manifest. On success, the resulting package will be
compared to the input package, and makerepropkg will report whether the
artifacts are identical.
@@ -42,9 +42,6 @@ Options
*-d*::
If packages are not reproducible, compare them using diffoscope.
*-n*::
Do not run the check() function in the PKGBUILD.
*-c*::
Set the pacman cache directory.

View File

@@ -44,6 +44,6 @@ Options
See Also
--------
pacman(1)
linkman:pacman[1]
include::include/footer.asciidoc[]

View File

@@ -1,41 +0,0 @@
pkgctl-aur-drop-from-repo(1)
============================
Name
----
pkgctl-aur-drop-from-repo - Drop a package from the official repository to the AUR
Synopsis
--------
pkgctl aur drop-from-repo [OPTIONS] [PATH]...
Description
-----------
Drops a specified package from the official repositories to the Arch User
Repository.
This command requires a local Git clone of the package repository. It
reconfigures the repository for AUR compatibility and pushes it to the
AUR. Afterwards, the package is removed from the official repository.
By default, the package is automatically disowned in the AUR.
Options
-------
*--no-disown*::
Do not disown the package on the AUR
*-f, --force*::
Force push to the AUR overwriting the remote repository
*-h, --help*::
Show a help text
See Also
--------
pkgctl-db-remove(1)
include::include/footer.asciidoc[]

View File

@@ -1,37 +0,0 @@
pkgctl-aur(1)
=============
Name
----
pkgctl-aur - Interact with the Arch User Repository (AUR)
Synopsis
--------
pkgctl aur [OPTIONS] [SUBCOMMAND]
Description
-----------
Provides a suite of tools designed for managing and interacting with the Arch
User Repository (AUR). It simplifies various tasks related to AUR, including
importing repositories, managing packages, and transitioning packages between
the official repositories and the AUR.
Options
-------
*-h, --help*::
Show a help text
Subcommands
-----------
pkgctl aur drop-from-repo::
Drop a package from the official repository to the AUR
See Also
--------
pkgctl-aur-drop-from-repo(1)
include::include/footer.asciidoc[]

View File

@@ -35,6 +35,6 @@ Options
See Also
--------
pkgctl-auth-status(1)
linkman:pkgctl-auth-status[1]
include::include/footer.asciidoc[]

View File

@@ -27,6 +27,6 @@ Options
See Also
--------
pkgctl-auth-login(1)
linkman:pkgctl-auth-login[1]
include::include/footer.asciidoc[]

View File

@@ -32,7 +32,7 @@ pkgctl auth status::
See Also
--------
pkgctl-auth-login(1)
pkgctl-auth-status(1)
linkman:pkgctl-auth-login[1]
linkman:pkgctl-auth-status[1]
include::include/footer.asciidoc[]

View File

@@ -21,10 +21,7 @@ Build Options
Specify architectures to build for (disables auto-detection)
*--repo* 'REPO'::
Specify target repository for new packages not in any official repo.
Fallback to `'extra'` when building packages that are not present in any
official repository yet. Using this option is disallowed if the package is
already released, as it would circumvent the auto-detection safeguard.
Specify a target repository (disables auto-detection)
*-s, --staging*::
Build against the staging counterpart of the auto-detected repo
@@ -38,9 +35,8 @@ Build Options
*-c, --clean*::
Recreate the chroot before building
*--inspect* 'WHEN'::
Spawn an interactive shell to inspect the chroot after building. Useful to ease the debugging of a package build. +
Possible values for 'WHEN' are `'never'`, `'always'` or `'failure'`
*-I, --install* 'FILE'::
Install a package into the working copy of the chroot
*-w, --worker* 'SLOT'::
Name of the worker slot, useful for concurrent builds. By default the slot
@@ -51,17 +47,6 @@ Build Options
*--nocheck*::
Do not run the check() function in the PKGBUILD
Install Options
---------------
*-I, --install-to-chroot* 'FILE'::
Install a package to the working copy of the chroot
*-i, --install-to-host* 'MODE'::
Install the built packages to the host system. Useful when one wants to verify that the package works as intended.
* When 'MODE' is 'all', this installs all built packages
* When 'MODE' is 'auto', this installs all built packages which are currently installed
PKGBUILD Options
----------------
@@ -74,13 +59,6 @@ PKGBUILD Options
*--rebuild*::
Increment the current pkgrel variable
*--update-checksums*::
Force computation and update of the checksums by disabling auto-detection. +
Should only be used in special circumstances, like when adding new patch
files to the source array. During regular packaging operations, checksums
are either automatically updated when upgrading a package using `--pkgver`
or should remain immutable during rebuilds.
*-e, --edit*::
Edit the PKGBUILD before building
@@ -107,7 +85,7 @@ Options
See Also
--------
pkgctl-release(1)
pkgctl-db-update(1)
linkman:pkgctl-release[1]
linkman:pkgctl-db-update[1]
include::include/footer.asciidoc[]

View File

@@ -3,16 +3,17 @@ pkgctl-db-move(1)
Name
----
pkgctl-db-move - Move packages between binary repositories.
pkgctl-db-update - Update the binary repository as final release step
Synopsis
--------
pkgctl db move [OPTIONS] [SOURCE_REPO] [TARGET_REPO] [PKGBASE]...
pkgctl db update [OPTIONS]
Description
-----------
Move packages between binary repositories i.e. from 'extra-testing' to 'extra'.
Update the pacman database as final release step for packages that
have been transfered and staged on 'repos.archlinux.org'.
Options
-------

View File

@@ -12,27 +12,13 @@ pkgctl db remove [OPTIONS] [REPO] [PKGBASE]...
Description
-----------
Remove packages from pacman repositories. By default passing a pkgbase removes
all split packages, debug packages as well as entries from the state repo for
all existing architectures.
Beware when using the `--partial` option, as it may most likely lead to
undesired effects by leaving debug packages behind as well as dangling entries
in the state repository.
Remove packages from pacman repositories.
Options
-------
*--partial*::
Remove only partial pkgnames from a split package. This leaves debug
packages behind and pkgbase entries in the state repo.
*-a, --arch* 'ARCH'::
Remove only one specific architecture (disables auto-detection).
By default all architectures are removed when this option is not used.
*--noconfirm*::
Bypass any confirmation messages, should only be used with caution.
Override the architecture (disables auto-detection)
*-h, --help*::
Show a help text

View File

@@ -1,19 +1,18 @@
pkgctl-db-update(1)
===================
pkgctl-db-move(1)
=================
Name
----
pkgctl-db-update - Update the binary repository as final release step
pkgctl-db-move - Move packages between binary repositories
Synopsis
--------
pkgctl db update [OPTIONS]
pkgctl db move [OPTIONS] [SOURCE_REPO] [TARGET_REPO] [PKGBASE]...
Description
-----------
Update the pacman database as final release step for packages that
have been transfered and staged on 'repos.archlinux.org'.
Move packages between pacman repositories.
Options
-------

View File

@@ -27,9 +27,7 @@ Options
Use the given <msg> as the commit message
*-r, --repo* 'REPO'::
Specify target repository for new packages not in any official repo.
Using this option is disallowed if the package is already released, as it
would circumvent the auto-detection safeguard.
Specify a target repository (disables auto-detection)
*-s, --staging*::
Build against the staging counterpart of the auto-detected repo
@@ -46,6 +44,6 @@ Options
See Also
--------
pkgctl-db-update(1)
linkman:pkgctl-db-update[1]
include::include/footer.asciidoc[]

View File

@@ -1,40 +0,0 @@
pkgctl-repo-clean(1)
====================
Name
----
pkgctl-repo-clean - Remove untracked files from the working tree
Synopsis
--------
pkgctl repo clean [OPTION] [PATH]...
Description
-----------
Cleans the working tree by recursively removing files that are not under
version control, starting from the current directory.
Files unknown to Git as well as ignored files are removed. This can, for
example, be useful to remove all build products.
Options
-------
*-i, --interactive*::
Show what would be done and clean files interactively
*-n, --dry-run*::
Don't actually remove anything, just show what would be done
*-h, --help*::
Show a help text
See Also
--------
git-clean(1)
include::include/footer.asciidoc[]

View File

@@ -46,7 +46,7 @@ Options
See Also
--------
pkgctl-repo-configure(1)
pkgctl-repo-switch(1)
linkman:pkgctl-repo-configure[1]
linkman:pkgctl-repo-switch[1]
include::include/footer.asciidoc[]

View File

@@ -22,8 +22,6 @@ The remote protocol is automatically determined from the author email
address by choosing SSH for all official packager identities and
read-only HTTPS otherwise.
Git default excludes and hooks are applied to the configured repo.
Options
-------

View File

@@ -33,8 +33,8 @@ Options
See Also
--------
pkgctl-auth(1)
pkgctl-repo-clone(1)
pkgctl-repo-configure(1)
linkman:pkgctl-auth[1]
linkman:pkgctl-repo-clone[1]
linkman:pkgctl-repo-configure[1]
include::include/footer.asciidoc[]

View File

@@ -18,9 +18,6 @@ no arguments, open the package cloned in the current working directory.
Options
-------
*--print*::
Print the url instead of opening it with xdg-open
*-h, --help*::
Show a help text

View File

@@ -32,9 +32,6 @@ Options
Subcommands
-----------
pkgctl repo clean::
Remove untracked files from the working tree
pkgctl repo clone::
Clone a package repository
@@ -53,11 +50,10 @@ pkgctl repo web::
See Also
--------
pkgctl-repo-clean(1)
pkgctl-repo-clone(1)
pkgctl-repo-configure(1)
pkgctl-repo-create(1)
pkgctl-repo-switch(1)
pkgctl-repo-web(1)
linkman:pkgctl-repo-clone[1]
linkman:pkgctl-repo-configure[1]
linkman:pkgctl-repo-create[1]
linkman:pkgctl-repo-switch[1]
linkman:pkgctl-repo-web[1]
include::include/footer.asciidoc[]

View File

@@ -1,71 +0,0 @@
pkgctl-search(1)
================
Name
----
pkgctl-search - Search for an expression across the GitLab packaging group
Synopsis
--------
pkgctl search [OPTIONS] QUERY
Description
-----------
Search for an expression across the GitLab packaging group.
To use a filter, include it in your query. You may use wildcards (*) to
use glob matching.
Available filters for the blobs scope: path, extension
Every usage of the search command must be authenticated. Consult the
`'pkgctl auth'` command to authenticate with GitLab or view the authentication
status.
Search Tips
-----------
Syntax Description Example
───────────────────────────────────────
" Exact search "gem sidekiq"
~ Fuzzy search J~ Doe
| Or display | banner
+ And display +banner
- Exclude display -banner
* Partial bug error 50*
\ Escape \*md
# Issue ID #23456
! Merge request !23456
Options
-------
*-h, --help*::
Show a help text
Filter Options
--------------
*--no-default-filter*::
Do not apply default filter (like -path:keys/pgp/*.asc)
Output Options
--------------
*--json*::
Enable printing in JSON; Shorthand for `'--format json'`
*-F, --format* 'FORMAT'::
Controls the formatting of the results; `FORMAT` is `'pretty'`, `'plain'`,
or `'json'` (default `pretty`)
*-N, --no-line-number*::
Don't show line numbers when formatting results
See Also
--------
pkgctl-auth(1)
include::include/footer.asciidoc[]

View File

@@ -1,66 +0,0 @@
pkgctl-version-check(1)
=======================
Name
----
pkgctl-version-check - Compares local package versions against upstream
Synopsis
--------
pkgctl version check [OPTIONS] [PKGBASE...]
Description
-----------
Compares the versions of packages in the local packaging repository against
their latest upstream versions.
Upon execution, it generates a grouped list that provides detailed insights
into each package's status. For each package, it displays the current local
version alongside the latest version available upstream.
Outputs a summary of up-to-date packages, out-of-date packages, and any check
failures.
This simplifies the maintenance of PKGBUILD files, reducing the manual effort
required to track version changes from upstream sources.
Configuration
-------------
Uses nvchecker(1) and a `.nvchecker.toml` file located alongside the
PKGBUILD. Refer to the configuration section in pkgctl-version(1).
Options
-------
*-v, --verbose*::
Display results including up-to-date versions
*-h, --help*::
Show a help text
Exit Codes
----------
On exit, return one of the following codes:
*0*::
Normal exit condition, all checked versions are up-to-date
*1*::
Unknown cause of failure
*2*::
Normal exit condition, but there are out-of-date versions
*3*::
Failed to run some version checks
See Also
--------
pkgctl-version(1)
nvchecker(1)
include::include/footer.asciidoc[]

View File

@@ -1,120 +0,0 @@
pkgctl-version-setup(1)
=======================
Name
----
pkgctl-version-setup - Automatically detect and setup a basic nvchecker config
Synopsis
--------
pkgctl version setup [OPTIONS] [PKGBASE...]
Description
-----------
This subcommand automates the creation of a basic nvchecker(1) configuration
file by analyzing the source array specified in the PKGBUILD(1) file of a
package. This command intelligently detects various platforms and APIs (e.g.,
GitHub, GitLab, PyPI) used by the package sources and generates a corresponding
`.nvchecker.toml` configuration based on its best guess.
This is particularly useful for initializing nvchecker(1) settings for a
package without manually crafting the `.nvchecker.toml` file. It simplifies the
process of setting up version checks, especially when transitioning a package's
monitoring from one source platform to another or starting version checks for a
new package.
If no `PKGBASE` is specified, the command defaults to using the current working
directory.
To obtain a list of supported sources and their expected URL formats, please
consult the sources section.
Options
-------
*-f, --force*::
Overwrite existing nvchecker(1) configuration
*--prefer-platform-api*::
Prefer platform specific GitHub/GitLab API over git for complex cases
*--url* 'URL'::
Derive check target from the given URL instead of the source array entries
*--no-check*::
Do not run pkgctl-version-check(1) after setup
*-h, --help*::
Show a help text
Sources
-------
Here are the currently supported platforms and sources, along with examples of
URL formats that enable their automatic detection as specific source types:
*Git*::
* https://github.com/example/project
* https://gitlab.com/example/group/project
* git://git.foobar.org/example
* git+https://git.foobar.org/example
*GitHub*::
* https://github.com/example/project
* https://github.com/example/project/archive/v1.0/project-v1.0.tar.gz
*GitLab*::
* https://gitlab.com/example/group/project
* https://gitlab.archlinux.org/archlinux/devtools.git
* https://gitlab.archlinux.org/archlinux/devtools/-/releases/v1.1.0/downloads/devtools-v1.1.0.tar.gz
*Hackage*::
* https://hackage.haskell.org/package/xmonad
* https://hackage.haskell.org/package/xmonad-0.18.0/xmonad-0.18.0.tar.gz
* https://hackage.haskell.org/packages/archive/xmonad/0.18.0/xmonad-0.18.0.tar.gz
*NPM*::
* https://registry.npmjs.org/node-gyp/-/node-gyp-10.0.1.tgz
* https://www.npmjs.com/package/node-gyp
*PyPI*::
* https://pypi.io/packages/source/p/pyflakes
* https://pypi.org/packages/source/b/bleach
* https://files.pythonhosted.org/packages/source/p/pyflakes
* https://pypi.org/project/SQLAlchemy/
*RubyGems*::
* https://rubygems.org/downloads/diff-lcs-1.5.1.gem
* https://rubygems.org/gems/diff-lcs
*CPAN*::
* https://search.cpan.org/CPAN/authors/id/C/CO/COSIMO/Locale-PO-0.27.tar.gz
* https://cpan.metacpan.org/authors/id/C/CO/COSIMO/Locale-PO-0.27.tar.gz
*crates.io*::
* https://static.crates.io/crates/shotgun/shotgun-1.0.crate
* https://crates.io/api/v1/crates/shotgun/1.0/download
* https://crates.io/crates/git-smash
Examples
--------
*pkgctl version setup*::
Detects the source from the current directory's PKGBUILD(1) and
sets up a basic `.nvchecker.toml`.
*pkgctl version setup --url https://github.com/example/project*::
Generates an `.nvchecker.toml` for the current PKGBUILD(1) but
overrides the source URL with the specified GitHub project.
See Also
--------
pkgctl-version(1)
pkgctl-version-check(1)
nvchecker(1)
PKGBUILD(5)
include::include/footer.asciidoc[]

View File

@@ -1,53 +0,0 @@
pkgctl-version-upgrade(1)
=========================
Name
----
pkgctl-version-upgrade - Adjust the PKGBUILD to match the latest upstream version
Synopsis
--------
pkgctl version upgrade [OPTIONS] [PKGBASE...]
Description
-----------
Streamlines the process of keeping PKGBUILD files up-to-date with the latest
upstream versions.
Upon execution, it automatically adjusts the PKGBUILD file, ensuring that the
pkgver field is set to match the latest version available from the upstream
source. In addition to updating the pkgver, this command also resets the pkgrel
to 1 and updates checksums.
Outputs a summary of upgraded packages, up-to-date packages, and any check
failures.
This simplifies the maintenance of PKGBUILD files, reducing the manual effort
required to track and implement version changes from upstream sources.
Configuration
-------------
Uses nvchecker(1) and a `.nvchecker.toml` file located alongside the
PKGBUILD. Refer to the configuration section in pkgctl-version(1).
Options
-------
*--no-update-checksums*::
Disable computation and update of the checksums
*-v, --verbose*::
Display results including up-to-date versions
*-h, --help*::
Show a help text
See Also
--------
pkgctl-version(1)
nvchecker(1)
include::include/footer.asciidoc[]

View File

@@ -3,41 +3,16 @@ pkgctl-version(1)
Name
----
pkgctl-version - Check and manage package versions against upstream
pkgctl-version - Show pkgctl version information
Synopsis
--------
pkgctl version [OPTIONS] [SUBCOMMAND]
pkgctl version [OPTIONS]
Description
-----------
Commands related to package versions, including checks for outdated packages.
Uses nvchecker(1) and a `.nvchecker.toml` file located alongside the
PKGBUILD.
Configuration
-------------
The `.nvchecker.toml` file must contain a section that matches the
package's pkgbase. The pkgbase section within the `.nvchecker.toml` file
specifies the source and method for checking the latest version of the
corresponding package.
Use pkgctl-version-setup(1) to automatically detect and setup a basic nvchecker
config based on the source array of the package PKGBUILD.
For detailed information on the various configuration options available for the
`.nvchecker.toml` file, refer to the configuration files section in
nvchecker(1). This documentation provides insights into the possible
options that can be utilized to customize the version checking process.
To supply GitHub or GitLab tokens to nvchecker, a `keyfile.toml` should be
placed in the `$XDG_CONFIG_HOME`/nvchecker` directory. This keyfile is
used for providing the necessary authentication tokens required for
accessing the GitHub or GitLab API.
Shows the current version information of pkgctl.
Options
-------
@@ -45,23 +20,4 @@ Options
*-h, --help*::
Show a help text
Subcommands
-----------
pkgctl version check::
Compares local package versions against upstream
pkgctl version setup::
Automatically detect and setup a basic nvchecker config
pkgctl version upgrade::
Adjust the PKGBUILD to match the latest upstream version
See Also
--------
pkgctl-version-check(1)
pkgctl-version-setup(1)
pkgctl-version-upgrade(1)
include::include/footer.asciidoc[]

View File

@@ -26,9 +26,6 @@ Options
Subcommands
-----------
pkgctl aur::
Interact with the Arch User Repository
pkgctl auth::
Authenticate with services like GitLab
@@ -47,23 +44,18 @@ pkgctl release::
pkgctl repo::
Manage Git packaging repositories and their configuration
pkgctl search::
Search for an expression across the GitLab packaging group
pkgctl version::
Check and manage package versions against upstream
Show pkgctl version information
See Also
--------
pkgctl-aur(1)
pkgctl-auth(1)
pkgctl-build(1)
pkgctl-db(1)
pkgctl-diff(1)
pkgctl-release(1)
pkgctl-repo(1)
pkgctl-search(1)
pkgctl-version(1)
linkman:pkgctl-auth[1]
linkman:pkgctl-build[1]
linkman:pkgctl-db[1]
linkman:pkgctl-diff[1]
linkman:pkgctl-release[1]
linkman:pkgctl-repo[1]
linkman:pkgctl-version[1]
include::include/footer.asciidoc[]

View File

@@ -63,7 +63,6 @@ nspawn_args=(
--slice="devtools-$(systemd-escape "${SUDO_USER:-$USER}")"
--machine="arch-nspawn-$$"
--as-pid2
--console=autopipe
)
if (( ${#cache_dirs[@]} == 0 )); then
@@ -72,7 +71,6 @@ fi
# shellcheck disable=2016
host_mirrors=($(pacman-conf --repo extra Server 2> /dev/null | sed -r 's#(.*/)extra/os/.*#\1$repo/os/$arch#'))
host_cachemirrors=($(pacman-conf --repo extra CacheServer 2> /dev/null | sed -r 's#(.*/)extra/os/.*#\1$repo/os/$arch#'))
for host_mirror in "${host_mirrors[@]}"; do
if [[ $host_mirror == *file://* ]]; then
@@ -107,8 +105,6 @@ copy_hostconf () {
printf 'Server = %s\n' "${host_mirrors[@]}" >"$working_dir/etc/pacman.d/mirrorlist"
[[ -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"

View File

@@ -7,6 +7,8 @@ _DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
# shellcheck source=src/lib/valid-tags.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-tags.sh
# shellcheck source=src/lib/util/git.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/git.sh
set -e
@@ -35,7 +37,7 @@ fi
# validate repo is really repo-arch
if [[ -z $FORCE ]]; then
for tag in "$@"; do
if ! in_array "$tag" "${DEVTOOLS_VALID_TAGS[@]}"; then
if ! in_array "$tag" "${_tags[@]}"; then
die "archrelease: Invalid tag: '%s' (use -f to force release)" "$tag"
fi
done
@@ -55,8 +57,8 @@ gittag=$(get_tag_from_pkgver "$pkgver")
if ! branchname=$(git symbolic-ref --short HEAD); then
die 'not on any branch'
fi
if [[ "${branchname}" != main ]]; then
die 'must be run from the main branch'
if ! is_valid_release_branch "${branchname}"; then
die 'must be run from a valid release branch (%s)' "${VALID_RELEASE_BRANCHES[@]}"
fi
# Check if remote origin is setup properly
@@ -85,10 +87,10 @@ if git tag --verify "$gittag" &> /dev/null; then
if [[ "$cwd_checksum" != "$tag_checksum" ]]; then
die "tagged PKGBUILD is not the same as the working dir PKGBUILD"
fi
git push --tags --set-upstream origin main || abort
git push --tags --set-upstream origin "${branchname}" || abort
exit 0
fi
msg "Releasing package"
git tag --sign --message="Package release ${pkgver}" "$gittag" || abort
git push --tags --set-upstream origin main || abort
git push --tags --set-upstream origin "${branchname}" || abort

View File

@@ -5,13 +5,11 @@
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
# shellcheck source=src/lib/common.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
# shellcheck source=src/lib/util/srcinfo.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/srcinfo.sh
# shellcheck source=src/lib/util/git.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/git.sh
source /usr/share/makepkg/util/util.sh
set -eo pipefail
check_pkgbuild_validity() {
# shellcheck source=contrib/makepkg/PKGBUILD.proto
@@ -74,14 +72,12 @@ if ! repo_spec=$(git config --local devtools.version) || [[ ${repo_spec} != "${G
exit 1
fi
if ! repo_variant=$(git config --local devtools.variant) || [[ ${repo_variant} != canonical ]]; then
error "cannot release from a repository with none canonical specs (%s), try:" "${repo_variant:-development}"
msg2 'pkgctl repo configure'
exit 1
if ! branchname=$(git symbolic-ref --short HEAD); then
die 'not on any branch'
fi
if [[ "$(git symbolic-ref --short HEAD)" != main ]]; then
die 'must be run from the main branch'
if ! is_valid_release_branch "${branchname}"; then
die 'must be run from a valid release branch (%s)' "${VALID_RELEASE_BRANCHES[@]}"
fi
source=()
@@ -105,6 +101,9 @@ case "$cmd" in
;;
esac
if [[ "${branchname}" == "unstable" ]] && [[ "$repo" != *"unstable" ]]; then
die 'Cannot release from unstable branch into non-unstable repo: %s' "${repo}"
fi
if (( ${#validpgpkeys[@]} != 0 )); then
if [[ -d keys ]]; then
@@ -151,7 +150,7 @@ fi
server=${PACKAGING_REPO_RELEASE_HOST}
rsyncopts=("${RSYNC_OPTS[@]}" --perms --chmod='ug=rw,o=r')
rsyncopts=(-e ssh -p '--chmod=ug=rw,o=r' -c -h -L --progress --partial -y)
archreleaseopts=()
while getopts ':l:a:s:f' flag; do
case $flag in
@@ -187,10 +186,13 @@ done
# check for PKGBUILD standards
check_pkgbuild_validity
# auto generate .SRCINFO
# shellcheck disable=SC2119
write_srcinfo_file
git add --force .SRCINFO
# auto generate .SRCINFO if present
if [[ -f .SRCINFO ]]; then
stat_busy 'Generating .SRCINFO'
makepkg --printsrcinfo > .SRCINFO
git add .SRCINFO
stat_done
fi
if [[ -n $(git status --porcelain --untracked-files=no) ]]; then
stat_busy 'Staging files'
@@ -213,14 +215,14 @@ if [[ -n $(git status --porcelain --untracked-files=no) ]]; then
echo "$msgtemplate" > "$msgfile"
if [[ -n $GIT_EDITOR ]]; then
$GIT_EDITOR "$msgfile" || die
elif giteditor=$(git config --get core.editor); then
$giteditor "$msgfile" || die
elif [[ -n $VISUAL ]]; then
$VISUAL "$msgfile" || die
elif [[ -n $EDITOR ]]; then
$EDITOR "$msgfile" || die
elif giteditor=$(git config --get core.editor); then
$giteditor "$msgfile" || die
else
die "No usable editor found (tried \$GIT_EDITOR, git config [core.editor], \$VISUAL, \$EDITOR)."
die "No usable editor found (tried \$GIT_EDITOR, \$VISUAL, \$EDITOR, git config [core.editor])."
fi
[[ -s $msgfile ]] || die
stat_busy 'Committing changes'

View File

@@ -1,57 +0,0 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_API_ARCHWEB_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_API_ARCHWEB_SH=1
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
# shellcheck source=src/lib/common.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
set -e
set -o pipefail
archweb_query_all_packages() {
[[ -z ${WORKDIR:-} ]] && setup_workdir
stat_busy "Query all released packages"
mapfile -t pkgbases < <(
curl --location --show-error --no-progress-meter --fail --retry 3 --retry-delay 3 \
"${PKGBASE_MAINTAINER_URL}" 2> "${WORKDIR}/error" \
| jq --raw-output --exit-status 'keys[]' 2> "${WORKDIR}/error"
)
if ! wait $!; then
stat_failed
print_workdir_error
return 1
fi
stat_done
printf "%s\n" "${pkgbases[@]}"
return 0
}
archweb_query_maintainer_packages() {
local maintainer=$1
[[ -z ${WORKDIR:-} ]] && setup_workdir
stat_busy "Query maintainer packages"
mapfile -t pkgbases < <(
curl --location --show-error --no-progress-meter --fail --retry 3 --retry-delay 3 \
"${PKGBASE_MAINTAINER_URL}" 2> "${WORKDIR}/error" \
| jq --raw-output --exit-status '. as $parent | keys[] | select(. as $key | $parent[$key] | index("'"${maintainer}"'"))' 2> "${WORKDIR}/error"
)
if ! wait $!; then
stat_failed
print_workdir_error
return 1
fi
stat_done
printf "%s\n" "${pkgbases[@]}"
return 0
}

View File

@@ -13,63 +13,13 @@ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/config.sh
set -e
graphql_api_call() {
local outfile=$1
local request=$2
local node_type=$3
local data=$4
local hasNextPage cursor
# empty token
if [[ -z "${GITLAB_TOKEN}" ]]; then
msg_error " api call failed: No token provided"
return 1
fi
[[ -z ${WORKDIR:-} ]] && setup_workdir
api_workdir=$(mktemp --tmpdir="${WORKDIR}" --directory pkgctl-gitlab-api.XXXXXXXXXX)
# normalize graphql data and prepare query
data="${data//\"/\\\"}"
data='{
"query": "'"${data}"'"
}'
data="${data//$'\t'/ }"
data="${data//$'\n'/}"
cursor=""
hasNextPage=true
while [[ ${hasNextPage} == true ]]; do
data=$(sed -E 's|after: \\"[a-zA-Z0-9]*\\"|after: \\"'"${cursor}"'\\"|' <<< "${data}")
result="${api_workdir}/result.${cursor}"
if ! curl --request "${request}" \
--url "https://${GITLAB_HOST}/api/graphql" \
--header "Authorization: Bearer ${GITLAB_TOKEN}" \
--header "Content-Type: application/json" \
--data "${data}" \
--output "${result}" \
--silent; then
msg_error " api call failed: $(cat "${outfile}")"
return 1
fi
hasNextPage=$(jq --raw-output ".data | .${node_type} | .pageInfo | .hasNextPage" < "${result}")
cursor=$(jq --raw-output ".data | .${node_type} | .pageInfo | .endCursor" < "${result}")
cp "${result}" "${api_workdir}/tmp"
jq ".data.${node_type}.nodes" "${api_workdir}/tmp" > "${result}"
done
jq --slurp add "${api_workdir}"/result.* > "${outfile}"
return 0
}
gitlab_api_call() {
local outfile=$1
local request=$2
local endpoint=$3
local data=${4:-}
local error
# empty token
if [[ -z "${GITLAB_TOKEN}" ]]; then
@@ -88,113 +38,27 @@ gitlab_api_call() {
return 1
fi
if ! gitlab_check_api_errors "${outfile}"; then
return 1
fi
return 0
}
gitlab_api_call_paged() {
local outfile=$1
local status_file=$2
local request=$3
local endpoint=$4
local data=${5:-}
local result header
# empty token
if [[ -z "${GITLAB_TOKEN}" ]]; then
msg_error " api call failed: No token provided"
return 1
fi
[[ -z ${WORKDIR:-} ]] && setup_workdir
api_workdir=$(mktemp --tmpdir="${WORKDIR}" --directory pkgctl-gitlab-api.XXXXXXXXXX)
tmp_file=$(mktemp --tmpdir="${api_workdir}" spinner.tmp.XXXXXXXXXX)
local next_page=1
local total_pages=1
while [[ -n "${next_page}" ]]; do
percentage=$(( 100 * next_page / total_pages ))
printf "📡 Querying GitLab: %s/%s [%s] %%spinner%%" \
"${BOLD}${next_page}" "${total_pages}" "${percentage}%${ALL_OFF}" \
> "${tmp_file}"
mv "${tmp_file}" "${status_file}"
result="${api_workdir}/result.${next_page}"
header="${api_workdir}/header"
if ! curl --request "${request}" \
--get \
--url "https://${GITLAB_HOST}/api/v4/${endpoint}&per_page=100&page=${next_page}" \
--header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \
--header "Content-Type: application/json" \
--data-urlencode "${data}" \
--dump-header "${header}" \
--output "${result}" \
--silent; then
msg_error " api call failed: $(cat "${result}")"
return 1
fi
if ! gitlab_check_api_errors "${result}"; then
return 1
fi
next_page=$(grep "x-next-page" "${header}" | tr -d '\r' | awk '{ print $2 }')
total_pages=$(grep "x-total-pages" "${header}" | tr -d '\r' | awk '{ print $2 }')
done
jq --slurp add "${api_workdir}"/result.* > "${outfile}"
return 0
}
gitlab_check_api_errors() {
local file=$1
local error
# search API only returns an array, no errors
if [[ $(jq --raw-output 'type' < "${file}") == "array" ]]; then
return 0
fi
# check for general purpose api error
if error=$(jq --raw-output --exit-status '.error' < "${file}"); then
if error=$(jq --raw-output --exit-status '.error' < "${outfile}"); then
msg_error " api call failed: ${error}"
return 1
fi
# check for api specific error messages
if ! jq --raw-output --exit-status '.id' < "${file}" >/dev/null; then
if jq --raw-output --exit-status '.message | keys[]' < "${file}" &>/dev/null; then
if ! jq --raw-output --exit-status '.id' < "${outfile}" >/dev/null; then
if jq --raw-output --exit-status '.message | keys[]' < "${outfile}" &>/dev/null; then
while read -r error; do
msg_error " api call failed: ${error}"
done < <(jq --raw-output --exit-status '.message|to_entries|map("\(.key) \(.value[])")[]' < "${file}")
elif error=$(jq --raw-output --exit-status '.message' < "${file}"); then
done < <(jq --raw-output --exit-status '.message|to_entries|map("\(.key) \(.value[])")[]' < "${outfile}")
elif error=$(jq --raw-output --exit-status '.message' < "${outfile}"); then
msg_error " api call failed: ${error}"
fi
return 1
fi
return 0
}
graphql_check_api_errors() {
local file=$1
local error
# early exit if we do not have errors
if ! jq --raw-output --exit-status '.errors[]' < "${file}" &>/dev/null; then
return 0
fi
# check for api specific error messages
while read -r error; do
msg_error " api call failed: ${error}"
done < <(jq --raw-output --exit-status '.errors[].message' < "${file}")
return 1
}
gitlab_api_get_user() {
local outfile username
@@ -217,23 +81,6 @@ gitlab_api_get_user() {
return 0
}
gitlab_api_get_project_name_mapping() {
local query=$1
local outfile
[[ -z ${WORKDIR:-} ]] && setup_workdir
outfile=$(mktemp --tmpdir="${WORKDIR}" pkgctl-gitlab-api.XXXXXXXXXX)
# query user details
if ! graphql_api_call "${outfile}" POST projects "${query}"; then
msg_warn " Invalid token provided?"
exit 1
fi
cat "${outfile}"
return 0
}
# Convert arbitrary project names to GitLab valid path names.
#
# GitLab has several limitations on project and group names and also maintains
@@ -283,22 +130,3 @@ gitlab_api_create_project() {
printf "%s" "${path}"
return 0
}
# TODO: parallelize
# https://docs.gitlab.com/ee/api/search.html#scope-blobs
gitlab_api_search() {
local search=$1
local status_file=$2
local outfile
[[ -z ${WORKDIR:-} ]] && setup_workdir
outfile=$(mktemp --tmpdir="${WORKDIR}" pkgctl-gitlab-api.XXXXXXXXXX)
if ! gitlab_api_call_paged "${outfile}" "${status_file}" GET "/groups/archlinux%2fpackaging%2fpackages/search?scope=blobs" "search=${search}"; then
return 1
fi
cat "${outfile}"
return 0
}

View File

@@ -1,65 +0,0 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_AUR_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_AUR_SH=1
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
set -eo pipefail
pkgctl_aur_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [COMMAND] [OPTIONS]
Interact with the Arch User Repository (AUR).
Provides a suite of tools designed for managing and interacting with the Arch
User Repository (AUR). It simplifies various tasks related to AUR, including
importing repositories, managing packages, and transitioning packages between
the official repositories and the AUR.
COMMANDS
drop-from-repo Drop a package from the official repository to the AUR
OPTIONS
-h, --help Show this help text
EXAMPLES
$ ${COMMAND} drop-from-repo libfoo
_EOF_
}
pkgctl_aur() {
if (( $# < 1 )); then
pkgctl_aur_usage
exit 0
fi
# option checking
while (( $# )); do
case $1 in
-h|--help)
pkgctl_aur_usage
exit 0
;;
drop-from-repo)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/aur/drop-from-repo.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/aur/drop-from-repo.sh
pkgctl_aur_drop_from_repo "$@"
exit 0
;;
-*)
die "invalid argument: %s" "$1"
;;
*)
die "invalid command: %s" "$1"
;;
esac
done
}

View File

@@ -1,173 +0,0 @@
#!/bin/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_AUR_DROP_FROM_REPO_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_AUR_DROP_FROM_REPO_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/db/remove.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/db/remove.sh
# shellcheck source=src//lib/util/pacman.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/pacman.sh
source /usr/share/makepkg/util/message.sh
set -eo pipefail
pkgctl_aur_drop_from_repo_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS] [PATH]...
Drops a specified package from the official repositories to the Arch
User Repository.
This command requires a local Git clone of the package repository. It
reconfigures the repository for AUR compatibility and pushes it to the
AUR. Afterwards, the package is removed from the official repository.
By default, the package is automatically disowned in the AUR.
OPTIONS
--no-disown Do not disown the package on the AUR
-f, --force Force push to the AUR overwriting the remote repository
-h, --help Show this help text
EXAMPLES
$ ${COMMAND} foo
$ ${COMMAND} --no-disown --force
_EOF_
}
pkgctl_aur_drop_from_repo() {
# options
local paths=()
local DISOWN=1
local FORCE=0
# variables
local path realpath pkgbase pkgrepo remote_url
while (( $# )); do
case $1 in
-h|--help)
pkgctl_aur_drop_from_repo_usage
exit 0
;;
--no-disown)
DISOWN=0
shift
;;
-f|--force)
FORCE=1
shift
;;
--)
shift
break
;;
-*)
die "Invalid argument: %s" "$1"
;;
*)
paths=("$@")
break
;;
esac
done
# check if invoked without any path from within a packaging repo
if (( ${#paths[@]} == 0 )); then
if [[ -f PKGBUILD ]]; then
paths=(".")
else
pkgctl_aur_drop_from_repo_usage
exit 1
fi
fi
for path in "${paths[@]}"; do
# resolve symlink for basename
if ! realpath=$(realpath --canonicalize-existing -- "${path}"); then
die "No such directory: ${path}"
fi
# skip paths that are not directories
if [[ ! -d "${realpath}" ]]; then
continue
fi
pkgbase=$(basename "${realpath}")
pkgbase=${pkgbase%.git}
if [[ ! -d "${realpath}/.git" ]]; then
die "Not a Git repository: ${path}"
fi
pushd "${path}" >/dev/null
if [[ ! -f PKGBUILD ]]; then
die 'PKGBUILD not found in %s' "${path}"
fi
msg "Dropping ${pkgbase} to the AUR"
remote_url="${AUR_URL_SSH}:${pkgbase}.git"
if ! git remote add origin "${remote_url}" &>/dev/null; then
git remote set-url origin "${remote_url}"
fi
# move the main branch to master
if [[ $(git symbolic-ref --quiet --short HEAD) == main ]]; then
git branch --move master
git config branch.master.merge refs/heads/master
fi
# auto generate .SRCINFO if not already present
if [[ -z "$(git ls-tree -r HEAD --name-only .SRCINFO)" ]]; then
stat_busy 'Generating .SRCINFO'
makepkg --printsrcinfo > .SRCINFO
stat_done
git add --force -- .SRCINFO
git commit --quiet --message "Adding .SRCINFO" -- .SRCINFO
fi
msg "Pushing ${pkgbase} to the AUR"
if (( FORCE )); then
AUR_OVERWRITE=1 \
GIT_SSH_COMMAND="ssh -o SendEnv=AUR_OVERWRITE" \
git push --force --no-follow-tags origin master
else
git push --no-follow-tags origin master
fi
# update the local default branch in case this clone is used in the future
git remote set-head origin master
if (( DISOWN )); then
msg "Disowning ${pkgbase} on the AUR"
# shellcheck disable=SC2029
ssh "${AUR_URL_SSH}" disown "${pkgbase}"
fi
# auto-detection of the repo to remove from
if ! pkgrepo=$(get_pacman_repo_from_pkgbuild PKGBUILD); then
die 'Failed to get pacman repo'
fi
msg "Deleting ${pkgbase} from the official repository"
if [[ -z "${pkgrepo}" ]]; then
warning 'Did not find %s in any repository, please delete manually' "${pkgbase}"
else
msg2 " repo: ${pkgrepo}"
pkgctl_db_remove "${pkgrepo}" "${pkgbase}"
fi
popd >/dev/null
done
}

View File

@@ -14,25 +14,18 @@ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/db/update.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/release.sh
# shellcheck source=src/lib/util/git.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/git.sh
# shellcheck source=src/lib/util/srcinfo.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/srcinfo.sh
# shellcheck source=src/lib/util/pacman.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/pacman.sh
# shellcheck source=src/lib/util/pkgbuild.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/pkgbuild.sh
# shellcheck source=src/lib/valid-build-install.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-build-install.sh
# shellcheck source=src/lib/valid-repos.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-repos.sh
# shellcheck source=src/lib/valid-tags.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-tags.sh
# shellcheck source=src/lib/valid-inspect.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-inspect.sh
source /usr/share/makepkg/util/config.sh
source /usr/share/makepkg/util/message.sh
set -eo pipefail
set -e
set -o pipefail
pkgctl_build_usage() {
@@ -49,24 +42,19 @@ pkgctl_build_usage() {
BUILD OPTIONS
--arch ARCH Specify architectures to build for (disables auto-detection)
--repo REPO Specify target repository for new packages not in any official repo
--repo REPO Specify a target repository (disables auto-detection)
-s, --staging Build against the staging counterpart of the auto-detected repo
-t, --testing Build against the testing counterpart of the auto-detected repo
-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)
-I, --install FILE Install a package into the working copy of the chroot
-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
INSTALL OPTIONS
-I, --install-to-chroot FILE Install a package to the working copy of the chroot
-i, --install-to-host MODE Install the built package to the host system, possible modes are 'all' and 'auto'
PKGBUILD OPTIONS
--pkgver=PKGVER Set pkgver, reset pkgrel and update checksums
--pkgrel=PKGREL Set pkgrel to a given value
--rebuild Increment the current pkgrel variable
--update-checksums Force computation and update of the checksums (disables auto-detection)
-e, --edit Edit the PKGBUILD before building
RELEASE OPTIONS
@@ -89,7 +77,8 @@ pkgctl_build_check_option_group_repo() {
local repo=$2
local testing=$3
local staging=$4
if [[ -n "${repo}" ]] || (( testing )) || (( staging )); then
if ( (( testing )) && (( staging )) ) ||
( [[ $repo =~ ^.*-(staging|testing)$ ]] && ( (( testing )) || (( staging )) )); then
die "The argument '%s' cannot be used with one or more of the other specified arguments" "${option}"
exit 1
fi
@@ -115,7 +104,7 @@ pkgctl_build() {
exit 1
fi
local UPDATE_CHECKSUMS=0
local UPDPKGSUMS=0
local EDIT=0
local REBUILD=0
local OFFLOAD=0
@@ -123,7 +112,6 @@ pkgctl_build() {
local TESTING=0
local RELEASE=0
local DB_UPDATE=0
local INSTALL_TO_HOST=none
local REPO=
local PKGVER=
@@ -136,13 +124,12 @@ pkgctl_build() {
local MAKECHROOT_OPTIONS=()
local RELEASE_OPTIONS=()
local MAKEPKG_OPTIONS=()
local INSTALL_HOST_PACKAGES=()
local WORKER=
local WORKER_SLOT=
# variables
local _arch path pkgbase pkgrepo source pkgbuild_checksum current_checksum
local loop_arch path pkgbase pkgrepo source
while (( $# )); do
case $1 in
@@ -152,19 +139,18 @@ pkgctl_build() {
;;
--repo)
(( $# <= 1 )) && die "missing argument for %s" "$1"
pkgctl_build_check_option_group_repo '--repo' "${REPO}" "${TESTING}" "${STAGING}"
REPO="${2}"
RELEASE_OPTIONS+=("--repo" "${REPO}")
pkgctl_build_check_option_group_repo '--repo' "${REPO}" "${TESTING}" "${STAGING}"
shift 2
;;
--arch)
(( $# <= 1 )) && die "missing argument for %s" "$1"
if [[ ${2} == all ]]; then
BUILD_ARCH=("${DEVTOOLS_VALID_ARCHES[@]::${#DEVTOOLS_VALID_ARCHES[@]}-1}")
BUILD_ARCH=("${_arch[@]::${#_arch[@]}-1}")
elif [[ ${2} == any ]]; then
BUILD_ARCH=("${DEVTOOLS_VALID_ARCHES[0]}")
BUILD_ARCH=("${_arch[0]}")
elif ! in_array "${2}" "${BUILD_ARCH[@]}"; then
if ! in_array "${2}" "${DEVTOOLS_VALID_ARCHES[@]}"; then
if ! in_array "${2}" "${_arch[@]}"; then
die 'invalid architecture: %s' "${2}"
fi
BUILD_ARCH+=("${2}")
@@ -175,7 +161,7 @@ pkgctl_build() {
pkgctl_build_check_option_group_ver '--pkgver' "${PKGVER}" "${PKGREL}" "${REBUILD}"
PKGVER="${1#*=}"
PKGREL=1
UPDATE_CHECKSUMS=1
UPDPKGSUMS=1
shift
;;
--pkgrel=*)
@@ -183,10 +169,6 @@ pkgctl_build() {
PKGREL="${1#*=}"
shift
;;
--update-checksums)
UPDATE_CHECKSUMS=1
shift
;;
--rebuild)
# shellcheck source=src/lib/util/git.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/git.sh
@@ -203,37 +185,23 @@ pkgctl_build() {
shift
;;
-s|--staging)
pkgctl_build_check_option_group_repo '--staging' "${REPO}" "${TESTING}" "${STAGING}"
STAGING=1
RELEASE_OPTIONS+=("--staging")
pkgctl_build_check_option_group_repo '--staging' "${REPO}" "${TESTING}" "${STAGING}"
shift
;;
-t|--testing)
pkgctl_build_check_option_group_repo '--testing' "${REPO}" "${TESTING}" "${STAGING}"
TESTING=1
RELEASE_OPTIONS+=("--testing")
pkgctl_build_check_option_group_repo '--testing' "${REPO}" "${TESTING}" "${STAGING}"
shift
;;
-c|--clean)
BUILD_OPTIONS+=("-c")
shift
;;
-I|--install-to-chroot)
-I|--install)
(( $# <= 1 )) && die "missing argument for %s" "$1"
if (( OFFLOAD )); then
MAKECHROOT_OPTIONS+=("-I" "$2")
else
MAKECHROOT_OPTIONS+=("-I" "$(realpath "$2")")
fi
warning 'installing packages to the chroot may break reproducible builds, use with caution!'
shift 2
;;
-i|--install-to-host)
(( $# <= 1 )) && die "missing argument for %s" "$1"
if ! in_array "$2" "${DEVTOOLS_VALID_BUILD_INSTALL[@]}"; then
die 'invalid install mode: %s' "${2}"
fi
INSTALL_TO_HOST=$2
MAKECHROOT_OPTIONS+=("-I" "$2")
warning 'installing packages into the chroot may break reproducible builds, use with caution!'
shift 2
;;
--nocheck)
@@ -241,14 +209,6 @@ pkgctl_build() {
warning 'not running checks is disallowed for official packages, except for bootstrapping. Please rebuild after bootstrapping is completed!'
shift
;;
--inspect)
(( $# <= 1 )) && die "missing argument for %s" "$1"
if ! in_array "${2}" "${DEVTOOLS_VALID_INSPECT_MODES[@]}"; then
die "Invalid inspect mode: %s" "${2}"
fi
MAKECHROOT_OPTIONS+=("-x" "${2}")
shift 2
;;
-r|--release)
# shellcheck source=src/lib/release.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/release.sh
@@ -312,17 +272,13 @@ pkgctl_build() {
# Update pacman cache for auto-detection
if [[ -z ${REPO} ]]; then
update_pacman_repo_cache multilib
update_pacman_repo_cache
# Check valid repos if not resolved dynamically
elif ! in_array "${REPO}" "${DEVTOOLS_VALID_REPOS[@]}"; then
elif ! in_array "${REPO}" "${_repos[@]}"; then
die "Invalid repository target: %s" "${REPO}"
fi
for path in "${paths[@]}"; do
# skip paths that are not directories
if [[ ! -d "${path}" ]]; then
continue
fi
pushd "${path}" >/dev/null
if [[ ! -f PKGBUILD ]]; then
@@ -334,30 +290,16 @@ pkgctl_build() {
. ./PKGBUILD
pkgbase=${pkgbase:-$pkgname}
pkgrepo=${REPO}
pkgbuild_checksum=$(b2sum PKGBUILD | awk '{print $1}')
msg "Building ${pkgbase}"
# auto-detect target repository
if ! repo=$(get_pacman_repo_from_pkgbuild PKGBUILD); then
die 'Failed to query pacman repo'
fi
# fail if an existing package specifies --repo
if [[ -n "${repo}" ]] && [[ -n ${pkgrepo} ]]; then
# allow unstable to use --repo
if [[ ${pkgrepo} == *unstable ]]; then
repo=${pkgrepo}
else
die 'Using --repo for packages that exist in official repositories is disallowed'
# auto-detection of build target
if [[ -z ${pkgrepo} ]]; then
if ! pkgrepo=$(get_pacman_repo_from_pkgbuild PKGBUILD); then
die 'failed to get pacman repo'
fi
if [[ -z "${pkgrepo}" ]]; then
die 'unknown repo, specify --repo for packages not currently in any official repo'
fi
fi
# assign auto-detected target repository
if [[ -n ${repo} ]]; then
pkgrepo=${repo}
# fallback to extra for unreleased packages
elif [[ -z ${pkgrepo} ]]; then
pkgrepo=extra
fi
# special cases to resolve final build target
@@ -374,13 +316,13 @@ pkgctl_build() {
BUILD_ARCH=("")
elif (( ${#BUILD_ARCH[@]} == 0 )); then
if in_array any "${arch[@]}"; then
BUILD_ARCH=("${DEVTOOLS_VALID_ARCHES[0]}")
BUILD_ARCH=("${_arch[0]}")
else
for _arch in "${arch[@]}"; do
if in_array "${_arch}" "${DEVTOOLS_VALID_ARCHES[@]}"; then
BUILD_ARCH+=("$_arch")
for loop_arch in "${arch[@]}"; do
if in_array "${loop_arch}" "${_arch[@]}"; then
BUILD_ARCH+=("$loop_arch")
else
warning 'invalid architecture, not building for: %s' "${_arch}"
warning 'invalid architecture, not building for: %s' "${loop_arch}"
fi
done
fi
@@ -410,14 +352,20 @@ pkgctl_build() {
# update pkgver
if [[ -n ${PKGVER} ]]; then
if [[ $(type -t pkgver) == function ]]; then
# TODO: check if die or warn, if we provide _commit _gitcommit setter maybe?
warning 'setting pkgver variable has no effect if the PKGBUILD has a pkgver() function'
fi
msg "Bumping pkgver to ${PKGVER}"
pkgbuild_set_pkgver "${PKGVER}"
grep --extended-regexp --quiet --max-count=1 "^pkgver=${pkgver}$" PKGBUILD || die "Non-standard pkgver declaration"
sed --regexp-extended "s|^(pkgver=)${pkgver}$|\1${PKGVER}|g" -i PKGBUILD
fi
# update pkgrel
if [[ -n ${PKGREL} ]]; then
msg "Bumping pkgrel to ${PKGREL}"
pkgbuild_set_pkgrel "${PKGREL}"
grep --extended-regexp --quiet --max-count=1 "^pkgrel=${pkgrel}$" PKGBUILD || die "Non-standard pkgrel declaration"
sed --regexp-extended "s|^(pkgrel=)${pkgrel}$|\1${PKGREL}|g" -i PKGBUILD
fi
# edit PKGBUILD
@@ -437,19 +385,10 @@ pkgctl_build() {
stat_done
fi
# update checksums if any sources are declared
if (( UPDATE_CHECKSUMS )) && (( ${#source[@]} >= 1 )); then
if ! result=$(pkgbuild_update_checksums /dev/stderr); then
die "${result}"
fi
fi
# re-source the PKGBUILD if it changed
current_checksum="$(b2sum PKGBUILD | awk '{print $1}')"
if [[ ${pkgbuild_checksum} != "${current_checksum}" ]]; then
pkgbuild_checksum=${current_checksum}
# shellcheck source=contrib/makepkg/PKGBUILD.proto
. ./PKGBUILD
# update checksums if any sources are declared
if (( UPDPKGSUMS )) && (( ${#source[@]} >= 1 )); then
updpkgsums
fi
# execute build
@@ -469,41 +408,9 @@ pkgctl_build() {
fi
done
# re-source the PKGBUILD if it changed
current_checksum="$(b2sum PKGBUILD | awk '{print $1}')"
if [[ ${pkgbuild_checksum} != "${current_checksum}" ]]; then
pkgbuild_checksum=${current_checksum}
# shellcheck source=contrib/makepkg/PKGBUILD.proto
. ./PKGBUILD
fi
# auto generate .SRCINFO
# shellcheck disable=SC2119
write_srcinfo_file
# test-install (some of) the produced packages
if [[ ${INSTALL_TO_HOST} == auto ]] || [[ ${INSTALL_TO_HOST} == all ]]; then
# shellcheck disable=2119
load_makepkg_config
# this is inspired by print_all_package_names from libmakepkg
local version pkg_architecture pkg pkgfile
version=$(get_full_version)
for pkg in "${pkgname[@]}"; do
pkg_architecture=$(get_pkg_arch "$pkg")
pkgfile=$(realpath "$(printf "%s/%s-%s-%s%s\n" "${PKGDEST:-.}" "$pkg" "$version" "$pkg_architecture" "$PKGEXT")")
# check if we install all packages or if the (split-)package is already installed
if [[ ${INSTALL_TO_HOST} == all ]] || ( [[ ${INSTALL_TO_HOST} == auto ]] && pacman -Qq -- "$pkg" &>/dev/null ); then
INSTALL_HOST_PACKAGES+=("$pkgfile")
fi
done
fi
# release the build
if (( RELEASE )); then
pkgctl_release "${RELEASE_OPTIONS[@]}"
pkgctl_release --repo "${pkgrepo}" "${RELEASE_OPTIONS[@]}"
fi
# reset common PKGBUILD variables
@@ -511,12 +418,6 @@ pkgctl_build() {
popd >/dev/null
done
# install all collected packages to the host system
if (( ${#INSTALL_HOST_PACKAGES[@]} )); then
msg "Installing built packages to the host system"
sudo pacman -U -- "${INSTALL_HOST_PACKAGES[@]}"
fi
# update the binary package repo db as last action
if (( RELEASE )) && (( DB_UPDATE )); then
# shellcheck disable=2119

View File

@@ -1,22 +0,0 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_CACHE_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_CACHE_SH=1
set -e
readonly XDG_DEVTOOLS_CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/devtools"
get_cache_file() {
local filename=$1
local path="${XDG_DEVTOOLS_CACHE_DIR}/${filename}"
mkdir --parents -- "$(dirname -- "$path")"
if [[ ! -f ${path} ]]; then
touch -- "${path}"
fi
printf '%s' "${path}"
}

View File

@@ -13,7 +13,7 @@ set +u +o posix
$DEVTOOLS_INCLUDE_COMMON_SH
# Avoid any encoding problems
export LANG=C.UTF-8
export LANG=C
# Set buildtool properties
export BUILDTOOL=devtools
@@ -22,44 +22,21 @@ export BUILDTOOLVER=@buildtoolver@
# Set common properties
export PACMAN_KEYRING_DIR=/etc/pacman.d/gnupg
export GITLAB_HOST=gitlab.archlinux.org
export GIT_REPO_SPEC_VERSION=2
export GIT_REPO_SPEC_VERSION=1
export GIT_PACKAGING_NAMESPACE=archlinux/packaging/packages
export GIT_PACKAGING_NAMESPACE_ID=11323
export GIT_PACKAGING_URL_SSH="git@${GITLAB_HOST}:${GIT_PACKAGING_NAMESPACE}"
export GIT_PACKAGING_URL_HTTPS="https://${GITLAB_HOST}/${GIT_PACKAGING_NAMESPACE}"
export PACKAGING_REPO_RELEASE_HOST=repos.archlinux.org
export PKGBASE_MAINTAINER_URL=https://archlinux.org/packages/pkgbase-maintainer
export AUR_URL_SSH=aur@aur.archlinux.org
export RSYNC_OPTS=(
--rsh=ssh
--checksum
--copy-links
--human-readable
--progress
--partial
--partial-dir=.partial
--delay-updates
)
# ensure TERM is set with a fallback to dumb
export TERM=${TERM:-dumb}
export VALID_RELEASE_BRANCHES=(main unstable)
# check if messages are to be printed using color
if [[ -t 2 && "$TERM" != dumb ]] || [[ ${DEVTOOLS_COLOR} == always ]]; then
colorize
if tput setaf 0 &>/dev/null; then
PURPLE="$(tput setaf 5)"
DARK_GREEN="$(tput setaf 2)"
UNDERLINE="$(tput smul)"
else
PURPLE="\e[35m"
DARK_GREEN="\e[32m"
UNDERLINE="\e[4m"
fi
else
# shellcheck disable=2034
declare -gr ALL_OFF='' BOLD='' BLUE='' GREEN='' RED='' YELLOW='' PURPLE='' DARK_GREEN='' UNDERLINE=''
declare -gr ALL_OFF='' BOLD='' BLUE='' GREEN='' RED='' YELLOW=''
fi
stat_busy() {
@@ -78,11 +55,6 @@ stat_done() {
printf "${BOLD}done${ALL_OFF}\n" >&2
}
stat_failed() {
# shellcheck disable=2059
printf "${BOLD}${RED}failed${ALL_OFF}\n" >&2
}
msg_success() {
local msg=$1
local padding
@@ -107,15 +79,6 @@ msg_warn() {
printf "%s %s\n" "${padding}${YELLOW}!${ALL_OFF}" "${msg}" >&2
}
print_workdir_error() {
if [[ ! -f "${WORKDIR}"/error ]]; then
return
fi
while read -r LINE; do
error '%s' "${LINE}"
done < "${WORKDIR}/error"
}
_setup_workdir=false
setup_workdir() {
[[ -z ${WORKDIR:-} ]] && WORKDIR=$(mktemp -d --tmpdir "${0##*/}.XXXXXXXXXX")
@@ -128,9 +91,6 @@ cleanup() {
if [[ -n ${WORKDIR:-} ]] && $_setup_workdir; then
rm -rf "$WORKDIR"
fi
if tput setaf 0 &>/dev/null; then
tput cnorm >&2
fi
exit "${1:-0}"
}
@@ -162,7 +122,7 @@ lock() {
# Only reopen the FD if it wasn't handed to us
if ! [[ "/dev/fd/$1" -ef "$2" ]]; then
mkdir -p -- "$(dirname -- "$2")"
eval "exec $1>>"'"$2"'
eval "exec $1>"'"$2"'
fi
if ! flock -n "$1"; then
@@ -353,17 +313,3 @@ is_debug_package() {
pkgdesc="$(getpkgdesc "${pkgfile}")"
[[ ${pkgdesc} == "Detached debugging symbols for "* && ${pkgbase}-debug = "${pkgname}" ]]
}
# Proxy function to check if a file exists. Using [[ -f ... ]] directly is not
# always wanted because we might want to expand bash globs first. This way we
# can pass unquoted globs to is_globfile() and have them expanded as function
# arguments before being checked.
is_globfile() {
[[ -f $1 ]]
}
join_by() {
local IFS="$1"
shift
echo "$*"
}

View File

@@ -8,12 +8,6 @@ DEVTOOLS_INCLUDE_DB_REMOVE_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/util/pacman.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/pacman.sh
# shellcheck source=src/lib/util/term.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/term.sh
# shellcheck source=src/lib/valid-repos.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-repos.sh
set -e
@@ -23,19 +17,10 @@ pkgctl_db_remove_usage() {
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS] [REPO] [PKGBASE]...
Remove packages from pacman repositories. By default passing a pkgbase removes
all split packages, debug packages as well as entries from the state repo for
all existing architectures.
Beware when using the --partial option, as it may most likely lead to
undesired effects by leaving debug packages behind as well as dangling entries
in the state repository.
Remove packages from binary repositories.
OPTIONS
-a, --arch Remove only one specific architecture (disables auto-detection)
--partial Remove only partial pkgnames from a split package. This leaves
debug packages behind and pkgbase entries in the state repo.
--noconfirm Bypass any confirmation messages, should only be used with caution
-a, --arch Override the architecture (disables auto-detection)
-h, --help Show this help text
EXAMPLES
@@ -46,13 +31,8 @@ _EOF_
pkgctl_db_remove() {
local REPO=""
local ARCH=any
local PKGBASES=()
local pkgnames=()
local partial=0
local confirm=1
local dbscripts_options=()
local lookup_repo=multilib
local pkgname
# option checking
while (( $# )); do
@@ -61,20 +41,11 @@ pkgctl_db_remove() {
pkgctl_db_remove_usage
exit 0
;;
--partial)
partial=1
dbscripts_options+=(--partial)
shift
;;
-a|--arch)
(( $# <= 1 )) && die "missing argument for %s" "$1"
dbscripts_options+=(--arch "$2")
ARCH=$2
shift 2
;;
--noconfirm)
confirm=0
shift
;;
-*)
die "invalid argument: %s" "$1"
;;
@@ -92,62 +63,7 @@ pkgctl_db_remove() {
REPO=$1
shift
PKGBASES+=("$@")
pkgnames=("${PKGBASES[@]}")
# check if the target repo is valid
if ! in_array "${REPO}" "${DEVTOOLS_VALID_REPOS[@]}"; then
die "Invalid repository target: %s" "${REPO}"
fi
# update pacman cache to query all pkgnames
if (( ! partial )); then
case ${REPO} in
*-unstable)
update_pacman_repo_cache unstable
;;
*-staging)
update_pacman_repo_cache multilib-staging
;;
*-testing)
update_pacman_repo_cache multilib-testing
;;
*)
update_pacman_repo_cache multilib
;;
esac
# fetch the pkgnames of all pkgbase as present in the repo
mapfile -t pkgnames < <(get_pkgnames_from_repo_pkgbase "${REPO}" "${PKGBASES[@]}")
echo
if (( ! ${#pkgnames[@]} )); then
error "Packages not found in %s" "${REPO}"
exit 1
fi
fi
# print list of packages
printf "%sRemoving packages from %s:%s\n" "${RED}" "${REPO}" "${ALL_OFF}"
for pkgname in "${pkgnames[@]}"; do
printf "• %s\n" "${pkgname}"
done
# print explenation about partial removal
if (( partial )); then
echo
msg_warn "${YELLOW}Removing only partial pkgnames from a split package.${ALL_OFF}"
msg_warn "${YELLOW}This leaves debug packages and pkgbase entries in the state repo!${ALL_OFF}"
fi
# ask for confirmation
if (( confirm )); then
echo
if ! prompt "${GREEN}${BOLD}?${ALL_OFF} Are you sure this is correct?"; then
exit 1
fi
fi
echo
# shellcheck disable=SC2029
ssh "${PACKAGING_REPO_RELEASE_HOST}" db-remove "${dbscripts_options[@]}" "${REPO}" "${PKGBASES[@]}"
ssh "${PACKAGING_REPO_RELEASE_HOST}" db-remove "${REPO}" "${ARCH}" "${PKGBASES[@]}"
}

View File

@@ -35,7 +35,7 @@ pkgctl_release_usage() {
OPTIONS
-m, --message MSG Use the given <msg> as the commit message
-r, --repo REPO Specify target repository for new packages not in any official repo
-r, --repo REPO Specify a target repository (disables auto-detection)
-s, --staging Release to the staging counterpart of the auto-detected repo
-t, --testing Release to the testing counterpart of the auto-detected repo
-u, --db-update Automatically update the pacman database after uploading
@@ -43,8 +43,8 @@ pkgctl_release_usage() {
EXAMPLES
$ ${COMMAND}
$ ${COMMAND} --staging --message 'libyay 0.42 rebuild' libfoo libbar
$ ${COMMAND} --repo extra --db-update new-package
$ ${COMMAND} --repo core-testing --message 'libyay 0.42 rebuild' libfoo libbar
$ ${COMMAND} --staging --db-update libfoo
_EOF_
}
@@ -124,9 +124,9 @@ pkgctl_release() {
# Update pacman cache for auto-detection
if [[ -z ${REPO} ]]; then
update_pacman_repo_cache multilib
update_pacman_repo_cache
# Check valid repos if not resolved dynamically
elif ! in_array "${REPO}" "${DEVTOOLS_VALID_REPOS[@]}"; then
elif ! in_array "${REPO}" "${_repos[@]}"; then
die "Invalid repository target: %s" "${REPO}"
fi
@@ -134,27 +134,15 @@ pkgctl_release() {
pushd "${path}" >/dev/null
pkgbase=$(basename "${path}")
# auto-detect target repository
if ! repo=$(get_pacman_repo_from_pkgbuild PKGBUILD); then
die 'Failed to query pacman repo'
fi
# fail if an existing package specifies --repo
if [[ -n "${repo}" ]] && [[ -n ${REPO} ]]; then
# allow unstable to use --repo
if [[ ${REPO} == *unstable ]]; then
repo=${REPO}
else
die 'Using --repo for packages that exist in official repositories is disallowed'
fi
fi
# fail if a new package does not specify --repo
if [[ -z "${repo}" ]]; then
if [[ -z ${REPO} ]]; then
die 'Specify --repo for packages that do not yet exist in official repositories'
fi
if [[ -n ${REPO} ]]; then
repo=${REPO}
else
if ! repo=$(get_pacman_repo_from_pkgbuild PKGBUILD); then
die 'Failed to get pacman repo'
fi
if [[ -z "${repo}" ]]; then
die 'Unknown repo, please specify --repo for new packages'
fi
fi
if (( TESTING )); then

View File

@@ -27,7 +27,6 @@ pkgctl_repo_usage() {
without SSH access using read-only HTTPS.
COMMANDS
clean Remove untracked files from the working tree
clone Clone a package repository
configure Configure a clone according to distro specs
create Create a new GitLab package repository
@@ -38,7 +37,6 @@ pkgctl_repo_usage() {
-h, --help Show this help text
EXAMPLES
$ ${COMMAND} clean --interactive *
$ ${COMMAND} clone libfoo linux libbar
$ ${COMMAND} clone --maintainer mynickname
$ ${COMMAND} configure *
@@ -61,14 +59,6 @@ pkgctl_repo() {
pkgctl_repo_usage
exit 0
;;
clean)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/repo/clean.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/repo/clean.sh
pkgctl_repo_clean "$@"
exit 0
;;
clone)
_DEVTOOLS_COMMAND+=" $1"
shift

View File

@@ -1,114 +0,0 @@
#!/bin/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_REPO_CLEAN_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_REPO_CLEAN_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
pkgctl_repo_clean_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTION] [PATH]...
Cleans the working tree by recursively removing files that are not under
version control, starting from the current directory.
Files unknown to Git as well as ignored files are removed. This can, for
example, be useful to remove all build products.
OPTIONS
-i, --interactive Show what would be done and clean files interactively
-n, --dry-run Don't remove anything, just show what would be done
-h, --help Show this help text
EXAMPLES
$ ${COMMAND} libfoo linux libbar
$ ${COMMAND} --interactive libfoo linux libbar
$ ${COMMAND} --dry-run *
_EOF_
}
pkgctl_repo_clean() {
# options
local git_clean_options=()
local paths
local path pkgbase
while (( $# )); do
case $1 in
-i|--interactive)
git_clean_options+=("$1")
shift
;;
-n|--dry-run)
git_clean_options+=("$1")
shift
;;
-h|--help)
pkgctl_repo_clean_usage
exit 0
;;
--)
shift
break
;;
-*)
die "invalid argument: %s" "$1"
;;
*)
paths=("$@")
break
;;
esac
done
# check if invoked without any path from within a packaging repo
if (( ${#paths[@]} == 0 )); then
paths=(".")
fi
# print message about the work chunk
printf "🗑️ Removing untracked files from %s working trees\n" "${BOLD}${#paths[@]}${ALL_OFF}"
for path in "${paths[@]}"; do
# skip paths that are not directories
if [[ ! -d "${path}" ]]; then
continue
fi
if [[ ! -f "${path}/PKGBUILD" ]]; then
msg_error "Not a package repository: ${path}"
continue
fi
if [[ ! -d "${path}/.git" ]]; then
msg_error "Not a Git repository: ${path}"
continue
fi
pkgbase=$(basename "$(realpath "${path}")")
pkgbase=${pkgbase%.git}
# run dry mode to see if git would clean any files
if [[ ! $(git -C "${path}" clean -x -d --dry-run 2>&1) ]]; then
continue
fi
# git clean untracked files
msg_success "Cleaning ${BOLD}${pkgbase}${ALL_OFF}"
if ! git -C "${path}" clean -x -d --force "${git_clean_options[@]}"; then
msg_error "Failed to remove untracked files"
fi
echo
done
}

View File

@@ -8,19 +8,14 @@ DEVTOOLS_INCLUDE_REPO_CLONE_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/api/archweb.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/api/archweb.sh
# shellcheck source=src/lib/api/gitlab.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/api/gitlab.sh
# shellcheck source=src/lib/repo/configure.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/repo/configure.sh
# shellcheck source=src/lib/util/git.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/git.sh
source /usr/share/makepkg/util/message.sh
set -e
set -o pipefail
pkgctl_repo_clone_usage() {
@@ -57,7 +52,6 @@ pkgctl_repo_clone() {
fi
# options
local protocol=ssh
local GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_SSH}
local CLONE_ALL=0
local MAINTAINER=
@@ -78,7 +72,6 @@ pkgctl_repo_clone() {
;;
--protocol=https)
GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_HTTPS}
protocol=https
CONFIGURE_OPTIONS+=("$1")
shift
;;
@@ -89,7 +82,6 @@ pkgctl_repo_clone() {
else
die "unsupported protocol: %s" "$2"
fi
protocol="$2"
CONFIGURE_OPTIONS+=("$1" "$2")
shift 2
;;
@@ -140,18 +132,33 @@ pkgctl_repo_clone() {
# Query packages of a maintainer
if [[ -n ${MAINTAINER} ]]; then
mapfile -t pkgbases < <(archweb_query_maintainer_packages "${MAINTAINER}")
if ! wait $!; then
die "Failed to query maintainer packages"
stat_busy "Query packages"
max_pages=$(curl --silent --location --fail --retry 3 --retry-delay 3 "https://archlinux.org/packages/search/json/?sort=name&maintainer=${MAINTAINER}" | jq -r '.num_pages')
if [[ ! ${max_pages} =~ ([[:digit:]]) ]]; then
stat_done
warning "found no packages for maintainer ${MAINTAINER}"
exit 0
fi
mapfile -t pkgbases < <(for page in $(seq "${max_pages}"); do
curl --silent --location --fail --retry 3 --retry-delay 3 "https://archlinux.org/packages/search/json/?sort=name&maintainer=${MAINTAINER}&page=${page}" | jq -r '.results[].pkgbase'
stat_progress
done | sort --unique)
stat_done
fi
# Query all released packages
if (( CLONE_ALL )); then
mapfile -t pkgbases < <(archweb_query_all_packages)
if ! wait $!; then
die "Failed to query all packages"
stat_busy "Query all released packages"
max_pages=$(curl --silent --location --fail --retry 3 --retry-delay 3 "https://archlinux.org/packages/search/json/?sort=name" | jq -r '.num_pages')
if [[ ! ${max_pages} =~ ([[:digit:]]) ]]; then
stat_done
die "failed to query packages"
fi
mapfile -t pkgbases < <(for page in $(seq "${max_pages}"); do
curl --silent --location --fail --retry 3 --retry-delay 3 "https://archlinux.org/packages/search/json/?sort=name&page=${page}" | jq -r '.results[].pkgbase'
stat_progress
done | sort --unique)
stat_done
fi
# parallelization
@@ -164,12 +171,6 @@ pkgctl_repo_clone() {
if [[ -n "${VERSION}" ]]; then
command+=" --switch '${VERSION}'"
fi
# warm up ssh connection as it may require user input (key unlock, hostkey verification etc)
if [[ ${protocol} == ssh ]]; then
git_warmup_ssh_connection
fi
if ! parallel --bar --jobs "${jobs}" "${command}" ::: "${pkgbases[@]}"; then
die 'Failed to clone some packages, please check the output'
exit 1

View File

@@ -10,14 +10,11 @@ _DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
# shellcheck source=src/lib/api/gitlab.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/api/gitlab.sh
# shellcheck source=src/lib/util/git.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/git.sh
source /usr/share/makepkg/util/config.sh
source /usr/share/makepkg/util/message.sh
set -e
shopt -s nullglob
pkgctl_repo_configure_usage() {
@@ -35,8 +32,6 @@ pkgctl_repo_configure_usage() {
address by choosing SSH for all official packager identities and
read-only HTTPS otherwise.
Git default excludes and hooks are applied to the configured repo.
OPTIONS
--protocol https Configure remote url to use https
-j, --jobs N Run up to N jobs in parallel (default: $(nproc))
@@ -107,7 +102,7 @@ pkgctl_repo_configure() {
# variables
local -r command=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
local path realpath pkgbase remote_url project_path hook
local path realpath pkgbase remote_url project_path
local PACKAGER GPGKEY packager_name packager_email
while (( $# )); do
@@ -193,12 +188,6 @@ pkgctl_repo_configure() {
if [[ -n ${BOLD} ]]; then
export DEVTOOLS_COLOR=always
fi
# warm up ssh connection as it may require user input (key unlock, hostkey verification etc)
if [[ ${proto} == ssh ]]; then
git_warmup_ssh_connection
fi
if ! parallel --bar --jobs "${jobs}" "${command}" ::: "${paths[@]}"; then
die 'Failed to configure some packages, please check the output'
exit 1
@@ -207,14 +196,9 @@ pkgctl_repo_configure() {
fi
for path in "${paths[@]}"; do
# resolve symlink for basename
if ! realpath=$(realpath --canonicalize-existing -- "${path}"); then
if ! realpath=$(realpath -e "${path}"); then
die "No such directory: ${path}"
fi
# skip paths that aren't directories
if [[ ! -d "${realpath}" ]]; then
continue
fi
pkgbase=$(basename "${realpath}")
pkgbase=${pkgbase%.git}
@@ -238,15 +222,7 @@ pkgctl_repo_configure() {
git config branch.main.merge refs/heads/main
fi
# configure spec version and variant to avoid using development hooks in production
git config devtools.version "${GIT_REPO_SPEC_VERSION}"
if [[ ${_DEVTOOLS_LIBRARY_DIR} == /usr/share/devtools ]]; then
git config devtools.variant canonical
else
warning "Configuring with development version of pkgctl, do not use this repo in production"
git config devtools.variant development
fi
git config pull.rebase true
git config branch.autoSetupRebase always
git config branch.main.remote origin
@@ -273,18 +249,6 @@ pkgctl_repo_configure() {
git config user.signingKey "${GPGKEY}"
fi
# set default git exclude
mkdir -p .git/info
ln -sf "${_DEVTOOLS_LIBRARY_DIR}/git.conf.d/template/info/exclude" \
.git/info/exclude
# set default git hooks
mkdir -p .git/hooks
rm -f .git/hooks/*.sample
for hook in "${_DEVTOOLS_LIBRARY_DIR}"/git.conf.d/template/hooks/*; do
ln -sf "${hook}" ".git/hooks/$(basename "${hook}")"
done
if ! git ls-remote origin &>/dev/null; then
warning "configured remote origin may not exist, run:"
msg2 "pkgctl repo create ${pkgbase}"

View File

@@ -101,21 +101,16 @@ pkgctl_repo_switch() {
fi
for path in "${paths[@]}"; do
# resolve symlink for basename
if ! realpath=$(realpath --canonicalize-existing -- "${path}"); then
if ! realpath=$(realpath -e -- "${path}"); then
die "No such directory: ${path}"
fi
# skip paths that are not directories
if [[ ! -d "${realpath}" ]]; then
continue
fi
# skip paths that are not git repositories
if [[ ! -d "${realpath}/.git" ]]; then
pkgbase=$(basename "${realpath}")
if [[ ! -d "${path}/.git" ]]; then
error "Not a Git repository: ${path}"
continue
fi
pkgbase=$(basename "${realpath}")
if ! git -C "${path}" checkout "${GIT_CHECKOUT_OPTIONS[@]}" "${GIT_REF}"; then
die "Failed to switch ${pkgbase} to version ${VERSION}"
fi

View File

@@ -23,7 +23,6 @@ pkgctl_repo_web_usage() {
no arguments, open the package cloned in the current working directory.
OPTIONS
--print Print the url instead of opening it with xdg-open
-h, --help Show this help text
EXAMPLES
@@ -33,8 +32,7 @@ _EOF_
pkgctl_repo_web() {
local pkgbases=()
local path giturl pkgbase url
local mode=open
local path giturl pkgbase
# option checking
while (( $# )); do
@@ -43,10 +41,6 @@ pkgctl_repo_web() {
pkgctl_repo_web_usage
exit 0
;;
--print)
mode=print
shift
;;
--)
shift
break
@@ -62,7 +56,7 @@ pkgctl_repo_web() {
done
# Check if web mode has xdg-open
if [[ ${mode} == open ]] && ! command -v xdg-open &>/dev/null; then
if ! command -v xdg-open &>/dev/null; then
die "The web command requires 'xdg-open'"
fi
@@ -84,18 +78,7 @@ pkgctl_repo_web() {
fi
for pkgbase in "${pkgbases[@]}"; do
pkgbase=$(basename "${pkgbase}")
path=$(gitlab_project_name_to_path "${pkgbase}")
url="${GIT_PACKAGING_URL_HTTPS}/${path}"
case ${mode} in
open)
xdg-open "${url}"
;;
print)
printf "%s\n" "${url}"
;;
*)
die "Unknown mode: ${mode}"
esac
xdg-open "${GIT_PACKAGING_URL_HTTPS}/${path}"
done
}

View File

@@ -1,308 +0,0 @@
#!/bin/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_SEARCH_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_SEARCH_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/cache.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/cache.sh
# shellcheck source=src/lib/api/gitlab.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/api/gitlab.sh
# shellcheck source=src/lib/valid-search.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-search.sh
# shellcheck source=src/lib/util/term.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/term.sh
source /usr/share/makepkg/util/util.sh
source /usr/share/makepkg/util/message.sh
set -eo pipefail
pkgctl_search_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS] QUERY
Search for an expression across the GitLab packaging group.
To use a filter, include it in your query. You may use wildcards (*) to
use glob matching.
Available filters for the blobs scope: path, extension
Every usage of the search command must be authenticated. Consult the
'pkgctl auth' command to authenticate with GitLab or view the
authentication status.
SEARCH TIPS
Syntax Description Example
───────────────────────────────────────
" Exact search "gem sidekiq"
~ Fuzzy search J~ Doe
| Or display | banner
+ And display +banner
- Exclude display -banner
* Partial bug error 50*
\\ Escape \\*md
# Issue ID #23456
! Merge request !23456
OPTIONS
-h, --help Show this help text
FILTER OPTIONS
--no-default-filter Do not apply default filter (like -path:keys/pgp/*.asc)
OUTPUT OPTIONS
--json Enable printing in JSON; Shorthand for '--format json'
-F, --format FORMAT Controls the formatting of the results; FORMAT is 'pretty',
'plain', or 'json' (default: pretty)
-N, --no-line-number Don't show line numbers when formatting results
EXAMPLES
$ ${COMMAND} linux
$ ${COMMAND} --json '"pytest -v" +PYTHONPATH'
_EOF_
}
pkgctl_search_check_option_group_format() {
local option=$1
local output_format=$2
if [[ -n ${output_format} ]]; then
die "The argument '%s' cannot be used with one or more of the other specified arguments" "${option}"
exit 1
fi
return 0
}
pkgctl_search() {
if (( $# < 1 )); then
pkgctl_search_usage
exit 0
fi
# options
local search
local output_format=
local use_default_filter=1
local line_numbers=1
# variables
local bat_style="header,grid"
local default_filter="-path:keys/pgp/*.asc"
local graphql_lookup_batch=200
local output result query entries from until length
local project_name_cache_file project_name_lookup project_ids project_id project_name project_slice
local mapping_output path startline currentline data line
while (( $# )); do
case $1 in
-h|--help)
pkgctl_search_usage
exit 0
;;
--no-default-filter)
use_default_filter=0
shift
;;
--json)
pkgctl_search_check_option_group_format "$1" "${output_format}"
output_format=json
shift
;;
-F|--format)
(( $# <= 1 )) && die "missing argument for %s" "$1"
pkgctl_search_check_option_group_format "$1" "${output_format}"
output_format="${2}"
if ! in_array "${output_format}" "${valid_search_output_format[@]}"; then
die "Unknown output format: %s" "${output_format}"
fi
shift 2
;;
-N|--no-line-number)
line_numbers=0
shift
;;
--)
shift
break
;;
-*)
die "invalid argument: %s" "$1"
;;
*)
break
;;
esac
done
if (( $# == 0 )); then
pkgctl_search_usage
exit 1
fi
# assign search parameter
search="${*}"
if (( use_default_filter )); then
search+=" ${default_filter}"
fi
# assign default output format
if [[ -z ${output_format} ]]; then
output_format=pretty
fi
# check for optional dependencies
if [[ ${output_format} == pretty ]] && ! command -v bat &>/dev/null; then
warning "Failed to find optional dependency 'bat': falling back to plain output"
output_format=plain
fi
# populate line numbers option
if (( line_numbers )); then
bat_style="numbers,${bat_style}"
fi
# call the gitlab search API
status_dir=$(mktemp --tmpdir="${WORKDIR}" --directory pkgctl-gitlab-api.XXXXXXXXXX)
printf "📡 Querying GitLab search API..." > "${status_dir}/status"
term_spinner_start "${status_dir}"
output=$(gitlab_api_search "${search}" "${status_dir}/status")
term_spinner_stop "${status_dir}"
msg_success "Querying GitLab search API"
# collect project ids whose name needs to be looked up
project_name_cache_file=$(get_cache_file gitlab/project_id_to_name)
lock 11 "${project_name_cache_file}" "Locking project name cache"
mapfile -t project_ids < <(
jq --raw-output '[.[].project_id] | unique[]' <<< "${output}" | \
grep --invert-match --file <(awk '{ print $1 }' < "${project_name_cache_file}" ))
# look up project names
tmp_file=$(mktemp --tmpdir="${WORKDIR}" pkgctl-gitlab-api-spinner.tmp.XXXXXXXXXX)
printf "📡 Querying GitLab project names..." > "${status_dir}/status"
term_spinner_start "${status_dir}"
local entries="${#project_ids[@]}"
local until=0
while (( until < entries )); do
from=${until}
until=$(( until + graphql_lookup_batch ))
if (( until > entries )); then
until=${entries}
fi
length=$(( until - from ))
percentage=$(( 100 * until / entries ))
printf "📡 Querying GitLab project names: %s/%s [%s] %%spinner%%" \
"${BOLD}${until}" "${entries}" "${percentage}%${ALL_OFF}" \
> "${tmp_file}"
mv "${tmp_file}" "${status_dir}/status"
project_slice=("${project_ids[@]:${from}:${length}}")
printf -v projects '"gid://gitlab/Project/%s",' "${project_slice[@]}"
query='{
projects(after: "" ids: ['"${projects}"']) {
pageInfo {
startCursor
endCursor
hasNextPage
}
nodes {
id
name
}
}
}'
mapping_output=$(gitlab_api_get_project_name_mapping "${query}")
# update cache
while read -r project_id project_name; do
printf "%s %s\n" "${project_id}" "${project_name}" >> "${project_name_cache_file}"
done < <(jq --raw-output \
'.[] | "\(.id | rindex("/") as $lastSlash | .[$lastSlash+1:]) \(.name)"' \
<<< "${mapping_output}")
done
term_spinner_stop "${status_dir}"
msg_success "Querying GitLab project names"
# read project_id to name mapping from cache
declare -A project_name_lookup=()
while read -r project_id project_name; do
project_name_lookup[${project_id}]=${project_name}
done < "${project_name_cache_file}"
# close project name cache lock
lock_close 11
# output mode JSON
if [[ ${output_format} == json ]]; then
jq --from-file <(
for project_id in $(jq '.[].project_id' <<< "${output}"); do
project_name=${project_name_lookup[${project_id}]}
printf 'map(if .project_id == %s then . + {"project_name": "%s"} else . end) | ' \
"${project_id}" "${project_name}"
done
printf .
) <<< "${output}"
exit 0
fi
# pretty print each result
while read -r result; do
# read properties from search result
mapfile -t data < <(jq --raw-output ".data" <<< "${result}")
{ read -r project_id; read -r path; read -r startline; } < <(
jq --raw-output ".project_id, .path, .startline" <<< "${result}"
)
project_name=${project_name_lookup[${project_id}]}
# remove trailing newline for multiline results
if (( ${#data[@]} > 1 )) && [[ ${data[-1]} == "" ]]; then
unset "data[${#data[@]}-1]"
fi
# output mode plain
if [[ ${output_format} == plain ]]; then
printf "%s%s%s\n" "${PURPLE}" "${project_name}/${path}" "${ALL_OFF}"
currentline=${startline}
for line in "${data[@]}"; do
if (( line_numbers )); then
line="${DARK_GREEN}${currentline}${ALL_OFF}: ${line}"
currentline=$(( currentline + 1 ))
fi
printf "%s\n" "${line}"
done
printf "\n"
continue
fi
# prepend empty lines to match startline
if (( startline > 1 )); then
mapfile -t data < <(
printf '%.0s\n' $(seq 1 "$(( startline - 1 ))")
printf "%s\n" "${data[@]}"
)
fi
bat \
--file-name="${project_name}/${path}" \
--line-range "${startline}:" \
--paging=never \
--force-colorization \
--style "${bat_style}" \
--map-syntax "PKGBUILD:Bourne Again Shell (bash)" \
--map-syntax ".SRCINFO:INI" \
--map-syntax "*install:Bourne Again Shell (bash)" \
--map-syntax "*sysusers*:Bourne Again Shell (bash)" \
--map-syntax "*tmpfiles*:Bourne Again Shell (bash)" \
--map-syntax "*.hook:INI" \
<(printf "%s\n" "${data[@]}")
done < <(jq --compact-output '.[]' <<< "${output}")
}

View File

@@ -7,9 +7,6 @@ DEVTOOLS_INCLUDE_UTIL_GIT_SH=1
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
# shellcheck source=src/lib/common.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
git_diff_tree() {
local commit=$1
@@ -26,9 +23,7 @@ git_diff_tree() {
-- "${path}"
}
git_warmup_ssh_connection() {
msg 'Establishing ssh connection to git@%s' "${GITLAB_HOST}"
if ! ssh -T "git@${GITLAB_HOST}" >/dev/null; then
die 'Failed to establish ssh connection to git@%s' "${GITLAB_HOST}"
fi
is_valid_release_branch() {
local branch=$1
in_array "${branch}" "${VALID_RELEASE_BRANCHES[@]}"
}

View File

@@ -1,57 +0,0 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_UTIL_MAKEPKG_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_UTIL_MAKEPKG_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/util/srcinfo.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/srcinfo.sh
set -e
makepkg_source_package() {
if (( EUID != 0 )); then
[[ -z ${WORKDIR:-} ]] && setup_workdir
export WORKDIR DEVTOOLS_INCLUDE_COMMON_SH
fakeroot -- bash -$- -c "source '${BASH_SOURCE[0]}' && ${FUNCNAME[0]}"
return
fi
(
# shellcheck disable=SC2030 disable=SC2031
export LIBMAKEPKG_LINT_PKGBUILD_SH=1
lint_pkgbuild() { :; }
# shellcheck disable=SC2030 disable=SC2031
export LIBMAKEPKG_SRCINFO_SH=1
write_srcinfo() { print_srcinfo; }
# explicitly instruct makepkg to not sign the source package, even when
# the BUILDENV array in makepkg.conf contains 'sign'
set +e -- -F --source --nosign
# shellcheck source=/usr/bin/makepkg
source "$(command -v makepkg)"
)
}
makepkg_generate_integrity() {
if [[ -z ${DEVTOOLS_GENERATE_INTEGRITY} ]]; then
[[ -z ${WORKDIR:-} ]] && setup_workdir
export WORKDIR DEVTOOLS_INCLUDE_COMMON_SH
bash -$- -c "DEVTOOLS_GENERATE_INTEGRITY=1; source '${BASH_SOURCE[0]}' && ${FUNCNAME[0]}"
return
fi
(
# shellcheck disable=SC2030 disable=SC2031
export LIBMAKEPKG_LINT_PKGBUILD_SH=1
lint_pkgbuild() { :; }
set +e -- --geninteg
# shellcheck source=/usr/bin/makepkg
source "$(command -v makepkg)"
)
}

View File

@@ -18,12 +18,10 @@ readonly _DEVTOOLS_MAKEPKG_CONF_DIR=${_DEVTOOLS_LIBRARY_DIR}/makepkg.conf.d
update_pacman_repo_cache() {
local repo=${1:-multilib}
mkdir -p "${_DEVTOOLS_PACMAN_CACHE_DIR}"
msg "Updating pacman database cache"
lock 10 "${_DEVTOOLS_PACMAN_CACHE_DIR}.lock" "Locking pacman database cache"
fakeroot -- pacman --config "${_DEVTOOLS_PACMAN_CONF_DIR}/${repo}.conf" \
fakeroot -- pacman --config "${_DEVTOOLS_PACMAN_CONF_DIR}/multilib.conf" \
--dbpath "${_DEVTOOLS_PACMAN_CACHE_DIR}" \
-Sy
lock_close 10
@@ -31,7 +29,6 @@ update_pacman_repo_cache() {
get_pacman_repo_from_pkgbuild() {
local path=${1:-PKGBUILD}
local repo=${2:-multilib}
# shellcheck source=contrib/makepkg/PKGBUILD.proto
mapfile -t pkgnames < <(source "${path}"; printf "%s\n" "${pkgname[@]}")
@@ -41,50 +38,15 @@ get_pacman_repo_from_pkgbuild() {
return
fi
# update the pacman repo cache if it doesn't exist yet
if [[ ! -d "${_DEVTOOLS_PACMAN_CACHE_DIR}" ]]; then
update_pacman_repo_cache "${repo}"
fi
slock 10 "${_DEVTOOLS_PACMAN_CACHE_DIR}.lock" "Locking pacman database cache"
# query repo of passed pkgname, specify --nodeps twice to skip all dependency checks
mapfile -t repos < <(pacman --config "${_DEVTOOLS_PACMAN_CONF_DIR}/${repo}.conf" \
mapfile -t repos < <(pacman --config "${_DEVTOOLS_PACMAN_CONF_DIR}/multilib.conf" \
--dbpath "${_DEVTOOLS_PACMAN_CACHE_DIR}" \
--sync \
--nodeps \
--nodeps \
-S \
--print \
--print-format '%n %r' \
"${pkgnames[0]}" 2>/dev/null | awk '$1=="'"${pkgnames[0]}"'"{print $2}'
"${pkgnames[0]}" | grep -E "^${pkgnames[0]} " | awk '{print $2}'
)
lock_close 10
printf "%s" "${repos[0]}"
}
get_pkgnames_from_repo_pkgbase() {
local repo=$1
shift
local pkgbases=("$@")
# update the pacman repo cache if it doesn't exist yet
if [[ ! -d "${_DEVTOOLS_PACMAN_CACHE_DIR}" ]]; then
update_pacman_repo_cache universe
fi
slock 10 "${_DEVTOOLS_PACMAN_CACHE_DIR}.lock" "Locking pacman database cache"
# query pkgnames of passed pkgbase inside a repo
mapfile -t pkgnames < <(expac --config <(sed "s|#DBPath.*|DBPath = $(realpath "${_DEVTOOLS_PACMAN_CACHE_DIR}")|" < "${_DEVTOOLS_PACMAN_CONF_DIR}/universe.conf") \
--sync '%r %e %n' 2>/dev/null \
| sort | awk -v pkgbase="${pkgbases[*]}" \
'BEGIN { split(pkgbase, array); for (item in array) filter[array[item]]=1 } $1=="'"${repo}"'" && $2 in filter {print $3}'
)
lock_close 10
if (( ! ${#pkgnames[@]} )); then
return 1
fi
printf "%s\n" "${pkgnames[@]}"
return 0
}

View File

@@ -1,91 +0,0 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_UTIL_PKGBUILD_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_UTIL_PKGBUILD_SH=1
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
# shellcheck source=src/lib/util/makepkg.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/makepkg.sh
source /usr/share/makepkg/util/message.sh
source /usr/share/makepkg/util/schema.sh
set -eo pipefail
# set the pkgver variable in a PKGBUILD
# assumes that the pkgbuild is sourced to detect the presence of a pkgver function
pkgbuild_set_pkgver() {
local new_pkgver=$1
local pkgver=${pkgver}
if [[ $(type -t pkgver) == function ]]; then
# TODO: check if die or warn, if we provide _commit _gitcommit setter maybe?
warning 'setting pkgver variable has no effect if the PKGBUILD has a pkgver() function'
fi
if ! grep --extended-regexp --quiet --max-count=1 "^pkgver=${pkgver}$" PKGBUILD; then
die "Non-standard pkgver declaration"
fi
sed --regexp-extended "s|^(pkgver=)${pkgver}$|\1${new_pkgver}|g" --in-place PKGBUILD
}
# set the pkgrel variable in a PKGBUILD
# assumes that the pkgbuild is sourced so pkgrel is present
pkgbuild_set_pkgrel() {
local new_pkgrel=$1
local pkgrel=${pkgrel}
if ! grep --extended-regexp --quiet --max-count=1 "^pkgrel=${pkgrel}$" PKGBUILD; then
die "Non-standard pkgrel declaration"
fi
sed --regexp-extended "s|^(pkgrel=)${pkgrel}$|\1${new_pkgrel}|g" --in-place PKGBUILD
}
pkgbuild_update_checksums() {
local status_file=$1
local builddir newbuildfile sumtypes newsums
[[ -z ${WORKDIR:-} ]] && setup_workdir
builddir=$(mktemp --tmpdir="${WORKDIR}" --directory update-checksums.XXXXXX)
newbuildfile="${builddir}/PKGBUILD"
# generate new integrity checksums
if ! newsums=$(BUILDDIR=${builddir} makepkg_generate_integrity 2>"${status_file}"); then
printf 'Failed to generate new checksums'
return 1
fi
# early exit if no integrity checksums are needed
if [[ -z ${newsums} ]]; then
return 0
fi
# replace the integrity sums and write it to a temporary file
sumtypes=$(IFS='|'; echo "${known_hash_algos[*]}")
if ! awk --assign=sumtypes="${sumtypes}" --assign=newsums="${newsums}" '
$0 ~"^[[:blank:]]*(" sumtypes ")sums(_[^=]+)?\\+?=", $0 ~ "\\)[[:blank:]]*(#.*)?$" {
if (!w) {
print newsums
w++
}
next
}
1
END { if (!w) print newsums }' PKGBUILD > "${newbuildfile}"; then
printf 'Failed to replace the generated checksums'
return 1
fi
# overwrite the original PKGBUILD while preserving permissions
if ! cat -- "${newbuildfile}" > PKGBUILD; then
printf "Failed to write to the PKGBUILD file"
return 1
fi
return 0
}

View File

@@ -1,69 +0,0 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_UTIL_SRCINFO_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_UTIL_SRCINFO_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/util.sh
source /usr/share/makepkg/srcinfo.sh
set -eo pipefail
print_srcinfo() {
local pkgpath=${1:-.}
local outdir pkg pid
local pids=()
# source the PKGBUILD
# shellcheck source=contrib/makepkg/PKGBUILD.proto
. "${pkgpath}"/PKGBUILD
# run without parallelization for single packages
if (( ${#pkgname[@]} == 1 )); then
write_srcinfo_content
return 0
fi
[[ -z ${WORKDIR:-} ]] && setup_workdir
outdir=$(mktemp --directory --tmpdir="${WORKDIR}" pkgctl-srcinfo.XXXXXXXXXX)
# fork workload for each split pkgname
for pkg in "${pkgname[@]}"; do
(
# deactivate errexit to avoid makepkg abort on grep_function
set +e
srcinfo_write_package "$pkg" > "${outdir}/${pkg}"
)&
pids+=($!)
done
# join workload
for pid in "${pids[@]}"; do
if ! wait "${pid}"; then
return 1
fi
done
# collect output
srcinfo_write_global
for pkg in "${pkgname[@]}"; do
srcinfo_separate_section
cat "${outdir}/${pkg}"
done
}
write_srcinfo_file() {
local pkgpath=${1:-.}
stat_busy 'Generating .SRCINFO'
if ! print_srcinfo "${pkgpath}" > "${pkgpath}"/.SRCINFO; then
error 'Failed to write .SRCINFO file'
return 1
fi
stat_done
}

View File

@@ -1,198 +0,0 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_UTIL_TERM_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_UTIL_TERM_SH=1
set -eo pipefail
readonly PKGCTL_TERM_SPINNER_DOTS=Dots
export PKGCTL_TERM_SPINNER_DOTS
readonly PKGCTL_TERM_SPINNER_DOTS12=Dots12
export PKGCTL_TERM_SPINNER_DOTS12
readonly PKGCTL_TERM_SPINNER_LINE=Line
export PKGCTL_TERM_SPINNER_LINE
readonly PKGCTL_TERM_SPINNER_SIMPLE_DOTS_SCROLLING=SimpleDotsScrolling
export PKGCTL_TERM_SPINNER_SIMPLE_DOTS_SCROLLING
readonly PKGCTL_TERM_SPINNER_TRIANGLE=Triangle
export PKGCTL_TERM_SPINNER_TRIANGLE
readonly PKGCTL_TERM_SPINNER_RANDOM=Random
export PKGCTL_TERM_SPINNER_RANDOM
readonly PKGCTL_TERM_SPINNER_TYPES=(
"${PKGCTL_TERM_SPINNER_DOTS}"
"${PKGCTL_TERM_SPINNER_DOTS12}"
"${PKGCTL_TERM_SPINNER_LINE}"
"${PKGCTL_TERM_SPINNER_SIMPLE_DOTS_SCROLLING}"
"${PKGCTL_TERM_SPINNER_TRIANGLE}"
)
export PKGCTL_TERM_SPINNER_TYPES
term_cursor_hide() {
tput civis >&2
}
term_cursor_show() {
tput cnorm >&2
}
term_cursor_up() {
tput cuu1
}
term_carriage_return() {
tput cr
}
term_erase_line() {
tput el
}
term_erase_lines() {
local lines=$1
local cursor_up erase_line
cursor_up=$(term_cursor_up)
erase_line="$(term_carriage_return)$(term_erase_line)"
local prefix=''
for _ in $(seq 1 "${lines}"); do
printf '%s' "${prefix}${erase_line}"
prefix="${cursor_up}"
done
}
_pkgctl_spinner_type=${PKGCTL_TERM_SPINNER_RANDOM}
term_spinner_set_type() {
_pkgctl_spinner_type=$1
}
# takes a status directory that can be used to dynamically update the spinner
# by writing to the `status` file inside that directory atomically.
# replace the placeholder %spinner% with the currently configured spinner type
term_spinner_start() {
local status_dir=$1
local parent_pid=$$
(
local spinner_type=${_pkgctl_spinner_type}
local spinner_offset=0
local frame_buffer=''
local spinner status_message line
local status_file="${status_dir}/status"
local next_file="${status_dir}/next"
local drawn_file="${status_dir}/drawn"
# assign random spinner type
if [[ ${spinner_type} == "${PKGCTL_TERM_SPINNER_RANDOM}" ]]; then
spinner_type=${PKGCTL_TERM_SPINNER_TYPES[$((RANDOM % ${#PKGCTL_TERM_SPINNER_TYPES[@]}))]}
fi
# select spinner based on the named type
case "${spinner_type}" in
"${PKGCTL_TERM_SPINNER_DOTS}")
spinner=("⠋" "⠙" "⠹" "⠸" "⠼" "⠴" "⠦" "⠧" "⠇" "⠏")
update_interval=0.08
;;
"${PKGCTL_TERM_SPINNER_DOTS12}")
spinner=("⢀⠀" "⡀⠀" "⠄⠀" "⢂⠀" "⡂⠀" "⠅⠀" "⢃⠀" "⡃⠀" "⠍⠀" "⢋⠀" "⡋⠀" "⠍⠁" "⢋⠁" "⡋⠁" "⠍⠉" "⠋⠉" "⠋⠉" "⠉⠙" "⠉⠙" "⠉⠩" "⠈⢙" "⠈⡙" "⢈⠩" "⡀⢙" "⠄⡙" "⢂⠩" "⡂⢘" "⠅⡘" "⢃⠨" "⡃⢐" "⠍⡐" "⢋⠠" "⡋⢀" "⠍⡁" "⢋⠁" "⡋⠁" "⠍⠉" "⠋⠉" "⠋⠉" "⠉⠙" "⠉⠙" "⠉⠩" "⠈⢙" "⠈⡙" "⠈⠩" "⠀⢙" "⠀⡙" "⠀⠩" "⠀⢘" "⠀⡘" "⠀⠨" "⠀⢐" "⠀⡐" "⠀⠠" "⠀⢀" "⠀⡀")
update_interval=0.08
;;
"${PKGCTL_TERM_SPINNER_LINE}")
spinner=("⎯" "\\" "|" "/")
update_interval=0.13
;;
"${PKGCTL_TERM_SPINNER_SIMPLE_DOTS_SCROLLING}")
spinner=(". " ".. " "..." " .." " ." " ")
update_interval=0.2
;;
"${PKGCTL_TERM_SPINNER_TRIANGLE}")
spinner=("◢" "◣" "◤" "◥")
update_interval=0.05
;;
esac
# hide the cursor while spinning
term_cursor_hide
# run the spinner as long as the parent process didn't terminate
while ps -p "${parent_pid}" &>/dev/null; do
# cache the new status template if it exists
if mv "${status_file}" "${next_file}" &>/dev/null; then
status_message="$(cat "$next_file")"
elif [[ -z "${status_message}" ]]; then
# wait until we either have a new or cached status
sleep 0.05
fi
# fill the frame buffer with the current status
local prefix=''
while IFS= read -r line; do
# replace spinner placeholder
line=${line//%spinner%/${spinner[spinner_offset%${#spinner[@]}]}}
# append the current line to the frame buffer
frame_buffer+="${prefix}${line}"
prefix=$'\n'
done <<< "${status_message}"
# print current frame buffer
echo -n "${frame_buffer}" >&2
mv "${next_file}" "${drawn_file}" &>/dev/null ||:
# setup next frame buffer to clear current content
frame_buffer=$(term_erase_lines "$(awk 'END {print NR}' <<< "${status_message}")")
# advance the spinner animation offset
(( ++spinner_offset ))
# sleep for the spinner update interval
sleep "${update_interval}"
done
)&
_pkgctl_spinner_pid=$!
disown
}
term_spinner_stop() {
local status_dir=$1
local frame_buffer status_file
# kill the spinner process
if ! kill "${_pkgctl_spinner_pid}" > /dev/null 2>&1; then
return 1
fi
unset _pkgctl_spinner_pid
# acquire last drawn status
status_file="${status_dir}/drawn"
if [[ ! -f ${status_file} ]]; then
return 0
fi
# clear terminal based on last status line
frame_buffer=$(term_erase_lines "$(awk 'END {print NR}' < "${status_file}")")
echo -n "${frame_buffer}" >&2
# show the cursor after stopping the spinner
term_cursor_show
}
prompt() {
local message=$1
local answer
read -r -p "${message} (y/N) " answer
case "${answer}" in
y|Y|yes|Yes|YES)
true
;;
*)
false
;;
esac
}

View File

@@ -1,11 +0,0 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
:
# shellcheck disable=2034
DEVTOOLS_VALID_BUILD_INSTALL=(
none
auto
all
)

View File

@@ -1,10 +0,0 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
# shellcheck disable=2034
DEVTOOLS_VALID_INSPECT_MODES=(
never
always
failure
)

View File

@@ -4,7 +4,7 @@
:
# shellcheck disable=2034
DEVTOOLS_VALID_REPOS=(
_repos=(
core core-staging core-testing
extra extra-staging extra-testing
multilib multilib-staging multilib-testing
@@ -13,7 +13,7 @@ DEVTOOLS_VALID_REPOS=(
)
# shellcheck disable=2034
DEVTOOLS_VALID_BUILDREPOS=(
_build_repos=(
core-staging core-testing
extra extra-staging extra-testing
multilib multilib-staging multilib-testing

View File

@@ -1,11 +0,0 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
:
# shellcheck disable=2034
valid_search_output_format=(
pretty
plain
json
)

View File

@@ -4,18 +4,13 @@
:
# shellcheck disable=2034
DEVTOOLS_VALID_BINARY_ARCHES=(
_arch=(
x86_64
)
# shellcheck disable=2034
DEVTOOLS_VALID_ARCHES=(
"${DEVTOOLS_VALID_BINARY_ARCHES[@]}"
any
)
# shellcheck disable=2034
DEVTOOLS_VALID_TAGS=(
_tags=(
core-x86_64 core-any
core-staging-x86_64 core-staging-any
core-testing-x86_64 core-testing-any

View File

@@ -1,75 +0,0 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_VERSION_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_VERSION_SH=1
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
set -e
pkgctl_version_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [COMMAND] [OPTIONS]
Check and manage package versions against upstream.
COMMANDS
check Compares local package versions against upstream
setup Automatically detect and setup a basic nvchecker config
upgrade Adjust the PKGBUILD to match the latest upstream version
OPTIONS
-h, --help Show this help text
EXAMPLES
$ ${COMMAND} check libfoo linux libbar
$ ${COMMAND} setup libfoo
_EOF_
}
pkgctl_version() {
if (( $# < 1 )); then
pkgctl_version_usage
exit 0
fi
while (( $# )); do
case $1 in
-h|--help)
pkgctl_version_usage
exit 0
;;
check)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/version/check.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/version/check.sh
pkgctl_version_check "$@"
exit $?
;;
upgrade)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/version/upgrade.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/version/upgrade.sh
pkgctl_version_upgrade "$@"
exit $?
;;
setup)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/version/setup.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/version/setup.sh
pkgctl_version_setup "$@"
exit 0
;;
*)
die "invalid argument: %s" "$1"
;;
esac
done
}

View File

@@ -1,347 +0,0 @@
#!/bin/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
[[ -z ${DEVTOOLS_INCLUDE_VERSION_CHECK_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_VERSION_CHECK_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/util/term.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/term.sh
source /usr/share/makepkg/util/message.sh
set -eo pipefail
readonly PKGCTL_VERSION_CHECK_EXIT_UP_TO_DATE=0
export PKGCTL_VERSION_CHECK_EXIT_UP_TO_DATE
readonly PKGCTL_VERSION_CHECK_EXIT_OUT_OF_DATE=2
export PKGCTL_VERSION_CHECK_EXIT_OUT_OF_DATE
readonly PKGCTL_VERSION_CHECK_EXIT_FAILURE=3
export PKGCTL_VERSION_CHECK_EXIT_FAILURE
pkgctl_version_check_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS] [PKGBASE]...
Compares the versions of packages in the local packaging repository against
their latest upstream versions.
Upon execution, it generates a grouped list that provides detailed insights
into each package's status. For each package, it displays the current local
version alongside the latest version available upstream.
Outputs a summary of up-to-date packages, out-of-date packages, and any
check failures.
OPTIONS
-v, --verbose Display results including up-to-date versions
-h, --help Show this help text
EXAMPLES
$ ${COMMAND} neovim vim
_EOF_
}
pkgctl_version_check() {
local pkgbases=()
local verbose=0
local path status_file path pkgbase upstream_version result
local up_to_date=()
local out_of_date=()
local failure=()
local current_item=0
local section_separator=''
local exit_code=${PKGCTL_VERSION_CHECK_EXIT_UP_TO_DATE}
while (( $# )); do
case $1 in
-h|--help)
pkgctl_version_check_usage
exit 0
;;
-v|--verbose)
verbose=1
shift
;;
--)
shift
break
;;
-*)
die "invalid argument: %s" "$1"
;;
*)
pkgbases=("$@")
break
;;
esac
done
if ! command -v nvchecker &>/dev/null; then
die "The \"$_DEVTOOLS_COMMAND\" command requires 'nvchecker'"
fi
# Check if used without pkgbases in a packaging directory
if (( ${#pkgbases[@]} == 0 )); then
if [[ -f PKGBUILD ]]; then
pkgbases=(".")
else
pkgctl_version_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
# start a terminal spinner as checking versions takes time
status_dir=$(mktemp --tmpdir="${WORKDIR}" --directory pkgctl-version-check-spinner.XXXXXXXXXX)
term_spinner_start "${status_dir}"
for path in "${pkgbases[@]}"; do
# skip paths that are not directories
if [[ ! -d "${path}" ]]; then
continue
fi
pushd "${path}" >/dev/null
# update the current terminal spinner status
(( ++current_item ))
pkgctl_version_check_spinner \
"${status_dir}" \
"${#up_to_date[@]}" \
"${#out_of_date[@]}" \
"${#failure[@]}" \
"${current_item}" \
"${#pkgbases[@]}"
if [[ ! -f "PKGBUILD" ]]; then
result="${BOLD}${path}${ALL_OFF}: no PKGBUILD found"
failure+=("${result}")
popd >/dev/null
continue
fi
# reset common PKGBUILD variables
unset pkgbase pkgname arch source pkgver pkgrel validpgpkeys
# shellcheck source=contrib/makepkg/PKGBUILD.proto
. ./PKGBUILD
pkgbase=${pkgbase:-$pkgname}
if ! result=$(get_upstream_version); then
result="${BOLD}${pkgbase}${ALL_OFF}: ${result}"
failure+=("${result}")
popd >/dev/null
continue
fi
upstream_version=${result}
if ! result=$(vercmp "${upstream_version}" "${pkgver}"); then
result="${BOLD}${pkgbase}${ALL_OFF}: failed to compare version ${upstream_version} against ${pkgver}"
failure+=("${result}")
popd >/dev/null
continue
fi
if (( result == 0 )); then
result="${BOLD}${pkgbase}${ALL_OFF}: current version ${PURPLE}${pkgver}${ALL_OFF} is latest"
up_to_date+=("${result}")
elif (( result < 0 )); then
result="${BOLD}${pkgbase}${ALL_OFF}: current version ${PURPLE}${pkgver}${ALL_OFF} is newer than ${DARK_GREEN}${upstream_version}${ALL_OFF}"
up_to_date+=("${result}")
elif (( result > 0 )); then
result="${BOLD}${pkgbase}${ALL_OFF}: upgrade from version ${PURPLE}${pkgver}${ALL_OFF} to ${DARK_GREEN}${upstream_version}${ALL_OFF}"
out_of_date+=("${result}")
fi
popd >/dev/null
done
# stop the terminal spinner after all checks
term_spinner_stop "${status_dir}"
if (( verbose )) && (( ${#up_to_date[@]} > 0 )); then
printf "%sUp-to-date%s\n" "${section_separator}${BOLD}${UNDERLINE}" "${ALL_OFF}"
section_separator=$'\n'
for result in "${up_to_date[@]}"; do
msg_success " ${result}"
done
fi
if (( ${#failure[@]} > 0 )); then
exit_code=${PKGCTL_VERSION_CHECK_EXIT_FAILURE}
printf "%sFailure%s\n" "${section_separator}${BOLD}${UNDERLINE}" "${ALL_OFF}"
section_separator=$'\n'
for result in "${failure[@]}"; do
msg_error " ${result}"
done
fi
if (( ${#out_of_date[@]} > 0 )); then
exit_code=${PKGCTL_VERSION_CHECK_EXIT_OUT_OF_DATE}
printf "%sOut-of-date%s\n" "${section_separator}${BOLD}${UNDERLINE}" "${ALL_OFF}"
section_separator=$'\n'
for result in "${out_of_date[@]}"; do
msg_warn " ${result}"
done
fi
# Show summary when processing multiple packages
if (( ${#pkgbases[@]} > 1 )); then
printf '%s' "${section_separator}"
pkgctl_version_check_summary \
"${#up_to_date[@]}" \
"${#out_of_date[@]}" \
"${#failure[@]}"
fi
# return status based on results
return "${exit_code}"
}
get_upstream_version() {
local config=.nvchecker.toml
local output errors upstream_version
local output
local opts=()
local keyfile="${XDG_CONFIG_HOME:-${HOME}/.config}/nvchecker/keyfile.toml"
# check nvchecker config file
if ! errors=$(nvchecker_check_config "${config}"); then
printf "%s" "${errors}"
return 1
fi
# populate keyfile to nvchecker opts
if [[ -f ${keyfile} ]]; then
opts+=(--keyfile "${keyfile}")
fi
if ! output=$(GIT_TERMINAL_PROMPT=0 nvchecker --file "${config}" --logger json "${opts[@]}" 2>&1 | \
jq --raw-output 'select(.level != "debug")'); then
printf "failed to run nvchecker: %s" "${output}"
return 1
fi
if ! errors=$(nvchecker_check_error "${output}"); then
printf "%s" "${errors}"
return 1
fi
if ! upstream_version=$(jq --raw-output --exit-status '.version' <<< "${output}"); then
printf "failed to select version from result"
return 1
fi
printf "%s" "${upstream_version}"
return 0
}
nvchecker_check_config() {
local config=$1
local restricted_properties=(keyfile httptoken token)
local property
# check if the config file exists
if [[ ! -f ${config} ]]; then
printf "configuration file not found: %s" "${config}"
return 1
fi
# check if config contains any restricted properties like secrets
for property in "${restricted_properties[@]}"; do
if grep --max-count=1 --quiet "^${property}" < "${config}"; then
printf "restricted property in %s: %s" "${config}" "${property}"
return 1
fi
done
# check if the config contains a pkgbase section
if [[ -n ${pkgbase} ]] && ! grep --max-count=1 --extended-regexp --quiet "^\\[\"?${pkgbase}\"?\\]" < "${config}"; then
printf "missing pkgbase section in %s: %s" "${config}" "${pkgbase}"
return 1
fi
# check if the config contains any section other than pkgbase
if [[ -n ${pkgbase} ]] && property=$(grep --max-count=1 --perl-regexp "^\\[(?!\"?${pkgbase}\"?\\]).+\\]" < "${config}"); then
printf "non-pkgbase section not supported in %s: %s" "${config}" "${property}"
return 1
fi
}
nvchecker_check_error() {
local result=$1
local errors
if ! errors=$(jq --raw-output --exit-status \
'select(.level == "error") | "\(.event)" + if .error then ": \(.error)" else "" end' \
<<< "${result}"); then
return 0
fi
mapfile -t errors <<< "${errors}"
printf "%s\n" "${errors[@]}"
return 1
}
pkgctl_version_check_summary() {
local up_to_date_count=$1
local out_of_date_count=$2
local failure_count=$3
# print nothing if all stats are zero
if (( up_to_date_count == 0 )) && \
(( out_of_date_count == 0 )) && \
(( failure_count == 0 )); then
return 0
fi
# print summary for all none zero stats
printf "%sSummary%s\n" "${BOLD}${UNDERLINE}" "${ALL_OFF}"
if (( up_to_date_count > 0 )); then
msg_success " Up-to-date: ${BOLD}${up_to_date_count}${ALL_OFF}" 2>&1
fi
if (( failure_count > 0 )); then
msg_error " Failure: ${BOLD}${failure_count}${ALL_OFF}" 2>&1
fi
if (( out_of_date_count > 0 )); then
msg_warn " Out-of-date: ${BOLD}${out_of_date_count}${ALL_OFF}" 2>&1
fi
}
pkgctl_version_check_spinner() {
local status_dir=$1
local up_to_date_count=$2
local out_of_date_count=$3
local failure_count=$4
local current=$5
local total=$6
local percentage=$(( 100 * current / total ))
local tmp_file="${status_dir}/tmp"
local status_file="${status_dir}/status"
# print the current summary
pkgctl_version_check_summary \
"${up_to_date_count}" \
"${out_of_date_count}" \
"${failure_count}" > "${tmp_file}"
# print the progress status
printf "📡 Checking: %s/%s [%s] %%spinner%%" \
"${BOLD}${current}" "${total}" "${percentage}%${ALL_OFF}" \
>> "${tmp_file}"
# swap the status file
mv "${tmp_file}" "${status_file}"
}

View File

@@ -1,528 +0,0 @@
#!/bin/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
[[ -z ${DEVTOOLS_INCLUDE_VERSION_SETUP_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_VERSION_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/version/check.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/version/check.sh
source /usr/share/makepkg/util/message.sh
source /usr/share/makepkg/util/source.sh
set -eo pipefail
pkgctl_version_setup_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS] [PKGBASE]...
Automate the creation of a basic nvchecker configuration file by
analyzing the source 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 nvchecker configuration
--prefer-platform-api Prefer platform specific GitHub/GitLab API for complex cases
--url URL Derive check target from URL instead of source array
--no-check Do not run version check after setup
-h, --help Show this help text
EXAMPLES
$ ${COMMAND} neovim vim
_EOF_
}
pkgctl_version_setup() {
local pkgbases=()
local override_url=
local run_check=1
local force=0
local prefer_platform_api=0
local path ret
local checks=()
while (( $# )); do
case $1 in
-h|--help)
pkgctl_version_setup_usage
exit 0
;;
-f|--force)
force=1
shift
;;
--prefer-platform-api)
prefer_platform_api=1
shift
;;
--url)
(( $# <= 1 )) && die "missing argument for %s" "$1"
override_url=$2
shift 2
;;
--no-check)
run_check=0
shift
;;
--)
shift
break
;;
-*)
die "invalid argument: %s" "$1"
;;
*)
pkgbases=("$@")
break
;;
esac
done
# Check if used without pkgbases in a packaging directory
if (( ${#pkgbases[@]} == 0 )); then
if [[ -f PKGBUILD ]]; then
pkgbases=(".")
else
pkgctl_version_setup_usage
exit 1
fi
fi
ret=0
for path in "${pkgbases[@]}"; do
# skip paths that are not directories
if [[ ! -d "${path}" ]]; then
continue
fi
pushd "${path}" >/dev/null
if nvchecker_setup "${path}" "${force}" "${prefer_platform_api}" "${override_url}"; then
checks+=("${path}")
else
ret=1
fi
popd >/dev/null
done
# run checks on the setup targets
if (( run_check )) && (( ${#checks[@]} >= 1 )); then
echo
pkgctl_version_check --verbose "${checks[@]}" || true
fi
return $ret
}
nvchecker_setup() {
local path=$1
local force=$2
local prefer_platform_api=$3
local override_url=$4
local pkgbase pkgname source source_url proto domain url_parts section body
if [[ ! -f PKGBUILD ]]; then
msg_error "${BOLD}${path}:${ALL_OFF} no PKGBUILD found"
return 1
fi
unset body pkgbase pkgname source url
# 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}
# try to guess from url as last try
if [[ -n ${url} ]]; then
source+=("${url}")
fi
# handle overwrite of existing config
if [[ -f .nvchecker.toml ]] && (( ! force )); then
msg_warn "${BOLD}${pkgbase}:${ALL_OFF} nvchecker already configured"
return 1
fi
# override the source array with a passed URL
if [[ -n ${override_url} ]]; then
source=("${override_url}")
fi
# skip empty source array
if (( ${#source[@]} == 0 )); then
msg_error "${BOLD}${pkgbase}:${ALL_OFF} PKGBUILD has no source array"
return 1
fi
for source_url in "${source[@]}"; do
# Strips out filename::http for example
source_url=$(get_url "${source_url}")
# discard query fragments
source_url=${source_url%\?*}
source_url=${source_url%#*}
# skip patches
if [[ ${source_url} == *.patch ]]; then
continue
fi
# skip signatures
if [[ ${source_url} == *.asc ]] || [[ ${source_url} == *.sig ]]; then
continue
fi
# skip local files
if [[ ${source_url} != *://* ]]; then
continue
fi
# split URL segments while avoiding empty element after protocol and newline at the end
mapfile -td / url_parts <<< "${source_url/:\/\//\/}/"
unset "url_parts[-1]"
# extract protocol and domain to select the configuration type
proto=${url_parts[0]}
domain=${url_parts[1]}
case "${domain}" in
gitlab.*)
if (( prefer_platform_api )); then
body=$(nvchecker_setup_gitlab "${url_parts[@]}")
else
body=$(nvchecker_setup_git "${url_parts[@]}")
fi
break
;;
github.com)
if (( prefer_platform_api )); then
body=$(nvchecker_setup_github "${url_parts[@]}")
else
body=$(nvchecker_setup_git "${url_parts[@]}")
fi
break
;;
codeberg.org)
body=$(nvchecker_setup_git "${url_parts[@]}")
break
;;
pypi.org|pypi.io|files.pythonhosted.org)
body=$(nvchecker_setup_pypi "${url_parts[@]}")
break
;;
hackage.haskell.org)
body=$(nvchecker_setup_hackage "${url_parts[@]}")
break
;;
registry.npmjs.org|npmjs.com|www.npmjs.com)
body=$(nvchecker_setup_npm "${url_parts[@]}")
break
;;
rubygems.org)
body=$(nvchecker_setup_rubygems "${url_parts[@]}")
break
;;
*.cpan.org|*.mcpan.org|*.metacpan.org)
body=$(nvchecker_setup_cpan "${url_parts[@]}")
break
;;
crates.io|*.crates.io)
body=$(nvchecker_setup_crates_io "${url_parts[@]}")
break
;;
*)
if [[ ${proto} == git ]] || [[ ${proto} == git+https ]]; then
body=$(nvchecker_setup_git "${url_parts[@]}")
fi
;;
esac
done
if [[ -z "${body}" ]]; then
msg_error "${BOLD}${pkgbase}:${ALL_OFF} unable to automatically setup nvchecker"
return 1
fi
# escape the section if it contains toml subsection chars
section="${pkgbase}"
if [[ ${section} == *.* ]]; then
section="\"${section}\""
fi
msg_success "${BOLD}${pkgbase}:${ALL_OFF} successfully configured nvchecker"
cat > .nvchecker.toml << EOF
[${section}]
${body}
EOF
}
get_git_url_from_parts() {
local url_parts=("$@")
local proto=${url_parts[0]#*+}
local domain=${url_parts[1]}
local url
url="${proto}://$(join_by / "${url_parts[@]:1}")"
case "${domain}" in
gitlab.*)
url=${url%/-/*/*}
[[ ${url} != *.git ]] && url+=.git
;;
github.com|codeberg.org)
url="${proto}://$(join_by / "${url_parts[@]:1:3}")"
[[ ${url} != *.git ]] && url+=.git
;;
esac
printf '%s' "${url}"
}
# PyPI
#
# As Arch python packages don't necessarily match the pypi name, when the
# provided source url comes from pypi.io or pypi.org try to extract the package
# name from the (predictable) tarball download url for example:
#
# https://pypi.io/packages/source/p/pyflakes/pyflakes-3.1.0.tar.gz
# https://pypi.io/packages/source/p/pyflakes
# https://pypi.org/packages/source/b/bleach
# https://files.pythonhosted.org/packages/source/p/pyflakes
# https://pypi.org/project/SQLAlchemy/
nvchecker_setup_pypi() {
local url_parts=("$@")
local pypi
if [[ ${url_parts[2]} == packages ]]; then
pypi=${url_parts[5]}
elif [[ ${url_parts[2]} == project ]]; then
pypi=${url_parts[3]}
else
return 1
fi
cat << EOF
source = "pypi"
pypi = "${pypi}"
EOF
}
# Git
#
# Set up a generic Git source, while removing the proto specific part from makepkg
#
# git+https://github.com/prometheus/prometheus.git
# https://git.foobar.com/some/path/group/project.git
# https://gitlab.com/sub/group/project/-/archive/8.0.0/packages-8.0.0.tar.gz
nvchecker_setup_git() {
local url_parts=("$@")
local url
url=$(get_git_url_from_parts "${url_parts[@]}")
cat << EOF
source = "git"
git = "${url}"
EOF
# best effort check if the tags are prefixed with v
if git_tags_have_version_prefix "${url}"; then
echo 'prefix = "v"'
fi
}
git_tags_have_version_prefix() {
local url=$1
# best effort check if the tags are prefixed with v
if ! grep --max-count=1 --quiet --extended-regex 'refs/tags/v[0-9]+[\.0-9]*$' \
<(GIT_TERMINAL_PROMPT=0 git ls-remote --quiet --tags "${url}" 2>/dev/null); then
return 1
fi
return 0
}
# Github
#
# We want to know the $org/$project name from the url
#
# https://github.com/prometheus/prometheus/archive/v2.49.1.tar.gz
nvchecker_setup_github() {
local url_parts=("$@")
local url project
if ! url=$(get_git_url_from_parts "${url_parts[@]}"); then
return 1
fi
project=${url#*://*/}
project=${project%.git}
cat << EOF
source = "github"
github = "${project}"
use_max_tag = true
EOF
# best effort check if the tags are prefixed with v
if git_tags_have_version_prefix "${url}"; then
echo 'prefix = "v"'
fi
}
# GitLab
#
# We want to know the $org/$project name from the url
#
# git+https://gitlab.com/inkscape/inkscape.git#tag=091e20ef0f204eb40ecde54436e1ef934a03d894
nvchecker_setup_gitlab() {
local url_parts=("$@")
local url project host
if ! url=$(get_git_url_from_parts "${url_parts[@]}"); then
return 1
fi
project=${url#*://*/}
project=${project%.git}
cat << EOF
source = "gitlab"
gitlab = "${project}"
EOF
host=${url#*://}
host=${host%%/*}
if [[ ${host} != gitlab.com ]]; then
echo "host = \"${host}\""
fi
echo "use_max_tag = true"
# best effort check if the tags are prefixed with v
if git_tags_have_version_prefix "${url}"; then
echo 'prefix = "v"'
fi
}
# Hackage
#
# We want to know the project name
#
# https://hackage.haskell.org/package/xmonad
# https://hackage.haskell.org/package/xmonad-0.18.0/xmonad-0.18.0.tar.gz
# https://hackage.haskell.org/packages/archive/digits/0.3.1/digits-0.3.1.tar.gz
nvchecker_setup_hackage() {
local url_parts=("$@")
local hackage
if [[ ${url_parts[2]} == packages ]]; then
hackage=${url_parts[4]}
elif [[ ${url_parts[2]} == package ]] && (( ${#url_parts[@]} == 4 )); then
hackage=${url_parts[3]}
elif [[ ${url_parts[2]} == package ]] && (( ${#url_parts[@]} >= 5 )); then
hackage=${url_parts[3]%-*}
else
return 1
fi
cat << EOF
source = "hackage"
hackage = "${hackage}"
EOF
}
# NPM
#
# We want to know the project name
#
# https://registry.npmjs.org/eslint_d/-/eslint_d-12.1.0.tgz
# https://www.npmjs.com/package/node-gyp
nvchecker_setup_npm() {
local url_parts=("$@")
local npm
if [[ ${url_parts[1]} == registry.npmjs.org ]]; then
npm=${url_parts[2]}
elif [[ ${url_parts[2]} == package ]] && (( ${#url_parts[@]} == 4 )); then
npm=${url_parts[3]}
else
return 1
fi
cat << EOF
source = "npm"
npm = "${npm}"
EOF
}
# RubyGems
#
# We want to know the project name
#
# https://rubygems.org/downloads/polyglot-0.3.5.gem
# https://rubygems.org/gems/diff-lcs
nvchecker_setup_rubygems() {
local url_parts=("$@")
local gem
if [[ ${url_parts[2]} == downloads ]]; then
gem=${url_parts[-1]%-*}
elif [[ ${url_parts[2]} == gems ]]; then
gem=${url_parts[3]}
else
return 1
fi
cat << EOF
source = "gems"
gems = "${gem}"
EOF
}
# CPAN
#
# We want to know the project name
#
# source = https://search.cpan.org/CPAN/authors/id/C/CO/COSIMO/Locale-PO-1.2.3.tar.gz
nvchecker_setup_cpan() {
local url_parts=("$@")
local cpan=${url_parts[-1]}
cpan=${cpan%-*}
cat << EOF
source = "cpan"
cpan = "${cpan}"
EOF
}
# crates.io
#
# We want to know the crate name
#
# https://crates.io/api/v1/crates/${pkgname}/${pkgver}/download
# https://static.crates.io/crates/${pkgname}/$pkgname-$pkgver.crate
# https://crates.io/crates/git-smash
nvchecker_setup_crates_io() {
local url_parts=("$@")
local crate
if [[ ${url_parts[2]} == crates ]]; then
crate=${url_parts[3]}
elif [[ ${url_parts[4]} == crates ]]; then
crate=${url_parts[5]}
else
return 1
fi
for i in "${!url_parts[@]}"; do
if [[ ${url_parts[i]} == crates ]]; then
crate=${url_parts[(( i + 1 ))]}
fi
done
cat << EOF
source = "cratesio"
cratesio = "${crate}"
EOF
}

View File

@@ -1,286 +0,0 @@
#!/bin/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
[[ -z ${DEVTOOLS_INCLUDE_VERSION_UPGRADE_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_VERSION_UPGRADE_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/version/check.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/version/check.sh
# shellcheck source=src/lib/util/pkgbuild.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/pkgbuild.sh
# shellcheck source=src/lib/util/term.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/term.sh
source /usr/share/makepkg/util/message.sh
set -e
pkgctl_version_upgrade_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS] [PKGBASE]...
Streamlines the process of keeping PKGBUILD files up-to-date with the latest
upstream versions.
Upon execution, it automatically adjusts the PKGBUILD file, ensuring that the
pkgver field is set to match the latest version available from the upstream
source. In addition to updating the pkgver, this command also resets the pkgrel
to 1 and updates checksums.
Outputs a summary of upgraded packages, up-to-date packages, and any check
failures.
OPTIONS
--no-update-checksums Disable computation and update of the checksums
-v, --verbose Display results including up-to-date versions
-h, --help Show this help text
EXAMPLES
$ ${COMMAND} neovim vim
_EOF_
}
pkgctl_version_upgrade() {
local path upstream_version result
local pkgbases=()
local verbose=0
local exit_code=0
local current_item=0
local update_checksums=1
while (( $# )); do
case $1 in
-h|--help)
pkgctl_version_upgrade_usage
exit 0
;;
--no-update-checksums)
update_checksums=0
shift
;;
-v|--verbose)
verbose=1
shift
;;
--)
shift
break
;;
-*)
die "invalid argument: %s" "$1"
;;
*)
pkgbases=("$@")
break
;;
esac
done
if ! command -v nvchecker &>/dev/null; then
die "The \"$_DEVTOOLS_COMMAND\" command requires 'nvchecker'"
fi
# Check if used without pkgbases in a packaging directory
if (( ${#pkgbases[@]} == 0 )); then
if [[ -f PKGBUILD ]]; then
pkgbases=(".")
else
pkgctl_version_upgrade_usage
exit 1
fi
fi
# enable verbose mode when we only have a single item to check
if (( ${#pkgbases[@]} == 1 )); then
verbose=1
fi
# start a terminal spinner as checking versions takes time
status_dir=$(mktemp --tmpdir="${WORKDIR}" --directory pkgctl-version-check-spinner.XXXXXXXXXX)
term_spinner_start "${status_dir}"
for path in "${pkgbases[@]}"; do
# skip paths that aren't directories
if [[ ! -d "${path}" ]]; then
continue
fi
pushd "${path}" >/dev/null
(( ++current_item ))
if [[ ! -f "PKGBUILD" ]]; then
result="${BOLD}${path}${ALL_OFF}: no PKGBUILD found"
failure+=("${result}")
popd >/dev/null
continue
fi
# reset common PKGBUILD variables
unset pkgbase pkgname arch source pkgver pkgrel validpgpkeys
# shellcheck source=contrib/makepkg/PKGBUILD.proto
. ./PKGBUILD
pkgbase=${pkgbase:-$pkgname}
# update the current terminal spinner status
pkgctl_version_upgrade_spinner \
"${status_dir}" \
"${#up_to_date[@]}" \
"${#out_of_date[@]}" \
"${#failure[@]}" \
"${current_item}" \
"${#pkgbases[@]}" \
"${pkgbase}" \
"query latest version"
if ! result=$(get_upstream_version); then
result="${BOLD}${pkgbase}${ALL_OFF}: ${result}"
failure+=("${result}")
popd >/dev/null
continue
fi
upstream_version=${result}
if ! result=$(vercmp "${upstream_version}" "${pkgver}"); then
result="${BOLD}${pkgbase}${ALL_OFF}: failed to compare version ${upstream_version} against ${pkgver}"
failure+=("${result}")
popd >/dev/null
continue
fi
if (( result == 0 )); then
result="${BOLD}${pkgbase}${ALL_OFF}: current version ${PURPLE}${pkgver}${ALL_OFF} is latest"
up_to_date+=("${result}")
elif (( result < 0 )); then
result="${BOLD}${pkgbase}${ALL_OFF}: current version ${PURPLE}${pkgver}${ALL_OFF} is newer than ${DARK_GREEN}${upstream_version}${ALL_OFF}"
up_to_date+=("${result}")
elif (( result > 0 )); then
result="${BOLD}${pkgbase}${ALL_OFF}: upgraded from version ${PURPLE}${pkgver}${ALL_OFF} to ${DARK_GREEN}${upstream_version}${ALL_OFF}"
out_of_date+=("${result}")
# change the PKGBUILD
pkgbuild_set_pkgver "${upstream_version}"
pkgbuild_set_pkgrel 1
# download sources and update the checksums
if (( update_checksums )); then
pkgctl_version_upgrade_spinner \
"${status_dir}" \
"${#up_to_date[@]}" \
"${#out_of_date[@]}" \
"${#failure[@]}" \
"${current_item}" \
"${#pkgbases[@]}" \
"${pkgbase}" \
"updating checksums"
if ! result=$(pkgbuild_update_checksums /dev/null); then
result="${BOLD}${pkgbase}${ALL_OFF}: failed to update checksums for version ${DARK_GREEN}${upstream_version}${ALL_OFF}"
failure+=("${result}")
fi
fi
fi
popd >/dev/null
done
# stop the terminal spinner after all checks
term_spinner_stop "${status_dir}"
if (( verbose )) && (( ${#up_to_date[@]} > 0 )); then
printf "%sUp-to-date%s\n" "${section_separator}${BOLD}${UNDERLINE}" "${ALL_OFF}"
section_separator=$'\n'
for result in "${up_to_date[@]}"; do
msg_success " ${result}"
done
fi
if (( ${#failure[@]} > 0 )); then
exit_code=1
printf "%sFailure%s\n" "${section_separator}${BOLD}${UNDERLINE}" "${ALL_OFF}"
section_separator=$'\n'
for result in "${failure[@]}"; do
msg_error " ${result}"
done
fi
if (( ${#out_of_date[@]} > 0 )); then
printf "%sUpgraded%s\n" "${section_separator}${BOLD}${UNDERLINE}" "${ALL_OFF}"
section_separator=$'\n'
for result in "${out_of_date[@]}"; do
msg_warn " ${result}"
done
fi
# Show summary when processing multiple packages
if (( ${#pkgbases[@]} > 1 )); then
printf '%s' "${section_separator}"
pkgctl_version_upgrade_summary \
"${#up_to_date[@]}" \
"${#out_of_date[@]}" \
"${#failure[@]}"
fi
# return status based on results
return "${exit_code}"
}
pkgctl_version_upgrade_summary() {
local up_to_date_count=$1
local out_of_date_count=$2
local failure_count=$3
# print nothing if all stats are zero
if (( up_to_date_count == 0 )) && \
(( out_of_date_count == 0 )) && \
(( failure_count == 0 )); then
return 0
fi
# print summary for all none zero stats
printf "%sSummary%s\n" "${BOLD}${UNDERLINE}" "${ALL_OFF}"
if (( up_to_date_count > 0 )); then
msg_success " Up-to-date: ${BOLD}${up_to_date_count}${ALL_OFF}" 2>&1
fi
if (( failure_count > 0 )); then
msg_error " Failure: ${BOLD}${failure_count}${ALL_OFF}" 2>&1
fi
if (( out_of_date_count > 0 )); then
msg_warn " Upgraded: ${BOLD}${out_of_date_count}${ALL_OFF}" 2>&1
fi
}
pkgctl_version_upgrade_spinner() {
local status_dir=$1
local up_to_date_count=$2
local out_of_date_count=$3
local failure_count=$4
local current=$5
local total=$6
local pkgbase=$7
local message=$8
local percentage=$(( 100 * current / total ))
local tmp_file="${status_dir}/tmp"
local status_file="${status_dir}/status"
# print the current summary
pkgctl_version_upgrade_summary \
"${up_to_date_count}" \
"${out_of_date_count}" \
"${failure_count}" > "${tmp_file}"
# print the progress status
printf "📡 %s: %s\n" \
"${pkgbase}" "${BOLD}${message}${ALL_OFF}" >> "${tmp_file}"
printf "⌛ Upgrading: %s/%s [%s] %%spinner%%" \
"${BOLD}${current}" "${total}" "${percentage}%${ALL_OFF}" \
>> "${tmp_file}"
# swap the status file
mv "${tmp_file}" "${status_file}"
}

View File

@@ -0,0 +1,47 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_VERSION_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_VERSION_SH=1
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
source /usr/share/makepkg/util/message.sh
set -e
pkgctl_version_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS]
Shows the current version information of pkgctl
OPTIONS
-h, --help Show this help text
_EOF_
}
pkgctl_version_print() {
cat <<- _EOF_
pkgctl @buildtoolver@
_EOF_
}
pkgctl_version() {
while (( $# )); do
case $1 in
-h|--help)
pkgctl_version_usage
exit 0
;;
*)
die "invalid argument: %s" "$1"
;;
esac
done
pkgctl_version_print
}

View File

@@ -8,12 +8,9 @@ _DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
# shellcheck source=src/lib/archroot.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/archroot.sh
# shellcheck source=src/lib/valid-inspect.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-inspect.sh
source /usr/share/makepkg/util/config.sh
source /usr/share/makepkg/util/util.sh
shopt -s nullglob
@@ -34,8 +31,6 @@ run_checkpkg=0
temp_chroot=0
tmp_opts="nosuid,nodev,size=50%,nr_inodes=2m"
inspect=never
bindmounts_ro=()
bindmounts_rw=()
@@ -81,7 +76,6 @@ usage() {
echo '-C Run checkpkg on the package'
echo '-T Build in a temporary directory'
echo '-U Run makepkg as a specified user'
echo '-x <when> Inspect chroot after build (never, always, failure)'
exit 1
}
@@ -149,7 +143,7 @@ install_packages() {
cp -- "${install_pkgs[@]}" "$copydir/root/"
arch-nspawn "$copydir" "${bindmounts_ro[@]}" "${bindmounts_rw[@]}" \
pacman -U --noconfirm --ask=4 -- "${pkgnames[@]/#//root/}"
bash -c 'yes y | pacman -U -- "$@"' -bash "${pkgnames[@]/#//root/}"
ret=$?
rm -- "${pkgnames[@]/#/$copydir/root/}"
@@ -286,7 +280,7 @@ move_products() {
}
# }}}
while getopts 'hcur:I:l:nCTD:d:U:x:' arg; do
while getopts 'hcur:I:l:nCTD:d:U:' arg; do
case "$arg" in
c) clean_first=1 ;;
D) bindmounts_ro+=("--bind-ro=$OPTARG") ;;
@@ -299,7 +293,6 @@ while getopts 'hcur:I:l:nCTD:d:U:x:' arg; do
C) run_checkpkg=1 ;;
T) temp_chroot=1; copy+="-$$" ;;
U) makepkg_user="$OPTARG" ;;
x) inspect="$OPTARG" ;;
h|*) usage ;;
esac
done
@@ -321,10 +314,6 @@ else
copydir="$chrootdir/$copy"
fi
if ! in_array "${inspect}" "${DEVTOOLS_VALID_INSPECT_MODES[@]}"; then
die "Invalid inspect mode: %s" "${inspect}"
fi
# Pass all arguments after -- right to makepkg
makepkg_args+=("${@:$OPTIND}")
@@ -379,16 +368,11 @@ download_sources
prepare_chroot
nspawn_build_args=(
--bind="${PWD//:/\\:}:/startdir"
--bind="${SRCDEST//:/\\:}:/srcdest"
--tmpfs="/tmp:${tmp_opts}"
"${bindmounts_ro[@]}"
"${bindmounts_rw[@]}"
)
if arch-nspawn "$copydir" \
"${nspawn_build_args[@]}" \
--bind="${PWD//:/\\:}:/startdir" \
--bind="${SRCDEST//:/\\:}:/srcdest" \
--tmpfs="/tmp:${tmp_opts}" \
"${bindmounts_ro[@]}" "${bindmounts_rw[@]}" \
/chrootbuild "${makepkg_args[@]}"
then
mapfile -t pkgnames < <(sudo -u "$makepkg_user" bash -c 'source PKGBUILD; printf "%s\n" "${pkgname[@]}"')
@@ -398,18 +382,6 @@ else
move_logfiles
fi
if [[ $inspect == always ]] || ( [[ $inspect == failure ]] && (( ret != 0 )) ); then
if (( ret == 0 )); then
msg "Build succeeded, inspecting %s" "$copydir"
else
error "Build failed, inspecting %s" "$copydir"
fi
arch-nspawn "$copydir" \
"${nspawn_build_args[@]}" \
--user=builduser \
--chdir=/build
fi
(( temp_chroot )) && delete_chroot "$copydir" "$copy"
if (( ret != 0 )); then

View File

@@ -22,7 +22,6 @@ declare -a buildenv buildopts installed installpkgs
archiveurl='https://archive.archlinux.org/packages'
buildroot=/var/lib/archbuild/reproducible
diffoscope=0
makepkg_options=()
chroot=$USER
[[ -n ${SUDO_USER:-} ]] && chroot=$SUDO_USER
@@ -117,7 +116,6 @@ For more details see https://reproducible-builds.org/
OPTIONS
-d Run diffoscope if the package is unreproducible
-n Do not run the check() function in the PKGBUILD
-c <dir> Set pacman cache
-M <file> Location of a makepkg config file
-l <chroot> The directory name to use as the chroot namespace
@@ -130,10 +128,9 @@ __EOF__
# save all args for check_root
orig_args=("$@")
while getopts 'dnM:c:l:h' arg; do
while getopts 'dM:c:l:h' arg; do
case "$arg" in
d) diffoscope=1 ;;
n) makepkg_options+=(--nocheck) ;;
M) archroot_args+=(-M "$OPTARG") ;;
c) cache_dirs+=("$OPTARG") ;;
l) chroot="$OPTARG" ;;
@@ -257,7 +254,7 @@ install -d -o "${SUDO_UID:-$UID}" -g "$(id -g "${SUDO_UID:-$UID}")" "${namespace
arch-nspawn "${namespace}/build" \
--bind="${PWD}:/startdir" \
--bind="${SRCDEST}:/srcdest" \
/chrootbuild -C --noconfirm --log --holdver --skipinteg "${makepkg_options[@]}"
/chrootbuild -C --noconfirm --log --holdver --skipinteg
ret=$?
if (( ${ret} == 0 )); then

View File

@@ -6,24 +6,15 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
# shellcheck source=src/lib/common.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
# shellcheck source=src/lib/util/makepkg.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/makepkg.sh
source /usr/share/makepkg/util/config.sh
# Deprecation warning
if [[ -z $_DEVTOOLS_COMMAND ]]; then
warning "${0##*/} is deprecated and will be removed. Use 'pkgctl build --offload' instead"
fi
# global defaults suitable for use by Arch staff
repo=extra
arch=x86_64
server=build.archlinux.org
rsyncopts=("${RSYNC_OPTS[@]}")
die() { printf "error: $1\n" "${@:2}"; exit 1; }
usage() {
cat <<- _EOF_
@@ -88,7 +79,7 @@ load_makepkg_config
# transferred, including local sources, install scripts, and changelogs.
export TEMPDIR=$(mktemp -d --tmpdir offload-build.XXXXXXXXXX)
export SRCPKGDEST=${TEMPDIR}
makepkg_source_package || die "unable to make source package"
makepkg --source || die "unable to make source package"
# Temporary cosmetic workaround makepkg if SRCDEST is set somewhere else
# but an empty src dir is created in PWD. Remove once fixed in makepkg.
@@ -100,14 +91,12 @@ mapfile -t files < <(
# shellcheck disable=SC2145
cat "$SRCPKGDEST"/*"$SRCEXT" |
ssh $server '
export TERM="'"${TERM}"'"
temp="${XDG_CACHE_HOME:-$HOME/.cache}/offload-build" &&
mkdir -p "$temp" &&
temp=$(mktemp -d -p "$temp") &&
cd "$temp" &&
{
bsdtar --strip-components 1 -xvf - &&
export LOGDEST="" &&
script -qefc "'"${archbuild_cmd[@]@Q}"'" /dev/null &&
printf "%s\n" "" "-> build complete" &&
printf "\t%s\n" "$temp"/*
@@ -117,29 +106,16 @@ mapfile -t files < <(
if [[ -f /usr/share/devtools/makepkg.conf.d/'"${repo}"'-'"${arch}"'.conf ]]; then
makepkg_config="/usr/share/devtools/makepkg.conf.d/'"${repo}"'-'"${arch}"'.conf"
fi &&
while read -r file; do
[[ -f "${file}" ]] && printf "%s\n" "${file}" ||:
done < <(makepkg --config <(cat "${makepkg_user_config}" "${makepkg_config}" 2>/dev/null) --packagelist) &&
makepkg --config <(cat "${makepkg_user_config}" "${makepkg_config}" 2>/dev/null) --packagelist &&
printf "%s\n" "${temp}/PKGBUILD"
find "${temp}" -name "*.log"
')
if (( ${#files[@]} )); then
msg 'Downloading files...'
rsync "${rsyncopts[@]}" "${files[@]/#/$server:}" "${TEMPDIR}/" || die
if is_globfile "${TEMPDIR}"/*.log; then
mv "${TEMPDIR}"/*.log "${LOGDEST:-${PWD}}/"
fi
# missing PKGBUILD download means the build failed
if [[ ! -f "${TEMPDIR}/PKGBUILD" ]]; then
error "Build failed, check logs in ${LOGDEST:-${PWD}}"
exit 1
fi
mv "${TEMPDIR}/PKGBUILD" "${PWD}/"
printf '%s\n' '' '-> copying files...'
scp "${files[@]/#/$server:}" "${TEMPDIR}/"
mv "${TEMPDIR}"/*.pkg.tar* "${PKGDEST:-${PWD}}/"
mv "${TEMPDIR}/PKGBUILD" "${PWD}/"
else
exit 1
fi

View File

@@ -19,15 +19,13 @@ usage() {
Unified command-line frontend for devtools.
COMMANDS
aur Interact with the Arch User Repository
auth Authenticate with services like GitLab
build Build packages inside a clean chroot
db Pacman database modification for package update, move etc
diff Compare package files using different modes
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
version Check and manage package versions against upstream
version Show pkgctl version information
OPTIONS
-h, --help Show this help text
@@ -39,16 +37,8 @@ if (( $# < 1 )); then
exit 1
fi
pkgctl_version_print() {
cat <<- _EOF_
pkgctl @buildtoolver@
_EOF_
}
export _DEVTOOLS_COMMAND='pkgctl'
setup_workdir
load_devtools_config
# command checking
@@ -58,14 +48,6 @@ while (( $# )); do
usage
exit 0
;;
aur)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/aur.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/aur.sh
pkgctl_aur "$@"
exit 0
;;
build)
_DEVTOOLS_COMMAND+=" $1"
shift
@@ -112,28 +94,14 @@ while (( $# )); do
pkgctl_release "$@"
exit 0
;;
search)
version|--version|-V)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/release.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/search.sh
pkgctl_search "$@"
exit 0
;;
version)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/version.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/version.sh
# shellcheck source=src/lib/version/version.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/version/version.sh
pkgctl_version "$@"
exit 0
;;
--version|-V)
_DEVTOOLS_COMMAND+=" $1"
shift
pkgctl_version_print
exit 0
;;
*)
die "invalid command: %s" "$1"
;;

View File

@@ -31,7 +31,7 @@ recache() {
(( VERBOSE )) && verbosity=--progress-bar
for repo in "${DEVTOOLS_VALID_REPOS[@]}"; do
for repo in "${_repos[@]}"; do
if [[ -n "$SOLINKS_MIRROR" ]]; then
mirror="$SOLINKS_MIRROR"
elif ! mirror="$(set -o pipefail; pacman-conf --repo "$repo" Server 2>/dev/null | head -n1)"; then
@@ -72,7 +72,7 @@ is_outdated_cache() {
# links databases are generated at about the same time every day; we should
# attempt to check for new database files if any of them are over a day old
for repo in "${DEVTOOLS_VALID_REPOS[@]}"; do
for repo in "${_repos[@]}"; do
for arch in "${arches[@]}"; do
local dbpath=${SOCACHE_DIR}/${arch}/${repo}.links.tar.gz
if [[ ! -f ${dbpath} ]] || [[ $(find "${dbpath}" -mtime +0) ]]; then
@@ -85,10 +85,10 @@ is_outdated_cache() {
}
search() {
local repo=$1 arch lib=$2 srepos=("${DEVTOOLS_VALID_REPOS[@]}")
local repo=$1 arch lib=$2 srepos=("${_repos[@]}")
if [[ $repo != all ]]; then
if ! in_array "${repo}" "${DEVTOOLS_VALID_REPOS[@]}"; then
if ! in_array "${repo}" "${_repos[@]}"; then
echo "${BASH_SOURCE[0]##*/}: unrecognized repo '$repo'"
echo "Try '${BASH_SOURCE[0]##*/} --help' for more information."
exit 1

View File

@@ -1,127 +0,0 @@
bats_require_minimum_version 1.5.0
export _DEVTOOLS_LIBRARY_DIR="${PWD}/src"
_pkgctl_version_setup() {
source ${_DEVTOOLS_LIBRARY_DIR}/lib/version/setup.sh
pkgctl_version_setup "$@"
}
setup_and_check_config() {
pushd "test/fixture/version/setup/$1"
shift
_pkgctl_version_setup --force --no-check "$@"
diff .nvchecker.toml nvchecker.assert.toml
popd
}
@test "opt-no-force" {
pushd test/fixture/version/setup/opt-no-force
touch .nvchecker.toml
run ! _pkgctl_version_setup --no-check "$@"
popd
}
@test "opt-url" {
pushd test/fixture/version/setup/opt-url
_pkgctl_version_setup --no-check --force --url \
"https://crates.io/api/v1/crates/shotgun/1.0/download" "$@"
diff .nvchecker.toml nvchecker.assert.toml
popd
}
@test "codeberg-tarball" {
setup_and_check_config codeberg-tarball
}
@test "files.pythonhosted.org" {
setup_and_check_config files.pythonhosted.org
}
@test "github-git" {
setup_and_check_config github-git
}
@test "github-git-as-platform" {
setup_and_check_config github-git-as-platform --prefer-platform-api
}
@test "github-git-v-prefix" {
setup_and_check_config github-git-v-prefix
}
@test "github-git-v-prefix-as-platform" {
setup_and_check_config github-git-v-prefix-as-platform --prefer-platform-api
}
@test "github-tarball" {
setup_and_check_config github-tarball
}
@test "github-tarball-as-platform" {
setup_and_check_config github-tarball-as-platform --prefer-platform-api
}
@test "gitlab-archlinux-tarball" {
setup_and_check_config gitlab-archlinux-tarball
}
@test "gitlab-archlinux-tarball-as-platform" {
setup_and_check_config gitlab-archlinux-tarball-as-platform --prefer-platform-api
}
@test "gitlab-git-multi-group" {
setup_and_check_config gitlab-git-multi-group
}
@test "gitlab-git-multi-group-as-platform" {
setup_and_check_config gitlab-git-multi-group-as-platform --prefer-platform-api
}
@test "gitlab-tarball-multi-group" {
setup_and_check_config gitlab-tarball-multi-group
}
@test "gitlab-tarball-multi-group-as-platform" {
setup_and_check_config gitlab-tarball-multi-group-as-platform --prefer-platform-api
}
@test "hackage-tarball" {
setup_and_check_config hackage-tarball
}
@test "pkgbase-with-dot" {
setup_and_check_config pkgbase-with-dot
}
@test "pypi.io" {
setup_and_check_config pypi.io
}
@test "pypi.org" {
setup_and_check_config pypi.org
}
@test "registry.npmjs.org" {
setup_and_check_config registry.npmjs.org
}
@test "git-custom" {
setup_and_check_config git-custom
}
@test "rubygems.org" {
setup_and_check_config rubygems.org
}
@test "cpan.org" {
setup_and_check_config cpan.org
}
@test "crates.io" {
setup_and_check_config crates.io
}
@test "static.crates.io" {
setup_and_check_config static.crates.io
}

View File

@@ -1 +0,0 @@
*/.nvchecker.toml

View File

@@ -1,18 +0,0 @@
pkgname=xmobar
pkgver=1.0
pkgrel=1
pkgdesc=''
url='https://codeberg.org/xmobar/xmobar'
arch=(any)
source=(
dynamic-compilation.patch
${pkgname}-${pkgver}.tar.gz::https://codeberg.org/xmobar/xmobar/archive/${pkgver}.tar.gz
)
sha512sums=('319f3a77d500c505826ab487e4011bb1a22b8cae70c17b964574a09a6488a864a1aaabb6a298468d121110dd485f179bc712a5106e49eb8ae638e02b5115190a'
'15db3e27d1ff957e26e706e4c67cec6e43d89f5a39cd6d81ddb5ae8426e32d938494fbba39fa322461d992a95d2e522c10b186a1ca2c5c3e996f944b6e6ef7c4')
package() {
:
}
# vim: ts=2 sw=2 et:

View File

@@ -1,3 +0,0 @@
[xmobar]
source = "git"
git = "https://codeberg.org/xmobar/xmobar.git"

View File

@@ -1,14 +0,0 @@
pkgname=perl-locale-po
pkgver=0.3.5
pkgrel=1
pkgdesc=''
arch=(any)
url='http://polyglot.rubyforge.org/'
source=("https://search.cpan.org/CPAN/authors/id/C/CO/COSIMO/Locale-PO-$pkgver.tar.gz")
sha256sums=('59d66ef5e3c166431c39cb8b7c1d02af419051352f27912f6a43981b3def16af')
package() {
:
}
# vim: ts=2 sw=2 et:

View File

@@ -1,3 +0,0 @@
[perl-locale-po]
source = "cpan"
cpan = "Locale-PO"

View File

@@ -1,17 +0,0 @@
pkgname=shotgun
pkgver=0.3.5
pkgrel=1
pkgdesc='Minimal X screenshot utility'
arch=('any')
url='https://github.com/neXromancers/shotgun'
license=('MIT')
depends=('cargo')
options=('!emptydirs')
source=("https://crates.io/api/v1/crates/${pkgname}/${pkgver}/download")
sha256sums=('59d66ef5e3c166431c39cb8b7c1d02af419051352f27912f6a43981b3def16af')
package() {
:
}
# vim: ts=2 sw=2 et:

Some files were not shown because too many files have changed in this diff Show More