Send patches - preferably formatted by git format-patch - to patches at archlinux32 dot org.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile223
-rw-r--r--README.md40
-rw-r--r--config/makepkg/x86_64.conf4
-rw-r--r--config/makepkg/x86_64_v3.conf4
-rw-r--r--config/pacman/core-staging-with-build-support.conf (renamed from config/pacman/staging-with-build-support.conf)13
-rw-r--r--config/pacman/core-staging-x86_64_v3.conf (renamed from config/pacman/staging-x86_64_v3.conf)13
-rw-r--r--config/pacman/core-staging.conf (renamed from config/pacman/staging.conf)13
-rw-r--r--config/pacman/core-testing-x86_64_v3.conf (renamed from config/pacman/testing-x86_64_v3.conf)9
-rw-r--r--config/pacman/core-testing.conf (renamed from config/pacman/testing.conf)9
-rw-r--r--config/pacman/extra-staging-with-build-support.conf99
-rw-r--r--config/pacman/extra-staging-x86_64_v3.conf95
-rw-r--r--config/pacman/extra-staging.conf95
-rw-r--r--config/pacman/extra-testing-x86_64_v3.conf89
-rw-r--r--config/pacman/extra-testing.conf89
-rw-r--r--config/pacman/extra-x86_64_v3.conf9
-rw-r--r--config/pacman/extra.conf11
-rw-r--r--config/pacman/gnome-unstable.conf9
-rw-r--r--config/pacman/kde-unstable.conf9
-rw-r--r--config/pacman/multilib-staging.conf13
-rw-r--r--config/pacman/multilib-testing.conf9
-rw-r--r--config/pacman/multilib.conf11
-rw-r--r--config/setarch-aliases.d/i4861
-rw-r--r--contrib/completion/bash/devtools.in543
-rw-r--r--contrib/completion/zsh/_devtools.in185
-rw-r--r--doc/man/archbuild.1.asciidoc3
-rw-r--r--doc/man/devtools.7.asciidoc20
-rw-r--r--doc/man/diffpkg.1.asciidoc6
-rw-r--r--doc/man/include/footer.asciidoc28
-rw-r--r--doc/man/makerepropkg.1.asciidoc2
-rw-r--r--doc/man/mkarchroot.1.asciidoc2
-rw-r--r--doc/man/pkgctl-auth-login.1.asciidoc40
-rw-r--r--doc/man/pkgctl-auth-status.1.asciidoc32
-rw-r--r--doc/man/pkgctl-auth.1.asciidoc38
-rw-r--r--doc/man/pkgctl-build.1.asciidoc91
-rw-r--r--doc/man/pkgctl-db-move.1.asciidoc24
-rw-r--r--doc/man/pkgctl-db-remove.1.asciidoc26
-rw-r--r--doc/man/pkgctl-db-update.1.asciidoc23
-rw-r--r--doc/man/pkgctl-diff.1.asciidoc73
-rw-r--r--doc/man/pkgctl-release.1.asciidoc49
-rw-r--r--doc/man/pkgctl-repo-clone.1.asciidoc52
-rw-r--r--doc/man/pkgctl-repo-configure.1.asciidoc39
-rw-r--r--doc/man/pkgctl-repo-create.1.asciidoc40
-rw-r--r--doc/man/pkgctl-repo-switch.1.asciidoc36
-rw-r--r--doc/man/pkgctl-repo-web.1.asciidoc24
-rw-r--r--doc/man/pkgctl-repo.1.asciidoc59
-rw-r--r--doc/man/pkgctl-version.1.asciidoc23
-rw-r--r--doc/man/pkgctl.1.asciidoc61
-rw-r--r--lib/valid-repos.sh32
-rw-r--r--lib/valid-tags.sh27
-rw-r--r--src/arch-nspawn.in15
-rw-r--r--src/archbuild.in38
-rw-r--r--src/archco.in26
-rw-r--r--src/archrelease.in95
-rw-r--r--src/checkpkg.in5
-rw-r--r--src/commitpkg.in136
-rw-r--r--src/crossrepomove.in91
-rw-r--r--src/diffpkg.in25
-rw-r--r--src/export-pkgbuild-keys.in7
-rw-r--r--src/find-libdeps.in7
-rw-r--r--src/finddeps.in5
-rw-r--r--src/lddd.in5
-rw-r--r--src/lib/api/gitlab.sh132
-rw-r--r--src/lib/archroot.sh (renamed from lib/archroot.sh)7
-rw-r--r--src/lib/auth.sh72
-rw-r--r--src/lib/auth/login.sh101
-rw-r--r--src/lib/auth/status.sh69
-rw-r--r--src/lib/build/build.sh420
-rw-r--r--src/lib/common.sh (renamed from lib/common.sh)62
-rw-r--r--src/lib/config.sh48
-rw-r--r--src/lib/db.sh80
-rw-r--r--src/lib/db/move.sh64
-rw-r--r--src/lib/db/remove.sh69
-rw-r--r--src/lib/db/update.sh46
-rw-r--r--src/lib/release.sh167
-rw-r--r--src/lib/repo.sh110
-rw-r--r--src/lib/repo/clone.sh199
-rw-r--r--src/lib/repo/configure.sh259
-rw-r--r--src/lib/repo/create.sh113
-rw-r--r--src/lib/repo/switch.sh119
-rw-r--r--src/lib/repo/web.sh84
-rw-r--r--src/lib/util/git.sh24
-rw-r--r--src/lib/util/pacman.sh52
-rw-r--r--src/lib/valid-repos.sh22
-rw-r--r--src/lib/valid-tags.sh26
-rw-r--r--src/lib/version/version.sh47
-rw-r--r--src/makechrootpkg.in13
-rw-r--r--src/makerepropkg.in19
-rw-r--r--src/mkarchroot.in13
-rw-r--r--src/offload-build.in6
-rw-r--r--src/pkgctl.in109
-rw-r--r--src/rebuildpkgs.in111
-rw-r--r--src/sogrep.in33
-rwxr-xr-xtest/bin/pkgctl12
93 files changed, 4873 insertions, 735 deletions
diff --git a/Makefile b/Makefile
index 04de8ee..e415f40 100644
--- a/Makefile
+++ b/Makefile
@@ -1,48 +1,64 @@
V=$(shell git describe --exact-match)
+SHELL=/bin/bash
BUILDTOOLVER ?= $(V)
PREFIX = /usr/local
MANDIR = $(PREFIX)/share/man
+DATADIR = $(PREFIX)/share/devtools
BUILDDIR = build
-BINPROGS = $(addprefix $(BUILDDIR)/,$(patsubst src/%,bin/%,$(patsubst %.in,%,$(wildcard src/*.in))))
-LIBUTILS = $(wildcard lib/*)
+rwildcard=$(foreach d,$(wildcard $(1:=/*)),$(call rwildcard,$d,$2) $(filter $(subst *,%,$2),$d))
+
+BINPROGS_SRC = $(wildcard src/*.in)
+BINPROGS = $(addprefix $(BUILDDIR)/,$(patsubst src/%,bin/%,$(patsubst %.in,%,$(BINPROGS_SRC))))
+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/*)
SETARCH_ALIASES = $(wildcard config/setarch-aliases.d/*)
MANS = $(addprefix $(BUILDDIR)/,$(patsubst %.asciidoc,%,$(wildcard doc/man/*.asciidoc)))
-GENERATED_CONFIGS = \
- pacman-extra-i486.conf \
- pacman-extra-i686.conf \
- pacman-extra-pentium4.conf \
- pacman-testing-i486.conf \
- pacman-testing-i686.conf \
- pacman-testing-pentium4.conf \
- pacman-staging-i486.conf \
- pacman-staging-i686.conf \
- pacman-staging-pentium4.conf \
- pacman-staging-with-build-support-i486.conf \
- pacman-staging-with-build-support-i686.conf \
- pacman-staging-with-build-support-pentium4.conf \
- pacman-kde-unstable-i486.conf \
- pacman-kde-unstable-i686.conf \
- pacman-kde-unstable-pentium4.conf \
- pacman-gnome-unstable-i486.conf \
- pacman-gnome-unstable-i686.conf \
- pacman-gnome-unstable-pentium4.conf \
- makepkg-i486.conf \
- makepkg-i686.conf \
- makepkg-pentium4.conf
-GENERATED_CONFIGS := $(addprefix $(BUILDDIR)/config/,$(GENERATED_CONFIGS))
+GENERATED_PACMAN_CONFIGS = \
+ core-testing-i486.conf \
+ core-testing-i686.conf \
+ core-testing-pentium4.conf \
+ core-staging-i486.conf \
+ core-staging-i686.conf \
+ core-staging-pentium4.conf \
+ core-staging-with-build-support-i486.conf \
+ core-staging-with-build-support-i686.conf \
+ core-staging-with-build-support-pentium4.conf \
+ extra-i486.conf \
+ extra-i686.conf \
+ extra-pentium4.conf \
+ extra-testing-i486.conf \
+ extra-testing-i686.conf \
+ extra-testing-pentium4.conf \
+ extra-staging-i486.conf \
+ extra-staging-i686.conf \
+ extra-staging-pentium4.conf \
+ extra-staging-with-build-support-i486.conf \
+ extra-staging-with-build-support-i686.conf \
+ extra-staging-with-build-support-pentium4.conf \
+ kde-unstable-i486.conf \
+ kde-unstable-i686.conf \
+ kde-unstable-pentium4.conf \
+ gnome-unstable-i486.conf \
+ gnome-unstable-i686.conf \
+ gnome-unstable-pentium4.conf
+GENERATED_MAKEPKG_CONFIGS = \
+ i486.conf \
+ i686.conf \
+ pentium4.conf
+GENERATED_PACMAN_CONFIGS := $(addprefix $(BUILDDIR)/pacman.conf.d/,$(GENERATED_PACMAN_CONFIGS))
+GENERATED_MAKEPKG_CONFIGS := $(addprefix $(BUILDDIR)/makepkg.conf.d/,$(GENERATED_MAKEPKG_CONFIGS))
COMMITPKG_LINKS = \
+ core-testingpkg \
+ core-stagingpkg \
extrapkg \
- testingpkg \
- stagingpkg \
- communitypkg \
- community-testingpkg \
- community-stagingpkg \
+ extra-testingpkg \
+ extra-stagingpkg \
multilibpkg \
multilib-testingpkg \
multilib-stagingpkg \
@@ -50,24 +66,38 @@ COMMITPKG_LINKS = \
gnome-unstablepkg
ARCHBUILD_LINKS = \
+ core-testing-i486-build \
+ core-testing-i686-build \
+ core-testing-pentium4-build \
+ core-testing-x86_64-build \
+ core-testing-x86_64_v3-build \
+ core-staging-i486-build \
+ core-staging-i686-build \
+ core-staging-pentium4-build \
+ core-staging-x86_64-build \
+ core-staging-x86_64_v3-build \
+ core-staging-x86_64-build \
+ core-staging-with-build-support-i486-build \
+ core-staging-with-build-support-i686-build \
+ core-staging-with-build-support-pentium4-build \
extra-i486-build \
extra-i686-build \
extra-pentium4-build \
extra-x86_64-build \
extra-x86_64_v3-build \
- testing-i486-build \
- testing-i686-build \
- testing-pentium4-build \
- testing-x86_64-build \
- testing-x86_64_v3-build \
- staging-i486-build \
- staging-i686-build \
- staging-pentium4-build \
- staging-x86_64-build \
- staging-x86_64_v3-build \
- staging-with-build-support-i486-build \
- staging-with-build-support-i686-build \
- staging-with-build-support-pentium4-build \
+ extra-testing-i486-build \
+ extra-testing-i686-build \
+ extra-testing-pentium4-build \
+ extra-testing-x86_64-build \
+ extra-testing-x86_64_v3-build \
+ extra-staging-i486-build \
+ extra-staging-i686-build \
+ extra-staging-pentium4-build \
+ extra-staging-x86_64-build \
+ extra-staging-x86_64_v3-build \
+ extra-staging-with-build-support-i486-build \
+ extra-staging-with-build-support-i686-build \
+ extra-staging-with-build-support-pentium4-build \
multilib-build \
multilib-testing-build \
multilib-staging-build \
@@ -80,20 +110,14 @@ ARCHBUILD_LINKS = \
gnome-unstable-pentium4-build \
gnome-unstable-x86_64-build
-CROSSREPOMOVE_LINKS = \
- extra2community \
- community2extra
-
COMPLETIONS = $(addprefix $(BUILDDIR)/,$(patsubst %.in,%,$(wildcard contrib/completion/*/*)))
-BASHCOMPLETION_LINKS = \
- archco \
- communityco
-all: binprogs configfiles completion man
+all: binprogs library conf completion man configfiles
binprogs: $(BINPROGS)
+library: $(LIBRARY)
completion: $(COMPLETIONS)
-configfiles: $(GENERATED_CONFIGS)
+configfiles: $(GENERATED_MAKEPKG_CONFIGS) $(GENERATED_PACMAN_CONFIGS)
man: $(MANS)
@@ -111,10 +135,12 @@ ifneq ($(wildcard setarch-aliases.d/*),)
endif
-edit = sed -e "s|@pkgdatadir[@]|$(PREFIX)/share/devtools|g"
+edit = sed \
+ -e "s|@pkgdatadir[@]|$(DATADIR)|g" \
+ -e "s|@buildtoolver[@]|$(BUILDTOOLVER)|g"
GEN_MSG = @echo "GEN $(patsubst $(BUILDDIR)/%,%,$@)"
-$(BUILDDIR)/config/makepkg-i486.conf: config/makepkg/x86_64.conf
+$(BUILDDIR)/makepkg.conf.d/i486.conf: config/makepkg/x86_64.conf
@echo "GEN $(notdir $@)"
@mkdir -p $(dir $@)
@sed " \
@@ -125,7 +151,7 @@ $(BUILDDIR)/config/makepkg-i486.conf: config/makepkg/x86_64.conf
" "$<" > "$@"
@sed -i 's/--ultra -20/--ultra -19/' "$@"
-$(BUILDDIR)/config/makepkg-i686.conf: config/makepkg/x86_64.conf
+$(BUILDDIR)/makepkg.conf.d/i686.conf: config/makepkg/x86_64.conf
@echo "GEN $(notdir $@)"
@mkdir -p $(dir $@)
@sed " \
@@ -134,13 +160,13 @@ $(BUILDDIR)/config/makepkg-i686.conf: config/makepkg/x86_64.conf
" "$<" > "$@"
@sed -i 's/--ultra -20/--ultra -19/' "$@"
-$(BUILDDIR)/config/makepkg-pentium4.conf: $(BUILDDIR)/config/makepkg-i686.conf
+$(BUILDDIR)/makepkg.conf.d/pentium4.conf: $(BUILDDIR)/makepkg.conf.d/i686.conf
@echo "GEN $(notdir $@)"
@mkdir -p $(dir $@)
@sed '/^CHOST=/ ! s,\(["=]\)i686\([-" ]\),\1pentium4\2,g' "$<" > "$@"
@sed -i 's/--ultra -20/--ultra -19/' "$@"
-$(BUILDDIR)/config/pacman-%-i486.conf: config/pacman/%.conf
+$(BUILDDIR)/pacman.conf.d/%-i486.conf: config/pacman/%.conf
@echo "GEN $(notdir $@)"
@mkdir -p $(dir $@)
@sed " \
@@ -148,7 +174,7 @@ $(BUILDDIR)/config/pacman-%-i486.conf: config/pacman/%.conf
/^Architecture = / s/^.*\$$/Architecture = i486/; \
" "$<" > "$@"
-$(BUILDDIR)/config/pacman-%-i686.conf: config/pacman/%.conf
+$(BUILDDIR)/pacman.conf.d/%-i686.conf: config/pacman/%.conf
@echo "GEN $(notdir $@)"
@mkdir -p $(dir $@)
@sed " \
@@ -156,7 +182,7 @@ $(BUILDDIR)/config/pacman-%-i686.conf: config/pacman/%.conf
/^Architecture = / s/^.*$$/Architecture = i686/ \
" "$<" > "$@"
-$(BUILDDIR)/config/pacman-%-pentium4.conf: config/pacman/%.conf
+$(BUILDDIR)/pacman.conf.d/%-pentium4.conf: config/pacman/%.conf
@echo "GEN $(notdir $@)"
@mkdir -p $(dir $@)
@sed " \
@@ -165,77 +191,94 @@ $(BUILDDIR)/config/pacman-%-pentium4.conf: config/pacman/%.conf
" "$<" > "$@"
define buildInScript
-$(1)/%: $(2)%.in $(LIBUTILS)
+$(1)/%: $(2)%$(3)
$$(GEN_MSG)
@mkdir -p $$(dir $$@)
@$(RM) "$$@"
- @{ echo -n 'm4_changequote([[[,]]])'; cat $$<; } | m4 -P --define=m4_devtools_version=$$(BUILDTOOLVER) | $(edit) >$$@
- @chmod $(3) "$$@"
- @bash -n "$$@"
+ @cat $$< | $(edit) >$$@
+ @chmod $(4) "$$@"
+ @bash -O extglob -n "$$@"
endef
-$(eval $(call buildInScript,build/bin,src/,555))
-$(foreach completion,$(wildcard contrib/completion/*),$(eval $(call buildInScript,build/$(completion),$(completion)/,444)))
+$(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/asciidoc.conf doc/man/include/footer.asciidoc
$(GEN_MSG)
@mkdir -p $(BUILDDIR)/doc/man
- @a2x --no-xmllint --asciidoc-opts="-f doc/asciidoc.conf" -d manpage -f manpage --destination-dir=$(BUILDDIR)/doc/man -a pkgdatadir=$(PREFIX)/share/devtools $<
+ @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 $(BUILDDIR)/pacman.conf.d
+ @cp -a $(MAKEPKG_CONFIGS) $(BUILDDIR)/makepkg.conf.d
+ @cp -a $(PACMAN_CONFIGS) $(BUILDDIR)/pacman.conf.d
clean:
rm -rf $(BUILDDIR)
install: all
install -dm0755 $(DESTDIR)$(PREFIX)/bin
- install -dm0755 $(DESTDIR)$(PREFIX)/share/devtools/setarch-aliases.d
+ install -dm0755 $(DESTDIR)$(DATADIR)/setarch-aliases.d
+ install -dm0755 $(DESTDIR)$(DATADIR)/makepkg.conf.d
+ install -dm0755 $(DESTDIR)$(DATADIR)/pacman.conf.d
install -m0755 ${BINPROGS} $(DESTDIR)$(PREFIX)/bin
- for conf in ${MAKEPKG_CONFIGS}; do install -Dm0644 $$conf $(DESTDIR)$(PREFIX)/share/devtools/makepkg-$${conf##*/}; done
- for conf in ${PACMAN_CONFIGS}; do install -Dm0644 $$conf $(DESTDIR)$(PREFIX)/share/devtools/pacman-$${conf##*/}; done
- for conf in ${GENERATED_CONFIGS}; do install -Dm0644 $$conf $(DESTDIR)$(PREFIX)/share/devtools/$${conf##*/}; done
- for a in ${SETARCH_ALIASES}; do install -m0644 $$a -t $(DESTDIR)$(PREFIX)/share/devtools/setarch-aliases.d; done
+ install -dm0755 $(DESTDIR)$(DATADIR)/lib
+ cp -ra $(BUILDDIR)/lib/* $(DESTDIR)$(DATADIR)/lib
+ 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 $(GENERATED_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 conf in $(notdir $(GENERATED_PACMAN_CONFIGS)); do install -Dm0644 $(BUILDDIR)/pacman.conf.d/$$conf $(DESTDIR)$(DATADIR)/pacman.conf.d/$${conf##*/}; done
+ for a in ${SETARCH_ALIASES}; do install -m0644 $$a -t $(DESTDIR)$(DATADIR)/setarch-aliases.d; done
for l in ${COMMITPKG_LINKS}; do ln -sf commitpkg $(DESTDIR)$(PREFIX)/bin/$$l; done
for l in ${ARCHBUILD_LINKS}; do ln -sf archbuild $(DESTDIR)$(PREFIX)/bin/$$l; done
- for l in ${CROSSREPOMOVE_LINKS}; do ln -sf crossrepomove $(DESTDIR)$(PREFIX)/bin/$$l; done
ln -sf find-libdeps $(DESTDIR)$(PREFIX)/bin/find-libprovides
install -Dm0644 $(BUILDDIR)/contrib/completion/bash/devtools $(DESTDIR)$(PREFIX)/share/bash-completion/completions/devtools
- for l in ${BASHCOMPLETION_LINKS}; do ln -sf devtools $(DESTDIR)$(PREFIX)/share/bash-completion/completions/$$l; done
+ for f in $(notdir $(BINPROGS)); do ln -sf devtools $(DESTDIR)$(PREFIX)/share/bash-completion/completions/$$f; done
install -Dm0644 $(BUILDDIR)/contrib/completion/zsh/_devtools $(DESTDIR)$(PREFIX)/share/zsh/site-functions/_devtools
- ln -sf archco $(DESTDIR)$(PREFIX)/bin/communityco
for manfile in $(MANS); do \
install -Dm644 $$manfile -t $(DESTDIR)$(MANDIR)/man$${manfile##*.}; \
done;
uninstall:
for f in $(notdir $(BINPROGS)); do rm -f $(DESTDIR)$(PREFIX)/bin/$$f; done
- for conf in ${MAKEPKG_CONFIGS}; do rm -f $(DESTDIR)$(PREFIX)/share/devtools/makepkg-$${conf##*/}; done
- for conf in ${PACMAN_CONFIGS}; do rm -f $(DESTDIR)$(PREFIX)/share/devtools/pacman-$${conf##*/}; done
- for f in $(notdir $(SETARCH_ALIASES)); do rm -f $(DESTDIR)$(PREFIX)/share/devtools/setarch-aliases.d/$$f; done
+ for f in $(notdir $(LIBRARY)); do rm -f $(DESTDIR)$(DATADIR)/lib/$$f; done
+ rm -rf $(DESTDIR)$(DATADIR)/lib
+ 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
for l in ${COMMITPKG_LINKS}; do rm -f $(DESTDIR)$(PREFIX)/bin/$$l; done
for l in ${ARCHBUILD_LINKS}; do rm -f $(DESTDIR)$(PREFIX)/bin/$$l; done
- for l in ${CROSSREPOMOVE_LINKS}; do rm -f $(DESTDIR)$(PREFIX)/bin/$$l; done
- for l in ${BASHCOMPLETION_LINKS}; do rm -f $(DESTDIR)$(PREFIX)/share/bash-completion/completions/$$l; done
- rm $(DESTDIR)$(PREFIX)/share/bash-completion/completions/devtools
- rm $(DESTDIR)$(PREFIX)/share/zsh/site-functions/_devtools
- rm -f $(DESTDIR)$(PREFIX)/bin/communityco
+ rm -f $(DESTDIR)$(PREFIX)/share/bash-completion/completions/devtools
+ for f in $(notdir $(BINPROGS)); do rm -f $(DESTDIR)$(PREFIX)/share/bash-completion/completions/$$f; done
+ rm -f $(DESTDIR)$(PREFIX)/share/zsh/site-functions/_devtools
rm -f $(DESTDIR)$(PREFIX)/bin/find-libprovides
for manfile in $(notdir $(MANS)); do rm -f $(DESTDIR)$(MANDIR)/man$${manfile##*.}/$${manfile}; done;
- rmdir --ignore-fail-on-non-empty $(DESTDIR)$(PREFIX)/share/devtools/setarch-aliases.d $(DESTDIR)$(PREFIX)/share/devtools
+ rmdir --ignore-fail-on-non-empty \
+ $(DESTDIR)$(DATADIR)/setarch-aliases.d \
+ $(DESTDIR)$(DATADIR)/makepkg.conf.d \
+ $(DESTDIR)$(DATADIR)/pacman.conf.d \
+ $(DESTDIR)$(DATADIR)
-TODAY=$(shell date +"%Y%m%d")
tag:
- @sed -E "s|^V=[0-9]{8}|V=$(TODAY)|" -i Makefile
- @git commit --gpg-sign --message "Version $(TODAY)" Makefile
- @git tag --sign --message "Version $(TODAY)" $(TODAY)
+ @echo "current version: v$(V)"
+ @read -r -p "tag version: v" VERSION && \
+ sed -E "s|^V=.+|V=$$VERSION|" -i Makefile && \
+ git commit --gpg-sign --message "chore(release): version v$$VERSION" Makefile && \
+ git tag --sign --message "Version v$$VERSION" v$$VERSION
+
+release: dist
+ glab release create v$(RELEASE) devtools-$(RELEASE).tar.gz*
dist:
- git archive --format=tar --prefix=devtools32-$(V)/ $(V) | gzip -9 > devtools32-$(V).tar.gz
+ git archive --format=tar --prefix=devtools32-$(V)/ v$(V) | gzip > devtools32-$(V).tar.gz
gpg --detach-sign --use-agent devtools32-$(V).tar.gz
upload:
scp devtools32-$(V).tar.gz devtools32-$(V).tar.gz.sig sources.archlinux32.org:httpdocs/sources/
-check: $(BINPROGS) $(BUILDDIR)/contrib/completion/bash/devtools config/makepkg/x86_64.conf contrib/makepkg/PKGBUILD.proto
+check: $(BINPROGS_SRC) $(LIBRARY_SRC) contrib/completion/bash/devtools.in config/makepkg/x86_64.conf contrib/makepkg/PKGBUILD.proto
shellcheck $^
-.PHONY: all completion man clean install uninstall dist upload check tag
+.PHONY: all binprogs library completion conf man clean install uninstall tag dist upload check
.DELETE_ON_ERROR:
diff --git a/README.md b/README.md
index ef69f3b..95683a9 100644
--- a/README.md
+++ b/README.md
@@ -14,6 +14,15 @@ files like `makepkg.conf`.
BUILDTOOLVER="${pkgver}-${pkgrel}-${arch}" make all
```
+## Development
+
+For local development testing, there is a convenience wrapper for `pkgctl` that
+will automatically build the project and proxy all calls to the local build directory:
+
+```sh
+./test/bin/pkgctl --help
+```
+
## Releasing
1. bump the version in the Makefile
@@ -23,6 +32,37 @@ BUILDTOOLVER="${pkgver}-${pkgrel}-${arch}" make all
5. Upload the source tarball with ```make dist upload```
6. Update the package
+## Dependencies
+
+### Runtime Dependencies
+
+- arch-install-scripts
+- awk
+- bash
+- binutils
+- coreutils
+- diffutils
+- findutils
+- grep
+- jq
+- ncurses
+- openssh
+- parallel
+- rsync
+- sed
+- systemd
+- util-linux
+- bzr
+- git
+- mercurial
+- subversion
+
+### Development Dependencies
+
+- asciidoc
+- make
+- shellcheck
+
## License
Devtools is licensed under the terms of the **GPL-3.0-or-later** (see [LICENSE](LICENSE)).
diff --git a/config/makepkg/x86_64.conf b/config/makepkg/x86_64.conf
index 43215af..41fd6b0 100644
--- a/config/makepkg/x86_64.conf
+++ b/config/makepkg/x86_64.conf
@@ -46,13 +46,13 @@ CFLAGS="-march=x86-64 -mtune=generic -O2 -pipe -fno-plt -fexceptions \
CXXFLAGS="$CFLAGS -Wp,-D_GLIBCXX_ASSERTIONS"
LDFLAGS="-Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now"
LTOFLAGS="-flto=auto"
-#RUSTFLAGS="-C opt-level=2"
+RUSTFLAGS=""
#-- Make Flags: change this for DistCC/SMP systems
#MAKEFLAGS="-j2"
#-- Debugging flags
DEBUG_CFLAGS="-g"
DEBUG_CXXFLAGS="$DEBUG_CFLAGS"
-#DEBUG_RUSTFLAGS="-C debuginfo=2"
+DEBUG_RUSTFLAGS="-C debuginfo=2"
#########################################################################
# BUILD ENVIRONMENT
diff --git a/config/makepkg/x86_64_v3.conf b/config/makepkg/x86_64_v3.conf
index d9405d8..3c9d20d 100644
--- a/config/makepkg/x86_64_v3.conf
+++ b/config/makepkg/x86_64_v3.conf
@@ -46,13 +46,13 @@ CFLAGS="-march=x86-64-v3 -mtune=generic -O2 -pipe -fno-plt -fexceptions \
CXXFLAGS="$CFLAGS -Wp,-D_GLIBCXX_ASSERTIONS"
LDFLAGS="-Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now"
LTOFLAGS="-flto=auto"
-#RUSTFLAGS="-C opt-level=2"
+RUSTFLAGS=""
#-- Make Flags: change this for DistCC/SMP systems
#MAKEFLAGS="-j2"
#-- Debugging flags
DEBUG_CFLAGS="-g"
DEBUG_CXXFLAGS="$DEBUG_CFLAGS"
-#DEBUG_RUSTFLAGS="-C debuginfo=2"
+DEBUG_RUSTFLAGS="-C debuginfo=2"
#########################################################################
# BUILD ENVIRONMENT
diff --git a/config/pacman/staging-with-build-support.conf b/config/pacman/core-staging-with-build-support.conf
index 3d2c125..7b62e6f 100644
--- a/config/pacman/staging-with-build-support.conf
+++ b/config/pacman/core-staging-with-build-support.conf
@@ -73,25 +73,22 @@ LocalFileSigLevel = Optional
[build-support]
Include = /etc/pacman.d/mirrorlist
-[staging]
+[core-staging]
Include = /etc/pacman.d/mirrorlist
-[community-staging]
+[extra-staging]
Include = /etc/pacman.d/mirrorlist
-[testing]
-Include = /etc/pacman.d/mirrorlist
-
-[community-testing]
+[core-testing]
Include = /etc/pacman.d/mirrorlist
[core]
Include = /etc/pacman.d/mirrorlist
-[extra]
+[extra-testing]
Include = /etc/pacman.d/mirrorlist
-[community]
+[extra]
Include = /etc/pacman.d/mirrorlist
# An example of a custom package repository. See the pacman manpage for
diff --git a/config/pacman/staging-x86_64_v3.conf b/config/pacman/core-staging-x86_64_v3.conf
index 46ba8f8..f1eff4a 100644
--- a/config/pacman/staging-x86_64_v3.conf
+++ b/config/pacman/core-staging-x86_64_v3.conf
@@ -70,25 +70,22 @@ LocalFileSigLevel = Optional
# repo name header and Include lines. You can add preferred servers immediately
# after the header, and they will be used before the default mirrors.
-[staging]
+[core-staging]
Include = /etc/pacman.d/mirrorlist
-[testing]
+[core-testing]
Include = /etc/pacman.d/mirrorlist
[core]
Include = /etc/pacman.d/mirrorlist
-[extra]
-Include = /etc/pacman.d/mirrorlist
-
-[community-staging]
+[extra-staging]
Include = /etc/pacman.d/mirrorlist
-[community-testing]
+[extra-testing]
Include = /etc/pacman.d/mirrorlist
-[community]
+[extra]
Include = /etc/pacman.d/mirrorlist
# An example of a custom package repository. See the pacman manpage for
diff --git a/config/pacman/staging.conf b/config/pacman/core-staging.conf
index 321a4e8..552d51d 100644
--- a/config/pacman/staging.conf
+++ b/config/pacman/core-staging.conf
@@ -70,27 +70,24 @@ LocalFileSigLevel = Optional
# repo name header and Include lines. You can add preferred servers immediately
# after the header, and they will be used before the default mirrors.
-[staging]
+[core-staging]
Include = /etc/pacman.d/mirrorlist
-[community-staging]
+[core-testing]
Include = /etc/pacman.d/mirrorlist
-[testing]
+[core]
Include = /etc/pacman.d/mirrorlist
-[community-testing]
+[extra-staging]
Include = /etc/pacman.d/mirrorlist
-[core]
+[extra-testing]
Include = /etc/pacman.d/mirrorlist
[extra]
Include = /etc/pacman.d/mirrorlist
-[community]
-Include = /etc/pacman.d/mirrorlist
-
# An example of a custom package repository. See the pacman manpage for
# tips on creating your own repositories.
#[custom]
diff --git a/config/pacman/testing-x86_64_v3.conf b/config/pacman/core-testing-x86_64_v3.conf
index 2eb463d..112a40c 100644
--- a/config/pacman/testing-x86_64_v3.conf
+++ b/config/pacman/core-testing-x86_64_v3.conf
@@ -70,19 +70,16 @@ LocalFileSigLevel = Optional
# repo name header and Include lines. You can add preferred servers immediately
# after the header, and they will be used before the default mirrors.
-[testing]
+[core-testing]
Include = /etc/pacman.d/mirrorlist
[core]
Include = /etc/pacman.d/mirrorlist
-[extra]
-Include = /etc/pacman.d/mirrorlist
-
-[community-testing]
+[extra-testing]
Include = /etc/pacman.d/mirrorlist
-[community]
+[extra]
Include = /etc/pacman.d/mirrorlist
# An example of a custom package repository. See the pacman manpage for
diff --git a/config/pacman/testing.conf b/config/pacman/core-testing.conf
index bf9003c..d8b8af3 100644
--- a/config/pacman/testing.conf
+++ b/config/pacman/core-testing.conf
@@ -70,19 +70,16 @@ LocalFileSigLevel = Optional
# repo name header and Include lines. You can add preferred servers immediately
# after the header, and they will be used before the default mirrors.
-[testing]
-Include = /etc/pacman.d/mirrorlist
-
-[community-testing]
+[core-testing]
Include = /etc/pacman.d/mirrorlist
[core]
Include = /etc/pacman.d/mirrorlist
-[extra]
+[extra-testing]
Include = /etc/pacman.d/mirrorlist
-[community]
+[extra]
Include = /etc/pacman.d/mirrorlist
# An example of a custom package repository. See the pacman manpage for
diff --git a/config/pacman/extra-staging-with-build-support.conf b/config/pacman/extra-staging-with-build-support.conf
new file mode 100644
index 0000000..7b62e6f
--- /dev/null
+++ b/config/pacman/extra-staging-with-build-support.conf
@@ -0,0 +1,99 @@
+#
+# /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 -C - -f %u > %o
+#XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u
+#CleanMethod = KeepInstalled
+#UseDelta = 0.7
+Architecture = auto
+
+# Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup
+#IgnorePkg =
+#IgnoreGroup =
+
+#NoUpgrade =
+#NoExtract =
+
+# Misc options
+#UseSyslog
+#Color
+#TotalDownload
+# We cannot check disk space from within a chroot environment
+#CheckSpace
+#VerbosePkgLists
+
+# 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.
+
+[build-support]
+Include = /etc/pacman.d/mirrorlist
+
+[core-staging]
+Include = /etc/pacman.d/mirrorlist
+
+[extra-staging]
+Include = /etc/pacman.d/mirrorlist
+
+[core-testing]
+Include = /etc/pacman.d/mirrorlist
+
+[core]
+Include = /etc/pacman.d/mirrorlist
+
+[extra-testing]
+Include = /etc/pacman.d/mirrorlist
+
+[extra]
+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
+
diff --git a/config/pacman/extra-staging-x86_64_v3.conf b/config/pacman/extra-staging-x86_64_v3.conf
new file mode 100644
index 0000000..f1eff4a
--- /dev/null
+++ b/config/pacman/extra-staging-x86_64_v3.conf
@@ -0,0 +1,95 @@
+#
+# /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 = x86_64_v3 x86_64
+
+# 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.
+
+[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
+
+# 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
diff --git a/config/pacman/extra-staging.conf b/config/pacman/extra-staging.conf
new file mode 100644
index 0000000..552d51d
--- /dev/null
+++ b/config/pacman/extra-staging.conf
@@ -0,0 +1,95 @@
+#
+# /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.
+
+[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
+
+# 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
diff --git a/config/pacman/extra-testing-x86_64_v3.conf b/config/pacman/extra-testing-x86_64_v3.conf
new file mode 100644
index 0000000..112a40c
--- /dev/null
+++ b/config/pacman/extra-testing-x86_64_v3.conf
@@ -0,0 +1,89 @@
+#
+# /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 = x86_64_v3 x86_64
+
+# 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.
+
+[core-testing]
+Include = /etc/pacman.d/mirrorlist
+
+[core]
+Include = /etc/pacman.d/mirrorlist
+
+[extra-testing]
+Include = /etc/pacman.d/mirrorlist
+
+[extra]
+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
diff --git a/config/pacman/extra-testing.conf b/config/pacman/extra-testing.conf
new file mode 100644
index 0000000..d8b8af3
--- /dev/null
+++ b/config/pacman/extra-testing.conf
@@ -0,0 +1,89 @@
+#
+# /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.
+
+[core-testing]
+Include = /etc/pacman.d/mirrorlist
+
+[core]
+Include = /etc/pacman.d/mirrorlist
+
+[extra-testing]
+Include = /etc/pacman.d/mirrorlist
+
+[extra]
+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
diff --git a/config/pacman/extra-x86_64_v3.conf b/config/pacman/extra-x86_64_v3.conf
index afb7a0c..1c248cd 100644
--- a/config/pacman/extra-x86_64_v3.conf
+++ b/config/pacman/extra-x86_64_v3.conf
@@ -70,19 +70,16 @@ LocalFileSigLevel = Optional
# repo name header and Include lines. You can add preferred servers immediately
# after the header, and they will be used before the default mirrors.
-#[testing]
+#[core-testing]
#Include = /etc/pacman.d/mirrorlist
[core]
Include = /etc/pacman.d/mirrorlist
-[extra]
-Include = /etc/pacman.d/mirrorlist
-
-#[community-testing]
+#[extra-testing]
#Include = /etc/pacman.d/mirrorlist
-[community]
+[extra]
Include = /etc/pacman.d/mirrorlist
# An example of a custom package repository. See the pacman manpage for
diff --git a/config/pacman/extra.conf b/config/pacman/extra.conf
index e855f3c..8c84772 100644
--- a/config/pacman/extra.conf
+++ b/config/pacman/extra.conf
@@ -70,19 +70,16 @@ LocalFileSigLevel = Optional
# repo name header and Include lines. You can add preferred servers immediately
# after the header, and they will be used before the default mirrors.
-#[testing]
-#Include = /etc/pacman.d/mirrorlist
-
-#[community-testing]
+#[core-testing]
#Include = /etc/pacman.d/mirrorlist
[core]
Include = /etc/pacman.d/mirrorlist
-[extra]
-Include = /etc/pacman.d/mirrorlist
+#[extra-testing]
+#Include = /etc/pacman.d/mirrorlist
-[community]
+[extra]
Include = /etc/pacman.d/mirrorlist
# An example of a custom package repository. See the pacman manpage for
diff --git a/config/pacman/gnome-unstable.conf b/config/pacman/gnome-unstable.conf
index d7ae13b..7f1b3d8 100644
--- a/config/pacman/gnome-unstable.conf
+++ b/config/pacman/gnome-unstable.conf
@@ -73,19 +73,16 @@ LocalFileSigLevel = Optional
[gnome-unstable]
Include = /etc/pacman.d/mirrorlist
-[testing]
-Include = /etc/pacman.d/mirrorlist
-
-[community-testing]
+[core-testing]
Include = /etc/pacman.d/mirrorlist
[core]
Include = /etc/pacman.d/mirrorlist
-[extra]
+[extra-testing]
Include = /etc/pacman.d/mirrorlist
-[community]
+[extra]
Include = /etc/pacman.d/mirrorlist
# An example of a custom package repository. See the pacman manpage for
diff --git a/config/pacman/kde-unstable.conf b/config/pacman/kde-unstable.conf
index 6e6bfd8..603fc80 100644
--- a/config/pacman/kde-unstable.conf
+++ b/config/pacman/kde-unstable.conf
@@ -73,19 +73,16 @@ LocalFileSigLevel = Optional
[kde-unstable]
Include = /etc/pacman.d/mirrorlist
-[testing]
-Include = /etc/pacman.d/mirrorlist
-
-[community-testing]
+[core-testing]
Include = /etc/pacman.d/mirrorlist
[core]
Include = /etc/pacman.d/mirrorlist
-[extra]
+[extra-testing]
Include = /etc/pacman.d/mirrorlist
-[community]
+[extra]
Include = /etc/pacman.d/mirrorlist
# An example of a custom package repository. See the pacman manpage for
diff --git a/config/pacman/multilib-staging.conf b/config/pacman/multilib-staging.conf
index 5b300c0..82cf9e3 100644
--- a/config/pacman/multilib-staging.conf
+++ b/config/pacman/multilib-staging.conf
@@ -70,27 +70,24 @@ LocalFileSigLevel = Optional
# repo name header and Include lines. You can add preferred servers immediately
# after the header, and they will be used before the default mirrors.
-[staging]
+[core-staging]
Include = /etc/pacman.d/mirrorlist
-[community-staging]
+[core-testing]
Include = /etc/pacman.d/mirrorlist
-[testing]
+[core]
Include = /etc/pacman.d/mirrorlist
-[community-testing]
+[extra-staging]
Include = /etc/pacman.d/mirrorlist
-[core]
+[extra-testing]
Include = /etc/pacman.d/mirrorlist
[extra]
Include = /etc/pacman.d/mirrorlist
-[community]
-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]
diff --git a/config/pacman/multilib-testing.conf b/config/pacman/multilib-testing.conf
index db5b9cc..b1d40b7 100644
--- a/config/pacman/multilib-testing.conf
+++ b/config/pacman/multilib-testing.conf
@@ -70,19 +70,16 @@ LocalFileSigLevel = Optional
# repo name header and Include lines. You can add preferred servers immediately
# after the header, and they will be used before the default mirrors.
-[testing]
-Include = /etc/pacman.d/mirrorlist
-
-[community-testing]
+[core-testing]
Include = /etc/pacman.d/mirrorlist
[core]
Include = /etc/pacman.d/mirrorlist
-[extra]
+[extra-testing]
Include = /etc/pacman.d/mirrorlist
-[community]
+[extra]
Include = /etc/pacman.d/mirrorlist
# If you want to run 32 bit applications on your x86_64 system,
diff --git a/config/pacman/multilib.conf b/config/pacman/multilib.conf
index 1707f94..e09a9d5 100644
--- a/config/pacman/multilib.conf
+++ b/config/pacman/multilib.conf
@@ -70,19 +70,16 @@ LocalFileSigLevel = Optional
# repo name header and Include lines. You can add preferred servers immediately
# after the header, and they will be used before the default mirrors.
-#[testing]
-#Include = /etc/pacman.d/mirrorlist
-
-#[community-testing]
+#[core-testing]
#Include = /etc/pacman.d/mirrorlist
[core]
Include = /etc/pacman.d/mirrorlist
-[extra]
-Include = /etc/pacman.d/mirrorlist
+#[extra-testing]
+#Include = /etc/pacman.d/mirrorlist
-[community]
+[extra]
Include = /etc/pacman.d/mirrorlist
# If you want to run 32 bit applications on your x86_64 system,
diff --git a/config/setarch-aliases.d/i486 b/config/setarch-aliases.d/i486
new file mode 100644
index 0000000..193dd70
--- /dev/null
+++ b/config/setarch-aliases.d/i486
@@ -0,0 +1 @@
+i686
diff --git a/contrib/completion/bash/devtools.in b/contrib/completion/bash/devtools.in
index e7925b3..3faad27 100644
--- a/contrib/completion/bash/devtools.in
+++ b/contrib/completion/bash/devtools.in
@@ -2,89 +2,468 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
-_devtools_compgen() {
- local i r
- COMPREPLY=($(compgen -W '$*' -- "$cur"))
- for ((i=1; i < ${#COMP_WORDS[@]}-1; i++)); do
- for r in "${!COMPREPLY[@]}"; do
- if [[ ${COMP_WORDS[i]} = "${COMPREPLY[r]}" ]]; then
- unset 'COMPREPLY[r]'; break
- fi
- done
- done
-}
-
-_archco_pkg() {
- _devtools_compgen "$(
- command pacman "-$1"
- )"
-}
-
-_archco() {
- local cur prev
- COMPREPLY=()
- cur=$(_get_cword)
- prev=${COMP_WORDS[COMP_CWORD-1]}
-
- _archco_pkg Slq
- true
-} &&
-complete -F _archco archco communityco
-
-_makechrootpkg() {
- local cur
- COMPREPLY=()
- _get_comp_words_by_ref cur
-
- case $cur in
- -*)
- COMPREPLY=( $( compgen -W '-I -c -h -l -r -u' -- "$cur" ) )
- ;;
- *)
- _filedir
- return 0
- ;;
- esac
-
- true
-} &&
+_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+# 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
+
+_binary_arch=${_arch[*]:0:-1}
+_colors=(never always auto)
+
+
+_makechrootpkg_args=(
+ -h
+ -c
+ -d
+ -D
+ -u
+ -r
+ -I
+ -l
+ -n
+ -T
+ -U
+)
+_makechrootpkg_args_d_opts() { _filedir -d; }
+_makechrootpkg_args_D_opts() { _filedir -d; }
+_makechrootpkg_args_r_opts() { _filedir -d; }
+_makechrootpkg_args_I_opts() { _filedir '*.pkg.tar.*'; }
+_makechrootpkg_args_l_opts() { _filedir -d; }
+_makechrootpkg_args_U_opts() { :; }
+_makechrootpkg() { __devtools_complete _makechrootpkg; }
complete -F _makechrootpkg makechrootpkg
-_mkarchroot() {
- local cur
- COMPREPLY=()
- _get_comp_words_by_ref cur
-
- case $cur in
- -*)
- COMPREPLY=( $( compgen -W '-C -M -c -h' -- "$cur" ) )
- ;;
- *)
- _filedir
- return 0
- ;;
- esac
-
- true
-} &&
+
+_makerepropkg_args=(
+ -h
+ -d
+ -c
+ -M
+)
+_makerepropkg_args_c_opts() { _filedir -d; }
+_makerepropkg_args_M_opts() { _filedir '*.conf'; }
+_makerepropkg_opts() { _filedir '*.pkg.tar.*'; }
+_makerepropkg() { __devtools_complete _makerepropkg; }
+complete -F _makerepropkg makerepropkg
+
+
+_mkarchroot_args=(
+ -U
+ -C
+ -M
+ -c
+ -h
+)
+_mkarchroot_args_U_opts() { _filedir '*.pkg.tar.*'; }
+_mkarchroot_args_C_opts() { _filedir '*.conf'; }
+_mkarchroot_args_M_opts() { _filedir '*.conf'; }
+_mkarchroot_args_c_opts() { _filedir -d; }
+_mkarchroot_opts() {
+ local args
+ args=$(__pkgctl_word_count_after_subcommand)
+ if (( args == 0 )); then
+ _filedir -d
+ elif (( args >= 1 )); then
+ _devtools_completions_all_packages
+ fi
+}
+_mkarchroot() { __devtools_complete _mkarchroot; }
complete -F _mkarchroot mkarchroot
-_arch-nspawn() {
- local cur
- COMPREPLY=()
- _get_comp_words_by_ref cur
-
- case $cur in
- -*)
- COMPREPLY=( $( compgen -W '-C -M -c -h' -- "$cur" ) )
- ;;
- *)
- _filedir
- return 0
- ;;
- esac
-
- true
-} &&
-complete -F _arch-nspawn arch-nspawn
-# ex:et ts=2 sw=2 ft=sh
+
+_arch_nspawn_args=(
+ -C
+ -M
+ -c
+ -f
+ -s
+ -h
+)
+_arch_nspawn_args_C_opts() { _filedir '*.conf'; }
+_arch_nspawn_args_M_opts() { _filedir '*.conf'; }
+_arch_nspawn_args_c_opts() { _filedir -d; }
+_arch_nspawn_args_f_opts() { _filedir; }
+_arch_nspawn_opts() {
+ local args
+ args=$(__pkgctl_word_count_after_subcommand)
+ if (( args == 0 )); then
+ _filedir -d
+ fi
+}
+_arch_nspawn() { __devtools_complete _arch_nspawn; }
+complete -F _arch_nspawn arch-nspawn
+
+
+_sogrep_args=(
+ -v --verbose
+ -r --refresh
+ -h --help
+)
+_sogrep_opts() {
+ local args
+ args=$(__pkgctl_word_count_after_subcommand)
+ if (( args == 0 )); then
+ _devtools_completions_repo all
+ fi
+}
+_sogrep() { __devtools_complete _sogrep; }
+complete -F _sogrep sogrep
+
+
+_offload_build_args=(
+ -r --repo
+ -a --arch
+ -s --server
+ -h --help
+)
+_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_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; }
+_offload_build() { __devtools_complete _offload_build; }
+complete -F _offload_build offload-build
+
+
+_pkgctl_cmds=(
+ auth
+ build
+ db
+ diff
+ release
+ repo
+ version
+)
+_pkgctl_args=(
+ -V --version
+ -h --help
+)
+
+
+_pkgctl_auth_cmds=(
+ login
+ status
+)
+
+
+_pkgctl_auth_login_args=(
+ -g --gen-access-token
+ -h --help
+)
+
+
+_pkgctl_auth_status_args=(
+ -t --show-token
+ -h --help
+)
+
+
+_pkgctl_build_args=(
+ --arch
+ --repo
+
+ -s --staging
+ -t --testing
+ -o --offload
+ -c --clean
+ -w --worker
+
+ --pkgver
+ --pkgrel
+ --rebuild
+ -e --edit
+
+ -r --release
+ -m --message
+ -u --db-update
+
+ -h --help
+)
+_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__pkgver_opts() { :; }
+_pkgctl_build_args__pkgrel_opts() { :; }
+_pkgctl_build_args__message_opts() { :; }
+_pkgctl_build_args_m_opts() { _pkgctl_build_args__message_opts; }
+_pkgctl_build_opts() { _filedir -d; }
+
+
+_pkgctl_db_cmds=(
+ move
+ remove
+ update
+)
+
+
+_pkgctl_db_move_args=(
+ -h --help
+)
+_pkgctl_db_move_opts() {
+ local subcommand args
+ subcommand=(db move)
+ args=$(__pkgctl_word_count_after_subcommand "${subcommand[@]}")
+
+ if (( args == 0 )); then
+ _devtools_completions_repo
+ elif (( args == 1 )); then
+ _devtools_completions_repo
+ elif (( args >= 2 )); then
+ _devtools_completions_all_packages
+ fi
+}
+
+
+_pkgctl_db_remove_args=(
+ -a --arch
+ -h --help
+)
+_pkgctl_db_remove_opts() {
+ local subcommand args
+ subcommand=(db remove)
+ args=$(__pkgctl_word_count_after_subcommand "${subcommand[@]}")
+
+ if (( args == 0 )); then
+ _devtools_completions_repo
+ elif (( args >= 1 )); then
+ _devtools_completions_all_packages
+ fi
+}
+
+
+_pkgctl_db_update_args=(
+ -h --help
+)
+
+
+_pkgctl_release_args=(
+ -m --message
+ -r --repo
+ -s --staging
+ -t --testing
+ -u --db-update
+ -h --help
+)
+_pkgctl_release_args__message_opts() { :; }
+_pkgctl_release_args_m_opts() { _pkgctl_release_args__message_opts; }
+_pkgctl_release_args__repo_opts() { _devtools_completions_repo; }
+_pkgctl_release_args_r_opts() { _pkgctl_release_args__repo_opts; }
+_pkgctl_release_opts() { _filedir -d; }
+
+
+_pkgctl_repo_cmds=(
+ clone
+ configure
+ create
+ switch
+ web
+)
+
+
+_pkgctl_repo_clone_args=(
+ -m --maintainer
+ --protocol
+ --switch
+ -u --unprivileged
+ --universe
+ -j --jobs
+ -h --help
+)
+_pkgctl_repo_clone_args__maintainer_opts() { :; }
+_pkgctl_repo_clone_args_m_opts() { _pkgctl_repo_clone_args__maintainer_opts; }
+_pkgctl_repo_clone_args__protocol_opts() { _devtools_completions_protocol; }
+_pkgctl_repo_clone_args__switch_opts() { :; }
+_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_configure_args=(
+ --protocol
+ -j --jobs
+ -h --help
+)
+_pkgctl_repo_configure_args__protocol_opts() { _devtools_completions_protocol; }
+_pkgctl_repo_configure_args__jobs_opts() { :; }
+_pkgctl_repo_configure_args_j_opts() { _pkgctl_repo_clone_args__jobs_opts; }
+_pkgctl_repo_configure_opts() { _filedir -d; }
+
+
+_pkgctl_repo_create_args=(
+ -c --clone
+ -h --help
+)
+
+
+_pkgctl_repo_switch_args=(
+ --discard-changes
+ -f --force
+ -h --help
+)
+_pkgctl_repo_switch_opts() {
+ local subcommand args
+ subcommand=(repo switch)
+ args=$(__pkgctl_word_count_after_subcommand "${subcommand[@]}")
+
+ if (( args == 0 )); then
+ :
+ elif (( args >= 1 )); then
+ _filedir -d;
+ fi
+}
+
+
+_pkgctl_repo_web_args=(
+ -h --help
+)
+_pkgctl_repo_web_opts() { _filedir -d; }
+
+
+_pkgctl_diff_args=(
+ -l --list
+ -d --diffoscope
+ -p --pkginfo
+ -b --buildinfo
+ -m --makepkg-config
+ -u -U --unified
+ -y --side-by-side
+ --color
+ -W --width
+ -P --pool
+ -v --verbose
+ -h --help
+)
+_pkgctl_diff_args__makepkg_config_opts() { _filedir '*.conf'; }
+_pkgctl_diff_args_m_opts() { _pkgctl_diff_args__makepkg_config_opts; }
+_pkgctl_diff_args__width_opts() { :; }
+_pkgctl_diff_args_W_opts() { _pkgctl_diff_args__width_opts; }
+_pkgctl_diff_args__color_opts() { _devtools_completions_color; }
+_pkgctl_diff_args__pool_opts() { _filedir -d; }
+_pkgctl_diff_args_P_opts() { _pkgctl_diff_args__pool_opts; }
+_pkgctl_diff_opts() { _devtools_completions_all_packages; }
+
+
+_pkgctl_version_args=(
+ -h --help
+)
+
+
+_devtools_completions_color() {
+ mapfile -t COMPREPLY < <(compgen -W "${_colors[*]}" -- "$cur")
+}
+_devtools_completions_arch() {
+ mapfile -t COMPREPLY < <(compgen -W "${_arch[*]}" -- "$cur")
+}
+_devtools_completions_repo() {
+ local optional=${1:-}
+ mapfile -t COMPREPLY < <(compgen -W "${optional} ${_repos[*]}" -- "$cur")
+}
+_devtools_completions_build_repo() {
+ mapfile -t COMPREPLY < <(compgen -W "${_build_repos[*]}" -- "$cur")
+}
+_devtools_completions_all_packages() {
+ mapfile -t COMPREPLY < <(compgen -W "$(pacman -Sql)" -- "$cur")
+}
+_devtools_completions_protocol() {
+ mapfile -t COMPREPLY < <(compgen -W "https" -- "$cur")
+}
+
+__devtools_complete() {
+ local service=$1
+ local cur prev
+
+ # Don't break words at : and =
+ COMP_WORDBREAKS=${COMP_WORDBREAKS//[:=]}
+
+ cur=$(_get_cword)
+ prev=${COMP_WORDS[COMP_CWORD-1]}
+
+ __pkgctl_handle_subcommands "${service}"
+ return 0
+}
+
+__pkgctl_has_func() {
+ declare -f -- "${1}" &>/dev/null
+}
+
+__pkgctl_has_array() {
+ declare -p -- "${1}" &>/dev/null
+}
+
+__pkgctl_is_subcommand() {
+ __pkgctl_has_array "${1}"_args || \
+ __pkgctl_has_array "${1}"_cmds
+}
+
+__pkgctl_words_after_subcommand() {
+ local subcommand=("$@")
+ local subcommand_idx=0
+ local word prev_word
+ for ((i = 1; i < ${#COMP_WORDS[@]}; ++i)); do
+ word=${COMP_WORDS[i]}
+ prev_word=${COMP_WORDS[i-1]}
+ # skip options and the current typing
+ if [[ ${word} == -* ]] || [[ ${word} == "${cur}" ]]; then
+ continue
+ fi
+ # skip until we resolved the passed subcommand
+ if (( subcommand_idx < ${#subcommand[@]} )); then
+ if [[ $word == "${subcommand[$subcommand_idx]}" ]]; then
+ subcommand_idx=$(( subcommand_idx + 1 ))
+ fi
+ continue
+ fi
+ # skip previous options as they belong to the argument
+ if [[ ${prev_word} == -* ]] && __pkgctl_has_func "${service_name}_args${prev_word//-/_}_opts"; then
+ continue
+ fi
+ printf "%s\n" "${word}"
+ done
+}
+__pkgctl_word_count_after_subcommand() {
+ local subcommand=("$@")
+ mapfile -t words < <(__pkgctl_words_after_subcommand "${subcommand[@]}")
+ echo "${#words[@]}"
+}
+
+__pkgctl_handle_subcommands() {
+ local service_name=${1}
+ local index=${2:-0}
+ local word ref
+
+ # recurse into nested subcommands
+ for ((i = index + 1; i < ${#COMP_WORDS[@]}; ++i)); do
+ word=${COMP_WORDS[i]}
+ if [[ ${word} == -* ]] || [[ ${word} == "${cur}" ]]; then
+ continue
+ fi
+ if __pkgctl_is_subcommand "${service_name}_${word}"; then
+ __pkgctl_handle_subcommands "${service_name}_${word}" "${i}"
+ return
+ fi
+ done
+
+ # dynamic argument options
+ if [[ $prev == -* ]] && word=${prev//-/_} && __pkgctl_has_func "${service_name}_args${word}_opts"; then
+ "${service_name}_args${word}_opts"
+ # dynamic subcommand options
+ elif [[ $cur != -* ]] && __pkgctl_has_func "${service_name}_opts"; then
+ "${service_name}_opts"
+ # subcommand argument array
+ elif ( ! __pkgctl_has_array "${service_name}"_cmds || [[ $cur == -* ]] ) && __pkgctl_has_array "${service_name}_args"; then
+ declare -n ref="${service_name}_args"
+ mapfile -t COMPREPLY < <(compgen -W "${ref[*]}" -- "$cur")
+ # subcommand array
+ elif __pkgctl_has_array "${service_name}"_cmds; then
+ declare -n ref="${service_name}_cmds"
+ mapfile -t COMPREPLY < <(compgen -W "${ref[*]}" -- "$cur")
+ fi
+}
+
+
+_pkgctl() { __devtools_complete _pkgctl; }
+complete -F _pkgctl pkgctl
+# ex:noet ts=4 sw=4 ft=sh
diff --git a/contrib/completion/zsh/_devtools.in b/contrib/completion/zsh/_devtools.in
index 48d3dfd..a473bc2 100644
--- a/contrib/completion/zsh/_devtools.in
+++ b/contrib/completion/zsh/_devtools.in
@@ -1,9 +1,12 @@
-#compdef archbuild archco arch-nspawn archrelease commitpkg diffpkg finddeps makechrootpkg mkarchroot rebuildpkgs extrapkg=commitpkg corepkg=commitpkg testingpkg=commitpkg stagingpkg=commitpkg communitypkg=commitpkg community-testingpkg=commitpkg community-stagingpkg=commitpkg multilibpkg=commitpkg multilib-testingpkg=commitpkg extra-x86_64-build=archbuild testing-x86_64-build=archbuild staging-x86_64-build=archbuild multilib-build=archbuild multilib-testing-build=archbuild multilib-staging-build=archbuild kde-unstable-x86_64-build=archbuild gnome-unstable-x86_64-build=archbuild communityco=archco checkpkg sogrep offload-build makerepropkg
+#compdef archbuild arch-nspawn archrelease commitpkg pkgctl diffpkg finddeps makechrootpkg mkarchroot extrapkg=commitpkg corepkg=commitpkg testingpkg=commitpkg stagingpkg=commitpkg communitypkg=commitpkg community-testingpkg=commitpkg community-stagingpkg=commitpkg multilibpkg=commitpkg multilib-testingpkg=commitpkg extra-x86_64-build=archbuild testing-x86_64-build=archbuild staging-x86_64-build=archbuild multilib-build=archbuild multilib-testing-build=archbuild multilib-staging-build=archbuild kde-unstable-x86_64-build=archbuild gnome-unstable-x86_64-build=archbuild checkpkg sogrep offload-build makerepropkg
#
# SPDX-License-Identifier: GPL-3.0-or-later
-m4_include(lib/valid-tags.sh)
-m4_include(lib/valid-repos.sh)
+_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+# 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
_binary_arch=${_arch[*]:0:-1}
_colors=(never always auto)
@@ -15,10 +18,122 @@ _archbuild_args=(
'--[Introduce makechrootpkg options]:*::makechrootpkg options:= _dispatch makechrootpkg makechrootpkg'
)
-_archco_args=(
+_pkgctl_auth_cmds=(
+ "pkgctl auth command"
+ "login[Authenticate with the GitLab instance]"
+ "status[View authentication status]"
+)
+
+_pkgctl_auth_login_args=(
+ '(-g --gen-access-token)'{-g,--gen-access-token}'[Open the URL to generate a new personal access token]'
+ '(-h --help)'{-h,--help}'[Display usage]'
+)
+
+_pkgctl_auth_status_args=(
+ '(-t --show-token)'{-t,--show-token}'[Display the auth token]'
+ '(-h --help)'{-h,--help}'[Display usage]'
+)
+
+_pkgctl_build_args=(
+ "--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]'
+ '(-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]'
+ '(-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:"
+ '(-u --db-update)'{-u,--db-update}'[Automatically update the pacman database as last action]'
+ '(-h --help)'{-h,--help}'[Display usage]'
+ '*:git_dir:_files -/'
+)
+
+_pkgctl_db_cmds=(
+ "pkgctl db command"
+ "move[Move packages between pacman repositories]"
+ "remove[Remove packages from pacman repositories]"
+ "update[Update the pacman database as final release step]"
+)
+
+_pkgctl_db_move_args=(
+ '(-h --help)'{-h,--help}'[Display usage]'
+ "1:src-repo:($_repos[*])"
+ "2:target-repo:($_repos[*])"
+ '*:pkgbase:_devtools_completions_all_packages'
+)
+
+_pkgctl_db_remove_args=(
+ '(-a --arch=)'{-a,--arch=}"[Override the architecture (disables auto-detection)]:arch:($_arch[*])"
+ '(-h --help)'{-h,--help}'[Display usage]'
+ "1:repo:($_repos[*])"
+ '*:pkgbase:_devtools_completions_all_packages'
+)
+
+_pkgctl_db_update_args=(
+ '(-h --help)'{-h,--help}'[Display usage]'
+)
+
+_pkgctl_release_args=(
+ '(-m --message=)'{-m,--message=}"[Use the given <msg> as the commit message]:message:"
+ '(-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]'
+ '(-h --help)'{-h,--help}'[Display usage]'
+ '*:git_dir:_files -/'
+)
+
+_pkgctl_repo_cmds=(
+ "pkgctl repo command"
+ "clone[Clone a package repository]"
+ "configure[Configure a clone according to distro specs]"
+ "create[Create a new GitLab package repository]"
+ "switch[Switch a package repository to a specified version]"
+ "web[Open the packaging repository's website]"
+)
+
+_pkgctl_repo_switch_args=(
+ '(-f --force --discard-changes)'{-f,--force,--discard-changes}'[Discard changes if index or working tree is dirty]'
+ '(-h --help)'{-h,--help}'[Display usage]'
+ '1:version'
+ '*: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)'
+ '--switch=[Switch the current working tree to a specified version]'
+ '--universe[Clone all existing packages, useful for cache warming]'
+ '(-j --jobs)'{-j,--jobs}'[Run up to N jobs in parallel (default: number of processing units)]:jobs:'
+ '(-h --help)'{-h,--help}'[Display usage]'
'*:packages:_devtools_completions_all_packages'
)
+_pkgctl_repo_configure_args=(
+ '--protocol[Configure remote url to use https]:proto:(https)'
+ '(-j --jobs)'{-j,--jobs}'[Run up to N jobs in parallel (default: number of processing units)]:jobs:'
+ '(-h --help)'{-h,--help}'[Display usage]'
+ '*:git_dir:_files -/'
+)
+
+_pkgctl_repo_create_args=(
+ '(-c --clone)'{-c,--clone}'[Clone the Git repository after creation]'
+ '(-h --help)'{-h,--help}'[Display usage]'
+ '1:pkgbase'
+)
+
+_pkgctl_repo_web_args=(
+ '(-h --help)'{-h,--help}'[Display usage]'
+ '*:git_dir:_files -/'
+)
+
_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(.)"'
@@ -86,11 +201,6 @@ _mkarchroot_args=(
'*:packages:_devtools_completions_all_packages'
)
-_rebuildpkgs_args=(
- '1:chroot_dir:_files -/'
- '*:packages:_devtools_completions_all_packages'
-)
-
_checkpkg_args=(
'(-r --rmdir)'{-r,--rmdir}'[Remove the temporary directory]'
'(-w --warn)'{-w,--warn}'[Print a warning in case of differences]'
@@ -127,9 +237,62 @@ _devtools_completions_all_packages() {
compadd - "${(@)packages}"
}
+_pkgctl_cmds=(
+ "pkgctl command"
+ "auth[Authenticate with services like GitLab]"
+ "build[Build packages inside a clean chroot]"
+ "db[Pacman database modification for packge 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]"
+ "version[Show pkgctl version information]"
+)
+
+_pkgctl_args=(
+ '(-V --version)'{-V,--version}'[Show pkgctl version information]'
+ '(-h --help)'{-h,--help}'[Display usage]'
+)
+
+_pkgctl_version_args=(
+ '(-h --help)'{-h,--help}'[Display usage]'
+)
+
+_pkgctl_diff_args=("${_diffpkg_args[@]}")
+
+_handle_subcommands() {
+ local service_name=${1}
+ if typeset -p ${service_name}_cmds &> /dev/null; then
+ _arguments -C \
+ "1: :->cmds" \
+ '*::arg:->args'
+ case $state in
+ cmds)
+ if [[ "${line[-1]}" == -* ]] && typeset -p ${service_name}_args &> /dev/null; then
+ local argname="${service_name}_args[@]"
+ _arguments -s "${(P)argname}"
+ else
+ local service_cmds=${service_name}_cmds[@]
+ _values "${(P)service_cmds}"
+ fi
+ ;;
+ args)
+ 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}"
+ elif typeset -p ${service_sub}_cmds &> /dev/null; then
+ _handle_subcommands "${service_sub}"
+ fi
+ ;;
+ esac
+ elif typeset -p ${service_name}_args &> /dev/null; then
+ local argname="${service_name}_args[@]"
+ _arguments -s "${(P)argname}"
+ fi
+}
+
_devtools() {
- local argname="_${service//-/_}_args[@]"
- _arguments -s "${(P)argname}"
+ _handle_subcommands _${service//-/_}
}
_devtools
diff --git a/doc/man/archbuild.1.asciidoc b/doc/man/archbuild.1.asciidoc
index 6b00572..2a2d843 100644
--- a/doc/man/archbuild.1.asciidoc
+++ b/doc/man/archbuild.1.asciidoc
@@ -23,8 +23,9 @@ Description
* staging-x86_64-build
* testing-x86_64-build
-The symlink used to run it will be inspected by archbuild, to determine which target you want it to use. It will load the available pacman configuration from 'pacman-reponame-arch.conf' with a fallback to 'pacman-reponame.conf' from {pkgdatadir}. The makepkg configuration is loaded from 'makepkg-repo-arch.conf' with a fallback to 'makepkg-reponame.conf' from {pkgdatadir}.
+The symlink used to run it will be inspected by archbuild, to determine which target you want it to use. It will load the available pacman configuration from 'reponame-arch.conf' with a fallback to 'reponame.conf' from {pkgdatadir}/pacman.conf.d. The makepkg configuration is loaded from 'repo-arch.conf' with a fallback to 'reponame.conf' from {pkgdatadir}/makepkg.conf.d.
+It will also load the bind mount configuration from 'mount.d/arch' in {pkgdatadir}. The file format is that each line starting with ro and rw will be used, other lines will be ignored, and the rest of the used line is out/path:in/path preceded by a space as a separator. ro means it is a read-only mount, rw means a read-write mount.
Options
-------
diff --git a/doc/man/devtools.7.asciidoc b/doc/man/devtools.7.asciidoc
index 9062278..4ed11cf 100644
--- a/doc/man/devtools.7.asciidoc
+++ b/doc/man/devtools.7.asciidoc
@@ -8,16 +8,22 @@ devtools - Developer tools for the Arch Linux distribution
Description
-----------
-Devtools contains tools for package maintenance in Arch Linux. The toolset
-varies from tools for building packages in a clean chroot ('mkarchroot',...),
-packaging related tools for sonames ('sogrep', 'lddd') and tools for
-repository management such as ('archco', 'extra2community')
+Devtools contains tools for package maintenance in Arch Linux. It comes with a
+unified command-line frontend called 'pkgctl' that aids to conveniently
+interact with all the different tools this collection provides.
+
+The toolset varies from tools for building packages in a clean chroot
+('mkarchroot', 'archbuild', ...), packaging related tools ('sogrep', 'diffpkg',
+'lddd') and tools for repository management such as ('pkgrepo').
Programs
--------
The list below gives a short overview; see the respective documentation
for details.
+linkman:pkgctl[1]
+ Unified command-line frontend for devtools
+
linkman:archbuild[1]
Build an Arch Linux package inside a clean chroot
@@ -27,6 +33,12 @@ linkman:arch-nspawn[1]
linkman:checkpkg[1]
Compare the current build package with the repository version
+linkman:diffpkg[1]
+ Compare package files using different modes
+
+linkman:export-pkgbuild-keys[1]
+ Export valid source signing keys from a PKGBUILD
+
linkman:find-libdeps[1]
Find soname dependencies for a package
diff --git a/doc/man/diffpkg.1.asciidoc b/doc/man/diffpkg.1.asciidoc
index bfb2094..35b2ded 100644
--- a/doc/man/diffpkg.1.asciidoc
+++ b/doc/man/diffpkg.1.asciidoc
@@ -1,5 +1,5 @@
diffpkg(1)
-===========
+==========
Name
----
@@ -30,7 +30,6 @@ Options
*-M, --makepkg-config*::
Set an alternate makepkg configuration file
-
*-P, --pool*='DIR'::
Search diff target in pool dir (default `'/srv/ftp/pool'`)
@@ -71,7 +70,4 @@ Modes
*-b, --buildinfo*::
Activate .BUILDINFO diff mode
-See Also
---------
-
include::include/footer.asciidoc[]
diff --git a/doc/man/include/footer.asciidoc b/doc/man/include/footer.asciidoc
index 14c5d36..e7b1827 100644
--- a/doc/man/include/footer.asciidoc
+++ b/doc/man/include/footer.asciidoc
@@ -1,27 +1,7 @@
-Bugs
-----
-Bugs can be reported on the project's GitLab bug tracker 'https://gitlab.archlinux.org/archlinux/devtools'
+Homepage
+--------
+'https://gitlab.archlinux.org/archlinux/devtools'
-Authors
--------
-
-Maintainers:
-
-* Aaron Griffin <aaronmgriffin@gmail.com>
-* Allan McRae <allan@archlinux.org>
-* Bartłomiej Piotrowski <bpiotrowski@archlinux.org>
-* Dan McGee <dan@archlinux.org>
-* Dave Reisner <dreisner@archlinux.org>
-* Evangelos Foutras <evangelos@foutrelis.com>
-* Jan Alexander Steffens (heftig) <jan.steffens@gmail.com>
-* Jelle van der Waa <jelle@archlinux.org>
-* Levente Polyak <anthraxx@archlinux.org>
-* Pierre Schmitz <pierre@archlinux.de>
-* Sébastien Luttringer <seblu@seblu.net>
-* Sven-Hendrik Haase <svenstaro@gmail.com>
-* Thomas Bächler <thomas@archlinux.org>
-
-For additional contributors, use `git shortlog -s` on the devtools.git
-repository.
+Please report bugs and feature requests in the issue tracker. Please do your best to provide a reproducible test case for bugs.
diff --git a/doc/man/makerepropkg.1.asciidoc b/doc/man/makerepropkg.1.asciidoc
index 4e694b3..6044d7c 100644
--- a/doc/man/makerepropkg.1.asciidoc
+++ b/doc/man/makerepropkg.1.asciidoc
@@ -1,5 +1,5 @@
makerepropkg(1)
-================
+===============
Name
----
diff --git a/doc/man/mkarchroot.1.asciidoc b/doc/man/mkarchroot.1.asciidoc
index 7930c4c..a435852 100644
--- a/doc/man/mkarchroot.1.asciidoc
+++ b/doc/man/mkarchroot.1.asciidoc
@@ -1,5 +1,5 @@
mkarchroot(1)
-==============
+=============
Name
----
diff --git a/doc/man/pkgctl-auth-login.1.asciidoc b/doc/man/pkgctl-auth-login.1.asciidoc
new file mode 100644
index 0000000..eeeec4e
--- /dev/null
+++ b/doc/man/pkgctl-auth-login.1.asciidoc
@@ -0,0 +1,40 @@
+pkgctl-auth-login(1)
+====================
+
+Name
+----
+pkgctl-auth-login - Authenticate with the GitLab instance
+
+Synopsis
+--------
+pkgctl auth login [OPTIONS]
+
+Description
+-----------
+
+Interactively authenticate with the GitLab instance.
+
+The minimum required scopes for the token are: 'api', 'write_repository'.
+
+The GitLab API token can either be stored in a plaintext file in
+'$XDG_CONFIG_HOME/devtools/gitlab.conf', or supplied via the
+'DEVTOOLS_GITLAB_TOKEN' environment variable using any command (gpg, vault,
+password manager) by declaring a shell alias:
+
+ $ alias pkgctl='DEVTOOLS_GITLAB_TOKEN="$(command to obtain token)" pkgctl'
+
+Options
+-------
+
+*-g, --gen-access-token*::
+ Open the URL to generate a new personal access token
+
+*-h, --help*::
+ Show a help text
+
+See Also
+--------
+
+linkman:pkgctl-auth-status[1]
+
+include::include/footer.asciidoc[]
diff --git a/doc/man/pkgctl-auth-status.1.asciidoc b/doc/man/pkgctl-auth-status.1.asciidoc
new file mode 100644
index 0000000..e23ee2e
--- /dev/null
+++ b/doc/man/pkgctl-auth-status.1.asciidoc
@@ -0,0 +1,32 @@
+pkgctl-auth-status(1)
+=====================
+
+Name
+----
+pkgctl-auth-status - View authentication status
+
+Synopsis
+--------
+pkgctl auth status [OPTIONS]
+
+Description
+-----------
+
+Verifies and displays information about your authentication state of
+services like the GitLab instance and reports issues if any.
+
+Options
+-------
+
+*-t, --show-token*::
+ Display the auth token
+
+*-h, --help*::
+ Show a help text
+
+See Also
+--------
+
+linkman:pkgctl-auth-login[1]
+
+include::include/footer.asciidoc[]
diff --git a/doc/man/pkgctl-auth.1.asciidoc b/doc/man/pkgctl-auth.1.asciidoc
new file mode 100644
index 0000000..4912b02
--- /dev/null
+++ b/doc/man/pkgctl-auth.1.asciidoc
@@ -0,0 +1,38 @@
+pkgctl-auth(1)
+==============
+
+Name
+----
+pkgctl-auth - Authenticate with serivces like GitLab.
+
+Synopsis
+--------
+pkgctl auth [OPTIONS] [SUBCOMMAND]
+
+Description
+-----------
+
+Manage the authorization for the GitLab instance and show its current status.
+
+Options
+-------
+
+*-h, --help*::
+ Show a help text
+
+Subcommands
+-----------
+
+pkgctl auth login::
+ Authenticate with the GitLab instance
+
+pkgctl auth status::
+ View authentication status
+
+See Also
+--------
+
+linkman:pkgctl-auth-login[1]
+linkman:pkgctl-auth-status[1]
+
+include::include/footer.asciidoc[]
diff --git a/doc/man/pkgctl-build.1.asciidoc b/doc/man/pkgctl-build.1.asciidoc
new file mode 100644
index 0000000..f68e7cf
--- /dev/null
+++ b/doc/man/pkgctl-build.1.asciidoc
@@ -0,0 +1,91 @@
+pkgctl-build(1)
+===============
+
+Name
+----
+pkgctl-build - Build packages inside a clean chroot
+
+Synopsis
+--------
+pkgctl build [OPTIONS] [PATH...]
+
+Description
+-----------
+
+TODO
+
+Build Options
+-------------
+
+*--arch* 'ARCH'::
+ Specify architectures to build for (disables auto-detection)
+
+*--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
+
+*-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
+ is automatically assigned to the current tty pts number. In case the caller
+ is not a tty, choose a random slot between 1 and number of available
+ processing units.
+
+*--nocheck*::
+ Do not run the check() function in the PKGBUILD
+
+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
+
+*-e, --edit*::
+ Edit the PKGBUILD before building
+
+Release Options
+---------------
+
+*-r, --release*::
+ Automatically commit, tag and release after building +
+ Specifying this option is required when using any of the following options
+ in this section
+
+*-m, --message* 'MSG'::
+ Use the given <msg> as the commit message
+
+*-u, --db-update*::
+ Automatically update the pacman database as last action
+
+Options
+-------
+
+*-h, --help*::
+ Show a help text
+
+See Also
+--------
+
+linkman:pkgctl-release[1]
+linkman:pkgctl-db-update[1]
+
+include::include/footer.asciidoc[]
diff --git a/doc/man/pkgctl-db-move.1.asciidoc b/doc/man/pkgctl-db-move.1.asciidoc
new file mode 100644
index 0000000..1ee02f8
--- /dev/null
+++ b/doc/man/pkgctl-db-move.1.asciidoc
@@ -0,0 +1,24 @@
+pkgctl-db-move(1)
+=================
+
+Name
+----
+pkgctl-db-update - Update the binary repository as final release step
+
+Synopsis
+--------
+pkgctl db update [OPTIONS]
+
+Description
+-----------
+
+Update the pacman database as final release step for packages that
+have been transfered and staged on 'repos.archlinux.org'.
+
+Options
+-------
+
+*-h, --help*::
+ Show a help text
+
+include::include/footer.asciidoc[]
diff --git a/doc/man/pkgctl-db-remove.1.asciidoc b/doc/man/pkgctl-db-remove.1.asciidoc
new file mode 100644
index 0000000..a95766d
--- /dev/null
+++ b/doc/man/pkgctl-db-remove.1.asciidoc
@@ -0,0 +1,26 @@
+pkgctl-db-remove(1)
+===================
+
+Name
+----
+pkgctl-db-remove - Remove packages from binary repositories
+
+Synopsis
+--------
+pkgctl db remove [OPTIONS] [REPO] [PKGBASE]...
+
+Description
+-----------
+
+Remove packages from pacman repositories.
+
+Options
+-------
+
+*-a, --arch* 'ARCH'::
+ Override the architecture (disables auto-detection)
+
+*-h, --help*::
+ Show a help text
+
+include::include/footer.asciidoc[]
diff --git a/doc/man/pkgctl-db-update.1.asciidoc b/doc/man/pkgctl-db-update.1.asciidoc
new file mode 100644
index 0000000..fa7205e
--- /dev/null
+++ b/doc/man/pkgctl-db-update.1.asciidoc
@@ -0,0 +1,23 @@
+pkgctl-db-move(1)
+=================
+
+Name
+----
+pkgctl-db-move - Move packages between binary repositories
+
+Synopsis
+--------
+pkgctl db move [OPTIONS] [SOURCE_REPO] [TARGET_REPO] [PKGBASE]...
+
+Description
+-----------
+
+Move packages between pacman repositories.
+
+Options
+-------
+
+*-h, --help*::
+ Show a help text
+
+include::include/footer.asciidoc[]
diff --git a/doc/man/pkgctl-diff.1.asciidoc b/doc/man/pkgctl-diff.1.asciidoc
new file mode 100644
index 0000000..7eb9e68
--- /dev/null
+++ b/doc/man/pkgctl-diff.1.asciidoc
@@ -0,0 +1,73 @@
+pkgctl-diff(1)
+==============
+
+Name
+----
+pkgctl-diff - Compare package files using different modes.
+
+Synopsis
+--------
+pkgctl diff [OPTIONS] [MODES] [FILE|PKGNAME...]
+
+Description
+-----------
+
+Searches for a locally built package corresponding to the PKGBUILD, and
+downloads the last version of that package from the Pacman repositories.
+It then compares the package archives using different modes while using
+simple tar content list by default.
+
+When given one package, use it to diff against the locally built one.
+When given two packages, diff both packages against each other.
+
+In either case, a package name will be converted to a filename from the cache
+or pool, and 'pkgctl diff' will proceed as though this filename was initially
+specified.
+
+Options
+-------
+
+*-M, --makepkg-config*::
+ Set an alternate makepkg configuration file
+
+*-P, --pool*='DIR'::
+ Search diff target in pool dir (default `'/srv/ftp/pool'`)
+
+*-v, --verbose*::
+ Provide more detailed/unfiltered output
+
+*-h, --help*::
+ Show a help text
+
+Output Options
+--------------
+
+*--color*[='WHEN']::
+ Color output; 'WHEN' is `'never'`, `'always'`, or `'auto'`; Plain *--color* means *--color='auto'*
+
+*-u, -U, --unified*::
+ Output 3 lines of unified context
+
+*-y, --side-by-side*::
+ Output in two columns
+
+*-W, --width*[='NUM']::
+ Output at most 'NUM' (default `'auto'`) print columns; 'NUM' can be `'auto'`, `'columns'` or a number.
+ `'auto'` will be resolved to the maximum line length of both files, guaranteeing the diff to be uncut.
+
+Modes
+-----
+
+*-l, --list*::
+ Activate tar content list diff mode (default)
+
+*-d, --diffoscope*::
+ Activate diffoscope diff mode
+
+*-p, --pkginfo*::
+ Activate .PKGINFO diff mode
+
+*-b, --buildinfo*::
+ Activate .BUILDINFO diff mode
+
+include::include/footer.asciidoc[]
diff --git a/doc/man/pkgctl-release.1.asciidoc b/doc/man/pkgctl-release.1.asciidoc
new file mode 100644
index 0000000..c991db4
--- /dev/null
+++ b/doc/man/pkgctl-release.1.asciidoc
@@ -0,0 +1,49 @@
+pkgctl-release(1)
+=================
+
+Name
+----
+pkgctl-release - Release step to commit, tag and upload build artifacts
+
+Synopsis
+--------
+pkgctl release [OPTIONS] [PATH...]
+
+Description
+-----------
+
+Modified version controlled files will first be staged for commit,
+afterwards a Git tag matching the pkgver will be created and finally
+all build artifacts will be uploaded.
+
+By default the target pacman repository will be auto-detected by querying
+the repo it is currently released in. When initially adding a new package
+to the repositories, the target repo must be specified manually.
+
+Options
+-------
+
+*-m, --message* 'MSG'::
+ Use the given <msg> as the commit message
+
+*-r, --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
+
+*-u, --db-update*::
+ Automatically update the pacman database after uploading
+
+*-h, --help*::
+ Show a help text
+
+See Also
+--------
+
+linkman:pkgctl-db-update[1]
+
+include::include/footer.asciidoc[]
diff --git a/doc/man/pkgctl-repo-clone.1.asciidoc b/doc/man/pkgctl-repo-clone.1.asciidoc
new file mode 100644
index 0000000..421c71f
--- /dev/null
+++ b/doc/man/pkgctl-repo-clone.1.asciidoc
@@ -0,0 +1,52 @@
+pkgctl-repo-clone(1)
+====================
+
+Name
+----
+pkgctl-repo-clone - Clone a package repository
+
+Synopsis
+--------
+pkgctl repo clone [OPTIONS] [PKGNAME...]
+
+Description
+-----------
+
+Clone Git packaging repositories from the canonical namespace.
+
+The configure command is subsequently invoked to synchronize the distro
+specs and makepkg.conf settings. The unprivileged option can be used
+for cloning packaging repositories without SSH access using read-only
+HTTPS.
+
+Options
+-------
+
+*-m, --maintainer* 'NAME'::
+ Clone all packages of the named maintainer
+
+*--protocol* 'https'::
+ Clone the repository over https
+
+*--universe*::
+ Clone all existing packages, useful for cache warming
+
+*--switch* 'VERSION'::
+ Switch to a specified version. The working tree and the index are updated to
+ match the version.
+
+*-j, --jobs* 'N'::
+ Run up to N jobs in parallel. By default the number of jobs is equal to the
+ number of available processing units. For sequential processing this option
+ needs to be passed with 1.
+
+*-h, --help*::
+ Show a help text
+
+See Also
+--------
+
+linkman:pkgctl-repo-configure[1]
+linkman:pkgctl-repo-switch[1]
+
+include::include/footer.asciidoc[]
diff --git a/doc/man/pkgctl-repo-configure.1.asciidoc b/doc/man/pkgctl-repo-configure.1.asciidoc
new file mode 100644
index 0000000..6bdea93
--- /dev/null
+++ b/doc/man/pkgctl-repo-configure.1.asciidoc
@@ -0,0 +1,39 @@
+pkgctl-repo-configure(1)
+========================
+
+Name
+----
+pkgctl-repo-configure - Configure a clone according to distro specs
+
+Synopsis
+--------
+pkgctl repo configure [OPTIONS] [PATH...]
+
+Description
+-----------
+
+Configure Git packaging repositories according to distro specs and
+'makepkg.conf' settings.
+
+Git author information and the used signing key is set up from
+'makepkg.conf' read from any valid location like '/etc' or 'XDG_CONFIG_HOME'.
+
+The remote protocol is automatically determined from the author email
+address by choosing SSH for all official packager identities and
+read-only HTTPS otherwise.
+
+Options
+-------
+
+*--protocol* 'https'::
+ Configure remote url to use https
+
+*-j, --jobs* 'N'::
+ Run up to N jobs in parallel. By default the number of jobs is equal to the
+ number of available processing units. For sequential processing this option
+ needs to be passed with 1.
+
+*-h, --help*::
+ Show a help text
+
+include::include/footer.asciidoc[]
diff --git a/doc/man/pkgctl-repo-create.1.asciidoc b/doc/man/pkgctl-repo-create.1.asciidoc
new file mode 100644
index 0000000..7c58776
--- /dev/null
+++ b/doc/man/pkgctl-repo-create.1.asciidoc
@@ -0,0 +1,40 @@
+pkgctl-repo-create(1)
+=====================
+
+Name
+----
+pkgctl-repo-create - Create a new GitLab package repository
+
+Synopsis
+--------
+pkgctl repo create [OPTIONS] [PKGBASE...]
+
+Description
+-----------
+
+Create a new Git packaging repository in the canonical GitLab namespace.
+
+This command requires a valid GitLab API authentication. To setup a new
+GitLab token or check the currently configured one please consult the
+'auth' subcommand for further instructions.
+
+If invoked without a parameter, try to create a packaging repository
+based on the 'PKGBUILD' from the current working directory.
+
+Options
+-------
+
+*-c, --clone*::
+ Clone the Git repository after creation
+
+*-h, --help*::
+ Show a help text
+
+See Also
+--------
+
+linkman:pkgctl-auth[1]
+linkman:pkgctl-repo-clone[1]
+linkman:pkgctl-repo-configure[1]
+
+include::include/footer.asciidoc[]
diff --git a/doc/man/pkgctl-repo-switch.1.asciidoc b/doc/man/pkgctl-repo-switch.1.asciidoc
new file mode 100644
index 0000000..ac12019
--- /dev/null
+++ b/doc/man/pkgctl-repo-switch.1.asciidoc
@@ -0,0 +1,36 @@
+pkgctl-repo-switch(1)
+=====================
+
+Name
+----
+pkgctl-repo-switch - Switch a package repository to a specified version
+
+Synopsis
+--------
+pkgctl repo switch [OPTIONS] [VERSION] [PKGBASE]...
+
+Description
+-----------
+
+Switch a package source repository to a specified version, tag or branch.
+The working tree and the index are updated to match the specified ref.
+
+If a version identifier is specified in the pacman version format, that
+identifier is automatically translated to the Git tag name accordingly.
+
+The current working directory is used if no PKGBASE is specified.
+
+Options
+-------
+
+*--discard-changes*::
+ Proceed even if the index or the working tree differs from HEAD. Both the
+ index and working tree are restored to match the switching target.
+
+*-f, --force*::
+ An alias for '--discard-changes'.
+
+*-h, --help*::
+ Show a help text
+
+include::include/footer.asciidoc[]
diff --git a/doc/man/pkgctl-repo-web.1.asciidoc b/doc/man/pkgctl-repo-web.1.asciidoc
new file mode 100644
index 0000000..8769be7
--- /dev/null
+++ b/doc/man/pkgctl-repo-web.1.asciidoc
@@ -0,0 +1,24 @@
+pkgctl-repo-web(1)
+==================
+
+Name
+----
+pkgctl-repo-web - Open the packaging repository's website
+
+Synopsis
+--------
+pkgctl repo web [OPTIONS] [PKGBASE...]
+
+Description
+-----------
+
+Open the packaging repository's website via xdg-open. If called with
+no arguments, open the package cloned in the current working directory.
+
+Options
+-------
+
+*-h, --help*::
+ Show a help text
+
+include::include/footer.asciidoc[]
diff --git a/doc/man/pkgctl-repo.1.asciidoc b/doc/man/pkgctl-repo.1.asciidoc
new file mode 100644
index 0000000..57be170
--- /dev/null
+++ b/doc/man/pkgctl-repo.1.asciidoc
@@ -0,0 +1,59 @@
+pkgctl-repo(1)
+==============
+
+Name
+----
+pkgctl-repo - Manage Git packaging repositories and their configuration
+
+Synopsis
+--------
+pkgctl repo [OPTIONS] [SUBCOMMAND]
+
+Description
+-----------
+
+Manage Git packaging repositories and helps with their configuration
+according to distro specs.
+
+Git author information and the used signing key is set up from
+'makepkg.conf' read from any valid location like '/etc' or 'XDG_CONFIG_HOME'.
+The configure command can be used to synchronize the distro specs and
+makepkg.conf settings for previously cloned repositories.
+
+The unprivileged option can be used for cloning packaging repositories
+without SSH access using read-only HTTPS.
+
+Options
+-------
+
+*-h, --help*::
+ Show a help text
+
+Subcommands
+-----------
+
+pkgctl repo clone::
+ Clone a package repository
+
+pkgctl repo configure::
+ Configure a clone according to distro specs
+
+pkgctl repo create::
+ Create a new GitLab package repository
+
+pkgctl repo switch::
+ Switch a package repository to a specified version
+
+pkgctl repo web::
+ Open the packaging repository's website
+
+See Also
+--------
+
+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[]
diff --git a/doc/man/pkgctl-version.1.asciidoc b/doc/man/pkgctl-version.1.asciidoc
new file mode 100644
index 0000000..9beebf5
--- /dev/null
+++ b/doc/man/pkgctl-version.1.asciidoc
@@ -0,0 +1,23 @@
+pkgctl-version(1)
+=================
+
+Name
+----
+pkgctl-version - Show pkgctl version information
+
+Synopsis
+--------
+pkgctl version [OPTIONS]
+
+Description
+-----------
+
+Shows the current version information of pkgctl.
+
+Options
+-------
+
+*-h, --help*::
+ Show a help text
+
+include::include/footer.asciidoc[]
diff --git a/doc/man/pkgctl.1.asciidoc b/doc/man/pkgctl.1.asciidoc
new file mode 100644
index 0000000..72cda1e
--- /dev/null
+++ b/doc/man/pkgctl.1.asciidoc
@@ -0,0 +1,61 @@
+pkgctl(1)
+=========
+
+Name
+----
+pkgctl - Unified command-line frontend for devtools
+
+Synopsis
+--------
+pkgctl [SUBCOMMAND] [OPTIONS]
+
+Description
+-----------
+
+TODO
+
+Options
+-------
+
+*-V, --version*::
+ Show pkgctl version information
+
+*-h, --help*::
+ Show a help text
+
+Subcommands
+-----------
+
+pkgctl auth::
+ Authenticate with services like GitLab
+
+pkgctl build::
+ Build packages inside a clean chroot
+
+pkgctl db::
+ Pacman database modification for packge update, move etc
+
+pkgctl diff::
+ Compare package files using different modes
+
+pkgctl release::
+ Release step to commit, tag and upload build artifacts
+
+pkgctl repo::
+ Manage Git packaging repositories and their configuration
+
+pkgctl version::
+ Show pkgctl version information
+
+See Also
+--------
+
+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[]
diff --git a/lib/valid-repos.sh b/lib/valid-repos.sh
deleted file mode 100644
index 9ac9639..0000000
--- a/lib/valid-repos.sh
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/hint/bash
-#
-# SPDX-License-Identifier: GPL-3.0-or-later
-:
-
-# shellcheck disable=2034
-_repos=(
- staging
- testing
- core
- extra
- community-staging
- community-testing
- community
- multilib-staging
- multilib-testing
- multilib
- gnome-unstable
- kde-unstable
-)
-
-# shellcheck disable=2034
-_build_repos=(
- staging
- testing
- extra
- multilib-staging
- multilib-testing
- multilib
- gnome-unstable
- kde-unstable
-)
diff --git a/lib/valid-tags.sh b/lib/valid-tags.sh
deleted file mode 100644
index 0e8366e..0000000
--- a/lib/valid-tags.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/hint/bash
-#
-# SPDX-License-Identifier: GPL-3.0-or-later
-:
-
-# shellcheck disable=2034
-_arch=(
- i686
- x86_64
- any
-)
-
-# shellcheck disable=2034
-_tags=(
- core-i686 core-x86_64 core-any
- extra-i686 extra-x86_64 extra-any
- multilib-x86_64
- staging-i686 staging-x86_64 staging-any
- testing-i686 testing-x86_64 testing-any
- multilib-testing-x86_64
- multilib-staging-x86_64
- community-i686 community-x86_64 community-any
- community-staging-i686 community-staging-x86_64 community-staging-any
- community-testing-i686 community-testing-x86_64 community-testing-any
- kde-unstable-i686 kde-unstable-x86_64 kde-unstable-any
- gnome-unstable-i686 gnome-unstable-x86_64 gnome-unstable-any
-)
diff --git a/src/arch-nspawn.in b/src/arch-nspawn.in
index ae50043..11af616 100644
--- a/src/arch-nspawn.in
+++ b/src/arch-nspawn.in
@@ -2,8 +2,12 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
-m4_include(lib/common.sh)
-m4_include(lib/archroot.sh)
+_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+# shellcheck source=src/lib/common.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
+# shellcheck source=src/lib/archroot.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/archroot.sh
+
# umask might have been changed in /etc/profile
# ensure that sane default is set again
@@ -28,6 +32,9 @@ usage() {
exit 1
}
+# save all args for check_root
+orig_args=("$@")
+
while getopts 'hC:M:c:f:s' arg; do
case "$arg" in
C) pac_conf="$OPTARG" ;;
@@ -42,7 +49,7 @@ done
shift $((OPTIND - 1))
(( $# < 1 )) && die 'You must specify a directory.'
-check_root
+check_root "" "${BASH_SOURCE[0]}" "${orig_args[@]}"
working_dir=$(readlink -f "$1")
shift 1
@@ -54,7 +61,7 @@ if (( ${#cache_dirs[@]} == 0 )); then
fi
# shellcheck disable=2016
-host_mirrors=($(pacman-conf --config "${pac_conf:-$working_dir/etc/pacman.conf}" --repo extra Server 2> /dev/null | sed -r 's#(.*/)extra/os/.*#\1$repo/os/$arch#;t;s#(.*/)[^/]+/extra(/?)$#\1$arch/$repo\2#'))
+host_mirrors=($(pacman-conf --repo extra Server 2> /dev/null | sed -r 's#(.*/)extra/os/.*#\1$repo/os/$arch#'))
for host_mirror in "${host_mirrors[@]}"; do
if [[ $host_mirror == *file://* ]]; then
diff --git a/src/archbuild.in b/src/archbuild.in
index a5eb9a0..d023e0d 100644
--- a/src/archbuild.in
+++ b/src/archbuild.in
@@ -2,8 +2,12 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
-m4_include(lib/common.sh)
-m4_include(lib/archroot.sh)
+_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+# shellcheck source=src/lib/common.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
+# shellcheck source=src/lib/archroot.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/archroot.sh
+
base_packages=(base-devel)
makechrootpkg_args=(-c -n -C)
@@ -23,16 +27,32 @@ if [[ -f "@pkgdatadir@/setarch-aliases.d/${arch}" ]]; then
else
set_arch="${arch}"
fi
+
+# Architecture-specific Mount
+arch_mounts=()
+if [[ -f "@pkgdatadir@/mount.d/${arch}" ]]; then
+ mapfile -t arch_mounts < "@pkgdatadir@/mount.d/${arch}"
+fi
+for arch_mount in "${arch_mounts[@]}"; do
+ if [[ $arch_mount = rw* ]]; then
+ arch_mount=${arch_mount#rw }
+ in_array "$arch_mount" "${makechrootpkg_args[@]}" || makechrootpkg_args+=("-d" "$arch_mount")
+ elif [[ $arch_mount = ro* ]]; then
+ arch_mount=${arch_mount#ro }
+ in_array "$arch_mount" "${makechrootpkg_args[@]}" || makechrootpkg_args+=("-D" "$arch_mount")
+ fi
+done
+
chroots='/var/lib/archbuild'
clean_first=false
-pacman_config="@pkgdatadir@/pacman-${repo}.conf"
-if [[ -f @pkgdatadir@/pacman-${repo}-${arch}.conf ]]; then
- pacman_config="@pkgdatadir@/pacman-${repo}-${arch}.conf"
+pacman_config="@pkgdatadir@/pacman.conf.d/${repo}.conf"
+if [[ -f @pkgdatadir@/pacman.conf.d/${repo}-${arch}.conf ]]; then
+ pacman_config="@pkgdatadir@/pacman.conf.d/${repo}-${arch}.conf"
fi
-makepkg_config="@pkgdatadir@/makepkg-${arch}.conf"
-if [[ -f @pkgdatadir@/makepkg-${repo}-${arch}.conf ]]; then
- makepkg_config="@pkgdatadir@/makepkg-${repo}-${arch}.conf"
+makepkg_config="@pkgdatadir@/makepkg.conf.d/${arch}.conf"
+if [[ -f @pkgdatadir@/makepkg.conf.d/${repo}-${arch}.conf ]]; then
+ makepkg_config="@pkgdatadir@/makepkg.conf.d/${repo}-${arch}.conf"
fi
usage() {
@@ -54,7 +74,7 @@ while getopts 'hcr:' arg; do
esac
done
-check_root SOURCE_DATE_EPOCH,SRCDEST,SRCPKGDEST,PKGDEST,LOGDEST,MAKEFLAGS,PACKAGER,GNUPGHOME,PKGEXT
+check_root SOURCE_DATE_EPOCH,SRCDEST,SRCPKGDEST,PKGDEST,LOGDEST,MAKEFLAGS,PACKAGER,GNUPGHOME "${BASH_SOURCE[0]}" "$@"
if [ "${arch}" = "x86_64" ]; then
cache_dir=''
diff --git a/src/archco.in b/src/archco.in
deleted file mode 100644
index a93d819..0000000
--- a/src/archco.in
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/bin/bash
-#
-# SPDX-License-Identifier: GPL-3.0-or-later
-
-m4_include(lib/common.sh)
-
-scriptname=${0##*/}
-
-if [[ -z $1 ]]; then
- printf 'Usage: %s <package name>...\n' "$scriptname"
- exit 1
-fi
-
-case $scriptname in
- archco)
- SVNURL="svn+ssh://svn-packages@repos.archlinux.org/srv/repos/svn-packages/svn";;
- communityco)
- SVNURL="svn+ssh://svn-community@repos.archlinux.org/srv/repos/svn-community/svn";;
- *)
- die "Couldn't find svn url for %s" "$scriptname"
- ;;
-esac
-
-for i in "$@"; do
- svn co "$SVNURL/$i"
-done
diff --git a/src/archrelease.in b/src/archrelease.in
index 3490ee2..818b0ca 100644
--- a/src/archrelease.in
+++ b/src/archrelease.in
@@ -2,8 +2,19 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
-m4_include(lib/common.sh)
-m4_include(lib/valid-tags.sh)
+_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+# shellcheck source=src/lib/common.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
+# shellcheck source=src/lib/valid-tags.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-tags.sh
+
+set -e
+
+
+# Deprecation warning
+if [[ -z $_DEVTOOLS_COMMAND ]]; then
+ warning "${0##*/} is deprecated and will be removed. Use 'pkgctl release' instead"
+fi
# parse command line options
FORCE=
@@ -34,54 +45,50 @@ if [[ ! -f PKGBUILD ]]; then
die 'archrelease: PKGBUILD not found'
fi
-trunk=${PWD##*/}
+# shellcheck source=contrib/makepkg/PKGBUILD.proto
+. ./PKGBUILD
+pkgbase=${pkgbase:-$pkgname}
+pkgver=$(get_full_version "$pkgbase")
+gittag=$(get_tag_from_pkgver "$pkgver")
-# Normally this should be trunk, but it may be something
-# such as 'gnome-unstable'
-IFS='/' read -r -d '' -a parts <<< "$PWD"
-if [[ "${parts[*]:(-2):1}" == "repos" ]]; then
- die 'archrelease: Should not be in repos dir (try from trunk/)'
+# Check if releasing from a branch
+if ! branchname=$(git symbolic-ref --short HEAD); then
+ die 'not on any branch'
fi
-unset parts
-
-if [[ $(svn status -q) ]]; then
- die 'archrelease: You have not committed your changes yet!'
+if [[ "${branchname}" != main ]]; then
+ die 'must be run from the main branch'
fi
-pushd .. >/dev/null
-mapfile -t known_files < <(svn ls -r HEAD "$trunk")
-wait $! || die "failed to discover committed files"
-
-# gracefully handle files containing an "@" character
-known_files=("${known_files[@]/%/@}")
-
-# update repo directory first to avoid a commit failure
-svn up repos
+# Check if remote origin is setup properly
+if ! giturl=$(git remote get-url origin) || [[ ${giturl} != *${GIT_PACKAGING_URL_SSH}* ]]; then
+ die "remote origin is not configured, run 'pkgctl repo configure'"
+fi
+if ! git ls-remote origin >/dev/null; then
+ die "configured remote origin may not exist, run 'pkgctl repo create ${pkgbase}' to create it"
+fi
-for tag in "$@"; do
- stat_busy "Copying %s to %s" "${trunk}" "${tag}"
+msg 'Fetching remote changes'
+git fetch --prune --prune-tags origin || die 'failed to fetch remote changes'
- if [[ -d repos/$tag ]]; then
- mapfile -t trash < <(svn ls --recursive "repos/$tag")
- wait $! || die "failed to discover existing files"
- if (( ${#trash[@]} )); then
- trash=("${trash[@]/#/repos/$tag/}")
- svn rm -q "${trash[@]/%/@}"
- fi
- else
- mkdir -p "repos/$tag"
- svn add --parents -q "repos/$tag"
+# Check if local branch is up to date and contains the latest origin commit
+if remoteref=$(git rev-parse "origin/${branchname}" 2>/dev/null); then
+ if [[ $(git branch "${branchname}" --contains "${remoteref}" --format '%(refname:short)') != "${branchname}" ]]; then
+ die "local branch is out of date, run 'git pull --rebase'"
fi
+fi
- # copy all files at once from trunk to the subdirectory in repos/
- svn copy -q -r HEAD "${known_files[@]/#/$trunk/}" "repos/$tag/"
-
- stat_done
-done
-
-stat_busy "Releasing package"
-printf -v tag_list ", %s" "$@"; tag_list="${tag_list#, }"
-svn commit -q -m "archrelease: copy ${trunk} to $tag_list" || abort
-stat_done
+# If the tag exists we check if it's properly signed and that it
+# matches the working directory PKGBUILD.
+if git tag --verify "$gittag" &> /dev/null; then
+ cwd_checksum=$(sha256sum PKGBUILD|cut -d' ' -f1)
+ tag_checksum=$(git show "${gittag}:PKGBUILD" | sha256sum |cut -d' ' -f1)
+ 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
+ exit 0
+fi
-popd >/dev/null
+msg "Releasing package"
+git tag --sign --message="Package release ${pkgver}" "$gittag" || abort
+git push --tags --set-upstream origin main || abort
diff --git a/src/checkpkg.in b/src/checkpkg.in
index fe5b71a..ccb7259 100644
--- a/src/checkpkg.in
+++ b/src/checkpkg.in
@@ -2,7 +2,10 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
-m4_include(lib/common.sh)
+_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+# shellcheck source=src/lib/common.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
+
usage() {
cat <<- _EOF_
diff --git a/src/commitpkg.in b/src/commitpkg.in
index 235d12b..8a8087a 100644
--- a/src/commitpkg.in
+++ b/src/commitpkg.in
@@ -2,7 +2,39 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
-m4_include(lib/common.sh)
+_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
+
+
+check_pkgbuild_validity() {
+ # shellcheck source=contrib/makepkg/PKGBUILD.proto
+ . ./PKGBUILD
+
+ # skip when there are no sources available
+ if (( ! ${#source[@]} )); then
+ return
+ fi
+
+ # validate sources hash algo is at least > sha1
+ local bad_algos=("cksums" "md5sums" "sha1sums")
+ local good_hash_algo=false
+
+ # from makepkg libmakepkg/util/schema.sh
+ for integ in "${known_hash_algos[@]}"; do
+ local sumname="${integ}sums"
+ if [[ -n ${!sumname} ]] && ! in_array "${sumname}" "${bad_algos[@]}"; then
+ good_hash_algo=true
+ break
+ fi
+ done
+
+ if ! $good_hash_algo; then
+ die "PKGBUILD lacks a secure cryptographic checksum, insecure algorithms: ${bad_algos[*]}"
+ fi
+}
# Source makepkg.conf; fail if it is not found
if [[ -r '/etc/makepkg.conf' ]]; then
@@ -23,10 +55,25 @@ fi
cmd=${0##*/}
+# Deprecation warning
+if [[ -z $_DEVTOOLS_COMMAND ]]; then
+ warning "${cmd} is deprecated and will be removed. Use 'pkgctl release' instead"
+fi
+
if [[ ! -f PKGBUILD ]]; then
die 'No PKGBUILD file'
fi
+if ! repo_spec=$(git config --local devtools.version) || [[ ${repo_spec} != "${GIT_REPO_SPEC_VERSION}" ]]; then
+ error "repository specs are out of date, try:"
+ msg2 'pkgctl repo configure'
+ exit 1
+fi
+
+if [[ "$(git symbolic-ref --short HEAD)" != main ]]; then
+ die 'must be run from the main branch'
+fi
+
source=()
# shellcheck source=contrib/makepkg/PKGBUILD.proto
. ./PKGBUILD
@@ -60,7 +107,7 @@ if (( ${#validpgpkeys[@]} != 0 )); then
export-pkgbuild-keys || die 'Failed to export valid PGP keys for source files'
fi
- svn add --parents --force keys/pgp/*
+ git add --force -- keys/pgp/*
fi
# find files which should be under source control
@@ -79,15 +126,21 @@ for key in "${validpgpkeys[@]}"; do
needsversioning+=("keys/pgp/$key.asc")
done
-# assert that they really are controlled by SVN
+# assert that they really are controlled by git
if (( ${#needsversioning[*]} )); then
- # svn status's output is only two columns when the status is unknown
- while read -r status filename; do
- [[ $status = '?' ]] && unversioned+=("$filename")
- done < <(svn status -v "${needsversioning[@]}")
- (( ${#unversioned[*]} )) && die "%s is not under version control" "${unversioned[@]}"
+ for file in "${needsversioning[@]}"; do
+ # skip none existing files
+ if [[ ! -f "${file}" ]]; then
+ continue
+ fi
+ if ! git ls-files --error-unmatch "$file"; then
+ die "%s is not under version control" "$file"
+ fi
+ done
fi
+
+server=${PACKAGING_REPO_RELEASE_HOST}
rsyncopts=(-e ssh -p '--chmod=ug=rw,o=r' -c -h -L --progress --partial -y)
archreleaseopts=()
while getopts ':l:a:s:f' flag; do
@@ -121,31 +174,50 @@ for _arch in "${arch[@]}"; do
fi
done
-if [[ -z $server ]]; then
- server='repos.archlinux.org'
+# check for PKGBUILD standards
+check_pkgbuild_validity
+
+# auto generate .SRCINFO if present
+if [[ -f .SRCINFO ]]; then
+ stat_busy 'Generating .SRCINFO'
+ makepkg --printsrcinfo > .SRCINFO
+ git add .SRCINFO
+ stat_done
fi
-if [[ -n $(svn status -q) ]]; then
- msgtemplate="upgpkg: $pkgbase $(get_full_version)"
+if [[ -n $(git status --porcelain --untracked-files=no) ]]; then
+ stat_busy 'Staging files'
+ for f in $(git ls-files --modified); do
+ git add "$f"
+ done
+ for f in $(git ls-files --deleted); do
+ git rm "$f"
+ done
+ stat_done
+
+ msgtemplate="upgpkg: $(get_full_version)"
if [[ -n $1 ]]; then
- stat_busy 'Committing changes to trunk'
- svn commit -q -m "${msgtemplate}: ${1}" || die
+ stat_busy 'Committing changes'
+ git commit -q -m "${msgtemplate}: ${1}" || die
stat_done
else
- msgfile="$(mktemp)"
+ [[ -z ${WORKDIR:-} ]] && setup_workdir
+ msgfile=$(mktemp --tmpdir="${WORKDIR}" commitpkg.XXXXXXXXXX)
echo "$msgtemplate" > "$msgfile"
- if [[ -n $SVN_EDITOR ]]; then
- $SVN_EDITOR "$msgfile"
+ if [[ -n $GIT_EDITOR ]]; then
+ $GIT_EDITOR "$msgfile" || die
elif [[ -n $VISUAL ]]; then
- $VISUAL "$msgfile"
+ $VISUAL "$msgfile" || die
elif [[ -n $EDITOR ]]; then
- $EDITOR "$msgfile"
+ $EDITOR "$msgfile" || die
+ elif giteditor=$(git config --get core.editor); then
+ $giteditor "$msgfile" || die
else
- vi "$msgfile"
+ die "No usable editor found (tried \$GIT_EDITOR, \$VISUAL, \$EDITOR, git config [core.editor])."
fi
[[ -s $msgfile ]] || die
- stat_busy 'Committing changes to trunk'
- svn commit -q -F "$msgfile" || die
+ stat_busy 'Committing changes'
+ git commit -v -q -F "$msgfile" || die
unlink "$msgfile"
stat_done
fi
@@ -219,23 +291,3 @@ if [[ ${#uploads[*]} -gt 0 ]]; then
msg 'Uploading all package and signature files'
rsync "${rsyncopts[@]}" "${uploads[@]}" "$server:staging/$repo/" || die
fi
-
-if [[ "${arch[*]}" == 'any' ]]; then
- if [[ -d ../repos/$repo-x86_64 ]]; then
- pushd ../repos/ >/dev/null
- stat_busy "Removing %s" "$repo-x86_64"
- svn rm -q "$repo-x86_64"
- svn commit -q -m "Removed $repo-x86_64 for $pkgname"
- stat_done
- popd >/dev/null
- fi
-else
- if [[ -d ../repos/$repo-any ]]; then
- pushd ../repos/ >/dev/null
- stat_busy "Removing %s" "$repo-any"
- svn rm -q "$repo-any"
- svn commit -q -m "Removed $repo-any for $pkgname"
- stat_done
- popd >/dev/null
- fi
-fi
diff --git a/src/crossrepomove.in b/src/crossrepomove.in
deleted file mode 100644
index 08a3067..0000000
--- a/src/crossrepomove.in
+++ /dev/null
@@ -1,91 +0,0 @@
-#!/bin/bash
-#
-# SPDX-License-Identifier: GPL-3.0-or-later
-
-m4_include(lib/common.sh)
-
-scriptname=${0##*/}
-
-if [[ -z $1 ]]; then
- printf 'Usage: %s [pkgbase]\n' "$scriptname"
- exit 1
-fi
-
-pkgbase="${1}"
-
-case $scriptname in
- extra2community)
- source_name='packages'
- target_name='community'
- source_repo='extra'
- target_repo='community'
- ;;
- community2extra)
- source_name='community'
- target_name='packages'
- source_repo='community'
- target_repo='extra'
- ;;
- *)
- die "Couldn't find configuration for %s" "$scriptname"
- ;;
-esac
-
-server='repos.archlinux.org'
-source_svn="svn+ssh://svn-${source_name}@${server}/srv/repos/svn-${source_name}/svn"
-target_svn="svn+ssh://svn-${target_name}@${server}/srv/repos/svn-${target_name}/svn"
-source_dbscripts="/srv/repos/svn-${source_name}/dbscripts"
-target_dbscripts="/srv/repos/svn-${target_name}/dbscripts"
-
-setup_workdir
-
-pushd "$WORKDIR" >/dev/null
-
-msg "Downloading sources for %s" "${pkgbase}"
-svn -q checkout -N "${target_svn}" target_checkout
-mkdir -p "target_checkout/${pkgbase}/repos"
-svn -q export "${source_svn}/${pkgbase}/trunk" "target_checkout/${pkgbase}/trunk" || die
-# shellcheck source=contrib/makepkg/PKGBUILD.proto
-. "target_checkout/${pkgbase}/trunk/PKGBUILD"
-
-msg "Downloading packages for %s" "${pkgbase}"
-for _arch in "${arch[@]}"; do
- if [[ "${_arch[*]}" == 'any' ]]; then
- repo_arch='x86_64'
- else
- repo_arch=${_arch}
- fi
- for _pkgname in "${pkgname[@]}"; do
- fullver=$(get_full_version "$_pkgname")
- pkgpath="/srv/ftp/${source_repo}/os/${repo_arch}/${_pkgname}-${fullver}-${_arch}.pkg.tar.*"
- debugpath="/srv/ftp/${source_repo}-debug/os/${repo_arch}/${_pkgname}-debug-${fullver}-${_arch}.pkg.tar.*"
- # Fail if $pkgpath doesn't match but keep $debugpath optional
- # shellcheck disable=2029
- ssh "${server}" "bash -c '
- install ${pkgpath} -Dt staging/${target_repo} &&
- (install ${debugpath} -Dt staging/${target_repo} 2>/dev/null || true)
- '" || die
- done
-done
-
-msg "Adding %s to %s" "${pkgbase}" "${target_repo}"
-svn -q add "target_checkout/${pkgbase}"
-svn -q commit -m"${scriptname}: Moving ${pkgbase} from ${source_repo} to ${target_repo}" target_checkout
-pushd "target_checkout/${pkgbase}/trunk" >/dev/null
-archrelease "${arch[@]/#/$target_repo-}" || die
-popd >/dev/null
-
-# shellcheck disable=2029
-ssh "${server}" "${target_dbscripts}/db-update" || die
-
-msg "Removing %s from %s" "${pkgbase}" "${source_repo}"
-for _arch in "${arch[@]}"; do
- # shellcheck disable=2029
- ssh "${server}" "${source_dbscripts}/db-remove ${source_repo} ${_arch} ${pkgbase}"
-done
-svn -q checkout -N "${source_svn}" source_checkout
-svn -q up "source_checkout/${pkgbase}"
-svn -q rm "source_checkout/${pkgbase}"
-svn -q commit -m"${scriptname}: Moving ${pkgbase} from ${source_repo} to ${target_repo}" source_checkout
-
-popd >/dev/null
diff --git a/src/diffpkg.in b/src/diffpkg.in
index 10b0904..160c4ba 100644
--- a/src/diffpkg.in
+++ b/src/diffpkg.in
@@ -2,11 +2,15 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
-m4_include(lib/common.sh)
+_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+# shellcheck source=src/lib/common.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
+
usage() {
- cat <<- _EOF_
- Usage: ${BASH_SOURCE[0]##*/} [OPTIONS] [MODES] [FILE|PKGNAME...]
+ local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
+ cat <<- _EOF_
+ Usage: ${COMMAND} [OPTIONS] [MODES] [FILE|PKGNAME...]
Searches for a locally built package corresponding to the PKGBUILD, and
downloads the last version of that package from the Pacman repositories.
@@ -17,8 +21,8 @@ usage() {
When given two packages, diff both packages against each other.
In either case, a package name will be converted to a filename from the
- cache, and diffpkg will proceed as though this filename was initially
- specified.
+ cache, and '${COMMAND}' will proceed as though this filename was
+ initially specified.
OPTIONS
-M, --makepkg-config Set an alternate makepkg configuration file
@@ -211,7 +215,8 @@ diff_pkgs() {
[[ -f $oldpkg ]] || die "No such file: %s" "${oldpkg}"
[[ -f $newpkg ]] || die "No such file: %s" "${newpkg}"
- DIFFOPTIONS+=(--label "${oldpkg}" --label "${newpkg}")
+ local -a diffoptions
+ diffoptions=("${DIFFOPTIONS[@]}" --label "${oldpkg}" --label "${newpkg}")
if (( TARLIST )); then
tar_list "$oldpkg" > "$TMPDIR/old"
@@ -232,7 +237,7 @@ diff_pkgs() {
# Resolve dynamic auto width one we know the content to diff
if [[ $DIFFWIDTH == --width=auto ]]; then
AUTOLENGTH=$(file_diff_columns "$TMPDIR/old" "$TMPDIR/new")
- DIFFOPTIONS+=("--width=${AUTOLENGTH}")
+ diffoptions+=("--width=${AUTOLENGTH}")
fi
# Print a header for side-by-side view as it lacks labels
@@ -240,7 +245,7 @@ diff_pkgs() {
printf -- "--- %s\n+++ %s\n" "${oldpkg}" "${newpkg}"
fi
- diff "${DIFFOPTIONS[@]}" "$TMPDIR/old" "$TMPDIR/new"
+ diff "${diffoptions[@]}" "$TMPDIR/old" "$TMPDIR/new"
fi
if (( DIFFOSCOPE )); then
@@ -248,6 +253,7 @@ diff_pkgs() {
fi
}
+shopt -s extglob
fetch_pkg() {
local pkg pkgdest pkgurl
case $1 in
@@ -295,10 +301,11 @@ fetch_pkg() {
echo "$pkgdest"
}
+shopt -u extglob
if (( $# < 2 )); then
if [[ ! -f PKGBUILD ]]; then
- die "This must be run in the directory of a built package.\nTry '$(basename "$0") --help' for more information."
+ die "This must be run in the directory of a built package.\nTry '${COMMAND} --help' for more information."
fi
# shellcheck source=contrib/makepkg/PKGBUILD.proto
diff --git a/src/export-pkgbuild-keys.in b/src/export-pkgbuild-keys.in
index 8697b3d..c19fc8b 100644
--- a/src/export-pkgbuild-keys.in
+++ b/src/export-pkgbuild-keys.in
@@ -2,7 +2,10 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
-m4_include(lib/common.sh)
+_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+# shellcheck source=src/lib/common.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
+
usage() {
cat <<- _EOF_
@@ -35,7 +38,7 @@ if [[ ! -f PKGBUILD ]]; then
fi
mapfile -t validpgpkeys < <(
- # shellcheck source=PKGBUILD.proto
+ # shellcheck source=contrib/makepkg/PKGBUILD.proto
. ./PKGBUILD
if (( ${#validpgpkeys[@]} )); then
printf "%s\n" "${validpgpkeys[@]}"
diff --git a/src/find-libdeps.in b/src/find-libdeps.in
index 5a11580..afdf0f5 100644
--- a/src/find-libdeps.in
+++ b/src/find-libdeps.in
@@ -2,7 +2,10 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
-m4_include(lib/common.sh)
+_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+# shellcheck source=src/lib/common.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
+
set -e
@@ -40,6 +43,7 @@ else
pushd "$WORKDIR" >/dev/null
fi
+shopt -s extglob
process_sofile() {
# extract the library name: libfoo.so
shopt -s extglob nullglob
@@ -56,6 +60,7 @@ process_sofile() {
soobjects+=("${soname}=${soversion}-${soarch}")
fi
}
+shopt -u extglob
case $script_mode in
deps) find_args=(-perm -u+x);;
diff --git a/src/finddeps.in b/src/finddeps.in
index da7cb85..20d7095 100644
--- a/src/finddeps.in
+++ b/src/finddeps.in
@@ -4,7 +4,10 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
-m4_include(lib/common.sh)
+_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+# shellcheck source=src/lib/common.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
+
match=$1
diff --git a/src/lddd.in b/src/lddd.in
index 12f8d67..80c22c4 100644
--- a/src/lddd.in
+++ b/src/lddd.in
@@ -4,7 +4,10 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
-m4_include(lib/common.sh)
+_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+# shellcheck source=src/lib/common.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
+
ifs=$IFS
IFS="${IFS}:"
diff --git a/src/lib/api/gitlab.sh b/src/lib/api/gitlab.sh
new file mode 100644
index 0000000..e5f4237
--- /dev/null
+++ b/src/lib/api/gitlab.sh
@@ -0,0 +1,132 @@
+#!/hint/bash
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+[[ -z ${DEVTOOLS_INCLUDE_API_GITLAB_SH:-} ]] || return 0
+DEVTOOLS_INCLUDE_API_GITLAB_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/config.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/config.sh
+
+set -e
+
+
+gitlab_api_call() {
+ local outfile=$1
+ local request=$2
+ local endpoint=$3
+ local data=${4:-}
+ local error
+
+ # empty token
+ if [[ -z "${GITLAB_TOKEN}" ]]; then
+ msg_error " api call failed: No token provided"
+ return 1
+ fi
+
+ if ! curl --request "${request}" \
+ --url "https://${GITLAB_HOST}/api/v4/${endpoint}" \
+ --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \
+ --header "Content-Type: application/json" \
+ --data "${data}" \
+ --output "${outfile}" \
+ --silent; then
+ msg_error " api call failed: $(cat "${outfile}")"
+ return 1
+ fi
+
+ # check for general purpose api error
+ 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' < "${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[])")[]' < "${outfile}")
+ elif error=$(jq --raw-output --exit-status '.message' < "${outfile}"); then
+ msg_error " api call failed: ${error}"
+ fi
+ return 1
+ fi
+
+ return 0
+}
+
+gitlab_api_get_user() {
+ local outfile username
+
+ [[ -z ${WORKDIR:-} ]] && setup_workdir
+ outfile=$(mktemp --tmpdir="${WORKDIR}" pkgctl-gitlab-api.XXXXXXXXXX)
+
+ # query user details
+ if ! gitlab_api_call "${outfile}" GET "user/"; then
+ msg_warn " Invalid token provided?"
+ exit 1
+ fi
+
+ # extract username from details
+ if ! username=$(jq --raw-output --exit-status '.username' < "${outfile}"); then
+ msg_error " failed to query username: $(cat "${outfile}")"
+ return 1
+ fi
+
+ printf "%s" "${username}"
+ return 0
+}
+
+# Convert arbitrary project names to GitLab valid path names.
+#
+# GitLab has several limitations on project and group names and also maintains
+# a list of reserved keywords as documented on their docs.
+# https://docs.gitlab.com/ee/user/reserved_names.html
+#
+# 1. replace single '+' between word boundaries with '-'
+# 2. replace any other '+' with literal 'plus'
+# 3. replace any special chars other than '_', '-' and '.' with '-'
+# 4. replace consecutive '_-' chars with a single '-'
+# 5. replace 'tree' with 'unix-tree' due to GitLab reserved keyword
+gitlab_project_name_to_path() {
+ local name=$1
+ printf "%s" "${name}" \
+ | sed -E 's/([a-zA-Z0-9]+)\+([a-zA-Z]+)/\1-\2/g' \
+ | sed -E 's/\+/plus/g' \
+ | sed -E 's/[^a-zA-Z0-9_\-\.]/-/g' \
+ | sed -E 's/[_\-]{2,}/-/g' \
+ | sed -E 's/^tree$/unix-tree/g'
+}
+
+gitlab_api_create_project() {
+ local pkgbase=$1
+ local outfile data path project_path
+
+ [[ -z ${WORKDIR:-} ]] && setup_workdir
+ outfile=$(mktemp --tmpdir="${WORKDIR}" pkgctl-gitlab-api.XXXXXXXXXX)
+
+ project_path=$(gitlab_project_name_to_path "${pkgbase}")
+
+ # create GitLab project
+ data='{
+ "name": "'"${pkgbase}"'",
+ "path": "'"${project_path}"'",
+ "namespace_id": "'"${GIT_PACKAGING_NAMESPACE_ID}"'",
+ "request_access_enabled": "false"
+ }'
+ if ! gitlab_api_call "${outfile}" POST "projects/" "${data}"; then
+ return 1
+ fi
+
+ if ! path=$(jq --raw-output --exit-status '.path' < "${outfile}"); then
+ msg_error " failed to query path: $(cat "${outfile}")"
+ return 1
+ fi
+
+ printf "%s" "${path}"
+ return 0
+}
diff --git a/lib/archroot.sh b/src/lib/archroot.sh
index d7917da..8386c6c 100644
--- a/lib/archroot.sh
+++ b/src/lib/archroot.sh
@@ -4,18 +4,19 @@
:
# shellcheck disable=2034
-CHROOT_VERSION='v4'
+CHROOT_VERSION='v5'
##
# usage : check_root $keepenv
##
-orig_argv=("${BASH_SOURCE[0]}" "$@")
check_root() {
local keepenv=$1
+ shift
+ local orig_argv=("$@")
(( EUID == 0 )) && return
if type -P sudo >/dev/null; then
- exec sudo --preserve-env=$keepenv -- "${orig_argv[@]}"
+ exec sudo --preserve-env="${keepenv}" -- "${orig_argv[@]}"
else
exec su root -c "$(printf ' %q' "${orig_argv[@]}")"
fi
diff --git a/src/lib/auth.sh b/src/lib/auth.sh
new file mode 100644
index 0000000..77d6a90
--- /dev/null
+++ b/src/lib/auth.sh
@@ -0,0 +1,72 @@
+#!/hint/bash
+#
+# This may be included with or without `set -euE`
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+[[ -z ${DEVTOOLS_INCLUDE_AUTH_SH:-} ]] || return 0
+DEVTOOLS_INCLUDE_AUTH_SH=1
+
+_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+
+set -e
+
+
+pkgctl_auth_usage() {
+ local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
+ cat <<- _EOF_
+ Usage: ${COMMAND} [COMMAND] [OPTIONS]
+
+ Authenticate with services like GitLab.
+
+ COMMANDS
+ login Authenticate with the GitLab instance
+ status View authentication status
+
+ OPTIONS
+ -h, --help Show this help text
+
+ EXAMPLES
+ $ ${COMMAND} login --gen-access-token
+ $ ${COMMAND} status
+_EOF_
+}
+
+pkgctl_auth() {
+ if (( $# < 1 )); then
+ pkgctl_auth_usage
+ exit 0
+ fi
+
+ # option checking
+ while (( $# )); do
+ case $1 in
+ -h|--help)
+ pkgctl_auth_usage
+ exit 0
+ ;;
+ login)
+ _DEVTOOLS_COMMAND+=" $1"
+ shift
+ # shellcheck source=src/lib/auth/login.sh
+ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/auth/login.sh
+ pkgctl_auth_login "$@"
+ exit 0
+ ;;
+ status)
+ _DEVTOOLS_COMMAND+=" $1"
+ shift
+ # shellcheck source=src/lib/auth/status.sh
+ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/auth/status.sh
+ pkgctl_auth_status "$@"
+ exit 0
+ ;;
+ -*)
+ die "invalid argument: %s" "$1"
+ ;;
+ *)
+ die "invalid command: %s" "$1"
+ ;;
+ esac
+ done
+}
diff --git a/src/lib/auth/login.sh b/src/lib/auth/login.sh
new file mode 100644
index 0000000..d427676
--- /dev/null
+++ b/src/lib/auth/login.sh
@@ -0,0 +1,101 @@
+#!/hint/bash
+#
+# This may be included with or without `set -euE`
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+[[ -z ${DEVTOOLS_INCLUDE_AUTH_LOGIN_SH:-} ]] || return 0
+DEVTOOLS_INCLUDE_AUTH_LOGIN_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/config.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/config.sh
+# shellcheck source=src/lib/api/gitlab.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/api/gitlab.sh
+
+set -e
+
+
+pkgctl_auth_login_usage() {
+ local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
+ cat <<- _EOF_
+ Usage: ${COMMAND} [OPTIONS]
+
+ Interactively authenticate with the GitLab instance.
+
+ The minimum required scopes for the token are: 'api', 'write_repository'.
+
+ The GitLab API token can either be stored in a plaintext file, or
+ supplied via the DEVTOOLS_GITLAB_TOKEN environment variable using a
+ vault, see pkgctl-auth-login(1) for details.
+
+ OPTIONS
+ -g, --gen-access-token Open the URL to generate a new personal access token
+ -h, --help Show this help text
+
+ EXAMPLES
+ $ ${COMMAND}
+ $ ${COMMAND} --gen-access-token
+_EOF_
+}
+
+
+pkgctl_auth_login() {
+ local token personal_access_token_url
+ local GEN_ACESS_TOKEN=0
+
+ # option checking
+ while (( $# )); do
+ case $1 in
+ -h|--help)
+ pkgctl_auth_login_usage
+ exit 0
+ ;;
+ -g|--gen-access-token)
+ GEN_ACESS_TOKEN=1
+ shift
+ ;;
+ *)
+ die "invalid argument: %s" "$1"
+ ;;
+ esac
+ done
+
+ personal_access_token_url="https://${GITLAB_HOST}/-/profile/personal_access_tokens?name=pkgctl+token&scopes=api,write_repository"
+
+ cat <<- _EOF_
+ Logging into ${BOLD}${GITLAB_HOST}${ALL_OFF}
+
+ Tip: you can generate a Personal Access Token here ${personal_access_token_url}
+ The minimum required scopes are 'api' and 'write_repository'.
+
+ If you do not want to store the token in a plaintext file, you can abort
+ the following prompt and supply the token via the DEVTOOLS_GITLAB_TOKEN
+ environment variable using a vault, see pkgctl-auth-login(1) for details.
+_EOF_
+
+ if (( GEN_ACESS_TOKEN )); then
+ xdg-open "${personal_access_token_url}" 2>/dev/null
+ fi
+
+ # read token from stdin
+ read -s -r -p "${GREEN}?${ALL_OFF} ${BOLD}Paste your authentication token:${ALL_OFF} " token
+ echo
+
+ if [[ -z ${token} ]]; then
+ msg_error " No token provided"
+ exit 1
+ fi
+
+ # check if the passed token works
+ GITLAB_TOKEN="${token}"
+ if ! result=$(gitlab_api_get_user); then
+ printf "%s\n" "$result"
+ exit 1
+ fi
+
+ msg_success " Logged in as ${BOLD}${result}${ALL_OFF}"
+ save_devtools_config
+}
diff --git a/src/lib/auth/status.sh b/src/lib/auth/status.sh
new file mode 100644
index 0000000..6cbaab1
--- /dev/null
+++ b/src/lib/auth/status.sh
@@ -0,0 +1,69 @@
+#!/hint/bash
+#
+# This may be included with or without `set -euE`
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+[[ -z ${DEVTOOLS_INCLUDE_AUTH_STATUS_SH:-} ]] || return 0
+DEVTOOLS_INCLUDE_AUTH_STATUS_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/gitlab.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/api/gitlab.sh
+
+set -e
+
+
+pkgctl_auth_status_usage() {
+ local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
+ cat <<- _EOF_
+ Usage: ${COMMAND} [OPTIONS]
+
+ Verifies and displays information about your authentication state of
+ services like the GitLab instance and reports issues if any.
+
+ OPTIONS
+ -t, --show-token Display the auth token
+ -h, --help Show this help text
+
+ EXAMPLES
+ $ ${COMMAND}
+ $ ${COMMAND} --show-token
+_EOF_
+}
+
+pkgctl_auth_status() {
+ local SHOW_TOKEN=0
+ # option checking
+ while (( $# )); do
+ case $1 in
+ -h|--help)
+ pkgctl_auth_status_usage
+ exit 0
+ ;;
+ -t|--show-token)
+ SHOW_TOKEN=1
+ shift
+ ;;
+ *)
+ die "invalid argument: %s" "$1"
+ ;;
+ esac
+ done
+
+ printf "%s\n" "${BOLD}${GITLAB_HOST}${ALL_OFF}"
+ # shellcheck disable=2119
+ if ! username=$(gitlab_api_get_user); then
+ printf "%s\n" "${username}"
+ exit 1
+ fi
+
+ msg_success " Logged in as ${BOLD}${username}${ALL_OFF}"
+ if (( SHOW_TOKEN )); then
+ msg_success " Token: ${GITLAB_TOKEN}"
+ else
+ msg_success " Token: **************************"
+ fi
+}
diff --git a/src/lib/build/build.sh b/src/lib/build/build.sh
new file mode 100644
index 0000000..3394395
--- /dev/null
+++ b/src/lib/build/build.sh
@@ -0,0 +1,420 @@
+#!/hint/bash
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+[[ -z ${DEVTOOLS_INCLUDE_BUILD_SH:-} ]] || return 0
+DEVTOOLS_INCLUDE_BUILD_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/update.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/db/update.sh
+# shellcheck source=src/lib/release.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/pacman.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/pacman.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
+
+source /usr/share/makepkg/util/config.sh
+source /usr/share/makepkg/util/message.sh
+
+set -e
+set -o pipefail
+
+
+pkgctl_build_usage() {
+ local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
+ cat <<- _EOF_
+ Usage: ${COMMAND} [OPTIONS] [PATH]...
+
+ Build packages inside a clean chroot
+
+ When a new pkgver is set using the appropriate PKGBUILD options the
+ checksums are automatically updated.
+
+ TODO
+
+ BUILD OPTIONS
+ --arch ARCH Specify architectures to build for (disables auto-detection)
+ --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
+ -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
+
+ 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
+ -e, --edit Edit the PKGBUILD before building
+
+ RELEASE OPTIONS
+ -r, --release Automatically commit, tag and release after building
+ -m, --message MSG Use the given <msg> as the commit message
+ -u, --db-update Automatically update the pacman database as last action
+
+ OPTIONS
+ -h, --help Show this help text
+
+ EXAMPLES
+ $ ${COMMAND}
+ $ ${COMMAND} --rebuild --staging --message 'libyay 0.42 rebuild' libfoo libbar
+ $ ${COMMAND} --pkgver 1.42 --release --db-update
+_EOF_
+}
+
+pkgctl_build_check_option_group_repo() {
+ local option=$1
+ local repo=$2
+ local testing=$3
+ local staging=$4
+ 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
+ return 0
+}
+
+pkgctl_build_check_option_group_ver() {
+ local option=$1
+ local pkgver=$2
+ local pkgrel=$3
+ local rebuild=$4
+ if [[ -n "${pkgver}" ]] || [[ -n "${pkgrel}" ]] || (( rebuild )); then
+ die "The argument '%s' cannot be used with one or more of the other specified arguments" "${option}"
+ exit 1
+ fi
+ return 0
+}
+
+# TODO: import pgp keys
+pkgctl_build() {
+ if (( $# < 1 )) && [[ ! -f PKGBUILD ]]; then
+ pkgctl_build_usage
+ exit 1
+ fi
+
+ local UPDPKGSUMS=0
+ local EDIT=0
+ local REBUILD=0
+ local OFFLOAD=0
+ local STAGING=0
+ local TESTING=0
+ local RELEASE=0
+ local DB_UPDATE=0
+
+ local REPO=
+ local PKGVER=
+ local PKGREL=
+ local MESSAGE=
+
+ local paths=()
+ local BUILD_ARCH=()
+ local BUILD_OPTIONS=()
+ local MAKECHROOT_OPTIONS=()
+ local RELEASE_OPTIONS=()
+ local MAKEPKG_OPTIONS=()
+
+ local WORKER=
+ local WORKER_SLOT=
+
+ # variables
+ local path pkgbase pkgrepo source
+
+ while (( $# )); do
+ case $1 in
+ -h|--help)
+ pkgctl_build_usage
+ exit 0
+ ;;
+ --repo)
+ (( $# <= 1 )) && die "missing argument for %s" "$1"
+ REPO="${2}"
+ 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=("${_arch[@]::${#_arch[@]}-1}")
+ elif [[ ${2} == any ]]; then
+ BUILD_ARCH=("${_arch[0]}")
+ elif ! in_array "${2}" "${BUILD_ARCH[@]}"; then
+ if ! in_array "${2}" "${_arch[@]}"; then
+ die 'invalid architecture: %s' "${2}"
+ fi
+ BUILD_ARCH+=("${2}")
+ fi
+ shift 2
+ ;;
+ --pkgver=*)
+ pkgctl_build_check_option_group_ver '--pkgver' "${PKGVER}" "${PKGREL}" "${REBUILD}"
+ PKGVER="${1#*=}"
+ PKGREL=1
+ UPDPKGSUMS=1
+ shift
+ ;;
+ --pkgrel=*)
+ pkgctl_build_check_option_group_ver '--pkgrel' "${PKGVER}" "${PKGREL}" "${REBUILD}"
+ PKGREL="${1#*=}"
+ shift
+ ;;
+ --rebuild)
+ # shellcheck source=src/lib/util/git.sh
+ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/git.sh
+ pkgctl_build_check_option_group_ver '--rebuild' "${PKGVER}" "${PKGREL}" "${REBUILD}"
+ REBUILD=1
+ shift
+ ;;
+ -e|--edit)
+ EDIT=1
+ shift
+ ;;
+ -o|--offload)
+ OFFLOAD=1
+ shift
+ ;;
+ -s|--staging)
+ STAGING=1
+ pkgctl_build_check_option_group_repo '--staging' "${REPO}" "${TESTING}" "${STAGING}"
+ shift
+ ;;
+ -t|--testing)
+ TESTING=1
+ pkgctl_build_check_option_group_repo '--testing' "${REPO}" "${TESTING}" "${STAGING}"
+ shift
+ ;;
+ -c|--clean)
+ BUILD_OPTIONS+=("-c")
+ shift
+ ;;
+ -I|--install)
+ (( $# <= 1 )) && die "missing argument for %s" "$1"
+ MAKECHROOT_OPTIONS+=("-I" "$2")
+ warning 'installing packages into the chroot may break reproducible builds, use with caution!'
+ shift 2
+ ;;
+ --nocheck)
+ MAKEPKG_OPTIONS+=("--nocheck")
+ warning 'not running checks is disallowed for official packages, except for bootstrapping. Please rebuild after bootstrapping is completed!'
+ shift
+ ;;
+ -r|--release)
+ # shellcheck source=src/lib/release.sh
+ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/release.sh
+ RELEASE=1
+ shift
+ ;;
+ -m|--message)
+ (( $# <= 1 )) && die "missing argument for %s" "$1"
+ MESSAGE=$2
+ RELEASE_OPTIONS+=("--message" "${MESSAGE}")
+ shift 2
+ ;;
+ -u|--db-update)
+ DB_UPDATE=1
+ shift
+ ;;
+ -w|--worker)
+ (( $# <= 1 )) && die "missing argument for %s" "$1"
+ WORKER_SLOT=$2
+ shift 2
+ ;;
+ --)
+ shift
+ break
+ ;;
+ -*)
+ die "invalid argument: %s" "$1"
+ ;;
+ *)
+ paths=("$@")
+ break
+ ;;
+ esac
+ done
+
+ # check if any release specific options were specified without releasing
+ if (( ! RELEASE )); then
+ if (( DB_UPDATE )); then
+ die "cannot use --db-update without --release"
+ fi
+ if [[ -n "${MESSAGE}" ]]; then
+ die "cannot use --message without --release"
+ fi
+ fi
+
+ # check if invoked without any path from within a packaging repo
+ if (( ${#paths[@]} == 0 )); then
+ if [[ -f PKGBUILD ]]; then
+ paths=(".")
+ else
+ pkgctl_build_usage
+ exit 1
+ fi
+ fi
+
+ # assign default worker slot
+ if [[ -z ${WORKER_SLOT} ]] && ! WORKER_SLOT="$(tty | sed 's|/dev/pts/||')"; then
+ WORKER_SLOT=$(( RANDOM % $(nproc) + 1 ))
+ fi
+ WORKER="${USER}-${WORKER_SLOT}"
+
+ # Update pacman cache for auto-detection
+ if [[ -z ${REPO} ]]; then
+ update_pacman_repo_cache
+ # Check valid repos if not resolved dynamically
+ elif ! in_array "${REPO}" "${_repos[@]}"; then
+ die "Invalid repository target: %s" "${REPO}"
+ fi
+
+ for path in "${paths[@]}"; do
+ pushd "${path}" >/dev/null
+
+ if [[ ! -f PKGBUILD ]]; then
+ die 'PKGBUILD not found in %s' "${path}"
+ fi
+
+ source=()
+ # shellcheck source=contrib/makepkg/PKGBUILD.proto
+ . ./PKGBUILD
+ pkgbase=${pkgbase:-$pkgname}
+ pkgrepo=${REPO}
+ msg "Building ${pkgbase}"
+
+ # 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
+
+ # special cases to resolve final build target
+ if (( TESTING )); then
+ pkgrepo="${pkgrepo}-testing"
+ elif (( STAGING )); then
+ pkgrepo="${pkgrepo}-staging"
+ elif [[ $pkgrepo == core ]]; then
+ pkgrepo="${pkgrepo}-testing"
+ fi
+
+ # auto-detection of build architecture
+ if [[ $pkgrepo = multilib* ]]; then
+ BUILD_ARCH=("")
+ elif (( ${#BUILD_ARCH[@]} == 0 )); then
+ if in_array any "${arch[@]}"; then
+ BUILD_ARCH=("${_arch[0]}")
+ else
+ BUILD_ARCH+=("${arch[@]}")
+ fi
+ fi
+
+ # print gathered build modes
+ msg2 " repo: ${pkgrepo}"
+ msg2 " arch: ${BUILD_ARCH[*]}"
+ msg2 "worker: ${WORKER}"
+
+ # increment pkgrel on rebuild
+ if (( REBUILD )); then
+ # try to figure out of pkgrel has been changed
+ if ! old_pkgrel=$(git_diff_tree HEAD PKGBUILD | grep --perl-regexp --only-matching --max-count=1 '^-pkgrel=\K\w+'); then
+ old_pkgrel=${pkgrel}
+ fi
+ # check if pkgrel conforms expectations
+ [[ ${pkgrel/.*} =~ ^[0-9]+$ ]] || die "Non-standard pkgrel declaration"
+ [[ ${old_pkgrel/.*} =~ ^[0-9]+$ ]] || die "Non-standard pkgrel declaration"
+ # increment pkgrel if it hasn't been changed yet
+ if [[ ${pkgrel} = "${old_pkgrel}" ]]; then
+ PKGREL=$((${pkgrel/.*}+1))
+ else
+ warning 'ignoring --rebuild as pkgrel has already been incremented from %s to %s' "${old_pkgrel}" "${pkgrel}"
+ fi
+ fi
+
+ # 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}"
+ 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}"
+ 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
+ if (( EDIT )); then
+ stat_busy 'Editing PKGBUILD'
+ if [[ -n $GIT_EDITOR ]]; then
+ $GIT_EDITOR PKGBUILD || die
+ elif [[ -n $VISUAL ]]; then
+ $VISUAL PKGBUILD || die
+ elif [[ -n $EDITOR ]]; then
+ $EDITOR PKGBUILD || die
+ elif giteditor=$(git config --get core.editor); then
+ $giteditor PKGBUILD || die
+ else
+ die "No usable editor found (tried \$GIT_EDITOR, \$VISUAL, \$EDITOR, git config [core.editor])."
+ fi
+ stat_done
+ fi
+
+
+ # update checksums if any sources are declared
+ if (( UPDPKGSUMS )) && (( ${#source[@]} >= 1 )); then
+ updpkgsums
+ fi
+
+ # execute build
+ for arch in "${BUILD_ARCH[@]}"; do
+ if [[ -n $arch ]]; then
+ msg "Building ${pkgbase} for [${pkgrepo}] (${arch})"
+ BUILDTOOL="${pkgrepo}-${arch}-build"
+ else
+ msg "Building ${pkgbase} for [${pkgrepo}]"
+ BUILDTOOL="${pkgrepo}-build"
+ fi
+
+ if (( OFFLOAD )); then
+ offload-build --repo "${pkgrepo}" -- "${BUILD_OPTIONS[@]}" -- "${MAKECHROOT_OPTIONS[@]}" -l "${WORKER}" -- "${MAKEPKG_OPTIONS[@]}"
+ else
+ "${BUILDTOOL}" "${BUILD_OPTIONS[@]}" -- "${MAKECHROOT_OPTIONS[@]}" -l "${WORKER}" -- "${MAKEPKG_OPTIONS[@]}"
+ fi
+ done
+
+ # release the build
+ if (( RELEASE )); then
+ pkgctl_release --repo "${pkgrepo}" "${RELEASE_OPTIONS[@]}"
+ fi
+
+ # reset common PKGBUILD variables
+ unset pkgbase pkgname arch pkgrepo source pkgver pkgrel validpgpkeys
+ popd >/dev/null
+ done
+
+ # update the binary package repo db as last action
+ if (( RELEASE )) && (( DB_UPDATE )); then
+ # shellcheck disable=2119
+ pkgctl_db_update
+ fi
+}
diff --git a/lib/common.sh b/src/lib/common.sh
index a5e4616..3d1ee56 100644
--- a/lib/common.sh
+++ b/src/lib/common.sh
@@ -4,23 +4,33 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
-[[ -z ${_INCLUDE_COMMON_SH:-} ]] || return 0
-_INCLUDE_COMMON_SH="$(set +o|grep nounset)"
+[[ -z ${DEVTOOLS_INCLUDE_COMMON_SH:-} ]] || return 0
+DEVTOOLS_INCLUDE_COMMON_SH="$(set +o|grep nounset)"
set +u +o posix
# shellcheck disable=1091
. /usr/share/makepkg/util.sh
-$_INCLUDE_COMMON_SH
+$DEVTOOLS_INCLUDE_COMMON_SH
# Avoid any encoding problems
export LANG=C
# Set buildtool properties
export BUILDTOOL=devtools
-export BUILDTOOLVER=m4_devtools_version
+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=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
# check if messages are to be printed using color
-if [[ -t 2 && "$TERM" != dumb ]]; then
+if [[ -t 2 && "$TERM" != dumb ]] || [[ ${DEVTOOLS_COLOR} == always ]]; then
colorize
else
# shellcheck disable=2034
@@ -33,11 +43,40 @@ stat_busy() {
printf "${GREEN}==>${ALL_OFF}${BOLD} ${mesg}...${ALL_OFF}" "$@" >&2
}
+stat_progress() {
+ # shellcheck disable=2059
+ printf "${BOLD}.${ALL_OFF}" >&2
+}
+
stat_done() {
# shellcheck disable=2059
printf "${BOLD}done${ALL_OFF}\n" >&2
}
+msg_success() {
+ local msg=$1
+ local padding
+ padding=$(echo "${msg}"|sed -E 's/( *).*/\1/')
+ msg=$(echo "${msg}"|sed -E 's/ *(.*)/\1/')
+ printf "%s %s\n" "${padding}${GREEN}✓${ALL_OFF}" "${msg}" >&2
+}
+
+msg_error() {
+ local msg=$1
+ local padding
+ padding=$(echo "${msg}"|sed -E 's/( *).*/\1/')
+ msg=$(echo "${msg}"|sed -E 's/ *(.*)/\1/')
+ printf "%s %s\n" "${padding}${RED}x${ALL_OFF}" "${msg}" >&2
+}
+
+msg_warn() {
+ local msg=$1
+ local padding
+ padding=$(echo "${msg}"|sed -E 's/( *).*/\1/')
+ msg=$(echo "${msg}"|sed -E 's/ *(.*)/\1/')
+ printf "%s %s\n" "${padding}${YELLOW}!${ALL_OFF}" "${msg}" >&2
+}
+
_setup_workdir=false
setup_workdir() {
[[ -z ${WORKDIR:-} ]] && WORKDIR=$(mktemp -d --tmpdir "${0##*/}.XXXXXXXXXX")
@@ -137,6 +176,7 @@ pkgver_equal() {
# $pkgver can be supplied with or without a pkgrel appended.
# If not supplied, any pkgrel will be matched.
##
+shopt -s extglob
find_cached_package() {
local searchdirs=("$PWD" "$PKGDEST") results=()
local targetname=$1 targetver=$2 targetarch=$3
@@ -191,7 +231,7 @@ find_cached_package() {
return 1
esac
}
-
+shopt -u extglob
check_package_validity(){
local pkgfile=$1
@@ -254,6 +294,16 @@ getpkgdesc() {
}
+get_tag_from_pkgver() {
+ local pkgver=$1
+ local tag=${pkgver}
+
+ tag=${tag/:/-}
+ tag=${tag//~/.}
+ echo "${tag}"
+}
+
+
is_debug_package() {
local pkgfile=${1} pkgbase pkgname pkgdesc
pkgbase="$(getpkgbase "${pkgfile}")"
diff --git a/src/lib/config.sh b/src/lib/config.sh
new file mode 100644
index 0000000..b09479a
--- /dev/null
+++ b/src/lib/config.sh
@@ -0,0 +1,48 @@
+#!/hint/bash
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+[[ -z ${DEVTOOLS_INCLUDE_CONFIG_SH:-} ]] || return 0
+DEVTOOLS_INCLUDE_CONFIG_SH=1
+
+set -e
+
+readonly XDG_DEVTOOLS_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/devtools"
+readonly XDG_DEVTOOLS_GITLAB_CONFIG="${XDG_DEVTOOLS_DIR}/gitlab.conf"
+
+# default config variables
+export GITLAB_TOKEN=""
+
+load_devtools_config() {
+ # temporary permission fixup
+ if [[ -d "${XDG_DEVTOOLS_DIR}" ]]; then
+ chmod 700 "${XDG_DEVTOOLS_DIR}"
+ fi
+ if [[ -f "${XDG_DEVTOOLS_GITLAB_CONFIG}" ]]; then
+ chmod 600 "${XDG_DEVTOOLS_GITLAB_CONFIG}"
+ fi
+ if [[ -n "${DEVTOOLS_GITLAB_TOKEN}" ]]; then
+ GITLAB_TOKEN="${DEVTOOLS_GITLAB_TOKEN}"
+ return
+ fi
+ if [[ -f "${XDG_DEVTOOLS_GITLAB_CONFIG}" ]]; then
+ GITLAB_TOKEN=$(grep GITLAB_TOKEN "${XDG_DEVTOOLS_GITLAB_CONFIG}"|cut -d= -f2|cut -d\" -f2)
+ return
+ fi
+ GITLAB_TOKEN=""
+}
+
+save_devtools_config() {
+ # temporary permission fixup
+ if [[ -d "${XDG_DEVTOOLS_DIR}" ]]; then
+ chmod 700 "${XDG_DEVTOOLS_DIR}"
+ fi
+ if [[ -f "${XDG_DEVTOOLS_GITLAB_CONFIG}" ]]; then
+ chmod 600 "${XDG_DEVTOOLS_GITLAB_CONFIG}"
+ fi
+ (
+ umask 0077
+ mkdir -p "${XDG_DEVTOOLS_DIR}"
+ printf 'GITLAB_TOKEN="%s"\n' "${GITLAB_TOKEN}" > "${XDG_DEVTOOLS_GITLAB_CONFIG}"
+ )
+}
diff --git a/src/lib/db.sh b/src/lib/db.sh
new file mode 100644
index 0000000..397ff0d
--- /dev/null
+++ b/src/lib/db.sh
@@ -0,0 +1,80 @@
+#!/hint/bash
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+[[ -z ${DEVTOOLS_INCLUDE_DB_SH:-} ]] || return 0
+DEVTOOLS_INCLUDE_DB_SH=1
+
+_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+
+set -e
+
+
+pkgctl_db_usage() {
+ local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
+ cat <<- _EOF_
+ Usage: ${COMMAND} [COMMAND] [OPTIONS]
+
+ Pacman database modification for packge update, move etc
+
+ COMMANDS
+ move Move packages between pacman repositories
+ remove Remove packages from pacman repositories
+ update Update the pacman database as final release step
+
+ OPTIONS
+ -h, --help Show this help text
+
+ EXAMPLES
+ $ ${COMMAND} move extra-staging extra-testing libfoo libbar
+ $ ${COMMAND} remove core-testing libfoo libbar
+ $ ${COMMAND} update
+_EOF_
+}
+
+pkgctl_db() {
+ if (( $# < 1 )); then
+ pkgctl_db_usage
+ exit 0
+ fi
+
+ # option checking
+ while (( $# )); do
+ case $1 in
+ -h|--help)
+ pkgctl_db_usage
+ exit 0
+ ;;
+ move)
+ _DEVTOOLS_COMMAND+=" $1"
+ shift
+ # shellcheck source=src/lib/db/move.sh
+ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/db/move.sh
+ pkgctl_db_move "$@"
+ exit 0
+ ;;
+ remove)
+ _DEVTOOLS_COMMAND+=" $1"
+ shift
+ # shellcheck source=src/lib/db/remove.sh
+ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/db/remove.sh
+ pkgctl_db_remove "$@"
+ exit 0
+ ;;
+ update)
+ _DEVTOOLS_COMMAND+=" $1"
+ shift
+ # shellcheck source=src/lib/db/update.sh
+ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/db/update.sh
+ pkgctl_db_update "$@"
+ exit 0
+ ;;
+ -*)
+ die "invalid argument: %s" "$1"
+ ;;
+ *)
+ die "invalid command: %s" "$1"
+ ;;
+ esac
+ done
+}
diff --git a/src/lib/db/move.sh b/src/lib/db/move.sh
new file mode 100644
index 0000000..825b350
--- /dev/null
+++ b/src/lib/db/move.sh
@@ -0,0 +1,64 @@
+#!/hint/bash
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+[[ -z ${DEVTOOLS_INCLUDE_DB_MOVE_SH:-} ]] || return 0
+DEVTOOLS_INCLUDE_DB_MOVE_SH=1
+
+_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+# shellcheck source=src/lib/common.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
+
+set -e
+
+
+pkgctl_db_move_usage() {
+ local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
+ cat <<- _EOF_
+ Usage: ${COMMAND} [OPTIONS] [SOURCE_REPO] [TARGET_REPO] [PKGBASE]...
+
+ Move packages between binary repositories.
+
+ OPTIONS
+ -h, --help Show this help text
+
+ EXAMPLES
+ $ ${COMMAND} extra-staging extra-testing libfoo libbar
+ $ ${COMMAND} extra core libfoo libbar
+_EOF_
+}
+
+pkgctl_db_move() {
+ local SOURCE_REPO=""
+ local TARGET_REPO=""
+ local PKGBASES=()
+
+ # option checking
+ while (( $# )); do
+ case $1 in
+ -h|--help)
+ pkgctl_db_move_usage
+ exit 0
+ ;;
+ -*)
+ die "invalid argument: %s" "$1"
+ ;;
+ *)
+ break
+ ;;
+ esac
+ done
+
+ if (( $# < 3 )); then
+ pkgctl_db_move_usage
+ exit 1
+ fi
+
+ SOURCE_REPO=$1
+ TARGET_REPO=$2
+ shift 2
+ PKGBASES+=("$@")
+
+ # shellcheck disable=SC2029
+ ssh "${PACKAGING_REPO_RELEASE_HOST}" db-move "${SOURCE_REPO}" "${TARGET_REPO}" "${PKGBASES[@]}"
+}
diff --git a/src/lib/db/remove.sh b/src/lib/db/remove.sh
new file mode 100644
index 0000000..ba21c83
--- /dev/null
+++ b/src/lib/db/remove.sh
@@ -0,0 +1,69 @@
+#!/hint/bash
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+[[ -z ${DEVTOOLS_INCLUDE_DB_REMOVE_SH:-} ]] || return 0
+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
+
+set -e
+
+
+pkgctl_db_remove_usage() {
+ local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
+ cat <<- _EOF_
+ Usage: ${COMMAND} [OPTIONS] [REPO] [PKGBASE]...
+
+ Remove packages from binary repositories.
+
+ OPTIONS
+ -a, --arch Override the architecture (disables auto-detection)
+ -h, --help Show this help text
+
+ EXAMPLES
+ $ ${COMMAND} core-testing libfoo libbar
+ $ ${COMMAND} --arch x86_64 core libyay
+_EOF_
+}
+
+pkgctl_db_remove() {
+ local REPO=""
+ local ARCH=any
+ local PKGBASES=()
+
+ # option checking
+ while (( $# )); do
+ case $1 in
+ -h|--help)
+ pkgctl_db_remove_usage
+ exit 0
+ ;;
+ -a|--arch)
+ (( $# <= 1 )) && die "missing argument for %s" "$1"
+ ARCH=$2
+ shift 2
+ ;;
+ -*)
+ die "invalid argument: %s" "$1"
+ ;;
+ *)
+ break
+ ;;
+ esac
+ done
+
+ if (( $# < 2 )); then
+ pkgctl_db_remove_usage
+ exit 1
+ fi
+
+ REPO=$1
+ shift
+ PKGBASES+=("$@")
+
+ # shellcheck disable=SC2029
+ ssh "${PACKAGING_REPO_RELEASE_HOST}" db-remove "${REPO}" "${ARCH}" "${PKGBASES[@]}"
+}
diff --git a/src/lib/db/update.sh b/src/lib/db/update.sh
new file mode 100644
index 0000000..269720d
--- /dev/null
+++ b/src/lib/db/update.sh
@@ -0,0 +1,46 @@
+#!/hint/bash
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+[[ -z ${DEVTOOLS_INCLUDE_DB_UPDATE_SH:-} ]] || return 0
+DEVTOOLS_INCLUDE_DB_UPDATE_SH=1
+
+_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+# shellcheck source=src/lib/common.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
+
+set -e
+
+
+pkgctl_db_update_usage() {
+ local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
+ cat <<- _EOF_
+ Usage: ${COMMAND} [OPTIONS]
+
+ Update the binary repository as final release step for packages that
+ have been transfered and staged on ${PACKAGING_REPO_RELEASE_HOST}.
+
+ OPTIONS
+ -h, --help Show this help text
+
+ EXAMPLES
+ $ ${COMMAND}
+_EOF_
+}
+
+pkgctl_db_update() {
+ # option checking
+ while (( $# )); do
+ case $1 in
+ -h|--help)
+ pkgctl_db_update_usage
+ exit 0
+ ;;
+ *)
+ die "invalid argument: %s" "$1"
+ ;;
+ esac
+ done
+
+ ssh "${PACKAGING_REPO_RELEASE_HOST}" db-update
+}
diff --git a/src/lib/release.sh b/src/lib/release.sh
new file mode 100644
index 0000000..aabbd35
--- /dev/null
+++ b/src/lib/release.sh
@@ -0,0 +1,167 @@
+#!/hint/bash
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+[[ -z ${DEVTOOLS_INCLUDE_RELEASE_SH:-} ]] || return 0
+DEVTOOLS_INCLUDE_RELEASE_SH=1
+
+_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+# shellcheck source=src/lib/db/update.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/db/update.sh
+# shellcheck source=src/lib/util/pacman.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/pacman.sh
+# shellcheck source=src/lib/valid-repos.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-repos.sh
+
+source /usr/share/makepkg/util/util.sh
+
+set -e
+
+
+pkgctl_release_usage() {
+ local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
+ cat <<- _EOF_
+ Usage: ${COMMAND} [OPTIONS] [PATH]...
+
+ Release step to commit, tag and upload build artifacts
+
+ Modified version controlled files will first be staged for commit,
+ afterwards a Git tag matching the pkgver will be created and finally
+ all build artifacts will be uploaded.
+
+ By default the target pacman repository will be auto-detected by querying
+ the repo it is currently released in. When initially adding a new package
+ to the repositories, the target repo must be specified manually.
+
+ OPTIONS
+ -m, --message MSG Use the given <msg> as the commit message
+ -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
+ -h, --help Show this help text
+
+ EXAMPLES
+ $ ${COMMAND}
+ $ ${COMMAND} --repo core-testing --message 'libyay 0.42 rebuild' libfoo libbar
+ $ ${COMMAND} --staging --db-update libfoo
+_EOF_
+}
+
+pkgctl_release_check_option_group() {
+ local option=$1
+ local repo=$2
+ local testing=$3
+ local staging=$4
+ if [[ -n "${repo}" ]] || (( testing )) || (( staging )); then
+ die "The argument '%s' cannot be used with one or more of the other specified arguments" "${option}"
+ exit 1
+ fi
+ return 0
+}
+
+pkgctl_release() {
+ if (( $# < 1 )) && [[ ! -f PKGBUILD ]]; then
+ pkgctl_release_usage
+ exit 1
+ fi
+
+ local MESSAGE=""
+ local PKGBASES=()
+ local REPO=""
+ local TESTING=0
+ local STAGING=0
+ local DB_UPDATE=0
+
+ local path pkgbase pkgnames repo repos
+
+ # option checking
+ while (( $# )); do
+ case $1 in
+ -h|--help)
+ pkgctl_release_usage
+ exit 0
+ ;;
+ -m|--message)
+ (( $# <= 1 )) && die "missing argument for %s" "$1"
+ MESSAGE=$2
+ shift 2
+ ;;
+ -r|--repo)
+ (( $# <= 1 )) && die "missing argument for %s" "$1"
+ pkgctl_release_check_option_group '--repo' "${REPO}" "${TESTING}" "${STAGING}"
+ REPO=$2
+ shift 2
+ ;;
+ -s|--staging)
+ pkgctl_release_check_option_group '--staging' "${REPO}" "${TESTING}" "${STAGING}"
+ STAGING=1
+ shift
+ ;;
+ -t|--testing)
+ pkgctl_release_check_option_group '--testing' "${REPO}" "${TESTING}" "${STAGING}"
+ TESTING=1
+ shift
+ ;;
+ -u|--db-update)
+ DB_UPDATE=1
+ shift
+ ;;
+ -*)
+ die "invalid option: %s" "$1"
+ ;;
+ *)
+ PKGBASES+=("$@")
+ break
+ ;;
+ esac
+ done
+
+ # Resolve package from current working directory
+ if (( 0 == ${#PKGBASES[@]} )); then
+ PKGBASES=("$PWD")
+ fi
+
+ # Update pacman cache for auto-detection
+ if [[ -z ${REPO} ]]; then
+ update_pacman_repo_cache
+ # Check valid repos if not resolved dynamically
+ elif ! in_array "${REPO}" "${_repos[@]}"; then
+ die "Invalid repository target: %s" "${REPO}"
+ fi
+
+ for path in "${PKGBASES[@]}"; do
+ pushd "${path}" >/dev/null
+ pkgbase=$(basename "${path}")
+
+ 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
+ repo="${repo}-testing"
+ elif (( STAGING )); then
+ repo="${repo}-staging"
+ elif [[ $repo == core ]]; then
+ repo="${repo}-testing"
+ fi
+
+ msg "Releasing ${pkgbase} to ${repo}"
+ commitpkg "${repo}" "${MESSAGE}"
+
+ unset repo
+ popd >/dev/null
+ done
+
+ if (( DB_UPDATE )); then
+ # shellcheck disable=2119
+ pkgctl_db_update
+ fi
+}
diff --git a/src/lib/repo.sh b/src/lib/repo.sh
new file mode 100644
index 0000000..9f545e9
--- /dev/null
+++ b/src/lib/repo.sh
@@ -0,0 +1,110 @@
+#!/hint/bash
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+[[ -z ${DEVTOOLS_INCLUDE_REPO_SH:-} ]] || return 0
+DEVTOOLS_INCLUDE_REPO_SH=1
+
+_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+
+set -e
+
+
+pkgctl_repo_usage() {
+ local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
+ cat <<- _EOF_
+ Usage: ${COMMAND} [COMMAND] [OPTIONS]
+
+ Manage Git packaging repositories and helps with their configuration
+ according to distro specs.
+
+ Git author information and the used signing key is set up from
+ makepkg.conf read from any valid location like /etc or XDG_CONFIG_HOME.
+ The configure command can be used to synchronize the distro specs and
+ makepkg.conf settings for previously cloned repositories.
+
+ The unprivileged option can be used for cloning packaging repositories
+ without SSH access using read-only HTTPS.
+
+ COMMANDS
+ clone Clone a package repository
+ configure Configure a clone according to distro specs
+ create Create a new GitLab package repository
+ switch Switch a package repository to a specified version
+ web Open the packaging repository's website
+
+ OPTIONS
+ -h, --help Show this help text
+
+ EXAMPLES
+ $ ${COMMAND} clone libfoo linux libbar
+ $ ${COMMAND} clone --maintainer mynickname
+ $ ${COMMAND} configure *
+ $ ${COMMAND} create libfoo
+ $ ${COMMAND} switch 2:1.19.5-1 libfoo
+ $ ${COMMAND} web linux
+_EOF_
+}
+
+pkgctl_repo() {
+ if (( $# < 1 )); then
+ pkgctl_repo_usage
+ exit 0
+ fi
+
+ # option checking
+ while (( $# )); do
+ case $1 in
+ -h|--help)
+ pkgctl_repo_usage
+ exit 0
+ ;;
+ clone)
+ _DEVTOOLS_COMMAND+=" $1"
+ shift
+ # shellcheck source=src/lib/repo/clone.sh
+ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/repo/clone.sh
+ pkgctl_repo_clone "$@"
+ exit 0
+ ;;
+ configure)
+ _DEVTOOLS_COMMAND+=" $1"
+ shift
+ # shellcheck source=src/lib/repo/configure.sh
+ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/repo/configure.sh
+ pkgctl_repo_configure "$@"
+ exit 0
+ ;;
+ create)
+ _DEVTOOLS_COMMAND+=" $1"
+ shift
+ # shellcheck source=src/lib/repo/create.sh
+ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/repo/create.sh
+ pkgctl_repo_create "$@"
+ exit 0
+ ;;
+ switch)
+ _DEVTOOLS_COMMAND+=" $1"
+ shift
+ # shellcheck source=src/lib/repo/switch.sh
+ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/repo/switch.sh
+ pkgctl_repo_switch "$@"
+ exit 0
+ ;;
+ web)
+ _DEVTOOLS_COMMAND+=" $1"
+ shift
+ # shellcheck source=src/lib/repo/web.sh
+ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/repo/web.sh
+ pkgctl_repo_web "$@"
+ exit 0
+ ;;
+ -*)
+ die "invalid argument: %s" "$1"
+ ;;
+ *)
+ die "invalid command: %s" "$1"
+ ;;
+ esac
+ done
+}
diff --git a/src/lib/repo/clone.sh b/src/lib/repo/clone.sh
new file mode 100644
index 0000000..08bded4
--- /dev/null
+++ b/src/lib/repo/clone.sh
@@ -0,0 +1,199 @@
+#!/bin/bash
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+[[ -z ${DEVTOOLS_INCLUDE_REPO_CLONE_SH:-} ]] || return 0
+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/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
+
+source /usr/share/makepkg/util/message.sh
+
+set -e
+
+
+pkgctl_repo_clone_usage() {
+ local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
+ cat <<- _EOF_
+ Usage: ${COMMAND} [OPTIONS] [PKGBASE]...
+
+ Clone Git packaging repositories from the canonical namespace.
+
+ The configure command is subsequently invoked to synchronize the distro
+ specs and makepkg.conf settings. The protocol option can be used
+ for cloning packaging repositories without SSH access using read-only
+ HTTPS.
+
+ OPTIONS
+ -m, --maintainer=NAME Clone all packages of the named maintainer
+ --protocol https Clone the repository over https
+ --switch VERSION Switch the current working tree to a specified version
+ --universe Clone all existing packages, useful for cache warming
+ -j, --jobs N Run up to N jobs in parallel (default: $(nproc))
+ -h, --help Show this help text
+
+ EXAMPLES
+ $ ${COMMAND} libfoo linux libbar
+ $ ${COMMAND} --maintainer mynickname
+ $ ${COMMAND} --switch 1:1.0-2 libfoo
+_EOF_
+}
+
+pkgctl_repo_clone() {
+ if (( $# < 1 )); then
+ pkgctl_repo_clone_usage
+ exit 0
+ fi
+
+ # options
+ local GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_SSH}
+ local CLONE_ALL=0
+ local MAINTAINER=
+ local VERSION=
+ local CONFIGURE_OPTIONS=()
+ local jobs=
+ jobs=$(nproc)
+
+ # variables
+ local command=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
+ local project_path
+
+ while (( $# )); do
+ case $1 in
+ -h|--help)
+ pkgctl_repo_clone_usage
+ exit 0
+ ;;
+ --protocol=https)
+ GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_HTTPS}
+ CONFIGURE_OPTIONS+=("$1")
+ shift
+ ;;
+ --protocol)
+ (( $# <= 1 )) && die "missing argument for %s" "$1"
+ if [[ $2 == https ]]; then
+ GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_HTTPS}
+ else
+ die "unsupported protocol: %s" "$2"
+ fi
+ CONFIGURE_OPTIONS+=("$1" "$2")
+ shift 2
+ ;;
+ -m|--maintainer)
+ (( $# <= 1 )) && die "missing argument for %s" "$1"
+ MAINTAINER="$2"
+ shift 2
+ ;;
+ --maintainer=*)
+ MAINTAINER="${1#*=}"
+ shift
+ ;;
+ --switch)
+ (( $# <= 1 )) && die "missing argument for %s" "$1"
+ # shellcheck source=src/lib/repo/switch.sh
+ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/repo/switch.sh
+ VERSION="$2"
+ shift 2
+ ;;
+ --switch=*)
+ # shellcheck source=src/lib/repo/switch.sh
+ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/repo/switch.sh
+ VERSION="${1#*=}"
+ shift
+ ;;
+ --universe)
+ CLONE_ALL=1
+ shift
+ ;;
+ -j|--jobs)
+ (( $# <= 1 )) && die "missing argument for %s" "$1"
+ jobs=$2
+ shift 2
+ ;;
+ --)
+ shift
+ break
+ ;;
+ -*)
+ die "invalid argument: %s" "$1"
+ ;;
+ *)
+ pkgbases=("$@")
+ break
+ ;;
+ esac
+ done
+
+ # Query packages of a maintainer
+ if [[ -n ${MAINTAINER} ]]; then
+ 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
+ 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
+ if [[ ${jobs} != 1 ]] && (( ${#pkgbases[@]} > 1 )); then
+ # force colors in parallel if parent process is colorized
+ if [[ -n ${BOLD} ]]; then
+ export DEVTOOLS_COLOR=always
+ fi
+ # assign command options
+ if [[ -n "${VERSION}" ]]; then
+ command+=" --switch '${VERSION}'"
+ fi
+ if ! parallel --bar --jobs "${jobs}" "${command}" ::: "${pkgbases[@]}"; then
+ die 'Failed to clone some packages, please check the output'
+ exit 1
+ fi
+ exit 0
+ fi
+
+ for pkgbase in "${pkgbases[@]}"; do
+ if [[ ! -d ${pkgbase} ]]; then
+ msg "Cloning ${pkgbase} ..."
+ project_path=$(gitlab_project_name_to_path "${pkgbase}")
+ remote_url="${GIT_REPO_BASE_URL}/${project_path}.git"
+ if ! git clone --origin origin "${remote_url}" "${pkgbase}"; then
+ die 'failed to clone %s' "${pkgbase}"
+ fi
+ else
+ warning "Skip cloning ${pkgbase}: Directory exists"
+ fi
+
+ pkgctl_repo_configure "${CONFIGURE_OPTIONS[@]}" "${pkgbase}"
+
+ if [[ -n "${VERSION}" ]]; then
+ pkgctl_repo_switch "${VERSION}" "${pkgbase}"
+ fi
+ done
+}
diff --git a/src/lib/repo/configure.sh b/src/lib/repo/configure.sh
new file mode 100644
index 0000000..73300ae
--- /dev/null
+++ b/src/lib/repo/configure.sh
@@ -0,0 +1,259 @@
+#!/bin/bash
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+[[ -z ${DEVTOOLS_INCLUDE_REPO_CONFIGURE_SH:-} ]] || return 0
+DEVTOOLS_INCLUDE_REPO_CONFIGURE_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/gitlab.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/api/gitlab.sh
+
+source /usr/share/makepkg/util/config.sh
+source /usr/share/makepkg/util/message.sh
+
+set -e
+
+
+pkgctl_repo_configure_usage() {
+ local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
+ cat <<- _EOF_
+ Usage: ${COMMAND} [OPTIONS] [PATH]...
+
+ Configure Git packaging repositories according to distro specs and
+ makepkg.conf settings.
+
+ Git author information and the used signing key is set up from
+ makepkg.conf read from any valid location like /etc or XDG_CONFIG_HOME.
+
+ The remote protocol is automatically determined from the author email
+ address by choosing SSH for all official packager identities and
+ read-only HTTPS otherwise.
+
+ OPTIONS
+ --protocol https Configure remote url to use https
+ -j, --jobs N Run up to N jobs in parallel (default: $(nproc))
+ -h, --help Show this help text
+
+ EXAMPLES
+ $ ${COMMAND} *
+_EOF_
+}
+
+get_packager_name() {
+ local packager=$1
+ local packager_pattern="(.+) <(.+@.+)>"
+ local name
+
+ if [[ ! $packager =~ $packager_pattern ]]; then
+ return 1
+ fi
+
+ name=$(echo "${packager}"|sed -E "s/${packager_pattern}/\1/")
+ printf "%s" "${name}"
+}
+
+get_packager_email() {
+ local packager=$1
+ local packager_pattern="(.+) <(.+@.+)>"
+ local email
+
+ if [[ ! $packager =~ $packager_pattern ]]; then
+ return 1
+ fi
+
+ email=$(echo "${packager}"|sed -E "s/${packager_pattern}/\2/")
+ printf "%s" "${email}"
+}
+
+is_packager_name_valid() {
+ local packager_name=$1
+ if [[ -z ${packager_name} ]]; then
+ return 1
+ elif [[ ${packager_name} == "John Doe" ]]; then
+ return 1
+ elif [[ ${packager_name} == "Unknown Packager" ]]; then
+ return 1
+ fi
+ return 0
+}
+
+is_packager_email_official() {
+ local packager_email=$1
+ if [[ -z ${packager_email} ]]; then
+ return 1
+ elif [[ $packager_email =~ .+@archlinux.org ]]; then
+ return 0
+ fi
+ return 1
+}
+
+pkgctl_repo_configure() {
+ # options
+ local GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_HTTPS}
+ local official=0
+ local proto=https
+ local proto_force=0
+ local jobs=
+ jobs=$(nproc)
+ local paths=()
+
+ # variables
+ local -r command=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
+ local path realpath pkgbase remote_url project_path
+ local PACKAGER GPGKEY packager_name packager_email
+
+ while (( $# )); do
+ case $1 in
+ -h|--help)
+ pkgctl_repo_configure_usage
+ exit 0
+ ;;
+ --protocol=https)
+ proto_force=1
+ shift
+ ;;
+ --protocol)
+ (( $# <= 1 )) && die "missing argument for %s" "$1"
+ if [[ $2 == https ]]; then
+ proto_force=1
+ else
+ die "unsupported protocol: %s" "$2"
+ fi
+ shift 2
+ ;;
+ -j|--jobs)
+ (( $# <= 1 )) && die "missing argument for %s" "$1"
+ jobs=$2
+ shift 2
+ ;;
+ --)
+ 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_repo_configure_usage
+ exit 1
+ fi
+ fi
+
+ # Load makepkg.conf variables to be available for packager identity
+ msg "Collecting packager identity from makepkg.conf"
+ # shellcheck disable=2119
+ load_makepkg_config
+ if [[ -n ${PACKAGER} ]]; then
+ if ! packager_name=$(get_packager_name "${PACKAGER}") || \
+ ! packager_email=$(get_packager_email "${PACKAGER}"); then
+ die "invalid PACKAGER format '${PACKAGER}' in makepkg.conf"
+ fi
+ if ! is_packager_name_valid "${packager_name}"; then
+ die "invalid PACKAGER '${PACKAGER}' in makepkg.conf"
+ fi
+ if is_packager_email_official "${packager_email}"; then
+ official=1
+ if (( ! proto_force )); then
+ proto=ssh
+ GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_SSH}
+ fi
+ fi
+ fi
+
+ msg2 "name : ${packager_name:-${YELLOW}undefined${ALL_OFF}}"
+ msg2 "email : ${packager_email:-${YELLOW}undefined${ALL_OFF}}"
+ msg2 "gpg-key : ${GPGKEY:-${YELLOW}undefined${ALL_OFF}}"
+ if [[ ${proto} == ssh ]]; then
+ msg2 "protocol: ${GREEN}${proto}${ALL_OFF}"
+ else
+ msg2 "protocol: ${YELLOW}${proto}${ALL_OFF}"
+ fi
+
+ # parallelization
+ if [[ ${jobs} != 1 ]] && (( ${#paths[@]} > 1 )); then
+ if [[ -n ${BOLD} ]]; then
+ export DEVTOOLS_COLOR=always
+ fi
+ if ! parallel --bar --jobs "${jobs}" "${command}" ::: "${paths[@]}"; then
+ die 'Failed to configure some packages, please check the output'
+ exit 1
+ fi
+ exit 0
+ fi
+
+ for path in "${paths[@]}"; do
+ if ! realpath=$(realpath -e "${path}"); then
+ die "No such directory: ${path}"
+ fi
+
+ pkgbase=$(basename "${realpath}")
+ pkgbase=${pkgbase%.git}
+ msg "Configuring ${pkgbase}"
+
+ if [[ ! -d "${path}/.git" ]]; then
+ die "Not a Git repository: ${path}"
+ fi
+
+ pushd "${path}" >/dev/null
+
+ project_path=$(gitlab_project_name_to_path "${pkgbase}")
+ remote_url="${GIT_REPO_BASE_URL}/${project_path}.git"
+ if ! git remote add origin "${remote_url}" &>/dev/null; then
+ git remote set-url origin "${remote_url}"
+ fi
+
+ # move the master branch to main
+ if [[ $(git symbolic-ref --quiet --short HEAD) == master ]]; then
+ git branch --move main
+ git config branch.main.merge refs/heads/main
+ fi
+
+ git config devtools.version "${GIT_REPO_SPEC_VERSION}"
+ git config pull.rebase true
+ git config branch.autoSetupRebase always
+ git config branch.main.remote origin
+ git config branch.main.rebase true
+
+ git config transfer.fsckobjects true
+ git config fetch.fsckobjects true
+ git config receive.fsckobjects true
+
+ # setup author identity
+ if [[ -n ${packager_name} ]]; then
+ git config user.name "${packager_name}"
+ git config user.email "${packager_email}"
+ fi
+
+ # force gpg for official packagers
+ if (( official )); then
+ git config commit.gpgsign true
+ fi
+
+ # set custom pgp key from makepkg.conf
+ if [[ -n $GPGKEY ]]; then
+ git config commit.gpgsign true
+ git config user.signingKey "${GPGKEY}"
+ fi
+
+ if ! git ls-remote origin &>/dev/null; then
+ warning "configured remote origin may not exist, run:"
+ msg2 "pkgctl repo create ${pkgbase}"
+ fi
+
+ popd >/dev/null
+ done
+}
diff --git a/src/lib/repo/create.sh b/src/lib/repo/create.sh
new file mode 100644
index 0000000..31b46e1
--- /dev/null
+++ b/src/lib/repo/create.sh
@@ -0,0 +1,113 @@
+#!/bin/bash
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+[[ -z ${DEVTOOLS_INCLUDE_REPO_CREATE_SH:-} ]] || return 0
+DEVTOOLS_INCLUDE_REPO_CREATE_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/gitlab.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/api/gitlab.sh
+# shellcheck source=src/lib/repo/clone.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/repo/clone.sh
+# shellcheck source=src/lib/repo/configure.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/repo/configure.sh
+
+set -e
+
+
+pkgctl_repo_create_usage() {
+ local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
+ cat <<- _EOF_
+ Usage: ${COMMAND} [OPTIONS] [PKGBASE]...
+
+ Create a new Git packaging repository in the canonical GitLab namespace.
+
+ This command requires a valid GitLab API authentication. To setup a new
+ GitLab token or check the currently configured one please consult the
+ 'auth' subcommand for further instructions.
+
+ If invoked without a parameter, try to create a packaging repository
+ based on the PKGBUILD from the current working directory and configure
+ the local repository afterwards.
+
+ OPTIONS
+ -c, --clone Clone the Git repository after creation
+ -h, --help Show this help text
+
+ EXAMPLES
+ $ ${COMMAND} libfoo
+_EOF_
+}
+
+pkgctl_repo_create() {
+ # options
+ local pkgbases=()
+ local pkgbase
+ local clone=0
+ local configure=0
+
+ # variables
+ local path
+
+ while (( $# )); do
+ case $1 in
+ -h|--help)
+ pkgctl_repo_create_usage
+ exit 0
+ ;;
+ -c|--clone)
+ clone=1
+ shift
+ ;;
+ -*)
+ die "invalid argument: %s" "$1"
+ ;;
+ *)
+ pkgbases=("$@")
+ break
+ ;;
+ esac
+ done
+
+ # check if invoked without any path from within a packaging repo
+ if (( ${#pkgbases[@]} == 0 )); then
+ if [[ -f PKGBUILD ]]; then
+ if ! path=$(realpath -e .); then
+ die "failed to read path from current directory"
+ fi
+ pkgbases=("$(basename "${path}")")
+ clone=0
+ configure=1
+ else
+ pkgctl_repo_create_usage
+ exit 1
+ fi
+ fi
+
+ # create projects
+ for pkgbase in "${pkgbases[@]}"; do
+ if ! gitlab_api_create_project "${pkgbase}" >/dev/null; then
+ die "failed to create project: ${pkgbase}"
+ fi
+ msg_success "Successfully created ${pkgbase}"
+ if (( clone )); then
+ pkgctl_repo_clone "${pkgbase}"
+ elif (( configure )); then
+ pkgctl_repo_configure
+ fi
+ done
+
+ # some convenience hints if not in auto clone/configure mode
+ if (( ! clone )) && (( ! configure )); then
+ cat <<- _EOF_
+
+ For new clones:
+ $(msg2 "pkgctl repo clone ${pkgbases[*]}")
+ For existing clones:
+ $(msg2 "pkgctl repo configure ${pkgbases[*]}")
+ _EOF_
+ fi
+}
diff --git a/src/lib/repo/switch.sh b/src/lib/repo/switch.sh
new file mode 100644
index 0000000..f411ac2
--- /dev/null
+++ b/src/lib/repo/switch.sh
@@ -0,0 +1,119 @@
+#!/bin/bash
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+[[ -z ${DEVTOOLS_INCLUDE_REPO_SWITCH_SH:-} ]] || return 0
+DEVTOOLS_INCLUDE_REPO_SWITCH_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 -e
+
+
+pkgctl_repo_switch_usage() {
+ local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
+ cat <<- _EOF_
+ Usage: ${COMMAND} [OPTIONS] [VERSION] [PKGBASE]...
+
+ Switch a package source repository to a specified version, tag or
+ branch. The working tree and the index are updated to match the
+ specified ref.
+
+ If a version identifier is specified in the pacman version format, that
+ identifier is automatically translated to the Git tag name accordingly.
+
+ The current working directory is used if no PKGBASE is specified.
+
+ OPTIONS
+ --discard-changes Discard changes if index or working tree is dirty
+ -f, --force An alias for --discard-changes
+ -h, --help Show this help text
+
+ EXAMPLES
+ $ ${COMMAND} 1.14.6-1 gopass gopass-jsonapi
+ $ ${COMMAND} --force 2:1.19.5-1
+ $ ${COMMAND} main
+_EOF_
+}
+
+pkgctl_repo_switch() {
+ if (( $# < 1 )); then
+ pkgctl_repo_switch_usage
+ exit 0
+ fi
+
+ # options
+ local VERSION
+ local GIT_REF
+ local GIT_CHECKOUT_OPTIONS=()
+ local paths path realpath pkgbase
+
+ while (( $# )); do
+ case $1 in
+ -h|--help)
+ pkgctl_repo_switch_usage
+ exit 0
+ ;;
+ -f|--force|--discard-changes)
+ GIT_CHECKOUT_OPTIONS+=("--force")
+ shift
+ ;;
+ --)
+ shift
+ break
+ ;;
+ -*)
+ # - is special to switch back to previous version
+ if [[ $1 != - ]]; then
+ die "invalid argument: %s" "$1"
+ fi
+ ;;&
+ *)
+ if [[ -n ${VERSION} ]]; then
+ break
+ fi
+ VERSION=$1
+ shift
+ ;;
+ esac
+ done
+
+ if [[ -z ${VERSION} ]]; then
+ error "missing positional argument 'VERSION'"
+ pkgctl_repo_switch_usage
+ exit 1
+ fi
+
+ GIT_REF="$(get_tag_from_pkgver "${VERSION}")"
+ paths=("$@")
+
+ # check if invoked without any path from within a packaging repo
+ if (( ${#paths[@]} == 0 )); then
+ if [[ -f PKGBUILD ]]; then
+ paths=(".")
+ else
+ die "Not a package repository: $(realpath -- .)"
+ fi
+ fi
+
+ for path in "${paths[@]}"; do
+ if ! realpath=$(realpath -e -- "${path}"); then
+ die "No such directory: ${path}"
+ fi
+ pkgbase=$(basename "${realpath}")
+
+ if [[ ! -d "${path}/.git" ]]; then
+ error "Not a Git repository: ${path}"
+ continue
+ fi
+
+ if ! git -C "${path}" checkout "${GIT_CHECKOUT_OPTIONS[@]}" "${GIT_REF}"; then
+ die "Failed to switch ${pkgbase} to version ${VERSION}"
+ fi
+ msg "Successfully switched ${pkgbase} to version ${VERSION}"
+ done
+}
diff --git a/src/lib/repo/web.sh b/src/lib/repo/web.sh
new file mode 100644
index 0000000..45ea53b
--- /dev/null
+++ b/src/lib/repo/web.sh
@@ -0,0 +1,84 @@
+#!/bin/bash
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+[[ -z ${DEVTOOLS_INCLUDE_REPO_WEB_SH:-} ]] || return 0
+DEVTOOLS_INCLUDE_REPO_WEB_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/gitlab.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/api/gitlab.sh
+
+set -e
+
+
+pkgctl_repo_web_usage() {
+ local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
+ cat <<- _EOF_
+ Usage: ${COMMAND} [OPTIONS] [PKGBASE]...
+
+ Open the packaging repository's website via xdg-open. If called with
+ no arguments, open the package cloned in the current working directory.
+
+ OPTIONS
+ -h, --help Show this help text
+
+ EXAMPLES
+ $ ${COMMAND} linux
+_EOF_
+}
+
+pkgctl_repo_web() {
+ local pkgbases=()
+ local path giturl pkgbase
+
+ # option checking
+ while (( $# )); do
+ case $1 in
+ -h|--help)
+ pkgctl_repo_web_usage
+ exit 0
+ ;;
+ --)
+ shift
+ break
+ ;;
+ -*)
+ die "invalid argument: %s" "$1"
+ ;;
+ *)
+ pkgbases=("$@")
+ break
+ ;;
+ esac
+ done
+
+ # Check if web mode has xdg-open
+ if ! command -v xdg-open &>/dev/null; then
+ die "The web command requires 'xdg-open'"
+ fi
+
+ # Check if used without pkgnames in a packaging directory
+ if (( ! $# )); then
+ path=${PWD}
+ if [[ ! -d "${path}/.git" ]]; then
+ die "Not a Git repository: ${path}"
+ fi
+
+ giturl=$(git -C "${path}" remote get-url origin)
+ if [[ ${giturl} != *${GIT_PACKAGING_NAMESPACE}* ]]; then
+ die "Not a packaging repository: ${path}"
+ fi
+
+ pkgbase=$(basename "${giturl}")
+ pkgbase=${pkgbase%.git}
+ pkgbases=("${pkgbase}")
+ fi
+
+ for pkgbase in "${pkgbases[@]}"; do
+ path=$(gitlab_project_name_to_path "${pkgbase}")
+ xdg-open "${GIT_PACKAGING_URL_HTTPS}/${path}"
+ done
+}
diff --git a/src/lib/util/git.sh b/src/lib/util/git.sh
new file mode 100644
index 0000000..c4af662
--- /dev/null
+++ b/src/lib/util/git.sh
@@ -0,0 +1,24 @@
+#!/hint/bash
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+[[ -z ${DEVTOOLS_INCLUDE_UTIL_GIT_SH:-} ]] || return 0
+DEVTOOLS_INCLUDE_UTIL_GIT_SH=1
+
+_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+
+
+git_diff_tree() {
+ local commit=$1
+ local path=$2
+ git \
+ --no-pager \
+ diff \
+ --color=never \
+ --color-moved=no \
+ --unified=0 \
+ --no-prefix \
+ --no-ext-diff \
+ "${commit}" \
+ -- "${path}"
+}
diff --git a/src/lib/util/pacman.sh b/src/lib/util/pacman.sh
new file mode 100644
index 0000000..f6c2d5f
--- /dev/null
+++ b/src/lib/util/pacman.sh
@@ -0,0 +1,52 @@
+#!/hint/bash
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+[[ -z ${DEVTOOLS_INCLUDE_UTIL_PACMAN_SH:-} ]] || return 0
+DEVTOOLS_INCLUDE_UTIL_PACMAN_SH=1
+
+_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+# shellcheck source=src/lib/common.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
+
+set -e
+
+
+readonly _DEVTOOLS_PACMAN_CACHE_DIR=${XDG_CACHE_DIR:-$HOME/.cache}/devtools/pacman/db
+readonly _DEVTOOLS_PACMAN_CONF_DIR=${_DEVTOOLS_LIBRARY_DIR}/pacman.conf.d
+readonly _DEVTOOLS_MAKEPKG_CONF_DIR=${_DEVTOOLS_LIBRARY_DIR}/makepkg.conf.d
+
+
+update_pacman_repo_cache() {
+ 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}/multilib.conf" \
+ --dbpath "${_DEVTOOLS_PACMAN_CACHE_DIR}" \
+ -Sy
+ lock_close 10
+}
+
+get_pacman_repo_from_pkgbuild() {
+ local path=${1:-PKGBUILD}
+
+ # shellcheck source=contrib/makepkg/PKGBUILD.proto
+ mapfile -t pkgnames < <(source "${path}"; printf "%s\n" "${pkgname[@]}")
+
+ if (( ${#pkgnames[@]} == 0 )); then
+ die 'Failed to get pkgname from %s' "${path}"
+ return
+ fi
+
+ slock 10 "${_DEVTOOLS_PACMAN_CACHE_DIR}.lock" "Locking pacman database cache"
+ mapfile -t repos < <(pacman --config "${_DEVTOOLS_PACMAN_CONF_DIR}/multilib.conf" \
+ --dbpath "${_DEVTOOLS_PACMAN_CACHE_DIR}" \
+ -S \
+ --print \
+ --print-format '%n %r' \
+ "${pkgnames[0]}" | grep -E "^${pkgnames[0]} " | awk '{print $2}'
+ )
+ lock_close 10
+
+ printf "%s" "${repos[0]}"
+}
diff --git a/src/lib/valid-repos.sh b/src/lib/valid-repos.sh
new file mode 100644
index 0000000..14f90ce
--- /dev/null
+++ b/src/lib/valid-repos.sh
@@ -0,0 +1,22 @@
+#!/hint/bash
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+:
+
+# shellcheck disable=2034
+_repos=(
+ core core-staging core-testing
+ extra extra-staging extra-testing
+ multilib multilib-staging multilib-testing
+ gnome-unstable
+ kde-unstable
+)
+
+# shellcheck disable=2034
+_build_repos=(
+ core-staging core-testing
+ extra extra-staging extra-testing
+ multilib multilib-staging multilib-testing
+ gnome-unstable
+ kde-unstable
+)
diff --git a/src/lib/valid-tags.sh b/src/lib/valid-tags.sh
new file mode 100644
index 0000000..5382c5c
--- /dev/null
+++ b/src/lib/valid-tags.sh
@@ -0,0 +1,26 @@
+#!/hint/bash
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+:
+
+# shellcheck disable=2034
+_arch=(
+ i686
+ x86_64
+ any
+)
+
+# shellcheck disable=2034
+_tags=(
+ core-x86_64 core-any
+ core-staging-x86_64 core-staging-any
+ core-testing-x86_64 core-testing-any
+ extra-x86_64 extra-any
+ extra-staging-x86_64 extra-staging-any
+ extra-testing-x86_64 extra-testing-any
+ multilib-x86_64
+ multilib-testing-x86_64
+ multilib-staging-x86_64
+ kde-unstable-x86_64 kde-unstable-any
+ gnome-unstable-x86_64 gnome-unstable-any
+)
diff --git a/src/lib/version/version.sh b/src/lib/version/version.sh
new file mode 100644
index 0000000..d00a460
--- /dev/null
+++ b/src/lib/version/version.sh
@@ -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
+}
diff --git a/src/makechrootpkg.in b/src/makechrootpkg.in
index e56e912..aac7a0b 100644
--- a/src/makechrootpkg.in
+++ b/src/makechrootpkg.in
@@ -2,8 +2,13 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
-m4_include(lib/common.sh)
-m4_include(lib/archroot.sh)
+_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+
+# shellcheck source=src/lib/common.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
+# shellcheck source=src/lib/archroot.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/archroot.sh
+
source /usr/share/makepkg/util/config.sh
@@ -24,6 +29,7 @@ clean_first=0
run_namcap=0
run_checkpkg=0
temp_chroot=0
+tmp_opts="nosuid,nodev,size=50%,nr_inodes=2m"
bindmounts_ro=()
bindmounts_rw=()
@@ -304,7 +310,7 @@ done
[[ -n $makepkg_user && -z $(id -u "$makepkg_user") ]] && die 'Invalid makepkg user.'
makepkg_user=${makepkg_user:-${SUDO_USER:-$USER}}
-check_root SOURCE_DATE_EPOCH,BUILDTOOL,BUILDTOOLVER,GNUPGHOME,SRCDEST,SRCPKGDEST,PKGDEST,LOGDEST,MAKEFLAGS,PACKAGER
+check_root SOURCE_DATE_EPOCH,BUILDTOOL,BUILDTOOLVER,GNUPGHOME,SRCDEST,SRCPKGDEST,PKGDEST,LOGDEST,MAKEFLAGS,PACKAGER "${BASH_SOURCE[0]}" "$@"
# Canonicalize chrootdir, getting rid of trailing /
chrootdir=$(readlink -e "$passeddir")
@@ -375,6 +381,7 @@ prepare_chroot
if arch-nspawn "$copydir" \
--bind="${PWD//:/\\:}:/startdir" \
--bind="${SRCDEST//:/\\:}:/srcdest" \
+ --tmpfs="/tmp:${tmp_opts}" \
"${bindmounts_ro[@]}" "${bindmounts_rw[@]}" \
/chrootbuild "${makepkg_args[@]}"
then
diff --git a/src/makerepropkg.in b/src/makerepropkg.in
index c58a923..398d4af 100644
--- a/src/makerepropkg.in
+++ b/src/makerepropkg.in
@@ -6,8 +6,12 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
-m4_include(lib/common.sh)
-m4_include(lib/archroot.sh)
+_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+# shellcheck source=src/lib/common.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
+# shellcheck source=src/lib/archroot.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/archroot.sh
+
source /usr/share/makepkg/util/config.sh
source /usr/share/makepkg/util/message.sh
@@ -93,7 +97,9 @@ get_makepkg_conf() {
return 1
fi
msg2 "using makepkg.conf from ${fname}"
- bsdtar xOqf "${buildtool_file/file:\/\//}" "usr/share/devtools/makepkg-${arch}.conf" > "${makepkg_conf}"
+ if ! bsdtar xOqf "${buildtool_file/file:\/\//}" "usr/share/devtools/makepkg.conf.d/${arch}.conf" > "${makepkg_conf}"; then
+ bsdtar xOqf "${buildtool_file/file:\/\//}" "usr/share/devtools/makepkg-${arch}.conf" > "${makepkg_conf}"
+ fi
return 0
}
@@ -119,6 +125,9 @@ OPTIONS
__EOF__
}
+# save all args for check_root
+orig_args=("$@")
+
while getopts 'dM:c:l:h' arg; do
case "$arg" in
d) diffoscope=1 ;;
@@ -131,7 +140,7 @@ while getopts 'dM:c:l:h' arg; do
done
shift $((OPTIND - 1))
-check_root
+check_root "" "${BASH_SOURCE[0]}" "${orig_args[@]}"
[[ -f PKGBUILD ]] || { error "No PKGBUILD in current directory."; exit 1; }
@@ -224,7 +233,7 @@ elif [[ "${BUILDTOOL}" = devtools ]] && get_makepkg_conf "${BUILDTOOL}-${BUILDTO
# fallback to current makepkg.conf
else
warning "Unknown buildtool (${BUILDTOOL}-${BUILDTOOLVER}), using fallback"
- makepkg_conf=@pkgdatadir@/makepkg-${CARCH}.conf
+ makepkg_conf=@pkgdatadir@/makepkg.conf.d/${CARCH}.conf
fi
printf '%s\n' "${allpkgfiles[@]}" | mkarchroot -M "${makepkg_conf}" -U "${archroot_args[@]}" "${namespace}/root" - || exit 1
diff --git a/src/mkarchroot.in b/src/mkarchroot.in
index 5fac505..2abe001 100644
--- a/src/mkarchroot.in
+++ b/src/mkarchroot.in
@@ -2,8 +2,12 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
-m4_include(lib/common.sh)
-m4_include(lib/archroot.sh)
+_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+# shellcheck source=src/lib/common.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
+# shellcheck source=src/lib/archroot.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/archroot.sh
+
# umask might have been changed in /etc/profile
# ensure that sane default is set again
@@ -28,6 +32,9 @@ usage() {
exit 1
}
+# save all args for check_root
+orig_args=("$@")
+
while getopts 'hUC:M:c:f:s' arg; do
case "$arg" in
U) umode=U ;;
@@ -48,7 +55,7 @@ shift $((OPTIND - 1))
(( $# < 2 )) && die 'You must specify a directory and one or more packages.'
-check_root
+check_root "" "${BASH_SOURCE[0]}" "${orig_args[@]}"
working_dir="$(readlink -f "$1")"
shift 1
diff --git a/src/offload-build.in b/src/offload-build.in
index 9e9d71e..027bad3 100644
--- a/src/offload-build.in
+++ b/src/offload-build.in
@@ -102,9 +102,9 @@ mapfile -t files < <(
printf "\t%s\n" "$temp"/*
} >&2 &&
makepkg_user_config="${XDG_CONFIG_HOME:-$HOME/.config}/pacman/makepkg.conf" &&
- makepkg_config="/usr/share/devtools/makepkg-'"${arch}"'.conf" &&
- if [[ -f /usr/share/devtools/makepkg-'"${repo}"'-'"${arch}"'.conf ]]; then
- makepkg_config="/usr/share/devtools/makepkg-'"${repo}"'-'"${arch}"'.conf"
+ makepkg_config="/usr/share/devtools/makepkg.conf.d/'"${arch}"'.conf" &&
+ if [[ -f /usr/share/devtools/makepkg.conf.d/'"${repo}"'-'"${arch}"'.conf ]]; then
+ makepkg_config="/usr/share/devtools/makepkg.conf.d/'"${repo}"'-'"${arch}"'.conf"
fi &&
makepkg --config <(cat "${makepkg_user_config}" "${makepkg_config}" 2>/dev/null) --packagelist &&
printf "%s\n" "${temp}/PKGBUILD"
diff --git a/src/pkgctl.in b/src/pkgctl.in
new file mode 100644
index 0000000..1797b32
--- /dev/null
+++ b/src/pkgctl.in
@@ -0,0 +1,109 @@
+#!/bin/bash
+#
+# 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/config.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/config.sh
+
+set -e
+
+
+usage() {
+ local -r COMMAND=${BASH_SOURCE[0]##*/}
+ cat <<- _EOF_
+ Usage: ${COMMAND} [COMMAND] [OPTIONS]
+
+ Unified command-line frontend for devtools.
+
+ COMMANDS
+ auth Authenticate with services like GitLab
+ build Build packages inside a clean chroot
+ db Pacman database modification for packge 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
+ version Show pkgctl version information
+
+ OPTIONS
+ -h, --help Show this help text
+_EOF_
+}
+
+if (( $# < 1 )); then
+ usage
+ exit 1
+fi
+
+export _DEVTOOLS_COMMAND='pkgctl'
+
+load_devtools_config
+
+# command checking
+while (( $# )); do
+ case $1 in
+ -h|--help)
+ usage
+ exit 0
+ ;;
+ build)
+ _DEVTOOLS_COMMAND+=" $1"
+ shift
+ # shellcheck source=src/lib/build/build.sh
+ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/build/build.sh
+ pkgctl_build "$@"
+ exit 0
+ ;;
+ repo)
+ _DEVTOOLS_COMMAND+=" $1"
+ shift
+ # shellcheck source=src/lib/repo.sh
+ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/repo.sh
+ pkgctl_repo "$@"
+ exit 0
+ ;;
+ auth)
+ _DEVTOOLS_COMMAND+=" $1"
+ shift
+ # shellcheck source=src/lib/auth.sh
+ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/auth.sh
+ pkgctl_auth "$@"
+ exit 0
+ ;;
+ db)
+ _DEVTOOLS_COMMAND+=" $1"
+ shift
+ # shellcheck source=src/lib/auth.sh
+ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/db.sh
+ pkgctl_db "$@"
+ exit 0
+ ;;
+ diff)
+ _DEVTOOLS_COMMAND+=" $1"
+ shift
+ diffpkg "$@"
+ exit 0
+ ;;
+ release)
+ _DEVTOOLS_COMMAND+=" $1"
+ shift
+ # shellcheck source=src/lib/release.sh
+ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/release.sh
+ pkgctl_release "$@"
+ exit 0
+ ;;
+ version|--version|-V)
+ _DEVTOOLS_COMMAND+=" $1"
+ shift
+ # shellcheck source=src/lib/version/version.sh
+ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/version/version.sh
+ pkgctl_version "$@"
+ exit 0
+ ;;
+ *)
+ die "invalid command: %s" "$1"
+ ;;
+ esac
+done
diff --git a/src/rebuildpkgs.in b/src/rebuildpkgs.in
deleted file mode 100644
index eddc17f..0000000
--- a/src/rebuildpkgs.in
+++ /dev/null
@@ -1,111 +0,0 @@
-#!/bin/bash
-#
-# SPDX-License-Identifier: GPL-3.0-or-later
-#
-# This script rebuilds a list of packages in order
-# and reports anything that fails
-#
-# Due to sudo usage, it is recommended to allow makechrootpkg
-# to be run with NOPASSWD in your sudoers file
-#
-# FIXME
-# Currently uses $(pwd)/rebuilds as the directory for rebuilding...
-# TODO make this work for community too
-
-m4_include(lib/common.sh)
-
-if (( $# < 1 )); then
- printf 'Usage: %s <chrootdir> <packages to rebuild>\n' "$(basename "${BASH_SOURCE[0]}")"
- printf ' example: %s ~/chroot readline bash foo bar baz\n' "$(basename "${BASH_SOURCE[0]}")"
- exit 1
-fi
-
-# Source makepkg.conf; fail if it is not found
-if [[ -r '/etc/makepkg.conf' ]]; then
- # shellcheck source=config/makepkg/x86_64.conf
- source '/etc/makepkg.conf'
-else
- die '/etc/makepkg.conf not found!'
-fi
-
-# Source user-specific makepkg.conf overrides
-if [[ -r "${XDG_CONFIG_HOME:-$HOME/.config}/pacman/makepkg.conf" ]]; then
- # shellcheck source=/dev/null
- source "${XDG_CONFIG_HOME:-$HOME/.config}/pacman/makepkg.conf"
-elif [[ -r "$HOME/.makepkg.conf" ]]; then
- # shellcheck source=/dev/null
- source "$HOME/.makepkg.conf"
-fi
-
-bump_pkgrel() {
- # Get the current pkgrel from SVN and update the working copy with it
- # This prevents us from incrementing out of control :)
- pbuild='.svn/text-base/PKGBUILD.svn-base'
- oldrel=$(grep 'pkgrel=' $pbuild | cut -d= -f2)
-
- #remove decimals
- rel=${oldrel%%.*}
-
- newrel=$((rel + 1))
-
- sed -i "s/pkgrel=$oldrel/pkgrel=$newrel/" PKGBUILD
-}
-
-pkg_from_pkgbuild() {
- # we want the sourcing to be done in a subshell so we don't pollute our current namespace
- export CARCH PKGEXT
- # shellcheck source=contrib/makepkg/PKGBUILD.proto
- (source PKGBUILD; echo "$pkgname-$pkgver-$pkgrel-$CARCH$PKGEXT")
-}
-
-chrootdir="$1"; shift
-pkgs=("$@")
-
-SVNPATH='svn+ssh://repos.archlinux.org/srv/repos/svn-packages/svn'
-
-msg "Work will be done in %s" "$(pwd)/rebuilds"
-
-REBUILD_ROOT="$(pwd)/rebuilds"
-mkdir -p "$REBUILD_ROOT"
-cd "$REBUILD_ROOT"
-
-/usr/bin/svn co -N $SVNPATH
-
-FAILED=""
-for pkg in "${pkgs[@]}"; do
- cd "$REBUILD_ROOT/svn-packages"
-
- msg2 "Building '%s'" "$pkg"
- /usr/bin/svn update "$pkg"
- if [[ ! -d "$pkg/trunk" ]]; then
- FAILED="$FAILED $pkg"
- warning "%s does not exist in SVN" "$pkg"
- continue
- fi
- cd "$pkg/trunk/"
-
- bump_pkgrel
-
- if ! sudo makechrootpkg -u -d -r "$chrootdir" -- --noconfirm; then
- FAILED="$FAILED $pkg"
- error "%s Failed!" "$pkg"
- else
- pkgfile=$(pkg_from_pkgbuild)
- if [[ -e $pkgfile ]]; then
- msg2 "%s Complete" "$pkg"
- else
- FAILED="$FAILED $pkg"
- error "%s Failed, no package built!" "$pkg"
- fi
- fi
-done
-
-cd "$REBUILD_ROOT"
-if [[ -n $FAILED ]]; then
- msg 'Packages failed:'
- for pkg in $FAILED; do
- msg2 "%s" "$pkg"
- done
-fi
-
-msg 'SVN pkgbumps in svn-packages/ - commit when ready'
diff --git a/src/sogrep.in b/src/sogrep.in
index d1ca1a1..0ee05cc 100644
--- a/src/sogrep.in
+++ b/src/sogrep.in
@@ -6,13 +6,17 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
-m4_include(lib/common.sh)
+_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+# shellcheck source=src/lib/common.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
+# shellcheck source=src/lib/valid-repos.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-repos.sh
+
# globals
-: ${SOLINKS_MIRROR:="https://mirror.pkgbuild.com"}
+fallback_mirror='https://geo.mirror.pkgbuild.com'
: ${SOCACHE_DIR:="${XDG_CACHE_HOME:-${HOME}/.cache}/sogrep"}
-m4_include(lib/valid-repos.sh)
arches=('x86_64')
# options
@@ -23,11 +27,16 @@ source /usr/share/makepkg/util/parseopts.sh
source /usr/share/makepkg/util/util.sh
recache() {
- local repo arch verbosity=-s
+ local repo arch fallback_linksdburl linksdburl mirror verbosity=-s
(( VERBOSE )) && verbosity=--progress-bar
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
+ mirror="$fallback_mirror"
+ fi
for arch in "${arches[@]}"; do
# delete extracted tarballs from previous sogrep versions
rm -rf "${SOCACHE_DIR}/${arch}/${repo}"
@@ -36,8 +45,20 @@ recache() {
local dbpath=${SOCACHE_DIR}/${arch}/${repo}.links.tar.gz
mkdir -p "${dbpath%/*}"
(( VERBOSE )) && echo "Fetching ${repo}.links.tar.gz..."
- if ! curl -fLR "${verbosity}" -o "${dbpath}" -z "${dbpath}" \
- "${SOLINKS_MIRROR}/${repo}/os/${arch}/${repo}.links.tar.gz"; then
+
+ if [[ "$mirror" == *"/${repo}/os/${arch}" ]]; then
+ linksdburl="${mirror}/${repo}.links.tar.gz"
+ else
+ linksdburl="${mirror}/${repo}/os/${arch}/${repo}.links.tar.gz"
+ fi
+ fallback_linksdburl="${fallback_mirror}/${repo}/os/${arch}/${repo}.links.tar.gz"
+
+ if curl -fLR "${verbosity}" -o "${dbpath}" -z "${dbpath}" "$linksdburl"; then
+ :
+ elif [[ "$linksdburl" != "$fallback_linksdburl" ]] \
+ && curl -fLR "${verbosity}" -o "${dbpath}" -z "${dbpath}" "$fallback_linksdburl"; then
+ :
+ else
echo "error: failed to download links database for repo ${repo}"
exit 1
fi
diff --git a/test/bin/pkgctl b/test/bin/pkgctl
new file mode 100755
index 0000000..9641af3
--- /dev/null
+++ b/test/bin/pkgctl
@@ -0,0 +1,12 @@
+#!/usr/bin/bash
+set -e
+
+root="$(dirname -- "$(readlink -f -- "$0")")/../.."
+
+# always build everything so we use an up-to-date state
+make -C "${root}" -j --no-print-directory --silent
+
+# run pkgctl from the build directory
+export PATH="${root}/build/bin:${PATH}"
+export _DEVTOOLS_LIBRARY_DIR="${root}/build"
+"${root}/build/bin/pkgctl" "$@"