diff --git a/bpkg-env b/bpkg-env new file mode 120000 index 0000000..3bff5f0 --- /dev/null +++ b/bpkg-env @@ -0,0 +1 @@ +lib/env/env.sh \ No newline at end of file diff --git a/bpkg.json b/bpkg.json index 07f28f3..373d8ee 100644 --- a/bpkg.json +++ b/bpkg.json @@ -6,6 +6,7 @@ "repo": "bpkg/bpkg", "install": "bash setup.sh", "commands": { - "lint": "shellcheck $BPKG_SCRIPT_SOURCES" + "lint": "command shellcheck **/*.sh", + "list-sources": "echo ${BPKG_SCRIPT_SOURCES[@]} | sed 's/ /\n/g'" } } diff --git a/lib/env/env.sh b/lib/env/env.sh new file mode 100755 index 0000000..d660815 --- /dev/null +++ b/lib/env/env.sh @@ -0,0 +1,203 @@ +#!/bin/bash + +if ! type -f bpkg-utils &>/dev/null; then + echo "error: bpkg-utils not found, aborting" + exit 1 +else + # shellcheck disable=SC2230 + # shellcheck source=lib/utils/utils.sh + source "$(which bpkg-utils)" +fi + +if ! type -f bpkg-package &>/dev/null; then + echo "error: bpkg-package not found, aborting" + exit 1 +else + # shellcheck disable=SC2230 + # shellcheck source=lib/package/package.sh + source "$(which bpkg-package)" +fi + +bpkg_initrc + +# Include config rc file if found +BPKG_USER_CONFIG_FILE="$HOME/.bpkgrc" + +# Include config rc file if found +BPKG_LOCAL_CONFIG_FILE="$(pwd)/.bpkgrc" + +## meta +export BPKG_DATE="$(date)" +export BPKG_HOME="${BPKG_HOME:-$HOME}" +export BPKG_INDEX="$BPKG_INDEX" + +## os +export BPKG_OS="$(uname)" +export BPKG_CWD="$(pwd)" +export BPKG_BIN="$(which bpkg)" +export BPKG_USER="$(uname)" + +## package +export BPKG_PACKAGE_USER +export BPKG_PACKAGE_NAME="$(bpkg_package name 2>/dev/null)" +export BPKG_PACKAGE_REPO="$(bpkg_package repo 2>/dev/null)" +export BPKG_PACKAGE_DEPS="${BPKG_PACKAGE_DEPS:-deps}" +export BPKG_PACKAGE_VERSION="$(bpkg_package version 2>/dev/null)" +export BPKG_PACKAGE_DESCRIPTION="$(bpkg_package description 2>/dev/null)" + +## remote +export BPKG_REMOTE="$BPKG_REMOTE" +# shellcheck disable=SC2178 +export BPKG_REMOTES="${BPKG_REMOTE[*]}" +export BPKG_REMOTE_RAW_PATH="$BPKG_REMOTE_RAW_PATH" + +if test -f bpkg.json || test -f package.json; then + declare -a BPKG_SCRIPT_SOURCES=() + BPKG_SCRIPT_SOURCES+=($(find . -name '*.sh')) + BPKG_SCRIPT_SOURCES+=($(find . -name '*.zsh')) + BPKG_SCRIPT_SOURCES+=($(find . -name '*.bash')) + export BPKG_SCRIPT_SOURCES +fi + +## output usage +usage () { + echo 'usage: bpkg-env [-h|--help]' + echo ' or: bpkg-env [--value]' + echo + echo 'example:' + echo '$ bpkg-env BPKG_PACKAGE*' + echo 'BPKG_PACKAGE_DEPS="deps"' + echo 'BPKG_PACKAGE_DESCRIPTION="Lightweight bash package manager"' + echo 'BPKG_PACKAGE_NAME="bpkg"' + echo 'BPKG_PACKAGE_REPO="bpkg/bpkg"' + echo 'BPKG_PACKAGE_USER="Linux"' + echo 'BPKG_PACKAGE_VERSION="1.0.7"' +} + +bpkg_env () { + local key="" + local should_emit_value=0 + + for opt in "$@"; do + case "$opt" in + -h|--help) + usage + return 0 + ;; + + --value) + should_emit_value=1 + shift + ;; + -*) + bpkg_error "Unknown option: \`$opt'" + return 2 + ;; + + *) + key="$1" + shift + ;; + esac + done + + { + printenv + echo BPKG_SCRIPT_SOURCES=\""${BPKG_SCRIPT_SOURCES[*]}"\" + } | \ + grep '^\s*BPKG_' | \ + sed 's/^\s*//g' | \ + sort | \ + { + did_emit=0 + + while read -r line; do + local kv=("" "") + local j=0 + + for (( i = 0; i < ${#line}; ++i )); do + if [ "${line:$i:1}" = "=" ] && (( j == 0 )); then + (( j++ )) + continue + fi + + kv[$j]+=${line:$i:1} + done + + if [ -n "$key" ]; then + regex="^${key/'*'/'.*'}$" + if ! [[ "${kv[0]}" =~ $regex ]]; then + continue + fi + fi + + if [ -z "${kv[1]}" ]; then + continue + fi + + if [ "${kv[1]:0:1}" = "$" ] || [ "${kv[1]:1:1}" = "$" ]; then + continue + fi + + if [ "${kv[1]:0:1}" = ";" ]; then + continue + fi + + if [ "${kv[1]}" = '"";' ]; then + continue + fi + + if (( should_emit_value == 0 )); then + printf '%s=' "${kv[0]}" + fi + + if [ "${kv[1]:0:1}" != '"' ]; then + printf '"' + fi + + printf '%s' "${kv[1]}" + + l=${#kv[1]} + lm1=$(( l - 1 )) + lm2=$(( l - 2 )) + + if [ "${kv[1]:$lm1:1}" != '"' ] && [ "${kv[1]:$lm2:1}" != '"' ] && [ "${kv[1]:$lm1:1}" != ';' ] ; then + printf '"' + fi + + # shellcheck disable=SC2030,SC2031 + did_emit=1 + echo + done + + if (( did_emit == 1 )); then + return 0 + fi + + return 1 + } + + return $? +} + +if [[ -f "$BPKG_USER_CONFIG_FILE" ]] && [ -z "$BPKG_USER_CONFIG_FILE_LOADED" ]; then + export BPKG_USER_CONFIG_FILE + export BPKG_USER_CONFIG_FILE_LOADED="1" + # shellcheck disable=SC1090 + source "$BPKG_USER_CONFIG_FILE_LOADED" +fi + +if [[ -f "$BPKG_LOCAL_CONFIG_FILE" ]] && [ -z "$BPKG_LOCAL_CONFIG_FILE_LOADED" ]; then + export BPKG_LOCAL_CONFIG_FILE + export BPKG_LOCAL_CONFIG_FILE_LOADED="1" + # shellcheck disable=SC1090 + source "$BPKG_LOCAL_CONFIG_FILE" +fi + +## Use as lib or perform install +if [[ ${BASH_SOURCE[0]} != "$0" ]]; then + export -f bpkg_env +else + bpkg_env "$@" + exit $? +fi diff --git a/lib/install/install.sh b/lib/install/install.sh index b275469..937d3a5 100755 --- a/lib/install/install.sh +++ b/lib/install/install.sh @@ -1,17 +1,12 @@ #!/bin/bash - -# Include config rc file if found -CONFIG_FILE="$HOME/.bpkgrc" -# shellcheck disable=SC1090 -[[ -f "$CONFIG_FILE" ]] && source "$CONFIG_FILE" - -## set defaults -if [[ ${#BPKG_REMOTES[@]} -eq 0 ]]; then - BPKG_REMOTES[0]=${BPKG_REMOTE-https://raw.githubusercontent.com} - BPKG_GIT_REMOTES[0]=${BPKG_GIT_REMOTE-https://github.com} +if ! type -f bpkg-env &>/dev/null; then + echo "error: bpkg-env not found, aborting" + exit 1 +else + # shellcheck disable=SC2230 + # shellcheck source=lib/env/env.sh + source "$(which bpkg-env)" fi -BPKG_USER="${BPKG_USER:-bpkg}" -BPKG_DEPS="${BPKG_DEPS:-deps}" let prevent_prune=0 @@ -278,7 +273,7 @@ bpkg_install_from_remote () { } if [[ ${#pkg_parts[@]} -eq 1 ]]; then - user="$BPKG_USER" + user="$BPKG_PACKAGE_DEFAULT_USER" name="${pkg_parts[0]}" elif [[ ${#pkg_parts[@]} -eq 2 ]]; then user="${pkg_parts[0]}" @@ -464,17 +459,17 @@ bpkg_install_from_remote () { ## perform local install otherwise else ## copy 'bpkg.json' or 'package.json' over - save_remote_file "$url/$package_file" "$cwd/$BPKG_DEPS/$name/$package_file" "$auth_param" + save_remote_file "$url/$package_file" "$cwd/$BPKG_PACKAGE_DEPS/$name/$package_file" "$auth_param" - ## make '$BPKG_DEPS/' directory if possible - mkdir -p "$cwd/$BPKG_DEPS/$name" + ## make '$BPKG_PACKAGE_DEPS/' directory if possible + mkdir -p "$cwd/$BPKG_PACKAGE_DEPS/$name" - ## make '$BPKG_DEPS/bin' directory if possible - mkdir -p "$cwd/$BPKG_DEPS/bin" + ## make '$BPKG_PACKAGE_DEPS/bin' directory if possible + mkdir -p "$cwd/$BPKG_PACKAGE_DEPS/bin" # install package dependencies info "Install dependencies for $name" - (cd "$cwd/$BPKG_DEPS/$name" && bpkg getdeps) + (cd "$cwd/$BPKG_PACKAGE_DEPS/$name" && bpkg getdeps) ## grab each script and place in deps directory for script in "${scripts[@]}"; do @@ -483,13 +478,13 @@ bpkg_install_from_remote () { local scriptname="$(echo "$script" | xargs basename )" info "fetch" "$url/$script" - info "write" "$cwd/$BPKG_DEPS/$name/$script" - save_remote_file "$url/$script" "$cwd/$BPKG_DEPS/$name/$script" "$auth_param" + info "write" "$cwd/$BPKG_PACKAGE_DEPS/$name/$script" + save_remote_file "$url/$script" "$cwd/$BPKG_PACKAGE_DEPS/$name/$script" "$auth_param" scriptname="${scriptname%.*}" - info "$scriptname to PATH" "$cwd/$BPKG_DEPS/bin/$scriptname" - ln -si "$cwd/$BPKG_DEPS/$name/$script" "$cwd/$BPKG_DEPS/bin/$scriptname" - chmod u+x "$cwd/$BPKG_DEPS/bin/$scriptname" + info "$scriptname to PATH" "$cwd/$BPKG_PACKAGE_DEPS/bin/$scriptname" + ln -si "$cwd/$BPKG_PACKAGE_DEPS/$name/$script" "$cwd/$BPKG_PACKAGE_DEPS/bin/$scriptname" + chmod u+x "$cwd/$BPKG_PACKAGE_DEPS/bin/$scriptname" fi ) done @@ -500,8 +495,8 @@ bpkg_install_from_remote () { ( if [[ "$file" ]];then info "fetch" "$url/$file" - info "write" "$cwd/$BPKG_DEPS/$name/$file" - save_remote_file "$url/$file" "$cwd/$BPKG_DEPS/$name/$file" "$auth_param" + info "write" "$cwd/$BPKG_PACKAGE_DEPS/$name/$file" + save_remote_file "$url/$file" "$cwd/$BPKG_PACKAGE_DEPS/$name/$file" "$auth_param" fi ) done diff --git a/lib/run/run.sh b/lib/run/run.sh index 3c598d8..15e3266 100755 --- a/lib/run/run.sh +++ b/lib/run/run.sh @@ -1,7 +1,5 @@ #!/bin/bash -shopt -s extglob - if ! type -f bpkg-utils &>/dev/null; then echo "error: bpkg-utils not found, aborting" exit 1 @@ -11,6 +9,15 @@ else source "$(which bpkg-utils)" fi +if ! type -f bpkg-env &>/dev/null; then + echo "error: bpkg-env not found, aborting" + exit 1 +else + # shellcheck disable=SC2230 + # shellcheck source=lib/env/env.sh + source "$(which bpkg-env)" +fi + if ! type -f bpkg-install &>/dev/null; then echo "error: bpkg-install not found, aborting" exit 1 @@ -96,21 +103,30 @@ bpkg_run () { esac done - local cmd="$(bpkg_package commands "$1")" + local cmd="$(bpkg_package commands "$1" 2>/dev/null)" if [ -n "$cmd" ]; then - if test -f bpkg.json || test -f package.json; then - BPKG_SCRIPT_SOURCES=$(find . -name '*.sh') - export BPKG_SCRIPT_SOURCES - fi - - export BPKG_NAME="$(bpkg_package name)" - export BPKG_REPO="$(bpkg_package repo)" - export BPKG_VERSION="$(bpkg_package version)" + # shellcheck disable=SC2230 + # shellcheck source=lib/env/env.sh + source "$(which bpkg-env)" + + local parts=() + # shellcheck disable=SC2086 + read -r -a parts <<< $cmd + local args=() + local prefix="${parts[0]}" + + for (( i = 1; i < ${#parts[@]}; i++ )); do + if [[ "${parts[$i]}" =~ \*.\* ]]; then + args+=($(find . -wholename "${parts[$i]}")) + else + args+=("${parts[$i]}") + fi + done shift # shellcheck disable=SC2068 - eval "$cmd" $@ + eval "$prefix" ${args[@]} $@ return $? fi @@ -129,10 +145,10 @@ bpkg_run () { cd "$dest" || return $? if [ -z "$name" ]; then - name="$(bpkg_package name)" + name="$(bpkg_package name 2>/dev/null)" fi - cmd="$(bpkg_package commands "$1")" + cmd="$(bpkg_package commands "$1" 2>/dev/null)" shift popd >/dev/null || return $? @@ -144,20 +160,26 @@ bpkg_run () { # shellcheck disable=SC1090 source "$(which "$name")" else - if test -f bpkg.json || test -f package.json; then - BPKG_SCRIPT_SOURCES=$(find . -name '*.sh') - export BPKG_SCRIPT_SOURCES - fi - - export BPKG_NAME="$(bpkg_package name)" - export BPKG_REPO="$(bpkg_package repo)" - export BPKG_VERSION="$(bpkg_package version)" + # shellcheck disable=SC2230 + # shellcheck source=lib/env/env.sh + source "$(which bpkg-env)" if [ -n "$cmd" ]; then + local parts=() + # shellcheck disable=SC2086 + read -r -a parts <<< $cmd + local args=() + local prefix="${parts[0]}" + + for (( i = 1; i < ${#parts[@]}; i++ )); do + if [[ "${parts[$i]}" =~ \*.\* ]]; then + args+=($(find . -wholename "${parts[$i]}")) + fi + done + shift # shellcheck disable=SC2068 - eval "$cmd" $@ - return $? + eval "$prefix" ${args[@]} $@ fi # shellcheck disable=SC2068 @@ -171,10 +193,7 @@ bpkg_run () { ## Use as lib or perform install if [[ ${BASH_SOURCE[0]} != "$0" ]]; then export -f bpkg_run -elif validate_parameters; then - bpkg_run "$@" - exit $? else - #param validation failed + bpkg_run "$@" exit $? fi diff --git a/lib/show/show.sh b/lib/show/show.sh index e42081e..a40e391 100755 --- a/lib/show/show.sh +++ b/lib/show/show.sh @@ -1,4 +1,9 @@ #!/bin/bash +# Include config rc file if found +CONFIG_FILE="$HOME/.bpkgrc" +# shellcheck disable=SC1090 +[[ -f "$CONFIG_FILE" ]] && source "$CONFIG_FILE" + VERSION="0.1.0" @@ -127,7 +132,7 @@ bpkg_show () { local readme=0 local sources=0 local pkg="" - for opt in "${@}"; do + for opt in "$@"; do case "$opt" in -V|--version) echo "${VERSION}" @@ -192,7 +197,7 @@ bpkg_show () { IFS=$'\n' return 0 fi - done < "${BPKG_REMOTE_INDEX_FILE}" + done < "$BPKG_REMOTE_INDEX_FILE" IFS="$OLDIFS" i=$((i+1)) @@ -205,5 +210,5 @@ bpkg_show () { if [[ ${BASH_SOURCE[0]} != "$0" ]]; then export -f bpkg_show elif bpkg_validate; then - bpkg_show "${@}" + bpkg_show "$@" fi diff --git a/lib/source/source.sh b/lib/source/source.sh index ecbf9ed..d00cd91 100755 --- a/lib/source/source.sh +++ b/lib/source/source.sh @@ -18,10 +18,7 @@ bpkg_source () { ## Use as lib or perform install if [[ ${BASH_SOURCE[0]} != "$0" ]]; then export -f bpkg_source -elif validate_parameters; then - bpkg_source "$@" - exit $? else - #param validation failed + bpkg_source "$@" exit $? fi diff --git a/lib/utils/utils.sh b/lib/utils/utils.sh index 7267ab3..b7178c9 100755 --- a/lib/utils/utils.sh +++ b/lib/utils/utils.sh @@ -14,14 +14,22 @@ bpkg_initrc() { if [ ${#BPKG_REMOTES[@]} -eq 0 ]; then BPKG_REMOTES[0]=${BPKG_REMOTE-https://raw.githubusercontent.com} BPKG_GIT_REMOTES[0]=${BPKG_GIT_REMOTE-https://github.com} + + export BPKG_REMOTES + export BPKG_GIT_REMOTE + export BPKG_GIT_REMOTES fi - BPKG_USER="${BPKG_USER:-"bpkg"}" - BPKG_INDEX=${BPKG_INDEX:-"$HOME/.bpkg/index"} + + export BPKG_PACKAGE_USER="${BPKG_PACKAGE_USER:-"bpkg"}" + export BPKG_INDEX=${BPKG_INDEX:-"$HOME/.bpkg/index"} + + bpkg_validate + + return $? } ## check parameter consistency bpkg_validate () { - bpkg_initrc if [ ${#BPKG_GIT_REMOTES[@]} -ne ${#BPKG_REMOTES[@]} ]; then error "$(printf 'BPKG_GIT_REMOTES[%d] differs in size from BPKG_REMOTES[%d] array' "${#BPKG_GIT_REMOTES[@]}" "${#BPKG_REMOTES[@]}")" return 1 @@ -91,43 +99,43 @@ bpkg_info () { bpkg_select_remote () { local remote=$1 local git_remote=$2 - BPKG_REMOTE_HOST=$(echo "$git_remote" | sed 's/.*:\/\///' | sed 's/\/$//' | tr '/' '_') - BPKG_REMOTE_INDEX="$BPKG_INDEX/$BPKG_REMOTE_HOST" + export BPKG_REMOTE_HOST=$(echo "$git_remote" | sed 's/.*:\/\///' | sed 's/\/$//' | tr '/' '_') + export BPKG_REMOTE_INDEX="$BPKG_INDEX/$BPKG_REMOTE_HOST" # shellcheck disable=SC2034 - BPKG_REMOTE_INDEX_FILE="$BPKG_REMOTE_INDEX/index.txt" - BPKG_OAUTH_TOKEN="" - BPKG_CURL_AUTH_PARAM="" - BPKG_GIT_REMOTE=$git_remote - BPKG_AUTH_GIT_REMOTE=$git_remote + export BPKG_REMOTE_INDEX_FILE="$BPKG_REMOTE_INDEX/index.txt" + export BPKG_OAUTH_TOKEN="" + export BPKG_CURL_AUTH_PARAM="" + export BPKG_GIT_REMOTE=$git_remote + export BPKG_AUTH_GIT_REMOTE=$git_remote if [ "${remote:0:10}" == "raw-oauth|" ]; then OLDIFS="${IFS}" IFS="|" # shellcheck disable=SC2206 local remote_parts=($remote) IFS="${OLDIFS}" - BPKG_OAUTH_TOKEN=${remote_parts[1]} + export BPKG_OAUTH_TOKEN=${remote_parts[1]} # shellcheck disable=SC2034 - BPKG_CURL_AUTH_PARAM="-u $BPKG_OAUTH_TOKEN:x-oauth-basic" - BPKG_REMOTE=${remote_parts[2]} + export BPKG_CURL_AUTH_PARAM="-u $BPKG_OAUTH_TOKEN:x-oauth-basic" + export BPKG_REMOTE=${remote_parts[2]} if [[ "$git_remote" == https://* ]] && [[ "$git_remote" != *x-oauth-basic* ]] && [[ "$git_remote" != *${BPKG_OAUTH_TOKEN}* ]]; then # shellcheck disable=SC2034 - BPKG_AUTH_GIT_REMOTE=${git_remote/https:\/\//https:\/\/$BPKG_OAUTH_TOKEN:x-oauth-basic@} + export BPKG_AUTH_GIT_REMOTE=${git_remote/https:\/\//https:\/\/$BPKG_OAUTH_TOKEN:x-oauth-basic@} fi else - BPKG_REMOTE=$remote + export BPKG_REMOTE="$remote" fi } -## given a user and name, sets BPKG_RAW_PATH using the available +## given a user and name, sets BPKG_REMOTE_RAW_PATH using the available ## BPKG_REMOTE and BPKG_OAUTH_TOKEN details bpkg_select_raw_path() { local user=$1 local name=$2 if [ "$BPKG_OAUTH_TOKEN" == "" ]; then - BPKG_RAW_PATH="$BPKG_REMOTE/$user/$name" + export BPKG_REMOTE_RAW_PATH="$BPKG_REMOTE/$user/$name" else # shellcheck disable=SC2034 - BPKG_RAW_PATH="$BPKG_REMOTE/$user/$name/raw" + Export BPKG_REMOTE_RAW_PATH="$BPKG_REMOTE/$user/$name/raw" fi return 0 } diff --git a/setup.sh b/setup.sh index 4c20fdf..1ffea44 100755 --- a/setup.sh +++ b/setup.sh @@ -69,7 +69,7 @@ if [ -z "$PREFIX" ]; then fi # All 'bpkg' supported commands -CMDS="json install package term suggest init utils update list show getdeps run source" +CMDS="json install package term suggest init utils update list show getdeps run source env" make_install () { local source