Coexist with a desktop that already manages its tools (Omarchy)
On an Omarchy laptop bootstrap left two of almost everything: VS Code from both pacman and the tarball (two menu entries, one shared ~/.config/Code profile), and kubectl/helm/k9s/kubectx/yq/jq/node/ansible in ~/.local/bin behind mise and pacman copies that always won on PATH. The zsh helpers (op*, grmb, secrets.env) also never reached the bash login shell. - lib/fetch.sh: add `shadowed`, true when another copy of a tool comes earlier on PATH than ~/.local/bin. Always false where zshrc puts ~/.local/bin first, so VM installs are unchanged. - bin/, node/, ansible/: skip tools that are shadowed. - vscode/: defer to any system `code`, and remove a tarball copy this module installed earlier. - bash/: new module; bash port of the zshrc helpers, sourced from ~/.bashrc via a marked block. No-ops without ~/.bashrc. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
# Managed by dotfiles/bash/install.sh — copied to ~/.config/dotfiles/dotfiles.bash
|
||||
# and overwritten on the next bootstrap run. Edit bash/dotfiles.bash in the
|
||||
# dotfiles repo instead.
|
||||
#
|
||||
# The bash port of the helpers in zsh/zshrc, for hosts that keep bash as the
|
||||
# login shell (Omarchy ships its own bash config and the zsh module cannot
|
||||
# install zsh there). Only the helpers: PATH, prompt and history stay with the
|
||||
# host's own rc. Keep the two in sync — see zsh/zshrc for the full rationale
|
||||
# behind each function.
|
||||
|
||||
# grmb <branch>... — delete remote branches; takes `origin/foo` or `foo`.
|
||||
grmb() {
|
||||
local remote=origin b rc=0
|
||||
if [ "$#" -eq 0 ]; then
|
||||
echo "grmb: usage: grmb <branch>... (origin/ prefix optional)" >&2
|
||||
return 2
|
||||
fi
|
||||
git fetch --prune --quiet "$remote" || return 1
|
||||
for b in "$@"; do
|
||||
b=${b#"${remote}"/}
|
||||
if git push "$remote" --delete "$b"; then
|
||||
echo "deleted ${remote}/${b}"
|
||||
else
|
||||
echo "grmb: could not delete ${b} (already gone? check: git ls-remote --heads ${remote})" >&2
|
||||
rc=1
|
||||
fi
|
||||
done
|
||||
return $rc
|
||||
}
|
||||
|
||||
# Secrets from this user's 1Password vault, written by dotfiles/secrets/install.sh.
|
||||
# Reading a local 0600 file keeps shell startup off the network.
|
||||
_DOTFILES_CONF="$HOME/.config/dotfiles"
|
||||
[ -f "$_DOTFILES_CONF/secrets.env" ] && source "$_DOTFILES_CONF/secrets.env"
|
||||
|
||||
# opr NAME | opc NAME[=VALUE] | opc NAME VALUE | opd NAME | opl [VAULT [ITEM]] | ops
|
||||
# Same behaviour as zsh/zshrc. The service-account token is loaded only inside
|
||||
# the subshells, never into this shell's environment.
|
||||
_dotfiles_op() {
|
||||
[ -f "$_DOTFILES_CONF/op.env" ] || { echo "no $_DOTFILES_CONF/op.env; run: ops" >&2; return 1; }
|
||||
( set -a; source "$_DOTFILES_CONF/op.env"; set +a; "$@" )
|
||||
}
|
||||
_dotfiles_env_name() {
|
||||
[[ $1 =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]] && return 0
|
||||
echo "$2: '$1' is not a valid variable name" >&2; return 2
|
||||
}
|
||||
opr() {
|
||||
_dotfiles_env_name "$1" opr || return
|
||||
_dotfiles_op sh -c 'op read "op://$OP_VAULT/$OP_ITEM/$1"' opr "$1"
|
||||
}
|
||||
opc() {
|
||||
local name=$1 value=
|
||||
if [[ $1 == *=* ]]; then
|
||||
# NAME=VALUE: split on the first '=' so values may contain '='
|
||||
name=${1%%=*} value=${1#*=}
|
||||
elif (( $# >= 2 )); then
|
||||
value=$2
|
||||
fi
|
||||
_dotfiles_env_name "$name" opc || return
|
||||
if [[ -z $value ]]; then
|
||||
read -rsp "$name: " value && echo
|
||||
[[ -n $value ]] || { echo "opc: empty value for $name; nothing changed" >&2; return 1; }
|
||||
fi
|
||||
# op's exit code is unreliable after an edit it did save; read the field back.
|
||||
_dotfiles_op sh -c '
|
||||
clean() { printf "%s" "${1:-(no output)}" | sed "s/^\[ERROR\] [0-9/]* [0-9:]* //"; }
|
||||
ref="op://$OP_VAULT/$OP_ITEM/$1"
|
||||
err=$(op item edit "$OP_ITEM" --vault "$OP_VAULT" "$1[concealed]=$2" 2>&1 >/dev/null)
|
||||
if [ "$(op read "$ref" 2>/dev/null)" = "$2" ]; then
|
||||
printf "opc: saved %s\n" "$ref" >&2
|
||||
else
|
||||
printf "opc: could not save %s\n op said: %s\n check vault, item and service-account write access with: opl\n" \
|
||||
"$ref" "$(clean "$err")" >&2
|
||||
exit 1
|
||||
fi' opc "$name" "$value" && ops
|
||||
}
|
||||
opd() {
|
||||
_dotfiles_env_name "$1" opd || return
|
||||
_dotfiles_op sh -c '
|
||||
clean() { printf "%s" "${1:-(no output)}" | sed "s/^\[ERROR\] [0-9/]* [0-9:]* //"; }
|
||||
ref="op://$OP_VAULT/$OP_ITEM/$1"
|
||||
err=$(op item edit "$OP_ITEM" --vault "$OP_VAULT" "$1[delete]" 2>&1 >/dev/null)
|
||||
if ! item=$(op item get "$OP_ITEM" --vault "$OP_VAULT" --format json 2>&1); then
|
||||
printf "opd: could not re-read %s to confirm the delete\n op said: %s\n" "$ref" "$(clean "$item")" >&2
|
||||
exit 1
|
||||
elif printf "%s" "$item" | jq -r ".fields[].label" | grep -qxF "$1"; then
|
||||
printf "opd: could not delete %s\n op said: %s\n" "$ref" "$(clean "$err")" >&2
|
||||
exit 1
|
||||
fi
|
||||
printf "opd: deleted %s\n" "$ref" >&2' opd "$1" \
|
||||
&& unset "$1" && ops
|
||||
}
|
||||
opl() {
|
||||
_dotfiles_op sh -c '
|
||||
vault=${1:-$OP_VAULT} item=${2:-$OP_ITEM}
|
||||
printf "op://%s/%s\n" "$vault" "$item" >&2
|
||||
op item get "$item" --vault "$vault" --reveal --format json' opl "$@" \
|
||||
| jq -r '
|
||||
[.fields[] | select(.purpose != "NOTES")] as $f
|
||||
| ([$f[] | .label // "" | length] | max // 0) as $w
|
||||
| $f[]
|
||||
| ((.label // "") + " " * ($w - ((.label // "") | length))) as $name
|
||||
| ((.value // "") | split("\n")) as $lines
|
||||
| "\($name) \($lines[0] // "")",
|
||||
($lines[1:][] | (" " * ($w + 2)) + .)'
|
||||
}
|
||||
ops() {
|
||||
"${DOTFILES_DIR:-$HOME/.dotfiles}/secrets/install.sh" \
|
||||
&& source "$_DOTFILES_CONF/secrets.env"
|
||||
}
|
||||
Reference in New Issue
Block a user