Compare commits

...

16 Commits

Author SHA1 Message Date
Levente Polyak
aa938224d1 wip getopt 2023-04-17 23:28:25 +02:00
Levente Polyak
02d04a7c43 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 <anthraxx@archlinux.org>
2023-04-15 23:03:39 +02:00
Christian Heusel
9860819976 pkgctl: introduce the version subcommand
Related to https://gitlab.archlinux.org/archlinux/devtools/-/issues/125

Closes #125

Signed-off-by: Christian Heusel <christian@heusel.eu>
Co-Authored-By: Levente Polyak <anthraxx@archlinux.org>
2023-04-15 23:03:39 +02:00
Levente Polyak
c2271745c4 completion: zsh: allow args even when the command has subcommands
This allows to show arguments on root level of commands that themselves
have subcommands available. Complete those when any - is used in the
completion word.
2023-04-15 23:03:39 +02:00
Levente Polyak
4aaa7e67fd WIP: REMOVE after POC, map community to extra 2023-04-15 23:03:38 +02:00
Levente Polyak
653759343a WIP: set git packaging namespace to bot-test for testing 2023-04-15 23:03:38 +02:00
Levente Polyak
900f675385 config: fixup file permissions to be more strict
Normally the default in Arch is that all home directories are private.
However, this may have been changed locally. To make sure we never
expose secrets, lets use a umask of 0077 when writing the config.

Additionally add some temporary fixup code to migrate the file and
directory permissions of already existing paths.

Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
2023-04-15 23:03:38 +02:00
Levente Polyak
9d009de849 build: support nocheck for initial bootstrap builds
Output a warning when this option is used to remind packagers to rebuild
the packages with checks once the bootstrap cycle has been completed.
2023-04-15 23:03:38 +02:00
Levente Polyak
7003aecba1 doc: add dependency declaration to the README.md
This will help to make sure dependencies are explicitly stated and
reflected in the PKGBUILD.
2023-04-15 23:03:38 +02:00
Christian Heusel
6517dd780e config: allow suppying the gitlab token via env var
This would allow to supply the gitlab tokens via the env var
DEVTOOLS_GITLAB_TOKEN and therefore allow users to choose whatever
program they want to fill this env var.

Closes #113

Signed-off-by: Christian Heusel <christian@heusel.eu>
2023-04-15 23:03:38 +02:00
Campbell Jones
f484f9eccb edit: improve editor presence checking
Adds a check for the configured Git editor (git config core.editor) in
both commitpkg and build.sh.

Additionally, instead of blindly executing vi when all other options are
exhausted, remove it instead as it is a none standard installed editor
anyway.

Closes #106

Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
2023-04-15 23:03:38 +02:00
Levente Polyak
3a41c91524 rebuildpkgs: drop legacy script, will be replaced with a smarter UX
Instead of trying to port this ancient script, which doesn't even seem
to work with community, let's instead remove it. We will be adding a
replacement script in pkgctl soon with a smarter and more convenient UX.
2023-04-15 23:03:38 +02:00
Levente Polyak
fbe8028e82 doc: update manpage footer for GitLab and remove static list of maintainers
The list of all maintainers that have worked so far on devtools is
exceeding a sane amount making each manpage convulsed. The authors can
be pulled from GitLab directly without occupying lots of space on every
manpage. We would like to express gratitude to all our maintainers.

Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
2023-04-15 23:03:38 +02:00
Levente Polyak
7659b2f6ab gitlab: add project path function to map special chars
Automatic path conversion is limited to GitLab API v4 and will be
removed in the future. It's expected that the caller does the path
conversion on caller side and only passes a valid path to the API within
its limitations.

Hence convert project names to valid paths:
  1. replace single '+' between word boundaries with '-'
  2. replace any other '+' with literal 'plus'
  3. replace any special chars other than '_', '-' and '.' with '-'

Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
2023-04-15 23:03:38 +02:00
Levente Polyak
9f75e17adf repo-configure: automatically determine protocol from packager identity
The remote protocol is automatically determined from the author email
address by choosing SSH for all official packager identities and
read-only HTTPS otherwise.

Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
2023-04-15 23:03:38 +02:00
Levente Polyak
e21f2085b2 build: command to build packages inside a clean chroot 2023-04-15 23:03:38 +02:00
24 changed files with 1332 additions and 305 deletions

2
.gitignore vendored
View File

@@ -1,3 +1,3 @@
*~
devtools-*.tar.gz*
build/
/build/

View File

@@ -32,6 +32,36 @@ will automatically build the project and proxy all calls to the local build dire
5. Upload the source tarball with ```make dist upload```
6. Update the package
## Dependencies
### Runtime
- arch-install-scripts
- awk
- bash
- binutils
- coreutils
- diffutils
- findutils
- grep
- jq
- openssh
- parallel
- rsync
- sed
- util-linux
- bzr
- git
- mercurial
- subversion
### Development
- asciidoc
- make
- shellcheck
## License
Devtools is licensed under the terms of the **GPL-3.0-or-later** (see [LICENSE](LICENSE)).

View File

@@ -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
}
_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
_pkgrepo_pkg() {
_devtools_compgen "$(
command pacman "-$1"
)"
}
_binary_arch=${_arch[*]:0:-1}
_colors=(never always auto)
_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
} &&
_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
_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
true
} &&
_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
_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
true
} &&
complete -F _arch-nspawn arch-nspawn
# ex:et ts=2 sw=2 ft=sh
_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

View File

@@ -1,4 +1,4 @@
#compdef archbuild 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
#compdef archbuild arch-nspawn archrelease commitpkg pkgctl diffpkg finddeps makechrootpkg mkarchroot 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
@@ -34,6 +34,26 @@ _pkgctl_auth_status_args=(
'(-h --help)'{-h,--help}'[Display usage]'
)
_pkgctl_build_args=(
"--arch=[Specify architectures to build for (disables auto-detection)]:arch:($_arch[*])"
"--repo=[Specify a target repository (disables auto-detection)]:repo:($_repos[*])"
'(-s --staging)'{-s,--staging}'[Build against the staging counterpart of the auto-detected repo]'
'(-t --testing)'{-t,--testing}'[Build against the testing counterpart of the auto-detected repo]'
'(-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.*(.)"'
'--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:'
'--rebuild[Increment the pkgrel variable]'
'(-e --edit)'{-e,--edit}'[Edit the PKGBUILD before building]'
'(-r --release)'{-r,--release}'[Automatically commit, tag and release after building]'
'(-m --message=)'{-m,--message=}"[Use the given <msg> as the commit message]:message:"
'(-u --db-update)'{-u,--db-update}'[Automatically update the pacman database as last action]'
'(-h --help)'{-h,--help}'[Display usage]'
'*:git_dir:_files -/'
)
_pkgctl_db_cmds=(
"pkgctl db command"
"move[Move packages between pacman repositories]"
@@ -79,14 +99,12 @@ _pkgctl_repo_cmds=(
_pkgctl_repo_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]'
'--universe[Clone all existing packages, useful for cache warming]'
'(-h --help)'{-h,--help}'[Display usage]'
'*:packages:_devtools_completions_all_packages'
)
_pkgctl_repo_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 -/'
)
@@ -169,11 +187,6 @@ _mkarchroot_args=(
'*:packages:_devtools_completions_all_packages'
)
_rebuildpkgs_args=(
'1:chroot_dir:_files -/'
'*:packages:_devtools_completions_all_packages'
)
_checkpkg_args=(
'(-r --rmdir)'{-r,--rmdir}'[Remove the temporary directory]'
'(-w --warn)'{-w,--warn}'[Print a warning in case of differences]'
@@ -213,10 +226,21 @@ _devtools_completions_all_packages() {
_pkgctl_cmds=(
"pkgctl command"
"auth[Authenticate with services like GitLab]"
"build[Build packages inside a clean chroot]"
"db[Pacman database modification for packge update, move etc]"
"diff[Compare package files using different modes]"
"release[Release step to commit, tag and upload build artifacts]"
"repo[Manage Git packaging repositories and their configuration]"
"version[Show pkgctl version information]"
)
_pkgctl_args=(
'(-V --version)'{-V,--version}'[Show pkgctl version information]'
'(-h --help)'{-h,--help}'[Display usage]'
)
_pkgctl_version_args=(
'(-h --help)'{-h,--help}'[Display usage]'
)
_pkgctl_diff_args=("${_diffpkg_args[@]}")
@@ -229,8 +253,13 @@ _handle_subcommands() {
'*::arg:->args'
case $state in
cmds)
local service_cmds=${service_name}_cmds[@]
_values "${(P)service_cmds}"
if [[ "${line[-1]}" == -* ]] && typeset -p ${service_name}_args &> /dev/null; then
local argname="${service_name}_args[@]"
_arguments -s "${(P)argname}"
else
local service_cmds=${service_name}_cmds[@]
_values "${(P)service_cmds}"
fi
;;
args)
local service_sub=${service_name}_$line[1]

View File

@@ -1,27 +1,7 @@
Bugs
----
Bugs can be reported on the project's GitLab bug tracker 'https://gitlab.archlinux.org/archlinux/devtools'
Homepage
--------
'https://gitlab.archlinux.org/archlinux/devtools'
Authors
-------
Maintainers:
* Aaron Griffin <aaronmgriffin@gmail.com>
* Allan McRae <allan@archlinux.org>
* Bartłomiej Piotrowski <bpiotrowski@archlinux.org>
* Dan McGee <dan@archlinux.org>
* Dave Reisner <dreisner@archlinux.org>
* Evangelos Foutras <evangelos@foutrelis.com>
* Jan Alexander Steffens (heftig) <jan.steffens@gmail.com>
* Jelle van der Waa <jelle@archlinux.org>
* Levente Polyak <anthraxx@archlinux.org>
* Pierre Schmitz <pierre@archlinux.de>
* Sébastien Luttringer <seblu@seblu.net>
* Sven-Hendrik Haase <svenstaro@gmail.com>
* Thomas Bächler <thomas@archlinux.org>
For additional contributors, use `git shortlog -s` on the devtools.git
repository.
Please report bugs and feature requests in the issue tracker. Please do your best to provide a reproducible test case for bugs.

View File

@@ -0,0 +1,83 @@
pkgctl-build(1)
===============
Name
----
pkgctl-build - Build packages inside a clean chroot
Synopsis
--------
pkgctl build [OPTIONS] [PATH...]
Description
-----------
TODO
Build Options
-------------
*--arch* 'ARCH'::
Specify architectures to build for (disables auto-detection)
*--repo* 'REPO'::
Specify a target repository (disables auto-detection)
*-s, --staging*::
Build against the staging counterpart of the auto-detected repo
*-t, --testing*::
Build against the testing counterpart of the auto-detected repo
*-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
*--nocheck*::
Do not run the check() function in the PKGBUILD
PKGBUILD Options
----------------
*--pkgver*='PKGVER'::
Set pkgver, reset pkgrel and update checksums
*--pkgrel*='PKGREL'::
Set pkgrel to a given value
*--rebuild*::
Increment the current pkgrel variable
*-e, --edit*::
Edit the PKGBUILD before building
Release Options
---------------
*-r, --release*::
Automatically commit, tag and release after building
*-m, --message* 'MSG'::
Use the given <msg> as the commit message
*-u, --db-update*::
Automatically update the pacman database as last action
Options
-------
*-h, --help*::
Show a help text
See Also
--------
linkman:pkgctl-release[1]
linkman:pkgctl-db-update[1]
include::include/footer.asciidoc[]

View File

@@ -25,9 +25,6 @@ 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

View File

@@ -17,15 +17,14 @@ Configure Git packaging repositories according to distro specs and
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.
The remote protocol is automatically determined from the author email
address by choosing SSH for all official packager identities and
read-only HTTPS otherwise.
Options
-------
*-u, --unprivileged*::
Configure read-only repo without packager info as Git author
*-h, --help*::
Show a help text

View File

@@ -0,0 +1,23 @@
pkgctl-version(1)
=================
Name
----
pkgctl-version - Show pkgctl version information
Synopsis
--------
pkgctl version [OPTIONS]
Description
-----------
Shows the current version information of pkgctl.
Options
-------
*-h, --help*::
Show a help text
include::include/footer.asciidoc[]

View File

@@ -14,12 +14,24 @@ Description
TODO
Options
-------
*-V, --version*::
Show pkgctl version information
*-h, --help*::
Show a help text
Subcommands
-----------
pkgctl auth::
Authenticate with services like GitLab
pkgctl build::
Build packages inside a clean chroot
pkgctl db::
Pacman database modification for packge update, move etc
@@ -32,13 +44,18 @@ pkgctl release::
pkgctl repo::
Manage Git packaging repositories and their configuration
pkgctl version::
Show pkgctl version information
See Also
--------
linkman:pkgctl-auth[1]
linkman:pkgctl-build[1]
linkman:pkgctl-db[1]
linkman:pkgctl-diff[1]
linkman:pkgctl-release[1]
linkman:pkgctl-repo[1]
linkman:pkgctl-version[1]
include::include/footer.asciidoc[]

46
opts.sh Executable file
View File

@@ -0,0 +1,46 @@
#!/bin/bash
# NOTE: This requires GNU getopt
if ! ARGS=$(getopt --options vdm:D: \
--long verbose,debug,memory:,debugfile: \
--name 'pkgctl foo' -- "$@"); then
exit 1
fi
eval set -- "$ARGS"
echo "${ARGS}"
while (( $# )); do
case "$1" in
-v | --verbose ) echo verbose; shift ;;
-d | --debug ) echo debug; shift ;;
-m | --memory ) echo "memory=$2"; shift 2 ;;
-D | --debugfile ) echo "debugfile=$2"; shift 2 ;;
--)
echo --
shift
break
;;
-*)
echo "invalid argument: %s" "$1"
exit 1
;;
*)
echo STAR "$1"
shift
;;
esac
done
echo main
if (( ! $# )); then
echo missing positional param: version
exit 1
fi
version=$1
shift
echo "version $version"
echo "$@"

View File

@@ -198,8 +198,10 @@ if [[ -n $(git status --short --untracked-files=no) ]]; then
$VISUAL "$msgfile" || die
elif [[ -n $EDITOR ]]; then
$EDITOR "$msgfile" || die
elif giteditor=$(git config --get core.editor); then
$giteditor "$msgfile" || die
else
vi "$msgfile" || die
die "No usable editor found (tried \$GIT_EDITOR, \$VISUAL, \$EDITOR, git config [core.editor])."
fi
[[ -s $msgfile ]] || die
stat_busy 'Committing changes'

View File

@@ -81,16 +81,30 @@ gitlab_api_get_user() {
return 0
}
# 1. replace single '+' between word boundaries with '-'
# 2. replace any other '+' with literal 'plus'
# 3. replace any special chars other than '_', '-' and '.' with '-'
gitlab_project_name_to_path() {
local name=$1
printf "%s" "${name}" \
| sed -E 's/([a-zA-Z0-9]+)\+([a-zA-Z]+)/\1-\2/g' \
| sed -E 's/\+/plus/g' \
| sed -E 's/[^a-zA-Z0-9_\-\.]/-/g'
}
gitlab_api_create_project() {
local pkgbase=$1
local outfile data path
local outfile data path project_path
[[ -z ${WORKDIR:-} ]] && setup_workdir
outfile=$(mktemp --tmpdir="${WORKDIR}" pkgctl-gitlab-api.XXXXXXXXXX)
project_path=$(gitlab_project_name_to_path "${pkgbase}")
# create GitLab project
data='{
"name": "'"${pkgbase}"'",
"path": "'"${project_path}"'",
"namespace_id": "'"${GIT_PACKAGING_NAMESPACE_ID}"'",
"request_access_enabled": "false"
}'

412
src/lib/build/build.sh Normal file
View File

@@ -0,0 +1,412 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_BUILD_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_BUILD_SH=1
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
# shellcheck source=src/lib/common.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
# shellcheck source=src/lib/db/update.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/db/update.sh
# shellcheck source=src/lib/release.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/release.sh
# shellcheck source=src/lib/util/git.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/git.sh
# shellcheck source=src/lib/util/pacman.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/pacman.sh
# shellcheck source=src/lib/valid-repos.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-repos.sh
# shellcheck source=src/lib/valid-tags.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-tags.sh
source /usr/share/makepkg/util/config.sh
source /usr/share/makepkg/util/message.sh
set -e
pkgctl_build_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS] [PATH]...
Build packages inside a clean chroot
When a new pkgver is set using the appropriate PKGBUILD options the
checksums are automatically updated.
TODO
BUILD OPTIONS
--arch ARCH Specify architectures to build for (disables auto-detection)
--repo REPO Specify a target repository (disables auto-detection)
-s, --staging Build against the staging counterpart of the auto-detected repo
-t, --testing Build against the testing counterpart of the auto-detected repo
-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
--nocheck Do not run the check() function in the PKGBUILD
PKGBUILD OPTIONS
--pkgver=PKGVER Set pkgver, reset pkgrel and update checksums
--pkgrel=PKGREL Set pkgrel to a given value
--rebuild Increment the current pkgrel variable
-e, --edit Edit the PKGBUILD before building
RELEASE OPTIONS
-r, --release Automatically commit, tag and release after building
-m, --message MSG Use the given <msg> as the commit message
-u, --db-update Automatically update the pacman database as last action
OPTIONS
-h, --help Show this help text
EXAMPLES
$ ${COMMAND}
$ ${COMMAND} --rebuild --staging --message 'libyay 0.42 rebuild' libfoo libbar
$ ${COMMAND} --pkgver 1.42 --release --db-update
_EOF_
}
pkgctl_build_check_option_group_repo() {
local option=$1
local repo=$2
local testing=$3
local staging=$4
if ( (( testing )) && (( staging )) ) ||
( [[ $repo =~ ^.*-(staging|testing)$ ]] && ( (( testing )) || (( staging )) )); then
die "The argument '%s' cannot be used with one or more of the other specified arguments" "${option}"
exit 1
fi
return 0
}
pkgctl_build_check_option_group_ver() {
local option=$1
local pkgver=$2
local pkgrel=$3
local rebuild=$4
if [[ -n "${pkgver}" ]] || [[ -n "${pkgrel}" ]] || (( rebuild )); then
die "The argument '%s' cannot be used with one or more of the other specified arguments" "${option}"
exit 1
fi
return 0
}
# TODO: import pgp keys
pkgctl_build() {
if (( $# < 1 )) && [[ ! -f PKGBUILD ]]; then
pkgctl_build_usage
exit 1
fi
local UPDPKGSUMS=0
local EDIT=0
local REBUILD=0
local OFFLOAD=0
local STAGING=0
local TESTING=0
local RELEASE=0
local DB_UPDATE=0
local REPO=
local PKGVER=
local PKGREL=
local MESSAGE=
local paths=()
local BUILD_ARCH=()
local BUILD_OPTIONS=()
local MAKECHROOT_OPTIONS=()
local RELEASE_OPTIONS=()
local MAKEPKG_OPTIONS=()
local PTS
PTS="$(tty | sed 's|/dev/pts/||')"
local WORKER="${USER}-${PTS}"
# variables
local path pkgbase pkgrepo source
while (( $# )); do
case $1 in
-h|--help)
pkgctl_build_usage
exit 0
;;
--repo)
(( $# <= 1 )) && die "missing argument for %s" "$1"
REPO="${2}"
pkgctl_build_check_option_group_repo '--repo' "${REPO}" "${TESTING}" "${STAGING}"
shift 2
;;
--arch)
(( $# <= 1 )) && die "missing argument for %s" "$1"
if [[ ${2} == all ]]; then
BUILD_ARCH=("${_arch[@]::${#_arch[@]}-1}")
elif [[ ${2} == any ]]; then
BUILD_ARCH=("${_arch[0]}")
elif ! in_array "${2}" "${BUILD_ARCH[@]}"; then
if ! in_array "${2}" "${_arch[@]}"; then
die 'invalid architecture: %s' "${2}"
fi
BUILD_ARCH+=("${2}")
fi
shift 2
;;
--pkgver=*)
pkgctl_build_check_option_group_ver '--pkgver' "${PKGVER}" "${PKGREL}" "${REBUILD}"
PKGVER="${1#*=}"
PKGREL=1
UPDPKGSUMS=1
shift
;;
--pkgrel=*)
pkgctl_build_check_option_group_ver '--pkgrel' "${PKGVER}" "${PKGREL}" "${REBUILD}"
PKGREL="${1#*=}"
shift
;;
--rebuild)
# shellcheck source=src/lib/util/git.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/git.sh
pkgctl_build_check_option_group_ver '--rebuild' "${PKGVER}" "${PKGREL}" "${REBUILD}"
REBUILD=1
shift
;;
-e|--edit)
EDIT=1
shift
;;
-o|--offload)
OFFLOAD=1
shift
;;
-s|--staging)
STAGING=1
pkgctl_build_check_option_group_repo '--staging' "${REPO}" "${TESTING}" "${STAGING}"
shift
;;
-t|--testing)
TESTING=1
pkgctl_build_check_option_group_repo '--testing' "${REPO}" "${TESTING}" "${STAGING}"
shift
;;
-c|--clean)
BUILD_OPTIONS+=("-c")
shift
;;
-I|--install)
(( $# <= 1 )) && die "missing argument for %s" "$1"
MAKECHROOT_OPTIONS+=("-I" "$2")
warning 'installing packages into the chroot may break reproducible builds, use with caution!'
shift 2
;;
--nocheck)
MAKEPKG_OPTIONS+=("--nocheck")
warning 'not running checks is disallowed for official packages, except for bootstrapping. Please rebuild after bootstrapping is completed!'
shift
;;
-r|--release)
# shellcheck source=src/lib/release.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/release.sh
RELEASE=1
shift
;;
-m|--message)
(( $# <= 1 )) && die "missing argument for %s" "$1"
MESSAGE=$2
RELEASE_OPTIONS+=("--message" "${MESSAGE}")
shift 2
;;
-u|--db-update)
DB_UPDATE=1
shift
;;
--)
shift
break
;;
-*)
die "invalid argument: %s" "$1"
;;
*)
paths=("$@")
break
;;
esac
done
# check if invoked without any path from within a packaging repo
if (( ${#paths[@]} == 0 )); then
if [[ -f PKGBUILD ]]; then
paths=(".")
else
pkgctl_build_usage
exit 1
fi
fi
# Update pacman cache for auto-detection
if [[ -z ${REPO} ]]; then
update_pacman_repo_cache
# Check valid repos if not resolved dynamically
elif ! in_array "${REPO}" "${_repos[@]}"; then
die "Invalid repository target: %s" "${REPO}"
fi
for path in "${paths[@]}"; do
pushd "${path}" >/dev/null
if [[ ! -f PKGBUILD ]]; then
die 'PKGBUILD not found in %s' "${path}"
fi
source=()
# shellcheck source=contrib/makepkg/PKGBUILD.proto
. ./PKGBUILD
pkgbase=${pkgbase:-$pkgname}
pkgrepo=${REPO}
msg "Building ${pkgbase}"
# auto-detection of build target
if [[ -z ${pkgrepo} ]]; then
if ! pkgrepo=$(get_pacman_repo_from_pkgbuild PKGBUILD); then
die 'failed to get pacman repo'
fi
if [[ -z "${pkgrepo}" ]]; then
die 'unknown repo, please specify --repo for new packages'
fi
fi
# TODO: REMOVE AFTER POC
if [[ ${pkgrepo} == community ]]; then
pkgrepo=extra
fi
# special cases to resolve final build target
if (( TESTING )); then
pkgrepo="${pkgrepo}-testing"
elif (( STAGING )); then
pkgrepo="${pkgrepo}-staging"
elif [[ $pkgrepo == core ]]; then
pkgrepo="${pkgrepo}-testing"
fi
# auto-detection of build architecture
if [[ $pkgrepo = multilib* ]]; then
BUILD_ARCH=("")
elif (( ${#BUILD_ARCH[@]} == 0 )); then
if in_array any "${arch[@]}"; then
BUILD_ARCH=("${_arch[0]}")
else
BUILD_ARCH+=("${arch[@]}")
fi
fi
# print gathered build modes
msg2 "repo: ${pkgrepo}"
msg2 "arch: ${BUILD_ARCH[*]}"
# increment pkgrel on rebuild
if (( REBUILD )); then
# try to figure out of pkgrel has been changed
if ! old_pkgrel=$(git_diff_tree HEAD PKGBUILD | grep --perl-regexp --only-matching --max-count=1 '^-pkgrel=\K\w+'); then
old_pkgrel=${pkgrel}
fi
# check if pkgrel conforms expectations
[[ ${pkgrel/.*} =~ ^[0-9]+$ ]] || die "Non-standard pkgrel declaration"
[[ ${old_pkgrel/.*} =~ ^[0-9]+$ ]] || die "Non-standard pkgrel declaration"
# increment pkgrel if it hasn't been changed yet
if [[ ${pkgrel} = "${old_pkgrel}" ]]; then
PKGREL=$((${pkgrel/.*}+1))
else
warning 'ignoring --rebuild as pkgrel has already been incremented from %s to %s' "${old_pkgrel}" "${pkgrel}"
fi
fi
# update pkgver
if [[ -n ${PKGVER} ]]; then
if [[ $(type -t pkgver) == function ]]; then
# TODO: check if die or warn, if we provide _commit _gitcommit setter maybe?
warning 'setting pkgver variable has no effect if the PKGBUILD has a pkgver() function'
fi
msg "Bumping pkgver to ${PKGVER}"
grep --extended-regexp --quiet --max-count=1 "^pkgver=${pkgver}$" PKGBUILD || die "Non-standard pkgver declaration"
sed --regexp-extended "s|^(pkgver=)${pkgver}$|\1${PKGVER}|g" -i PKGBUILD
fi
# update pkgrel
if [[ -n ${PKGREL} ]]; then
msg "Bumping pkgrel to ${PKGREL}"
grep --extended-regexp --quiet --max-count=1 "^pkgrel=${pkgrel}$" PKGBUILD || die "Non-standard pkgrel declaration"
sed --regexp-extended "s|^(pkgrel=)${pkgrel}$|\1${PKGREL}|g" -i PKGBUILD
fi
# edit PKGBUILD
if (( EDIT )); then
stat_busy 'Editing PKGBUILD'
if [[ -n $GIT_EDITOR ]]; then
$GIT_EDITOR PKGBUILD || die
elif [[ -n $VISUAL ]]; then
$VISUAL PKGBUILD || die
elif [[ -n $EDITOR ]]; then
$EDITOR PKGBUILD || die
elif giteditor=$(git config --get core.editor); then
$giteditor PKGBUILD || die
else
die "No usable editor found (tried \$GIT_EDITOR, \$VISUAL, \$EDITOR, git config [core.editor])."
fi
stat_done
fi
# update checksums if any sources are declared
if (( UPDPKGSUMS )) && (( ${#source[@]} >= 1 )); then
updpkgsums
fi
# execute build
for arch in "${BUILD_ARCH[@]}"; do
if [[ -n $arch ]]; then
msg "Building ${pkgbase} for [${pkgrepo}] (${arch})"
BUILDTOOL="${pkgrepo}-${arch}-build"
else
msg "Building ${pkgbase} for [${pkgrepo}]"
BUILDTOOL="${pkgrepo}-build"
fi
# TODO: REMOVE AFTER POC
offload_tool=${pkgrepo}
if [[ ${pkgrepo} == core-* ]]; then
BUILDTOOL=${BUILDTOOL/core-/}
offload_tool=${offload_tool/core-/}
elif [[ ${pkgrepo} == extra-* ]]; then
BUILDTOOL=${BUILDTOOL/extra-/}
offload_tool=${offload_tool/extra-/}
fi
if (( OFFLOAD )); then
offload-build --repo "${offload_tool}" -- "${BUILD_OPTIONS[@]}" -- "${MAKECHROOT_OPTIONS[@]}" -l "${WORKER}" -- "${MAKEPKG_OPTIONS[@]}"
else
"${BUILDTOOL}" "${BUILD_OPTIONS[@]}" -- "${MAKECHROOT_OPTIONS[@]}" -l "${WORKER}" -- "${MAKEPKG_OPTIONS[@]}"
fi
done
# release the build
if (( RELEASE )); then
pkgctl_release --repo "${pkgrepo}" "${RELEASE_OPTIONS[@]}"
fi
# reset common PKGBUILD variables
unset pkgbase pkgname arch pkgrepo source pkgver pkgrel validpgpkeys
popd >/dev/null
done
# update the binary package repo db as last action
if (( RELEASE )) && (( DB_UPDATE )); then
# shellcheck disable=2119
pkgctl_db_update
fi
}

View File

@@ -22,12 +22,12 @@ export BUILDTOOLVER=@buildtoolver@
# 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_REPO_SPEC_VERSION=0
export GIT_PACKAGING_NAMESPACE=bot-test/packages
export GIT_PACKAGING_NAMESPACE_ID=11233
export GIT_PACKAGING_URL_SSH="ssh://git@${GITLAB_HOST}:222/${GIT_PACKAGING_NAMESPACE}"
export GIT_PACKAGING_URL_HTTPS="https://${GITLAB_HOST}/${GIT_PACKAGING_NAMESPACE}"
export PACKAGING_REPO_RELEASE_HOST=repos.archlinux.org
export PACKAGING_REPO_RELEASE_HOST=repos.sandbox.archlinux.org
# check if messages are to be printed using color
if [[ -t 2 && "$TERM" != dumb ]]; then

View File

@@ -14,14 +14,31 @@ readonly XDG_DEVTOOLS_GITLAB_CONFIG="${XDG_DEVTOOLS_DIR}/gitlab.conf"
export GITLAB_TOKEN=""
load_devtools_config() {
if [[ ! -f "${XDG_DEVTOOLS_GITLAB_CONFIG}" ]]; then
GITLAB_TOKEN=""
# temporary permission fixup
if [[ -d "${XDG_DEVTOOLS_DIR}" ]]; then
chmod 700 "${XDG_DEVTOOLS_DIR}"
fi
if [[ -f "${XDG_DEVTOOLS_GITLAB_CONFIG}" ]]; then
chmod 600 "${XDG_DEVTOOLS_GITLAB_CONFIG}"
fi
if [[ -n "${DEVTOOLS_GITLAB_TOKEN}" ]]; then
GITLAB_TOKEN="${DEVTOOLS_GITLAB_TOKEN}"
return
fi
GITLAB_TOKEN=$(grep GITLAB_TOKEN "${XDG_DEVTOOLS_GITLAB_CONFIG}"|cut -d= -f2|cut -d\" -f2)
if [[ -f "${XDG_DEVTOOLS_GITLAB_CONFIG}" ]]; then
GITLAB_TOKEN=$(grep GITLAB_TOKEN "${XDG_DEVTOOLS_GITLAB_CONFIG}"|cut -d= -f2|cut -d\" -f2)
return
fi
GITLAB_TOKEN=""
}
save_devtools_config() {
mkdir -p "${XDG_DEVTOOLS_DIR}"
printf 'GITLAB_TOKEN="%s"\n' "${GITLAB_TOKEN}" > "${XDG_DEVTOOLS_GITLAB_CONFIG}"
# temporary permission fixup
chmod 700 "${XDG_DEVTOOLS_DIR}"
chmod 600 "${XDG_DEVTOOLS_GITLAB_CONFIG}"
(
umask 0077
mkdir -p "${XDG_DEVTOOLS_DIR}"
printf 'GITLAB_TOKEN="%s"\n' "${GITLAB_TOKEN}" > "${XDG_DEVTOOLS_GITLAB_CONFIG}"
)
}

View File

@@ -145,6 +145,11 @@ pkgctl_release() {
fi
fi
# TODO: REMOVE AFTER POC
if [[ ${repo} == community ]]; then
repo=extra
fi
if (( TESTING )); then
repo="${repo}-testing"
elif (( STAGING )); then

View File

@@ -32,8 +32,6 @@ pkgctl_repo_clone_usage() {
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 this help text
@@ -56,6 +54,9 @@ pkgctl_repo_clone() {
local CONFIGURE_OPTIONS=()
local pkgbases
# variables
local project_path
while (( $# )); do
case $1 in
-h|--help)
@@ -128,7 +129,8 @@ pkgctl_repo_clone() {
for pkgbase in "${pkgbases[@]}"; do
if [[ ! -d ${pkgbase} ]]; then
msg "Cloning ${pkgbase} ..."
remote_url="${GIT_REPO_BASE_URL}/${pkgbase}.git"
project_path=$(gitlab_project_name_to_path "${pkgbase}")
remote_url="${GIT_REPO_BASE_URL}/${project_path}.git"
git clone --origin origin "${remote_url}" "${pkgbase}"
else
warning "Skip cloning ${pkgbase}: Directory exists"

View File

@@ -27,11 +27,12 @@ pkgctl_repo_configure_usage() {
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.
The remote protocol is automatically determined from the author email
address by choosing SSH for all official packager identities and
read-only HTTPS otherwise.
OPTIONS
-u, --unprivileged Configure read-only repo without packager info as Git author
-h, --help Show this help text
EXAMPLES
@@ -39,16 +40,64 @@ pkgctl_repo_configure_usage() {
_EOF_
}
get_packager_name() {
local packager=$1
local packager_pattern="(.+) <(.+@.+)>"
local name
if [[ ! $packager =~ $packager_pattern ]]; then
return 1
fi
name=$(echo "${packager}"|sed -E "s/${packager_pattern}/\1/")
printf "%s" "${name}"
}
get_packager_email() {
local packager=$1
local packager_pattern="(.+) <(.+@.+)>"
local email
if [[ ! $packager =~ $packager_pattern ]]; then
return 1
fi
email=$(echo "${packager}"|sed -E "s/${packager_pattern}/\2/")
printf "%s" "${email}"
}
is_packager_name_valid() {
local packager_name=$1
if [[ -z ${packager_name} ]]; then
return 1
elif [[ ${packager_name} == "John Doe" ]]; then
return 1
elif [[ ${packager_name} == "Unknown Packager" ]]; then
return 1
fi
return 0
}
is_packager_email_official() {
local packager_email=$1
if [[ -z ${packager_email} ]]; then
return 1
elif [[ $packager_email =~ .+@archlinux.org ]]; then
return 0
fi
return 1
}
pkgctl_repo_configure() {
# options
local GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_SSH}
local UNPRIVILEGED=0
local PACKAGER_NAME=
local PACKAGER_EMAIL=
local GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_HTTPS}
local official=0
local proto=https
local paths=()
# variables
local path realpath pkgbase remote_url
local path realpath pkgbase remote_url project_path
local PACKAGER GPGKEY packager_name packager_email
while (( $# )); do
case $1 in
@@ -56,11 +105,6 @@ pkgctl_repo_configure() {
pkgctl_repo_configure_usage
exit 0
;;
-u|--unprivileged)
GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_HTTPS}
UNPRIVILEGED=1
shift
;;
--)
shift
break
@@ -85,34 +129,33 @@ pkgctl_repo_configure() {
fi
fi
# Load makepkg.conf variables to be available
# Load makepkg.conf variables to be available for packager identity
msg "Collecting packager identity from makepkg.conf"
# shellcheck disable=2119
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"
if [[ -n ${PACKAGER} ]]; then
if ! packager_name=$(get_packager_name "${PACKAGER}") || \
! packager_email=$(get_packager_email "${PACKAGER}"); then
die "invalid PACKAGER format '${PACKAGER}' in makepkg.conf"
fi
packager_pattern="(.+) <(.+@.+)>"
if [[ ! $PACKAGER =~ $packager_pattern ]]; then
die "Invalid Packager format '${PACKAGER}' in makepkg.conf"
if ! is_packager_name_valid "${packager_name}"; then
die "invalid PACKAGER '${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"
if is_packager_email_official "${packager_email}"; then
official=1
proto=ssh
GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_SSH}
fi
fi
msg "Collected packager settings"
msg2 "name : ${PACKAGER_NAME}"
msg2 "email : ${PACKAGER_EMAIL}"
msg2 "gpg-key : ${GPGKEY:-undefined}"
# TODO: print which protocol got auto detected, ssh https
msg2 "name : ${packager_name:-${YELLOW}undefined${ALL_OFF}}"
msg2 "email : ${packager_email:-${YELLOW}undefined${ALL_OFF}}"
msg2 "gpg-key : ${GPGKEY:-${YELLOW}undefined${ALL_OFF}}"
if [[ ${proto} == ssh ]]; then
msg2 "protocol: ${GREEN}${proto}${ALL_OFF}"
else
msg2 "protocol: ${YELLOW}${proto}${ALL_OFF}"
fi
for path in "${paths[@]}"; do
if ! realpath=$(realpath -e "${path}"); then
@@ -129,41 +172,52 @@ pkgctl_repo_configure() {
continue
fi
remote_url="${GIT_REPO_BASE_URL}/${pkgbase}.git"
if ! git -C "${path}" remote add origin "${remote_url}" &>/dev/null; then
git -C "${path}" remote set-url origin "${remote_url}"
pushd "${path}" >/dev/null
project_path=$(gitlab_project_name_to_path "${pkgbase}")
remote_url="${GIT_REPO_BASE_URL}/${project_path}.git"
if ! git remote add origin "${remote_url}" &>/dev/null; then
git remote set-url origin "${remote_url}"
fi
# move the master branch to main
if [[ $(git -C "${path}" symbolic-ref --short HEAD) == master ]]; then
git -C "${path}" branch --move main
git -C "${path}" config branch.main.merge refs/heads/main
if [[ $(git symbolic-ref --short HEAD) == master ]]; then
git branch --move main
git config branch.main.merge refs/heads/main
fi
git -C "${path}" config devtools.version "${GIT_REPO_SPEC_VERSION}"
git -C "${path}" config pull.rebase true
git -C "${path}" config branch.autoSetupRebase always
git -C "${path}" config branch.main.remote origin
git -C "${path}" config branch.main.rebase true
git config devtools.version "${GIT_REPO_SPEC_VERSION}"
git config pull.rebase true
git config branch.autoSetupRebase always
git config branch.main.remote origin
git config branch.main.rebase true
git -C "${path}" config transfer.fsckobjects true
git -C "${path}" config fetch.fsckobjects true
git -C "${path}" config receive.fsckobjects true
git config transfer.fsckobjects true
git config fetch.fsckobjects true
git config receive.fsckobjects true
if (( ! UNPRIVILEGED )); then
git -C "${path}" config user.name "${PACKAGER_NAME}"
git -C "${path}" config user.email "${PACKAGER_EMAIL}"
git -C "${path}" config commit.gpgsign true
if [[ -n $GPGKEY ]]; then
git -C "${path}" config user.signingKey "${GPGKEY}"
else
warning "Missing makepkg.conf configuration: GPGKEY"
fi
# setup author identity
if [[ -n ${packager_name} ]]; then
git config user.name "${packager_name}"
git config user.email "${packager_email}"
fi
# force gpg for official packagers
if (( official )); then
git config commit.gpgsign true
fi
# set custom pgp key from makepkg.conf
if [[ -n $GPGKEY ]]; then
git config commit.gpgsign true
git config user.signingKey "${GPGKEY}"
fi
if ! git ls-remote origin &>/dev/null; then
warning "configured remote origin may not exist, run:"
msg2 "pkgctl repo create ${pkgbase}"
fi
popd >/dev/null
done
}

24
src/lib/util/git.sh Normal file
View File

@@ -0,0 +1,24 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_UTIL_GIT_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_UTIL_GIT_SH=1
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
git_diff_tree() {
local commit=$1
local path=$2
git \
--no-pager \
diff \
--color=never \
--color-moved=no \
--unified=0 \
--no-prefix \
--no-ext-diff \
"${commit}" \
-- "${path}"
}

View File

@@ -0,0 +1,47 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_VERSION_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_VERSION_SH=1
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
source /usr/share/makepkg/util/message.sh
set -e
pkgctl_version_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS]
Shows the current version information of pkgctl
OPTIONS
-h, --help Show this help text
_EOF_
}
pkgctl_version_print() {
cat <<- _EOF_
pkgctl @buildtoolver@
_EOF_
}
pkgctl_version() {
while (( $# )); do
case $1 in
-h|--help)
pkgctl_version_usage
exit 0
;;
*)
die "invalid argument: %s" "$1"
;;
esac
done
pkgctl_version_print
}

View File

@@ -102,9 +102,9 @@ mapfile -t files < <(
printf "\t%s\n" "$temp"/*
} >&2 &&
makepkg_user_config="${XDG_CONFIG_HOME:-$HOME/.config}/pacman/makepkg.conf" &&
makepkg_config="/usr/share/devtools/makepkg.conf.d/'"${arch}"'.conf" &&
if [[ -f /usr/share/devtools/makepkg.conf.d/'"${repo}"'-'"${arch}"'.conf ]]; then
makepkg_config="/usr/share/devtools/makepkg.conf.d/'"${repo}"'-'"${arch}"'.conf"
makepkg_config="/usr/share/devtools/makepkg-'"${arch}"'.conf" &&
if [[ -f /usr/share/devtools/makepkg-'"${repo}"'-'"${arch}"'.conf ]]; then
makepkg_config="/usr/share/devtools/makepkg-'"${repo}"'-'"${arch}"'.conf"
fi &&
makepkg --config <(cat "${makepkg_user_config}" "${makepkg_config}" 2>/dev/null) --packagelist &&
printf "%s\n" "${temp}/PKGBUILD"

View File

@@ -20,10 +20,12 @@ usage() {
COMMANDS
auth Authenticate with services like GitLab
build Build packages inside a clean chroot
db Pacman database modification for packge update, move etc
diff Compare package files using different modes
release Release step to commit, tag and upload build artifacts
repo Manage Git packaging repositories and their configuration
version Show pkgctl version information
OPTIONS
-h, --help Show this help text
@@ -46,6 +48,14 @@ while (( $# )); do
usage
exit 0
;;
build)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/build/build.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/build/build.sh
pkgctl_build "$@"
exit 0
;;
repo)
_DEVTOOLS_COMMAND+=" $1"
shift
@@ -84,6 +94,14 @@ while (( $# )); do
pkgctl_release "$@"
exit 0
;;
version|--version|-V)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/version/version.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/version/version.sh
pkgctl_version "$@"
exit 0
;;
*)
die "invalid command: %s" "$1"
;;

View File

@@ -1,114 +0,0 @@
#!/bin/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# This script rebuilds a list of packages in order
# and reports anything that fails
#
# Due to sudo usage, it is recommended to allow makechrootpkg
# to be run with NOPASSWD in your sudoers file
#
# FIXME
# Currently uses $(pwd)/rebuilds as the directory for rebuilding...
# TODO make this work for community too
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
# shellcheck source=src/lib/common.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
if (( $# < 1 )); then
printf 'Usage: %s <chrootdir> <packages to rebuild>\n' "$(basename "${BASH_SOURCE[0]}")"
printf ' example: %s ~/chroot readline bash foo bar baz\n' "$(basename "${BASH_SOURCE[0]}")"
exit 1
fi
# Source makepkg.conf; fail if it is not found
if [[ -r '/etc/makepkg.conf' ]]; then
# shellcheck source=config/makepkg/x86_64.conf
source '/etc/makepkg.conf'
else
die '/etc/makepkg.conf not found!'
fi
# Source user-specific makepkg.conf overrides
if [[ -r "${XDG_CONFIG_HOME:-$HOME/.config}/pacman/makepkg.conf" ]]; then
# shellcheck source=/dev/null
source "${XDG_CONFIG_HOME:-$HOME/.config}/pacman/makepkg.conf"
elif [[ -r "$HOME/.makepkg.conf" ]]; then
# shellcheck source=/dev/null
source "$HOME/.makepkg.conf"
fi
bump_pkgrel() {
# Get the current pkgrel from git and update the working copy with it
# This prevents us from incrementing out of control :)
pbuild='.svn/text-base/PKGBUILD.svn-base'
oldrel=$(grep 'pkgrel=' $pbuild | cut -d= -f2)
#remove decimals
rel=${oldrel%%.*}
newrel=$((rel + 1))
sed -i "s/pkgrel=$oldrel/pkgrel=$newrel/" PKGBUILD
}
pkg_from_pkgbuild() {
# we want the sourcing to be done in a subshell so we don't pollute our current namespace
export CARCH PKGEXT
# shellcheck source=contrib/makepkg/PKGBUILD.proto
(source PKGBUILD; echo "$pkgname-$pkgver-$pkgrel-$CARCH$PKGEXT")
}
chrootdir="$1"; shift
pkgs=("$@")
SVNPATH='svn+ssh://repos.archlinux.org/srv/repos/svn-packages/svn'
msg "Work will be done in %s" "$(pwd)/rebuilds"
REBUILD_ROOT="$(pwd)/rebuilds"
mkdir -p "$REBUILD_ROOT"
cd "$REBUILD_ROOT"
/usr/bin/svn co -N $SVNPATH
FAILED=""
for pkg in "${pkgs[@]}"; do
cd "$REBUILD_ROOT/svn-packages"
msg2 "Building '%s'" "$pkg"
/usr/bin/svn update "$pkg"
if [[ ! -d "$pkg/trunk" ]]; then
FAILED="$FAILED $pkg"
warning "%s does not exist in SVN" "$pkg"
continue
fi
cd "$pkg/trunk/"
bump_pkgrel
if ! sudo makechrootpkg -u -d -r "$chrootdir" -- --noconfirm; then
FAILED="$FAILED $pkg"
error "%s Failed!" "$pkg"
else
pkgfile=$(pkg_from_pkgbuild)
if [[ -e $pkgfile ]]; then
msg2 "%s Complete" "$pkg"
else
FAILED="$FAILED $pkg"
error "%s Failed, no package built!" "$pkg"
fi
fi
done
cd "$REBUILD_ROOT"
if [[ -n $FAILED ]]; then
msg 'Packages failed:'
for pkg in $FAILED; do
msg2 "%s" "$pkg"
done
fi
msg 'SVN pkgbumps in svn-packages/ - commit when ready'