Compare commits

..

1 Commits

Author SHA1 Message Date
Jelle van der Waa
a0c0c63a85 PoC: build offline support 2024-10-10 19:35:42 +02:00
63 changed files with 184 additions and 3911 deletions

View File

@@ -1,6 +1,6 @@
SHELL=/bin/bash -o pipefail
V=1.3.1
V=1.2.1
BUILDTOOLVER ?= $(V)
PREFIX = /usr/local

View File

@@ -74,9 +74,7 @@ Component: pkgctl db remove
- expac
- fakeroot
- findutils
- glow
- grep
- gum
- jq
- ncurses
- openssh

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 \
-Wl,-z,pack-relative-relocs"
LTOFLAGS="-flto=auto"
RUSTFLAGS="-Cforce-frame-pointers=yes"
#-- Make Flags: change this for DistCC/SMP systems
#MAKEFLAGS="-j2"
#-- Debugging flags
DEBUG_CFLAGS="-g"
DEBUG_CXXFLAGS="$DEBUG_CFLAGS"
DEBUG_RUSTFLAGS="-C debuginfo=2"
#########################################################################
# BUILD ENVIRONMENT
@@ -81,7 +83,7 @@ BUILDENV=(!distcc color !ccache check !sign)
# 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.
#
#-- strip: Strip symbols from binaries/libraries
@@ -93,7 +95,6 @@ BUILDENV=(!distcc color !ccache check !sign)
#-- purge: Remove files specified by PURGE_TARGETS
#-- debug: Add debugging flags as specified in DEBUG_* variables
#-- 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)
@@ -113,8 +114,6 @@ DOC_DIRS=(usr/{,local/}{,share/}{doc,gtk-doc} opt/*/{doc,gtk-doc})
PURGE_TARGETS=(usr/{,share}/info/dir .packlist *.pod)
#-- Directory to store source code in for debug packages
DBGSRCDIR="/usr/src/debug"
#-- Prefix and directories for library autodeps
LIB_DIRS=('lib:usr/lib' 'lib32:usr/lib32')
#########################################################################
# PACKAGE OUTPUT

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 \
-Wl,-z,pack-relative-relocs"
LTOFLAGS="-flto=auto"
RUSTFLAGS="-Cforce-frame-pointers=yes"
#-- Make Flags: change this for DistCC/SMP systems
#MAKEFLAGS="-j2"
#-- Debugging flags
DEBUG_CFLAGS="-g"
DEBUG_CXXFLAGS="$DEBUG_CFLAGS"
DEBUG_RUSTFLAGS="-C debuginfo=2"
#########################################################################
# BUILD ENVIRONMENT
@@ -81,7 +83,7 @@ BUILDENV=(!distcc color !ccache check !sign)
# 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.
#
#-- strip: Strip symbols from binaries/libraries
@@ -93,7 +95,6 @@ BUILDENV=(!distcc color !ccache check !sign)
#-- purge: Remove files specified by PURGE_TARGETS
#-- debug: Add debugging flags as specified in DEBUG_* variables
#-- 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)
@@ -113,8 +114,6 @@ DOC_DIRS=(usr/{,local/}{,share/}{doc,gtk-doc} opt/*/{doc,gtk-doc})
PURGE_TARGETS=(usr/{,share}/info/dir .packlist *.pod)
#-- Directory to store source code in for debug packages
DBGSRCDIR="/usr/src/debug"
#-- Prefix and directories for library autodeps
LIB_DIRS=('lib:usr/lib' 'lib32:usr/lib32')
#########################################################################
# PACKAGE OUTPUT

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace
VerbosePkgLists
ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# 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.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace
VerbosePkgLists
ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# 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.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace
VerbosePkgLists
ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# 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.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace
VerbosePkgLists
ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# 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.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace
VerbosePkgLists
ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# 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.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace
VerbosePkgLists
ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# 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.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace
VerbosePkgLists
ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# 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.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace
VerbosePkgLists
ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# 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.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace
VerbosePkgLists
ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# 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.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace
VerbosePkgLists
ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# 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.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace
VerbosePkgLists
ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# 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.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace
VerbosePkgLists
ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# 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.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace
VerbosePkgLists
ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# 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.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace
VerbosePkgLists
ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# 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.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace
VerbosePkgLists
ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# 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.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace
VerbosePkgLists
ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# 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.

View File

@@ -36,8 +36,6 @@ NoProgressBar
#CheckSpace
VerbosePkgLists
ParallelDownloads = 5
DownloadUser = alpm
#DisableSandbox
# 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.

View File

@@ -13,10 +13,6 @@ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-repos.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-inspect.sh
# shellcheck source=src/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)
@@ -149,7 +145,6 @@ _pkgctl_cmds=(
build
db
diff
issue
release
repo
search
@@ -376,19 +371,14 @@ _pkgctl_version_cmds=(
_pkgctl_version_check_args=(
-v --verbose
-h --help
--json
-F --format
)
_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=(
--prefer-platform-api
--url
--no-check
--no-upstream
-f --force
-h --help
)
@@ -446,185 +436,6 @@ _pkgctl_diff_args__pool_opts() { _filedir -d; }
_pkgctl_diff_args_P_opts() { _pkgctl_diff_args__pool_opts; }
_pkgctl_diff_opts() { _devtools_completions_all_packages; }
_pkgctl_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=(
-h --help
@@ -659,30 +470,6 @@ _devtools_completions_inspect() {
_devtools_completions_search_format() {
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() {
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
# shellcheck source=src/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)
@@ -94,112 +90,6 @@ _pkgctl_db_update_args=(
'(-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=(
'(-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[*])"
@@ -398,7 +288,6 @@ _pkgctl_cmds=(
"build[Build packages inside a clean chroot]"
"db[Pacman database modification for package update, move etc]"
"diff[Compare package files using different modes]"
"issue[Work with GitLab packaging issues]"
"release[Release step to commit, tag and upload build artifacts]"
"repo[Manage Git packaging repositories and their configuration]"
"search[Search for an expression across the GitLab packaging group]"
@@ -418,10 +307,8 @@ _pkgctl_version_cmds=(
)
_pkgctl_version_check_args=(
'(-v --verbose)'{-v,--verbose}'[Display results including up-to-date versions]'
'(-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 -/'
)
@@ -430,7 +317,6 @@ _pkgctl_version_setup_args=(
'--prefer-platform-api[Prefer platform specific GitHub/GitLab API for complex cases]'
'--url[Derive check target from URL instead of source array]:url:'
'--no-check[Do not run version check after setup]'
'--no-upstream[Setup a blank config for packages without upstream sources]'
'(-h --help)'{-h,--help}'[Display usage]'
'*:git_dir:_files -/'
)

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

@@ -34,25 +34,12 @@ PKGBUILD. Refer to the configuration section in pkgctl-version(1).
Options
-------
*-v, --verbose*::
Display results including up-to-date versions
*-h, --help*::
Show a help text
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
----------

View File

@@ -42,15 +42,10 @@ Options
*--url* 'URL'::
Derive check target from the given URL instead of the source array entries
*--no-check*::
Do not run pkgctl-version-check(1) after setup
*--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*::
Show a help text

View File

@@ -39,14 +39,6 @@ placed in the `$XDG_CONFIG_HOME`/nvchecker` directory. This keyfile is
used for providing the necessary authentication tokens required for
accessing the GitHub or GitLab API.
Combiner Source
---------------
To utilize the combiner source, the `pkgbase` section must be declared as the
combiner source. Additionally, individual sections should be added using a
quoted table key consisting of the `pkgbase` followed by the stage name,
separated by double colons. For example: `["sudo:stage1"]`.
Options
-------

View File

@@ -12,9 +12,9 @@ pkgctl [SUBCOMMAND] [OPTIONS]
Description
-----------
Command-line utility serving as a unified interface for multiple development tools.
This tool aims to simplify and optimize interactions with devtools by offering
various subcommands for executing tasks related to package management, repository management,
Command-line utility serving as a unified interface for multiple development tools.
This tool aims to simplify and optimize interactions with devtools by offering
various subcommands for executing tasks related to package management, repository management,
version control, among others.
Utilizing pkgctl enables users to efficiently administer their development workflows.
@@ -46,9 +46,6 @@ pkgctl db::
pkgctl diff::
Compare package files using different modes
pkgctl issue::
Work with GitLab packaging issues
pkgctl release::
Release step to commit, tag and upload build artifacts
@@ -69,7 +66,6 @@ pkgctl-auth(1)
pkgctl-build(1)
pkgctl-db(1)
pkgctl-diff(1)
pkgctl-issue(1)
pkgctl-release(1)
pkgctl-repo(1)
pkgctl-search(1)

View File

@@ -65,7 +65,6 @@ nspawn_args=(
--machine="arch-nspawn-$$"
--as-pid2
--console=autopipe
--timezone=off
)
if (( ${#cache_dirs[@]} == 0 )); then

View File

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

View File

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

View File

@@ -8,12 +8,8 @@ DEVTOOLS_INCLUDE_API_GITLAB_SH=1
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
# shellcheck source=src/lib/common.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
# shellcheck source=src/lib/cache.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/cache.sh
# shellcheck source=src/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
@@ -119,13 +115,11 @@ gitlab_api_call_paged() {
local next_page=1
local total_pages=1
local known_total_pages=1
local percentage=100
while [[ -n "${next_page}" ]]; do
percentage=$(( 100 * next_page / total_pages ))
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}"
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 }')
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
jq --slurp add "${api_workdir}"/result.* > "${outfile}"
@@ -249,101 +234,6 @@ gitlab_api_get_project_name_mapping() {
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.
#
# GitLab has several limitations on project and group names and also maintains
@@ -412,492 +302,3 @@ gitlab_api_search() {
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

@@ -55,6 +55,7 @@ pkgctl_build_usage() {
-o, --offload Build on a remote server and transfer artifacts afterwards
-c, --clean Recreate the chroot before building
--inspect WHEN Spawn an interactive shell to inspect the chroot (never, always, failure)
--offline MODE Run a part of the build process offline (build, check)
-w, --worker SLOT Name of the worker slot, useful for concurrent builds (disables automatic names)
--nocheck Do not run the check() function in the PKGBUILD
@@ -198,6 +199,10 @@ pkgctl_build() {
EDIT=1
shift
;;
--offline)
MAKECHROOT_OPTIONS+=("-o" "$2")
shift 2
;;
-o|--offload)
OFFLOAD=1
shift

View File

@@ -34,18 +34,8 @@ export PACKAGING_REPO_RELEASE_HOST=repos.archlinux.org
export PKGBASE_MAINTAINER_URL=https://archlinux.org/packages/pkgbase-maintainer
export AUR_URL_SSH=aur@aur.archlinux.org
# 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=(
--rsh="ssh ${SSH_OPTS[*]}"
--rsh=ssh
--checksum
--copy-links
--human-readable
@@ -64,23 +54,15 @@ if [[ -t 2 && "$TERM" != dumb ]] || [[ ${DEVTOOLS_COLOR} == always ]]; then
if tput setaf 0 &>/dev/null; then
PURPLE="$(tput setaf 5)"
DARK_GREEN="$(tput setaf 2)"
DARK_RED="$(tput setaf 1)"
DARK_BLUE="$(tput setaf 4)"
DARK_YELLOW="$(tput setaf 3)"
UNDERLINE="$(tput smul)"
GRAY=$(tput setaf 242)
else
PURPLE="\e[35m"
DARK_GREEN="\e[32m"
DARK_RED="\e[31m"
DARK_BLUE="\e[34m"
DARK_YELLOW="\e[33m"
UNDERLINE="\e[4m"
GRAY=""
fi
else
# 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
stat_busy() {
@@ -386,55 +368,7 @@ is_globfile() {
}
join_by() {
local IFS=" "
local sep=$1
local split
local IFS="$1"
shift
split=$(printf "%s" "$*")
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"
echo "$*"
}

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

@@ -157,11 +157,6 @@ pkgctl_release() {
repo=${REPO}
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
repo="${repo}-testing"
elif (( STAGING )); then

View File

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

View File

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

View File

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

View File

@@ -7,8 +7,6 @@ DEVTOOLS_INCLUDE_UTIL_TERM_SH=1
set -eo pipefail
readonly PKGCTL_TERM_ICON_CONFIDENTIAL=
export PKGCTL_TERM_ICON_CONFIDENTIAL
readonly PKGCTL_TERM_SPINNER_DOTS=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
# shellcheck source=src/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
@@ -41,15 +39,8 @@ pkgctl_version_check_usage() {
check failures.
OPTIONS
-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)
-v, --verbose Display results including up-to-date versions
-h, --help Show this help text
EXAMPLES
$ ${COMMAND} neovim vim
@@ -59,11 +50,9 @@ _EOF_
pkgctl_version_check() {
local pkgbases=()
local verbose=0
local output_format=pretty
local path status_file path pkgbase upstream_version result
local json_data=()
local up_to_date=()
local out_of_date=()
local failure=()
@@ -77,18 +66,6 @@ pkgctl_version_check() {
pkgctl_version_check_usage
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)
verbose=1
shift
@@ -126,11 +103,9 @@ pkgctl_version_check() {
verbose=1
fi
if [[ ${output_format} == pretty ]]; then
# start a terminal spinner as checking versions takes time
status_dir=$(mktemp --tmpdir="${WORKDIR}" --directory pkgctl-version-check-spinner.XXXXXXXXXX)
term_spinner_start "${status_dir}"
fi
# start a terminal spinner as checking versions takes time
status_dir=$(mktemp --tmpdir="${WORKDIR}" --directory pkgctl-version-check-spinner.XXXXXXXXXX)
term_spinner_start "${status_dir}"
for path in "${pkgbases[@]}"; do
# skip paths that are not directories
@@ -139,23 +114,19 @@ pkgctl_version_check() {
fi
pushd "${path}" >/dev/null
if [[ ${output_format} == pretty ]]; then
# update the current terminal spinner status
(( ++current_item ))
pkgctl_version_check_spinner \
"${status_dir}" \
"${#up_to_date[@]}" \
"${#out_of_date[@]}" \
"${#failure[@]}" \
"${current_item}" \
"${#pkgbases[@]}"
fi
# update the current terminal spinner status
(( ++current_item ))
pkgctl_version_check_spinner \
"${status_dir}" \
"${#up_to_date[@]}" \
"${#out_of_date[@]}" \
"${#failure[@]}" \
"${current_item}" \
"${#pkgbases[@]}"
if [[ ! -f "PKGBUILD" ]]; then
result="no PKGBUILD found"
pkgbase=$(basename "${path}")
json_data+=("$(build_json_package_version_entry "${pkgbase}" failure "${result}" false null null)")
failure+=("${BOLD}${pkgbase}${ALL_OFF}: ${result}")
result="${BOLD}${path}${ALL_OFF}: no PKGBUILD found"
failure+=("${result}")
popd >/dev/null
continue
fi
@@ -167,36 +138,27 @@ pkgctl_version_check() {
pkgbase=${pkgbase:-$pkgname}
if ! result=$(get_upstream_version); then
json_data+=("$(build_json_package_version_entry "${pkgbase}" failure "${result}" false "${pkgver}" null)")
failure+=("${BOLD}${pkgbase}${ALL_OFF}: ${result}")
result="${BOLD}${pkgbase}${ALL_OFF}: ${result}"
failure+=("${result}")
popd >/dev/null
continue
fi
upstream_version=${result}
if ! result=$(vercmp "${upstream_version}" "${pkgver}"); then
result="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}"
result="${BOLD}${pkgbase}${ALL_OFF}: failed to compare version ${upstream_version} against ${pkgver}"
failure+=("${result}")
popd >/dev/null
continue
fi
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"
up_to_date+=("${result}")
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}"
up_to_date+=("${result}")
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}"
out_of_date+=("${result}")
fi
@@ -204,18 +166,8 @@ pkgctl_version_check() {
popd >/dev/null
done
if [[ ${output_format} == pretty ]]; then
# stop the terminal spinner after all checks
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
# stop the terminal spinner after all checks
term_spinner_stop "${status_dir}"
if (( verbose )) && (( ${#up_to_date[@]} > 0 )); then
printf "%sUp-to-date%s\n" "${section_separator}${BOLD}${UNDERLINE}" "${ALL_OFF}"
@@ -256,24 +208,6 @@ pkgctl_version_check() {
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() {
local config=.nvchecker.toml
local output errors upstream_version
@@ -292,8 +226,7 @@ get_upstream_version() {
opts+=(--keyfile "${keyfile}")
fi
if ! output=$(GIT_TERMINAL_PROMPT=0 GIT_CONFIG_GLOBAL=/dev/null GIT_CONFIG_SYSTEM=/dev/null \
nvchecker --file "${config}" --logger json "${opts[@]}" 2>&1 | \
if ! output=$(GIT_TERMINAL_PROMPT=0 nvchecker --file "${config}" --logger json "${opts[@]}" 2>&1 | \
jq --raw-output 'select((.level != "debug") and (.event != "ignoring invalid version"))'); then
printf "failed to run nvchecker: %s" "${output}"
return 1
@@ -304,22 +237,11 @@ get_upstream_version() {
return 1
fi
if ! output=$(jq --raw-output --exit-status 'select(.name == "'"${pkgbase}"'")' <<< "${output}"); then
printf "failed to select pkgbase result from output"
return 1
fi
if ! upstream_version=$(jq --raw-output --exit-status '.version' <<< "${output}"); then
printf "failed to select version from result"
return 1
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}"
return 0
}
@@ -351,7 +273,7 @@ nvchecker_check_config() {
fi
# check if the config contains any section other than pkgbase
if [[ -n ${pkgbase} ]] && property=$(grep --max-count=1 --perl-regexp "^\\[(?!\"?${pkgbase//+/\\+}(:.+)?\"?\\]).+\\]" < "${config}"); then
if [[ -n ${pkgbase} ]] && property=$(grep --max-count=1 --perl-regexp "^\\[(?!\"?${pkgbase//+/\\+}\"?\\]).+\\]" < "${config}"); then
printf "non-pkgbase section not supported in %s: %s" "${config}" "${property}"
return 1
fi

View File

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

View File

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

View File

@@ -23,6 +23,7 @@ fi
repo=extra
arch=x86_64
server=build.archlinux.org
rsyncopts=("${RSYNC_OPTS[@]}")
usage() {
cat <<- _EOF_
@@ -77,8 +78,7 @@ fi
archbuild_cmd=("${repo}${archbuild_arch:+-$archbuild_arch}-build" "$@")
[[ -z ${WORKDIR:-} ]] && setup_workdir
export TEMPDIR=$(mktemp --tmpdir="${WORKDIR}" --directory offload-build.XXXXXXXXXX)
trap 'rm -rf $TEMPDIR' EXIT INT TERM QUIT
# Load makepkg.conf variables to be available
load_makepkg_config
@@ -86,41 +86,32 @@ load_makepkg_config
# Use a source-only tarball as an intermediate to transfer files. This
# guarantees the checksums are okay, and guarantees that all needed files are
# 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"
# Temporary cosmetic workaround makepkg if SRCDEST is set somewhere else
# 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
# Create a temporary directory on the server
remote_temp=$(
ssh "${SSH_OPTS[@]}" -- "$server" '
temp="${XDG_CACHE_HOME:-$HOME/.cache}/offload-build" &&
mkdir -p "$temp" &&
mktemp --directory --tmpdir="$temp"
')
# Transfer the srcpkg to the server
msg "Transferring source package to the server..."
_srcpkg=("$SRCPKGDEST"/*"$SRCEXT")
srcpkg="${_srcpkg[0]}"
rsync "${RSYNC_OPTS[@]}" -- "$srcpkg" "$server":"$remote_temp" || die
# 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}"' &&
mapfile -t files < <(
# This is sort of bash golfing but it allows running a mildly complex
# 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" &&
mkdir -p "$temp" &&
temp=$(mktemp -d -p "$temp") &&
cd "$temp" &&
{
bsdtar --strip-components 1 -xvf - &&
export LOGDEST="" &&
script -qefc "'"${archbuild_cmd[@]@Q}"'" /dev/null &&
printf "%s\n" "" "-> build complete" &&
printf "\t%s\n" "$temp"/*
} >&2 &&
makepkg_user_config="${XDG_CONFIG_HOME:-$HOME/.config}/pacman/makepkg.conf" &&
makepkg_config="/usr/share/devtools/makepkg.conf.d/'"${arch}"'.conf" &&
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
[[ -f "${file}" ]] && printf "%s\n" "${file}" ||:
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"
')
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
find "${temp}" -name "*.log"
')
if (( ${#files[@]} )); then
msg 'Downloading files...'
rsync "${RSYNC_OPTS[@]}" -- "${files[@]/#/$server:}" "${TEMPDIR}/" || die
rsync "${rsyncopts[@]}" "${files[@]/#/$server:}" "${TEMPDIR}/" || die
if is_globfile "${TEMPDIR}"/*.log; then
mv "${TEMPDIR}"/*.log "${LOGDEST:-${PWD}}/"
fi
if is_globfile "${TEMPDIR}"/*.pkg.tar*; then
# Building a package may change the PKGBUILD during update_pkgver
mv "${TEMPDIR}/PKGBUILD" "${PWD}/"
mv "${TEMPDIR}"/*.pkg.tar* "${PKGDEST:-${PWD}}/"
else
# missing PKGBUILD download means the build failed
if [[ ! -f "${TEMPDIR}/PKGBUILD" ]]; then
error "Build failed, check logs in ${LOGDEST:-${PWD}}"
exit 1
fi
mv "${TEMPDIR}/PKGBUILD" "${PWD}/"
mv "${TEMPDIR}"/*.pkg.tar* "${PKGDEST:-${PWD}}/"
else
exit 1
fi

View File

@@ -24,7 +24,6 @@ usage() {
build Build packages inside a clean chroot
db Pacman database modification for package update, move etc
diff Compare package files using different modes
issue Work with GitLab packaging issues
release Release step to commit, tag and upload build artifacts
repo Manage Git packaging repositories and their configuration
search Search for an expression across the GitLab packaging group
@@ -105,14 +104,6 @@ while (( $# )); do
diffpkg "$@"
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
;;
release)
_DEVTOOLS_COMMAND+=" $1"
shift