Skip to content

Commit

Permalink
Improve runtime data dir init and --working-dir handling
Browse files Browse the repository at this point in the history
* KUBLER_DATA_DIR is now properly initialized if empty or non-existing
* bash-completion now handles --working-dir correctly, also affects all
  further completions
* KUBLER_WORKING_DIR now works when set via kubler.conf
* add a default .gitignore as part of KUBLER_DATA_DIR init
  • Loading branch information
edannenberg committed Jan 28, 2019
1 parent 09be3fa commit cc918de
Show file tree
Hide file tree
Showing 11 changed files with 151 additions and 43 deletions.
2 changes: 1 addition & 1 deletion cmd/argbash/dep-graph.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ print_help ()
{
printf 'Usage: %s dep-graph [-d|--as-raw-dot] [-a|--as-ascii] [-b|--as-boxart] [-o|--output-file] [-w|--working-dir <arg>] [--debug] <target-id-1> [<target-id-2>] ... [<target-id-n>] ...\n' "${_KUBLER_BIN}"
printf "\t%s\n" "<target-id>: Namespace or image for the graph, i.e. myns or myns/myimage"
printf "\t%s\n" "-d,--as-dot: Output dot markup only"
printf "\t%s\n" "-r,--as-raw-dot: Output dot markup only"
printf "\t%s\n" "-a,--as-ascii: ASCII output via kubler/graph-easy image"
printf "\t%s\n" "-b,--as-boxart: Unicode ASCII output kubler/graph-easy image"
printf "\t%s\n" "-o,--output-file: Specify an output file, if omitted stdout is used for ascii/boxart"
Expand Down
7 changes: 0 additions & 7 deletions cmd/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -220,13 +220,6 @@ function main() {
# shellcheck disable=SC2034
[[ "${_arg_clear_build_container}" == 'on' ]] && _arg_force_full_image_build='on'

# clone kubler-images repo if non-existing
if [[ "${KUBLER_DISABLE_KUBLER_NS}" != 'true' ]] && ! is_git_dir "${_KUBLER_NAMESPACE_DIR}"/kubler; then
add_status_value 'kubler-images'
clone_or_update_git_repo "${_KUBLER_NS_GIT_URL}" "${_KUBLER_NAMESPACE_DIR}" 'kubler'
add_status_value
fi

# prepare a --interactive build
# shellcheck disable=SC2154
[[ "${_arg_interactive_no_deps}" == 'on' ]] && _arg_interactive='on'
Expand Down
1 change: 1 addition & 0 deletions cmd/new.sh
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ function add_namespace() {
msg_info "Initial image tag, a.k.a. version?"
ask 'Image Tag' "${_TODAY}"
add_template_filter_var '_tmpl_image_tag' "${__ask}"
add_template_sed_replace '^IMAGE_TAG' '#IMAGE_TAG'
msg_info_sub
else
msg_info_sub
Expand Down
9 changes: 8 additions & 1 deletion engine/docker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,11 @@ function import_portage_tree() {

portage_file="${portage_file//latest/${_TODAY}}"

image_path="${KUBLER_DATA_DIR}"/tmp/kubler-portage
if [[ "${KUBLER_DISABLE_KUBLER_NS}" != 'true' ]]; then
image_path="${KUBLER_DATA_DIR}"/namespaces/kubler/builder/bob-portage
else
image_path="${KUBLER_DATA_DIR}"/tmp/kubler-portage
fi
[[ ! -d "${image_path}" ]] && mkdir -p "${image_path}"
cp "${_KUBLER_DIR}"/engine/docker/bob-portage/Dockerfile.template "${image_path}"/

Expand All @@ -558,7 +562,10 @@ function import_portage_tree() {
}

function handle_import_portage_tree_error() {
[[ -d "${KUBLER_DATA_DIR}"/namespaces/kubler/builder/bob-portage ]] \
&& rm -r "${KUBLER_DATA_DIR}"/namespaces/kubler/builder/bob-portage
[[ -d "${KUBLER_DATA_DIR}"/tmp/kubler-portage ]] && rm -r "${KUBLER_DATA_DIR}"/tmp/kubler-portage
dir_is_empty "${KUBLER_DATA_DIR}"/tmp && rm -r "${KUBLER_DATA_DIR}"/tmp
}

# Docker import a stage3 tar ball for given stage3_image_id
Expand Down
11 changes: 7 additions & 4 deletions kubler.conf
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,28 @@
# Image version, ideally set via user config so it's shared by all --working-dirs of current user
#IMAGE_TAG='20190123'
# Default maintainer, override via namespace kubler.conf
AUTHOR='Erik Dannenberg <[email protected]>'
#AUTHOR='Erik Dannenberg <[email protected]>'

# Kubler's runtime data dir, needs to be writable by the current user
#KUBLER_DATA_DIR="${HOME}/.kubler}"
#KUBLER_DATA_DIR="${HOME}/.kubler"
# Gentoo's stage3 and portage files download location
#KUBLER_DOWNLOAD_DIR="${KUBLER_DATA_DIR}/downloads"
# Gentoo's build related downloads, like source code, patches, etc
#KUBLER_DISTFILES_DIR="${KUBLER_DATA_DIR}/distfiles"
# Gentoo's binary package cache location
#KUBLER_PACKAGES_DIR="${KUBLER_DATA_DIR}/packages"

# Lock --working-dir to given path. If you enable this use an absolute path or ensure KUBLER_DATA_DIR above is set.
#KUBLER_WORKING_DIR="${KUBLER_DATA_DIR}"

# Ouput related config
# Disable compact output, effectively always passes -v to all commands
# If true disables compact output, effectively always passes -v to all commands
#KUBLER_VERBOSE='false'
# If true and compact output is enabled send output to log file instead of /dev/null
#KUBLER_CMD_LOG='true'
# Shall we ring the terminal bell on error?
#KUBLER_BELL_ON_ERROR='true'
# Disabling this only works when set as ENV before starting Kubler
# Use colored output messages?
#KUBLER_COLORS='true'

# Update the portage container via git. Not recommended as it can be quite slow due to the amount of upstream changes.
Expand Down
29 changes: 26 additions & 3 deletions kubler.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

readonly _KUBLER_VERSION=0.9.0-beta
readonly _KUBLER_BASH_MIN=4.2
readonly _KUBLER_CONF=kubler.conf

# shellcheck disable=SC1004
_help_header=' __ ___. .__
Expand Down Expand Up @@ -125,6 +126,25 @@ function compare_versions() {
return 2
}

# Read config from /etc/kubler.conf or $_KUBLER_DIR/kubler.conf as fallback, then $KUBLER_DATA_DIR config if it exists
#
# Arguments:
# 1: kubler_dir
function source_base_conf() {
local kubler_dir conf_path
kubler_dir="$1"
conf_path=/etc/"${_KUBLER_CONF}"
if [[ ! -f "${conf_path}" ]]; then
conf_path="${kubler_dir}/${_KUBLER_CONF}"
[[ ! -f "${conf_path}" ]] && die "Couldn't find config at /etc/${_KUBLER_CONF} or ${conf_path}"
fi
# shellcheck source=kubler.conf
source "${conf_path}"
conf_path="${KUBLER_DATA_DIR}/${_KUBLER_CONF}"
# shellcheck source=template/docker/namespace/kubler.conf.multi
[[ -n "${KUBLER_DATA_DIR}" && -f "${conf_path}" ]] && source "${conf_path}"
}

# Arguments:
# 1: exit_message as string
# 2: exit_code as int, optional, default: 1
Expand Down Expand Up @@ -164,9 +184,7 @@ function main() {
[[ -d "${lib_dir}" ]] || die "Couldn't find ${lib_dir}" 2
readonly _LIB_DIR="${lib_dir}"

KUBLER_DATA_DIR="${KUBLER_DATA_DIR:-${HOME}/.kubler}"
[[ ! -d "${KUBLER_DATA_DIR}" ]] && mkdir -p "${KUBLER_DATA_DIR}"/{cmd/argbash,engine,log,namespaces,tmp}
[[ ! -d "${KUBLER_DATA_DIR}" ]] && "Couldn't create KUBLER_DATA_DIR at ${KUBLER_DATA_DIR}"
source_base_conf "${_KUBLER_DIR}"

core="${_LIB_DIR}"/core.sh
[[ -f "${core}" ]] || die "Couldn't read ${core}" 2
Expand All @@ -192,6 +210,8 @@ function main() {
[[ -z "${working_dir}" ]] && working_dir="${PWD}"
detect_namespace "${working_dir}"

validate_or_init_data_dir "${KUBLER_DATA_DIR}"

# handle --help for main script
[[ -z "${_arg_command}" && "${_arg_help}" == 'on' ]] && { bc_helper; show_help; exit 0; }

Expand All @@ -217,6 +237,9 @@ function main() {
# handle --help for command script
[[ "${_arg_help}" == 'on' ]] && { show_help; exit 0; }

if [[ "${KUBLER_CMD_LOG}" == 'true' && "${_arg_verbose}" == 'off' && ! -d "${_KUBLER_LOG_DIR}" ]];then
mkdir -p "${_KUBLER_LOG_DIR}" || die
fi
[[ "${_arg_verbose}" == 'off' ]] && file_exists_and_truncate "${_KUBLER_LOG_DIR}/${_arg_command}.log"

# run the selected command
Expand Down
46 changes: 43 additions & 3 deletions lib/core.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,17 @@

KUBLER_DISABLE_KUBLER_NS="${KUBLER_DISABLE_KUBLER_NS:-false}"

KUBLER_DATA_DIR="${KUBLER_DATA_DIR:-${HOME}/.kubler}"
KUBLER_DOWNLOAD_DIR="${KUBLER_DOWNLOAD_DIR:-${KUBLER_DATA_DIR}/downloads}"
KUBLER_DISTFILES_DIR="${KUBLER_DISTFILES_DIR:-${KUBLER_DATA_DIR}/distfiles}"
KUBLER_PACKAGES_DIR="${KUBLER_PACKAGES_DIR:-${KUBLER_DATA_DIR}/packages}"
KUBLER_DEPGRAPH_IMAGE="${KUBLER_DEPGRAPH_IMAGE:-kubler/graph-easy}"

AUTHOR="${AUTHOR:-Erik Dannenberg <erik.dannenberg@xtrade-gmbh.de>}"

readonly _KUBLER_NAMESPACE_DIR="${KUBLER_DATA_DIR}"/namespaces
readonly _KUBLER_LOG_DIR="${KUBLER_DATA_DIR}"/log
readonly _KUBLER_NS_GIT_URL='https://github.com/edannenberg/kubler-images.git'
readonly _KUBLER_CONF='kubler.conf'
readonly _IMAGE_PATH="images/"
readonly _BUILDER_PATH="builder/"
readonly _STAGE3_NAMESPACE="kubler-gentoo"
Expand Down Expand Up @@ -149,6 +151,40 @@ function has_required_binaries() {
done
}

# Check if passed target_path is a valid KUBLER_DATA_DIR, if not create and/or initialize the dir.
#
# Arguments:
# 1: target_path
function validate_or_init_data_dir() {
local target_path conf_sed_args kubler_ns_path
target_path="$1"
if [[ ! -d "${target_path}" ]]; then
mkdir -p "${target_path}" || die
elif dir_is_empty "${target_path}"; then
cp "${_KUBLER_DIR}"/template/docker/namespace/kubler.conf.multi "${target_path}/${_KUBLER_CONF}" || die
# shellcheck disable=SC2034
conf_sed_args=(
'-e' "s|\${_tmpl_author}|Your Name|g"
'-e' "s|\${_tmpl_author_email}|[email protected]|g"
'-e' "s|\${_tmpl_image_tag}|${_TODAY}|g"
'-e' "s|\${_tmpl_engine}|${BUILD_ENGINE}|g"
)
replace_in_file "${target_path}/${_KUBLER_CONF}" sed_args[@] || die
cp "${_KUBLER_DIR}"/template/gitignore-data-dir "${target_path}"/.gitignore || die
else
[[ ! -f "${target_path}/${_KUBLER_CONF}" ]] \
&& die "Configured KUBLER_DATA_DIR ${target_path} is not empty but has no ${_KUBLER_CONF} file, aborting."
fi
# clone kubler-images repo if non-existing
[[ ! -d "${target_path}"/namespaces ]] && mkdir "${target_path}"/namespaces
kubler_ns_path="${target_path}"/namespaces/kubler
if [[ -z "${KUBLER_BC_HELP}" && "${KUBLER_DISABLE_KUBLER_NS}" != 'true' ]] && ! is_git_dir "${kubler_ns_path}"; then
add_status_value 'kubler-images'
clone_or_update_git_repo "${_KUBLER_NS_GIT_URL}" "${target_path}"/namespaces 'kubler'
add_status_value
fi
}

# Source build engine script depending on passed engine_id or BUILD_ENGINE value
#
# Arguments:
Expand Down Expand Up @@ -557,7 +593,11 @@ function detect_namespace() {

get_absolute_path "${working_dir}"
# shellcheck disable=SC2154
[[ -d "${__get_absolute_path}" ]] || die "fatal: Couldn't find namespace location: ${working_dir}"
if [[ ! -d "${__get_absolute_path}" ]]; then
# silent exit if called by bash completion
[[ "${KUBLER_BC_HELP}" != 'true' ]] && msg_error "fatal: Couldn't find namespace location: ${working_dir}"
die
fi

# find next namespace dir, respect symlink paths, as in don't resolve
find_in_parents "${working_dir}" "${_KUBLER_CONF}"
Expand Down Expand Up @@ -614,7 +654,7 @@ function detect_namespace() {

# ..then current namespace config
# shellcheck source=kubler.conf
[[ "${_kubler_ns_conf}" != "${_kubler_user_conf}" && -f "${_kubler_ns_conf}" ]] && source "${_kubler_ns_conf}"
[[ "${_NAMESPACE_TYPE}" != 'local' && -f "${_kubler_ns_conf}" ]] && source "${_kubler_ns_conf}"

# just for well formatted output
get_absolute_path "${real_ns_dir}"
Expand Down
76 changes: 54 additions & 22 deletions lib/kubler-completion.bash
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,26 @@ function _bc_kubler_find_in_compwords() {
done
}

# Scan compwords for --working-dir arg and return it's given path if set
function _bc_kubler_scan_wdir_in_compwords() {
___bc_kubler_scan_wdir_in_compwords=
local word c path_index passed_wdir
c=1
path_index=0
while [[ $c -lt ${COMP_CWORD} ]]; do
word="${COMP_WORDS[c]}"
if [[ '--working-dir' == "${word}" ]]; then
path_index=$(( c + 1 ))
if [[ ${path_index} -lt ${COMP_CWORD} ]]; then
passed_wdir="${COMP_WORDS[${path_index}]}"
[[ -n "${passed_wdir}" ]] && ___bc_kubler_scan_wdir_in_compwords="${COMP_WORDS[${path_index}]}"
fi
return
fi
((c++))
done
}

# Returns an array with all matches for given $pattern and $text.
# Adapted from: http://regexraptor.net/downloads/return_all_matches.sh
#
Expand Down Expand Up @@ -63,11 +83,15 @@ function _bc_kubler_init()

# Init namespace related global vars that need to be refreshed on each new completion
function _bc_kubler_init_ns_vars() {
local help_output parsed_help
local help_output parsed_help help_args
_bc_kubler_dir=
_bc_kubler_working_dir=
_bc_kubler_ns_type=
help_output="$(KUBLER_BC_HELP=true kubler --help)"
help_args=()
_bc_kubler_scan_wdir_in_compwords
[[ -n "${___bc_kubler_scan_wdir_in_compwords}" ]] \
&& help_args+=( '--working-dir' "${___bc_kubler_scan_wdir_in_compwords}" )
help_output="$(KUBLER_BC_HELP=true kubler "${help_args[@]}" --help)"
readarray -t parsed_help <<< "${help_output}"
_bc_kubler_dir="${parsed_help[0]}"
_bc_kubler_working_dir="${parsed_help[1]}"
Expand Down Expand Up @@ -105,68 +129,76 @@ function _bc_kubler_comp_image() {
___bc_kubler_comp_image="$(find "${current_image_path}" -maxdepth 1 -mindepth 1 -type d ! -name '.*' -printf '%f ')"
}

function _kubler()
{
local cur_comp prev kubler_global_opts kubler_cmds current_opts regex_cmds regex_opts current_cmd cmd_opts
function _kubler() {
local cur prev kubler_global_opts kubler_cmds current_opts regex_cmds regex_opts current_cmd cmd_opts
COMPREPLY=()
cur_comp="${COMP_WORDS[COMP_CWORD]}"
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
kubler_global_opts="--help --debug --working-dir --verbose"

_bc_kubler_init_ns_vars

if [[ "${prev}" == '--working-dir' ]]; then
if declare -f _filedir 1> /dev/null; then
_filedir -d
else
COMPREPLY=( $(compgen -o dirnames -- "${cur}") )
fi
return
fi

# check for a completed kubler command
_bc_kubler_find_in_compwords "${_bc_kubler_cmds}"
if [[ -z "${___bc_kubler_find_in_compwords}" ]]; then
case "${cur_comp}" in
case "${cur}" in
# complete global args
--*) COMPREPLY=( $(compgen -W "${kubler_global_opts}" -- ${cur_comp}) )
--*) COMPREPLY=( $(compgen -W "${kubler_global_opts}" -- ${cur}) )
;;
# complete commands
*) if [[ "${_bc_kubler_ns_type}" == 'none' ]];then
# only new command allowed if we are not in a kubler ns dir
COMPREPLY=( $(compgen -W "new" -- ${cur_comp}) )
COMPREPLY=( $(compgen -W "new" -- ${cur}) )
else
COMPREPLY=( $(compgen -W "${_bc_kubler_cmds}" -- ${cur_comp}) )
COMPREPLY=( $(compgen -W "${_bc_kubler_cmds}" -- ${cur}) )
fi
;;
esac
return
else
# handle various cases for completed commands/args
current_cmd="${___bc_kubler_find_in_compwords}"
case "${current_cmd}:${cur_comp}" in
case "${current_cmd}:${cur}" in
*:--*) current_opts="_bc_kubler_cmd_${current_cmd//-/_}_opts";
COMPREPLY=( $(compgen -W "${!current_opts}" -- ${cur_comp}) )
COMPREPLY=( $(compgen -W "${!current_opts}" -- ${cur}) )
;;
build:*/*) _bc_kubler_comp_image
cur_comp="${cur_comp#*/}"
COMPREPLY=( $(compgen -P "${COMP_WORDS[COMP_CWORD]%/*}/" -W "${___bc_kubler_comp_image}" -- ${cur_comp}) )
cur="${cur#*/}"
COMPREPLY=( $(compgen -P "${COMP_WORDS[COMP_CWORD]%/*}/" -W "${___bc_kubler_comp_image}" -- ${cur}) )
;;
clean:*) [[ "${prev}" == '-i' || "${prev}" == '--image-ns' ]] && \
_bc_kubler_comp_namespace && compopt -o nospace && COMPREPLY=( $(compgen -W "${___bc_kubler_comp_namespace}" -- ${cur_comp}) )
_bc_kubler_comp_namespace && compopt -o nospace && COMPREPLY=( $(compgen -W "${___bc_kubler_comp_namespace}" -- ${cur}) )
;;
push:*/*) _bc_kubler_comp_image
cur_comp="${cur_comp#*/}"
COMPREPLY=( $(compgen -P "${COMP_WORDS[COMP_CWORD]%/*}/" -W "${___bc_kubler_comp_image}" -- ${cur_comp}) )
cur="${cur#*/}"
COMPREPLY=( $(compgen -P "${COMP_WORDS[COMP_CWORD]%/*}/" -W "${___bc_kubler_comp_image}" -- ${cur}) )
;;
dep-graph:*/*)
_bc_kubler_comp_image
cur_comp="${cur_comp#*/}"
COMPREPLY=( $(compgen -P "${COMP_WORDS[COMP_CWORD]%/*}/" -W "${___bc_kubler_comp_image}" -- ${cur_comp}) )
cur="${cur#*/}"
COMPREPLY=( $(compgen -P "${COMP_WORDS[COMP_CWORD]%/*}/" -W "${___bc_kubler_comp_image}" -- ${cur}) )
;;
new:*) cmd_opts='builder image namespace'
[[ "${_bc_kubler_ns_type}" == 'none' ]] && cmd_opts='namespace'
[[ "${_bc_kubler_ns_type}" == 'single' ]] && cmd_opts='builder image'
if [[ "${prev}" == 'image' || "${prev}" == 'builder' ]]; then
_bc_kubler_comp_namespace && compopt -o nospace && COMPREPLY=( $(compgen -W "${___bc_kubler_comp_namespace}" -- ${cur_comp}) )
_bc_kubler_comp_namespace && compopt -o nospace && COMPREPLY=( $(compgen -W "${___bc_kubler_comp_namespace}" -- ${cur}) )
else
_bc_kubler_find_in_compwords "${cmd_opts}"
[[ -z "${___bc_kubler_find_in_compwords}" ]] && COMPREPLY=( $(compgen -W "${cmd_opts}" -- ${cur_comp}) )
[[ -z "${___bc_kubler_find_in_compwords}" ]] && COMPREPLY=( $(compgen -W "${cmd_opts}" -- ${cur}) )
fi
;;
*:*) [[ "${current_cmd}" = 'build' || "${current_cmd}" = 'dep-graph' || "${current_cmd}" = 'push' ]] && \
_bc_kubler_comp_namespace && compopt -o nospace && COMPREPLY=( $(compgen -W "${___bc_kubler_comp_namespace}" -- ${cur_comp}) )
_bc_kubler_comp_namespace && compopt -o nospace && COMPREPLY=( $(compgen -W "${___bc_kubler_comp_namespace}" -- ${cur}) )
;;
esac
fi
Expand Down
3 changes: 2 additions & 1 deletion lib/util.sh
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,8 @@ function pwrap() {

redirect_target='/dev/null'
# shellcheck disable=SC2154
[[ "${KUBLER_CMD_LOG}" == 'true' ]] && redirect_target="${_KUBLER_LOG_DIR}/${_arg_command}.log"
[[ "${KUBLER_CMD_LOG}" == 'true' && -n "${_is_valid_cmd}" ]] \
&& redirect_target="${_KUBLER_LOG_DIR}/${_arg_command}.log"

# launch spinner in bg
# shellcheck disable=SC2154
Expand Down
2 changes: 1 addition & 1 deletion template/docker/namespace/kubler.conf.multi
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
AUTHOR="${_tmpl_author} <${_tmpl_author_email}>"
# Global tag (a.k.a version) for all images
# Image version, ideally set via user config so it's shared by all --working-dirs of current user
IMAGE_TAG="${_tmpl_image_tag}"

# Ouput related config
Expand Down
Loading

0 comments on commit cc918de

Please sign in to comment.