Generate & install completion scripts in build system

The previous commit added a means to generating the completion scripts
and this one plugs that into the build system.

A new build option 'install_completions' has been introduced. Set to
'True' by default.

Completions for bash and fish use pkg-config for getting the preferred
install locations for the completions. If the packages are not
available, fallbacks are in-place.

The 'completion' subdir has been kept to work around the ideology of
Meson that does not allow creating/outputing files in subdirectories nor
using the output of custom_target() in install_data().

https://github.com/containers/toolbox/pull/840
This commit is contained in:
Ondřej Míchal 2021-11-21 16:16:07 +02:00
parent d69ce6794b
commit bafbbe81c9
6 changed files with 89 additions and 107 deletions

View file

@ -43,3 +43,4 @@ database, etc..
See our guides on See our guides on
[installing & getting started](https://containertoolbx.org/install/) with [installing & getting started](https://containertoolbx.org/install/) with
Toolbox and [Linux distro support](https://containertoolbx.org/distros/). Toolbox and [Linux distro support](https://containertoolbx.org/distros/).

View file

@ -1,100 +0,0 @@
# Check for bash
[ -z "$BASH_VERSION" ] && return
__toolbox_containers() {
toolbox list -c 2>/dev/null | tail -n +2 2>/dev/null | cut -d " " -f 3 2>/dev/null
}
__toolbox_distros() {
echo "fedora"
echo "rhel"
}
__toolbox_images() {
toolbox list -i 2>/dev/null | tail -n +2 2>/dev/null | cut -d " " -f 3 2>/dev/null
}
__toolbox() {
local MIN_VERSION=32
local RAWHIDE_VERSION=34
local commands="create enter help init-container list rm rmi run"
local global_options="--assumeyes --help --log-level --log-podman"
local log_levels="debug info warn error fatal panic"
declare -A options
local options=([create]="--distro --image --release" \
[enter]="--distro --release" \
[help]="$commands" \
[init-container]="--home --home-link --monitor-host --shell --uid --user" \
[list]="--containers --images" \
[rm]="--all --force" \
[rmi]="--all --force" \
[run]="--container --distro --release")
_init_completion -s || return
if [ "${COMP_CWORD}" -eq 1 ]; then
mapfile -t COMPREPLY < <(compgen -W "$global_options $commands" -- "$2")
return 0
fi
# If a global option is mentioned, don't mention it anymore
for option in $global_options; do
if [[ "${COMP_LINE}" =~ "$option" ]]; then
global_options="${global_options/$option}"
fi
done
# If a command is mentioned, don't mention any more commands
local command
for cmd in $commands; do
if [[ "${COMP_LINE}" =~ "$cmd" ]]; then
commands=""
command="$cmd"
fi
done
case "$prev" in
--assumeyes | -y | --help | -h | --verbose | -v | --log-podman)
mapfile -t COMPREPLY < <(compgen -W "$global_options $commands" -- "$2")
return 0
;;
--container | -c)
mapfile -t COMPREPLY < <(compgen -W "$(__toolbox_containers)" -- "$2")
return 0
;;
--distro | -d)
mapfile -t COMPREPLY < <(compgen -W "$(__toolbox_distros)" -- "$2")
return 0
;;
--image | -i)
mapfile -t COMPREPLY < <(compgen -W "$(__toolbox_images)" -- "$2")
return 0
;;
--release | -r)
mapfile -t COMPREPLY < <(compgen -W "$(seq $MIN_VERSION $RAWHIDE_VERSION)" -- "$2")
return 0
;;
--log-level)
mapfile -t COMPREPLY < <(compgen -W "$log_levels" -- "$2")
return 0
;;
esac
local extra_comps
case "$command" in
rm | enter)
extra_comps="$(__toolbox_containers)"
;;&
rmi)
extra_comps="$(__toolbox_images)"
;;&
*)
mapfile -t COMPREPLY < <(compgen -W "${options[$command]} $extra_comps" -- "$2")
return 0;
;;
esac
}
complete -F __toolbox toolbox

View file

@ -0,0 +1,41 @@
#!/usr/bin/env python3
#
# Copyright © 2022 Ondřej Míchal
# Copyright © 2022 Red Hat Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import os
import subprocess
import sys
if len(sys.argv) != 3:
print('{}: wrong arguments'.format(sys.argv[0]), file=sys.stderr)
print('Usage: {} [SOURCE DIR] [COMPLETION TYPE]'.format(sys.argv[0]), file=sys.stderr)
print()
print("SOURCE DIR is path to the Toolbox Go source code")
print("COMPLETION TYPE is either 'bash', 'zsh' or 'fish'")
sys.exit(1)
source_dir = sys.argv[1]
completion_type = sys.argv[2]
try:
os.chdir(source_dir)
output = subprocess.run(['go', 'run', '.', 'completion', completion_type], check=True)
except subprocess.CalledProcessError as e:
print('{}: go run returned non-zero exit status {}'.format(sys.argv[0], e.returncode), file=sys.stderr)
sys.exit(e.returncode)
sys.exit(0)

36
completion/meson.build Normal file
View file

@ -0,0 +1,36 @@
generate_completions_program = find_program('generate_completions.py')
if bash_completion.found()
bash_comp_dir = bash_completion.get_pkgconfig_variable('completionsdir')
else
bash_comp_dir = get_option('datadir') / 'bash-completion' / 'completions'
message('bash-completion not found: using', get_option('prefix') / bash_comp_dir, 'as a falback install directory')
endif
if fish.found()
fish_comp_dir = fish.get_pkgconfig_variable('completionsdir')
else
fish_comp_dir = get_option('datadir') / 'fish' / 'completions'
message('fish not found: using', get_option('prefix') / fish_comp_dir, 'as a fallback install directory')
endif
completion_bash = custom_target('bash-completion',
capture: true,
command: [generate_completions_program, meson.global_source_root() / 'src', 'bash'],
install: true,
install_dir: bash_comp_dir,
output: 'toolbox')
completion_zsh = custom_target('zsh-completion',
capture: true,
command: [generate_completions_program, meson.global_source_root() / 'src', 'zsh'],
install: true,
install_dir: get_option('datadir') / 'zsh' / 'site_functions',
output: '_toolbox')
completion_fish = custom_target('fish-completion',
capture: true,
command: [generate_completions_program, meson.global_source_root() / 'src', 'fish'],
install: true,
install_dir: fish_comp_dir,
output: 'toolbox.fish')

View file

@ -19,6 +19,7 @@ shellcheck = find_program('shellcheck', required: false)
skopeo = find_program('skopeo', required: false) skopeo = find_program('skopeo', required: false)
bash_completion = dependency('bash-completion', required: false) bash_completion = dependency('bash-completion', required: false)
fish = dependency('fish', required: false)
migration_path_for_coreos_toolbox = get_option('migration_path_for_coreos_toolbox') migration_path_for_coreos_toolbox = get_option('migration_path_for_coreos_toolbox')
profiledir = get_option('profile_dir') profiledir = get_option('profile_dir')
@ -32,13 +33,6 @@ if tmpfilesdir == '' or not fs.exists('/run/.containerenv')
endif endif
endif endif
if bash_completion.found()
install_data(
'completion/bash/toolbox',
install_dir: bash_completion.get_variable(pkgconfig: 'completionsdir')
)
endif
if not skopeo.found() if not skopeo.found()
message('Running system tests requires Skopeo for OCI image manipulation.') message('Running system tests requires Skopeo for OCI image manipulation.')
endif endif
@ -70,5 +64,8 @@ subdir('data')
subdir('doc') subdir('doc')
subdir('profile.d') subdir('profile.d')
subdir('src') subdir('src')
if get_option('install_completions')
subdir('completion')
endif
meson.add_install_script('meson_post_install.py') meson.add_install_script('meson_post_install.py')

View file

@ -17,3 +17,10 @@ option(
description: 'Directory for system-wide tmpfiles.d(5) files', description: 'Directory for system-wide tmpfiles.d(5) files',
type: 'string', type: 'string',
) )
option(
'install_completions',
description: 'Install bash, zsh and fish command completions',
type: 'boolean',
value: true,
)