summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLevente Polyak <anthraxx@archlinux.org>2022-09-11 20:42:30 +0200
committerLevente Polyak <anthraxx@archlinux.org>2023-05-19 22:27:11 +0200
commit5eb09a9cc931ca506875276dcd7b794395ba77d0 (patch)
tree695a655f240a10b6e9374081cbe2884bb21f027d
parent66758941594831e5da81a7c00280e73ccc842688 (diff)
downloaddevtools-5eb09a9cc931ca506875276dcd7b794395ba77d0.tar.xz
archco: implement clone and configure subcommands
Manages 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. Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
-rw-r--r--contrib/completion/zsh/_devtools.in40
-rw-r--r--lib/common.sh9
-rw-r--r--src/archco.in238
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