From bb72473529e300724eb7d78890da85a9ca7f6157 Mon Sep 17 00:00:00 2001
From: Levente Polyak <anthraxx@archlinux.org>
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.
---
 doc/man/devtools.7.asciidoc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'doc/man/devtools.7.asciidoc')

diff --git a/doc/man/devtools.7.asciidoc b/doc/man/devtools.7.asciidoc
index 9062278..1bd118f 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', 'extra2community')
+repository management such as ('archco')
 
 Programs
 --------
-- 
cgit v1.2.3-70-g09d2


From 3d3176beb6eb0319809be386cd903fa03bdabc73 Mon Sep 17 00:00:00 2001
From: Levente Polyak <anthraxx@archlinux.org>
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 <anthraxx@archlinux.org>
---
 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 'doc/man/devtools.7.asciidoc')

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 a8be7423efb287edd5ef80002a75a853fc0c9c1d Mon Sep 17 00:00:00 2001
From: Levente Polyak <anthraxx@archlinux.org>
Date: Mon, 12 Sep 2022 01:34:08 +0200
Subject: pkgctl: add a unified command-line frontend for devtools

This is the first step of a simple and highly structured unified
interface to devtools commands in a single wrapper.

The split is based on groups like `repo`, `build` and `diff`

Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
---
 contrib/completion/zsh/_devtools.in      | 42 ++++++++++++------
 doc/man/devtools.7.asciidoc              | 20 +++++++--
 doc/man/diffpkg.1.asciidoc               |  4 --
 doc/man/pkgctl-diff.1.asciidoc           | 73 ++++++++++++++++++++++++++++++++
 doc/man/pkgctl-repo-clone.1.asciidoc     | 42 ++++++++++++++++++
 doc/man/pkgctl-repo-configure.1.asciidoc | 32 ++++++++++++++
 doc/man/pkgctl-repo-web.1.asciidoc       | 24 +++++++++++
 doc/man/pkgctl-repo.1.asciidoc           | 51 ++++++++++++++++++++++
 doc/man/pkgctl.1.asciidoc                | 32 ++++++++++++++
 src/diffpkg.in                           | 11 ++---
 src/pkgctl.in                            | 56 ++++++++++++++++++++++++
 src/pkgrepo.in                           |  7 +--
 12 files changed, 365 insertions(+), 29 deletions(-)
 create mode 100644 doc/man/pkgctl-diff.1.asciidoc
 create mode 100644 doc/man/pkgctl-repo-clone.1.asciidoc
 create mode 100644 doc/man/pkgctl-repo-configure.1.asciidoc
 create mode 100644 doc/man/pkgctl-repo-web.1.asciidoc
 create mode 100644 doc/man/pkgctl-repo.1.asciidoc
 create mode 100644 doc/man/pkgctl.1.asciidoc
 create mode 100644 src/pkgctl.in

(limited to 'doc/man/devtools.7.asciidoc')

diff --git a/contrib/completion/zsh/_devtools.in b/contrib/completion/zsh/_devtools.in
index d30648a..959497e 100644
--- a/contrib/completion/zsh/_devtools.in
+++ b/contrib/completion/zsh/_devtools.in
@@ -1,4 +1,4 @@
-#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
+#compdef archbuild pkgrepo arch-nspawn archrelease commitpkg pkgctl 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
 
@@ -149,31 +149,47 @@ _devtools_completions_all_packages() {
 	compadd - "${(@)packages}"
 }
 
-_devtools() {
-	local service_func=_${service//-/_}
-	local service_cmds=${service_func}_cmds
-	if typeset -p ${service_cmds} &> /dev/null; then
+_pkgctl_cmds=(
+	"pkgctl command"
+	"diff[Compare package files using different modes]"
+	"repo[Manage Git packaging repositories and their configuration]"
+)
+
+_pkgctl_diff_args=("${_diffpkg_args[@]}")
+
+_pkgctl_repo_cmds=("${_pkgrepo_cmds[@]}")
+_pkgctl_repo_clone_args=("${_pkgrepo_clone_args[@]}")
+_pkgctl_repo_configure_args=("${_pkgrepo_configure_args[@]}")
+
+_handle_subcommands() {
+	local service_name=${1}
+	if typeset -p ${service_name}_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}"
+				local service_cmds=${service_name}_cmds[@]
+				_values "${(P)service_cmds}"
 				;;
 			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}[@]
+				local service_sub=${service_name}_$line[1]
+				if typeset -p ${service_sub}_args &> /dev/null; then
+					local cmd_args=${service_sub}_args[@]
 					_arguments -s "${(P)cmd_args}"
+				elif typeset -p ${service_sub}_cmds &> /dev/null; then
+					_handle_subcommands "${service_sub}"
 				fi
 				;;
 		esac
-		return 0
+	elif typeset -p ${service_name}_args &> /dev/null; then
+		local argname="${service_name}_args[@]"
+		_arguments -s "${(P)argname}"
 	fi
-	local argname="${service_func}_args[@]"
-	_arguments -s "${(P)argname}"
+}
 
+_devtools() {
+	_handle_subcommands _${service//-/_}
 }
 
 _devtools
diff --git a/doc/man/devtools.7.asciidoc b/doc/man/devtools.7.asciidoc
index 6b2d0c1..4ed11cf 100644
--- a/doc/man/devtools.7.asciidoc
+++ b/doc/man/devtools.7.asciidoc
@@ -8,16 +8,22 @@ devtools - Developer tools for the Arch Linux distribution
 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 ('pkgrepo')
+Devtools contains tools for package maintenance in Arch Linux. It comes with a
+unified command-line frontend called 'pkgctl' that aids to conveniently
+interact with all the different tools this collection provides.
+
+The toolset varies from tools for building packages in a clean chroot
+('mkarchroot', 'archbuild', ...), packaging related tools ('sogrep', 'diffpkg',
+'lddd') and tools for repository management such as ('pkgrepo').
 
 Programs
 --------
 The list below gives a short overview; see the respective documentation
 for details.
 
+linkman:pkgctl[1]
+	Unified command-line frontend for devtools
+
 linkman:archbuild[1]
 	Build an Arch Linux package inside a clean chroot
 
@@ -27,6 +33,12 @@ linkman:arch-nspawn[1]
 linkman:checkpkg[1]
 	Compare the current build package with the repository version
 
+linkman:diffpkg[1]
+	Compare package files using different modes
+
+linkman:export-pkgbuild-keys[1]
+	Export valid source signing keys from a PKGBUILD
+
 linkman:find-libdeps[1]
 	Find soname dependencies for a package
 
diff --git a/doc/man/diffpkg.1.asciidoc b/doc/man/diffpkg.1.asciidoc
index bfb2094..2f7c115 100644
--- a/doc/man/diffpkg.1.asciidoc
+++ b/doc/man/diffpkg.1.asciidoc
@@ -30,7 +30,6 @@ Options
 *-M, --makepkg-config*::
 	Set an alternate makepkg configuration file
 
-
 *-P, --pool*='DIR'::
 	Search diff target in pool dir (default `'/srv/ftp/pool'`)
 
@@ -71,7 +70,4 @@ Modes
 *-b, --buildinfo*::
 	Activate .BUILDINFO diff mode
 
-See Also
---------
-
 include::include/footer.asciidoc[]
diff --git a/doc/man/pkgctl-diff.1.asciidoc b/doc/man/pkgctl-diff.1.asciidoc
new file mode 100644
index 0000000..7eb9e68
--- /dev/null
+++ b/doc/man/pkgctl-diff.1.asciidoc
@@ -0,0 +1,73 @@
+pkgctl-diff(1)
+==============
+
+Name
+----
+pkgctl-diff - Compare package files using different modes.
+
+Synopsis
+--------
+pkgctl diff [OPTIONS] [MODES] [FILE|PKGNAME...]
+
+Description
+-----------
+
+Searches for a locally built package corresponding to the PKGBUILD, and
+downloads the last version of that package from the Pacman repositories.
+It then compares the package archives using different modes while using
+simple tar content list by default.
+
+When given one package, use it to diff against the locally built one.
+When given two packages, diff both packages against each other.
+
+In either case, a package name will be converted to a filename from the cache
+or pool, and 'pkgctl diff' will proceed as though this filename was initially
+specified.
+
+Options
+-------
+
+*-M, --makepkg-config*::
+	Set an alternate makepkg configuration file
+
+*-P, --pool*='DIR'::
+	Search diff target in pool dir (default `'/srv/ftp/pool'`)
+
+*-v, --verbose*::
+	Provide more detailed/unfiltered output
+
+*-h, --help*::
+	Show a help text
+
+Output Options
+--------------
+
+*--color*[='WHEN']::
+	Color output; 'WHEN' is `'never'`, `'always'`, or `'auto'`; Plain *--color* means *--color='auto'*
+
+*-u, -U, --unified*::
+	Output 3 lines of unified context
+
+*-y, --side-by-side*::
+	Output in two columns
+
+*-W, --width*[='NUM']::
+	Output at most 'NUM' (default `'auto'`) print columns; 'NUM' can be `'auto'`, `'columns'` or a number.
+	`'auto'` will be resolved to the maximum line length of both files, guaranteeing the diff to be uncut.
+
+Modes
+-----
+
+*-l, --list*::
+	Activate tar content list diff mode (default)
+
+*-d, --diffoscope*::
+	Activate diffoscope diff mode
+
+*-p, --pkginfo*::
+	Activate .PKGINFO diff mode
+
+*-b, --buildinfo*::
+	Activate .BUILDINFO diff mode
+
+include::include/footer.asciidoc[]
diff --git a/doc/man/pkgctl-repo-clone.1.asciidoc b/doc/man/pkgctl-repo-clone.1.asciidoc
new file mode 100644
index 0000000..9770ef8
--- /dev/null
+++ b/doc/man/pkgctl-repo-clone.1.asciidoc
@@ -0,0 +1,42 @@
+pkgctl-repo-clone(1)
+======================
+
+Name
+----
+pkgctl-repo-clone - Clone a package repository
+
+Synopsis
+--------
+pkgctl repo clone [OPTIONS] [PKGNAME...]
+
+Description
+-----------
+
+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
+
+*--universe*::
+	Clone all existing packages, useful for cache warming
+
+*-h, --help*::
+	Show a help text
+
+See Also
+--------
+
+linkman:pkgctl-repo-configure[1]
+
+include::include/footer.asciidoc[]
diff --git a/doc/man/pkgctl-repo-configure.1.asciidoc b/doc/man/pkgctl-repo-configure.1.asciidoc
new file mode 100644
index 0000000..c3a14de
--- /dev/null
+++ b/doc/man/pkgctl-repo-configure.1.asciidoc
@@ -0,0 +1,32 @@
+pkgctl-repo-configure(1)
+========================
+
+Name
+----
+pkgctl-repo-configure - Configure a clone according to distro specs
+
+Synopsis
+--------
+pkgctl repo configure [OPTIONS] [PATH...]
+
+Description
+-----------
+
+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 a help text
+
+include::include/footer.asciidoc[]
diff --git a/doc/man/pkgctl-repo-web.1.asciidoc b/doc/man/pkgctl-repo-web.1.asciidoc
new file mode 100644
index 0000000..8769be7
--- /dev/null
+++ b/doc/man/pkgctl-repo-web.1.asciidoc
@@ -0,0 +1,24 @@
+pkgctl-repo-web(1)
+==================
+
+Name
+----
+pkgctl-repo-web - Open the packaging repository's website
+
+Synopsis
+--------
+pkgctl repo web [OPTIONS] [PKGBASE...]
+
+Description
+-----------
+
+Open the packaging repository's website via xdg-open. If called with
+no arguments, open the package cloned in the current working directory.
+
+Options
+-------
+
+*-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
new file mode 100644
index 0000000..564679a
--- /dev/null
+++ b/doc/man/pkgctl-repo.1.asciidoc
@@ -0,0 +1,51 @@
+pkgctl-repo(1)
+================
+
+Name
+----
+pkgctl-repo - Manage Git packaging repositories and their configuration
+
+Synopsis
+--------
+pkgctl repo [OPTIONS] [SUBCOMMAND]
+
+Description
+-----------
+
+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.
+
+Options
+-------
+
+*-h, --help*::
+	Show a help text
+
+Subcommands
+-----------
+
+pkgctl repo clone::
+	Clone a package repository
+
+pkgctl repo configure::
+	Configure a clone according to distro specs
+
+pkgctl repo web::
+	Open the packaging repository's website
+
+See Also
+--------
+
+linkman:pkgctl-repo-clone[1]
+linkman:pkgctl-repo-configure[1]
+linkman:pkgctl-repo-web[1]
+
+include::include/footer.asciidoc[]
diff --git a/doc/man/pkgctl.1.asciidoc b/doc/man/pkgctl.1.asciidoc
new file mode 100644
index 0000000..0455074
--- /dev/null
+++ b/doc/man/pkgctl.1.asciidoc
@@ -0,0 +1,32 @@
+pkgctl(1)
+=========
+
+Name
+----
+pkgctl - Unified command-line frontend for devtools
+
+Synopsis
+--------
+pkgctl [SUBCOMMAND] [OPTIONS]
+
+Description
+-----------
+
+TODO
+
+Subcommands
+-----------
+
+pkgctl diff::
+	Compare package files using different modes
+
+pkgctl repo::
+	Manage Git packaging repositories and their configuration
+
+See Also
+--------
+
+linkman:pkgctl-diff[1]
+linkman:pkgctl-repo[1]
+
+include::include/footer.asciidoc[]
diff --git a/src/diffpkg.in b/src/diffpkg.in
index 6d07419..4856e44 100644
--- a/src/diffpkg.in
+++ b/src/diffpkg.in
@@ -5,8 +5,9 @@
 m4_include(lib/common.sh)
 
 usage() {
-    cat <<- _EOF_
-		Usage: ${BASH_SOURCE[0]##*/} [OPTIONS] [MODES] [FILE|PKGNAME...]
+	local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
+	cat <<- _EOF_
+		Usage: ${COMMAND} [OPTIONS] [MODES] [FILE|PKGNAME...]
 
 		Searches for a locally built package corresponding to the PKGBUILD, and
 		downloads the last version of that package from the Pacman repositories.
@@ -17,8 +18,8 @@ usage() {
 		When given two packages, diff both packages against each other.
 
 		In either case, a package name will be converted to a filename from the
-		cache, and diffpkg will proceed as though this filename was initially
-		specified.
+		cache, and '${COMMAND}' will proceed as though this filename was
+		initially specified.
 
 		OPTIONS
 		    -M, --makepkg-config Set an alternate makepkg configuration file
@@ -300,7 +301,7 @@ shopt -u extglob
 
 if (( $# < 2 )); then
 	if [[ ! -f PKGBUILD ]]; then
-		die "This must be run in the directory of a built package.\nTry '$(basename "$0") --help' for more information."
+		die "This must be run in the directory of a built package.\nTry '${COMMAND} --help' for more information."
 	fi
 
 	# shellcheck source=contrib/makepkg/PKGBUILD.proto
diff --git a/src/pkgctl.in b/src/pkgctl.in
new file mode 100644
index 0000000..9b7d89c
--- /dev/null
+++ b/src/pkgctl.in
@@ -0,0 +1,56 @@
+#!/bin/bash
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+m4_include(lib/common.sh)
+
+set -e
+
+
+usage() {
+	local -r COMMAND=${BASH_SOURCE[0]##*/}
+	cat <<- _EOF_
+		Usage: ${COMMAND} [COMMAND] [OPTIONS]
+
+		Unified command-line frontend for devtools.
+
+		COMMANDS
+		    diff    Compare package files using different modes
+		    repo    Manage Git packaging repositories and their configuration
+
+		OPTIONS
+		    -h, --help     Show this help text
+_EOF_
+}
+
+if (( $# < 1 )); then
+	usage
+	exit 1
+fi
+
+export _DEVTOOLS_COMMAND='pkgctl'
+
+# command checking
+while (( $# )); do
+	case $1 in
+		-h|--help)
+			usage
+			exit 0
+			;;
+		repo)
+			_DEVTOOLS_COMMAND+=" $1"
+			shift
+			pkgrepo "$@"
+			exit 0
+			;;
+		diff)
+			_DEVTOOLS_COMMAND+=" $1"
+			shift
+			diffpkg "$@"
+			exit 0
+			;;
+		*)
+			die "invalid command: %s" "$1"
+			;;
+	esac
+done
diff --git a/src/pkgrepo.in b/src/pkgrepo.in
index c6f5951..00f46e1 100644
--- a/src/pkgrepo.in
+++ b/src/pkgrepo.in
@@ -9,10 +9,11 @@ source /usr/share/makepkg/util/message.sh
 
 set -e
 
+COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
 
 usage() {
     cat <<- _EOF_
-		Usage: ${BASH_SOURCE[0]##*/} [COMMAND] [OPTIONS]
+		Usage: ${COMMAND} [COMMAND] [OPTIONS]
 
 		Manage Git packaging repositories and helps with their configuration
 		according to distro specs.
@@ -37,7 +38,7 @@ _EOF_
 
 usage_clone() {
     cat <<- _EOF_
-		Usage: ${BASH_SOURCE[0]##*/} clone [OPTIONS] [PKGNAME...]
+		Usage: ${COMMAND} clone [OPTIONS] [PKGNAME...]
 
 		Clone Git packaging repositories from the canonical namespace.
 
@@ -57,7 +58,7 @@ _EOF_
 
 usage_configure() {
     cat <<- _EOF_
-		Usage: ${BASH_SOURCE[0]##*/} configure [OPTIONS] [PATH...]
+		Usage: ${COMMAND} configure [OPTIONS] [PATH...]
 
 		Configure Git packaging repositories according to distro specs and
 		makepkg.conf settings.
-- 
cgit v1.2.3-70-g09d2

