# -*- mode: sh; sh-shell: bash -*-
# vim: set ft=bash:
# shellcheck shell=bash
# shellcheck disable=2016
### Module to install, initialize and update bar itself
function init # --hidden|--update|--update-existing - initialize bar in a workdir.
{
# shellcheck disable=2155
local origin="$(command -v bar)"
local prefix="${origin%/bin/*}"
[[ -f "$prefix/bin/bar" && -d "$prefix/share/bar/Bar.d" && -f "$prefix/share/bar/Barf" ]] ||
die "bar not properly installed, run './bar init_install <prefix>' from its git repository first"
local update=
local update_existing=
local hidden=
if [[ "${1:-}" == --update ]]; then
update=true
shift
elif [[ "${1:-}" == --update-existing ]]; then
update_existing=true
shift
elif [[ "${1:-}" == --hidden ]]; then
hidden=true
shift
fi
if [[ -z "$update" && ( -f bar || -f .bar )]]; then
die "bar already initialized"
fi
if [[ -n "$update" || -n "$update_existing" ]]; then
if [[ -f bar ]]; then
if [[ "$origin" -nt "bar" ]]; then
debug "updating 'bar'"
# prevent writing into the running script
cp -L "$origin" "bar.new"
mv "bar.new" "bar"
fi
if [[ -n "$update" ]]; then
debug "updating 'Bar.d'"
cp -Lru "$prefix/share/bar/Bar.d/"* "Bar.d"
else
debug "updating existing 'Bar.d'"
rsync -rtuL --existing "$prefix/share/bar/Bar.d/" "Bar.d/"
fi
elif [[ -f .bar ]]; then
if [[ "$origin" -nt ".bar" ]]; then
debug "updating '.bar'"
cp -L "$origin" ".bar.new"
mv ".bar.new" ".bar"
fi
if [[ -n "$update" ]]; then
debug "updating '.Bar.d'"
cp -Lru "$prefix/share/bar/Bar.d/"* ".Bar.d"
else
debug "updating existing '.Bar.d'"
rsync -rtuL --existing "$prefix/share/bar/Bar.d/" "Bar.d/"
fi
else
die "bar not initialized"
fi
return 0
fi
if [[ -z "$hidden" ]]; then
debug "installing bar"
cp -L "$origin" "bar.new"
mv "bar.new" "bar"
cp -L "$prefix/share/bar/Barf" "Barf"
cp -Lr "$prefix/share/bar/Bar.d" "Bar.d"
else
debug "installing .bar"
cp -L "$origin" ".bar"
cp -L "$prefix/share/bar/Barf" ".Barf"
cp -Lr "$prefix/share/bar/Bar.d" ".Bar.d"
fi
return 0
}
rule init_update_gitignore: is_git_toplevel? -- '
require --opt testdir
git_add_ignore ".bar.*"
[[ -v TESTDIR_PREFIX ]] && git_add_ignore "$TESTDIR_PREFIX-"\*
'
## Initialize bar in a workdir. This copies the main 'bar' script, a default 'Barf' and all
## 'Bar.d/' modules to current directory. When the workdir is a git repository then
## '.gitignore' is updated to exclude the files and directories 'bar' will use for
## temporary/testing storage. A user may edit the 'Barf' file to suit the project/personal
## preference. Unneeded modules in 'Bar.d' can be deleted. When that is done the new/changed
## files should be committed to version control.
rule init: 'called_as? bar' -
rule init: 'called_as? bar' init_update_gitignore
rule init: '!called_as bar' -- error "not called as installed bar"
## Updates a initialized working tree. That is 'bar' itself will be updated when a newer
## version is available and any module in 'Bar.d/' that exists in the local working tree will
## be updated as well. Barf will be left untouched.
rule init_update_existing: 'called_as? bar' -- init --update-existing
rule init_update_existing: 'called_as? bar' init_update_gitignore
rule init_update_existing: '!called_as bar' -- error "not called as installed bar"
## Updates a initialized working tree. That is 'bar' itself will be updated when a newer
## version is available and all modules including ones that are not present in 'Bar.d/' will
## be updated as well. Barf will be left untouched.
rule init_update: 'called_as? bar' -- init --update
rule init_update: 'called_as? bar' init_update_gitignore
rule init_update: '!called_as bar' -- error "not called as installed bar"
## Since the Barf is the users configuration we can't just update it this 'a bit mouthful'
## rule will do a merge of the local './Barf' with the shipped 'Barf.default'. This will
## leave conflicts which have to be manually resolved. This is only useful when the shipped
## when 'Barf' was not or only slightly edited.
function init_update_merge_barf
{
# shellcheck disable=2155
local origin="$(command -v bar)"
local prefix="${origin%/bin/*}"
if [[ -f "$prefix/share/bar/Barf" ]]; then
info "merging Barf file"
else
die "bar not properly installed, run './bar init_install <prefix>' from its git repository first"
fi
if [[ -f Barf ]]; then
git merge-file --diff-algorithm=histogram ./Barf /dev/null "$prefix/share/bar/Barf" ||
note "Please check the merged Barf file conflict markers and fix them"
elif [[ -f .Barf ]]; then
git merge-file --diff-algorithm=histogram ./.Barf /dev/null "$prefix/share/bar/Barf" ||
note "Please check the merged Barf file conflict markers and fix them"
else
die "bar not initialized"
fi
}
function init_install ## [prefix] - install links in [prefix] or '~/.local'.
{
## Bar will usually exist somewhere in a users home directory where it got checked
## out. Bar does rolling releases, it is continuously improved. To make this checked out
## version available for use this 'init_install' will create symlinks at the given
## [prefix] directory or in '~/.local' by default.
local prefix="${1:-$HOME/.local}"
shift
# shellcheck disable=2155
local origin="$(realpath "$BASH_ARGV0")"
# link the main script
if [[ "$origin" != *"/bar" ]]; then
die "not called as original bar"
elif [[ -d "$prefix" && ! -f "$prefix/bin/bar" ]]; then
mkdir -p "$prefix/bin"
ln -s "$origin" "$prefix/bin/bar" || error "linking $origin to $prefix/bin/bar"
info "linked $origin to $prefix/bin/bar"
ln -s "$origin" "$prefix/bin/please" || error "linking $origin to $prefix/bin/please"
info "linked $origin to $prefix/bin/please"
fi
# link Bar.d
if [[ ! -d "$prefix/share/bar" ]]; then
mkdir -p "$prefix/share/bar"
ln -s "${origin%/*}/Bar.d" "$prefix/share/bar/Bar.d"
info "linked ${origin%/*}/Bar.d to $prefix/share/bar/Bar.d"
ln -s "${origin%/*}/Barf.default" "$prefix/share/bar/Barf"
info "linked ${origin%/*}/Barf.default to $prefix/share/bar/Barf"
ln -s "${origin%/*}/Pleasef.default" "$prefix/share/bar/Pleasef"
info "linked ${origin%/*}/Pleasef.default to $prefix/share/bar/Pleasef"
else
warn "can't link to $prefix/share/bar/"
fi
# link .config/please
if [[ -L "$HOME/.config/please/std_lib" || ! -d "$HOME/.config/please" ]]; then
mkdir -p "$HOME/.config/please"
ln -s "${origin%/*}/Bar.d/"* "$HOME/.config/please/" || true # TODO: better update handling
info "linked ${origin%/*}/Bar.d/* to $HOME/.config/please/"
else
warn "can't create to $HOME/.config/please"
fi
if [[ ! -f "$HOME/.Pleasef" ]]; then
cp -L "$prefix/share/bar/Pleasef" "$HOME/.Pleasef"
info "installed default $HOME/.Pleasef"
fi
# link bash completion
if [[ ! -d "$HOME/.bash_completion" ]]; then
mkdir -p "$HOME/.bash_completion"
fi
if [[ ! -f "$HOME/.bash_completion/bar_complete" ]]; then
ln -s "${origin%/*}/contrib/bar_complete" "$HOME/.bash_completion/bar_complete" || error "linking completion script"
info "linked ${origin%/*}/contrib/bar_complete to $HOME/.bash_completion/bar_complete"
note "To enable bash completion, source $HOME/.bash_completion/bar_complete in your .bashrc or restart your shell"
fi
}