diff options
| author | David Vazgenovich Shakaryan <dvshakaryan@gmail.com> | 2025-12-19 22:40:15 -0800 |
|---|---|---|
| committer | David Vazgenovich Shakaryan <dvshakaryan@gmail.com> | 2025-12-19 22:40:15 -0800 |
| commit | ab5766625df66a33101d96fe8b717a19707e6598 (patch) | |
| tree | d9da4754b0f57365dac2f38b187a2b75b38e1de5 /gbpm.sh | |
| parent | f1301dd07b68370fd839ee9d4f6ff96997336730 (diff) | |
| download | gbpm-ab5766625df66a33101d96fe8b717a19707e6598.tar.gz gbpm-ab5766625df66a33101d96fe8b717a19707e6598.tar.xz | |
genericisev0.4
Diffstat (limited to 'gbpm.sh')
| -rwxr-xr-x | gbpm.sh | 176 |
1 files changed, 176 insertions, 0 deletions
@@ -0,0 +1,176 @@ +#!/usr/bin/env bash +# +# Copyright 2014 David Vazgenovich Shakaryan +# Distributed under the terms of the MIT License. +# +# gbpm +# https://git.potato.am/gbpm.git/ +# Manage multiple Python/Ruby/etc. installations with no black magic. +# +# Output must be executed: gbpm() { . <(/path/to/gbpm.sh "${@}"); } + +GBPM_VERSION='0.4' + +: ${GBPM_OPTS_PATH:="${HOME}/.pythons"} + +_echo() { + echo "echo '${@//\'/\'\\\'\'}'" +} + +_export() { + echo "export PATH='${PATH//\'/\'\\\'\'}'" + echo 'hash -r' +} + +_warn() { + echo "echo 'gbpm: ${@//\'/\'\\\'\'}' >&2" +} + +_die() { + [[ -n "${@}" ]] && _warn "${@}" + + echo 'false' + exit 1 +} + +_populate_dirs() { + [[ -d "${GBPM_OPTS_PATH}" ]] \ + || _die "directory ${GBPM_OPTS_PATH} does not exist" + + mapfile -td $'\0' dirs < <(shopt -s nullglob; + printf '%s\0' "${GBPM_OPTS_PATH}"/* | sort -zV) + + [[ -n "${dirs}" ]] || _die "directory ${GBPM_OPTS_PATH} is empty" +} + +_populate_selected() { + local dir dirs + + mapfile -td : dirs < <(printf %s "${PATH}") + + selected=() + for dir in "${dirs[@]}"; do + if [[ "${dir}" == "${GBPM_OPTS_PATH}/"* ]]; then + dir="${dir%/bin}" + selected+=("${dir##*/}") + fi + done + + [[ "${#selected[@]}" -ne 0 ]] || return 1 + [[ "${#selected[@]}" -eq 1 ]] \ + || _warn 'warning: multiple managed paths found in PATH' +} + +_clear() { + local dir dirs cdirs + + mapfile -td : dirs < <(printf %s "${PATH}") + + for dir in "${dirs[@]}"; do + if [[ "${dir}" == "${GBPM_OPTS_PATH}/"* ]]; then + _echo "removing ${dir} from PATH" + else + cdirs+=("${dir}") + fi + done + + [[ "${#cdirs[@]}" -ne "${#dirs[@]}" ]] || return 1 + + PATH="$(IFS=':'; echo "${cdirs[*]}")" +} + +_add() { + _echo "adding ${1}/bin to PATH" + + PATH="${1}/bin:${PATH}" +} + +cmd_ls() { + local dir dirs selected str + + _populate_dirs + _populate_selected + + for dir in "${dirs[@]}"; do + str=" ${dir##*/}" + + [[ "${dir##*/}" == "${selected}" ]] && str="${str/ /*}" + + _echo "${str}" + done +} + +cmd_get() { + local dir selected + + _populate_selected || _die 'no managed path found in PATH' + + for dir in "${selected[@]}"; do + _echo "${dir}" + done +} + +cmd_set() { + [[ -n "${1}" ]] || _die 'set command requires an argument' + + local dir dirs match match_start + + _populate_dirs + + for dir in "${dirs[@]}"; do + [[ "${dir##*/}" == *"${1}"* ]] || continue + + match="${dir}" + + # match from start of version is preferred. we assume the + # version is at the beginning of the directory name or + # immediately following a hyphen. this avoids unintuitive + # behaviour like `2.1' matching `3.2.1' over `2.1.0'. + if [[ "${dir##*/}" == "${1}"* || + "${dir##*/}" == *-"${1}"* ]]; then + match_start="${dir}" + fi + done + + [[ -n "${match}" ]] || _die 'no matching version found' + [[ -n "${match_start}" ]] && match="${match_start}" + + _clear + _add "${match}" + _export +} + +cmd_clear() { + _clear || _die 'no managed path found in PATH' + _export +} + +cmd_version() { + _echo "gbpm ${GBPM_VERSION}" +} + +cmd_help() { + _echo 'Usage: gbpm <command> [args]' + _echo + _echo 'Commands:' + _echo ' ls List all available versions' + _echo ' get Display currently selected version' + _echo ' set Select specified version' + _echo ' clear Unselect any selected versions' + _echo ' version Display gbpm version' +} + +case "${1}" in + 'ls') + cmd_ls ;; + 'get') + cmd_get ;; + 'set') + cmd_set "${2}" ;; + 'clear') + cmd_clear ;; + 'version') + cmd_version ;; + *) + cmd_help ;; +esac |
