From bb72473529e300724eb7d78890da85a9ca7f6157 Mon Sep 17 00:00:00 2001 From: Levente Polyak Date: Fri, 9 Sep 2022 20:14:34 +0200 Subject: crossrepomove: drop support as this is not needed anymore We unified the source repositories to a single location. Having to cross repo move them between physical locations is not required anymore. --- contrib/completion/bash/devtools.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/completion/bash') diff --git a/contrib/completion/bash/devtools.in b/contrib/completion/bash/devtools.in index e7925b3..8183395 100644 --- a/contrib/completion/bash/devtools.in +++ b/contrib/completion/bash/devtools.in @@ -29,7 +29,7 @@ _archco() { _archco_pkg Slq true } && -complete -F _archco archco communityco +complete -F _archco archco _makechrootpkg() { local cur -- cgit v1.2.3-70-g09d2 From 3d3176beb6eb0319809be386cd903fa03bdabc73 Mon Sep 17 00:00:00 2001 From: Levente Polyak Date: Sun, 11 Sep 2022 22:17:09 +0200 Subject: pkgrepo: rename archco as a general purpose tool for packaging repos Signed-off-by: Levente Polyak --- contrib/completion/bash/devtools.in | 10 +- contrib/completion/zsh/_devtools.in | 10 +- doc/man/devtools.7.asciidoc | 2 +- src/archco.in | 260 ------------------------------------ src/pkgrepo.in | 260 ++++++++++++++++++++++++++++++++++++ 5 files changed, 271 insertions(+), 271 deletions(-) delete mode 100644 src/archco.in create mode 100644 src/pkgrepo.in (limited to 'contrib/completion/bash') diff --git a/contrib/completion/bash/devtools.in b/contrib/completion/bash/devtools.in index 8183395..a353b99 100644 --- a/contrib/completion/bash/devtools.in +++ b/contrib/completion/bash/devtools.in @@ -14,22 +14,22 @@ _devtools_compgen() { done } -_archco_pkg() { +_pkgrepo_pkg() { _devtools_compgen "$( command pacman "-$1" )" } -_archco() { - local cur prev +_pkgrepo() { + local cur prev COMPREPLY=() cur=$(_get_cword) prev=${COMP_WORDS[COMP_CWORD-1]} - _archco_pkg Slq + _pkgrepo_pkg Slq true } && -complete -F _archco archco +complete -F _pkgrepo pkgrepo _makechrootpkg() { local cur diff --git a/contrib/completion/zsh/_devtools.in b/contrib/completion/zsh/_devtools.in index d2fcfed..f6417df 100644 --- a/contrib/completion/zsh/_devtools.in +++ b/contrib/completion/zsh/_devtools.in @@ -1,4 +1,4 @@ -#compdef archbuild archco arch-nspawn archrelease commitpkg diffpkg finddeps makechrootpkg mkarchroot rebuildpkgs extrapkg=commitpkg corepkg=commitpkg testingpkg=commitpkg stagingpkg=commitpkg communitypkg=commitpkg community-testingpkg=commitpkg community-stagingpkg=commitpkg multilibpkg=commitpkg multilib-testingpkg=commitpkg extra-x86_64-build=archbuild testing-x86_64-build=archbuild staging-x86_64-build=archbuild multilib-build=archbuild multilib-testing-build=archbuild multilib-staging-build=archbuild kde-unstable-x86_64-build=archbuild gnome-unstable-x86_64-build=archbuild checkpkg sogrep offload-build makerepropkg +#compdef archbuild pkgrepo arch-nspawn archrelease commitpkg diffpkg finddeps makechrootpkg mkarchroot rebuildpkgs extrapkg=commitpkg corepkg=commitpkg testingpkg=commitpkg stagingpkg=commitpkg communitypkg=commitpkg community-testingpkg=commitpkg community-stagingpkg=commitpkg multilibpkg=commitpkg multilib-testingpkg=commitpkg extra-x86_64-build=archbuild testing-x86_64-build=archbuild staging-x86_64-build=archbuild multilib-build=archbuild multilib-testing-build=archbuild multilib-staging-build=archbuild kde-unstable-x86_64-build=archbuild gnome-unstable-x86_64-build=archbuild checkpkg sogrep offload-build makerepropkg # # SPDX-License-Identifier: GPL-3.0-or-later @@ -15,20 +15,20 @@ _archbuild_args=( '--[Introduce makechrootpkg options]:*::makechrootpkg options:= _dispatch makechrootpkg makechrootpkg' ) -_archco_cmds=( - "archco command" +_pkgrepo_cmds=( + "pkgrepo command" "clone[Clone a package repository]" "configure[Configure a clone according to distro specs]" ) -_archco_clone_args=( +_pkgrepo_clone_args=( '(-m --maintainer=)'{-m,--maintainer=}'[Clone all packages of the named maintainer]:maintainer:' '(-u --unprivileged)'{-u,--unprivileged}'[Read-only access without packager info as Git author]' '(-h --help)'{-h,--help}'[Display usage]' '*:packages:_devtools_completions_all_packages' ) -_archco_configure_args=( +_pkgrepo_configure_args=( '(-u --unprivileged)'{-u,--unprivileged}'[Configure read-only repo without packager info as Git author]' '(-h --help)'{-h,--help}'[Display usage]' '*:git_dir:_files -/' diff --git a/doc/man/devtools.7.asciidoc b/doc/man/devtools.7.asciidoc index 1bd118f..6b2d0c1 100644 --- a/doc/man/devtools.7.asciidoc +++ b/doc/man/devtools.7.asciidoc @@ -11,7 +11,7 @@ Description Devtools contains tools for package maintenance in Arch Linux. The toolset varies from tools for building packages in a clean chroot ('mkarchroot',...), packaging related tools for sonames ('sogrep', 'lddd') and tools for -repository management such as ('archco') +repository management such as ('pkgrepo') Programs -------- diff --git a/src/archco.in b/src/archco.in deleted file mode 100644 index 2804cba..0000000 --- a/src/archco.in +++ /dev/null @@ -1,260 +0,0 @@ -#!/bin/bash -# -# SPDX-License-Identifier: GPL-3.0-or-later - -m4_include(lib/common.sh) - -source /usr/share/makepkg/util/config.sh -source /usr/share/makepkg/util/message.sh - -set -e - - -usage() { - cat <<- _EOF_ - Usage: ${BASH_SOURCE[0]##*/} [COMMAND] [OPTIONS] - - Manage Git packaging repositories and helps with their configuration - according to distro specs. - - Git author information and the used signing key is set up from - makepkg.conf read from any valid location like /etc or XDG_CONFIG_HOME. - The configure command can be used to synchronize the distro specs and - makepkg.conf settings for previously cloned repositories. - - The unprivileged option can be used for cloning packaging repositories - without SSH access using read-only HTTPS. - - COMMANDS - clone Clone a package repository - configure Configure a clone according to distro specs - - OPTIONS - -h, --help Show this help text -_EOF_ -} - -usage_clone() { - cat <<- _EOF_ - Usage: ${BASH_SOURCE[0]##*/} clone [OPTIONS] [PKGNAME...] - - Clone Git packaging repositories from the canonical namespace. - - The configure command is subsequently invoked to synchronize the distro - specs and makepkg.conf settings. The unprivileged option can be used - for cloning packaging repositories without SSH access using read-only - HTTPS. - - OPTIONS - -m, --maintainer=NAME Clone all packages of the named maintainer - -u, --unprivileged Clone package with read-only access and without - packager info as Git author. - -h, --help Show this help text -_EOF_ -} - -usage_configure() { - cat <<- _EOF_ - Usage: ${BASH_SOURCE[0]##*/} configure [OPTIONS] [PATH...] - - Configure Git packaging repositories according to distro specs and - makepkg.conf settings. - - Git author information and the used signing key is set up from - makepkg.conf read from any valid location like /etc or XDG_CONFIG_HOME. - The unprivileged option can be used for cloning packaging repositories - without SSH access using read-only HTTPS. - - OPTIONS - -u, --unprivileged Configure read-only repo without packager info as Git author. - -h, --help Show this help text -_EOF_ -} - -if (( $# < 1 )); then - usage - exit 1 -fi - -# commands -CLONE=0 -CONFIGURE=0 - -# options -GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_SSH} -UNPRIVILEGED=0 -MAINTAINER= -PACKAGER_NAME= -PACKAGER_EMAIL= - -# command checking -while (( $# )); do - case $1 in - -h|--help) - usage - exit 0 - ;; - clone) - CLONE=1 - CONFIGURE=1 - shift - break - ;; - configure) - CONFIGURE=1 - shift - break - ;; - *) - die "invalid argument: %s" "$1" - ;; - esac -done - -if (( CLONE )); then - # option checking - if (( $# < 1 )); then - usage_clone - exit 1 - fi - while (( $# )); do - case $1 in - -h|--help) - usage_clone - exit 0 - ;; - -u|--unprivileged) - GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_HTTPS} - UNPRIVILEGED=1 - shift - ;; - -m|--maintainer) - (( $# <= 1 )) && die "missing argument for %s" "$1" - MAINTAINER="$2" - shift 2 - ;; - --maintainer=*) - MAINTAINER="${1#*=}" - shift - ;; - --) - shift - break - ;; - -*) - die "invalid argument: %s" "$1" - ;; - *) - break - ;; - esac - done -elif (( CONFIGURE )); then - # option checking - if (( $# < 1 )); then - usage_configure - exit 1 - fi - while (( $# )); do - case $1 in - -h|--help) - usage_configure - exit 0 - ;; - -u|--unprivileged) - GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_HTTPS} - UNPRIVILEGED=1 - shift - ;; - --) - shift - break - ;; - -*) - die "invalid argument: %s" "$1" - ;; - *) - break - ;; - esac - done -fi - -pkgbases=("$@") - -# Load makepkg.conf variables to be available -load_makepkg_config - -# Check official packaging identity before setting Git author -if (( ! UNPRIVILEGED )); then - if [[ $PACKAGER == *"Unknown Packager"* ]]; then - die "Packager must be set in makepkg.conf" - fi - packager_pattern="(.+) <(.+@.+)>" - if [[ ! $PACKAGER =~ $packager_pattern ]]; then - die "Invalid Packager format '${PACKAGER}' in makepkg.conf" - fi - - PACKAGER_NAME=$(echo "${PACKAGER}"|sed -E "s/${packager_pattern}/\1/") - PACKAGER_EMAIL=$(echo "${PACKAGER}"|sed -E "s/${packager_pattern}/\2/") - - if [[ ! $PACKAGER_EMAIL =~ .+@archlinux.org ]]; then - die "Packager email '${PACKAGER_EMAIL}' is not an @archlinux.org address" - fi -fi - -# Query packages of a maintainer -if [[ -n ${MAINTAINER} ]]; then - stat_busy "Query packages for ${MAINTAINER}" - max_pages=$(curl --silent --location --fail --retry 3 --retry-delay 3 "https://archlinux.org/packages/search/json/?sort=name&maintainer=${MAINTAINER}" | jq -r '.num_pages') - mapfile -t pkgbases < <(for page in $(seq "${max_pages}"); do - curl --silent --location --fail --retry 3 --retry-delay 3 "https://archlinux.org/packages/search/json/?sort=name&maintainer=${MAINTAINER}&page=${page}" | jq -r '.results[].pkgbase' - stat_progress - done | sort --unique) - stat_done -fi - -for pkgbase in "${pkgbases[@]}"; do - if (( CLONE )); then - if [[ ! -d ${pkgbase} ]]; then - msg "Cloning ${pkgbase} ..." - remote_url="${GIT_REPO_BASE_URL}/${pkgbase}.git" - git clone --origin origin "${remote_url}" - else - warning "Skip cloning ${pkgbase}: Directory exists" - fi - fi - - if (( CONFIGURE )); then - msg "Configuring $(basename "${pkgbase}") ..." - path=${pkgbase} - if [[ ! -d "${path}/.git" ]]; then - error "Not a Git repository: ${path}" - continue - fi - - giturl=$(git -C "${path}" remote get-url origin) - if [[ ${giturl} != *${GIT_PACKAGING_NAMESPACE}* ]]; then - error "Not a packaging repository: ${path}" - continue - fi - - pkgbase=$(basename "${giturl}") - pkgbase=${pkgbase%.git} - remote_url="${GIT_REPO_BASE_URL}/${pkgbase}.git" - - git -C "${path}" remote set-url origin "${remote_url}" - git -C "${path}" config devtools.version "${GIT_REPO_SPEC_VERSION}" - git -C "${path}" config commit.gpgsign true - git -C "${path}" config pull.rebase true - git -C "${path}" config branch.main.rebase true - - if (( ! UNPRIVILEGED )); then - git -C "${path}" config user.name "${PACKAGER_NAME}" - git -C "${path}" config user.email "${PACKAGER_EMAIL}" - if [[ -n $GPGKEY ]]; then - git -C "${path}" config user.signingKey "${GPGKEY}" - fi - fi - fi -done diff --git a/src/pkgrepo.in b/src/pkgrepo.in new file mode 100644 index 0000000..2804cba --- /dev/null +++ b/src/pkgrepo.in @@ -0,0 +1,260 @@ +#!/bin/bash +# +# SPDX-License-Identifier: GPL-3.0-or-later + +m4_include(lib/common.sh) + +source /usr/share/makepkg/util/config.sh +source /usr/share/makepkg/util/message.sh + +set -e + + +usage() { + cat <<- _EOF_ + Usage: ${BASH_SOURCE[0]##*/} [COMMAND] [OPTIONS] + + Manage Git packaging repositories and helps with their configuration + according to distro specs. + + Git author information and the used signing key is set up from + makepkg.conf read from any valid location like /etc or XDG_CONFIG_HOME. + The configure command can be used to synchronize the distro specs and + makepkg.conf settings for previously cloned repositories. + + The unprivileged option can be used for cloning packaging repositories + without SSH access using read-only HTTPS. + + COMMANDS + clone Clone a package repository + configure Configure a clone according to distro specs + + OPTIONS + -h, --help Show this help text +_EOF_ +} + +usage_clone() { + cat <<- _EOF_ + Usage: ${BASH_SOURCE[0]##*/} clone [OPTIONS] [PKGNAME...] + + Clone Git packaging repositories from the canonical namespace. + + The configure command is subsequently invoked to synchronize the distro + specs and makepkg.conf settings. The unprivileged option can be used + for cloning packaging repositories without SSH access using read-only + HTTPS. + + OPTIONS + -m, --maintainer=NAME Clone all packages of the named maintainer + -u, --unprivileged Clone package with read-only access and without + packager info as Git author. + -h, --help Show this help text +_EOF_ +} + +usage_configure() { + cat <<- _EOF_ + Usage: ${BASH_SOURCE[0]##*/} configure [OPTIONS] [PATH...] + + Configure Git packaging repositories according to distro specs and + makepkg.conf settings. + + Git author information and the used signing key is set up from + makepkg.conf read from any valid location like /etc or XDG_CONFIG_HOME. + The unprivileged option can be used for cloning packaging repositories + without SSH access using read-only HTTPS. + + OPTIONS + -u, --unprivileged Configure read-only repo without packager info as Git author. + -h, --help Show this help text +_EOF_ +} + +if (( $# < 1 )); then + usage + exit 1 +fi + +# commands +CLONE=0 +CONFIGURE=0 + +# options +GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_SSH} +UNPRIVILEGED=0 +MAINTAINER= +PACKAGER_NAME= +PACKAGER_EMAIL= + +# command checking +while (( $# )); do + case $1 in + -h|--help) + usage + exit 0 + ;; + clone) + CLONE=1 + CONFIGURE=1 + shift + break + ;; + configure) + CONFIGURE=1 + shift + break + ;; + *) + die "invalid argument: %s" "$1" + ;; + esac +done + +if (( CLONE )); then + # option checking + if (( $# < 1 )); then + usage_clone + exit 1 + fi + while (( $# )); do + case $1 in + -h|--help) + usage_clone + exit 0 + ;; + -u|--unprivileged) + GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_HTTPS} + UNPRIVILEGED=1 + shift + ;; + -m|--maintainer) + (( $# <= 1 )) && die "missing argument for %s" "$1" + MAINTAINER="$2" + shift 2 + ;; + --maintainer=*) + MAINTAINER="${1#*=}" + shift + ;; + --) + shift + break + ;; + -*) + die "invalid argument: %s" "$1" + ;; + *) + break + ;; + esac + done +elif (( CONFIGURE )); then + # option checking + if (( $# < 1 )); then + usage_configure + exit 1 + fi + while (( $# )); do + case $1 in + -h|--help) + usage_configure + exit 0 + ;; + -u|--unprivileged) + GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_HTTPS} + UNPRIVILEGED=1 + shift + ;; + --) + shift + break + ;; + -*) + die "invalid argument: %s" "$1" + ;; + *) + break + ;; + esac + done +fi + +pkgbases=("$@") + +# Load makepkg.conf variables to be available +load_makepkg_config + +# Check official packaging identity before setting Git author +if (( ! UNPRIVILEGED )); then + if [[ $PACKAGER == *"Unknown Packager"* ]]; then + die "Packager must be set in makepkg.conf" + fi + packager_pattern="(.+) <(.+@.+)>" + if [[ ! $PACKAGER =~ $packager_pattern ]]; then + die "Invalid Packager format '${PACKAGER}' in makepkg.conf" + fi + + PACKAGER_NAME=$(echo "${PACKAGER}"|sed -E "s/${packager_pattern}/\1/") + PACKAGER_EMAIL=$(echo "${PACKAGER}"|sed -E "s/${packager_pattern}/\2/") + + if [[ ! $PACKAGER_EMAIL =~ .+@archlinux.org ]]; then + die "Packager email '${PACKAGER_EMAIL}' is not an @archlinux.org address" + fi +fi + +# Query packages of a maintainer +if [[ -n ${MAINTAINER} ]]; then + stat_busy "Query packages for ${MAINTAINER}" + max_pages=$(curl --silent --location --fail --retry 3 --retry-delay 3 "https://archlinux.org/packages/search/json/?sort=name&maintainer=${MAINTAINER}" | jq -r '.num_pages') + mapfile -t pkgbases < <(for page in $(seq "${max_pages}"); do + curl --silent --location --fail --retry 3 --retry-delay 3 "https://archlinux.org/packages/search/json/?sort=name&maintainer=${MAINTAINER}&page=${page}" | jq -r '.results[].pkgbase' + stat_progress + done | sort --unique) + stat_done +fi + +for pkgbase in "${pkgbases[@]}"; do + if (( CLONE )); then + if [[ ! -d ${pkgbase} ]]; then + msg "Cloning ${pkgbase} ..." + remote_url="${GIT_REPO_BASE_URL}/${pkgbase}.git" + git clone --origin origin "${remote_url}" + else + warning "Skip cloning ${pkgbase}: Directory exists" + fi + fi + + if (( CONFIGURE )); then + msg "Configuring $(basename "${pkgbase}") ..." + path=${pkgbase} + if [[ ! -d "${path}/.git" ]]; then + error "Not a Git repository: ${path}" + continue + fi + + giturl=$(git -C "${path}" remote get-url origin) + if [[ ${giturl} != *${GIT_PACKAGING_NAMESPACE}* ]]; then + error "Not a packaging repository: ${path}" + continue + fi + + pkgbase=$(basename "${giturl}") + pkgbase=${pkgbase%.git} + remote_url="${GIT_REPO_BASE_URL}/${pkgbase}.git" + + git -C "${path}" remote set-url origin "${remote_url}" + git -C "${path}" config devtools.version "${GIT_REPO_SPEC_VERSION}" + git -C "${path}" config commit.gpgsign true + git -C "${path}" config pull.rebase true + git -C "${path}" config branch.main.rebase true + + if (( ! UNPRIVILEGED )); then + git -C "${path}" config user.name "${PACKAGER_NAME}" + git -C "${path}" config user.email "${PACKAGER_EMAIL}" + if [[ -n $GPGKEY ]]; then + git -C "${path}" config user.signingKey "${GPGKEY}" + fi + fi + fi +done -- cgit v1.2.3-70-g09d2 From f961e2e94803dd46c4fa5941eb15a7d4612bd0f0 Mon Sep 17 00:00:00 2001 From: Levente Polyak Date: Thu, 23 Mar 2023 23:37:58 +0100 Subject: completion: implemented structured declarative bash completions This will make it tremendously easier to add arguments, subcommands and special positional option handling. Instead of the need to code the nested structure via bash and switch cases, we can simply declare functions and arrays with the matching names according to the subcommands or argument labels. Signed-off-by: Levente Polyak --- contrib/completion/bash/devtools.in | 506 ++++++++++++++++++++++++++++++------ 1 file changed, 424 insertions(+), 82 deletions(-) (limited to 'contrib/completion/bash') diff --git a/contrib/completion/bash/devtools.in b/contrib/completion/bash/devtools.in index a353b99..e3ae023 100644 --- a/contrib/completion/bash/devtools.in +++ b/contrib/completion/bash/devtools.in @@ -2,89 +2,431 @@ # # SPDX-License-Identifier: GPL-3.0-or-later -_devtools_compgen() { - local i r - COMPREPLY=($(compgen -W '$*' -- "$cur")) - for ((i=1; i < ${#COMP_WORDS[@]}-1; i++)); do - for r in "${!COMPREPLY[@]}"; do - if [[ ${COMP_WORDS[i]} = "${COMPREPLY[r]}" ]]; then - unset 'COMPREPLY[r]'; break - fi - done - done -} - -_pkgrepo_pkg() { - _devtools_compgen "$( - command pacman "-$1" - )" -} - -_pkgrepo() { - local cur prev - COMPREPLY=() - cur=$(_get_cword) - prev=${COMP_WORDS[COMP_CWORD-1]} - - _pkgrepo_pkg Slq - true -} && -complete -F _pkgrepo pkgrepo - -_makechrootpkg() { - local cur - COMPREPLY=() - _get_comp_words_by_ref cur - - case $cur in - -*) - COMPREPLY=( $( compgen -W '-I -c -h -l -r -u' -- "$cur" ) ) - ;; - *) - _filedir - return 0 - ;; - esac - - true -} && +_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@} +# shellcheck source=src/lib/valid-tags.sh +source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-tags.sh +# shellcheck source=src/lib/valid-repos.sh +source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-repos.sh + +_binary_arch=${_arch[*]:0:-1} +_colors=(never always auto) + + +_makechrootpkg_args=( + -h + -c + -d + -D + -u + -r + -I + -l + -n + -T + -U +) +_makechrootpkg_args_d_opts() { _filedir -d; } +_makechrootpkg_args_D_opts() { _filedir -d; } +_makechrootpkg_args_r_opts() { _filedir -d; } +_makechrootpkg_args_I_opts() { _filedir '*.pkg.tar.*'; } +_makechrootpkg_args_l_opts() { _filedir -d; } +_makechrootpkg_args_U_opts() { :; } +_makechrootpkg() { __devtools_complete _makechrootpkg; } complete -F _makechrootpkg makechrootpkg -_mkarchroot() { - local cur - COMPREPLY=() - _get_comp_words_by_ref cur - - case $cur in - -*) - COMPREPLY=( $( compgen -W '-C -M -c -h' -- "$cur" ) ) - ;; - *) - _filedir - return 0 - ;; - esac - - true -} && + +_makerepropkg_args=( + -h + -d + -c + -M +) +_makerepropkg_args_c_opts() { _filedir -d; } +_makerepropkg_args_M_opts() { _filedir '*.conf'; } +_makerepropkg_opts() { _filedir '*.pkg.tar.*'; } +_makerepropkg() { __devtools_complete _makerepropkg; } +complete -F _makerepropkg makerepropkg + + +_mkarchroot_args=( + -U + -C + -M + -c + -h +) +_mkarchroot_args_U_opts() { _filedir '*.pkg.tar.*'; } +_mkarchroot_args_C_opts() { _filedir '*.conf'; } +_mkarchroot_args_M_opts() { _filedir '*.conf'; } +_mkarchroot_args_c_opts() { _filedir -d; } +_mkarchroot_opts() { + local args + args=$(__pkgctl_word_count_after_subcommand) + if (( args == 0 )); then + _filedir -d + elif (( args >= 1 )); then + _devtools_completions_all_packages + fi +} +_mkarchroot() { __devtools_complete _mkarchroot; } complete -F _mkarchroot mkarchroot -_arch-nspawn() { - local cur - COMPREPLY=() - _get_comp_words_by_ref cur - - case $cur in - -*) - COMPREPLY=( $( compgen -W '-C -M -c -h' -- "$cur" ) ) - ;; - *) - _filedir - return 0 - ;; - esac - - true -} && -complete -F _arch-nspawn arch-nspawn -# ex:et ts=2 sw=2 ft=sh + +_arch_nspawn_args=( + -C + -M + -c + -f + -s + -h +) +_arch_nspawn_args_C_opts() { _filedir '*.conf'; } +_arch_nspawn_args_M_opts() { _filedir '*.conf'; } +_arch_nspawn_args_c_opts() { _filedir -d; } +_arch_nspawn_args_f_opts() { _filedir; } +_arch_nspawn_opts() { + local args + args=$(__pkgctl_word_count_after_subcommand) + if (( args == 0 )); then + _filedir -d + fi +} +_arch_nspawn() { __devtools_complete _arch_nspawn; } +complete -F _arch_nspawn arch-nspawn + + +_sogrep_args=( + -v --verbose + -r --refresh + -h --help +) +_sogrep_opts() { + local args + args=$(__pkgctl_word_count_after_subcommand) + if (( args == 0 )); then + _devtools_completions_repo all + fi +} +_sogrep() { __devtools_complete _sogrep; } +complete -F _sogrep sogrep + + +_offload_build_args=( + -r --repo + -a --arch + -s --server + -h --help +) +_offload_build_args__repo_opts() { _devtools_completions_build_repo; } +_offload_build_args_r_opts() { _offload_build_args__repo_opts; } +_offload_build_args__arch_opts() { _devtools_completions_arch; } +_offload_build_args_a_opts() { _offload_build_args__arch_opts; } +_offload_build_args__server_opts() { :; } +_offload_build_args_s_opts() { _offload_build_args__server_opts; } +_offload_build() { __devtools_complete _offload_build; } +complete -F _offload_build offload-build + + +_pkgctl_cmds=( + auth + build + db + diff + release + repo + version +) +_pkgctl_args=( + -V --version + -h --help +) + + +_pkgctl_auth_cmds=( + login + status +) + + +_pkgctl_auth_login_args=( + -g --gen-access-token + -h --help +) + + +_pkgctl_auth_status_args=( + -t --show-token + -h --help +) + + +_pkgctl_build_args=( + --arch + --repo + + -s --staging + -t --testing + -o --offload + -c --clean + + --pkgver + --pkgrel + --rebuild + -e --edit + + -r --release + -m --message + -u --db-update + + -h --help +) +_pkgctl_build_args__arch_opts() { _devtools_completions_arch; } +_pkgctl_build_args__repo_opts() { _devtools_completions_repo; } +_pkgctl_build_args__pkgver_opts() { :; } +_pkgctl_build_args__pkgrel_opts() { :; } +_pkgctl_build_args__message_opts() { :; } +_pkgctl_build_args_m_opts() { _pkgctl_build_args__message_opts; } +_pkgctl_build_opts() { _filedir -d; } + + +_pkgctl_db_cmds=( + move + remove + update +) + + +_pkgctl_db_move_args=( + -h --help +) +_pkgctl_db_move_opts() { + local subcommand args + subcommand=(db move) + args=$(__pkgctl_word_count_after_subcommand "${subcommand[@]}") + + if (( args == 0 )); then + _devtools_completions_repo + elif (( args == 1 )); then + _devtools_completions_repo + elif (( args >= 2 )); then + _devtools_completions_all_packages + fi +} + + +_pkgctl_db_remove_args=( + -a --arch + -h --help +) +_pkgctl_db_remove_opts() { + local subcommand args + subcommand=(db remove) + args=$(__pkgctl_word_count_after_subcommand "${subcommand[@]}") + + if (( args == 0 )); then + _devtools_completions_repo + elif (( args >= 1 )); then + _devtools_completions_all_packages + fi +} + + +_pkgctl_db_update_args=( + -h --help +) + + +_pkgctl_release_args=( + -m --message + -r --repo + -s --staging + -t --testing + -u --db-update + -h --help +) +_pkgctl_release_args__message_opts() { :; } +_pkgctl_release_args_m_opts() { _pkgctl_release_args__message_opts; } +_pkgctl_release_args__repo_opts() { _devtools_completions_repo; } +_pkgctl_release_args_r_opts() { _pkgctl_release_args__repo_opts; } +_pkgctl_release_opts() { _filedir -d; } + + +_pkgctl_repo_cmds=( + clone + configure + create + web +) + + +_pkgctl_repo_clone_args=( + -m --maintainer + -u --unprivileged + --universe + -h --help +) +_pkgctl_repo_clone_args__maintainer_opts() { :; } +_pkgctl_repo_clone_args_m_opts() { _pkgctl_repo_clone_args__maintainer_opts; } +_pkgctl_repo_clone_opts() { _devtools_completions_all_packages; } + + +_pkgctl_repo_configure_args=( + -h --help +) +_pkgctl_repo_configure_opts() { _filedir -d; } + + +_pkgctl_repo_create_args=( + -c --clone + -h --help +) + + +_pkgctl_repo_web_args=( + -h --help +) +_pkgctl_repo_web_opts() { _filedir -d; } + + +_pkgctl_diff_args=( + -l --list + -d --diffoscope + -p --pkginfo + -b --buildinfo + -m --makepkg-config + -u -U --unified + -y --side-by-side + --color + -W --width + -P --pool + -v --verbose + -h --help +) +_pkgctl_diff_args__makepkg_config_opts() { _filedir '*.conf'; } +_pkgctl_diff_args_m_opts() { _pkgctl_diff_args__makepkg_config_opts; } +_pkgctl_diff_args__width_opts() { :; } +_pkgctl_diff_args_W_opts() { _pkgctl_diff_args__width_opts; } +_pkgctl_diff_args__color_opts() { _devtools_completions_color; } +_pkgctl_diff_args__pool_opts() { _filedir -d; } +_pkgctl_diff_args_P_opts() { _pkgctl_diff_args__pool_opts; } +_pkgctl_diff_opts() { _devtools_completions_all_packages; } + + +_pkgctl_version_args=( + -h --help +) + + +_devtools_completions_color() { + mapfile -t COMPREPLY < <(compgen -W "${_colors[*]}" -- "$cur") +} +_devtools_completions_arch() { + mapfile -t COMPREPLY < <(compgen -W "${_arch[*]}" -- "$cur") +} +_devtools_completions_repo() { + local optional=${1:-} + mapfile -t COMPREPLY < <(compgen -W "${optional} ${_repos[*]}" -- "$cur") +} +_devtools_completions_build_repo() { + mapfile -t COMPREPLY < <(compgen -W "${_build_repos[*]}" -- "$cur") +} +_devtools_completions_all_packages() { + mapfile -t COMPREPLY < <(compgen -W "$(pacman -Sql)" -- "$cur") +} + +__devtools_complete() { + local service=$1 + local cur prev + + # Don't break words at : and = + COMP_WORDBREAKS=${COMP_WORDBREAKS//[:=]} + + cur=$(_get_cword) + prev=${COMP_WORDS[COMP_CWORD-1]} + + __pkgctl_handle_subcommands "${service}" + return 0 +} + +__pkgctl_has_func() { + declare -f -- "${1}" &>/dev/null +} + +__pkgctl_has_array() { + declare -p -- "${1}" &>/dev/null +} + +__pkgctl_is_subcommand() { + __pkgctl_has_array "${1}"_args || \ + __pkgctl_has_array "${1}"_cmds +} + +__pkgctl_words_after_subcommand() { + local subcommand=("$@") + local subcommand_idx=0 + local word prev_word + for ((i = 1; i < ${#COMP_WORDS[@]}; ++i)); do + word=${COMP_WORDS[i]} + prev_word=${COMP_WORDS[i-1]} + # skip options and the current typing + if [[ ${word} == -* ]] || [[ ${word} == "${cur}" ]]; then + continue + fi + # skip until we resolved the passed subcommand + if (( subcommand_idx < ${#subcommand[@]} )); then + if [[ $word == "${subcommand[$subcommand_idx]}" ]]; then + subcommand_idx=$(( subcommand_idx + 1 )) + fi + continue + fi + # skip previous options as they belong to the argument + if [[ ${prev_word} == -* ]] && __pkgctl_has_func "${service_name}_args${prev_word//-/_}_opts"; then + continue + fi + printf "%s\n" "${word}" + done +} +__pkgctl_word_count_after_subcommand() { + local subcommand=("$@") + mapfile -t words < <(__pkgctl_words_after_subcommand "${subcommand[@]}") + echo "${#words[@]}" +} + +__pkgctl_handle_subcommands() { + local service_name=${1} + local index=${2:-0} + local word ref + + # recurse into nested subcommands + for ((i = index + 1; i < ${#COMP_WORDS[@]}; ++i)); do + word=${COMP_WORDS[i]} + if [[ ${word} == -* ]] || [[ ${word} == "${cur}" ]]; then + continue + fi + if __pkgctl_is_subcommand "${service_name}_${word}"; then + __pkgctl_handle_subcommands "${service_name}_${word}" "${i}" + return + fi + done + + # dynamic argument options + if [[ $prev == -* ]] && word=${prev//-/_} && __pkgctl_has_func "${service_name}_args${word}_opts"; then + "${service_name}_args${word}_opts" + # dynamic subcommand options + elif [[ $cur != -* ]] && __pkgctl_has_func "${service_name}_opts"; then + "${service_name}_opts" + # subcommand argument array + elif ( ! __pkgctl_has_array "${service_name}"_cmds || [[ $cur == -* ]] ) && __pkgctl_has_array "${service_name}_args"; then + declare -n ref="${service_name}_args" + mapfile -t COMPREPLY < <(compgen -W "${ref[*]}" -- "$cur") + # subcommand array + elif __pkgctl_has_array "${service_name}"_cmds; then + declare -n ref="${service_name}_cmds" + mapfile -t COMPREPLY < <(compgen -W "${ref[*]}" -- "$cur") + fi +} + + +_pkgctl() { __devtools_complete _pkgctl; } +complete -F _pkgctl pkgctl +# ex:noet ts=4 sw=4 ft=sh -- cgit v1.2.3-70-g09d2 From ed966351410b39bfcec749df59dbc434a5dade1e Mon Sep 17 00:00:00 2001 From: Christian Heusel Date: Sat, 15 Apr 2023 19:44:22 +0200 Subject: pkgctl repo: introduce the switch subcommand Signed-off-by: Christian Heusel Co-Authored-By: Levente Polyak --- contrib/completion/bash/devtools.in | 19 ++++++ contrib/completion/zsh/_devtools.in | 8 +++ doc/man/pkgctl-repo-switch.1.asciidoc | 36 ++++++++++ doc/man/pkgctl-repo.1.asciidoc | 4 ++ src/lib/repo.sh | 10 +++ src/lib/repo/switch.sh | 119 ++++++++++++++++++++++++++++++++++ 6 files changed, 196 insertions(+) create mode 100644 doc/man/pkgctl-repo-switch.1.asciidoc create mode 100644 src/lib/repo/switch.sh (limited to 'contrib/completion/bash') diff --git a/contrib/completion/bash/devtools.in b/contrib/completion/bash/devtools.in index e3ae023..e79b862 100644 --- a/contrib/completion/bash/devtools.in +++ b/contrib/completion/bash/devtools.in @@ -255,6 +255,7 @@ _pkgctl_repo_cmds=( clone configure create + switch web ) @@ -282,6 +283,24 @@ _pkgctl_repo_create_args=( ) +_pkgctl_repo_switch_args=( + --discard-changes + -f --force + -h --help +) +_pkgctl_repo_switch_opts() { + local subcommand args + subcommand=(repo switch) + args=$(__pkgctl_word_count_after_subcommand "${subcommand[@]}") + + if (( args == 0 )); then + : + elif (( args >= 1 )); then + _filedir -d; + fi +} + + _pkgctl_repo_web_args=( -h --help ) diff --git a/contrib/completion/zsh/_devtools.in b/contrib/completion/zsh/_devtools.in index 20c37ce..5760458 100644 --- a/contrib/completion/zsh/_devtools.in +++ b/contrib/completion/zsh/_devtools.in @@ -94,9 +94,17 @@ _pkgctl_repo_cmds=( "clone[Clone a package repository]" "configure[Configure a clone according to distro specs]" "create[Create a new GitLab package repository]" + "switch[Switch a package repository to a specified version]" "web[Open the packaging repository's website]" ) +_pkgctl_repo_switch_args=( + '(-f --force --discard-changes)'{-f,--force,--discard-changes}'[Discard changes if index or working tree is dirty]' + '(-h --help)'{-h,--help}'[Display usage]' + '1:version' + '*:git_dir:_files -/' +) + _pkgctl_repo_clone_args=( '(-m --maintainer=)'{-m,--maintainer=}'[Clone all packages of the named maintainer]:maintainer:' '--universe[Clone all existing packages, useful for cache warming]' diff --git a/doc/man/pkgctl-repo-switch.1.asciidoc b/doc/man/pkgctl-repo-switch.1.asciidoc new file mode 100644 index 0000000..ac12019 --- /dev/null +++ b/doc/man/pkgctl-repo-switch.1.asciidoc @@ -0,0 +1,36 @@ +pkgctl-repo-switch(1) +===================== + +Name +---- +pkgctl-repo-switch - Switch a package repository to a specified version + +Synopsis +-------- +pkgctl repo switch [OPTIONS] [VERSION] [PKGBASE]... + +Description +----------- + +Switch a package source repository to a specified version, tag or branch. +The working tree and the index are updated to match the specified ref. + +If a version identifier is specified in the pacman version format, that +identifier is automatically translated to the Git tag name accordingly. + +The current working directory is used if no PKGBASE is specified. + +Options +------- + +*--discard-changes*:: + Proceed even if the index or the working tree differs from HEAD. Both the + index and working tree are restored to match the switching target. + +*-f, --force*:: + An alias for '--discard-changes'. + +*-h, --help*:: + Show a help text + +include::include/footer.asciidoc[] diff --git a/doc/man/pkgctl-repo.1.asciidoc b/doc/man/pkgctl-repo.1.asciidoc index 630afd8..713b474 100644 --- a/doc/man/pkgctl-repo.1.asciidoc +++ b/doc/man/pkgctl-repo.1.asciidoc @@ -41,6 +41,9 @@ pkgctl repo configure:: pkgctl repo create:: Create a new GitLab package repository +pkgctl repo switch:: + Switch a package repository to a specified version + pkgctl repo web:: Open the packaging repository's website @@ -50,6 +53,7 @@ See Also linkman:pkgctl-repo-clone[1] linkman:pkgctl-repo-configure[1] linkman:pkgctl-repo-create[1] +linkman:pkgctl-repo-switch[1] linkman:pkgctl-repo-web[1] include::include/footer.asciidoc[] diff --git a/src/lib/repo.sh b/src/lib/repo.sh index 6b3817a..9f545e9 100644 --- a/src/lib/repo.sh +++ b/src/lib/repo.sh @@ -30,6 +30,7 @@ pkgctl_repo_usage() { clone Clone a package repository configure Configure a clone according to distro specs create Create a new GitLab package repository + switch Switch a package repository to a specified version web Open the packaging repository's website OPTIONS @@ -40,6 +41,7 @@ pkgctl_repo_usage() { $ ${COMMAND} clone --maintainer mynickname $ ${COMMAND} configure * $ ${COMMAND} create libfoo + $ ${COMMAND} switch 2:1.19.5-1 libfoo $ ${COMMAND} web linux _EOF_ } @@ -81,6 +83,14 @@ pkgctl_repo() { pkgctl_repo_create "$@" exit 0 ;; + switch) + _DEVTOOLS_COMMAND+=" $1" + shift + # shellcheck source=src/lib/repo/switch.sh + source "${_DEVTOOLS_LIBRARY_DIR}"/lib/repo/switch.sh + pkgctl_repo_switch "$@" + exit 0 + ;; web) _DEVTOOLS_COMMAND+=" $1" shift diff --git a/src/lib/repo/switch.sh b/src/lib/repo/switch.sh new file mode 100644 index 0000000..f411ac2 --- /dev/null +++ b/src/lib/repo/switch.sh @@ -0,0 +1,119 @@ +#!/bin/bash +# +# SPDX-License-Identifier: GPL-3.0-or-later + +[[ -z ${DEVTOOLS_INCLUDE_REPO_SWITCH_SH:-} ]] || return 0 +DEVTOOLS_INCLUDE_REPO_SWITCH_SH=1 + +_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@} +# shellcheck source=src/lib/common.sh +source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh + +source /usr/share/makepkg/util/message.sh + +set -e + + +pkgctl_repo_switch_usage() { + local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}} + cat <<- _EOF_ + Usage: ${COMMAND} [OPTIONS] [VERSION] [PKGBASE]... + + Switch a package source repository to a specified version, tag or + branch. The working tree and the index are updated to match the + specified ref. + + If a version identifier is specified in the pacman version format, that + identifier is automatically translated to the Git tag name accordingly. + + The current working directory is used if no PKGBASE is specified. + + OPTIONS + --discard-changes Discard changes if index or working tree is dirty + -f, --force An alias for --discard-changes + -h, --help Show this help text + + EXAMPLES + $ ${COMMAND} 1.14.6-1 gopass gopass-jsonapi + $ ${COMMAND} --force 2:1.19.5-1 + $ ${COMMAND} main +_EOF_ +} + +pkgctl_repo_switch() { + if (( $# < 1 )); then + pkgctl_repo_switch_usage + exit 0 + fi + + # options + local VERSION + local GIT_REF + local GIT_CHECKOUT_OPTIONS=() + local paths path realpath pkgbase + + while (( $# )); do + case $1 in + -h|--help) + pkgctl_repo_switch_usage + exit 0 + ;; + -f|--force|--discard-changes) + GIT_CHECKOUT_OPTIONS+=("--force") + shift + ;; + --) + shift + break + ;; + -*) + # - is special to switch back to previous version + if [[ $1 != - ]]; then + die "invalid argument: %s" "$1" + fi + ;;& + *) + if [[ -n ${VERSION} ]]; then + break + fi + VERSION=$1 + shift + ;; + esac + done + + if [[ -z ${VERSION} ]]; then + error "missing positional argument 'VERSION'" + pkgctl_repo_switch_usage + exit 1 + fi + + GIT_REF="$(get_tag_from_pkgver "${VERSION}")" + paths=("$@") + + # check if invoked without any path from within a packaging repo + if (( ${#paths[@]} == 0 )); then + if [[ -f PKGBUILD ]]; then + paths=(".") + else + die "Not a package repository: $(realpath -- .)" + fi + fi + + for path in "${paths[@]}"; do + if ! realpath=$(realpath -e -- "${path}"); then + die "No such directory: ${path}" + fi + pkgbase=$(basename "${realpath}") + + if [[ ! -d "${path}/.git" ]]; then + error "Not a Git repository: ${path}" + continue + fi + + if ! git -C "${path}" checkout "${GIT_CHECKOUT_OPTIONS[@]}" "${GIT_REF}"; then + die "Failed to switch ${pkgbase} to version ${VERSION}" + fi + msg "Successfully switched ${pkgbase} to version ${VERSION}" + done +} -- cgit v1.2.3-70-g09d2 From 8e3b6bcc5b82b270f8d310865f14f2b0405eddd7 Mon Sep 17 00:00:00 2001 From: Christian Heusel Date: Fri, 14 Apr 2023 17:14:05 +0200 Subject: pkgctl repo clone: add option to switch working tree Add an option to call the switch command after clone. Switch to a specified version. The working tree and the index are updated to match the version. Signed-off-by: Christian Heusel Signed-off-by: Levente Polyak --- contrib/completion/bash/devtools.in | 2 ++ contrib/completion/zsh/_devtools.in | 1 + doc/man/pkgctl-repo-clone.1.asciidoc | 5 +++++ src/lib/repo/clone.sh | 20 ++++++++++++++++++++ 4 files changed, 28 insertions(+) (limited to 'contrib/completion/bash') diff --git a/contrib/completion/bash/devtools.in b/contrib/completion/bash/devtools.in index e79b862..31269dd 100644 --- a/contrib/completion/bash/devtools.in +++ b/contrib/completion/bash/devtools.in @@ -262,12 +262,14 @@ _pkgctl_repo_cmds=( _pkgctl_repo_clone_args=( -m --maintainer + --switch -u --unprivileged --universe -h --help ) _pkgctl_repo_clone_args__maintainer_opts() { :; } _pkgctl_repo_clone_args_m_opts() { _pkgctl_repo_clone_args__maintainer_opts; } +_pkgctl_repo_clone_args__switch_opts() { :; } _pkgctl_repo_clone_opts() { _devtools_completions_all_packages; } diff --git a/contrib/completion/zsh/_devtools.in b/contrib/completion/zsh/_devtools.in index 5760458..ed52a22 100644 --- a/contrib/completion/zsh/_devtools.in +++ b/contrib/completion/zsh/_devtools.in @@ -107,6 +107,7 @@ _pkgctl_repo_switch_args=( _pkgctl_repo_clone_args=( '(-m --maintainer=)'{-m,--maintainer=}'[Clone all packages of the named maintainer]:maintainer:' + '--switch=[Switch the current working tree to a specified version]' '--universe[Clone all existing packages, useful for cache warming]' '(-h --help)'{-h,--help}'[Display usage]' '*:packages:_devtools_completions_all_packages' diff --git a/doc/man/pkgctl-repo-clone.1.asciidoc b/doc/man/pkgctl-repo-clone.1.asciidoc index a39fb37..8f3aef7 100644 --- a/doc/man/pkgctl-repo-clone.1.asciidoc +++ b/doc/man/pkgctl-repo-clone.1.asciidoc @@ -28,6 +28,10 @@ Options *--universe*:: Clone all existing packages, useful for cache warming +*--switch* 'VERSION':: + Switch to a specified version. The working tree and the index are updated to + match the version. + *-h, --help*:: Show a help text @@ -35,5 +39,6 @@ See Also -------- linkman:pkgctl-repo-configure[1] +linkman:pkgctl-repo-switch[1] include::include/footer.asciidoc[] diff --git a/src/lib/repo/clone.sh b/src/lib/repo/clone.sh index dee4870..340aa69 100644 --- a/src/lib/repo/clone.sh +++ b/src/lib/repo/clone.sh @@ -32,12 +32,14 @@ pkgctl_repo_clone_usage() { OPTIONS -m, --maintainer=NAME Clone all packages of the named maintainer + --switch VERSION Switch the current working tree to a specified version --universe Clone all existing packages, useful for cache warming -h, --help Show this help text EXAMPLES $ ${COMMAND} libfoo linux libbar $ ${COMMAND} --maintainer mynickname + $ ${COMMAND} --switch 1:1.0-2 libfoo _EOF_ } @@ -51,6 +53,7 @@ pkgctl_repo_clone() { local GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_SSH} local CLONE_ALL=0 local MAINTAINER= + local VERSION= local CONFIGURE_OPTIONS=() local pkgbases @@ -77,6 +80,19 @@ pkgctl_repo_clone() { MAINTAINER="${1#*=}" shift ;; + --switch) + (( $# <= 1 )) && die "missing argument for %s" "$1" + # shellcheck source=src/lib/repo/switch.sh + source "${_DEVTOOLS_LIBRARY_DIR}"/lib/repo/switch.sh + VERSION="$2" + shift 2 + ;; + --switch=*) + # shellcheck source=src/lib/repo/switch.sh + source "${_DEVTOOLS_LIBRARY_DIR}"/lib/repo/switch.sh + VERSION="${1#*=}" + shift + ;; --universe) CLONE_ALL=1 shift @@ -137,5 +153,9 @@ pkgctl_repo_clone() { fi pkgctl_repo_configure "${CONFIGURE_OPTIONS[@]}" "${pkgbase}" + + if [[ -n "${VERSION}" ]]; then + pkgctl_repo_switch "${VERSION}" "${pkgbase}" + fi done } -- cgit v1.2.3-70-g09d2 From 830dcde2d8353dbcce1e831adb7c7e8f538210a3 Mon Sep 17 00:00:00 2001 From: Levente Polyak Date: Fri, 5 May 2023 20:21:38 +0200 Subject: pkgctl build: support worker slots for none tty builds Allow overriding the worker slot with a dedicated option. Furthermore detect if the current tty is no pts and fall back to choosing a random worker slot between 1 and number of available processing units. Fixes #137 Signed-off-by: Levente Polyak --- contrib/completion/bash/devtools.in | 3 +++ contrib/completion/zsh/_devtools.in | 1 + doc/man/pkgctl-build.1.asciidoc | 6 ++++++ src/lib/build/build.sh | 23 ++++++++++++++++++----- 4 files changed, 28 insertions(+), 5 deletions(-) (limited to 'contrib/completion/bash') diff --git a/contrib/completion/bash/devtools.in b/contrib/completion/bash/devtools.in index 31269dd..b0a90e5 100644 --- a/contrib/completion/bash/devtools.in +++ b/contrib/completion/bash/devtools.in @@ -168,6 +168,7 @@ _pkgctl_build_args=( -t --testing -o --offload -c --clean + -w --worker --pkgver --pkgrel @@ -182,6 +183,8 @@ _pkgctl_build_args=( ) _pkgctl_build_args__arch_opts() { _devtools_completions_arch; } _pkgctl_build_args__repo_opts() { _devtools_completions_repo; } +_pkgctl_build_args__worker_opts() { :; } +_pkgctl_build_args_w_opts() { _pkgctl_build_args__worker_opts; } _pkgctl_build_args__pkgver_opts() { :; } _pkgctl_build_args__pkgrel_opts() { :; } _pkgctl_build_args__message_opts() { :; } diff --git a/contrib/completion/zsh/_devtools.in b/contrib/completion/zsh/_devtools.in index ed52a22..45ffde3 100644 --- a/contrib/completion/zsh/_devtools.in +++ b/contrib/completion/zsh/_devtools.in @@ -42,6 +42,7 @@ _pkgctl_build_args=( '(-o --offload)'{-o,--offload}'[Build on a remote server and transfer artifacts afterwards]' '(-c --clean)'{-c,--clean}'[Recreate the chroot before building]' '(-I --install)'{-I,--install}'[Install a package into the working copy of the chroot]:target:_files -g "*.pkg.tar.*(.)"' + '(-w --worker)'{-w,--worker}'[Name of the worker slot, useful for concurrent builds (disables auto-detection)]:slot:' '--nocheck[Do not run the check() function in the PKGBUILD]' '--pkgver=[Set pkgver, reset pkgrel and update checksums]:pkgver:' '--pkgrel=[Set pkgrel to a given value]:pkgrel:' diff --git a/doc/man/pkgctl-build.1.asciidoc b/doc/man/pkgctl-build.1.asciidoc index 489926e..f68e7cf 100644 --- a/doc/man/pkgctl-build.1.asciidoc +++ b/doc/man/pkgctl-build.1.asciidoc @@ -38,6 +38,12 @@ Build Options *-I, --install* 'FILE':: Install a package into the working copy of the chroot +*-w, --worker* 'SLOT':: + Name of the worker slot, useful for concurrent builds. By default the slot + is automatically assigned to the current tty pts number. In case the caller + is not a tty, choose a random slot between 1 and number of available + processing units. + *--nocheck*:: Do not run the check() function in the PKGBUILD diff --git a/src/lib/build/build.sh b/src/lib/build/build.sh index 2153200..191fded 100644 --- a/src/lib/build/build.sh +++ b/src/lib/build/build.sh @@ -25,6 +25,7 @@ source /usr/share/makepkg/util/config.sh source /usr/share/makepkg/util/message.sh set -e +set -o pipefail pkgctl_build_usage() { @@ -47,6 +48,7 @@ pkgctl_build_usage() { -o, --offload Build on a remote server and transfer artifacts afterwards -c, --clean Recreate the chroot before building -I, --install FILE Install a package into the working copy of the chroot + -w, --worker SLOT Name of the worker slot, useful for concurrent builds (disables automatic names) --nocheck Do not run the check() function in the PKGBUILD PKGBUILD OPTIONS @@ -123,9 +125,8 @@ pkgctl_build() { local RELEASE_OPTIONS=() local MAKEPKG_OPTIONS=() - local PTS - PTS="$(tty | sed 's|/dev/pts/||')" - local WORKER="${USER}-${PTS}" + local WORKER= + local WORKER_SLOT= # variables local path pkgbase pkgrepo source @@ -224,6 +225,11 @@ pkgctl_build() { DB_UPDATE=1 shift ;; + -w|--worker) + (( $# <= 1 )) && die "missing argument for %s" "$1" + WORKER_SLOT=$2 + shift 2 + ;; --) shift break @@ -258,6 +264,12 @@ pkgctl_build() { fi fi + # assign default worker slot + if [[ -z ${WORKER_SLOT} ]] && ! WORKER_SLOT="$(tty | sed 's|/dev/pts/||')"; then + WORKER_SLOT=$(( RANDOM % $(nproc) + 1 )) + fi + WORKER="${USER}-${WORKER_SLOT}" + # Update pacman cache for auto-detection if [[ -z ${REPO} ]]; then update_pacman_repo_cache @@ -311,8 +323,9 @@ pkgctl_build() { fi # print gathered build modes - msg2 "repo: ${pkgrepo}" - msg2 "arch: ${BUILD_ARCH[*]}" + msg2 " repo: ${pkgrepo}" + msg2 " arch: ${BUILD_ARCH[*]}" + msg2 "worker: ${WORKER}" # increment pkgrel on rebuild if (( REBUILD )); then -- cgit v1.2.3-70-g09d2 From 6ce666a1669235749c17d5c44d8a24dea4a135da Mon Sep 17 00:00:00 2001 From: Levente Polyak Date: Fri, 3 Feb 2023 00:58:59 +0100 Subject: feature(parallel): run up to N jobs in parallel for repo clone/configure Run up to N jobs in parallel. By default the number of jobs is equal to the number of available processing units. For sequential processing this option needs to be passed with 1. Signed-off-by: Levente Polyak --- contrib/completion/bash/devtools.in | 6 ++++++ contrib/completion/zsh/_devtools.in | 2 ++ doc/man/pkgctl-repo-clone.1.asciidoc | 5 +++++ doc/man/pkgctl-repo-configure.1.asciidoc | 5 +++++ src/lib/common.sh | 2 +- src/lib/repo/clone.sh | 31 +++++++++++++++++++++++++++++-- src/lib/repo/configure.sh | 27 +++++++++++++++++++++++---- 7 files changed, 71 insertions(+), 7 deletions(-) (limited to 'contrib/completion/bash') diff --git a/contrib/completion/bash/devtools.in b/contrib/completion/bash/devtools.in index b0a90e5..17f863f 100644 --- a/contrib/completion/bash/devtools.in +++ b/contrib/completion/bash/devtools.in @@ -268,17 +268,23 @@ _pkgctl_repo_clone_args=( --switch -u --unprivileged --universe + -j --jobs -h --help ) _pkgctl_repo_clone_args__maintainer_opts() { :; } _pkgctl_repo_clone_args_m_opts() { _pkgctl_repo_clone_args__maintainer_opts; } _pkgctl_repo_clone_args__switch_opts() { :; } +_pkgctl_repo_clone_args__jobs_opts() { :; } +_pkgctl_repo_clone_args_j_opts() { _pkgctl_repo_clone_args__jobs_opts; } _pkgctl_repo_clone_opts() { _devtools_completions_all_packages; } _pkgctl_repo_configure_args=( + -j --jobs -h --help ) +_pkgctl_repo_configure_args__jobs_opts() { :; } +_pkgctl_repo_configure_args_j_opts() { _pkgctl_repo_clone_args__jobs_opts; } _pkgctl_repo_configure_opts() { _filedir -d; } diff --git a/contrib/completion/zsh/_devtools.in b/contrib/completion/zsh/_devtools.in index 45ffde3..240f781 100644 --- a/contrib/completion/zsh/_devtools.in +++ b/contrib/completion/zsh/_devtools.in @@ -110,11 +110,13 @@ _pkgctl_repo_clone_args=( '(-m --maintainer=)'{-m,--maintainer=}'[Clone all packages of the named maintainer]:maintainer:' '--switch=[Switch the current working tree to a specified version]' '--universe[Clone all existing packages, useful for cache warming]' + '(-j --jobs)'{-j,--jobs}'[Run up to N jobs in parallel (default: number of processing units)]:jobs:' '(-h --help)'{-h,--help}'[Display usage]' '*:packages:_devtools_completions_all_packages' ) _pkgctl_repo_configure_args=( + '(-j --jobs)'{-j,--jobs}'[Run up to N jobs in parallel (default: number of processing units)]:jobs:' '(-h --help)'{-h,--help}'[Display usage]' '*:git_dir:_files -/' ) diff --git a/doc/man/pkgctl-repo-clone.1.asciidoc b/doc/man/pkgctl-repo-clone.1.asciidoc index 487ec35..d6da062 100644 --- a/doc/man/pkgctl-repo-clone.1.asciidoc +++ b/doc/man/pkgctl-repo-clone.1.asciidoc @@ -32,6 +32,11 @@ Options Switch to a specified version. The working tree and the index are updated to match the version. +*-j, --jobs* 'N':: + Run up to N jobs in parallel. By default the number of jobs is equal to the + number of available processing units. For sequential processing this option + needs to be passed with 1. + *-h, --help*:: Show a help text diff --git a/doc/man/pkgctl-repo-configure.1.asciidoc b/doc/man/pkgctl-repo-configure.1.asciidoc index 4499ed6..1b07dc7 100644 --- a/doc/man/pkgctl-repo-configure.1.asciidoc +++ b/doc/man/pkgctl-repo-configure.1.asciidoc @@ -25,6 +25,11 @@ read-only HTTPS otherwise. Options ------- +*-j, --jobs* 'N':: + Run up to N jobs in parallel. By default the number of jobs is equal to the + number of available processing units. For sequential processing this option + needs to be passed with 1. + *-h, --help*:: Show a help text diff --git a/src/lib/common.sh b/src/lib/common.sh index 24479eb..3d1ee56 100644 --- a/src/lib/common.sh +++ b/src/lib/common.sh @@ -30,7 +30,7 @@ export GIT_PACKAGING_URL_HTTPS="https://${GITLAB_HOST}/${GIT_PACKAGING_NAMESPACE export PACKAGING_REPO_RELEASE_HOST=repos.archlinux.org # check if messages are to be printed using color -if [[ -t 2 && "$TERM" != dumb ]]; then +if [[ -t 2 && "$TERM" != dumb ]] || [[ ${DEVTOOLS_COLOR} == always ]]; then colorize else # shellcheck disable=2034 diff --git a/src/lib/repo/clone.sh b/src/lib/repo/clone.sh index 340aa69..a02d799 100644 --- a/src/lib/repo/clone.sh +++ b/src/lib/repo/clone.sh @@ -34,6 +34,7 @@ pkgctl_repo_clone_usage() { -m, --maintainer=NAME Clone all packages of the named maintainer --switch VERSION Switch the current working tree to a specified version --universe Clone all existing packages, useful for cache warming + -j, --jobs N Run up to N jobs in parallel (default: $(nproc)) -h, --help Show this help text EXAMPLES @@ -55,9 +56,11 @@ pkgctl_repo_clone() { local MAINTAINER= local VERSION= local CONFIGURE_OPTIONS=() - local pkgbases + local jobs= + jobs=$(nproc) # variables + local command=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}} local project_path while (( $# )); do @@ -97,6 +100,11 @@ pkgctl_repo_clone() { CLONE_ALL=1 shift ;; + -j|--jobs) + (( $# <= 1 )) && die "missing argument for %s" "$1" + jobs=$2 + shift 2 + ;; --) shift break @@ -142,12 +150,31 @@ pkgctl_repo_clone() { stat_done fi + # parallelization + if [[ ${jobs} != 1 ]] && (( ${#pkgbases[@]} > 1 )); then + # force colors in parallel if parent process is colorized + if [[ -n ${BOLD} ]]; then + export DEVTOOLS_COLOR=always + fi + # assign command options + if [[ -n "${VERSION}" ]]; then + command+=" --switch '${VERSION}'" + fi + if ! parallel --bar --jobs "${jobs}" "${command}" ::: "${pkgbases[@]}"; then + die 'Failed to clone some packages, please check the output' + exit 1 + fi + exit 0 + fi + for pkgbase in "${pkgbases[@]}"; do if [[ ! -d ${pkgbase} ]]; then msg "Cloning ${pkgbase} ..." project_path=$(gitlab_project_name_to_path "${pkgbase}") remote_url="${GIT_REPO_BASE_URL}/${project_path}.git" - git clone --origin origin "${remote_url}" "${pkgbase}" + if ! git clone --origin origin "${remote_url}" "${pkgbase}"; then + die 'failed to clone %s' "${pkgbase}" + fi else warning "Skip cloning ${pkgbase}: Directory exists" fi diff --git a/src/lib/repo/configure.sh b/src/lib/repo/configure.sh index 942876a..a5708a0 100644 --- a/src/lib/repo/configure.sh +++ b/src/lib/repo/configure.sh @@ -33,6 +33,7 @@ pkgctl_repo_configure_usage() { read-only HTTPS otherwise. OPTIONS + -j, --jobs N Run up to N jobs in parallel (default: $(nproc)) -h, --help Show this help text EXAMPLES @@ -93,9 +94,12 @@ pkgctl_repo_configure() { local GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_HTTPS} local official=0 local proto=https + local jobs= + jobs=$(nproc) local paths=() # variables + local -r command=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}} local path realpath pkgbase remote_url project_path local PACKAGER GPGKEY packager_name packager_email @@ -105,6 +109,11 @@ pkgctl_repo_configure() { pkgctl_repo_configure_usage exit 0 ;; + -j|--jobs) + (( $# <= 1 )) && die "missing argument for %s" "$1" + jobs=$2 + shift 2 + ;; --) shift break @@ -157,10 +166,21 @@ pkgctl_repo_configure() { msg2 "protocol: ${YELLOW}${proto}${ALL_OFF}" fi + # parallelization + if [[ ${jobs} != 1 ]] && (( ${#paths[@]} > 1 )); then + if [[ -n ${BOLD} ]]; then + export DEVTOOLS_COLOR=always + fi + if ! parallel --bar --jobs "${jobs}" "${command}" ::: "${paths[@]}"; then + die 'Failed to configure some packages, please check the output' + exit 1 + fi + exit 0 + fi + for path in "${paths[@]}"; do if ! realpath=$(realpath -e "${path}"); then - error "No such directory: ${path}" - continue + die "No such directory: ${path}" fi pkgbase=$(basename "${realpath}") @@ -168,8 +188,7 @@ pkgctl_repo_configure() { msg "Configuring ${pkgbase}" if [[ ! -d "${path}/.git" ]]; then - error "Not a Git repository: ${path}" - continue + die "Not a Git repository: ${path}" fi pushd "${path}" >/dev/null -- cgit v1.2.3-70-g09d2 From a08bc2acf49c68061284c7991d41dc78c46ae2b4 Mon Sep 17 00:00:00 2001 From: Levente Polyak Date: Wed, 24 May 2023 02:40:52 +0200 Subject: feature(clone): add protocol option to force cloning over HTTPS This is a rather quick and simple implementation to override the current logic and force clone with HTTPS. Allowing to explicitly clone over HTTPS is currently required to unblock reproducible builds where no ssh keys and GitLab user accounts are set up as of now. Hence this quick solution comes into play to mitigate the regression on reproducible builds builders. Revisit the overall auto detection and protocol logic approach for a later release related to some ideas floating around in pending merge-requests. Signed-off-by: Levente Polyak --- contrib/completion/bash/devtools.in | 7 +++++++ contrib/completion/zsh/_devtools.in | 2 ++ doc/man/pkgctl-repo-clone.1.asciidoc | 3 +++ doc/man/pkgctl-repo-configure.1.asciidoc | 3 +++ src/lib/repo/clone.sh | 15 +++++++++++++-- src/lib/repo/configure.sh | 21 +++++++++++++++++++-- 6 files changed, 47 insertions(+), 4 deletions(-) (limited to 'contrib/completion/bash') diff --git a/contrib/completion/bash/devtools.in b/contrib/completion/bash/devtools.in index 17f863f..3faad27 100644 --- a/contrib/completion/bash/devtools.in +++ b/contrib/completion/bash/devtools.in @@ -265,6 +265,7 @@ _pkgctl_repo_cmds=( _pkgctl_repo_clone_args=( -m --maintainer + --protocol --switch -u --unprivileged --universe @@ -273,6 +274,7 @@ _pkgctl_repo_clone_args=( ) _pkgctl_repo_clone_args__maintainer_opts() { :; } _pkgctl_repo_clone_args_m_opts() { _pkgctl_repo_clone_args__maintainer_opts; } +_pkgctl_repo_clone_args__protocol_opts() { _devtools_completions_protocol; } _pkgctl_repo_clone_args__switch_opts() { :; } _pkgctl_repo_clone_args__jobs_opts() { :; } _pkgctl_repo_clone_args_j_opts() { _pkgctl_repo_clone_args__jobs_opts; } @@ -280,9 +282,11 @@ _pkgctl_repo_clone_opts() { _devtools_completions_all_packages; } _pkgctl_repo_configure_args=( + --protocol -j --jobs -h --help ) +_pkgctl_repo_configure_args__protocol_opts() { _devtools_completions_protocol; } _pkgctl_repo_configure_args__jobs_opts() { :; } _pkgctl_repo_configure_args_j_opts() { _pkgctl_repo_clone_args__jobs_opts; } _pkgctl_repo_configure_opts() { _filedir -d; } @@ -363,6 +367,9 @@ _devtools_completions_build_repo() { _devtools_completions_all_packages() { mapfile -t COMPREPLY < <(compgen -W "$(pacman -Sql)" -- "$cur") } +_devtools_completions_protocol() { + mapfile -t COMPREPLY < <(compgen -W "https" -- "$cur") +} __devtools_complete() { local service=$1 diff --git a/contrib/completion/zsh/_devtools.in b/contrib/completion/zsh/_devtools.in index 240f781..a473bc2 100644 --- a/contrib/completion/zsh/_devtools.in +++ b/contrib/completion/zsh/_devtools.in @@ -108,6 +108,7 @@ _pkgctl_repo_switch_args=( _pkgctl_repo_clone_args=( '(-m --maintainer=)'{-m,--maintainer=}'[Clone all packages of the named maintainer]:maintainer:' + '--protocol[Clone the repository over https]:proto:(https)' '--switch=[Switch the current working tree to a specified version]' '--universe[Clone all existing packages, useful for cache warming]' '(-j --jobs)'{-j,--jobs}'[Run up to N jobs in parallel (default: number of processing units)]:jobs:' @@ -116,6 +117,7 @@ _pkgctl_repo_clone_args=( ) _pkgctl_repo_configure_args=( + '--protocol[Configure remote url to use https]:proto:(https)' '(-j --jobs)'{-j,--jobs}'[Run up to N jobs in parallel (default: number of processing units)]:jobs:' '(-h --help)'{-h,--help}'[Display usage]' '*:git_dir:_files -/' diff --git a/doc/man/pkgctl-repo-clone.1.asciidoc b/doc/man/pkgctl-repo-clone.1.asciidoc index d6da062..421c71f 100644 --- a/doc/man/pkgctl-repo-clone.1.asciidoc +++ b/doc/man/pkgctl-repo-clone.1.asciidoc @@ -25,6 +25,9 @@ Options *-m, --maintainer* 'NAME':: Clone all packages of the named maintainer +*--protocol* 'https':: + Clone the repository over https + *--universe*:: Clone all existing packages, useful for cache warming diff --git a/doc/man/pkgctl-repo-configure.1.asciidoc b/doc/man/pkgctl-repo-configure.1.asciidoc index 1b07dc7..6bdea93 100644 --- a/doc/man/pkgctl-repo-configure.1.asciidoc +++ b/doc/man/pkgctl-repo-configure.1.asciidoc @@ -25,6 +25,9 @@ read-only HTTPS otherwise. Options ------- +*--protocol* 'https':: + Configure remote url to use https + *-j, --jobs* 'N':: Run up to N jobs in parallel. By default the number of jobs is equal to the number of available processing units. For sequential processing this option diff --git a/src/lib/repo/clone.sh b/src/lib/repo/clone.sh index a02d799..08bded4 100644 --- a/src/lib/repo/clone.sh +++ b/src/lib/repo/clone.sh @@ -26,12 +26,13 @@ pkgctl_repo_clone_usage() { Clone Git packaging repositories from the canonical namespace. The configure command is subsequently invoked to synchronize the distro - specs and makepkg.conf settings. The unprivileged option can be used + specs and makepkg.conf settings. The protocol option can be used for cloning packaging repositories without SSH access using read-only HTTPS. OPTIONS -m, --maintainer=NAME Clone all packages of the named maintainer + --protocol https Clone the repository over https --switch VERSION Switch the current working tree to a specified version --universe Clone all existing packages, useful for cache warming -j, --jobs N Run up to N jobs in parallel (default: $(nproc)) @@ -69,11 +70,21 @@ pkgctl_repo_clone() { pkgctl_repo_clone_usage exit 0 ;; - -u|--unprivileged) + --protocol=https) GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_HTTPS} CONFIGURE_OPTIONS+=("$1") shift ;; + --protocol) + (( $# <= 1 )) && die "missing argument for %s" "$1" + if [[ $2 == https ]]; then + GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_HTTPS} + else + die "unsupported protocol: %s" "$2" + fi + CONFIGURE_OPTIONS+=("$1" "$2") + shift 2 + ;; -m|--maintainer) (( $# <= 1 )) && die "missing argument for %s" "$1" MAINTAINER="$2" diff --git a/src/lib/repo/configure.sh b/src/lib/repo/configure.sh index a5708a0..81b7d19 100644 --- a/src/lib/repo/configure.sh +++ b/src/lib/repo/configure.sh @@ -33,6 +33,7 @@ pkgctl_repo_configure_usage() { read-only HTTPS otherwise. OPTIONS + --protocol https Configure remote url to use https -j, --jobs N Run up to N jobs in parallel (default: $(nproc)) -h, --help Show this help text @@ -94,6 +95,7 @@ pkgctl_repo_configure() { local GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_HTTPS} local official=0 local proto=https + local proto_force=0 local jobs= jobs=$(nproc) local paths=() @@ -109,6 +111,19 @@ pkgctl_repo_configure() { pkgctl_repo_configure_usage exit 0 ;; + --protocol=https) + proto_force=1 + shift + ;; + --protocol) + (( $# <= 1 )) && die "missing argument for %s" "$1" + if [[ $2 == https ]]; then + proto_force=1 + else + die "unsupported protocol: %s" "$2" + fi + shift 2 + ;; -j|--jobs) (( $# <= 1 )) && die "missing argument for %s" "$1" jobs=$2 @@ -152,8 +167,10 @@ pkgctl_repo_configure() { fi if is_packager_email_official "${packager_email}"; then official=1 - proto=ssh - GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_SSH} + if (( ! proto_force )); then + proto=ssh + GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_SSH} + fi fi fi -- cgit v1.2.3-70-g09d2