Compare commits

..

1 Commits

Author SHA1 Message Date
Christian Heusel
f77b767971 feat: record against which repo a package was built
Currently releasing a package into a repository it was not built against
would just work, which happened a few times by accident so far:

  $ pkgctl build --staging cowfortune
  # this pushes to extra
  $ pkgctl release cowfortune

We therefore now record against which repo a package was built against
and error out accordingly if this mismatches the repo we want to release
into.

Fixes #179

Component: pkgctl build
Component: pkgctl release
Signed-off-by: Christian Heusel <christian@heusel.eu>
2024-06-10 01:20:23 +02:00
92 changed files with 214 additions and 5058 deletions

View File

@@ -1,15 +0,0 @@
# EditorConfig configuration for devtools
# https://editorconfig.org
# Top-most EditorConfig file
root = true
# Unix-style newlines without trailing whitespaces, but with a newline
# ending every file, utf-8 charset, set indent to tabs
[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8
indent_style = tab
tab_width = 4

View File

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

View File

@@ -74,9 +74,7 @@ Component: pkgctl db remove
- expac - expac
- fakeroot - fakeroot
- findutils - findutils
- glow
- grep - grep
- gum
- jq - jq
- ncurses - ncurses
- openssh - openssh
@@ -94,7 +92,6 @@ Component: pkgctl db remove
- bat (pretty printing) - bat (pretty printing)
- nvchecker (version checking) - nvchecker (version checking)
- reuse (license compliance)
### Development Dependencies ### Development Dependencies

View File

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

View File

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

View File

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

View File

@@ -48,11 +48,13 @@ CXXFLAGS="$CFLAGS -Wp,-D_GLIBCXX_ASSERTIONS"
LDFLAGS="-Wl,-O1 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro -Wl,-z,now \ LDFLAGS="-Wl,-O1 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro -Wl,-z,now \
-Wl,-z,pack-relative-relocs" -Wl,-z,pack-relative-relocs"
LTOFLAGS="-flto=auto" LTOFLAGS="-flto=auto"
RUSTFLAGS="-Cforce-frame-pointers=yes"
#-- Make Flags: change this for DistCC/SMP systems #-- Make Flags: change this for DistCC/SMP systems
#MAKEFLAGS="-j2" #MAKEFLAGS="-j2"
#-- Debugging flags #-- Debugging flags
DEBUG_CFLAGS="-g" DEBUG_CFLAGS="-g"
DEBUG_CXXFLAGS="$DEBUG_CFLAGS" DEBUG_CXXFLAGS="$DEBUG_CFLAGS"
DEBUG_RUSTFLAGS="-C debuginfo=2"
######################################################################### #########################################################################
# BUILD ENVIRONMENT # BUILD ENVIRONMENT
@@ -81,7 +83,7 @@ BUILDENV=(!distcc color !ccache check !sign)
# These are default values for the options=() settings # These are default values for the options=() settings
######################################################################### #########################################################################
# #
# Makepkg defaults: OPTIONS=(!strip docs libtool staticlibs emptydirs !zipman !purge !debug !lto !autodeps) # Makepkg defaults: OPTIONS=(!strip docs libtool staticlibs emptydirs !zipman !purge !debug !lto)
# A negated option will do the opposite of the comments below. # A negated option will do the opposite of the comments below.
# #
#-- strip: Strip symbols from binaries/libraries #-- strip: Strip symbols from binaries/libraries
@@ -93,7 +95,6 @@ BUILDENV=(!distcc color !ccache check !sign)
#-- purge: Remove files specified by PURGE_TARGETS #-- purge: Remove files specified by PURGE_TARGETS
#-- debug: Add debugging flags as specified in DEBUG_* variables #-- debug: Add debugging flags as specified in DEBUG_* variables
#-- lto: Add compile flags for building with link time optimization #-- lto: Add compile flags for building with link time optimization
#-- autodeps: Automatically add depends/provides
# #
OPTIONS=(strip docs !libtool !staticlibs emptydirs zipman purge debug lto) OPTIONS=(strip docs !libtool !staticlibs emptydirs zipman purge debug lto)
@@ -113,8 +114,6 @@ DOC_DIRS=(usr/{,local/}{,share/}{doc,gtk-doc} opt/*/{doc,gtk-doc})
PURGE_TARGETS=(usr/{,share}/info/dir .packlist *.pod) PURGE_TARGETS=(usr/{,share}/info/dir .packlist *.pod)
#-- Directory to store source code in for debug packages #-- Directory to store source code in for debug packages
DBGSRCDIR="/usr/src/debug" DBGSRCDIR="/usr/src/debug"
#-- Prefix and directories for library autodeps
LIB_DIRS=('lib:usr/lib' 'lib32:usr/lib32')
######################################################################### #########################################################################
# PACKAGE OUTPUT # PACKAGE OUTPUT

View File

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

View File

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

View File

@@ -48,11 +48,13 @@ CXXFLAGS="$CFLAGS -Wp,-D_GLIBCXX_ASSERTIONS"
LDFLAGS="-Wl,-O1 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro -Wl,-z,now \ LDFLAGS="-Wl,-O1 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro -Wl,-z,now \
-Wl,-z,pack-relative-relocs" -Wl,-z,pack-relative-relocs"
LTOFLAGS="-flto=auto" LTOFLAGS="-flto=auto"
RUSTFLAGS="-Cforce-frame-pointers=yes"
#-- Make Flags: change this for DistCC/SMP systems #-- Make Flags: change this for DistCC/SMP systems
#MAKEFLAGS="-j2" #MAKEFLAGS="-j2"
#-- Debugging flags #-- Debugging flags
DEBUG_CFLAGS="-g" DEBUG_CFLAGS="-g"
DEBUG_CXXFLAGS="$DEBUG_CFLAGS" DEBUG_CXXFLAGS="$DEBUG_CFLAGS"
DEBUG_RUSTFLAGS="-C debuginfo=2"
######################################################################### #########################################################################
# BUILD ENVIRONMENT # BUILD ENVIRONMENT
@@ -81,7 +83,7 @@ BUILDENV=(!distcc color !ccache check !sign)
# These are default values for the options=() settings # These are default values for the options=() settings
######################################################################### #########################################################################
# #
# Makepkg defaults: OPTIONS=(!strip docs libtool staticlibs emptydirs !zipman !purge !debug !lto !autodeps) # Makepkg defaults: OPTIONS=(!strip docs libtool staticlibs emptydirs !zipman !purge !debug !lto)
# A negated option will do the opposite of the comments below. # A negated option will do the opposite of the comments below.
# #
#-- strip: Strip symbols from binaries/libraries #-- strip: Strip symbols from binaries/libraries
@@ -93,7 +95,6 @@ BUILDENV=(!distcc color !ccache check !sign)
#-- purge: Remove files specified by PURGE_TARGETS #-- purge: Remove files specified by PURGE_TARGETS
#-- debug: Add debugging flags as specified in DEBUG_* variables #-- debug: Add debugging flags as specified in DEBUG_* variables
#-- lto: Add compile flags for building with link time optimization #-- lto: Add compile flags for building with link time optimization
#-- autodeps: Automatically add depends/provides
# #
OPTIONS=(strip docs !libtool !staticlibs emptydirs zipman purge debug lto) OPTIONS=(strip docs !libtool !staticlibs emptydirs zipman purge debug lto)
@@ -113,8 +114,6 @@ DOC_DIRS=(usr/{,local/}{,share/}{doc,gtk-doc} opt/*/{doc,gtk-doc})
PURGE_TARGETS=(usr/{,share}/info/dir .packlist *.pod) PURGE_TARGETS=(usr/{,share}/info/dir .packlist *.pod)
#-- Directory to store source code in for debug packages #-- Directory to store source code in for debug packages
DBGSRCDIR="/usr/src/debug" DBGSRCDIR="/usr/src/debug"
#-- Prefix and directories for library autodeps
LIB_DIRS=('lib:usr/lib' 'lib32:usr/lib32')
######################################################################### #########################################################################
# PACKAGE OUTPUT # PACKAGE OUTPUT

View File

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

View File

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

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace #CheckSpace
VerbosePkgLists VerbosePkgLists
ParallelDownloads = 5 ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# By default, pacman accepts packages signed by keys that its local keyring # 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. # trusts (see pacman-key and its man page), as well as unsigned packages.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace #CheckSpace
VerbosePkgLists VerbosePkgLists
ParallelDownloads = 5 ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# By default, pacman accepts packages signed by keys that its local keyring # 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. # trusts (see pacman-key and its man page), as well as unsigned packages.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace #CheckSpace
VerbosePkgLists VerbosePkgLists
ParallelDownloads = 5 ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# By default, pacman accepts packages signed by keys that its local keyring # 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. # trusts (see pacman-key and its man page), as well as unsigned packages.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace #CheckSpace
VerbosePkgLists VerbosePkgLists
ParallelDownloads = 5 ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# By default, pacman accepts packages signed by keys that its local keyring # 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. # trusts (see pacman-key and its man page), as well as unsigned packages.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace #CheckSpace
VerbosePkgLists VerbosePkgLists
ParallelDownloads = 5 ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# By default, pacman accepts packages signed by keys that its local keyring # 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. # trusts (see pacman-key and its man page), as well as unsigned packages.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace #CheckSpace
VerbosePkgLists VerbosePkgLists
ParallelDownloads = 5 ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# By default, pacman accepts packages signed by keys that its local keyring # 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. # trusts (see pacman-key and its man page), as well as unsigned packages.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace #CheckSpace
VerbosePkgLists VerbosePkgLists
ParallelDownloads = 5 ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# By default, pacman accepts packages signed by keys that its local keyring # 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. # trusts (see pacman-key and its man page), as well as unsigned packages.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace #CheckSpace
VerbosePkgLists VerbosePkgLists
ParallelDownloads = 5 ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# By default, pacman accepts packages signed by keys that its local keyring # 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. # trusts (see pacman-key and its man page), as well as unsigned packages.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace #CheckSpace
VerbosePkgLists VerbosePkgLists
ParallelDownloads = 5 ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# By default, pacman accepts packages signed by keys that its local keyring # 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. # trusts (see pacman-key and its man page), as well as unsigned packages.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace #CheckSpace
VerbosePkgLists VerbosePkgLists
ParallelDownloads = 5 ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# By default, pacman accepts packages signed by keys that its local keyring # 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. # trusts (see pacman-key and its man page), as well as unsigned packages.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace #CheckSpace
VerbosePkgLists VerbosePkgLists
ParallelDownloads = 5 ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# By default, pacman accepts packages signed by keys that its local keyring # 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. # trusts (see pacman-key and its man page), as well as unsigned packages.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace #CheckSpace
VerbosePkgLists VerbosePkgLists
ParallelDownloads = 5 ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# By default, pacman accepts packages signed by keys that its local keyring # 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. # trusts (see pacman-key and its man page), as well as unsigned packages.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace #CheckSpace
VerbosePkgLists VerbosePkgLists
ParallelDownloads = 5 ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# By default, pacman accepts packages signed by keys that its local keyring # 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. # trusts (see pacman-key and its man page), as well as unsigned packages.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace #CheckSpace
VerbosePkgLists VerbosePkgLists
ParallelDownloads = 5 ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# By default, pacman accepts packages signed by keys that its local keyring # 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. # trusts (see pacman-key and its man page), as well as unsigned packages.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace #CheckSpace
VerbosePkgLists VerbosePkgLists
ParallelDownloads = 5 ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# By default, pacman accepts packages signed by keys that its local keyring # 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. # trusts (see pacman-key and its man page), as well as unsigned packages.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace #CheckSpace
VerbosePkgLists VerbosePkgLists
ParallelDownloads = 5 ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# By default, pacman accepts packages signed by keys that its local keyring # 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. # trusts (see pacman-key and its man page), as well as unsigned packages.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace #CheckSpace
VerbosePkgLists VerbosePkgLists
ParallelDownloads = 5 ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# By default, pacman accepts packages signed by keys that its local keyring # 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. # trusts (see pacman-key and its man page), as well as unsigned packages.

View File

@@ -13,10 +13,6 @@ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-repos.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-inspect.sh source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-inspect.sh
# shellcheck source=src/lib/valid-search.sh # shellcheck source=src/lib/valid-search.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-search.sh source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-search.sh
# shellcheck source=src/lib/valid-version.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-version.sh
# shellcheck source=src/lib/valid-issue.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-issue.sh
_colors=(never always auto) _colors=(never always auto)
@@ -149,7 +145,6 @@ _pkgctl_cmds=(
build build
db db
diff diff
issue
release release
repo repo
search search
@@ -305,7 +300,6 @@ _pkgctl_repo_cmds=(
clone clone
configure configure
create create
pull
switch switch
web web
) )
@@ -335,19 +329,6 @@ _pkgctl_repo_clean_args=(
) )
_pkgctl_repo_clean_opts() { _filedir -d; } _pkgctl_repo_clean_opts() { _filedir -d; }
_pkgctl_repo_pull_args=(
--discard-changes
--show-diff
--quiet
--autostash
-f --force
-j --jobs
-h --help
)
_pkgctl_repo_pull_args__jobs_opts() { :; }
_pkgctl_repo_pull_args_j_opts() { _pkgctl_repo_pull_args__jobs_opts; }
_pkgctl_repo_pull_opts() { _filedir -d; }
_pkgctl_repo_configure_args=( _pkgctl_repo_configure_args=(
--protocol --protocol
-j --jobs -j --jobs
@@ -381,25 +362,6 @@ _pkgctl_repo_switch_opts() {
fi fi
} }
_pkgctl_license_cmds=(
check
setup
)
_pkgctl_license_check_args=(
-h --help
)
_pkgctl_license_check_opts() { _filedir -d; }
_pkgctl_license_setup_args=(
--no-check
-f --force
-h --help
)
_pkgctl_license_setup_opts() { _filedir -d; }
_pkgctl_version_cmds=( _pkgctl_version_cmds=(
check check
setup setup
@@ -409,19 +371,14 @@ _pkgctl_version_cmds=(
_pkgctl_version_check_args=( _pkgctl_version_check_args=(
-v --verbose -v --verbose
-h --help -h --help
--json
-F --format
) )
_pkgctl_version_check_opts() { _filedir -d; } _pkgctl_version_check_opts() { _filedir -d; }
_pkgctl_version_check_args__format_opts() { _devtools_completions_version_output_format; }
_pkgctl_version_check_args_F_opts() { _devtools_completions_version_output_format; }
_pkgctl_version_setup_args=( _pkgctl_version_setup_args=(
--prefer-platform-api --prefer-platform-api
--url --url
--no-check --no-check
--no-upstream
-f --force -f --force
-h --help -h --help
) )
@@ -479,185 +436,6 @@ _pkgctl_diff_args__pool_opts() { _filedir -d; }
_pkgctl_diff_args_P_opts() { _pkgctl_diff_args__pool_opts; } _pkgctl_diff_args_P_opts() { _pkgctl_diff_args__pool_opts; }
_pkgctl_diff_opts() { _devtools_completions_all_packages; } _pkgctl_diff_opts() { _devtools_completions_all_packages; }
_pkgctl_issue_cmds=(
close
comment
create
edit
list
move
reopen
view
)
_pkgctl_issue_args=(
-h --help
)
_pkgctl_issue_close_args=(
-p --package
-m --message
-e --edit
-r --resolution
-h --help
)
_pkgctl_issue_close_opts() { :; }
_pkgctl_issue_close_args__package_opts() { _devtools_completions_all_packages; }
_pkgctl_issue_close_args_p_opts() { _pkgctl_issue_close_args__package_opts; }
_pkgctl_issue_close_args__message_opts() { :; }
_pkgctl_issue_close_args_m_opts() { _pkgctl_issue_close_args__message_opts; }
_pkgctl_issue_close_args__resolution_opts() { _devtools_completions_issue_resolution; }
_pkgctl_issue_close_args_r_opts() { _pkgctl_issue_close_args__resolution_opts; }
_pkgctl_issue_comment_args=(
-p --package
-m --message
-e --edit
-h --help
)
_pkgctl_issue_comment_opts() { :; }
_pkgctl_issue_comment_args__package_opts() { _devtools_completions_all_packages; }
_pkgctl_issue_comment_args_p_opts() { _pkgctl_issue_comment_args__package_opts; }
_pkgctl_issue_comment_args__message_opts() { :; }
_pkgctl_issue_comment_args_m_opts() { _pkgctl_issue_comment_args__message_opts; }
_pkgctl_issue_create_args=(
-p --package
-t --title
-F --file
-e --edit
-w --web
--recover
--confidentiality
--priority
--scope
--severity
--status
-h --help
)
_pkgctl_issue_create_opts() { :; }
_pkgctl_issue_create_args__package_opts() { _devtools_completions_all_packages; }
_pkgctl_issue_create_args_p_opts() { _pkgctl_issue_create_args__package_opts; }
_pkgctl_issue_create_args__title_opts() { :; }
_pkgctl_issue_create_args_t_opts() { _pkgctl_issue_create_args__title_opts; }
_pkgctl_issue_create_args__confidentiality_opts() { _devtools_completions_issue_confidentiality; }
_pkgctl_issue_create_args__priority_opts() { _devtools_completions_issue_priority; }
_pkgctl_issue_create_args__scope_opts() { _devtools_completions_issue_scope; }
_pkgctl_issue_create_args__severity_opts() { _devtools_completions_issue_severity; }
_pkgctl_issue_create_args__status_opts() { _devtools_completions_issue_status; }
_pkgctl_issue_edit_args=(
-p --package
-t --title
-e --edit
--recover
--confidentiality
--priority
--resolution
--scope
--severity
--status
-h --help
)
_pkgctl_issue_edit_opts() { :; }
_pkgctl_issue_edit_args__package_opts() { _devtools_completions_all_packages; }
_pkgctl_issue_edit_args_p_opts() { _pkgctl_issue_edit_args__package_opts; }
_pkgctl_issue_edit_args__title_opts() { :; }
_pkgctl_issue_edit_args_t_opts() { _pkgctl_issue_edit_args__title_opts; }
_pkgctl_issue_edit_args__confidentiality_opts() { _devtools_completions_issue_confidentiality; }
_pkgctl_issue_edit_args__priority_opts() { _devtools_completions_issue_priority; }
_pkgctl_issue_edit_args__resolution_opts() { _devtools_completions_issue_resolution; }
_pkgctl_issue_edit_args__scope_opts() { _devtools_completions_issue_scope; }
_pkgctl_issue_edit_args__severity_opts() { _devtools_completions_issue_severity; }
_pkgctl_issue_edit_args__status_opts() { _devtools_completions_issue_status; }
_pkgctl_issue_list_args=(
-g --group
-w --web
-A --all
-c --closed
-U --unconfirmed
--search
--in
-l --label
--confidentiality
--priority
--resolution
--scope
--severity
--status
--assignee
--assigned-to-me
--author
--created-by-me
-h --help
)
_pkgctl_issue_list_opts() { _devtools_completions_all_packages; }
_pkgctl_issue_list_args__search_opts() { :; }
_pkgctl_issue_list_args__in_opts() { _devtools_completions_issue_search_location; }
_pkgctl_issue_list_args__label_opts() { :; }
_pkgctl_issue_list_args_l_opts() { _pkgctl_issue_list_args__label_opts; }
_pkgctl_issue_list_args__confidentiality_opts() { _devtools_completions_issue_confidentiality; }
_pkgctl_issue_list_args__priority_opts() { _devtools_completions_issue_priority; }
_pkgctl_issue_list_args__resolution_opts() { _devtools_completions_issue_resolution; }
_pkgctl_issue_list_args__scope_opts() { _devtools_completions_issue_scope; }
_pkgctl_issue_list_args__severity_opts() { _devtools_completions_issue_severity; }
_pkgctl_issue_list_args__status_opts() { _devtools_completions_issue_status; }
_pkgctl_issue_list_args__assignee_opts() { :; }
_pkgctl_issue_list_args__author_opts() { :; }
_pkgctl_issue_move_args=(
-p --package
-m --message
-e --edit
-h --help
)
_pkgctl_issue_move_opts() {
local subcommand args
subcommand=(repo switch)
args=$(__pkgctl_word_count_after_subcommand "${subcommand[@]}")
if (( args == 0 )); then
:
elif (( args >= 1 )); then
_devtools_completions_all_packages
fi
}
_pkgctl_issue_move_args__package_opts() { _devtools_completions_all_packages; }
_pkgctl_issue_move_args_p_opts() { _pkgctl_issue_move_args__package_opts; }
_pkgctl_issue_move_args__message_opts() { :; }
_pkgctl_issue_move_args_m_opts() { _pkgctl_issue_move_args__message_opts; }
_pkgctl_issue_reopen_args=(
-p --package
-m --message
-e --edit
-h --help
)
_pkgctl_issue_reopen_opts() { :; }
_pkgctl_issue_reopen_args__package_opts() { _devtools_completions_all_packages; }
_pkgctl_issue_reopen_args_p_opts() { _pkgctl_issue_reopen_args__package_opts; }
_pkgctl_issue_reopen_args__message_opts() { :; }
_pkgctl_issue_reopen_args_m_opts() { _pkgctl_issue_reopen_args__message_opts; }
_pkgctl_issue_view_args=(
-p --package
-c --comments
-w --web
-h --help
)
_pkgctl_issue_view_opts() { :; }
_pkgctl_issue_view_args__package_opts() { _devtools_completions_all_packages; }
_pkgctl_issue_view_args_p_opts() { _pkgctl_issue_view_args__package_opts; }
_pkgctl_version_args=( _pkgctl_version_args=(
-h --help -h --help
@@ -692,30 +470,6 @@ _devtools_completions_inspect() {
_devtools_completions_search_format() { _devtools_completions_search_format() {
mapfile -t COMPREPLY < <(compgen -W "${valid_search_output_format[*]}" -- "$cur") mapfile -t COMPREPLY < <(compgen -W "${valid_search_output_format[*]}" -- "$cur")
} }
_devtools_completions_version_output_format() {
mapfile -t COMPREPLY < <(compgen -W "${DEVTOOLS_VALID_VERSION_OUTPUT_FORMAT[*]}" -- "$cur")
}
_devtools_completions_issue_severity() {
mapfile -t COMPREPLY < <(compgen -W "${DEVTOOLS_VALID_ISSUE_SEVERITY[*]}" -- "$cur")
}
_devtools_completions_issue_status() {
mapfile -t COMPREPLY < <(compgen -W "${DEVTOOLS_VALID_ISSUE_STATUS[*]}" -- "$cur")
}
_devtools_completions_issue_scope() {
mapfile -t COMPREPLY < <(compgen -W "${DEVTOOLS_VALID_ISSUE_SCOPE[*]}" -- "$cur")
}
_devtools_completions_issue_search_location() {
mapfile -t COMPREPLY < <(compgen -W "${DEVTOOLS_VALID_ISSUE_SEARCH_LOCATION[*]}" -- "$cur")
}
_devtools_completions_issue_resolution() {
mapfile -t COMPREPLY < <(compgen -W "${DEVTOOLS_VALID_ISSUE_RESOLUTION[*]}" -- "$cur")
}
_devtools_completions_issue_priority() {
mapfile -t COMPREPLY < <(compgen -W "${DEVTOOLS_VALID_ISSUE_PRIORITY[*]}" -- "$cur")
}
_devtools_completions_issue_confidentiality() {
mapfile -t COMPREPLY < <(compgen -W "${DEVTOOLS_VALID_ISSUE_CONFIDENTIALITY[*]}" -- "$cur")
}
__devtools_complete() { __devtools_complete() {
local service=$1 local service=$1

View File

@@ -13,10 +13,6 @@ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-repos.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-inspect.sh source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-inspect.sh
# shellcheck source=src/lib/valid-search.sh # shellcheck source=src/lib/valid-search.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-search.sh source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-search.sh
# shellcheck source=src/lib/valid-version.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-version.sh
# shellcheck source=src/lib/valid-issue.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-issue.sh
_colors=(never always auto) _colors=(never always auto)
@@ -61,7 +57,7 @@ _pkgctl_build_args=(
'--update-checksums[Force computation and update of the checksums (disables auto-detection)]' '--update-checksums[Force computation and update of the checksums (disables auto-detection)]'
'(-e --edit)'{-e,--edit}'[Edit the PKGBUILD before building]' '(-e --edit)'{-e,--edit}'[Edit the PKGBUILD before building]'
'(-r --release)'{-r,--release}'[Automatically commit, tag and release after building]' '(-r --release)'{-r,--release}'[Automatically commit, tag and release after building]'
'(-m --message)'{-m,--message}"[Use the given <msg> as the commit message]:message:" '(-m --message=)'{-m,--message=}"[Use the given <msg> as the commit message]:message:"
'(-u --db-update)'{-u,--db-update}'[Automatically update the pacman database as last action]' '(-u --db-update)'{-u,--db-update}'[Automatically update the pacman database as last action]'
'(-h --help)'{-h,--help}'[Display usage]' '(-h --help)'{-h,--help}'[Display usage]'
'*:git_dir:_files -/' '*:git_dir:_files -/'
@@ -94,115 +90,9 @@ _pkgctl_db_update_args=(
'(-h --help)'{-h,--help}'[Display usage]' '(-h --help)'{-h,--help}'[Display usage]'
) )
_pkgctl_issue_cmds=(
"pkgctl issue command"
"close[Close an issue]"
"comment[Comment on an issue]"
"create[Create a new issue]"
"edit[Edit and modify an issue]"
"list[List project or group issues]"
"move[Move an issue to another project]"
"reopen[Reopen a closed issue]"
"view[Display information about an issue]"
)
_pkgctl_issue_close_args=(
'(-p --package)'{-p,--package}'[Interact with <pkgbase> instead of the current directory]:pkgbase:_devtools_completions_all_packages'
'(-m --message)'{-m,--message}'[Use the provided message as the comment]:message:'
'(-e --edit)'{-e,--edit}'[Edit the comment using an editor]'
'(-r --resolution)'{-r,--resolution}"[Set a specific resolution label]:resolution:($DEVTOOLS_VALID_ISSUE_RESOLUTION[*])"
'(-h --help)'{-h,--help}'[Display usage]'
"1:issue_iid:"
)
_pkgctl_issue_comment_args=(
'(-p --package)'{-p,--package}'[Interact with <pkgbase> instead of the current directory]:pkgbase:_devtools_completions_all_packages'
'(-m --message)'{-m,--message}'[Use the provided message as the comment]:message:'
'(-e --edit)'{-e,--edit}'[Edit the comment using an editor]'
'(-h --help)'{-h,--help}'[Display usage]'
"1:issue_iid:"
)
_pkgctl_issue_create_args=(
'(-p --package)'{-p,--package}'[Interact with <pkgbase> instead of the current directory]:pkgbase:_devtools_completions_all_packages'
'(-t --title)'{-t,--title}'[Use the provided title for the issue]:title:'
'(-F --file)'{-F,--file}'[Take issue description from <file>]:file:_files'
'(-e --edit)'{-e,--edit}'[Edit the issue title and description using an editor]'
'(-w --web)'{-w,--web}'[Continue issue creation with the web interface]'
"--recover[Automatically recover from a failed run]"
"--confidentiality[Set the issue confidentiality]:confidential:($DEVTOOLS_VALID_ISSUE_CONFIDENTIALITY[*])"
"--priority[Set the priority label]:priority:($DEVTOOLS_VALID_ISSUE_PRIORITY[*])"
"--scope[Set the scope label]:scope:($DEVTOOLS_VALID_ISSUE_SCOPE[*])"
"--severity[Set the severity label]:severity:($DEVTOOLS_VALID_ISSUE_SEVERITY[*])"
"--status[Set the status label]:status:($DEVTOOLS_VALID_ISSUE_STATUS[*])"
'(-h --help)'{-h,--help}'[Display usage]'
)
_pkgctl_issue_edit_args=(
'(-p --package)'{-p,--package}'[Interact with <pkgbase> instead of the current directory]:pkgbase:_devtools_completions_all_packages'
'(-t --title)'{-t,--title}'[Use the provided title for the issue]:title:'
'(-e --edit)'{-e,--edit}'[Edit the issue title and description using an editor]'
"--recover[Automatically recover from a failed run]"
"--confidentiality[Set the issue confidentiality]:confidential:($DEVTOOLS_VALID_ISSUE_CONFIDENTIALITY[*])"
"--priority[Set the priority label]:priority:($DEVTOOLS_VALID_ISSUE_PRIORITY[*])"
"--resolution[Set the resolution label]:resolution:($DEVTOOLS_VALID_ISSUE_RESOLUTION[*])"
"--scope[Set the scope label]:scope:($DEVTOOLS_VALID_ISSUE_SCOPE[*])"
"--severity[Set the severity label]:severity:($DEVTOOLS_VALID_ISSUE_SEVERITY[*])"
"--status[Set the status label]:status:($DEVTOOLS_VALID_ISSUE_STATUS[*])"
'(-h --help)'{-h,--help}'[Display usage]'
"1:issue_iid:"
)
_pkgctl_issue_list_args=(
'(-g --group)'{-g,--group}'[Get issues from the whole packaging subgroup]'
'(-w --web)'{-w,--web}'[View results in a browser]'
'(-A --all)'{-A,--all}'[Get all issues including closed]'
'(-c --closed)'{-c,--closed}'[Get only closed issues]'
'(-U --unconfirmed)'{-U,--unconfirmed}'[Shorthand to filter by unconfirmed status label]'
'--search[Search in the fields defined by --in]:search:'
"--in[Search in title or description]:location:($DEVTOOLS_VALID_ISSUE_SEARCH_LOCATION[*])"
"--confidentiality[Filter by confidentiality]:confidential:($DEVTOOLS_VALID_ISSUE_CONFIDENTIALITY[*])"
"--priority[Shorthand to filter by priority label]:priority:($DEVTOOLS_VALID_ISSUE_PRIORITY[*])"
"--resolution[Shorthand to filter by resolution label]:resolution:($DEVTOOLS_VALID_ISSUE_RESOLUTION[*])"
"--scope[Shorthand to filter by scope label]:scope:($DEVTOOLS_VALID_ISSUE_SCOPE[*])"
"--severity[Shorthand to filter by severity label]:severity:($DEVTOOLS_VALID_ISSUE_SEVERITY[*])"
"--status[Shorthand to filter by status label]:status:($DEVTOOLS_VALID_ISSUE_STATUS[*])"
'--assignee[Filter issues assigned to the given username]:username:'
'--assigned-to-me[Shorthand to filter issues assigned to you]'
'--author[Filter issues authored by the given username]:username:'
'--created-by-me[Shorthand to filter issues created by you]'
'(-h --help)'{-h,--help}'[Display usage]'
'*:pkgbase:_devtools_completions_all_packages'
)
_pkgctl_issue_move_args=(
'(-p --package)'{-p,--package}'[Interact with <pkgbase> instead of the current directory]:pkgbase:_devtools_completions_all_packages'
'(-m --message)'{-m,--message}'[Use the provided message as the comment]:message:'
'(-e --edit)'{-e,--edit}'[Edit the comment using an editor]'
'(-h --help)'{-h,--help}'[Display usage]'
"1:issue_iid:"
'1:pkgbase:_devtools_completions_all_packages'
)
_pkgctl_issue_reopen_args=(
'(-p --package)'{-p,--package}'[Interact with <pkgbase> instead of the current directory]:pkgbase:_devtools_completions_all_packages'
'(-m --message)'{-m,--message}'[Use the provided message as the comment]:message:'
'(-e --edit)'{-e,--edit}'[Edit the comment using an editor]'
'(-h --help)'{-h,--help}'[Display usage]'
"1:issue_iid:"
)
_pkgctl_issue_view_args=(
'(-p --package)'{-p,--package}'[Interact with <pkgbase> instead of the current directory]:pkgbase:_devtools_completions_all_packages'
'(-c --comments)'{-c,--comments}'[Show issue comments and activities]'
'(-w --web)'{-w,--web}'[View results in a browser]'
'(-h --help)'{-h,--help}'[Display usage]'
"1:issue_iid:"
)
_pkgctl_release_args=( _pkgctl_release_args=(
'(-m --message)'{-m,--message}"[Use the given <msg> as the commit message]:message:" '(-m --message=)'{-m,--message=}"[Use the given <msg> as the commit message]:message:"
'(-r --repo)'{-r,--repo}"[Specify a target repository for new packages]:repo:($DEVTOOLS_VALID_REPOS[*])" '(-r --repo=)'{-r,--repo=}"[Specify a target repository for new packages]:repo:($DEVTOOLS_VALID_REPOS[*])"
'(-s --staging)'{-s,--staging}'[Release to the staging counterpart of the auto-detected repo]' '(-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]' '(-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]' '(-u --db-update)'{-u,--db-update}'[Automatically update the pacman database after uploading]'
@@ -228,7 +118,6 @@ _pkgctl_repo_cmds=(
"clone[Clone a package repository]" "clone[Clone a package repository]"
"configure[Configure a clone according to distro specs]" "configure[Configure a clone according to distro specs]"
"create[Create a new GitLab package repository]" "create[Create a new GitLab package repository]"
"pull[Update package repositories from their git remote]"
"switch[Switch a package repository to a specified version]" "switch[Switch a package repository to a specified version]"
"web[Open the packaging repository's website]" "web[Open the packaging repository's website]"
) )
@@ -257,17 +146,6 @@ _pkgctl_repo_clone_args=(
'*:packages:_devtools_completions_all_packages' '*:packages:_devtools_completions_all_packages'
) )
_pkgctl_repo_pull_args=(
'--discard-changes[Discard changes if index or working tree is dirty]'
'--quiet[Disable printing longer terminal output]'
'--show-diff[Always enable showing the diff]'
'--autostash[Stash before pulling and unstash afterwards]'
'(-f --force)'{-f,--force}'[Alias for --discard-changes]'
'(-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_configure_args=( _pkgctl_repo_configure_args=(
'--protocol[Configure remote url to use https]:proto:(https)' '--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:' '(-j --jobs)'{-j,--jobs}'[Run up to N jobs in parallel (default: number of processing units)]:jobs:'
@@ -410,8 +288,6 @@ _pkgctl_cmds=(
"build[Build packages inside a clean chroot]" "build[Build packages inside a clean chroot]"
"db[Pacman database modification for package update, move etc]" "db[Pacman database modification for package update, move etc]"
"diff[Compare package files using different modes]" "diff[Compare package files using different modes]"
"issue[Work with GitLab packaging issues]"
"license[Check and manage package license compliance]"
"release[Release step to commit, tag and upload build artifacts]" "release[Release step to commit, tag and upload build artifacts]"
"repo[Manage Git packaging repositories and their configuration]" "repo[Manage Git packaging repositories and their configuration]"
"search[Search for an expression across the GitLab packaging group]" "search[Search for an expression across the GitLab packaging group]"
@@ -423,24 +299,6 @@ _pkgctl_args=(
'(-h --help)'{-h,--help}'[Display usage]' '(-h --help)'{-h,--help}'[Display usage]'
) )
_pkgctl_license_cmds=(
"pkgctl license command"
"check[Checks package licensing compliance using REUSE]"
"setup[Automatically detect and setup a basic REUSE config]"
)
_pkgctl_license_check_args=(
'(-h --help)'{-h,--help}'[Display usage]'
'*:git_dir:_files -/'
)
_pkgctl_license_setup_args=(
'(-f --force)'{-f,--force}'[Overwrite existing REUSE config]'
'--no-check[Do not run license check after setup]'
'(-h --help)'{-h,--help}'[Display usage]'
'*:git_dir:_files -/'
)
_pkgctl_version_cmds=( _pkgctl_version_cmds=(
"pkgctl version command" "pkgctl version command"
"check[Compares local package versions against upstream versions]" "check[Compares local package versions against upstream versions]"
@@ -449,10 +307,8 @@ _pkgctl_version_cmds=(
) )
_pkgctl_version_check_args=( _pkgctl_version_check_args=(
'(-v --verbose)'{-v,--verbose}'[Display results including up-to-date versions]'
'(-h --help)'{-h,--help}'[Display usage]' '(-h --help)'{-h,--help}'[Display usage]'
'(-v --verbose)'{-v,--verbose}'[Display all results including up-to-date versions]'
'--json[Enable printing results in JSON]'
'(-F --format)'{-F,--format}"[Controls the output format of the results]:format:($DEVTOOLS_VALID_VERSION_OUTPUT_FORMAT[*])"
'*:git_dir:_files -/' '*:git_dir:_files -/'
) )
@@ -461,7 +317,6 @@ _pkgctl_version_setup_args=(
'--prefer-platform-api[Prefer platform specific GitHub/GitLab API for complex cases]' '--prefer-platform-api[Prefer platform specific GitHub/GitLab API for complex cases]'
'--url[Derive check target from URL instead of source array]:url:' '--url[Derive check target from URL instead of source array]:url:'
'--no-check[Do not run version check after setup]' '--no-check[Do not run version check after setup]'
'--no-upstream[Setup a blank config for packages without upstream sources]'
'(-h --help)'{-h,--help}'[Display usage]' '(-h --help)'{-h,--help}'[Display usage]'
'*:git_dir:_files -/' '*:git_dir:_files -/'
) )

View File

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

View File

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

View File

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

View File

@@ -15,8 +15,6 @@ Description
Build packages in clean chroot environment, offering various options Build packages in clean chroot environment, offering various options
and functionalities to customize the package building process. and functionalities to customize the package building process.
By default, chroot environments are located in '/var/lib/archbuild/'.
Build Options Build Options
------------- -------------

View File

@@ -1,47 +0,0 @@
pkgctl-issue-close(1)
=====================
Name
----
pkgctl-issue-close - Close an issue
Synopsis
--------
pkgctl issue close [OPTIONS] [IID]
Description
-----------
This command is used to close an issue in Arch Linux packaging projects. It
finalizes the issue by marking it as resolved and optionally providing a reason
for its closure.
To edit an issue, users must specify the issue ID (IID). By default, the
command operates within the current directory, but users have the option to
specify a different package base.
Users can provide a message directly through the command line to explain the
reason for closing the issue. For more detailed or precise reasons, users can
opt to edit the closure message using a text editor before submitting it.
Additionally, a specific resolution label can be set to categorize the closure
reason, with the default label being "completed."
Options
-------
*-p, --package* 'PKGBASE'::
Interact with `PKGBASE` instead of the current directory
*-m, --message* 'MSG'::
Use the provided message as the reason for closing
*-e, --edit*::
Edit the reason for closing using an editor
*-r, --resolution* 'REASON'::
Set a specific resolution label (default: completed)
*-h, --help*::
Show a help text
include::include/footer.asciidoc[]

View File

@@ -1,43 +0,0 @@
pkgctl-issue-comment(1)
=======================
Name
----
pkgctl-issue-comment - Comment on an issue
Synopsis
--------
pkgctl issue comment [OPTIONS] [IID]
Description
-----------
This command allows users to add comments to an issue in Arch Linux packaging
projects. This command is useful for providing feedback, updates, or any
additional information related to an issue directly within the project's issue
tracking system.
By default, the command interacts with the current directory, but users can
specify a different package base if needed.
Users can provide a comment message directly through the command line, ensuring
quick and efficient communication. Additionally, for more detailed or formatted
comments, users have the option to edit their comment using a text editor
before submitting it.
Options
-------
*-p, --package PKGBASE*::
Interact with `PKGBASE` instead of the current directory
*-m, --message MSG*::
Use the provided message as the comment
*-e, --edit*::
Edit the comment using an editor
*-h, --help*::
Show a help text
include::include/footer.asciidoc[]

View File

@@ -1,77 +0,0 @@
pkgctl-issue-create(1)
======================
Name
----
pkgctl-issue-create - Create a new issue
Synopsis
--------
pkgctl issue create [OPTIONS]
Description
-----------
The create command is used to create a new issue for an Arch Linux package.
This command is suitable for reporting bugs, regressions, feature requests, or
any other issues related to a package. It provides a flexible way to document
and track new issues within the project's issue tracking system.
By default, the command operates within the current directory, but users can
specify a different package base if needed.
Users can provide a title for the issue directly through the command line. The
issue description can be supplied from a file or edited using a text editor.
Alternatively, users can opt to continue the issue creation process using the
web interface for a more interactive experience.
The command allows setting various labels and attributes for the issue, such as
confidentiality, priority, scope, severity, and status. These options help
categorize and prioritize the issue appropriately within the tracking system.
In case of a failed run, the command can automatically recover to ensure that
the issue creation process is completed without losing any data.
This command is essential for maintainers, contributors, and users who need to
report new issues related to Arch Linux packages.
Options
-------
*-p, --package* 'PKGBASE'::
Interact with `PKGBASE` instead of the current directory
*-t, --title* 'TITLE'::
Use the provided title for the issue
*-F, --file* 'FILE'::
Take issue description from <file>
*-e, --edit*::
Edit the issue description using an editor
*-w, --web*::
Continue issue creation with the web interface
*--recover*::
Automatically recover from a failed run
*--confidentiality* 'TYPE'::
Set the issue confidentiality
*--priority* 'PRIORITY'::
Set the priority label
*--scope* 'SCOPE'::
Set the scope label
*--severity* 'SEVERITY'::
Set the severity label
*--status* 'STATUS'::
Set the status label
*-h, --help*::
Show a help text
include::include/footer.asciidoc[]

View File

@@ -1,75 +0,0 @@
pkgctl-issue-edit(1)
====================
Name
----
pkgctl-issue-edit - Edit and modify an issue
Synopsis
--------
pkgctl issue edit [OPTIONS] [IID]
Description
-----------
The pkgctl issue edit command is used to modify an existing issue in Arch Linux
packaging projects. This command allows users to update the issue's title,
description, and various attributes, ensuring that the issue information
remains accurate and up-to-date. It also provides a streamlined facility
for bug wranglers to categorize and prioritize issues efficiently.
To edit an issue, users must specify the issue ID (IID). By default, the
command operates within the current directory, but users can specify a
different package base if needed.
The command allows for direct updates to the issue title and description. For
more extensive changes, users can edit these details using a text editor. The
command provides various options to set or update labels and attributes such as
confidentiality, priority, resolution, scope, severity, and status. These
options help maintain clear and organized issue management.
In case of a failed run, the command can automatically recover to ensure that
the editing process is completed without losing any data.
This command is particularly useful for maintainers and contributors who need
to update the details of an issue to reflect new information or changes in
status. It ensures that all issue details are accurately maintained,
facilitating efficient tracking and resolution.
Options
-------
*-p, --package* 'PKGBASE'::
Interact with `PKGBASE` instead of the current directory
*-t, --title* 'TITLE'::
Use the provided title for the issue
*-e, --edit*::
Edit the issue title and description using an editor
*--recover*::
Automatically recover from a failed run
*--confidentiality* 'TYPE'::
Set the issue confidentiality
*--priority* 'PRIORITY'::
Set the priority label
*--resolution* 'REASON'::
Set the resolution label
*--scope* 'SCOPE'::
Set the scope label
*--severity* 'SEVERITY'::
Set the severity label
*--status* 'STATUS'::
Set the status label
*-h, --help*::
Show a help text
include::include/footer.asciidoc[]

View File

@@ -1,100 +0,0 @@
pkgctl-issue-list(1)
====================
Name
----
pkgctl-issue-list - List project or group issues
Synopsis
--------
pkgctl issue list [OPTIONS] [PKGBASE]
Description
-----------
The pkgctl issue list command is used to list issues associated with a specific
packaging project or the entire packaging subgroup in Arch Linux. This command
facilitates efficient issue management by allowing users to list and filter
issues based on various criteria.
Results can also be displayed directly in a web browser for easier navigation
and review.
The command offers filtering options to refine the results. Users can include
closed issues, filter exclusively for unconfirmed issues, or focus on issues
with specific labels such as priority, confidentiality, resolution, scope,
severity, and status.
Additionally, users can search within issue titles or descriptions and filter
issues by the assignee or author. There are also convenient shortcuts to filter
issues assigned to or created by the current user.
This command is particularly useful for package maintainers and contributors in
the Arch Linux community who need to track and manage issues efficiently. It
provides a comprehensive view of the project's or group's issue landscape,
enabling maintainers to address and prioritize issues effectively.
Options
-------
*-g, --group*::
Get issues from the whole packaging subgroup
*-w, --web*::
View results in a browser
*-h, --help*::
Show a help text
Filter Options
--------------
*-A, --all*::
Get all issues including closed
*-c, --closed*::
Get only closed issues
*-U, --unconfirmed*::
Shorthand to filter by unconfirmed status label
*--search* 'SEARCH'::
Search <string> in the fields defined by --in
*--in* 'LOCATION'::
Search in title or description (default: all)
*-l, --label* 'NAME'::
Filter issue by label <name>
*--confidentiality* 'TYPE'::
Filter by confidentiality
*--priority* 'PRIORITY'::
Shorthand to filter by priority label
*--resolution* 'REASON'::
Shorthand to filter by resolution label
*--scope* 'SCOPE'::
Shorthand to filter by scope label
*--severity* 'SEVERITY'::
Shorthand to filter by severity label
*--status* 'STATUS'::
Shorthand to filter by status label
*--assignee* 'USERNAME'::
Filter issues assigned to the given username
*--assigned-to-me*::
Shorthand to filter issues assigned to you
*--author* 'USERNAME'::
Filter issues authored by the given username
*--created-by-me*::
Shorthand to filter issues created by you
include::include/footer.asciidoc[]

View File

@@ -1,43 +0,0 @@
pkgctl-issue-move(1)
====================
Name
----
pkgctl-issue-move - Move an issue to another project
Synopsis
--------
pkgctl issue move [OPTIONS] [IID] [DESTINATION_PACKAGE]
Description
-----------
The move command allows users to transfer an issue from one project to another
within the Arch Linux packaging group. This is useful when an issue is
identified to be more relevant or better handled in a different project.
By default, the command operates within the current directory, but users can
specify a different package base from which to move the issue.
Users must specify the issue ID (IID) and the destination package to which the
issue should be moved. A comment message explaining the reason for the move can
be provided directly through the command line. For more detailed explanations
or additional context, users have the option to edit the move comment using a
text editor before submitting it.
Options
-------
*-p, --package* 'PKGBASE'::
Move from `PKGBASE` instead of the current directory
*-m, --message* 'MSG'::
Use the provided message as the comment
*-e, --edit*::
Edit the comment using an editor
*-h, --help*::
Show a help text
include::include/footer.asciidoc[]

View File

@@ -1,43 +0,0 @@
pkgctl-issue-reopen(1)
======================
Name
----
pkgctl-issue-reopen - Reopen a closed issue
Synopsis
--------
pkgctl issue reopen [OPTIONS] [IID]
Description
-----------
The reopen command is used to reopen a previously closed issue in Arch Linux
packaging projects. This command is useful when an issue needs to be revisited
or additional work is required after it was initially closed.
To edit an issue, users must specify the issue ID (IID). By default, the
command operates within the current directory, but users can specify a
different package base if needed.
Users can provide a message directly through the command line to explain the
reason for reopening the issue. For more detailed explanations or to provide
additional context, users have the option to edit the reopening comment using a
text editor before submitting it.
Options
-------
*-p, --package* 'PKGBASE'::
Interact with `PKGBASE` instead of the current directory
*-m, --message* 'MSG'::
Use the provided message as the comment
*-e, --edit*::
Edit the comment using an editor
*-h, --help*::
Show a help text
include::include/footer.asciidoc[]

View File

@@ -1,43 +0,0 @@
pkgctl-issue-view(1)
====================
Name
----
pkgctl-issue-view - Display information about an issue
Synopsis
--------
pkgctl issue view [OPTIONS]
Description
-----------
This command is designed to display detailed information about a specific issue
in Arch Linux packaging projects. It gathers and pretty prints all relevant
data about the issue, providing a comprehensive view that includes the issue's
description, status as well as labels and creation date.
By default, the command operates within the current directory, but users have
the option to specify a different package base. Additionally, users can choose
to view the issue in a web browser for a more interactive experience.
For those requiring deeper insights, the command can also display all comments
and activities related to the issue, providing a full historical context and
ongoing discussions.
Options
-------
*-p, --package* 'PKGBASE'::
Interact with `PKGBASE` instead of the current directory
*-c, --comments*::
Show issue comments and activities
*-w, --web*::
Open issue in a browser
*-h, --help*::
Show a help text
include::include/footer.asciidoc[]

View File

@@ -1,62 +0,0 @@
pkgctl-issue(1)
===============
Name
----
pkgctl-issue - Work with GitLab packaging issues
Synopsis
--------
pkgctl issue [SUBCOMMAND] [OPTIONS]
Description
-----------
Work with GitLab packaging issues.
Options
-------
*-h, --help*::
Show a help text
Subcommands
-----------
pkgctl issue close::
Close an issue
pkgctl issue comment::
Comment on an issue
pkgctl issue create::
Create a new issue
pkgctl issue edit::
Edit and modify an issue
pkgctl issue list::
List project or group issues
pkgctl issue move::
Move an issue to another project
pkgctl issue reopen::
Reopen a closed issue
pkgctl issue view::
Display information about an issue
See Also
--------
pkgctl-issue-close(1)
pkgctl-issue-comment(1)
pkgctl-issue-create(1)
pkgctl-issue-edit(1)
pkgctl-issue-list(1)
pkgctl-issue-move(1)
pkgctl-issue-reopen(1)
pkgctl-issue-view(1)
include::include/footer.asciidoc[]

View File

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

View File

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

View File

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

View File

@@ -1,50 +0,0 @@
pkgctl-repo-pull(1)
===================
Name
----
pkgctl-repo-pull - Pull in git changes
Synopsis
--------
pkgctl repo pull [OPTIONS] [PATH...]
Description
-----------
Update package repositories from their git remotes.
If only a single package is given the command also automatically shows a diff
of what has changed since the last time the repository was updated.
Options
-------
*--discard-changes*::
Discard changes if the index or working tree was modified. Otherwise abort
if anything was modified.
*--autostash*::
Stash before pulling and unstash afterwards
*--quiet*::
Do not show any longer terminal output like diffs.
*--show-diff*::
Show what has changed since the last time the repository was updated. Is
automatically set when only one 'PATH' is given.
*-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
--------
git-pull(1)
include::include/footer.asciidoc[]

View File

@@ -44,9 +44,6 @@ pkgctl repo configure::
pkgctl repo create:: pkgctl repo create::
Create a new GitLab package repository Create a new GitLab package repository
pkgctl repo pull::
Update package repositories from their git remotes
pkgctl repo switch:: pkgctl repo switch::
Switch a package repository to a specified version Switch a package repository to a specified version
@@ -60,7 +57,6 @@ pkgctl-repo-clean(1)
pkgctl-repo-clone(1) pkgctl-repo-clone(1)
pkgctl-repo-configure(1) pkgctl-repo-configure(1)
pkgctl-repo-create(1) pkgctl-repo-create(1)
pkgctl-repo-pull(1)
pkgctl-repo-switch(1) pkgctl-repo-switch(1)
pkgctl-repo-web(1) pkgctl-repo-web(1)

View File

@@ -34,25 +34,12 @@ PKGBUILD. Refer to the configuration section in pkgctl-version(1).
Options Options
------- -------
*-v, --verbose*::
Display results including up-to-date versions
*-h, --help*:: *-h, --help*::
Show a help text Show a help text
Filter Options
--------------
*-v, --verbose*::
Display all results including up-to-date versions
Output Options
--------------
*--json*::
Enable printing in JSON; Shorthand for `'--format json'`
*-F, --format* 'FORMAT'::
Controls the output format of the results; `FORMAT` is `'pretty'`,
or `'json'` (default `pretty`)
Exit Codes Exit Codes
---------- ----------

View File

@@ -42,15 +42,10 @@ Options
*--url* 'URL':: *--url* 'URL'::
Derive check target from the given URL instead of the source array entries Derive check target from the given URL instead of the source array entries
*--no-check*:: *--no-check*::
Do not run pkgctl-version-check(1) after setup Do not run pkgctl-version-check(1) after setup
*--no-upstream*::
Setup a blank config for packages without upstream sources, like meta
packages. This must only be used for cases without an upstream, please
reach out to the developer team for guidance regarding upstream sources
that are hard to configure.
*-h, --help*:: *-h, --help*::
Show a help text Show a help text

View File

@@ -46,9 +46,6 @@ pkgctl db::
pkgctl diff:: pkgctl diff::
Compare package files using different modes Compare package files using different modes
pkgctl issue::
Work with GitLab packaging issues
pkgctl release:: pkgctl release::
Release step to commit, tag and upload build artifacts Release step to commit, tag and upload build artifacts
@@ -69,7 +66,6 @@ pkgctl-auth(1)
pkgctl-build(1) pkgctl-build(1)
pkgctl-db(1) pkgctl-db(1)
pkgctl-diff(1) pkgctl-diff(1)
pkgctl-issue(1)
pkgctl-release(1) pkgctl-release(1)
pkgctl-repo(1) pkgctl-repo(1)
pkgctl-search(1) pkgctl-search(1)

View File

@@ -65,7 +65,6 @@ nspawn_args=(
--machine="arch-nspawn-$$" --machine="arch-nspawn-$$"
--as-pid2 --as-pid2
--console=autopipe --console=autopipe
--timezone=off
) )
if (( ${#cache_dirs[@]} == 0 )); then if (( ${#cache_dirs[@]} == 0 )); then
@@ -112,13 +111,7 @@ copy_hostconf () {
[[ -n $host_cachemirrors ]] && printf 'CacheServer = %s\n' "${host_cachemirrors[@]}" >>"$working_dir/etc/pacman.d/mirrorlist" [[ -n $host_cachemirrors ]] && printf 'CacheServer = %s\n' "${host_cachemirrors[@]}" >>"$working_dir/etc/pacman.d/mirrorlist"
[[ -n $pac_conf ]] && cp "$pac_conf" "$working_dir/etc/pacman.conf" [[ -n $pac_conf ]] && cp "$pac_conf" "$working_dir/etc/pacman.conf"
if [[ -n $makepkg_conf ]]; then [[ -n $makepkg_conf ]] && cp "$makepkg_conf" "$working_dir/etc/makepkg.conf"
cp "$makepkg_conf" "$working_dir/etc/makepkg.conf"
if [[ -d "${makepkg_conf}.d" ]] && is_globfile "${makepkg_conf}.d"/*.conf; then
mkdir --parents "$working_dir/etc/makepkg.conf.d/"
cp "${makepkg_conf}.d/"*.conf "$working_dir/etc/makepkg.conf.d/"
fi
fi
local file local file
for file in "${files[@]}"; do for file in "${files[@]}"; do

View File

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

View File

@@ -140,7 +140,7 @@ for _pkgname in "${pkgname[@]}"; do
bsdtar tf "$TEMPDIR/$oldpkg" | sort > "$TEMPDIR/filelist-$_pkgname-old" bsdtar tf "$TEMPDIR/$oldpkg" | sort > "$TEMPDIR/filelist-$_pkgname-old"
bsdtar tf "$pkgfile" | sort > "$TEMPDIR/filelist-$_pkgname" bsdtar tf "$pkgfile" | sort > "$TEMPDIR/filelist-$_pkgname"
diff --side-by-side --suppress-common-lines --width="${COLUMNS:-130}" --color=auto "$TEMPDIR/filelist-$_pkgname-old" "$TEMPDIR/filelist-$_pkgname" sdiff -s "$TEMPDIR/filelist-$_pkgname-old" "$TEMPDIR/filelist-$_pkgname"
find-libprovides "$TEMPDIR/$oldpkg" 2>/dev/null | sort > "$TEMPDIR/libraries-$_pkgname-old" find-libprovides "$TEMPDIR/$oldpkg" 2>/dev/null | sort > "$TEMPDIR/libraries-$_pkgname-old"
find-libprovides "$pkgfile" 2>/dev/null | sort > "$TEMPDIR/libraries-$_pkgname" find-libprovides "$pkgfile" 2>/dev/null | sort > "$TEMPDIR/libraries-$_pkgname"

View File

@@ -7,6 +7,8 @@ _DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
# shellcheck source=src/lib/util/srcinfo.sh # shellcheck source=src/lib/util/srcinfo.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/srcinfo.sh source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/srcinfo.sh
# shellcheck source=src/lib/state.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/state.sh
source /usr/share/makepkg/util/util.sh source /usr/share/makepkg/util/util.sh
@@ -120,20 +122,8 @@ if (( ${#validpgpkeys[@]} != 0 )); then
git add --force -- keys/pgp/* git add --force -- keys/pgp/*
fi fi
needsversioning=()
if [[ ! -e REUSE.toml || ! -e LICENSE || ! -d LICENSES ]]; then
# TODO: Make this a hard failure in the future after packagers have had
# some time to add licenses to all packages.
warning "package doesn't have proper licensing information, set it up using:"
msg2 'pkgctl license setup'
else
pkgctl license check
needsversioning+=(REUSE.toml LICENSE LICENSES/*)
fi
# find files which should be under source control # find files which should be under source control
needsversioning+=(PKGBUILD) needsversioning=(PKGBUILD)
for s in "${source[@]}"; do for s in "${source[@]}"; do
[[ $s != *://* ]] && needsversioning+=("$s") [[ $s != *://* ]] && needsversioning+=("$s")
done done
@@ -155,7 +145,7 @@ if (( ${#needsversioning[*]} )); then
if [[ ! -f "${file}" ]]; then if [[ ! -f "${file}" ]]; then
continue continue
fi fi
if ! git ls-files --error-unmatch "$file" >/dev/null; then if ! git ls-files --error-unmatch "$file"; then
die "%s is not under version control" "$file" die "%s is not under version control" "$file"
fi fi
done done
@@ -246,6 +236,9 @@ declare -a uploads
declare -a commit_arches declare -a commit_arches
declare -a skip_arches declare -a skip_arches
BUILD_STATE_DIR=$(get_state_folder "build-state")
state_file=
for _arch in "${arch[@]}"; do for _arch in "${arch[@]}"; do
if [[ -n $commit_arch && ${_arch} != "$commit_arch" ]]; then if [[ -n $commit_arch && ${_arch} != "$commit_arch" ]]; then
skip_arches+=("$_arch") skip_arches+=("$_arch")
@@ -259,6 +252,12 @@ for _arch in "${arch[@]}"; do
skip_arches+=("$_arch") skip_arches+=("$_arch")
continue 2 continue 2
fi fi
state_file="${BUILD_STATE_DIR}/$(basename "${pkgfile}").txt"
if [[ -f "${state_file}" ]] && [[ $(cat "${state_file}") != "${repo}" ]]; then
error "%s was not built against '%s', aborting" "${pkgfile}" "${repo}"
exit 1
fi
uploads+=("$pkgfile") uploads+=("$pkgfile")
done done

View File

@@ -14,8 +14,6 @@ set -o pipefail
archweb_query_all_packages() { archweb_query_all_packages() {
local -a pkgbases
[[ -z ${WORKDIR:-} ]] && setup_workdir [[ -z ${WORKDIR:-} ]] && setup_workdir
stat_busy "Query all released packages" stat_busy "Query all released packages"
@@ -38,7 +36,6 @@ archweb_query_all_packages() {
archweb_query_maintainer_packages() { archweb_query_maintainer_packages() {
local maintainer=$1 local maintainer=$1
local -a pkgbases
[[ -z ${WORKDIR:-} ]] && setup_workdir [[ -z ${WORKDIR:-} ]] && setup_workdir

View File

@@ -8,12 +8,8 @@ DEVTOOLS_INCLUDE_API_GITLAB_SH=1
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@} _DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
# shellcheck source=src/lib/common.sh # shellcheck source=src/lib/common.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
# shellcheck source=src/lib/cache.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/cache.sh
# shellcheck source=src/lib/config.sh # shellcheck source=src/lib/config.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/config.sh source "${_DEVTOOLS_LIBRARY_DIR}"/lib/config.sh
# shellcheck source=src/lib/valid-issue.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-issue.sh
set -e set -e
@@ -119,13 +115,11 @@ gitlab_api_call_paged() {
local next_page=1 local next_page=1
local total_pages=1 local total_pages=1
local known_total_pages=1
local percentage=100
while [[ -n "${next_page}" ]]; do while [[ -n "${next_page}" ]]; do
percentage=$(( 100 * next_page / total_pages )) percentage=$(( 100 * next_page / total_pages ))
printf "📡 Querying GitLab: %s/%s [%s] %%spinner%%" \ printf "📡 Querying GitLab: %s/%s [%s] %%spinner%%" \
"${BOLD}${next_page}" "${known_total_pages}" "${percentage}%${ALL_OFF}" \ "${BOLD}${next_page}" "${total_pages}" "${percentage}%${ALL_OFF}" \
> "${tmp_file}" > "${tmp_file}"
mv "${tmp_file}" "${status_file}" mv "${tmp_file}" "${status_file}"
@@ -150,15 +144,6 @@ gitlab_api_call_paged() {
next_page=$(grep "x-next-page" "${header}" | tr -d '\r' | awk '{ print $2 }') next_page=$(grep "x-next-page" "${header}" | tr -d '\r' | awk '{ print $2 }')
total_pages=$(grep "x-total-pages" "${header}" | tr -d '\r' | awk '{ print $2 }') total_pages=$(grep "x-total-pages" "${header}" | tr -d '\r' | awk '{ print $2 }')
# The api is not guaranteed to return x-total-pages for larger query results
# https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23931
# https://gitlab.com/gitlab-org/gitlab/-/issues/436373
if (( total_pages == 0 )); then
total_pages=${next_page}
known_total_pages="?"
else
known_total_pages=${total_pages}
fi
done done
jq --slurp add "${api_workdir}"/result.* > "${outfile}" jq --slurp add "${api_workdir}"/result.* > "${outfile}"
@@ -249,101 +234,6 @@ gitlab_api_get_project_name_mapping() {
return 0 return 0
} }
gitlab_lookup_project_names() {
local status_file=$1; shift
local project_ids=("$@")
local graphql_lookup_batch=200
local project_name_cache_file tmp_file from length percentage
local project_slice query projects mapping_output
# collect project ids whose name needs to be looked up
project_name_cache_file=$(get_cache_file gitlab/project_id_to_name)
lock 11 "${project_name_cache_file}" "Locking project name cache"
# early exit if there is nothing new to look up
if (( ! ${#project_ids[@]} )); then
cat "${project_name_cache_file}"
# close project name cache lock
lock_close 11
return
fi
# reduce project_ids to uncached entries
mapfile -t project_ids < <(
printf "%s\n" "${project_ids[@]}" | \
grep --invert-match --file <(awk '{ print $1 }' < "${project_name_cache_file}" ))
# look up project names
tmp_file=$(mktemp --tmpdir="${WORKDIR}" pkgctl-gitlab-api-spinner.tmp.XXXXXXXXXX)
local entries="${#project_ids[@]}"
local until=0
while (( until < entries )); do
from=${until}
until=$(( until + graphql_lookup_batch ))
if (( until > entries )); then
until=${entries}
fi
length=$(( until - from ))
percentage=$(( 100 * until / entries ))
printf "📡 Querying GitLab project names: %s/%s [%s] %%spinner%%" \
"${BOLD}${until}" "${entries}" "${percentage}%${ALL_OFF}" \
> "${tmp_file}"
mv "${tmp_file}" "${status_file}"
project_slice=("${project_ids[@]:${from}:${length}}")
printf -v projects '"gid://gitlab/Project/%s",' "${project_slice[@]}"
query='{
projects(after: "" ids: ['"${projects}"']) {
pageInfo {
startCursor
endCursor
hasNextPage
}
nodes {
id
name
}
}
}'
mapping_output=$(gitlab_api_get_project_name_mapping "${query}")
# update cache
while read -r project_id project_name; do
printf "%s %s\n" "${project_id}" "${project_name}" >> "${project_name_cache_file}"
done < <(jq --raw-output \
'.[] | "\(.id | rindex("/") as $lastSlash | .[$lastSlash+1:]) \(.name)"' \
<<< "${mapping_output}")
done
cat "${project_name_cache_file}"
# close project name cache lock
lock_close 11
}
longest_package_name_from_ids() {
local project_ids=("$@")
local longest=0
# collect project ids whose name needs to be looked up
project_name_cache_file=$(get_cache_file gitlab/project_id_to_name)
lock 11 "${project_name_cache_file}" "Locking project name cache"
# read project_id to name mapping from cache
while read -r project_id project_name; do
if (( ${#project_name} > longest )) && in_array "${project_id}" "${project_ids[@]}"; then
longest="${#project_name}"
fi
done < "${project_name_cache_file}"
# close project name cache lock
lock_close 11
printf "%s" "${longest}"
}
# Convert arbitrary project names to GitLab valid path names. # Convert arbitrary project names to GitLab valid path names.
# #
# GitLab has several limitations on project and group names and also maintains # GitLab has several limitations on project and group names and also maintains
@@ -412,492 +302,3 @@ gitlab_api_search() {
return 0 return 0
} }
# https://docs.gitlab.com/ee/api/projects.html#get-single-project
gitlab_project() {
local project=$1
local outfile project_path
[[ -z ${WORKDIR:-} ]] && setup_workdir
outfile=$(mktemp --tmpdir="${WORKDIR}" pkgctl-gitlab-api.XXXXXXXXXX)
project_path=$(gitlab_project_name_to_path "${project}")
if ! gitlab_api_call "${outfile}" GET "projects/archlinux%2fpackaging%2fpackages%2f${project_path}/"; then
return 1
fi
cat "${outfile}"
return 0
}
# TODO: parallelize
# https://docs.gitlab.com/ee/api/issues.html#list-project-issues
gitlab_projects_issues_list() {
local project=$1
local status_file=$2
local params=${3:-}
local data=${4:-}
local outfile
[[ -z ${WORKDIR:-} ]] && setup_workdir
outfile=$(mktemp --tmpdir="${WORKDIR}" pkgctl-gitlab-api.XXXXXXXXXX)
if ! gitlab_api_call_paged "${outfile}" "${status_file}" GET "/projects/archlinux%2fpackaging%2fpackages%2f${project}/issues?${params}" "${data}"; then
return 1
fi
cat "${outfile}"
return 0
}
# TODO: parallelize
# https://docs.gitlab.com/ee/api/issues.html#list-project-issues
gitlab_group_issue_list() {
local group=$1
local status_file=$2
local params=${3:-}
local data=${4:-}
local outfile
[[ -z ${WORKDIR:-} ]] && setup_workdir
outfile=$(mktemp --tmpdir="${WORKDIR}" pkgctl-gitlab-api.XXXXXXXXXX)
group=${group//\//%2f}
params=${params//\[/%5B}
params=${params//\]/%5D}
if ! gitlab_api_call_paged "${outfile}" "${status_file}" GET "/groups/${group}/issues?${params}" "${data}"; then
return 1
fi
cat "${outfile}"
}
# https://docs.gitlab.com/ee/api/issues.html#single-project-issue
gitlab_project_issue() {
local pkgbase=$1
local iid=$2
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}")
if ! gitlab_api_call "${outfile}" GET "projects/archlinux%2fpackaging%2fpackages%2f${project_path}/issues/${iid}"; then
return 1
fi
if ! path=$(jq --raw-output --exit-status '.title' < "${outfile}"); then
msg_error " failed to query path: $(cat "${outfile}")"
return 1
fi
cat "${outfile}"
return 0
}
gitlab_project_issue_create() {
local pkgbase=$1
local title=$2
local description=$3
local confidential=$4
shift 4
local labels=("${@}")
local outfile data iid project_path
[[ -z ${WORKDIR:-} ]] && setup_workdir
outfile=$(mktemp --tmpdir="${WORKDIR}" pkgctl-gitlab-api.XXXXXXXXXX)
project_path=$(gitlab_project_name_to_path "${pkgbase}")
data=$(jq --null-input \
--arg title "${title}" \
--arg description "${description}" \
--arg confidential "${confidential}" \
--arg labels "$(join_by , "${labels[@]}")" \
'$ARGS.named')
if ! gitlab_api_call "${outfile}" POST "/projects/archlinux%2fpackaging%2fpackages%2f${project_path}/issues" "${data}"; then
return 1
fi
if ! iid=$(jq --raw-output --exit-status '.iid' < "${outfile}"); then
msg_error " failed to query note: $(cat "${outfile}")"
return 1
fi
cat "${outfile}"
return 0
}
# TODO: parallelize
# https://docs.gitlab.com/ee/api/notes.html#list-project-issue-notes
gitlab_project_issue_notes() {
local project=$1
local iid=$2
local status_file=$3
local params=${4:-}
local outfile
[[ -z ${WORKDIR:-} ]] && setup_workdir
outfile=$(mktemp --tmpdir="${WORKDIR}" pkgctl-gitlab-api.XXXXXXXXXX)
if ! gitlab_api_call_paged "${outfile}" "${status_file}" GET "/projects/archlinux%2fpackaging%2fpackages%2f${project}/issues/${iid}/notes?${params}"; then
return 1
fi
cat "${outfile}"
return 0
}
# https://docs.gitlab.com/ee/api/issues.html#edit-an-issue
gitlab_project_issue_edit() {
local pkgbase=$1
local iid=$2
local params=$3
local data=${4:-}
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}")
if ! gitlab_api_call "${outfile}" PUT "/projects/archlinux%2fpackaging%2fpackages%2f${project_path}/issues/${iid}?${params}" "${data}"; then
return 1
fi
if ! path=$(jq --raw-output --exit-status '.title' < "${outfile}"); then
msg_error " failed to query path: $(cat "${outfile}")"
return 1
fi
cat "${outfile}"
return 0
}
gitlab_create_project_issue_note() {
local pkgbase=$1
local iid=$2
local body=$3
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}")
data=$(jq --null-input --arg body "${body}" '$ARGS.named')
if ! gitlab_api_call "${outfile}" POST "/projects/archlinux%2fpackaging%2fpackages%2f${project_path}/issues/${iid}/notes" "${data}"; then
return 1
fi
if ! path=$(jq --raw-output --exit-status '.body' < "${outfile}"); then
msg_error " failed to query note: $(cat "${outfile}")"
return 1
fi
cat "${outfile}"
return 0
}
gitlab_project_issue_move() {
local pkgbase=$1
local iid=$2
local to_project_id=$3
local outfile path project_path
[[ -z ${WORKDIR:-} ]] && setup_workdir
outfile=$(mktemp --tmpdir="${WORKDIR}" pkgctl-gitlab-api.XXXXXXXXXX)
project_path=$(gitlab_project_name_to_path "${pkgbase}")
if ! gitlab_api_call "${outfile}" POST "/projects/archlinux%2fpackaging%2fpackages%2f${project_path}/issues/${iid}/move?to_project_id=${to_project_id}"; then
return 1
fi
if ! path=$(jq --raw-output --exit-status '.title' < "${outfile}"); then
msg_error " failed to move issue: $(cat "${outfile}")"
return 1
fi
cat "${outfile}"
return 0
}
gitlab_severity_from_labels() {
local labels=("$@")
local severity="unknown"
local label
for label in "${labels[@]}"; do
if [[ ${label} == severity::* ]]; then
severity="${label#*-}"
fi
done
printf "%s" "${severity}"
}
severity_as_gitlab_label() {
local severity=$1
case "${severity}" in
lowest)
printf "severity::5-%s" "${severity}" ;;
low)
printf "severity::4-%s" "${severity}" ;;
medium)
printf "severity::3-%s" "${severity}" ;;
high)
printf "severity::2-%s" "${severity}" ;;
critical)
printf "severity::1-%s" "${severity}" ;;
*)
return 1 ;;
esac
return 0
}
gitlab_priority_from_labels() {
local labels=("$@")
local priority="normal"
local label
for label in "${labels[@]}"; do
if [[ ${label} == priority::* ]]; then
priority="${label#*-}"
fi
done
printf "%s" "${priority}"
}
priority_as_gitlab_label() {
local priority=$1
case "${priority}" in
low)
printf "priority::4-%s" "${priority}" ;;
normal)
printf "priority::3-%s" "${priority}" ;;
high)
printf "priority::2-%s" "${priority}" ;;
urgent)
printf "priority::1-%s" "${priority}" ;;
*)
return 1 ;;
esac
return 0
}
gitlab_scope_from_labels() {
local labels=("$@")
local scope="unknown"
local label
for label in "${labels[@]}"; do
if [[ ${label} == scope::* ]]; then
scope="${label#*::}"
fi
done
printf "%s" "${scope}"
}
scope_as_gitlab_label() {
local scope=$1
if ! in_array "${scope}" "${DEVTOOLS_VALID_ISSUE_SCOPE[@]}"; then
return 1
fi
printf "scope::%s" "${scope}"
}
gitlab_scope_short() {
local scope=$1
case "${scope}" in
regression)
scope=regress ;;
enhancement)
scope=enhance ;;
documentation)
scope=doc ;;
reproducibility)
scope=repro ;;
out-of-date)
scope=ood ;;
esac
printf "%s" "${scope}"
}
gitlab_scope_color() {
local scope=$1
local color="${GRAY}"
case "${scope}" in
bug)
color="${DARK_RED}" ;;
feature)
color="${DARK_BLUE}" ;;
security)
color="${RED}" ;;
question)
color="${PURPLE}" ;;
regression)
color="${DARK_RED}" ;;
enhancement)
color="${DARK_BLUE}" ;;
documentation)
color="${ALL_OFF}" ;;
reproducibility)
color="${DARK_GREEN}" ;;
out-of-date)
color="${DARK_YELLOW}" ;;
esac
printf "%s" "${color}"
}
status_as_gitlab_label() {
local status=$1
if ! in_array "${status}" "${DEVTOOLS_VALID_ISSUE_STATUS[@]}"; then
return 1
fi
printf "status::%s" "${status}"
return 0
}
gitlab_issue_state_display() {
local state=$1
if [[ ${state} == opened ]]; then
state=open
fi
printf "%s" "${state}"
}
gitlab_issue_status_from_labels() {
local labels=("$@")
local status=unconfirmed
local label
for label in "${labels[@]}"; do
if [[ ${label} == status::* ]]; then
status="${label#*::}"
fi
done
printf "%s" "${status}"
}
gitlab_issue_status_short() {
local status=$1
if [[ ${status} == waiting-* ]]; then
status=waiting
fi
printf "%s" "${status}"
}
gitlab_issue_status_color() {
local status=$1
local color="${GRAY}"
case "${status}" in
confirmed)
color="${GREEN}" ;;
in-progress)
color="${YELLOW}" ;;
in-review)
color="${PURPLE}" ;;
on-hold|unconfirmed)
color="${GRAY}" ;;
waiting-input|waiting-upstream)
color="${DARK_BLUE}" ;;
esac
printf "%s" "${color}"
}
resolution_as_gitlab_label() {
local resolution=$1
if ! in_array "${resolution}" "${DEVTOOLS_VALID_ISSUE_RESOLUTION[@]}"; then
return 1
fi
printf "resolution::%s" "${resolution}"
}
gitlab_resolution_from_labels() {
local labels=("$@")
local label
for label in "${labels[@]}"; do
if [[ ${label} == resolution::* ]]; then
printf "%s" "${label#*::}"
return 0
fi
done
return 1
}
gitlab_resolution_color() {
local resolution=$1
local color=""
case "${resolution}" in
cant-reproduce)
color="${DARK_YELLOW}" ;;
completed)
color="${GREEN}" ;;
duplicate)
color="${GRAY}" ;;
invalid)
color="${DARK_YELLOW}" ;;
not-a-bug)
color="${GRAY}" ;;
upstream)
color="${PURPLE}" ;;
wont-fix)
color="${DARK_BLUE}" ;;
esac
printf "%s" "${color}"
}
gitlab_severity_color() {
local severity=$1
local color="${PURPLE}"
case "${severity}" in
lowest)
color="${DARK_GREEN}" ;;
low)
color="${GREEN}" ;;
medium)
color="${YELLOW}" ;;
high)
color="${RED}" ;;
critical)
color="${RED}${UNDERLINE}" ;;
esac
printf "%s" "${color}"
}
gitlab_priority_color() {
local priority=$1
local color="${PURPLE}"
case "${priority}" in
low)
color="${DARK_GREEN}" ;;
normal)
color="${GREEN}" ;;
high)
color="${YELLOW}" ;;
urgent)
color="${RED}" ;;
esac
printf "%s" "${color}"
}
gitlab_issue_state_color() {
local state=$1
local state_color="${DARK_GREEN}"
if [[ ${state} == closed ]]; then
state_color="${DARK_RED}"
fi
printf "%s" "${state_color}"
}

View File

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

View File

@@ -165,7 +165,7 @@ pkgctl_aur_drop_from_repo() {
warning 'Did not find %s in any repository, please delete manually' "${pkgbase}" warning 'Did not find %s in any repository, please delete manually' "${pkgbase}"
else else
msg2 " repo: ${pkgrepo}" msg2 " repo: ${pkgrepo}"
pkgctl_db_remove --noconfirm "${pkgrepo}" "${pkgbase}" pkgctl_db_remove "${pkgrepo}" "${pkgbase}"
fi fi
popd >/dev/null popd >/dev/null

View File

@@ -63,7 +63,7 @@ pkgctl_auth_login() {
esac esac
done done
personal_access_token_url="https://${GITLAB_HOST}/-/user_settings/personal_access_tokens?name=pkgctl+token&scopes=api,write_repository" personal_access_token_url="https://${GITLAB_HOST}/-/profile/personal_access_tokens?name=pkgctl+token&scopes=api,write_repository"
cat <<- _EOF_ cat <<- _EOF_
Logging into ${BOLD}${GITLAB_HOST}${ALL_OFF} Logging into ${BOLD}${GITLAB_HOST}${ALL_OFF}

View File

@@ -12,6 +12,8 @@ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/db/update.sh source "${_DEVTOOLS_LIBRARY_DIR}"/lib/db/update.sh
# shellcheck source=src/lib/release.sh # shellcheck source=src/lib/release.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/release.sh source "${_DEVTOOLS_LIBRARY_DIR}"/lib/release.sh
# shellcheck source=src/lib/state.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/state.sh
# shellcheck source=src/lib/util/git.sh # shellcheck source=src/lib/util/git.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/git.sh source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/git.sh
# shellcheck source=src/lib/util/srcinfo.sh # shellcheck source=src/lib/util/srcinfo.sh
@@ -42,10 +44,10 @@ pkgctl_build_usage() {
Build packages inside a clean chroot Build packages inside a clean chroot
Build packages in clean chroot environment, offering various options When a new pkgver is set using the appropriate PKGBUILD options the
and functionalities to customize the package building process. checksums are automatically updated.
By default, chroot environments are located in /var/lib/archbuild/. TODO
BUILD OPTIONS BUILD OPTIONS
--arch ARCH Specify architectures to build for (disables auto-detection) --arch ARCH Specify architectures to build for (disables auto-detection)
@@ -79,8 +81,8 @@ pkgctl_build_usage() {
EXAMPLES EXAMPLES
$ ${COMMAND} $ ${COMMAND}
$ ${COMMAND} --rebuild --staging --release --message 'libyay 0.42 rebuild' libfoo libbar $ ${COMMAND} --rebuild --staging --message 'libyay 0.42 rebuild' libfoo libbar
$ ${COMMAND} --pkgver=1.42 --release --db-update $ ${COMMAND} --pkgver 1.42 --release --db-update
_EOF_ _EOF_
} }
@@ -129,6 +131,7 @@ pkgctl_build() {
local PKGVER= local PKGVER=
local PKGREL= local PKGREL=
local MESSAGE= local MESSAGE=
local BUILD_STATE_DIR=
local paths=() local paths=()
local BUILD_ARCH=() local BUILD_ARCH=()
@@ -304,6 +307,8 @@ pkgctl_build() {
fi fi
fi fi
BUILD_STATE_DIR=$(get_state_folder "build-state")
# assign default worker slot # assign default worker slot
if [[ -z ${WORKER_SLOT} ]] && ! WORKER_SLOT="$(tty | sed 's|/dev/pts/||')"; then if [[ -z ${WORKER_SLOT} ]] && ! WORKER_SLOT="$(tty | sed 's|/dev/pts/||')"; then
WORKER_SLOT=$(( RANDOM % $(nproc) + 1 )) WORKER_SLOT=$(( RANDOM % $(nproc) + 1 ))
@@ -481,8 +486,6 @@ pkgctl_build() {
# shellcheck disable=SC2119 # shellcheck disable=SC2119
write_srcinfo_file write_srcinfo_file
# test-install (some of) the produced packages
if [[ ${INSTALL_TO_HOST} == auto ]] || [[ ${INSTALL_TO_HOST} == all ]]; then
# shellcheck disable=2119 # shellcheck disable=2119
load_makepkg_config load_makepkg_config
@@ -492,14 +495,17 @@ pkgctl_build() {
for pkg in "${pkgname[@]}"; do for pkg in "${pkgname[@]}"; do
pkg_architecture=$(get_pkg_arch "$pkg") pkg_architecture=$(get_pkg_arch "$pkg")
pkgfile=$(realpath "$(printf "%s/%s-%s-%s%s\n" "${PKGDEST:-.}" "$pkg" "$version" "$pkg_architecture" "$PKGEXT")") pkgpath=$(realpath "$(printf "%s\n" "${PKGDEST:-.}")")
pkgfile=$(printf "%s-%s-%s%s\n" "$pkg" "$version" "$pkg_architecture" "$PKGEXT")
# check if we install all packages or if the (split-)package is already installed # check if we install all packages or if the (split-)package is already installed
if [[ ${INSTALL_TO_HOST} == all ]] || ( [[ ${INSTALL_TO_HOST} == auto ]] && pacman -Qq -- "$pkg" &>/dev/null ); then if [[ ${INSTALL_TO_HOST} == all ]] || ( [[ ${INSTALL_TO_HOST} == auto ]] && pacman -Qq -- "$pkg" &>/dev/null ); then
INSTALL_HOST_PACKAGES+=("$pkgfile") INSTALL_HOST_PACKAGES+=("${pkgpath}/${pkgfile}")
fi fi
# save against which repo we have built the package
printf "%s" "${pkgrepo}" > "${BUILD_STATE_DIR}/${pkgfile}.txt"
done done
fi
# release the build # release the build
if (( RELEASE )); then if (( RELEASE )); then

View File

@@ -18,9 +18,6 @@ export LANG=C.UTF-8
# Avoid systemd trying to color the terminal on systemd-nspawn # Avoid systemd trying to color the terminal on systemd-nspawn
export SYSTEMD_TINT_BACKGROUND=no export SYSTEMD_TINT_BACKGROUND=no
# Avoid diffoscope looking at remote debug info through readelf
unset DEBUGINFOD_URLS
# Set buildtool properties # Set buildtool properties
export BUILDTOOL=devtools export BUILDTOOL=devtools
export BUILDTOOLVER=@buildtoolver@ export BUILDTOOLVER=@buildtoolver@
@@ -37,18 +34,8 @@ export PACKAGING_REPO_RELEASE_HOST=repos.archlinux.org
export PKGBASE_MAINTAINER_URL=https://archlinux.org/packages/pkgbase-maintainer export PKGBASE_MAINTAINER_URL=https://archlinux.org/packages/pkgbase-maintainer
export AUR_URL_SSH=aur@aur.archlinux.org export AUR_URL_SSH=aur@aur.archlinux.org
# Create or reuse a shared SSH control socket with ControlMaster=auto. The
# connection is initialized on the first use and persisted for some time, so
# multiple invokations of devtools can share it.
# shellcheck disable=SC2016
export SSH_OPTS=(
-o ControlMaster=auto
-o ControlPersist=60s
-o ControlPath='${XDG_RUNTIME_DIR}/devtools-%r@%h:%p'
)
export RSYNC_OPTS=( export RSYNC_OPTS=(
--rsh="ssh ${SSH_OPTS[*]}" --rsh=ssh
--checksum --checksum
--copy-links --copy-links
--human-readable --human-readable
@@ -67,23 +54,15 @@ if [[ -t 2 && "$TERM" != dumb ]] || [[ ${DEVTOOLS_COLOR} == always ]]; then
if tput setaf 0 &>/dev/null; then if tput setaf 0 &>/dev/null; then
PURPLE="$(tput setaf 5)" PURPLE="$(tput setaf 5)"
DARK_GREEN="$(tput setaf 2)" DARK_GREEN="$(tput setaf 2)"
DARK_RED="$(tput setaf 1)"
DARK_BLUE="$(tput setaf 4)"
DARK_YELLOW="$(tput setaf 3)"
UNDERLINE="$(tput smul)" UNDERLINE="$(tput smul)"
GRAY=$(tput setaf 242)
else else
PURPLE="\e[35m" PURPLE="\e[35m"
DARK_GREEN="\e[32m" DARK_GREEN="\e[32m"
DARK_RED="\e[31m"
DARK_BLUE="\e[34m"
DARK_YELLOW="\e[33m"
UNDERLINE="\e[4m" UNDERLINE="\e[4m"
GRAY=""
fi fi
else else
# shellcheck disable=2034 # shellcheck disable=2034
declare -gr ALL_OFF='' BOLD='' BLUE='' GREEN='' RED='' YELLOW='' PURPLE='' DARK_RED='' DARK_GREEN='' DARK_BLUE='' DARK_YELLOW='' UNDERLINE='' GRAY='' declare -gr ALL_OFF='' BOLD='' BLUE='' GREEN='' RED='' YELLOW='' PURPLE='' DARK_GREEN='' UNDERLINE=''
fi fi
stat_busy() { stat_busy() {
@@ -141,8 +120,6 @@ print_workdir_error() {
} }
_setup_workdir=false _setup_workdir=false
# Ensure that there is no outside value for WORKDIR leaking in
unset WORKDIR
setup_workdir() { setup_workdir() {
[[ -z ${WORKDIR:-} ]] && WORKDIR=$(mktemp -d --tmpdir "${0##*/}.XXXXXXXXXX") [[ -z ${WORKDIR:-} ]] && WORKDIR=$(mktemp -d --tmpdir "${0##*/}.XXXXXXXXXX")
_setup_workdir=true _setup_workdir=true
@@ -389,55 +366,7 @@ is_globfile() {
} }
join_by() { join_by() {
local IFS=" " local IFS="$1"
local sep=$1
local split
shift shift
split=$(printf "%s" "$*") echo "$*"
echo "${split//${IFS}/"${sep}"}"
}
trim_string() {
local max_length=$1
local string=$2
if (( ${#string} > max_length )); then
# Subtract 3 from max_length to accommodate "..."
max_length=$((max_length - 3))
string="${string:0:max_length}..."
fi
printf "%s" "${string}"
}
relative_date_unit() {
local target_date=$1
local now diff value units unit names
target_date=$(date -d "$1" +%s)
now=$(date +%s)
diff=$((now - target_date))
local names=(year month week day hour minute second)
declare -A units=(
[year]=$((60 * 60 * 24 * 365))
[month]=$((60 * 60 * 24 * 30))
[week]=$((60 * 60 * 24 * 7))
[day]=$((60 * 60 * 24))
[hour]=$((60 * 60))
[minute]=60
[second]=1
)
for unit in "${names[@]}"; do
local value=$((diff / ${units[${unit}]}))
if (( value > 1 )); then
printf "%s %ss" "${value}" "${unit}"
return
elif (( value == 1 )); then
printf "%s %s" "${value}" "${unit}"
return
fi
done
printf "1 second"
} }

View File

@@ -1,194 +0,0 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_ISSUE_CLOSE_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_ISSUE_CLOSE_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 -eo pipefail
pkgctl_issue_close_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS] [IID]
This command is used to close an issue in Arch Linux packaging projects. It
finalizes the issue by marking it as resolved and optionally providing a reason
for its closure.
By default, the command operates within the current directory, but users have
the option to specify a different package base.
Users can provide a message directly through the command line to explain the
reason for closing the issue. Additionally, a specific resolution label can be
set to categorize the closure reason, with the default label being "completed."
OPTIONS
-p, --package PKGBASE Interact with <pkgbase> instead of the current directory
-m, --message MSG Use the provided message as the reason for closing
-e, --edit Edit the reason for closing using an editor
-r, --resolution REASON Set a specific resolution label (default: completed)
-h, --help Show this help text
EXAMPLES
$ ${COMMAND} 42
$ ${COMMAND} --edit --package linux 42
_EOF_
}
pkgctl_issue_close() {
if (( $# < 1 )); then
pkgctl_issue_close_usage
exit 0
fi
local iid=""
local pkgbase=""
local message=""
local edit=0
local labels=()
local resolution="completed"
local issue note
local params="state_event=close"
# option checking
while (( $# )); do
case $1 in
-h|--help)
pkgctl_issue_close_usage
exit 0
;;
-m|--message)
(( $# <= 1 )) && die "missing argument for %s" "$1"
message=$2
shift 2
;;
-p|--package)
(( $# <= 1 )) && die "missing argument for %s" "$1"
pkgbase=$2
shift 2
;;
-e|--edit)
edit=1
shift
;;
--resolution)
(( $# <= 1 )) && die "missing argument for %s" "$1"
if ! label="$(resolution_as_gitlab_label "$2")"; then
die "invalid argument for %s: %s" "$1" "$2"
fi
params+="&add_labels=${label}"
shift 2
;;
-*)
die "invalid argument: %s" "$1"
;;
*)
iid=$1
shift
;;
esac
done
if [[ -z ${iid} ]]; then
die "missing issue iid argument"
fi
if [[ -z ${pkgbase} ]]; then
if ! [[ -f PKGBUILD ]]; then
die "missing --package option or PKGBUILD in current directory"
fi
pkgbase=$(realpath --canonicalize-existing .)
fi
pkgbase=$(basename "${pkgbase}")
# spawn editor
if (( edit )); then
msgfile=$(mktemp --tmpdir="${WORKDIR}" pkgctl-issue-note.XXXXXXXXXX.md)
printf "%s\n" "${message}" >> "${msgfile}"
if [[ -n $VISUAL ]]; then
$VISUAL "${msgfile}" || die
elif [[ -n $EDITOR ]]; then
$EDITOR "${msgfile}" || die
else
die "No usable editor found (tried \$VISUAL, \$EDITOR)."
fi
message=$(cat "${msgfile}")
fi
# comment on issue
if [[ -n ${message} ]]; then
if ! note=$(gitlab_create_project_issue_note "${pkgbase}" "${iid}" "${message}"); then
msg_error "Failed to comment on issue ${BOLD}#${iid}${ALL_OFF}"
exit 1
fi
msg_success "Commented on issue ${BOLD}#${iid}${ALL_OFF}"
fi
# close issue
if ! issue=$(gitlab_project_issue_edit "${pkgbase}" "${iid}" "${params}"); then
msg_error "Failed to close issue ${BOLD}#${iid}${ALL_OFF}"
exit 1
fi
msg_success "Closed issue ${BOLD}#${iid}${ALL_OFF}"
echo
{ read -r iid; read -r title; read -r state; read -r created_at; read -r author; } < <(
jq --raw-output ".iid, .title, .state, .created_at, .author.username" <<< "${issue}"
)
mapfile -t labels < <(
jq --raw-output ".labels[]" <<< "${issue}"
)
severity="$(gitlab_severity_from_labels "${labels[@]}")"
severity_color="$(gitlab_severity_color "${severity}")"
created_at=$(relative_date_unit "${created_at}")
state_color="$(gitlab_issue_state_color "${state}")"
state="$(gitlab_issue_state_display "${state}")"
status="$(gitlab_issue_status_from_labels "${labels[@]}")"
status_color="$(gitlab_issue_status_color "${status}")"
scope="$(gitlab_scope_from_labels "${labels[@]}")"
scope_color="$(gitlab_scope_color "${scope}")"
scope_label=""
if [[ ${scope} != unknown ]]; then
scope_label="${scope_color}${scope}${ALL_OFF} ${GRAY}${ALL_OFF} "
fi
resolution_label=""
if resolution="$(gitlab_resolution_from_labels "${labels[@]}")"; then
resolution_color="$(gitlab_resolution_color "${resolution}")"
resolution_label="${resolution_color}${resolution}${ALL_OFF} ${GRAY}${ALL_OFF} "
fi
printf "%s%s • %s%sseverity %s • %s • %s%sopened by %s %s ago%s\n" \
"${state_color}${state}${ALL_OFF}" "${GRAY}" "${resolution_label}" "${severity_color}" "${severity}${GRAY}" \
"${status_color}${status}${GRAY}" "${scope_label}" "${GRAY}" "${author}" "${created_at}" "${ALL_OFF}"
printf "%s %s\n" "${BOLD}${title}${ALL_OFF}" "${GRAY}#${iid}${ALL_OFF}"
# show comment
if [[ -n ${note} ]]; then
{ read -r created_at; read -r author; } < <(
jq --raw-output ".created_at, .author.username" <<< "${note}"
)
body=$(jq --raw-output ".body" <<< "${note}")
created_at=$(relative_date_unit "${created_at}")
echo
echo "${BOLD}Comments / Notes${ALL_OFF}"
printf -v spaces '%*s' $(( COLUMNS - 2 )) ''
printf '%s\n\n' "${spaces// /─}"
printf "%s commented%s %s ago%s\n" "${author}" "${GRAY}" "${created_at}" "${ALL_OFF}"
echo "${body}" | glow
fi
}

View File

@@ -1,130 +0,0 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_ISSUE_COMMENT_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_ISSUE_COMMENT_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 -eo pipefail
pkgctl_issue_comment_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS] [IID]
This command allows users to add comments to an issue in Arch Linux packaging
projects. This command is useful for providing feedback, updates, or any
additional information related to an issue directly within the project's issue
tracking system.
By default, the command interacts with the current directory, but users can
specify a different package base if needed.
OPTIONS
-p, --package PKGBASE Interact with <pkgbase> instead of the current directory
-m, --message MSG Use the provided message as the comment
-e, --edit Edit the comment using an editor
-h, --help Show this help text
EXAMPLES
$ ${COMMAND} --message "I've attached some logs" 42
$ ${COMMAND} --package linux 42
$ ${COMMAND} 42
_EOF_
}
pkgctl_issue_comment() {
if (( $# < 1 )); then
pkgctl_issue_comment_usage
exit 0
fi
local iid=""
local pkgbase=""
local message=""
local edit=0
local note
# option checking
while (( $# )); do
case $1 in
-h|--help)
pkgctl_issue_comment_usage
exit 0
;;
-m|--message)
(( $# <= 1 )) && die "missing argument for %s" "$1"
message=$2
shift 2
;;
-p|--package)
(( $# <= 1 )) && die "missing argument for %s" "$1"
pkgbase=$2
shift 2
;;
-e|--edit)
edit=1
shift
;;
-*)
die "invalid argument: %s" "$1"
;;
*)
iid=$1
shift
;;
esac
done
if [[ -z ${iid} ]]; then
die "missing issue iid argument"
fi
if [[ -z ${pkgbase} ]]; then
if ! [[ -f PKGBUILD ]]; then
die "missing --package option or PKGBUILD in current directory"
fi
pkgbase=$(realpath --canonicalize-existing .)
fi
pkgbase=$(basename "${pkgbase}")
# spawn editor
if (( edit )) || [[ -z ${message} ]]; then
msgfile=$(mktemp --tmpdir="${WORKDIR}" pkgctl-issue-note.XXXXXXXXXX.md)
printf "%s\n" "${message}" >> "${msgfile}"
if [[ -n $VISUAL ]]; then
$VISUAL "${msgfile}" || die
elif [[ -n $EDITOR ]]; then
$EDITOR "${msgfile}" || die
else
die "No usable editor found (tried \$VISUAL, \$EDITOR)."
fi
message=$(< "${msgfile}")
fi
# comment on issue
if ! note=$(gitlab_create_project_issue_note "${pkgbase}" "${iid}" "${message}"); then
msg_error "Failed to comment on issue ${BOLD}#${iid}${ALL_OFF}"
exit 1
fi
msg_success "Commented on issue ${BOLD}#${iid}${ALL_OFF}"
echo
{ read -r created_at; read -r author; } < <(
jq --raw-output ".created_at, .author.username" <<< "${note}"
)
body=$(jq --raw-output ".body" <<< "${note}")
created_at=$(relative_date_unit "${created_at}")
printf "%s commented%s %s ago%s\n" "${author}" "${GRAY}" "${created_at}" "${ALL_OFF}"
echo "${body}" | glow
}

View File

@@ -1,296 +0,0 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_ISSUE_CREATE_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_ISSUE_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/util/term.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/term.sh
set -eo pipefail
pkgctl_issue_create_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS]
The create command is used to create a new issue for an Arch Linux package.
This command is suitable for reporting bugs, regressions, feature requests, or
any other issues related to a package. It provides a flexible way to document
and track new issues within the project's issue tracking system.
By default, the command operates within the current directory, but users can
specify a different package base if needed.
Users can provide a title for the issue directly through the command line.
The command allows setting various labels and attributes for the issue, such as
confidentiality, priority, scope, severity, and status.
In case of a failed run, the command can automatically recover to ensure that
the issue creation process is completed without losing any data.
OPTIONS
-p, --package PKGBASE Interact with <pkgbase> instead of the current directory
-t, --title TITLE Use the provided title for the issue
-F, --file FILE Take issue description from <file>
-e, --edit Edit the issue description using an editor
-w, --web Continue issue creation with the web interface
--recover Automatically recover from a failed run
--confidentiality TYPE Set the issue confidentiality
--priority PRIORITY Set the priority label
--scope SCOPE Set the scope label
--severity SEVERITY Set the severity label
--status STATUS Set the status label
-h, --help Show this help text
EXAMPLES
$ ${COMMAND} --package linux --title "some very informative title"
_EOF_
}
pkgctl_issue_create() {
if (( $# < 1 )); then
pkgctl_issue_create_usage
exit 0
fi
local pkgbase=""
local title_placeholder="PLACEHOLDER"
local title="${title_placeholder}"
local description=""
local labels=()
local msgfile=""
local edit=0
local web=0
local recover=0
local confidential=0
local issue_template_url="https://gitlab.archlinux.org/archlinux/packaging/templates/-/raw/master/.gitlab/issue_templates/Default.md"
local issue_template
local recovery_home=${XDG_DATA_HOME:-$HOME/.local/share}/devtools/recovery
local recovery_file
local issue_url
local project_path
local result
local iid
local message
local editor
# option checking
while (( $# )); do
case $1 in
-h|--help)
pkgctl_issue_create_usage
exit 0
;;
-t|--title)
(( $# <= 1 )) && die "missing argument for %s" "$1"
title=$2
shift 2
;;
-p|--package)
(( $# <= 1 )) && die "missing argument for %s" "$1"
pkgbase=$2
shift 2
;;
-F|--file)
(( $# <= 1 )) && die "missing argument for %s" "$1"
msgfile=$2
shift 2
;;
-e|--edit)
edit=1
shift
;;
-w|--web)
web=1
shift
;;
--recover)
recover=1
shift
;;
--confidentiality)
(( $# <= 1 )) && die "missing argument for %s" "$1"
if ! in_array "$2" "${DEVTOOLS_VALID_ISSUE_CONFIDENTIALITY[@]}"; then
die "invalid argument for %s: %s" "$1" "$2"
fi
if [[ $2 == confidential ]]; then
confidential=1
fi
shift 2
;;
--priority)
(( $# <= 1 )) && die "missing argument for %s" "$1"
if ! label="$(priority_as_gitlab_label "$2")"; then
die "invalid argument for %s: %s" "$1" "$2"
fi
labels+=("$label")
shift 2
;;
--scope)
(( $# <= 1 )) && die "missing argument for %s" "$1"
if ! label="$(scope_as_gitlab_label "$2")"; then
die "invalid argument for %s: %s" "$1" "$2"
fi
labels+=("$label")
shift 2
;;
--severity)
(( $# <= 1 )) && die "missing argument for %s" "$1"
if ! label="$(severity_as_gitlab_label "$2")"; then
die "invalid argument for %s: %s" "$1" "$2"
fi
labels+=("$label")
shift 2
;;
--status)
(( $# <= 1 )) && die "missing argument for %s" "$1"
if ! label="$(status_as_gitlab_label "$2")"; then
die "invalid argument for %s: %s" "$1" "$2"
fi
labels+=("$label")
shift 2
;;
*)
die "invalid argument: %s" "$1"
;;
esac
done
if [[ -z ${pkgbase} ]]; then
if ! [[ -f PKGBUILD ]]; then
die "missing --package option or PKGBUILD in current directory"
fi
pkgbase=$(realpath --canonicalize-existing .)
fi
pkgbase=$(basename "${pkgbase}")
project_path=$(gitlab_project_name_to_path "${pkgbase}")
recovery_file="${recovery_home}/issue_create_${pkgbase}.md"
# spawn web browser
if (( web )); then
if ! command -v xdg-open &>/dev/null; then
die "The web option requires 'xdg-open'"
fi
issue_url="${GIT_PACKAGING_URL_HTTPS}/${project_path}/-/issues/new"
echo "Opening ${issue_url} in your browser."
xdg-open "${issue_url}"
return
fi
# check existence of recovery file
if [[ -f ${recovery_file} ]]; then
if (( ! recover )); then
msg_warn "Recovery file already exists: ${recovery_file}"
if prompt "${GREEN}${BOLD}?${ALL_OFF} Do you want to recover?"; then
msgfile=${recovery_file}
recover=1
edit=1
fi
fi
fi
# check existence of msgfile
if [[ -n ${msgfile} ]]; then
if [[ ! -f ${msgfile} ]]; then
msg_error "File does not exist: ${msgfile}${ALL_OFF}"
exit 1
fi
else
# prepare msgfile and fetch the issue template
if ! issue_template=$(curl --url "${issue_template_url}" --silent); then
msg_error "Failed to fetch issue template${ALL_OFF}"
exit 1
fi
# populate message file
msgfile=$(mktemp --tmpdir="${WORKDIR}" pkgctl-issue-create.XXXXXXXXXX.md)
edit=1
printf "# Title: %s\n\n" "${title}" >> "${msgfile}"
printf "%s\n" "${issue_template}" >> "${msgfile}"
fi
# spawn editor
if (( edit )); then
if [[ -n $VISUAL ]]; then
editor=${VISUAL}
elif [[ -n $EDITOR ]]; then
editor=${EDITOR}
else
die "No usable editor found (tried \$VISUAL, \$EDITOR)."
fi
if ! ${editor} "${msgfile}"; then
message=$(< "${msgfile}")
pkgctl_issue_write_recovery_file "${pkgbase}" "${message}" "${recovery_file}" "${recover}"
fi
fi
# check if the file contains a title
message=$(< "${msgfile}")
description=${message}
if [[ ${message} == "# Title: "* ]]; then
title=$(head --lines 1 <<< "${message}")
title=${title//# Title: /}
description=$(tail --lines +2 <<< "${message}")
if [[ ${description} == $'\n'* ]]; then
description=$(tail --lines +3 <<< "${message}")
fi
fi
# validate title
if [[ ${title} == 'PLACEHOLDER' ]]; then
msg_error "Invalid issue title: ${title}${ALL_OFF}"
pkgctl_issue_write_recovery_file "${pkgbase}" "${message}" "${recovery_file}" "${recover}"
exit 1
fi
# create the issue
if ! result=$(gitlab_project_issue_create "${pkgbase}" "${title}" "${description}" "${confidential}" "${labels[@]}"); then
msg_error "Failed to create issue in ${BOLD}${pkgbase}${ALL_OFF}"
pkgctl_issue_write_recovery_file "${pkgbase}" "${message}" "${recovery_file}" "${recover}"
exit 1
fi
# delete old recovery file if we succeeded
if [[ -f ${recovery_file} ]]; then
rm --force "${recovery_file}"
fi
# read issue iid
{ read -r iid; } < <(
jq --raw-output ".iid" <<< "${result}"
)
issue_url="${GIT_PACKAGING_URL_HTTPS}/${project_path}/-/issues/${iid}"
msg_success "Created new issue ${BOLD}#${iid}${ALL_OFF}"
printf "%sView this issue on GitLab: %s%s\n" "${GRAY}" "${issue_url}" "${ALL_OFF}"
}
pkgctl_issue_write_recovery_file() {
local pkgbase=$1
local message=$2
local recovery_file=$3
local recover=$4
if [[ -f ${recovery_file} ]] && (( ! recover )); then
msg_warn "Recovery file already exists: ${recovery_file}"
if ! prompt "${YELLOW}${BOLD}?${ALL_OFF} Are you sure you want to overwrite it?"; then
return 1
fi
fi
mkdir -p "$(dirname "${recovery_file}")"
printf "%s\n" "${message}" > "${recovery_file}"
printf "Created recovery file: %s\n" "${recovery_file}"
return 0
}

View File

@@ -1,311 +0,0 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_ISSUE_EDIT_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_ISSUE_EDIT_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/util/term.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/term.sh
set -eo pipefail
pkgctl_issue_edit_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS] [IID]
The pkgctl issue edit command is used to modify an existing issue in Arch Linux
packaging projects. This command allows users to update the issue's title,
description, and various attributes, ensuring that the issue information
remains accurate and up-to-date. It also provides a streamlined facility
for bug wranglers to categorize and prioritize issues efficiently.
By default, the command operates within the current directory, but users can
specify a different package base if needed.
In case of a failed run, the command can automatically recover to ensure that
the editing process is completed without losing any data.
OPTIONS
-p, --package PKGBASE Interact with <pkgbase> instead of the current directory
-t, --title TITLE Use the provided title for the issue
-e, --edit Edit the issue title and description using an editor
--recover Automatically recover from a failed run
--confidentiality TYPE Set the issue confidentiality
--priority PRIORITY Set the priority label
--resolution REASON Set the resolution label
--scope SCOPE Set the scope label
--severity SEVERITY Set the severity label
--status STATUS Set the status label
-h, --help Show this help text
EXAMPLES
$ ${COMMAND} --package linux --title "some very informative title"
_EOF_
}
pkgctl_issue_edit() {
if (( $# < 1 )); then
pkgctl_issue_edit_usage
exit 0
fi
local pkgbase=""
local title=""
local description=""
local labels=()
local confidential=""
local msgfile=""
local edit=0
local recover=0
local recovery_home=${XDG_DATA_HOME:-$HOME/.local/share}/devtools/recovery
local recovery_file
local issue_url
local project_path
local result
local iid
local message
# option checking
while (( $# )); do
case $1 in
-h|--help)
pkgctl_issue_edit_usage
exit 0
;;
-p|--package)
(( $# <= 1 )) && die "missing argument for %s" "$1"
pkgbase=$2
shift 2
;;
-t|--title)
(( $# <= 1 )) && die "missing argument for %s" "$1"
title=$2
shift 2
;;
-e|--edit)
edit=1
shift
;;
--recover)
recover=1
shift
;;
--confidentiality)
(( $# <= 1 )) && die "missing argument for %s" "$1"
if ! in_array "$2" "${DEVTOOLS_VALID_ISSUE_CONFIDENTIALITY[@]}"; then
die "invalid argument for %s: %s" "$1" "$2"
fi
if [[ $2 == public ]]; then
confidential=false
else
confidential=true
fi
shift 2
;;
--priority)
(( $# <= 1 )) && die "missing argument for %s" "$1"
if ! label="$(priority_as_gitlab_label "$2")"; then
die "invalid argument for %s: %s" "$1" "$2"
fi
labels+=("$label")
shift 2
;;
--resolution)
(( $# <= 1 )) && die "missing argument for %s" "$1"
if ! label="$(resolution_as_gitlab_label "$2")"; then
die "invalid argument for %s: %s" "$1" "$2"
fi
labels+=("$label")
shift 2
;;
--scope)
(( $# <= 1 )) && die "missing argument for %s" "$1"
if ! label="$(scope_as_gitlab_label "$2")"; then
die "invalid argument for %s: %s" "$1" "$2"
fi
labels+=("$label")
shift 2
;;
--severity)
(( $# <= 1 )) && die "missing argument for %s" "$1"
if ! label="$(severity_as_gitlab_label "$2")"; then
die "invalid argument for %s: %s" "$1" "$2"
fi
labels+=("$label")
shift 2
;;
--status)
(( $# <= 1 )) && die "missing argument for %s" "$1"
if ! label="$(status_as_gitlab_label "$2")"; then
die "invalid argument for %s: %s" "$1" "$2"
fi
labels+=("$label")
shift 2
;;
-*)
die "invalid argument: %s" "$1"
;;
*)
iid=$1
shift
;;
esac
done
if [[ -z ${iid} ]]; then
die "missing issue iid argument"
fi
if [[ -z ${pkgbase} ]]; then
if ! [[ -f PKGBUILD ]]; then
die "missing --package option or PKGBUILD in current directory"
fi
pkgbase=$(realpath --canonicalize-existing .)
fi
pkgbase=$(basename "${pkgbase}")
project_path=$(gitlab_project_name_to_path "${pkgbase}")
recovery_file="${recovery_home}/issue_edit_${pkgbase}.md"
# load current issue data
if ! result=$(gitlab_project_issue "${pkgbase}" "${iid}"); then
die "Failed to query issue ${pkgbase} #${iid}"
fi
{ read -r current_title; read -r current_confidential; } < <(
jq --raw-output ".title, .confidential" <<< "${result}"
)
current_description=$(jq --raw-output ".description" <<< "${result}")
# check existence of recovery file
if [[ -f ${recovery_file} ]]; then
if (( ! recover )); then
msg_warn "Recovery file already exists: ${recovery_file}"
if prompt "${GREEN}${BOLD}?${ALL_OFF} Do you want to recover?"; then
msgfile=${recovery_file}
recover=1
edit=1
fi
fi
fi
# assign data to msgfile
if [[ -n ${msgfile} ]]; then
# check existence of msgfile
if [[ ! -f ${msgfile} ]]; then
msg_error "File does not exist: ${msgfile}${ALL_OFF}"
exit 1
fi
fi
# spawn editor
if (( edit )); then
if [[ -z ${msgfile} ]]; then
msgfile=$(mktemp --tmpdir="${WORKDIR}" pkgctl-issue-create.XXXXXXXXXX.md)
if [[ -n ${title} ]]; then
printf "# Title: %s\n\n" "${title}" >> "${msgfile}"
else
printf "# Title: %s\n\n" "${current_title}" >> "${msgfile}"
fi
printf "%s\n" "${current_description}" >> "${msgfile}"
fi
if [[ -n $VISUAL ]]; then
editor=${VISUAL}
elif [[ -n $EDITOR ]]; then
editor=${EDITOR}
else
die "No usable editor found (tried \$VISUAL, \$EDITOR)."
fi
if ! ${editor} "${msgfile}"; then
message=$(< "${msgfile}")
pkgctl_issue_write_recovery_file "${pkgbase}" "${message}" "${recovery_file}" "${recover}"
return 1
fi
fi
# check if the file contains a title
if [[ -n ${msgfile} ]]; then
message=$(< "${msgfile}")
description=${message}
if [[ ${message} == "# Title: "* ]]; then
title=$(head --lines 1 <<< "${message}")
title=${title//# Title: /}
description=$(tail --lines +2 <<< "${message}")
if [[ ${description} == $'\n'* ]]; then
description=$(tail --lines +3 <<< "${message}")
fi
fi
fi
# prepare changes
data='{}'
if [[ -n ${title} ]] && [[ ${title} != "${current_title}" ]]; then
result=$(jq --null-input \
--arg title "${title}" \
'$ARGS.named')
data=$(jq --slurp '.[0] * .[1]' <(echo "${data}") <(echo "${result}"))
fi
if [[ -n ${description} ]] && [[ ${description} != "${current_description}" ]]; then
result=$(jq --null-input \
--arg description "${description}" \
'$ARGS.named')
data=$(jq --slurp '.[0] * .[1]' <(echo "${data}") <(echo "${result}"))
fi
if [[ -n ${confidential} ]] && [[ ${confidential} != "${current_confidential}" ]]; then
result=$(jq --null-input \
--arg confidential "${confidential}" \
'$ARGS.named')
data=$(jq --slurp '.[0] * .[1]' <(echo "${data}") <(echo "${result}"))
fi
if (( ${#labels[@]} )); then
result=$(jq --null-input \
--arg add_labels "$(join_by , "${labels[@]}")" \
'$ARGS.named')
data=$(jq --slurp '.[0] * .[1]' <(echo "${data}") <(echo "${result}"))
fi
# edit the issue
if ! result=$(gitlab_project_issue_edit "${pkgbase}" "${iid}" "${params}" "${data}"); then
msg_error "Failed to edit issue ${BOLD}${pkgbase}${ALL_OFF} #${iid}"
pkgctl_issue_write_recovery_file "${pkgbase}" "${message}" "${recovery_file}" "${recover}"
exit 1
fi
# delete old recovery file if we succeeded
if [[ -f ${recovery_file} ]]; then
rm --force "${recovery_file}"
fi
issue_url="${GIT_PACKAGING_URL_HTTPS}/${project_path}/-/issues/${iid}"
msg_success "Updated issue ${BOLD}#${iid}${ALL_OFF}"
printf "%sView this issue on GitLab: %s%s\n" "${GRAY}" "${issue_url}" "${ALL_OFF}"
}
pkgctl_issue_write_recovery_file() {
local pkgbase=$1
local message=$2
local recovery_file=$3
if [[ -f ${recovery_file} ]]; then
msg_warn "Recovery file already exists: ${recovery_file}"
if ! prompt "${YELLOW}${BOLD}?${ALL_OFF} Are you sure you want to overwrite it?"; then
return 1
fi
fi
mkdir -p "$(dirname "${recovery_file}")"
printf "%s\n" "${message}" > "${recovery_file}"
printf "Created recovery file: %s\n" "${recovery_file}"
return 0
}

View File

@@ -1,124 +0,0 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_ISSUE_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_ISSUE_SH=1
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
set -eo pipefail
pkgctl_issue_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [COMMAND] [OPTIONS]
Work with GitLab packaging issues.
COMMANDS
close Close an issue
comment Comment on an issue
create Create a new issue
edit Edit and modify an issue
list List project or group issues
move Move an issue to another project
reopen Reopen a closed issue
view Display information about an issue
OPTIONS
-h, --help Show this help text
EXAMPLES
$ ${COMMAND} list libfoo libbar
$ ${COMMAND} view 4
_EOF_
}
pkgctl_issue() {
if (( $# < 1 )); then
pkgctl_issue_usage
exit 0
fi
# option checking
while (( $# )); do
case $1 in
-h|--help)
pkgctl_issue_usage
exit 0
;;
close)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/issue/close.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/issue/close.sh
pkgctl_issue_close "$@"
exit 0
;;
create)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/issue/create.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/issue/create.sh
pkgctl_issue_create "$@"
exit 0
;;
edit|update)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/issue/edit.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/issue/edit.sh
pkgctl_issue_edit "$@"
exit 0
;;
list)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/issue/list.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/issue/list.sh
pkgctl_issue_list "$@"
exit 0
;;
comment|note)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/issue/comment.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/issue/comment.sh
pkgctl_issue_comment "$@"
exit 0
;;
move)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/issue/move.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/issue/move.sh
pkgctl_issue_move "$@"
exit 0
;;
reopen)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/issue/reopen.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/issue/reopen.sh
pkgctl_issue_reopen "$@"
exit 0
;;
view)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/issue/view.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/issue/view.sh
pkgctl_issue_view "$@"
exit 0
;;
-*)
die "invalid argument: %s" "$1"
;;
*)
die "invalid command: %s" "$1"
;;
esac
done
}

View File

@@ -1,417 +0,0 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_ISSUE_LIST_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_ISSUE_LIST_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/util/term.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/term.sh
set -eo pipefail
pkgctl_issue_list_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS] [PKGBASE]
The pkgctl issue list command is used to list issues associated with a specific
packaging project or the entire packaging subgroup in Arch Linux. This command
facilitates efficient issue management by allowing users to list and filter
issues based on various criteria.
Results can also be displayed directly in a web browser for easier navigation
and review.
OPTIONS
-g, --group Get issues from the whole packaging subgroup
-w, --web View results in a browser
-h, --help Show this help text
FILTER
-A, --all Get all issues including closed
-c, --closed Get only closed issues
-U, --unconfirmed Shorthand to filter by unconfirmed status label
--search SEARCH Search <string> in the fields defined by --in
--in LOCATION Search in title or description (default: all)
-l, --label NAME Filter issue by label <name>
--confidentiality TYPE Filter by confidentiality
--priority PRIORITY Shorthand to filter by priority label
--resolution REASON Shorthand to filter by resolution label
--scope SCOPE Shorthand to filter by scope label
--severity SEVERITY Shorthand to filter by severity label
--status STATUS Shorthand to filter by status label
--assignee USERNAME Filter issues assigned to the given username
--assigned-to-me Shorthand to filter issues assigned to you
--author USERNAME Filter issues authored by the given username
--created-by-me Shorthand to filter issues created by you
EXAMPLES
$ ${COMMAND} libfoo libbar
$ ${COMMAND} --group --unconfirmed
_EOF_
}
pkgctl_issue_list() {
if (( $# < 1 )) && [[ ! -f PKGBUILD ]]; then
pkgctl_issue_list_usage
exit 0
fi
local paths path project_path params web_params label username issue_url
local group=0
local web=0
local confidential=0
local state=opened
local request_data=""
local search_in="all"
local labels=()
local assignee=
local author=
local scope=all
local confidentiality=
# option checking
while (( $# )); do
case $1 in
-h|--help)
pkgctl_issue_list_usage
exit 0
;;
-A|--all)
state=all
shift
;;
-c|--closed)
state=closed
shift
;;
-U|--unconfirmed)
labels+=("$(status_as_gitlab_label unconfirmed)")
shift
;;
-g|--group)
group=1
shift
;;
-w|--web)
web=1
shift
;;
--in)
(( $# <= 1 )) && die "missing argument for %s" "$1"
search_in=$2
shift 2
;;
--search)
(( $# <= 1 )) && die "missing argument for %s" "$1"
request_data="search=$2"
web_params+="&search=$2"
shift 2
;;
-l|--label)
(( $# <= 1 )) && die "missing argument for %s" "$1"
labels+=("$2")
shift 2
;;
--confidentiality)
(( $# <= 1 )) && die "missing argument for %s" "$1"
confidentiality=$2
if ! in_array "${confidentiality}" "${DEVTOOLS_VALID_ISSUE_CONFIDENTIALITY[@]}"; then
die "invalid argument for %s: %s" "$1" "$2"
fi
shift 2
;;
--priority)
(( $# <= 1 )) && die "missing argument for %s" "$1"
if ! label="$(priority_as_gitlab_label "$2")"; then
die "invalid argument for %s: %s" "$1" "$2"
fi
labels+=("$label")
shift 2
;;
--resolution)
(( $# <= 1 )) && die "missing argument for %s" "$1"
if ! label="$(resolution_as_gitlab_label "$2")"; then
die "invalid argument for %s: %s" "$1" "$2"
fi
labels+=("$label")
shift 2
;;
--scope)
(( $# <= 1 )) && die "missing argument for %s" "$1"
if ! label="$(scope_as_gitlab_label "$2")"; then
die "invalid argument for %s: %s" "$1" "$2"
fi
labels+=("$label")
shift 2
;;
--severity)
(( $# <= 1 )) && die "missing argument for %s" "$1"
if ! label="$(severity_as_gitlab_label "$2")"; then
die "invalid argument for %s: %s" "$1" "$2"
fi
labels+=("$label")
shift 2
;;
--status)
(( $# <= 1 )) && die "missing argument for %s" "$1"
if ! label="$(status_as_gitlab_label "$2")"; then
die "invalid argument for %s: %s" "$1" "$2"
fi
labels+=("$label")
shift 2
;;
--assignee)
(( $# <= 1 )) && die "missing argument for %s" "$1"
assignee="$2"
shift 2
;;
--assigned-to-me)
scope=assigned_to_me
shift
;;
--author)
(( $# <= 1 )) && die "missing argument for %s" "$1"
author="$2"
shift 2
;;
--created-by-me)
scope=created_by_me
shift
;;
-*)
die "invalid argument: %s" "$1"
;;
*)
paths=("$@")
break
;;
esac
done
if [[ ${search_in} == all ]]; then
search_in="title,description"
else
web_params+="&in=${search_in^^}"
fi
params+="&in=${search_in}"
if [[ ${state} != all ]]; then
params+="&state=${state}"
fi
web_params+="&state=${state}"
if (( ${#labels} )); then
params+="&labels=$(join_by , "${labels[@]}")"
web_params+="&label_name[]=$(join_by "&label_name[]=" "${labels[@]}")"
fi
if [[ -n ${scope} ]]; then
params+="&scope=${scope}"
if (( web )); then
if ! username=$(gitlab_api_get_user); then
exit 1
fi
case "${scope}" in
created_by_me) author=${username} ;;
assigned_to_me) assignee=${username} ;;
esac
fi
fi
if [[ -n ${assignee} ]]; then
params+="&assignee_username=${assignee}"
web_params+="&assignee_username=${assignee}"
fi
if [[ -n ${author} ]]; then
params+="&author_username=${author}"
web_params+="&author_username=${author}"
fi
if [[ -n ${confidentiality} ]]; then
if [[ ${confidentiality} == confidential ]]; then
params+="&confidential=true"
web_params+="&confidential=yes"
else
params+="&confidential=false"
web_params+="&confidential=no"
fi
fi
# check if invoked without any path from within a packaging repo
if (( ${#paths[@]} == 0 )); then
if [[ -f PKGBUILD ]] && (( ! group )); then
paths=("$(realpath --canonicalize-existing .)")
elif (( ! group )); then
pkgctl_issue_list_usage
exit 1
fi
fi
if (( web )) && ! command -v xdg-open &>/dev/null; then
die "The web option requires 'xdg-open'"
fi
local separator=" "
for path in "${paths[@]}"; do
# skip paths from a glob that aren't directories
if [[ -e "${path}" ]] && [[ ! -d "${path}" ]]; then
continue
fi
pkgbase=$(basename "${path}")
project_path=$(gitlab_project_name_to_path "${pkgbase}")
echo "${UNDERLINE}${pkgbase}${ALL_OFF}"
if (( web )); then
issue_url="${GIT_PACKAGING_URL_HTTPS}/${project_path}/-/issues/?${web_params}"
echo "Opening ${issue_url} in your browser."
xdg-open "${issue_url}"
continue
fi
status_dir=$(mktemp --tmpdir="${WORKDIR}" --directory pkgctl-gitlab-api.XXXXXXXXXX)
printf "📡 Querying GitLab issues API..." > "${status_dir}/status"
term_spinner_start "${status_dir}"
if ! output=$(gitlab_projects_issues_list "${project_path}" "${status_dir}/status" "${params}" "${request_data}"); then
term_spinner_stop "${status_dir}"
echo
continue
fi
term_spinner_stop "${status_dir}"
issue_count=$(jq --compact-output 'length' <<< "${output}")
if (( issue_count == 0 )); then
echo "No open issues match your search"
echo
continue
else
echo "Showing ${issue_count} issues that match your search"
fi
print_issue_list "${output}"
done
if (( group )); then
if (( web )); then
issue_url="https://${GITLAB_HOST}/groups/${GIT_PACKAGING_NAMESPACE}/-/issues/?${web_params}"
echo "Opening ${issue_url} in your browser."
xdg-open "${issue_url}"
return
fi
status_dir=$(mktemp --tmpdir="${WORKDIR}" --directory pkgctl-gitlab-api.XXXXXXXXXX)
printf "📡 Querying GitLab issues API..." > "${status_dir}/status"
term_spinner_start "${status_dir}"
if ! output=$(gitlab_group_issue_list "${GIT_PACKAGING_NAMESPACE_ID}" "${status_dir}/status" "${params}" "${request_data}"); then
term_spinner_stop "${status_dir}"
exit 1
fi
term_spinner_stop "${status_dir}"
print_issue_list "${output}"
fi
}
print_issue_list() {
local output=$1
local limit=${2:-100}
local i=0
local status_dir
local longest_pkgname
# limit results
output=$(jq ".[:${limit}]" <<< "${output}")
mapfile -t project_ids < <(
jq --raw-output '[.[].project_id] | unique[]' <<< "${output}")
status_dir=$(mktemp --tmpdir="${WORKDIR}" --directory pkgctl-gitlab-api.XXXXXXXXXX)
printf "📡 Querying GitLab project names..." > "${status_dir}/status"
term_spinner_start "${status_dir}"
# read project_id to name mapping from cache
declare -A project_name_lookup=()
while read -r project_id project_name; do
project_name_lookup[${project_id}]=${project_name}
done < <(gitlab_lookup_project_names "${status_dir}/status" "${project_ids[@]}")
longest_pkgname=$(longest_package_name_from_ids "${project_ids[@]}")
term_spinner_stop "${status_dir}"
result_file=$(mktemp --tmpdir="${WORKDIR}" pkgctl-issue-list.XXXXXXXXXX)
printf "📡 Collecting issue information %%spinner%%" > "${status_dir}/status"
term_spinner_start "${status_dir}"
local columns="ID,Title,Scope,Status,Severity,Age"
if (( group )); then
columns="ID,Package,Title,Scope,Status,Severity,Age"
fi
# pretty print each result
while read -r result; do
if (( i > limit )); then
break
fi
i=$(( ++i ))
{ read -r project_id; read -r iid; read -r title; read -r state; read -r created_at; read -r confidential; } < <(
jq --raw-output ".project_id, .iid, .title, .state, .created_at, .confidential" <<< "${result}"
)
mapfile -t labels < <(
jq --raw-output ".labels[]" <<< "${result}"
)
pkgbase=${project_name_lookup[${project_id}]}
created_at=$(relative_date_unit "${created_at}")
severity="$(gitlab_severity_from_labels "${labels[@]}")"
severity_color="$(gitlab_severity_color "${severity}")"
state_color="$(gitlab_issue_state_color "${state}")"
state="$(gitlab_issue_state_display "${state}")"
status="$(gitlab_issue_status_from_labels "${labels[@]}")"
status_color="$(gitlab_issue_status_color "${status}")"
status="$(gitlab_issue_status_short "${status}")"
scope="$(gitlab_scope_from_labels "${labels[@]}")"
scope_color="$(gitlab_scope_color "${scope}")"
scope="$(gitlab_scope_short "${scope}")"
title_space=$(( COLUMNS - 7 - 10 - 15 - 12 - 10 ))
if (( group )); then
title_space=$(( title_space - longest_pkgname ))
fi
if [[ ${confidential} == true ]]; then
title_space=$(( title_space - 2 ))
fi
title=$(trim_string "${title_space}" "${title}")
# gum is silly and doesn't allow double quotes
title=${title//\"/}
if [[ ${confidential} == true ]]; then
title="${YELLOW}${PKGCTL_TERM_ICON_CONFIDENTIAL} ${title}${ALL_OFF}"
fi
if (( group )); then
printf "%s\n" "${state_color}#$iid${ALL_OFF}${separator}${BOLD}${pkgbase}${separator}${ALL_OFF}${title}${separator}${scope_color}${scope}${ALL_OFF}${separator}${status_color}${status}${separator}${severity_color}${severity}${ALL_OFF}${separator}${GRAY}${created_at}${ALL_OFF}" \
>> "${result_file}"
else
printf "%s\n" "${state_color}#$iid${ALL_OFF}${separator}${title}${separator}${scope_color}${scope}${ALL_OFF}${separator}${status_color}${status}${separator}${severity_color}${severity}${ALL_OFF}${separator}${GRAY}${created_at}${ALL_OFF}" \
>> "${result_file}"
fi
done < <(jq --compact-output '.[]' <<< "${output}")
term_spinner_stop "${status_dir}"
gum table --print --border="none" --columns="${columns}" \
--separator="${separator}" --file "${result_file}"
}

View File

@@ -1,156 +0,0 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_ISSUE_MOVE_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_ISSUE_MOVE_SH=1
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
# shellcheck source=src/lib/common.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
# shellcheck source=src/lib/cache.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/cache.sh
# shellcheck source=src/lib/api/gitlab.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/api/gitlab.sh
set -eo pipefail
pkgctl_issue_move_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS] [IID] [DESTINATION_PACKAGE]
The move command allows users to transfer an issue from one project to another
within the Arch Linux packaging group. This is useful when an issue is
identified to be more relevant or better handled in a different project.
By default, the command operates within the current directory, but users can
specify a different package base from which to move the issue.
Users must specify the issue ID (IID) and the destination package to which the
issue should be moved. A comment message explaining the reason for the move can
be provided directly through the command line.
OPTIONS
-p, --package PKGBASE Move from <pkgbase> instead of the current directory
-m, --message MSG Use the provided message as the comment
-e, --edit Edit the comment using an editor
-h, --help Show this help text
EXAMPLES
$ ${COMMAND} 42 to-bar
$ ${COMMAND} --package from-foo 42 to-bar
_EOF_
}
pkgctl_issue_move() {
if (( $# < 1 )); then
pkgctl_issue_move_usage
exit 0
fi
local iid=""
local pkgbase=""
local message=""
local edit=0
local to_project_name to_project_id project_path issue_url to_iid result
# option checking
while (( $# )); do
case $1 in
-h|--help)
pkgctl_issue_move_usage
exit 0
;;
-p|--package)
(( $# <= 1 )) && die "missing argument for %s" "$1"
pkgbase=$2
shift 2
;;
-m|--message)
(( $# <= 1 )) && die "missing argument for %s" "$1"
message=$2
shift 2
;;
-e|--edit)
edit=1
shift
;;
-*)
die "invalid argument: %s" "$1"
;;
*)
break
;;
esac
done
if [[ -z ${pkgbase} ]]; then
if ! [[ -f PKGBUILD ]]; then
die "missing --package option or PKGBUILD in current directory"
fi
pkgbase=$(realpath --canonicalize-existing .)
fi
pkgbase=$(basename "${pkgbase}")
if (( $# < 2 )); then
pkgctl_issue_move_usage
exit 1
fi
iid=$1
to_project_name=$(basename "$2")
# spawn editor
if (( edit )); then
msgfile=$(mktemp --tmpdir="${WORKDIR}" pkgctl-issue-note.XXXXXXXXXX.md)
printf "%s\n" "${message}" >> "${msgfile}"
if [[ -n $VISUAL ]]; then
$VISUAL "${msgfile}" || die
elif [[ -n $EDITOR ]]; then
$EDITOR "${msgfile}" || die
else
die "No usable editor found (tried \$VISUAL, \$EDITOR)."
fi
message=$(cat "${msgfile}")
fi
if ! result=$(gitlab_project "${to_project_name}"); then
msg_error "Failed to query target project ${BOLD}${to_project_name}${ALL_OFF}"
exit 1
fi
if ! to_project_id=$(jq --raw-output ".id" <<< "${result}"); then
msg_error "Failed to query project id for ${BOLD}${to_project_name}${ALL_OFF}"
exit 1
fi
# comment on issue
if [[ -n ${message} ]]; then
if ! result=$(gitlab_create_project_issue_note "${pkgbase}" "${iid}" "${message}"); then
msg_error "Failed to comment on issue ${BOLD}#${iid}${ALL_OFF}"
exit 1
fi
msg_success "Commented on issue ${BOLD}#${iid}${ALL_OFF}"
fi
if ! result=$(gitlab_project_issue_move "${pkgbase}" "${iid}" "${to_project_id}"); then
msg_error "Failed to move issue ${BOLD}#${iid}${ALL_OFF} to ${BOLD}${to_project_name}${ALL_OFF}"
exit 1
fi
if ! to_iid=$(jq --raw-output ".iid" <<< "${result}"); then
msg_error "Failed to query issue id for ${BOLD}${to_project_name}${ALL_OFF}"
exit 1
fi
project_path=$(gitlab_project_name_to_path "${to_project_name}")
issue_url="${GIT_PACKAGING_URL_HTTPS}/${project_path}/-/issues/${to_iid}"
msg_success "Moved issue ${BOLD}${pkgbase}${ALL_OFF} ${BOLD}#${iid}${ALL_OFF} to ${BOLD}${to_project_name}${ALL_OFF} ${BOLD}#${to_iid}${ALL_OFF}"
echo
printf "%sView this issue on GitLab: %s%s\n" "${GRAY}" "${issue_url}" "${ALL_OFF}"
}

View File

@@ -1,189 +0,0 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_ISSUE_REOPEN_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_ISSUE_REOPEN_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 -eo pipefail
pkgctl_issue_reopen_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS] [IID]
The reopen command is used to reopen a previously closed issue in Arch Linux
packaging projects. This command is useful when an issue needs to be revisited
or additional work is required after it was initially closed.
By default, the command operates within the current directory, but users can
specify a different package base if needed.
Users can provide a message directly through the command line to explain the
reason for reopening the issue.
OPTIONS
-p, --package PKGBASE Interact with <pkgbase> instead of the current directory
-m, --message MSG Use the provided message as the comment
-e, --edit Edit the comment using an editor
-h, --help Show this help text
EXAMPLES
$ ${COMMAND} 42
$ ${COMMAND} --package linux 42
_EOF_
}
pkgctl_issue_reopen() {
if (( $# < 1 )); then
pkgctl_issue_reopen_usage
exit 0
fi
local iid=""
local pkgbase=""
local message=""
local edit=0
local issue note result resolution labels
local params="state_event=reopen"
# option checking
while (( $# )); do
case $1 in
-h|--help)
pkgctl_issue_reopen_usage
exit 0
;;
-p|--package)
(( $# <= 1 )) && die "missing argument for %s" "$1"
pkgbase=$2
shift 2
;;
-m|--message)
(( $# <= 1 )) && die "missing argument for %s" "$1"
message=$2
shift 2
;;
-e|--edit)
edit=1
shift
;;
-*)
die "invalid argument: %s" "$1"
;;
*)
iid=$1
shift
;;
esac
done
if [[ -z ${iid} ]]; then
die "missing issue iid argument"
fi
if [[ -z ${pkgbase} ]]; then
if ! [[ -f PKGBUILD ]]; then
die "missing --package option or PKGBUILD in current directory"
fi
pkgbase=$(realpath --canonicalize-existing .)
fi
pkgbase=$(basename "${pkgbase}")
# spawn editor
if (( edit )); then
msgfile=$(mktemp --tmpdir="${WORKDIR}" pkgctl-issue-note.XXXXXXXXXX.md)
printf "%s\n" "${message}" >> "${msgfile}"
if [[ -n $VISUAL ]]; then
$VISUAL "${msgfile}" || die
elif [[ -n $EDITOR ]]; then
$EDITOR "${msgfile}" || die
else
die "No usable editor found (tried \$VISUAL, \$EDITOR)."
fi
message=$(< "${msgfile}")
fi
# query issue details
if ! result=$(gitlab_project_issue "${pkgbase}" "${iid}"); then
die "Failed to fetch issue ${pkgbase} #${iid}"
fi
mapfile -t labels < <(
jq --raw-output ".labels[]" <<< "${result}"
)
if resolution=$(gitlab_resolution_from_labels "${labels[@]}"); then
resolution=$(resolution_as_gitlab_label "${resolution}")
params+="&remove_labels=${resolution}"
fi
# comment on issue
if [[ -n ${message} ]]; then
if ! note=$(gitlab_create_project_issue_note "${pkgbase}" "${iid}" "${message}"); then
msg_error "Failed to comment on issue ${BOLD}#${iid}${ALL_OFF}"
exit 1
fi
msg_success "Commented on issue ${BOLD}#${iid}${ALL_OFF}"
fi
# reopen issue
if ! issue=$(gitlab_project_issue_edit "${pkgbase}" "${iid}" "${params}"); then
msg_error "Failed to reopen issue ${BOLD}#${iid}${ALL_OFF}"
exit 1
fi
msg_success "Reopened issue ${BOLD}#${iid}${ALL_OFF}"
echo
{ read -r iid; read -r title; read -r state; read -r created_at; read -r author; } < <(
jq --raw-output ".iid, .title, .state, .created_at, .author.username" <<< "${issue}"
)
mapfile -t labels < <(
jq --raw-output ".labels[]" <<< "${issue}"
)
severity="$(gitlab_severity_from_labels "${labels[@]}")"
severity_color="$(gitlab_severity_color "${severity}")"
created_at=$(relative_date_unit "${created_at}")
state_color="$(gitlab_issue_state_color "${state}")"
state="$(gitlab_issue_state_display "${state}")"
status="$(gitlab_issue_status_from_labels "${labels[@]}")"
status_color="$(gitlab_issue_status_color "${status}")"
scope="$(gitlab_scope_from_labels "${labels[@]}")"
scope_color="$(gitlab_scope_color "${scope}")"
scope_label=""
if [[ ${scope} != unknown ]]; then
scope_label="${scope_color}${scope}${ALL_OFF} ${GRAY}${ALL_OFF} "
fi
printf "%s%s • %sseverity %s • %s • %s%sopened by %s %s ago%s\n" \
"${state_color}${state}${ALL_OFF}" "${GRAY}" "${severity_color}" "${severity}${GRAY}" \
"${status_color}${status}${GRAY}" "${scope_label}" "${GRAY}" "${author}" "${created_at}" "${ALL_OFF}"
printf "%s %s\n" "${BOLD}${title}${ALL_OFF}" "${GRAY}#${iid}${ALL_OFF}"
# show comment
if [[ -n ${note} ]]; then
{ read -r created_at; read -r author; } < <(
jq --raw-output ".created_at, .author.username" <<< "${note}"
)
body=$(jq --raw-output ".body" <<< "${note}")
created_at=$(relative_date_unit "${created_at}")
echo
echo "${BOLD}Comments / Notes${ALL_OFF}"
printf -v spaces '%*s' $(( COLUMNS - 2 )) ''
printf '%s\n\n' "${spaces// /─}"
printf "%s commented%s %s ago%s\n" "${author}" "${GRAY}" "${created_at}" "${ALL_OFF}"
echo "${body}" | glow
fi
}

View File

@@ -1,209 +0,0 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_ISSUE_VIEW_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_ISSUE_VIEW_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/util/term.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/term.sh
set -eo pipefail
pkgctl_issue_view_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS] [IID]
This command is designed to display detailed information about a specific issue
in Arch Linux packaging projects. It gathers and pretty prints all relevant
data about the issue, providing a comprehensive view that includes the issue's
description, status as well as labels and creation date.
By default, the command operates within the current directory, but users have
the option to specify a different package base. Additionally, users can choose
to view the issue in a web browser for a more interactive experience.
OPTIONS
-p, --package PKGBASE Interact with <pkgbase> instead of the current directory
-c, --comments Show issue comments and activities
-w, --web Open issue in a browser
-h, --help Show this help text
EXAMPLES
$ ${COMMAND} 4
$ ${COMMAND} --web --package linux 4
_EOF_
}
pkgctl_issue_view() {
if (( $# < 1 )); then
pkgctl_issue_view_usage
exit 0
fi
local web=0
local comments=0
local pkgbase=""
local iid=""
local project_path
# option checking
while (( $# )); do
case $1 in
-h|--help)
pkgctl_issue_view_usage
exit 0
;;
-p|--package)
(( $# <= 1 )) && die "missing argument for %s" "$1"
pkgbase=$2
shift 2
;;
-w|--web)
web=1
shift
;;
-c|--comments)
comments=1
shift
;;
-*)
die "invalid argument: %s" "$1"
;;
*)
iid=$1
shift
;;
esac
done
if [[ -z ${iid} ]]; then
die "missing issue iid argument"
fi
if [[ -z ${pkgbase} ]]; then
if ! [[ -f PKGBUILD ]]; then
die "missing --package option or PKGBUILD in current directory"
fi
pkgbase=$(realpath --canonicalize-existing .)
fi
pkgbase=$(basename "${pkgbase}")
project_path=$(gitlab_project_name_to_path "${pkgbase}")
if ! result=$(gitlab_project_issue "${pkgbase}" "${iid}"); then
die "Failed to view issue ${pkgbase} #${iid}"
fi
{ read -r iid; read -r title; read -r state; read -r created_at; read -r closed_at; read -r author; } < <(
jq --raw-output ".iid, .title, .state, .created_at, .closed_at, .author.username" <<< "${result}"
)
{ read -r upvotes; read -r downvotes; read -r user_notes_count; read -r confidential; } < <(
jq --raw-output ".upvotes, .downvotes, .user_notes_count, .confidential" <<< "${result}"
)
description=$(jq --raw-output ".description" <<< "${result}")
mapfile -t labels < <(
jq --raw-output ".labels[]" <<< "${result}"
)
mapfile -t assignees < <(
jq --raw-output ".assignees[].username" <<< "${result}"
)
if [[ ${closed_at} != null ]]; then
closed_by=$(jq --raw-output ".closed_by.username" <<< "${result}")
fi
issue_url="${GIT_PACKAGING_URL_HTTPS}/${project_path}/-/issues/${iid}"
if (( web )); then
if ! command -v xdg-open &>/dev/null; then
die "The web option requires 'xdg-open'"
fi
echo "Opening ${issue_url} in your browser."
xdg-open "${issue_url}"
return
fi
severity="$(gitlab_severity_from_labels "${labels[@]}")"
severity_color="$(gitlab_severity_color "${severity}")"
created_at=$(relative_date_unit "${created_at}")
state_color="$(gitlab_issue_state_color "${state}")"
state="$(gitlab_issue_state_display "${state}")"
status="$(gitlab_issue_status_from_labels "${labels[@]}")"
status_color="$(gitlab_issue_status_color "${status}")"
scope="$(gitlab_scope_from_labels "${labels[@]}")"
scope_color="$(gitlab_scope_color "${scope}")"
scope_label=""
if [[ ${scope} != unknown ]]; then
scope_label="${scope_color}${scope}${ALL_OFF} ${GRAY}${ALL_OFF} "
fi
resolution_label=""
if resolution="$(gitlab_resolution_from_labels "${labels[@]}")"; then
resolution_color="$(gitlab_resolution_color "${resolution}")"
resolution_label="${resolution_color}${resolution}${ALL_OFF} ${GRAY}${ALL_OFF} "
fi
confidential_label=""
if [[ ${confidential} == true ]]; then
confidential_label="${YELLOW}${PKGCTL_TERM_ICON_CONFIDENTIAL} CONFIDENTIAL${ALL_OFF} ${GRAY}${ALL_OFF} "
fi
printf "%s%s • %s%s%sseverity %s • %s • %s%sopened by %s %s ago%s\n" \
"${state_color}${state}${ALL_OFF}" "${GRAY}" "${confidential_label}" "${resolution_label}" "${severity_color}" "${severity}${ALL_OFF}${GRAY}" \
"${status_color}${status}${ALL_OFF}${GRAY}" "${scope_label}" "${GRAY}" "${author}" "${created_at}" "${ALL_OFF}"
printf "%s %s\n\n" "${BOLD}${title}${ALL_OFF}" "${GRAY}#${iid}${ALL_OFF}"
printf "%s\n" "${description}" | glow
printf "\n\n"
printf "%s%s upvotes • %s downvotes • %s comments%s\n" "${GRAY}" "${upvotes}" "${downvotes}" "${user_notes_count}" "${ALL_OFF}"
printf "%s %s\n" "${BOLD}Labels:${ALL_OFF}" "$(join_by ", " "${labels[@]}")"
printf "%s %s\n" "${BOLD}Assignees:${ALL_OFF}" "$(join_by ", " "${assignees[@]}")"
if [[ ${closed_at} != null ]]; then
closed_at=$(relative_date_unit "${closed_at}")
printf "%s %s %s ago\n" "${BOLD}Closed by:${ALL_OFF}" "${closed_by}" "${closed_at}"
fi
if (( comments )); then
printf "\n\n"
echo "${BOLD}Comments / Notes${ALL_OFF}"
printf -v spaces '%*s' $(( COLUMNS - 2 )) ''
printf '%s\n' "${spaces// /─}"
printf "\n\n"
status_dir=$(mktemp --tmpdir="${WORKDIR}" --directory pkgctl-gitlab-api.XXXXXXXXXX)
printf "📡 Querying GitLab issue notes API..." > "${status_dir}/status"
term_spinner_start "${status_dir}"
if ! output=$(gitlab_project_issue_notes "${project_path}" "${iid}" "${status_dir}/status" "sort=asc&order_by=created_at"); then
term_spinner_stop "${status_dir}"
msg_error "Failed to fetch comments"
exit 1
fi
term_spinner_stop "${status_dir}"
# pretty print each result
while read -r result; do
{ read -r created_at; read -r author; } < <(
jq --raw-output ".created_at, .author.username" <<< "${result}"
)
body=$(jq --raw-output ".body" <<< "${result}")
created_at=$(relative_date_unit "${created_at}")
printf "%s commented%s %s ago%s\n" "${author}" "${GRAY}" "${created_at}" "${ALL_OFF}"
echo "${body}" | glow
echo
done < <(jq --compact-output '.[]' <<< "${output}")
echo "$output" > /tmp/notes.json
fi
echo
printf "%sView this issue on GitLab: %s%s\n" "${GRAY}" "${issue_url}" "${ALL_OFF}"
}

View File

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

View File

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

View File

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

View File

@@ -157,11 +157,6 @@ pkgctl_release() {
repo=${REPO} repo=${REPO}
fi fi
# output a warning if .nvchecker.toml does not exists
if [[ ! -f ".nvchecker.toml" ]]; then
warning "Nvchecker integration is not set, run 'pkgctl version setup --help' to see how to automate the creation of the '.nvchecker.toml' configuration file"
fi
if (( TESTING )); then if (( TESTING )); then
repo="${repo}-testing" repo="${repo}-testing"
elif (( STAGING )); then elif (( STAGING )); then

View File

@@ -31,7 +31,6 @@ pkgctl_repo_usage() {
clone Clone a package repository clone Clone a package repository
configure Configure a clone according to distro specs configure Configure a clone according to distro specs
create Create a new GitLab package repository create Create a new GitLab package repository
pull Update package repositories from their git remote
switch Switch a package repository to a specified version switch Switch a package repository to a specified version
web Open the packaging repository's website web Open the packaging repository's website
@@ -41,7 +40,6 @@ pkgctl_repo_usage() {
EXAMPLES EXAMPLES
$ ${COMMAND} clean --interactive * $ ${COMMAND} clean --interactive *
$ ${COMMAND} clone libfoo linux libbar $ ${COMMAND} clone libfoo linux libbar
$ ${COMMAND} pull libfoo linux libbar
$ ${COMMAND} clone --maintainer mynickname $ ${COMMAND} clone --maintainer mynickname
$ ${COMMAND} configure * $ ${COMMAND} configure *
$ ${COMMAND} create libfoo $ ${COMMAND} create libfoo
@@ -103,14 +101,6 @@ pkgctl_repo() {
pkgctl_repo_switch "$@" pkgctl_repo_switch "$@"
exit 0 exit 0
;; ;;
pull)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/repo/pull.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/repo/pull.sh
pkgctl_repo_pull "$@"
exit 0
;;
web) web)
_DEVTOOLS_COMMAND+=" $1" _DEVTOOLS_COMMAND+=" $1"
shift shift

View File

@@ -65,7 +65,6 @@ pkgctl_repo_clone() {
local CONFIGURE_OPTIONS=() local CONFIGURE_OPTIONS=()
local jobs= local jobs=
jobs=$(nproc) jobs=$(nproc)
local -a pkgbases
# variables # variables
local command=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}} local command=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}

View File

@@ -271,7 +271,6 @@ pkgctl_repo_configure() {
if [[ -n $GPGKEY ]]; then if [[ -n $GPGKEY ]]; then
git config commit.gpgsign true git config commit.gpgsign true
git config user.signingKey "${GPGKEY}" git config user.signingKey "${GPGKEY}"
git config gpg.format openpgp
fi fi
# set default git exclude # set default git exclude

View File

@@ -1,195 +0,0 @@
#!/bin/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_REPO_PULL_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_REPO_PULL_SH=1
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
# shellcheck source=src/lib/common.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
# shellcheck source=src/lib/util/git.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/git.sh
source /usr/share/makepkg/util/message.sh
set -eo pipefail
pkgctl_repo_pull_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS] [PKGBASE]...
Update package repositories from their git remotes.
OPTIONS
--discard-changes Discard changes if index or working tree is dirty
--show-diff Always enable showing the diff
--autostash Stash before pulling and unstash afterwards
-j, --jobs N Run up to N jobs in parallel (default: $(nproc))
--quiet Disable printing longer terminal output
-h, --help Show this help text
EXAMPLES
$ ${COMMAND} gopass gopass-jsonapi
_EOF_
}
pkgctl_repo_pull() {
# options
local paths path pkgbase branch jobs remote
jobs=$(nproc)
local command=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
local git_rebase_options=()
local SHOW_DIFF=0
local QUIET=0
local DISCARD_CHANGES=0
local AUTOSTASH=0
while (( $# )); do
case $1 in
-h|--help)
pkgctl_repo_pull_usage
exit 0
;;
--discard-changes)
DISCARD_CHANGES=1
shift
;;
--show-diff)
SHOW_DIFF=1
shift
;;
--quiet)
QUIET=1
shift
;;
--autostash)
AUTOSTASH=1
git_rebase_options+=(--autostash)
shift
;;
-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
paths=(".")
fi
# check if we are only working on one repo and enable
if (( ${#paths[@]} == 1 )) && (( ! QUIET )); then
SHOW_DIFF=1
fi
# parallelization
if [[ ${jobs} != 1 ]] && (( ${#paths[@]} > 1 )); then
if [[ -n ${BOLD} ]]; then
export DEVTOOLS_COLOR=always
fi
# warm up ssh connection as it may require user input (key unlock, hostkey verification etc)
git_warmup_ssh_connection
# disable diffs if not enabled explicitly
if (( ! SHOW_DIFF )); then
command+=" --quiet"
fi
if (( DISCARD_CHANGES )); then
command+=" --discard-changes"
fi
if (( AUTOSTASH )); then
command+=" --autostash"
fi
if ! parallel --bar --jobs "${jobs}" "${command}" ::: "${paths[@]}"; then
die 'Failed to pull some packages, please check the previous output'
fi
exit 0
fi
for path in "${paths[@]}"; do
# skip paths that are not directories
if [[ ! -d "${path}" ]]; then
continue
fi
if [[ ! -f "${path}/PKGBUILD" ]]; then
msg_error " Not a package repository: ${path}"
continue
fi
if [[ ! -d "${path}/.git" ]]; then
msg_error " Not a Git repository: ${path}"
continue
fi
pkgbase=$(basename "$(realpath "${path}")")
pkgbase=${pkgbase%.git}
msg "Updating ${pkgbase}"
branch=$(git -C "${path}" symbolic-ref --quiet --short HEAD)
if [[ ${branch} != main ]]; then
msg_warn " Current branch is ${branch}, not updating from canonical upstream: ${pkgbase}"
fi
if ! git -C "${path}" diff-files --quiet && (( ! AUTOSTASH )) && (( ! DISCARD_CHANGES )); then
msg_error " Index contains unstaged changes, please stash them or pass --autostash before pulling: ${pkgbase}"
continue
fi
if ! git -C "${path}" diff-index --cached --quiet HEAD && (( ! AUTOSTASH )) && (( ! DISCARD_CHANGES )); then
msg_error " Index contains uncommited changes, please commit or stash them before pulling: ${pkgbase}"
continue
fi
remote=$(git -C "${path}" config "branch.${branch}.remote")
if [[ -z "${remote}" ]]; then
msg_error " No upstream tracking branch configured: ${pkgbase}"
continue
fi
if ! git -C "${path}" fetch --quiet "${remote}"; then
msg_error " Error while fetching: ${pkgbase}"
continue
fi
if [[ $(git -C "${path}" rev-parse HEAD) == $(git -C "${path}" rev-parse FETCH_HEAD) ]]; then
msg2 "Repo is up to date, nothing to do"
continue
fi
# discard any local modifications
if (( DISCARD_CHANGES )); then
git -C "${path}" restore --staged --worktree -- .
fi
if (( SHOW_DIFF )) && (( ! QUIET )); then
git -C "${path}" --no-pager diff --color --patch-with-stat HEAD..FETCH_HEAD
fi
if ! git -C "${path}" rebase --quiet "${git_rebase_options[@]}" "${remote}/${branch}"; then
msg_error " Error while pulling in the changes for ${pkgbase}"
exit 1
fi
done
}

View File

@@ -8,6 +8,8 @@ DEVTOOLS_INCLUDE_SEARCH_SH=1
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@} _DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
# shellcheck source=src/lib/common.sh # shellcheck source=src/lib/common.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
# shellcheck source=src/lib/cache.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/cache.sh
# shellcheck source=src/lib/api/gitlab.sh # shellcheck source=src/lib/api/gitlab.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/api/gitlab.sh source "${_DEVTOOLS_LIBRARY_DIR}"/lib/api/gitlab.sh
# shellcheck source=src/lib/valid-search.sh # shellcheck source=src/lib/valid-search.sh
@@ -93,8 +95,10 @@ pkgctl_search() {
# variables # variables
local bat_style="header,grid" local bat_style="header,grid"
local default_filter="-path:keys/pgp/*.asc" local default_filter="-path:keys/pgp/*.asc"
local output result project_name_lookup project_ids project_id project_name local graphql_lookup_batch=200
local path startline currentline data line local output result query entries from until length
local project_name_cache_file project_name_lookup project_ids project_id project_name project_slice
local mapping_output path startline currentline data line
while (( $# )); do while (( $# )); do
case $1 in case $1 in
@@ -172,20 +176,68 @@ pkgctl_search() {
term_spinner_stop "${status_dir}" term_spinner_stop "${status_dir}"
msg_success "Querying GitLab search API" msg_success "Querying GitLab search API"
# collect project ids whose name needs to be looked up
project_name_cache_file=$(get_cache_file gitlab/project_id_to_name)
lock 11 "${project_name_cache_file}" "Locking project name cache"
mapfile -t project_ids < <( mapfile -t project_ids < <(
jq --raw-output '[.[].project_id] | unique[]' <<< "${output}") jq --raw-output '[.[].project_id] | unique[]' <<< "${output}" | \
grep --invert-match --file <(awk '{ print $1 }' < "${project_name_cache_file}" ))
# look up project names
tmp_file=$(mktemp --tmpdir="${WORKDIR}" pkgctl-gitlab-api-spinner.tmp.XXXXXXXXXX)
printf "📡 Querying GitLab project names..." > "${status_dir}/status" printf "📡 Querying GitLab project names..." > "${status_dir}/status"
term_spinner_start "${status_dir}" term_spinner_start "${status_dir}"
local entries="${#project_ids[@]}"
local until=0
while (( until < entries )); do
from=${until}
until=$(( until + graphql_lookup_batch ))
if (( until > entries )); then
until=${entries}
fi
length=$(( until - from ))
percentage=$(( 100 * until / entries ))
printf "📡 Querying GitLab project names: %s/%s [%s] %%spinner%%" \
"${BOLD}${until}" "${entries}" "${percentage}%${ALL_OFF}" \
> "${tmp_file}"
mv "${tmp_file}" "${status_dir}/status"
project_slice=("${project_ids[@]:${from}:${length}}")
printf -v projects '"gid://gitlab/Project/%s",' "${project_slice[@]}"
query='{
projects(after: "" ids: ['"${projects}"']) {
pageInfo {
startCursor
endCursor
hasNextPage
}
nodes {
id
name
}
}
}'
mapping_output=$(gitlab_api_get_project_name_mapping "${query}")
# update cache
while read -r project_id project_name; do
printf "%s %s\n" "${project_id}" "${project_name}" >> "${project_name_cache_file}"
done < <(jq --raw-output \
'.[] | "\(.id | rindex("/") as $lastSlash | .[$lastSlash+1:]) \(.name)"' \
<<< "${mapping_output}")
done
term_spinner_stop "${status_dir}"
msg_success "Querying GitLab project names"
# read project_id to name mapping from cache # read project_id to name mapping from cache
declare -A project_name_lookup=() declare -A project_name_lookup=()
while read -r project_id project_name; do while read -r project_id project_name; do
project_name_lookup[${project_id}]=${project_name} project_name_lookup[${project_id}]=${project_name}
done < <(gitlab_lookup_project_names "${status_dir}/status" "${project_ids[@]}") done < "${project_name_cache_file}"
term_spinner_stop "${status_dir}" # close project name cache lock
msg_success "Querying GitLab project names" lock_close 11
# output mode JSON # output mode JSON
if [[ ${output_format} == json ]]; then if [[ ${output_format} == json ]]; then

18
src/lib/state.sh Normal file
View File

@@ -0,0 +1,18 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_STATE_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_STATE_SH=1
set -e
readonly XDG_DEVTOOLS_STATE_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/devtools"
get_state_folder() {
local foldername=$1
local path="${XDG_DEVTOOLS_STATE_DIR}/${foldername}"
mkdir --parents -- "$path"
printf '%s' "${path}"
}

View File

@@ -25,7 +25,6 @@ update_pacman_repo_cache() {
lock 10 "${_DEVTOOLS_PACMAN_CACHE_DIR}.lock" "Locking pacman database cache" lock 10 "${_DEVTOOLS_PACMAN_CACHE_DIR}.lock" "Locking pacman database cache"
fakeroot -- pacman --config "${_DEVTOOLS_PACMAN_CONF_DIR}/${repo}.conf" \ fakeroot -- pacman --config "${_DEVTOOLS_PACMAN_CONF_DIR}/${repo}.conf" \
--dbpath "${_DEVTOOLS_PACMAN_CACHE_DIR}" \ --dbpath "${_DEVTOOLS_PACMAN_CACHE_DIR}" \
--disable-sandbox \
-Sy -Sy
lock_close 10 lock_close 10
} }
@@ -33,7 +32,6 @@ update_pacman_repo_cache() {
get_pacman_repo_from_pkgbuild() { get_pacman_repo_from_pkgbuild() {
local path=${1:-PKGBUILD} local path=${1:-PKGBUILD}
local repo=${2:-multilib} local repo=${2:-multilib}
local -a pkgnames
# shellcheck source=contrib/makepkg/PKGBUILD.proto # shellcheck source=contrib/makepkg/PKGBUILD.proto
mapfile -t pkgnames < <(source "${path}"; printf "%s\n" "${pkgname[@]}") mapfile -t pkgnames < <(source "${path}"; printf "%s\n" "${pkgname[@]}")
@@ -68,7 +66,6 @@ get_pkgnames_from_repo_pkgbase() {
local repo=$1 local repo=$1
shift shift
local pkgbases=("$@") local pkgbases=("$@")
local -a pkgnames
# update the pacman repo cache if it doesn't exist yet # update the pacman repo cache if it doesn't exist yet
if [[ ! -d "${_DEVTOOLS_PACMAN_CACHE_DIR}" ]]; then if [[ ! -d "${_DEVTOOLS_PACMAN_CACHE_DIR}" ]]; then

View File

@@ -7,8 +7,6 @@ DEVTOOLS_INCLUDE_UTIL_TERM_SH=1
set -eo pipefail set -eo pipefail
readonly PKGCTL_TERM_ICON_CONFIDENTIAL=
export PKGCTL_TERM_ICON_CONFIDENTIAL
readonly PKGCTL_TERM_SPINNER_DOTS=Dots readonly PKGCTL_TERM_SPINNER_DOTS=Dots
export PKGCTL_TERM_SPINNER_DOTS export PKGCTL_TERM_SPINNER_DOTS

View File

@@ -1,68 +0,0 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
# shellcheck disable=2034
DEVTOOLS_VALID_ISSUE_SEVERITY=(
lowest
low
medium
high
critical
)
# shellcheck disable=2034
DEVTOOLS_VALID_ISSUE_PRIORITY=(
low
normal
high
urgent
)
# shellcheck disable=2034
DEVTOOLS_VALID_ISSUE_STATUS=(
confirmed
in-progress
in-review
on-hold
unconfirmed
waiting-input
waiting-upstream
)
# shellcheck disable=2034
DEVTOOLS_VALID_ISSUE_SCOPE=(
bug
feature
security
question
regression
enhancement
documentation
reproducibility
out-of-date
)
# shellcheck disable=2034
DEVTOOLS_VALID_ISSUE_SEARCH_LOCATION=(
title
description
all
)
# shellcheck disable=2034
DEVTOOLS_VALID_ISSUE_RESOLUTION=(
cant-reproduce
completed
duplicate
invalid
not-a-bug
upstream
wont-fix
)
# shellcheck disable=2034
DEVTOOLS_VALID_ISSUE_CONFIDENTIALITY=(
confidential
public
)

View File

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

View File

@@ -10,8 +10,6 @@ _DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
# shellcheck source=src/lib/util/term.sh # shellcheck source=src/lib/util/term.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/term.sh source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/term.sh
# shellcheck source=src/lib/valid-version.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-version.sh
source /usr/share/makepkg/util/message.sh source /usr/share/makepkg/util/message.sh
@@ -41,16 +39,9 @@ pkgctl_version_check_usage() {
check failures. check failures.
OPTIONS OPTIONS
-v, --verbose Display results including up-to-date versions
-h, --help Show this help text -h, --help Show this help text
FILTER OPTIONS
-v, --verbose Display all results including up-to-date versions
OUTPUT OPTIONS
--json Enable printing in JSON; Shorthand for '--format json'
-F, --format FORMAT Controls the output format of the results;
FORMAT is 'pretty', or 'json' (default: pretty)
EXAMPLES EXAMPLES
$ ${COMMAND} neovim vim $ ${COMMAND} neovim vim
_EOF_ _EOF_
@@ -59,11 +50,9 @@ _EOF_
pkgctl_version_check() { pkgctl_version_check() {
local pkgbases=() local pkgbases=()
local verbose=0 local verbose=0
local output_format=pretty
local path status_file path pkgbase upstream_version result local path status_file path pkgbase upstream_version result
local json_data=()
local up_to_date=() local up_to_date=()
local out_of_date=() local out_of_date=()
local failure=() local failure=()
@@ -77,18 +66,6 @@ pkgctl_version_check() {
pkgctl_version_check_usage pkgctl_version_check_usage
exit 0 exit 0
;; ;;
--json)
output_format=json
shift
;;
-F|--format)
(( $# <= 1 )) && die "missing argument for %s" "$1"
output_format="${2}"
if ! in_array "${output_format}" "${DEVTOOLS_VALID_VERSION_OUTPUT_FORMAT[@]}"; then
die "Unknown output format: %s" "${output_format}"
fi
shift 2
;;
-v|--verbose) -v|--verbose)
verbose=1 verbose=1
shift shift
@@ -126,11 +103,9 @@ pkgctl_version_check() {
verbose=1 verbose=1
fi fi
if [[ ${output_format} == pretty ]]; then
# start a terminal spinner as checking versions takes time # start a terminal spinner as checking versions takes time
status_dir=$(mktemp --tmpdir="${WORKDIR}" --directory pkgctl-version-check-spinner.XXXXXXXXXX) status_dir=$(mktemp --tmpdir="${WORKDIR}" --directory pkgctl-version-check-spinner.XXXXXXXXXX)
term_spinner_start "${status_dir}" term_spinner_start "${status_dir}"
fi
for path in "${pkgbases[@]}"; do for path in "${pkgbases[@]}"; do
# skip paths that are not directories # skip paths that are not directories
@@ -139,7 +114,6 @@ pkgctl_version_check() {
fi fi
pushd "${path}" >/dev/null pushd "${path}" >/dev/null
if [[ ${output_format} == pretty ]]; then
# update the current terminal spinner status # update the current terminal spinner status
(( ++current_item )) (( ++current_item ))
pkgctl_version_check_spinner \ pkgctl_version_check_spinner \
@@ -149,13 +123,10 @@ pkgctl_version_check() {
"${#failure[@]}" \ "${#failure[@]}" \
"${current_item}" \ "${current_item}" \
"${#pkgbases[@]}" "${#pkgbases[@]}"
fi
if [[ ! -f "PKGBUILD" ]]; then if [[ ! -f "PKGBUILD" ]]; then
result="no PKGBUILD found" result="${BOLD}${path}${ALL_OFF}: no PKGBUILD found"
pkgbase=$(basename "${path}") failure+=("${result}")
json_data+=("$(build_json_package_version_entry "${pkgbase}" failure "${result}" false null null)")
failure+=("${BOLD}${pkgbase}${ALL_OFF}: ${result}")
popd >/dev/null popd >/dev/null
continue continue
fi fi
@@ -167,36 +138,27 @@ pkgctl_version_check() {
pkgbase=${pkgbase:-$pkgname} pkgbase=${pkgbase:-$pkgname}
if ! result=$(get_upstream_version); then if ! result=$(get_upstream_version); then
json_data+=("$(build_json_package_version_entry "${pkgbase}" failure "${result}" false "${pkgver}" null)") result="${BOLD}${pkgbase}${ALL_OFF}: ${result}"
failure+=("${BOLD}${pkgbase}${ALL_OFF}: ${result}") failure+=("${result}")
popd >/dev/null popd >/dev/null
continue continue
fi fi
upstream_version=${result} upstream_version=${result}
if ! result=$(vercmp "${upstream_version}" "${pkgver}"); then if ! result=$(vercmp "${upstream_version}" "${pkgver}"); then
result="failed to compare version ${upstream_version} against ${pkgver}" result="${BOLD}${pkgbase}${ALL_OFF}: failed to compare version ${upstream_version} against ${pkgver}"
json_data+=("$(build_json_package_version_entry "${pkgbase}" failure "${result}" false "${pkgver}" "${upstream_version}")")
result="${BOLD}${pkgbase}${ALL_OFF}: ${result}"
failure+=("${result}") failure+=("${result}")
popd >/dev/null popd >/dev/null
continue continue
fi fi
if (( result == 0 )); then if (( result == 0 )); then
if (( verbose )); then
json_data+=("$(build_json_package_version_entry "${pkgbase}" success null false "${pkgver}" "${upstream_version}")")
fi
result="${BOLD}${pkgbase}${ALL_OFF}: current version ${PURPLE}${pkgver}${ALL_OFF} is latest" result="${BOLD}${pkgbase}${ALL_OFF}: current version ${PURPLE}${pkgver}${ALL_OFF} is latest"
up_to_date+=("${result}") up_to_date+=("${result}")
elif (( result < 0 )); then elif (( result < 0 )); then
if (( verbose )); then
json_data+=("$(build_json_package_version_entry "${pkgbase}" warning "local version is newer than upstream" false "${pkgver}" "${upstream_version}")")
fi
result="${BOLD}${pkgbase}${ALL_OFF}: current version ${PURPLE}${pkgver}${ALL_OFF} is newer than ${DARK_GREEN}${upstream_version}${ALL_OFF}" result="${BOLD}${pkgbase}${ALL_OFF}: current version ${PURPLE}${pkgver}${ALL_OFF} is newer than ${DARK_GREEN}${upstream_version}${ALL_OFF}"
up_to_date+=("${result}") up_to_date+=("${result}")
elif (( result > 0 )); then elif (( result > 0 )); then
json_data+=("$(build_json_package_version_entry "${pkgbase}" success null true "${pkgver}" "${upstream_version}")")
result="${BOLD}${pkgbase}${ALL_OFF}: upgrade from version ${PURPLE}${pkgver}${ALL_OFF} to ${DARK_GREEN}${upstream_version}${ALL_OFF}" result="${BOLD}${pkgbase}${ALL_OFF}: upgrade from version ${PURPLE}${pkgver}${ALL_OFF} to ${DARK_GREEN}${upstream_version}${ALL_OFF}"
out_of_date+=("${result}") out_of_date+=("${result}")
fi fi
@@ -204,18 +166,8 @@ pkgctl_version_check() {
popd >/dev/null popd >/dev/null
done done
if [[ ${output_format} == pretty ]]; then
# stop the terminal spinner after all checks # stop the terminal spinner after all checks
term_spinner_stop "${status_dir}" term_spinner_stop "${status_dir}"
fi
# early exit for json output
if [[ ${output_format} == json ]]; then
jq --null-input \
'$ARGS.positional' \
--jsonargs "${json_data[@]}"
return 0
fi
if (( verbose )) && (( ${#up_to_date[@]} > 0 )); then if (( verbose )) && (( ${#up_to_date[@]} > 0 )); then
printf "%sUp-to-date%s\n" "${section_separator}${BOLD}${UNDERLINE}" "${ALL_OFF}" printf "%sUp-to-date%s\n" "${section_separator}${BOLD}${UNDERLINE}" "${ALL_OFF}"
@@ -256,24 +208,6 @@ pkgctl_version_check() {
return "${exit_code}" return "${exit_code}"
} }
build_json_package_version_entry() {
local pkgbase=$1
local status=$2
local message=$3
local is_out_of_date=$4
local local_version=$5
local upstream_version=$6
jq --null-input \
--arg pkgbase "${pkgbase}" \
--arg status "${status}" \
--arg message "${message}" \
--arg local_version "${local_version}" \
--arg upstream_version "${upstream_version}" \
--argjson out_of_date "${is_out_of_date}" \
'$ARGS.named | walk(if type == "string" and (. == "null" or . == "") then null else . end)'
}
get_upstream_version() { get_upstream_version() {
local config=.nvchecker.toml local config=.nvchecker.toml
local output errors upstream_version local output errors upstream_version
@@ -292,8 +226,7 @@ get_upstream_version() {
opts+=(--keyfile "${keyfile}") opts+=(--keyfile "${keyfile}")
fi fi
if ! output=$(GIT_TERMINAL_PROMPT=0 GIT_CONFIG_GLOBAL=/dev/null GIT_CONFIG_SYSTEM=/dev/null \ if ! output=$(GIT_TERMINAL_PROMPT=0 nvchecker --file "${config}" --logger json "${opts[@]}" 2>&1 | \
nvchecker --file "${config}" --logger json "${opts[@]}" 2>&1 | \
jq --raw-output 'select((.level != "debug") and (.event != "ignoring invalid version"))'); then jq --raw-output 'select((.level != "debug") and (.event != "ignoring invalid version"))'); then
printf "failed to run nvchecker: %s" "${output}" printf "failed to run nvchecker: %s" "${output}"
return 1 return 1
@@ -309,12 +242,6 @@ get_upstream_version() {
return 1 return 1
fi fi
# implement none source for packages like meta and virtual packages that are always up to date
if [[ ${upstream_version} == None ]] && grep --quiet --extended-regexp '^source *= *"manual"' "${config}" &>/dev/null; then
printf '%s' "${pkgver:-${upstream_version}}"
return 0
fi
printf "%s" "${upstream_version}" printf "%s" "${upstream_version}"
return 0 return 0
} }
@@ -357,7 +284,7 @@ nvchecker_check_error() {
local errors local errors
if ! errors=$(jq --raw-output --exit-status \ if ! errors=$(jq --raw-output --exit-status \
'select((.level == "error") and (.error != null)) | "\(.event)" + if .error then ": \(.error)" else "" end' \ 'select(.level == "error") | "\(.event)" + if .error then ": \(.error)" else "" end' \
<<< "${result}"); then <<< "${result}"); then
return 0 return 0
fi fi

View File

@@ -33,7 +33,6 @@ pkgctl_version_setup_usage() {
--prefer-platform-api Prefer platform specific GitHub/GitLab API for complex cases --prefer-platform-api Prefer platform specific GitHub/GitLab API for complex cases
--url URL Derive check target from URL instead of source array --url URL Derive check target from URL instead of source array
--no-check Do not run version check after setup --no-check Do not run version check after setup
--no-upstream Setup a blank config for packages without upstream sources
-h, --help Show this help text -h, --help Show this help text
EXAMPLES EXAMPLES
@@ -47,7 +46,6 @@ pkgctl_version_setup() {
local run_check=1 local run_check=1
local force=0 local force=0
local prefer_platform_api=0 local prefer_platform_api=0
local no_upstream=0
local path ret local path ret
local checks=() local checks=()
@@ -75,10 +73,6 @@ pkgctl_version_setup() {
run_check=0 run_check=0
shift shift
;; ;;
--no-upstream)
no_upstream=1
shift
;;
--) --)
shift shift
break break
@@ -111,7 +105,7 @@ pkgctl_version_setup() {
fi fi
pushd "${path}" >/dev/null pushd "${path}" >/dev/null
if nvchecker_setup "${path}" "${force}" "${prefer_platform_api}" "${override_url}" "${no_upstream}"; then if nvchecker_setup "${path}" "${force}" "${prefer_platform_api}" "${override_url}"; then
checks+=("${path}") checks+=("${path}")
else else
ret=1 ret=1
@@ -133,7 +127,6 @@ nvchecker_setup() {
local force=$2 local force=$2
local prefer_platform_api=$3 local prefer_platform_api=$3
local override_url=$4 local override_url=$4
local no_upstream=$5
local pkgbase pkgname source source_url proto domain url_parts section body local pkgbase pkgname source source_url proto domain url_parts section body
if [[ ! -f PKGBUILD ]]; then if [[ ! -f PKGBUILD ]]; then
@@ -166,7 +159,7 @@ nvchecker_setup() {
fi fi
# skip empty source array # skip empty source array
if (( ${#source[@]} == 0 )) && (( ! no_upstream )); then if (( ${#source[@]} == 0 )); then
msg_error "${BOLD}${pkgbase}:${ALL_OFF} PKGBUILD has no source array" msg_error "${BOLD}${pkgbase}:${ALL_OFF} PKGBUILD has no source array"
return 1 return 1
fi fi
@@ -252,10 +245,6 @@ nvchecker_setup() {
esac esac
done done
if (( no_upstream )); then
body='source = "manual"'
fi
if [[ -z "${body}" ]]; then if [[ -z "${body}" ]]; then
msg_error "${BOLD}${pkgbase}:${ALL_OFF} unable to automatically setup nvchecker" msg_error "${BOLD}${pkgbase}:${ALL_OFF} unable to automatically setup nvchecker"
return 1 return 1

View File

@@ -105,7 +105,7 @@ sync_chroot() {
"Locking clean chroot [%s]" "$chrootdir/root" "Locking clean chroot [%s]" "$chrootdir/root"
stat_busy "Synchronizing chroot copy [%s] -> [%s]" "$chrootdir/root" "$copy" stat_busy "Synchronizing chroot copy [%s] -> [%s]" "$chrootdir/root" "$copy"
if is_btrfs "$chrootdir" && is_subvolume "$chrootdir/root" && ! mountpoint -q "$copydir"; then if is_btrfs "$chrootdir" && ! mountpoint -q "$copydir"; then
subvolume_delete_recursive "$copydir" || subvolume_delete_recursive "$copydir" ||
die "Unable to delete subvolume %s" "$copydir" die "Unable to delete subvolume %s" "$copydir"
btrfs subvolume snapshot "$chrootdir/root" "$copydir" >/dev/null || btrfs subvolume snapshot "$chrootdir/root" "$copydir" >/dev/null ||

View File

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

View File

@@ -23,6 +23,7 @@ fi
repo=extra repo=extra
arch=x86_64 arch=x86_64
server=build.archlinux.org server=build.archlinux.org
rsyncopts=("${RSYNC_OPTS[@]}")
usage() { usage() {
cat <<- _EOF_ cat <<- _EOF_
@@ -77,8 +78,7 @@ fi
archbuild_cmd=("${repo}${archbuild_arch:+-$archbuild_arch}-build" "$@") archbuild_cmd=("${repo}${archbuild_arch:+-$archbuild_arch}-build" "$@")
[[ -z ${WORKDIR:-} ]] && setup_workdir trap 'rm -rf $TEMPDIR' EXIT INT TERM QUIT
export TEMPDIR=$(mktemp --tmpdir="${WORKDIR}" --directory offload-build.XXXXXXXXXX)
# Load makepkg.conf variables to be available # Load makepkg.conf variables to be available
load_makepkg_config load_makepkg_config
@@ -86,41 +86,32 @@ load_makepkg_config
# Use a source-only tarball as an intermediate to transfer files. This # Use a source-only tarball as an intermediate to transfer files. This
# guarantees the checksums are okay, and guarantees that all needed files are # guarantees the checksums are okay, and guarantees that all needed files are
# transferred, including local sources, install scripts, and changelogs. # transferred, including local sources, install scripts, and changelogs.
export SRCPKGDEST="${TEMPDIR}" export TEMPDIR=$(mktemp -d --tmpdir offload-build.XXXXXXXXXX)
export SRCPKGDEST=${TEMPDIR}
makepkg_source_package || die "unable to make source package" makepkg_source_package || die "unable to make source package"
# Temporary cosmetic workaround makepkg if SRCDEST is set somewhere else # Temporary cosmetic workaround makepkg if SRCDEST is set somewhere else
# but an empty src dir is created in PWD. Remove once fixed in makepkg. # but an empty src dir is created in PWD. Remove once fixed in makepkg.
rmdir --ignore-fail-on-non-empty src 2>/dev/null || true rmdir --ignore-fail-on-non-empty src 2>/dev/null || true
# Create a temporary directory on the server mapfile -t files < <(
remote_temp=$( # This is sort of bash golfing but it allows running a mildly complex
ssh "${SSH_OPTS[@]}" -- "$server" ' # command over ssh with a single connection.
# shellcheck disable=SC2145
cat "$SRCPKGDEST"/*"$SRCEXT" |
ssh $server '
export TERM="'"${TERM}"'"
temp="${XDG_CACHE_HOME:-$HOME/.cache}/offload-build" && temp="${XDG_CACHE_HOME:-$HOME/.cache}/offload-build" &&
mkdir -p "$temp" && mkdir -p "$temp" &&
mktemp --directory --tmpdir="$temp" temp=$(mktemp -d -p "$temp") &&
') cd "$temp" &&
{
# Transfer the srcpkg to the server bsdtar --strip-components 1 -xvf - &&
msg "Transferring source package to the server..." export LOGDEST="" &&
_srcpkg=("$SRCPKGDEST"/*"$SRCEXT") script -qefc "'"${archbuild_cmd[@]@Q}"'" /dev/null &&
srcpkg="${_srcpkg[0]}" printf "%s\n" "" "-> build complete" &&
rsync "${RSYNC_OPTS[@]}" -- "$srcpkg" "$server":"$remote_temp" || die printf "\t%s\n" "$temp"/*
} >&2 &&
# Prepare the srcpkg on the server
msg "Extracting srcpkg"
ssh "${SSH_OPTS[@]}" -- "$server" "cd ${remote_temp@Q} && bsdtar --strip-components 1 -xvf $(basename "$srcpkg")" || die
# Run the build command on the server
msg "Running archbuild"
# shellcheck disable=SC2145
if ssh "${SSH_OPTS[@]}" -t -- "$server" "cd ${remote_temp@Q} && export LOGDEST="" && ${archbuild_cmd[@]@Q}"; then
msg "Build complete"
# Get an array of files that should be downloaded from the server
mapfile -t files < <(
ssh "${SSH_OPTS[@]}" -- "$server" "
cd ${remote_temp@Q}"' &&
makepkg_user_config="${XDG_CONFIG_HOME:-$HOME/.config}/pacman/makepkg.conf" && makepkg_user_config="${XDG_CONFIG_HOME:-$HOME/.config}/pacman/makepkg.conf" &&
makepkg_config="/usr/share/devtools/makepkg.conf.d/'"${arch}"'.conf" && makepkg_config="/usr/share/devtools/makepkg.conf.d/'"${arch}"'.conf" &&
if [[ -f /usr/share/devtools/makepkg.conf.d/'"${repo}"'-'"${arch}"'.conf ]]; then if [[ -f /usr/share/devtools/makepkg.conf.d/'"${repo}"'-'"${arch}"'.conf ]]; then
@@ -129,34 +120,26 @@ if ssh "${SSH_OPTS[@]}" -t -- "$server" "cd ${remote_temp@Q} && export LOGDEST="
while read -r file; do while read -r file; do
[[ -f "${file}" ]] && printf "%s\n" "${file}" ||: [[ -f "${file}" ]] && printf "%s\n" "${file}" ||:
done < <(makepkg --config <(cat "${makepkg_user_config}" "${makepkg_config}" 2>/dev/null) --packagelist) && done < <(makepkg --config <(cat "${makepkg_user_config}" "${makepkg_config}" 2>/dev/null) --packagelist) &&
printf "%s\n" '"${remote_temp@Q}/PKGBUILD"' printf "%s\n" "${temp}/PKGBUILD"
find '"${remote_temp@Q}"' -name "*.log" find "${temp}" -name "*.log"
') ')
else
# Build failed, only the logs should be downloaded from the server
mapfile -t files < <(
ssh "${SSH_OPTS[@]}" -- "$server" '
find '"${remote_temp@Q}"' -name "*.log"
')
fi
if (( ${#files[@]} )); then if (( ${#files[@]} )); then
msg 'Downloading files...' msg 'Downloading files...'
rsync "${RSYNC_OPTS[@]}" -- "${files[@]/#/$server:}" "${TEMPDIR}/" || die rsync "${rsyncopts[@]}" "${files[@]/#/$server:}" "${TEMPDIR}/" || die
if is_globfile "${TEMPDIR}"/*.log; then if is_globfile "${TEMPDIR}"/*.log; then
mv "${TEMPDIR}"/*.log "${LOGDEST:-${PWD}}/" mv "${TEMPDIR}"/*.log "${LOGDEST:-${PWD}}/"
fi fi
if is_globfile "${TEMPDIR}"/*.pkg.tar*; then # missing PKGBUILD download means the build failed
# Building a package may change the PKGBUILD during update_pkgver if [[ ! -f "${TEMPDIR}/PKGBUILD" ]]; then
mv "${TEMPDIR}/PKGBUILD" "${PWD}/"
mv "${TEMPDIR}"/*.pkg.tar* "${PKGDEST:-${PWD}}/"
else
error "Build failed, check logs in ${LOGDEST:-${PWD}}" error "Build failed, check logs in ${LOGDEST:-${PWD}}"
exit 1 exit 1
fi fi
mv "${TEMPDIR}/PKGBUILD" "${PWD}/"
mv "${TEMPDIR}"/*.pkg.tar* "${PKGDEST:-${PWD}}/"
else else
exit 1 exit 1
fi fi

View File

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