Compare commits

...

18 Commits

Author SHA1 Message Date
Levente Polyak
e678b901b2 wip: shell integration to allow controlling the working directory 2023-07-25 13:29:38 +02:00
Levente Polyak
b088dac219 wip: workspace
Co-Authored-By: Christian Heusel <christian@heusel.eu>
2023-07-25 13:29:16 +02:00
Levente Polyak
a07df0beea chore(release): version v1.0.2 2023-05-28 01:22:09 +02:00
Levente Polyak
c7d627165f chore(release): adjust Makefile for new release schema
Ask for the next release version and automatically create a signed tag.
Furthermore add a simple release target to call glab for uploading the
required artifacts.
2023-05-28 01:21:40 +02:00
Antonio Rojas
e47035e74d chore(build): improve error wording if no package repo could be detected
Not being in any official repo does not necessarily mean this is a new
package. One could simply be building an AUR or custom local package.
Make the message less confusing in such case.
2023-05-27 22:18:04 +02:00
Daniel M. Capella
9b11b16a7e chore(doc): remove duplicate subcommand from example help text 2023-05-27 21:44:09 +02:00
Levente Polyak
3283b2ca59 fix(commitpkg): only force existing files to be under version control
Before porting commitpkg to Git, the code has checked the SVN status for
none commited files. During the port this has changed by straight
checking for any passed files if they were under version control or not.

In general the whole logic is very brittle as variables are searched by
regex and directly passed to eval while ignoring any function scoping.
This leads to missing files when they reference the $pkgname inside a
package function but also provide wrong ones when eval simply returns
the first $pkgname while ignoring and function scopes.

In the future this should completely be replaces by .SRCINFO processing.

Fixes #145

Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
2023-05-27 01:53:45 +02:00
Toolybird
71cb9e97bb fix(archroot): preserve original args for check_root before discarding
arch-nspawn, mkarchroot, makerepropkg all call "shift" after getopts
processing. Save the original args and pass on to check_root to prevent
options being discarded.

Fixes 41d4624879
Fixes #149

Signed-off-by: Toolybird <toolybird@tuta.io>
Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
2023-05-26 01:06:14 +02:00
Levente Polyak
1b808b8e32 chore(release): version v1.0.1 2023-05-24 03:19:26 +02:00
Chih-Hsuan Yen
e4c40a9802 fix(completion): incorporate repo layout into offload-build completion
Use new repo names for build targets. This follows /usr/bin/*-build
links other than x86_64_v3 ones.
2023-05-24 03:06:03 +02:00
Levente Polyak
a08bc2acf4 feature(clone): add protocol option to force cloning over HTTPS
This is a rather quick and simple implementation to override the current
logic and force clone with HTTPS. Allowing to explicitly clone over HTTPS
is currently required to unblock reproducible builds where no ssh keys
and GitLab user accounts are set up as of now. Hence this quick solution
comes into play to mitigate the regression on reproducible builds
builders.

Revisit the overall auto detection and protocol logic approach for a
later release related to some ideas floating around in pending
merge-requests.

Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
2023-05-24 02:50:08 +02:00
Morten Linderud
f11cb9018e feature(commitpkg): auto generate .SRCINFO if present
This currently makes .SRCINFO files opt-in and helps to keep the file up
to date if already present.

Signed-off-by: Morten Linderud <foxboron@archlinux.org>
2023-05-23 03:03:39 +02:00
Jan Alexander Steffens (heftig)
d759eadb50 fix(diffpkg): Fix scoping of DIFFOPTIONS when comparing split pkgs
`diff_pkgs` needs to use a local variable for its options, otherwise
they will accumulate for each package diffed.

Whem comparing split packages this lead to earlier mutated DIFFOPTIONS
containing too many labels which resulted in a failure.
2023-05-23 02:20:03 +02:00
Jan Alexander Steffens (heftig)
1c399778f9 fix(commitpkg): reliably check tree status regardless of configuration
Check git status --porcelain, not --short.

`--short` is influenced by user configuration like `status.branch`
making it non-empty even on a clean tree. Use `--porcelain` to avoid
this.
2023-05-23 01:47:00 +02:00
Levente Polyak
edc14ef19c Version 1.0.0 2023-05-21 12:25:44 +02:00
Levente Polyak
6ce666a166 feature(parallel): run up to N jobs in parallel for repo clone/configure
Run up to N jobs in parallel. By default the number of jobs is equal to the
number of available processing units. For sequential processing this option
needs to be passed with 1.

Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
2023-05-20 16:12:45 +02:00
Levente Polyak
bf61b8472a chore(archroot): force build chroot recreation to adapt new configs
Bumping the chroot version will result in the chroots checking against
the local version and force recreation in case they do not match.

Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
2023-05-20 15:11:16 +02:00
Levente Polyak
80a8cdcba2 chore(git): use default ssh port 22 url scheme
We only need to specifically use ssh:// protocol prefix if we want to
specify a special port. As we moved to support pulling directly over
port 22 from out GitLab instance we can change the url scheme to the
simple variant.

Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
2023-05-20 12:20:36 +02:00
33 changed files with 1481 additions and 41 deletions

View File

@@ -1,6 +1,6 @@
SHELL=/bin/bash
V=20230307
V=1.0.2
BUILDTOOLVER ?= $(V)
PREFIX = /usr/local
@@ -17,6 +17,7 @@ LIBRARY = $(addprefix $(BUILDDIR)/,$(patsubst src/%,%,$(patsubst %.in,%,$(LIBRAR
MAKEPKG_CONFIGS=$(wildcard config/makepkg/*)
PACMAN_CONFIGS=$(wildcard config/pacman/*)
SETARCH_ALIASES = $(wildcard config/setarch-aliases.d/*)
INIT_SCRIPTS = $(wildcard config/init.d/*)
MANS = $(addprefix $(BUILDDIR)/,$(patsubst %.asciidoc,%,$(wildcard doc/man/*.asciidoc)))
COMMITPKG_LINKS = \
@@ -89,6 +90,7 @@ endef
$(eval $(call buildInScript,build/bin,src/,.in,755))
$(eval $(call buildInScript,build/lib,src/lib/,,644))
$(eval $(call buildInScript,build/init.d,config/init.d/,,644))
$(foreach completion,$(wildcard contrib/completion/*),$(eval $(call buildInScript,build/$(completion),$(completion)/,.in,444)))
$(BUILDDIR)/doc/man/%: doc/man/%.asciidoc doc/asciidoc.conf doc/man/include/footer.asciidoc
@@ -100,6 +102,8 @@ conf:
@install -d $(BUILDDIR)/makepkg.conf.d $(BUILDDIR)/pacman.conf.d
@cp -a $(MAKEPKG_CONFIGS) $(BUILDDIR)/makepkg.conf.d
@cp -a $(PACMAN_CONFIGS) $(BUILDDIR)/pacman.conf.d
@install -d $(BUILDDIR)/init.d
@cp -a $(INIT_SCRIPTS) $(BUILDDIR)/init.d
clean:
rm -rf $(BUILDDIR)
@@ -109,12 +113,14 @@ install: all
install -dm0755 $(DESTDIR)$(DATADIR)/setarch-aliases.d
install -dm0755 $(DESTDIR)$(DATADIR)/makepkg.conf.d
install -dm0755 $(DESTDIR)$(DATADIR)/pacman.conf.d
install -dm0755 $(DESTDIR)$(DATADIR)/init.d
install -m0755 ${BINPROGS} $(DESTDIR)$(PREFIX)/bin
install -dm0755 $(DESTDIR)$(DATADIR)/lib
cp -ra $(BUILDDIR)/lib/* $(DESTDIR)$(DATADIR)/lib
for conf in $(notdir $(MAKEPKG_CONFIGS)); do install -Dm0644 $(BUILDDIR)/makepkg.conf.d/$$conf $(DESTDIR)$(DATADIR)/makepkg.conf.d/$${conf##*/}; done
for conf in $(notdir $(PACMAN_CONFIGS)); do install -Dm0644 $(BUILDDIR)/pacman.conf.d/$$conf $(DESTDIR)$(DATADIR)/pacman.conf.d/$${conf##*/}; done
for a in ${SETARCH_ALIASES}; do install -m0644 $$a -t $(DESTDIR)$(DATADIR)/setarch-aliases.d; done
for f in $(notdir ${INIT_SCRIPTS}); do install -m0644 $(BUILDDIR)/init.d/$$f -t $(DESTDIR)$(DATADIR)/init.d; done
for l in ${COMMITPKG_LINKS}; do ln -sf commitpkg $(DESTDIR)$(PREFIX)/bin/$$l; done
for l in ${ARCHBUILD_LINKS}; do ln -sf archbuild $(DESTDIR)$(PREFIX)/bin/$$l; done
ln -sf find-libdeps $(DESTDIR)$(PREFIX)/bin/find-libprovides
@@ -132,6 +138,7 @@ uninstall:
for conf in $(notdir $(MAKEPKG_CONFIGS)); do rm -f $(DESTDIR)$(DATADIR)/makepkg.conf.d/$${conf##*/}; done
for conf in $(notdir $(PACMAN_CONFIGS)); do rm -f $(DESTDIR)$(DATADIR)/pacman.conf.d/$${conf##*/}; done
for f in $(notdir $(SETARCH_ALIASES)); do rm -f $(DESTDIR)$(DATADIR)/setarch-aliases.d/$$f; done
for f in $(notdir $(INIT_SCRIPTS)); do rm -f $(DESTDIR)$(DATADIR)/init.d/$$f; done
for l in ${COMMITPKG_LINKS}; do rm -f $(DESTDIR)$(PREFIX)/bin/$$l; done
for l in ${ARCHBUILD_LINKS}; do rm -f $(DESTDIR)$(PREFIX)/bin/$$l; done
rm -f $(DESTDIR)$(PREFIX)/share/bash-completion/completions/devtools
@@ -145,19 +152,20 @@ uninstall:
$(DESTDIR)$(DATADIR)/pacman.conf.d \
$(DESTDIR)$(DATADIR)
TODAY=$(shell date +"%Y%m%d")
tag:
@sed -E "s|^V=[0-9]{8}|V=$(TODAY)|" -i Makefile
@git commit --gpg-sign --message "Version $(TODAY)" Makefile
@git tag --sign --message "Version $(TODAY)" $(TODAY)
@echo "current version: v$(V)"
@read -r -p "tag version: v" VERSION && \
sed -E "s|^V=.+|V=$$VERSION|" -i Makefile && \
git commit --gpg-sign --message "chore(release): version v$$VERSION" Makefile && \
git tag --sign --message "Version v$$VERSION" v$$VERSION
release: dist
glab release create v$(RELEASE) devtools-$(RELEASE).tar.gz*
dist:
git archive --format=tar --prefix=devtools-$(V)/ $(V) | gzip > devtools-$(V).tar.gz
git archive --format=tar --prefix=devtools-$(V)/ v$(V) | gzip > devtools-$(V).tar.gz
gpg --detach-sign --use-agent devtools-$(V).tar.gz
upload:
scp devtools-$(V).tar.gz devtools-$(V).tar.gz.sig repos.archlinux.org:/srv/ftp/other/devtools/
check: $(BINPROGS_SRC) $(LIBRARY_SRC) contrib/completion/bash/devtools.in config/makepkg/x86_64.conf contrib/makepkg/PKGBUILD.proto
shellcheck $^

View File

@@ -43,6 +43,7 @@ will automatically build the project and proxy all calls to the local build dire
- coreutils
- diffutils
- findutils
- fzf
- grep
- jq
- ncurses

22
config/init.d/init.bash Normal file
View File

@@ -0,0 +1,22 @@
function pkgctl {
local cmd cmd_file code
cmd_file=$(mktemp --tmpdir "pkgctl.outcmd.XXXXXXXXXX")
if PKGCTL_OUTCMD="${cmd_file}" command pkgctl "$@"; then
cmd=$(<"$cmd_file")
command rm -f "$cmd_file"
eval "$cmd"
else
code=$?
command rm -f "$cmd_file"
return "$code"
fi
}
#\builtin alias pkgctl=__pkgctl
# =============================================================================
#
# To initialize pkgctl, add this to your configuration (usually ~/.zshrc):
#
# eval "$(pkgctl init bash)"

28
config/init.d/init.zsh Normal file
View File

@@ -0,0 +1,28 @@
# This script was automatically generated by pkgctl
# This function starts pkgctl and executes the command
# it produces, if any.
# It's needed because some shell commands, like `cd`,
# have no useful effect if executed in a subshell.
function pkgctl {
local cmd cmd_file code
cmd_file=$(mktemp --tmpdir "pkgctl.outcmd.XXXXXXXXXX")
if PKGCTL_OUTCMD="${cmd_file}" command pkgctl "$@"; then
cmd=$(<"$cmd_file")
command rm -f "$cmd_file"
eval "$cmd"
else
code=$?
command rm -f "$cmd_file"
return "$code"
fi
}
#\builtin alias pkgctl=__pkgctl
#\compdef __pkgctl=pkgctl
# =============================================================================
#
# To initialize pkgctl, add this to your configuration (usually ~/.zshrc):
#
# eval "$(pkgctl init zsh)"

View File

@@ -135,6 +135,7 @@ _pkgctl_cmds=(
release
repo
version
workspace
)
_pkgctl_args=(
-V --version
@@ -265,20 +266,30 @@ _pkgctl_repo_cmds=(
_pkgctl_repo_clone_args=(
-m --maintainer
--protocol
--switch
-u --unprivileged
--universe
-j --jobs
-h --help
)
_pkgctl_repo_clone_args__maintainer_opts() { :; }
_pkgctl_repo_clone_args_m_opts() { _pkgctl_repo_clone_args__maintainer_opts; }
_pkgctl_repo_clone_args__protocol_opts() { _devtools_completions_protocol; }
_pkgctl_repo_clone_args__switch_opts() { :; }
_pkgctl_repo_clone_args__jobs_opts() { :; }
_pkgctl_repo_clone_args_j_opts() { _pkgctl_repo_clone_args__jobs_opts; }
_pkgctl_repo_clone_opts() { _devtools_completions_all_packages; }
_pkgctl_repo_configure_args=(
--protocol
-j --jobs
-h --help
)
_pkgctl_repo_configure_args__protocol_opts() { _devtools_completions_protocol; }
_pkgctl_repo_configure_args__jobs_opts() { :; }
_pkgctl_repo_configure_args_j_opts() { _pkgctl_repo_clone_args__jobs_opts; }
_pkgctl_repo_configure_opts() { _filedir -d; }
@@ -312,6 +323,103 @@ _pkgctl_repo_web_args=(
_pkgctl_repo_web_opts() { _filedir -d; }
_pkgctl_workspace_cmds=(
add
cd
list
remove
show
switch
)
_pkgctl_workspace_add_args=(
-f --force
-s --switch
-c --cd
-h --help
)
_pkgctl_workspace_add_opts() {
local subcommand args
subcommand=(workspace add)
args=$(__pkgctl_word_count_after_subcommand "${subcommand[@]}")
if (( args == 0 )); then
:
elif (( args == 1 )); then
_filedir -d;
fi
}
_pkgctl_workspace_cd_args=(
-h --help
)
_pkgctl_workspace_cd_opts() {
local subcommand args
subcommand=(workspace cd)
args=$(__pkgctl_word_count_after_subcommand "${subcommand[@]}")
if (( args == 0 )); then
_devtools_completions_all_workspaces
fi
}
_pkgctl_workspace_list_args=(
-n --name
-p --path
-l --local
-h --help
)
_pkgctl_workspace_remove_args=(
-h --help
)
_pkgctl_workspace_remove_opts() {
local subcommand args
subcommand=(workspace remove)
args=$(__pkgctl_word_count_after_subcommand "${subcommand[@]}")
if (( args == 0 )); then
_devtools_completions_local_workspaces
fi
}
_pkgctl_workspace_show_args=(
-n --name
-p --path
-h --help
)
_pkgctl_workspace_show_opts() {
local subcommand args
subcommand=(workspace show)
args=$(__pkgctl_word_count_after_subcommand "${subcommand[@]}")
if (( args == 0 )); then
_devtools_completions_all_workspaces
fi
}
_pkgctl_workspace_switch_args=(
-i --interactive
-c --cd
-h --help
)
_pkgctl_workspace_switch_opts() {
local subcommand args
subcommand=(workspace switch)
args=$(__pkgctl_word_count_after_subcommand "${subcommand[@]}")
if (( args == 0 )); then
_devtools_completions_all_workspaces
fi
}
_pkgctl_diff_args=(
-l --list
-d --diffoscope
@@ -357,6 +465,15 @@ _devtools_completions_build_repo() {
_devtools_completions_all_packages() {
mapfile -t COMPREPLY < <(compgen -W "$(pacman -Sql)" -- "$cur")
}
_devtools_completions_all_workspaces() {
mapfile -t COMPREPLY < <(compgen -W "$(pkgctl workspace list --name)" -- "$cur")
}
_devtools_completions_local_workspaces() {
mapfile -t COMPREPLY < <(compgen -W "$(pkgctl workspace list --local --name)" -- "$cur")
}
_devtools_completions_protocol() {
mapfile -t COMPREPLY < <(compgen -W "https" -- "$cur")
}
__devtools_complete() {
local service=$1

View File

@@ -108,13 +108,17 @@ _pkgctl_repo_switch_args=(
_pkgctl_repo_clone_args=(
'(-m --maintainer=)'{-m,--maintainer=}'[Clone all packages of the named maintainer]:maintainer:'
'--protocol[Clone the repository over https]:proto:(https)'
'--switch=[Switch the current working tree to a specified version]'
'--universe[Clone all existing packages, useful for cache warming]'
'(-j --jobs)'{-j,--jobs}'[Run up to N jobs in parallel (default: number of processing units)]:jobs:'
'(-h --help)'{-h,--help}'[Display usage]'
'*:packages:_devtools_completions_all_packages'
)
_pkgctl_repo_configure_args=(
'--protocol[Configure remote url to use https]:proto:(https)'
'(-j --jobs)'{-j,--jobs}'[Run up to N jobs in parallel (default: number of processing units)]:jobs:'
'(-h --help)'{-h,--help}'[Display usage]'
'*:git_dir:_files -/'
)
@@ -130,6 +134,56 @@ _pkgctl_repo_web_args=(
'*:git_dir:_files -/'
)
_pkgctl_workspace_cmds=(
"pkgctl workspace command"
"add[TODO a]"
"cd[TODO a]"
"list[TODO a]"
"remove[TODO a]"
"show[TODOa a]"
"switch[TODO a]"
)
_pkgctl_workspace_add_args=(
'(-f --force)'{-f,--force}'[TODO name]'
'(-s --switch)'{-s,--switch}'[TODO path]'
'(-c --cd)'{-c,--cd}'[TODO path]'
'(-h --help)'{-h,--help}'[Display usage]'
'1:workspace'
'2:path:_files -/'
)
_pkgctl_workspace_cd_args=(
'(-h --help)'{-h,--help}'[Display usage]'
'1:workspace:_devtools_completions_all_workspaces'
)
_pkgctl_workspace_list_args=(
'(-n --name)'{-n,--name}'[TODO name]'
'(-p --path)'{-p,--path}'[TODO path]'
'(-l --local)'{-l,--local}'[TODO path]'
'(-h --help)'{-h,--help}'[Display usage]'
)
_pkgctl_workspace_remove_args=(
'(-h --help)'{-h,--help}'[Display usage]'
'1:workspace:_devtools_completions_local_workspaces'
)
_pkgctl_workspace_show_args=(
'(-n --name)'{-n,--name}'[TODO name]'
'(-p --path)'{-p,--path}'[TODO path]'
'(-h --help)'{-h,--help}'[Display usage]'
'1:workspace:_devtools_completions_all_workspaces'
)
_pkgctl_workspace_switch_args=(
'(-i --interactive)'{-i,--interactive}'[TODO]'
'(-c --cd)'{-c,--cd}'[TODO]'
'(-h --help)'{-h,--help}'[Display usage]'
'1:workspace:_devtools_completions_all_workspaces'
)
_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(.)"'
@@ -233,6 +287,18 @@ _devtools_completions_all_packages() {
compadd - "${(@)packages}"
}
_devtools_completions_all_workspaces() {
typeset -U workspaces
workspaces=($(_call_program workspaces pkgctl workspace list --name))
compadd - "${(@)workspaces}"
}
_devtools_completions_local_workspaces() {
typeset -U local_workspaces
local_workspaces=($(_call_program local_workspaces pkgctl workspace list --local --name))
compadd - "${(@)local_workspaces}"
}
_pkgctl_cmds=(
"pkgctl command"
"auth[Authenticate with services like GitLab]"
@@ -242,6 +308,7 @@ _pkgctl_cmds=(
"release[Release step to commit, tag and upload build artifacts]"
"repo[Manage Git packaging repositories and their configuration]"
"version[Show pkgctl version information]"
"workspace[TODO]"
)
_pkgctl_args=(

View File

@@ -25,6 +25,9 @@ Options
*-m, --maintainer* 'NAME'::
Clone all packages of the named maintainer
*--protocol* 'https'::
Clone the repository over https
*--universe*::
Clone all existing packages, useful for cache warming
@@ -32,6 +35,11 @@ Options
Switch to a specified version. The working tree and the index are updated to
match the version.
*-j, --jobs* 'N'::
Run up to N jobs in parallel. By default the number of jobs is equal to the
number of available processing units. For sequential processing this option
needs to be passed with 1.
*-h, --help*::
Show a help text

View File

@@ -25,6 +25,14 @@ read-only HTTPS otherwise.
Options
-------
*--protocol* 'https'::
Configure remote url to use https
*-j, --jobs* 'N'::
Run up to N jobs in parallel. By default the number of jobs is equal to the
number of available processing units. For sequential processing this option
needs to be passed with 1.
*-h, --help*::
Show a help text

View File

@@ -32,6 +32,9 @@ usage() {
exit 1
}
# save all args for check_root
orig_args=("$@")
while getopts 'hC:M:c:f:s' arg; do
case "$arg" in
C) pac_conf="$OPTARG" ;;
@@ -46,7 +49,7 @@ done
shift $((OPTIND - 1))
(( $# < 1 )) && die 'You must specify a directory.'
check_root "" "${BASH_SOURCE[0]}" "$@"
check_root "" "${BASH_SOURCE[0]}" "${orig_args[@]}"
working_dir=$(readlink -f "$1")
shift 1

View File

@@ -129,6 +129,10 @@ done
# assert that they really are controlled by git
if (( ${#needsversioning[*]} )); then
for file in "${needsversioning[@]}"; do
# skip none existing files
if [[ ! -f "${file}" ]]; then
continue
fi
if ! git ls-files --error-unmatch "$file"; then
die "%s is not under version control" "$file"
fi
@@ -173,7 +177,15 @@ done
# check for PKGBUILD standards
check_pkgbuild_validity
if [[ -n $(git status --short --untracked-files=no) ]]; then
# auto generate .SRCINFO if present
if [[ -f .SRCINFO ]]; then
stat_busy 'Generating .SRCINFO'
makepkg --printsrcinfo > .SRCINFO
git add .SRCINFO
stat_done
fi
if [[ -n $(git status --porcelain --untracked-files=no) ]]; then
stat_busy 'Staging files'
for f in $(git ls-files --modified); do
git add "$f"

View File

@@ -215,7 +215,8 @@ diff_pkgs() {
[[ -f $oldpkg ]] || die "No such file: %s" "${oldpkg}"
[[ -f $newpkg ]] || die "No such file: %s" "${newpkg}"
DIFFOPTIONS+=(--label "${oldpkg}" --label "${newpkg}")
local -a diffoptions
diffoptions=("${DIFFOPTIONS[@]}" --label "${oldpkg}" --label "${newpkg}")
if (( TARLIST )); then
tar_list "$oldpkg" > "$TMPDIR/old"
@@ -236,7 +237,7 @@ diff_pkgs() {
# Resolve dynamic auto width one we know the content to diff
if [[ $DIFFWIDTH == --width=auto ]]; then
AUTOLENGTH=$(file_diff_columns "$TMPDIR/old" "$TMPDIR/new")
DIFFOPTIONS+=("--width=${AUTOLENGTH}")
diffoptions+=("--width=${AUTOLENGTH}")
fi
# Print a header for side-by-side view as it lacks labels
@@ -244,7 +245,7 @@ diff_pkgs() {
printf -- "--- %s\n+++ %s\n" "${oldpkg}" "${newpkg}"
fi
diff "${DIFFOPTIONS[@]}" "$TMPDIR/old" "$TMPDIR/new"
diff "${diffoptions[@]}" "$TMPDIR/old" "$TMPDIR/new"
fi
if (( DIFFOSCOPE )); then

View File

@@ -4,7 +4,7 @@
:
# shellcheck disable=2034
CHROOT_VERSION='v4'
CHROOT_VERSION='v5'
##
# usage : check_root $keepenv

View File

@@ -16,6 +16,8 @@ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/release.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/workspace/util.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/workspace/util.sh
# shellcheck source=src/lib/valid-repos.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-repos.sh
# shellcheck source=src/lib/valid-tags.sh
@@ -278,6 +280,8 @@ pkgctl_build() {
die "Invalid repository target: %s" "${REPO}"
fi
enter_workspace
for path in "${paths[@]}"; do
pushd "${path}" >/dev/null
@@ -298,7 +302,7 @@ pkgctl_build() {
die 'failed to get pacman repo'
fi
if [[ -z "${pkgrepo}" ]]; then
die 'unknown repo, please specify --repo for new packages'
die 'unknown repo, specify --repo for packages not currently in any official repo'
fi
fi

View File

@@ -25,12 +25,12 @@ 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_SSH="git@${GITLAB_HOST}:${GIT_PACKAGING_NAMESPACE}"
export GIT_PACKAGING_URL_HTTPS="https://${GITLAB_HOST}/${GIT_PACKAGING_NAMESPACE}"
export PACKAGING_REPO_RELEASE_HOST=repos.archlinux.org
# check if messages are to be printed using color
if [[ -t 2 && "$TERM" != dumb ]]; then
if [[ -t 2 && "$TERM" != dumb ]] || [[ ${DEVTOOLS_COLOR} == always ]]; then
colorize
else
# shellcheck disable=2034

58
src/lib/init/init.sh Normal file
View File

@@ -0,0 +1,58 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_INIT_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_INIT_SH=1
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
set -e
pkgctl_init_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS] [SHELL]
TODO
eval "\$(pkgctl init bash)"
OPTIONS
-h, --help Show this help text
EXAMPLES
$ ${COMMAND} clone libfoo linux libbar
_EOF_
}
pkgctl_init() {
if (( $# < 1 )); then
pkgctl_init_usage
exit 0
fi
# option checking
while (( $# )); do
case $1 in
-h|--help)
pkgctl_init_usage
exit 0
;;
zsh)
cat "${_DEVTOOLS_LIBRARY_DIR}"/init.d/init.zsh
shift
;;
bash)
cat "${_DEVTOOLS_LIBRARY_DIR}"/init.d/init.bash
shift
;;
-*)
die "invalid argument: %s" "$1"
;;
*)
die "invalid command: %s" "$1"
;;
esac
done
}

View File

@@ -10,6 +10,8 @@ _DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/db/update.sh
# shellcheck source=src/lib/util/pacman.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/pacman.sh
# shellcheck source=src/lib/workspace/util.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/workspace/util.sh
# shellcheck source=src/lib/valid-repos.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-repos.sh
@@ -130,6 +132,8 @@ pkgctl_release() {
die "Invalid repository target: %s" "${REPO}"
fi
enter_workspace
for path in "${PKGBASES[@]}"; do
pushd "${path}" >/dev/null
pkgbase=$(basename "${path}")

View File

@@ -27,6 +27,7 @@ pkgctl_repo_usage() {
without SSH access using read-only HTTPS.
COMMANDS
cd Change current working directory into the repository
clone Clone a package repository
configure Configure a clone according to distro specs
create Create a new GitLab package repository
@@ -59,6 +60,14 @@ pkgctl_repo() {
pkgctl_repo_usage
exit 0
;;
cd)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/repo/cd.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/repo/cd.sh
pkgctl_repo_cd "$@"
exit 0
;;
clone)
_DEVTOOLS_COMMAND+=" $1"
shift

63
src/lib/repo/cd.sh Normal file
View File

@@ -0,0 +1,63 @@
#!/bin/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_REPO_CD_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_REPO_CD_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/workspace/util.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/workspace/util.sh
set -e
pkgctl_repo_cd_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS] [PKGBASE]...
OPTIONS
-h, --help Show this help text
EXAMPLES
$ ${COMMAND}
_EOF_
}
pkgctl_repo_cd() {
# options
local pkgbase
# variables
local path
local workspace
while (( $# )); do
case $1 in
-h|--help)
pkgctl_repo_cd_usage
exit 0
;;
-*)
die "invalid argument: %s" "$1"
;;
*)
pkgbase=$1
break
;;
esac
done
if [[ -z ${PKGCTL_OUTCMD} ]]; then
die "setup shell"
fi
workspace=$(get_active_workspace_name)
path=$(get_workspace_path_from_name "${workspace}")
printf "builtin cd -- %s\n" "${path}/${pkgbase}" >> "${PKGCTL_OUTCMD}"
}

View File

@@ -12,6 +12,8 @@ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/api/gitlab.sh
# shellcheck source=src/lib/repo/configure.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/repo/configure.sh
# shellcheck source=src/lib/workspace/util.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/workspace/util.sh
source /usr/share/makepkg/util/message.sh
@@ -26,14 +28,16 @@ pkgctl_repo_clone_usage() {
Clone Git packaging repositories from the canonical namespace.
The configure command is subsequently invoked to synchronize the distro
specs and makepkg.conf settings. The unprivileged option can be used
specs and makepkg.conf settings. The protocol option can be used
for cloning packaging repositories without SSH access using read-only
HTTPS.
OPTIONS
-m, --maintainer=NAME Clone all packages of the named maintainer
--protocol https Clone the repository over https
--switch VERSION Switch the current working tree to a specified version
--universe Clone all existing packages, useful for cache warming
-j, --jobs N Run up to N jobs in parallel (default: $(nproc))
-h, --help Show this help text
EXAMPLES
@@ -55,9 +59,11 @@ pkgctl_repo_clone() {
local MAINTAINER=
local VERSION=
local CONFIGURE_OPTIONS=()
local pkgbases
local jobs=
jobs=$(nproc)
# variables
local command=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
local project_path
while (( $# )); do
@@ -66,11 +72,21 @@ pkgctl_repo_clone() {
pkgctl_repo_clone_usage
exit 0
;;
-u|--unprivileged)
--protocol=https)
GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_HTTPS}
CONFIGURE_OPTIONS+=("$1")
shift
;;
--protocol)
(( $# <= 1 )) && die "missing argument for %s" "$1"
if [[ $2 == https ]]; then
GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_HTTPS}
else
die "unsupported protocol: %s" "$2"
fi
CONFIGURE_OPTIONS+=("$1" "$2")
shift 2
;;
-m|--maintainer)
(( $# <= 1 )) && die "missing argument for %s" "$1"
MAINTAINER="$2"
@@ -97,6 +113,11 @@ pkgctl_repo_clone() {
CLONE_ALL=1
shift
;;
-j|--jobs)
(( $# <= 1 )) && die "missing argument for %s" "$1"
jobs=$2
shift 2
;;
--)
shift
break
@@ -142,12 +163,33 @@ pkgctl_repo_clone() {
stat_done
fi
# parallelization
if [[ ${jobs} != 1 ]] && (( ${#pkgbases[@]} > 1 )); then
# force colors in parallel if parent process is colorized
if [[ -n ${BOLD} ]]; then
export DEVTOOLS_COLOR=always
fi
# assign command options
if [[ -n "${VERSION}" ]]; then
command+=" --switch '${VERSION}'"
fi
if ! parallel --bar --jobs "${jobs}" "${command}" ::: "${pkgbases[@]}"; then
die 'Failed to clone some packages, please check the output'
exit 1
fi
exit 0
fi
enter_workspace
for pkgbase in "${pkgbases[@]}"; do
if [[ ! -d ${pkgbase} ]]; then
msg "Cloning ${pkgbase} ..."
project_path=$(gitlab_project_name_to_path "${pkgbase}")
remote_url="${GIT_REPO_BASE_URL}/${project_path}.git"
git clone --origin origin "${remote_url}" "${pkgbase}"
if ! git clone --origin origin "${remote_url}" "${pkgbase}"; then
die 'failed to clone %s' "${pkgbase}"
fi
else
warning "Skip cloning ${pkgbase}: Directory exists"
fi
@@ -158,4 +200,6 @@ pkgctl_repo_clone() {
pkgctl_repo_switch "${VERSION}" "${pkgbase}"
fi
done
leave_workspace
}

View File

@@ -33,10 +33,12 @@ pkgctl_repo_configure_usage() {
read-only HTTPS otherwise.
OPTIONS
--protocol https Configure remote url to use https
-j, --jobs N Run up to N jobs in parallel (default: $(nproc))
-h, --help Show this help text
EXAMPLES
$ ${COMMAND} configure *
$ ${COMMAND} *
_EOF_
}
@@ -93,9 +95,13 @@ pkgctl_repo_configure() {
local GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_HTTPS}
local official=0
local proto=https
local proto_force=0
local jobs=
jobs=$(nproc)
local paths=()
# variables
local -r command=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
local path realpath pkgbase remote_url project_path
local PACKAGER GPGKEY packager_name packager_email
@@ -105,6 +111,24 @@ pkgctl_repo_configure() {
pkgctl_repo_configure_usage
exit 0
;;
--protocol=https)
proto_force=1
shift
;;
--protocol)
(( $# <= 1 )) && die "missing argument for %s" "$1"
if [[ $2 == https ]]; then
proto_force=1
else
die "unsupported protocol: %s" "$2"
fi
shift 2
;;
-j|--jobs)
(( $# <= 1 )) && die "missing argument for %s" "$1"
jobs=$2
shift 2
;;
--)
shift
break
@@ -143,8 +167,10 @@ pkgctl_repo_configure() {
fi
if is_packager_email_official "${packager_email}"; then
official=1
proto=ssh
GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_SSH}
if (( ! proto_force )); then
proto=ssh
GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_SSH}
fi
fi
fi
@@ -157,10 +183,21 @@ pkgctl_repo_configure() {
msg2 "protocol: ${YELLOW}${proto}${ALL_OFF}"
fi
# parallelization
if [[ ${jobs} != 1 ]] && (( ${#paths[@]} > 1 )); then
if [[ -n ${BOLD} ]]; then
export DEVTOOLS_COLOR=always
fi
if ! parallel --bar --jobs "${jobs}" "${command}" ::: "${paths[@]}"; then
die 'Failed to configure some packages, please check the output'
exit 1
fi
exit 0
fi
for path in "${paths[@]}"; do
if ! realpath=$(realpath -e "${path}"); then
error "No such directory: ${path}"
continue
die "No such directory: ${path}"
fi
pkgbase=$(basename "${realpath}")
@@ -168,8 +205,7 @@ pkgctl_repo_configure() {
msg "Configuring ${pkgbase}"
if [[ ! -d "${path}/.git" ]]; then
error "Not a Git repository: ${path}"
continue
die "Not a Git repository: ${path}"
fi
pushd "${path}" >/dev/null

View File

@@ -26,7 +26,7 @@ pkgctl_repo_web_usage() {
-h, --help Show this help text
EXAMPLES
$ ${COMMAND} web linux
$ ${COMMAND} linux
_EOF_
}

View File

@@ -14,7 +14,8 @@ _repos=(
# shellcheck disable=2034
_build_repos=(
extra staging testing
core-staging core-testing
extra extra-staging extra-testing
multilib multilib-staging multilib-testing
gnome-unstable
kde-unstable

107
src/lib/workspace.sh Normal file
View File

@@ -0,0 +1,107 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_WORKSPACE_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_WORKSPACE_SH=1
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
set -e
pkgctl_workspace_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [COMMAND] [OPTIONS]
Manage package workspace locations and settings
COMMANDS
add Add a new workspace
cd Change into the directory of the workspace
list, ls List availiable workspaces
remove, rm Remove a workspace
show Show details about a workspace
switch Switch the current worspace
OPTIONS
-h, --help Show this help text
EXAMPLES
$ ${COMMAND} workspace show
$ ${COMMAND} workspace list
$ ${COMMAND} workspace add test --cd
_EOF_
}
pkgctl_workspace() {
if (( $# < 1 )); then
pkgctl_workspace_usage
exit 0
fi
# option checking
while (( $# )); do
case $1 in
-h|--help)
pkgctl_workspace_usage
exit 0
;;
add)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/workspace/add.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/workspace/add.sh
pkgctl_workspace_add "$@"
exit 0
;;
cd)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/workspace/cd.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/workspace/cd.sh
pkgctl_workspace_cd "$@"
exit 0
;;
list|ls)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/workspace/list.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/workspace/list.sh
pkgctl_workspace_list "$@"
exit 0
;;
remove|rm)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/workspace/remove.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/workspace/remove.sh
pkgctl_workspace_remove "$@"
exit 0
;;
show)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/workspace/show.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/workspace/show.sh
pkgctl_workspace_show "$@"
exit 0
;;
switch)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/workspace/switch.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/workspace/switch.sh
pkgctl_workspace_switch "$@"
exit 0
;;
-*)
die "invalid argument: %s" "$1"
;;
*)
die "invalid command: %s" "$1"
;;
esac
done
}

124
src/lib/workspace/add.sh Normal file
View File

@@ -0,0 +1,124 @@
#!/bin/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_WORKSPACE_ADD_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_WORKSPACE_ADD_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/workspace/util.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/workspace/util.sh
source /usr/share/makepkg/util/message.sh
set -e
pkgctl_workspace_add_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS] NAME [PATH]
TODO
OPTIONS
-f, --force Overwrite if the workspace already exists
-s, --switch Switch to the new workspace
-c, --cd Change the current working directory
-h, --help Show this help text
EXAMPLES
$ ${COMMAND} aur
$ ${COMMAND} --force foobar ~/packages
_EOF_
}
pkgctl_workspace_add() {
if (( $# < 1 )); then
pkgctl_workspace_add_usage
exit 0
fi
# options
local force=0
local switch=0
local change_cwd=0
local name
local path
# variables
local full_path
while (( $# )); do
case $1 in
-h|--help)
pkgctl_workspace_add_usage
exit 0
;;
-c|--cd)
# shellcheck source=src/lib/workspace/cd.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/workspace/cd.sh
change_cwd=1
shift
;;
-s|--switch)
# shellcheck source=src/lib/workspace/switch.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/workspace/switch.sh
switch=1
shift
;;
-f|--force)
force=1
shift
;;
--)
shift
;;
-*)
die "invalid argument: %s" "$1"
;;
*)
if [[ -n ${name} ]]; then
path=$1
break;
fi
name=$1
shift
;;
esac
done
# path fallback inside XDG workspace dir
if [[ -z ${path} ]]; then
path=${name}
fi
if (( ! force )) && get_workspace_path_from_name "${name}" &>/dev/null; then
die "cannot create workspce '%s': Workspace already exists" "${name}"
fi
# TODO: xdg shorthand needs to be resolved into path
# TODO: detect relative paths (no leading /)
full_path=$(get_absolute_workspace_path "${path}")
if ! mkdir -p "${full_path}"; then
die "failed to create workspace path %s" "${full_path}"
fi
if ! [[ -w ${full_path} ]]; then
die "workspace path %s is not writable" "${full_path}"
fi
set_workspace "${name}" "${path}"
if (( switch )); then
pkgctl_workspace_switch "${name}"
fi
if (( change_cwd )); then
pkgctl_workspace_cd "${name}"
fi
}

70
src/lib/workspace/cd.sh Normal file
View File

@@ -0,0 +1,70 @@
#!/bin/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_WORKSPACE_CD_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_WORKSPACE_CD_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/workspace/util.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/workspace/util.sh
source /usr/share/makepkg/util/message.sh
set -e
pkgctl_workspace_cd_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS] [NAME]
TODO
OPTIONS
-h, --help Show this help text
EXAMPLES
_EOF_
}
pkgctl_workspace_cd() {
# options
local workspace=
# variables
local path
while (( $# )); do
case $1 in
-h|--help)
pkgctl_workspace_cd_usage
exit 0
;;
--)
shift
;;
-*)
die "invalid argument: %s" "$1"
;;
*)
workspace=$1
shift
break
;;
esac
done
if [[ -z ${PKGCTL_OUTCMD} ]]; then
die "setup shell"
fi
if [[ -z ${workspace} ]]; then
workspace=$(get_active_workspace_name)
fi
path=$(get_workspace_path_from_name "${workspace}")
printf "builtin cd -- %s\n" "${path}" >> "${PKGCTL_OUTCMD}"
}

134
src/lib/workspace/list.sh Normal file
View File

@@ -0,0 +1,134 @@
#!/bin/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_WORKSPACE_LIST_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_WORKSPACE_LIST_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/workspace/util.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/workspace/util.sh
source /usr/share/makepkg/util/message.sh
set -e
pkgctl_workspace_list_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS]
TODO
OPTIONS
-n, --name Only list raw workspace names
-p, --path Only list raw workspace paths
-l, --local None default workspaces only
-h, --help Show this help text
EXAMPLES
_EOF_
}
pkgctl_workspace_list_check_option_group() {
local option=$1
local print_mode=$2
if [[ ${print_mode} != pretty ]] && [[ ${print_mode} != "${option}" ]]; then
die "The argument '%s' cannot be used with one or more of the other specified arguments" "${option}"
exit 1
fi
return 0
}
pkgctl_workspace_list() {
# options
local print_mode=pretty
local only_local=0
# variables
local names name path active_workspace marker packages
local pad
local name_len=0
local packages_len=0
local workspaces
while (( $# )); do
case $1 in
-h|--help)
pkgctl_workspace_list_usage
exit 0
;;
-p|--path)
pkgctl_workspace_list_check_option_group --path "${print_mode}"
print_mode=path
shift
;;
-n|--name)
pkgctl_workspace_list_check_option_group --name "${print_mode}"
print_mode=name
shift
;;
-l|--local)
only_local=1
shift
;;
--)
shift
;;
*)
die "invalid argument: %s" "$1"
;;
esac
done
active_workspace=$(get_active_workspace_name)
mapfile -t names < <(get_all_workspace_names "${only_local}")
# cache values for pretty printing
if [[ ${print_mode} == pretty ]]; then
declare -A workspaces
pad=$(printf '%0.1s' " "{1..60})
for name in "${names[@]}"; do
echo "inter $name"
path=$(get_workspace_path_from_name "${name}")
packages=$(workspace_package_count "${name}")
if (( ${#name} > name_len )); then
name_len=${#name}
fi
if (( ${#packages} > packages_len )); then
packages_len=${#packages}
fi
workspaces["${name}->packages"]="${packages}"
workspaces["${name}->path"]="${path}"
done
fi
for name in "${names[@]}"; do
case ${print_mode} in
path)
path=$(get_workspace_path_from_name "${name}")
printf "%s\n" "${path}"
;;
name)
printf "%s\n" "${name}"
;;
pretty)
marker=" "
packages="${workspaces[${name}->packages]}"
path="${workspaces[${name}->path]}"
if [[ $name == "$active_workspace" ]]; then
marker="${GREEN}${BOLD}${ALL_OFF}${BOLD}"
fi
printf '%s %s %*.*s' "${marker}" "${name}" 0 $((name_len - ${#name} )) "${pad}"
printf ' 📦 %*.*s%s' 0 $((packages_len - ${#packages} )) "${pad}" "${packages}"
printf ' 📂 %s%s' "${path}" "${ALL_OFF}"
printf "%s\n" "${ALL_OFF}"
;;
esac
done
}

View File

@@ -0,0 +1,70 @@
#!/bin/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_WORKSPACE_REMOVE_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_WORKSPACE_REMOVE_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/workspace/util.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/workspace/util.sh
source /usr/share/makepkg/util/message.sh
set -e
pkgctl_workspace_remove_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS] NAME
TODO
OPTIONS
-h, --help Show this help text
EXAMPLES
_EOF_
}
pkgctl_workspace_remove() {
if (( $# < 1 )); then
pkgctl_workspace_remove_usage
exit 0
fi
# options
local name current
while (( $# )); do
case $1 in
-h|--help)
pkgctl_workspace_remove_usage
exit 0
;;
--)
shift
;;
-*)
die "invalid argument: %s" "$1"
;;
*)
name=$1
shift
break
;;
esac
done
# TODO: check current
current=$(get_active_workspace_name)
# TODO: check builtin default cwd
if ! remove_workspace "${name}"; then
die 'failed to remove workspace %s' "${name}"
fi
}

101
src/lib/workspace/show.sh Normal file
View File

@@ -0,0 +1,101 @@
#!/bin/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_WORKSPACE_SHOW_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_WORKSPACE_SHOW_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/workspace/util.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/workspace/util.sh
source /usr/share/makepkg/util/message.sh
set -e
pkgctl_workspace_show_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS] [NAME]
TODO
OPTIONS
-n, --name Print the workspace name
-p, --path Print the workspace location
-h, --help Show this help text
EXAMPLES
_EOF_
}
pkgctl_workspace_show_check_option_group() {
local option=$1
local print_mode=$2
if [[ ${print_mode} != pretty ]] && [[ ${print_mode} != "${option}" ]]; then
die "The argument '%s' cannot be used with one or more of the other specified arguments" "${option}"
exit 1
fi
return 0
}
pkgctl_workspace_show() {
# options
local print_mode=pretty
local workspace
# variables
local path packages
while (( $# )); do
case $1 in
-h|--help)
pkgctl_workspace_show_usage
exit 0
;;
-p|--path)
pkgctl_workspace_show_check_option_group --path "${print_mode}"
print_mode=path
shift
;;
-n|--name)
pkgctl_workspace_show_check_option_group --name "${print_mode}"
print_mode=name
shift
;;
--)
shift
;;
-*)
die "invalid argument: %s" "$1"
;;
*)
workspace=$1
shift
;;
esac
done
# use the active workspace if none is provided
if [[ -z ${workspace} ]]; then
workspace=$(get_active_workspace_name)
fi
path=$(get_workspace_path_from_name "${workspace}")
packages=$(workspace_package_count "${workspace}")
case ${print_mode} in
path)
printf "%s\n" "${path}"
;;
name)
printf "%s\n" "${workspace}"
;;
pretty)
msg2 "${workspace}: ${packages} packages ${path}"
;;
esac
}

121
src/lib/workspace/switch.sh Normal file
View File

@@ -0,0 +1,121 @@
#!/bin/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_WORKSPACE_SWITCH_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_WORKSPACE_SWITCH_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/workspace/add.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/workspace/add.sh
# shellcheck source=src/lib/workspace/cd.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/workspace/cd.sh
# shellcheck source=src/lib/workspace/list.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/workspace/list.sh
# shellcheck source=src/lib/workspace/util.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/workspace/util.sh
source /usr/share/makepkg/util/message.sh
set -e
pkgctl_workspace_switch_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
cat <<- _EOF_
Usage: ${COMMAND} [OPTIONS] [NAME]
TODO
OPTIONS
-i, --interactive Interactively select the workspace
-c, --create Create a new workspace before switching
--cd Change the working directory to the new workspace
-h, --help Show this help text
EXAMPLES
_EOF_
}
pkgctl_workspace_switch() {
if (( $# < 1 )); then
pkgctl_workspace_switch_usage
exit 0
fi
# options
local name=
local path=
local change_cwd=0
local interactive=0
local create=0
while (( $# )); do
case $1 in
-h|--help)
pkgctl_workspace_switch_usage
exit 0
;;
-c|--create)
create=1
shift
;;
--cd)
change_cwd=1
shift
;;
-i|--interactive)
interactive=1
shift
;;
--)
shift
;;
-*)
die "invalid argument: %s" "$1"
;;
*)
if [[ -z ${name} ]]; then
name=$1
elif [[ -z ${path} ]]; then
path=$1
else
die "invalid argument: %s" "$1"
fi
shift
;;
esac
done
if [[ -z ${name} ]]; then
name=default
fi
if (( interactive )); then
# TODO: check for fzf
name=$(pkgctl_workspace_list --name | sort | \
fzf --exit-0 --ansi --no-multi --keep-right --height=45%)
fi
if (( create )); then
if ! pkgctl_workspace_add "${name}"; then
exit 1
fi
fi
if ! path=$(get_workspace_path_from_name "${name}"); then
die 'workspace does not exist: %s' "${name}"
fi
if ! set_current_workspace "${name}"; then
die 'failed to set current workspace'
fi
msg "Switched to workspace %s" "${name}"
if (( change_cwd )); then
pkgctl_workspace_cd "$@"
fi
}

188
src/lib/workspace/util.sh Normal file
View File

@@ -0,0 +1,188 @@
#!/bin/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_WORKSPACE_UTIL_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_WORKSPACE_UTIL_SH=1
_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
# shellcheck source=src/lib/common.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
source /usr/share/makepkg/util/message.sh
set -e
is_xdg_workspace() {
local path=$1
[[ $path != */* ]] && [[ $path != . ]]
}
get_all_workspace_names() {
local only_local=$1
local names=()
local builtins=(default cwd)
TOML=~/.local/share/cargo/bin/toml
CONFIG=~/.config/devtools/workspace.toml
if (( ! only_local )); then
printf "%s\n" "${builtins[@]}"
fi
mapfile -t names < <(${TOML} get ${CONFIG} . | jq -r 'keys | join("\n")' | grep -v '^$')
if (( ${#names[@]} )); then
printf "%s\n" "${names[@]}"
fi
echo "${#names[@]}" >&2
}
get_workspace_path_from_name() {
local name=$1
local path
TOML=~/.local/share/cargo/bin/toml
CONFIG=~/.config/devtools/workspace.toml
case $name in
cwd)
path="${PWD}"
;;
default)
path=$name
;;
*)
if ! path="$(${TOML} get --raw ${CONFIG} -- "${name}.path")"; then
error "unknown workspace name: %s" "${name}"
return 1
fi
;;
esac
get_absolute_workspace_path "${path}"
}
get_absolute_workspace_path() {
local path=$1
# TODO XDG detection
XDG_PKGCTL_WORKSPACES=~/.local/state/pkgctl/workspace
if is_xdg_workspace "${path}"; then
printf "%s/%s" "${XDG_PKGCTL_WORKSPACES}" "${path}"
return
fi
if [[ $path == . ]]; then
printf "%s" "${PWD}"
return
fi
printf "%s" "${path}"
}
get_active_workspace_name() {
local workspace
if [[ -n ${PKGCTL_WORKSPACE} ]]; then
workspace="${PKGCTL_WORKSPACE}"
else
workspace=$(get_current_workspace_name)
fi
printf "%s" "${workspace}"
}
get_current_workspace_name() {
TOML=~/.local/share/cargo/bin/toml
CONFIG=~/.config/devtools/config.toml
DEFAULT_WORKSPACE=default
if ! workspace=$(${TOML} get --raw ${CONFIG} -- pkgctl.workspace); then
workspace=${DEFAULT_WORKSPACE}
fi
printf "%s" "${workspace}"
}
# TODO: name should reflect absolute?
get_current_workspace_path() {
:
}
set_workspace() {
local name=$1
local path=${2:-$name}
TOML=~/.local/share/cargo/bin/toml
CONFIG=~/.config/devtools/workspace.toml
[[ -z ${WORKDIR:-} ]] && setup_workdir
outfile=$(mktemp --tmpdir="${WORKDIR}" pkgctl-workspace.toml.XXXXXXXXXX)
${TOML} set "${CONFIG}" -- "${name}.path" "${path}" > "${outfile}"
mv "${outfile}" "${CONFIG}"
}
remove_workspace() {
local name=$1
local path=${2:-$name}
TOML=~/.local/share/cargo/bin/toml
CONFIG=~/.config/devtools/workspace.toml
[[ -z ${WORKDIR:-} ]] && setup_workdir
outfile=$(mktemp --tmpdir="${WORKDIR}" pkgctl-workspace.toml.XXXXXXXXXX)
tomlq --toml-output "del(.${name})" "${CONFIG}" > "${outfile}"
mv "${outfile}" "${CONFIG}"
}
set_current_workspace() {
local name=$1
TOML=~/.local/share/cargo/bin/toml
CONFIG=~/.config/devtools/config.toml
[[ -z ${WORKDIR:-} ]] && setup_workdir
outfile=$(mktemp --tmpdir="${WORKDIR}" pkgctl-workspace.toml.XXXXXXXXXX)
${TOML} set "${CONFIG}" -- "pkgctl.workspace" "${name}" > "${outfile}"
mv "${outfile}" "${CONFIG}"
}
# TODO: maybe by path instead?
workspace_package_count() {
local workspace=$1
path=$(get_workspace_path_from_name "${workspace}")
shopt -s nullglob
packages=("${path}/"*/PKGBUILD)
printf "%s" "${#packages[*]}"
}
PKGCTL_START_DIR=$(pwd)
PKGCTL_WORKSPACE_ACTIVE=0
enter_workspace() {
local path
local workspace
(( PKGCTL_WORKSPACE_ACTIVE )) && return
workspace=$(get_active_workspace_name)
path=$(get_workspace_path_from_name "${workspace}")
msg "Entering workspace %s in %s" "${workspace}" "${path}"
PKGCTL_WORKSPACE_ACTIVE=1
cd "${path}"
}
leave_workspace() {
(( ! PKGCTL_WORKSPACE_ACTIVE )) && return
PKGCTL_WORKSPACE_ACTIVE=0
cd "${PKGCTL_START_DIR}"
}

View File

@@ -125,6 +125,9 @@ OPTIONS
__EOF__
}
# save all args for check_root
orig_args=("$@")
while getopts 'dM:c:l:h' arg; do
case "$arg" in
d) diffoscope=1 ;;
@@ -137,7 +140,7 @@ while getopts 'dM:c:l:h' arg; do
done
shift $((OPTIND - 1))
check_root "" "${BASH_SOURCE[0]}" "$@"
check_root "" "${BASH_SOURCE[0]}" "${orig_args[@]}"
[[ -f PKGBUILD ]] || { error "No PKGBUILD in current directory."; exit 1; }

View File

@@ -32,6 +32,9 @@ usage() {
exit 1
}
# save all args for check_root
orig_args=("$@")
while getopts 'hUC:M:c:f:s' arg; do
case "$arg" in
U) umode=U ;;
@@ -52,7 +55,7 @@ shift $((OPTIND - 1))
(( $# < 2 )) && die 'You must specify a directory and one or more packages.'
check_root "" "${BASH_SOURCE[0]}" "$@"
check_root "" "${BASH_SOURCE[0]}" "${orig_args[@]}"
working_dir="$(readlink -f "$1")"
shift 1

View File

@@ -19,16 +19,19 @@ usage() {
Unified command-line frontend for devtools.
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
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
init Generate and print the shell configuration
release Release step to commit, tag and upload build artifacts
repo Manage Git packaging repositories and their configuration
version Show pkgctl version information
workspace Manage package workspace locations and settings
OPTIONS
-h, --help Show this help text
-w, --workspace NAME Override the configured workspace to use (default: xdg, cwd)
-h, --help Show this help text
_EOF_
}
@@ -38,6 +41,7 @@ if (( $# < 1 )); then
fi
export _DEVTOOLS_COMMAND='pkgctl'
export PKGCTL_WORKSPACE=""
load_devtools_config
@@ -48,6 +52,11 @@ while (( $# )); do
usage
exit 0
;;
-w|--workspace)
(( $# <= 1 )) && die "missing argument for %s" "$1"
PKGCTL_WORKSPACE=$2
shift 2
;;
build)
_DEVTOOLS_COMMAND+=" $1"
shift
@@ -86,6 +95,14 @@ while (( $# )); do
diffpkg "$@"
exit 0
;;
init)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/release.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/init/init.sh
pkgctl_init "$@"
exit 0
;;
release)
_DEVTOOLS_COMMAND+=" $1"
shift
@@ -102,6 +119,14 @@ while (( $# )); do
pkgctl_version "$@"
exit 0
;;
workspace)
_DEVTOOLS_COMMAND+=" $1"
shift
# shellcheck source=src/lib/workspace.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/workspace.sh
pkgctl_workspace "$@"
exit 0
;;
*)
die "invalid command: %s" "$1"
;;