diff options
-rw-r--r-- | contrib/completion/zsh/_devtools.in | 40 | ||||
-rw-r--r-- | lib/common.sh | 9 | ||||
-rw-r--r-- | src/archco.in | 238 |
3 files changed, 273 insertions, 14 deletions
diff --git a/contrib/completion/zsh/_devtools.in b/contrib/completion/zsh/_devtools.in index 707e3fa..1dc112f 100644 --- a/contrib/completion/zsh/_devtools.in +++ b/contrib/completion/zsh/_devtools.in @@ -15,10 +15,24 @@ _archbuild_args=( '--[Introduce makechrootpkg options]:*::makechrootpkg options:= _dispatch makechrootpkg makechrootpkg' ) -_archco_args=( +_archco_cmds=( + "archco command" + "clone[Clone a package repository]" + "configure[Configure a clone according to distro specs]" +) + +_archco_clone_args=( + '(-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=( + '(-u --unprivileged)'{-u,--unprivileged}'[Configure read-only repo without packager info as Git author]' + '(-h --help)'{-h,--help}'[Display usage]' + '*:git_dir:_files -/' +) + _arch_nspawn_args=( '-C[Location of a pacman config file]:pacman_config:_files -g "*.conf(.)"' '-M[Location of a makepkg config file]:makepkg_config:_files -g "*.conf(.)"' @@ -128,8 +142,30 @@ _devtools_completions_all_packages() { } _devtools() { - local argname="_${service//-/_}_args[@]" + local service_func=_${service//-/_} + local service_cmds=${service_func}_cmds + if typeset -p ${service_cmds} &> /dev/null; then + _arguments -C \ + "1: :->cmds" \ + '*::arg:->args' + case $state in + cmds) + local service_cmds_array=${service_cmds}[@] + _values "${(P)service_cmds_array}" + ;; + args) + local cmd_args_array=${service_func}_$line[1]_args + if typeset -p ${cmd_args_array} &> /dev/null; then + local cmd_args=${cmd_args_array}[@] + _arguments -s "${(P)cmd_args}" + fi + ;; + esac + return 0 + fi + local argname="${service_func}_args[@]" _arguments -s "${(P)argname}" + } _devtools diff --git a/lib/common.sh b/lib/common.sh index 577bb6e..5f134ae 100644 --- a/lib/common.sh +++ b/lib/common.sh @@ -19,6 +19,15 @@ export LANG=C export BUILDTOOL=devtools export BUILDTOOLVER=m4_devtools_version +# Set common properties +export PACMAN_KEYRING_DIR=/etc/pacman.d/gnupg +export GITLAB_HOST=gitlab.archlinux.org +export GIT_REPO_SPEC_VERSION=1 +export GIT_PACKAGING_NAMESPACE=archlinux/packaging/packages +export GIT_PACKAGING_NAMESPACE_ID=11323 +export GIT_PACKAGING_URL_SSH="ssh://git@${GITLAB_HOST}/${GIT_PACKAGING_NAMESPACE}" +export GIT_PACKAGING_URL_HTTPS="https://${GITLAB_HOST}/${GIT_PACKAGING_NAMESPACE}" + # check if messages are to be printed using color if [[ -t 2 && "$TERM" != dumb ]]; then colorize diff --git a/src/archco.in b/src/archco.in index c569e52..b401c23 100644 --- a/src/archco.in +++ b/src/archco.in @@ -4,21 +4,235 @@ m4_include(lib/common.sh) -scriptname=${0##*/} +source /usr/share/makepkg/util/config.sh +source /usr/share/makepkg/util/message.sh -if [[ -z $1 ]]; then - printf 'Usage: %s <package name>...\n' "$scriptname" +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 + -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 -case $scriptname in - archco) - GITURL="ssh://git@gitlab.archlinux.org:222/bot-test/packages";; - *) - die "Couldn't find Git url for %s" "$scriptname" - ;; -esac +# 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 + ;; + --) + 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 + +# 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 + +pkgbases=("$@") +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 -for pkgbase in "$@"; do - git clone --origin origin --config commit.gpgsign=true "${GITURL}/${pkgbase}.git" + 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 |