350 lines
10 KiB
Bash
Executable file
350 lines
10 KiB
Bash
Executable file
#!/usr/bin/env sh
|
|
|
|
# Licensed under ArAr v2 license: https://files.ari-web.xyz/files/ArAr.ari-archer.LICENSE
|
|
# Description: manage, switch and template licenses
|
|
|
|
# DEPENDS ON:
|
|
# general utilities: coreutils [head, awk, ...]
|
|
# license picker: fzf (optional)
|
|
# automatic config generation: git (optional)
|
|
# colours: ncurses (optional) [tput]
|
|
|
|
set -e
|
|
|
|
export VERSION='1.3'
|
|
|
|
# Init
|
|
|
|
if [ ! -d "$HOME" ]; then
|
|
# shellcheck disable=2016
|
|
{
|
|
echo 'FATAL: $HOME is not set to a valid directory'
|
|
echo 'TIP: try running: export HOME="$(eval echo '~')"'
|
|
} 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
depend() { command -v -- "$1" >/dev/null || (echo "FATAL: depend(): Dependency '$1' broken" 1>&2 && exit 11); }
|
|
|
|
# Colours (requires ncurses)
|
|
|
|
if [ "$LMGR_COLOURS" != 0 ]; then
|
|
depend 'tput'
|
|
|
|
RED=$(tput setaf 1)
|
|
GREEN=$(tput setaf 2)
|
|
YELLOW=$(tput setaf 3)
|
|
BRIGHT=$(tput bold)
|
|
RESET=$(tput sgr0)
|
|
fi
|
|
|
|
# Aliases
|
|
|
|
alias lless='less -NrIMJ --use-color --incsearch --line-num-width=2'
|
|
alias ffind='find -L'
|
|
|
|
# Constants
|
|
|
|
LICENSE_DIR="$HOME/.config/licenses"
|
|
LICENSE_SED='s/^@//'
|
|
|
|
# Utility functions
|
|
|
|
error() { printf " ${RED}*${RESET} %s\n" "$1" 1>&2; }
|
|
warn() { printf " ${YELLOW}*${RESET} %s\n" "$1" 1>&2; }
|
|
info() { printf " ${GREEN}*${RESET} %s\n" "$1"; }
|
|
einfo() { printf " ${BRIGHT}*${RESET} %s\n" "$1"; }
|
|
|
|
check_valid_license() {
|
|
lic="$(echo "$1" | sed "$LICENSE_SED")"
|
|
echo "$1" | grep -qi '^@' || (error "License '$lic' is not valid" && exit 9)
|
|
[ ! -f "$LICENSE_DIR"/"$lic" ] && (error "License '$lic' does not exist" && exit 10)
|
|
|
|
return 0
|
|
}
|
|
|
|
sed_escape() { echo "$1" | sed -e 's/[\/&]/\\&/g'; }
|
|
|
|
yn() {
|
|
printf " %s$([ "$1" ] && echo ' ')[y/n] " "$1"
|
|
|
|
read -r yn
|
|
[ "$yn" = 'y' ] || exit 0
|
|
}
|
|
|
|
# Functions
|
|
|
|
list_licenses() { ffind "$LICENSE_DIR" -maxdepth 1 -type f -printf " ${BRIGHT}*${RESET} @%f\n"; }
|
|
|
|
usage() {
|
|
echo " License manager v$VERSION"
|
|
echo ' manage, switch and template licenses'
|
|
echo ''
|
|
echo " \$AUTHOR_NAME -- '$AUTHOR_NAME'"
|
|
echo " \$AUTHOR_EMAIL -- '$AUTHOR_EMAIL'"
|
|
echo " \$AUTHOR_WEBSITE -- '$AUTHOR_WEBSITE'"
|
|
echo " \$LICENSE_DIR -- '$LICENSE_DIR'"
|
|
echo ''
|
|
echo " [ENV=VAL ...] $(basename "$0") <subcommand | @license>"
|
|
echo ''
|
|
echo ' help h show usage'
|
|
echo ' list-licenses l list awailable licenses'
|
|
echo ' current-license c show current active project license'
|
|
echo ' pick-license p pick a license in a FZF menu'
|
|
echo ' preview-license P @license_name preview a license template'
|
|
echo ' remove-license r remove all licenses from the current project'
|
|
echo " search-license s '<query | patten>' search for license"
|
|
echo ' template-help T print help for templating'
|
|
echo " new-template t 'template_name' create a new license template"
|
|
echo ' delete-license R @license_name ... delete a license from templates'
|
|
echo ' new-config C create a default config overwriting current one'
|
|
echo ' check-conflict k check if current licene(s) are conflicting'
|
|
echo ''
|
|
echo " LMGR_COLOURS=0|[1] turn colour on (1) or off (0) [${LMGR_COLOURS:-1}]"
|
|
}
|
|
|
|
make_new_config() {
|
|
mkdir -p "$HOME"/.config
|
|
|
|
{
|
|
echo '#!/usr/bin/env sh'
|
|
echo "export AUTHOR_NAME='$(git config user.name || echo "${USER}")'"
|
|
echo "export AUTHOR_EMAIL='$(git config user.email || echo "${USER}@gmail.com")'"
|
|
echo "export AUTHOR_WEBSITE='https://example.com/'"
|
|
echo "export LICENSE_DIR='$LICENSE_DIR'"
|
|
} >"$HOME"/.config/license.conf
|
|
|
|
warn "Make sure to edit '$HOME/.config/license.conf' to change \$AUTHOR_WEBSITE"
|
|
}
|
|
|
|
show_license() {
|
|
l_name='LICENSE'
|
|
[ -f UNLICENSE ] && l_name='UNLICENSE'
|
|
|
|
if [ -f "$l_name" ]; then
|
|
head -n1 "$l_name" | sed 's/^\s*//; s/\s*$//'
|
|
else
|
|
echo 'strong copyright (no license)'
|
|
fi
|
|
}
|
|
|
|
check_license_conflict() {
|
|
if [ -f ./LICENSE ] && [ -f ./UNLICENSE ]; then
|
|
error 'Licensing conflict: UNLICENSE and LICENSE both found'
|
|
|
|
printf ' Do you either (1) Remove LICENSE or (2) Remove UNLICENSE ? [1/2] '
|
|
read -r lr
|
|
|
|
case "$lr" in
|
|
1) rm LICENSE ;;
|
|
2) rm UNLICENSE ;;
|
|
*) error "'$lr' is not an option" && exit 1 ;;
|
|
esac || (error 'Could not resolve licensing conflict' && exit 6)
|
|
fi
|
|
}
|
|
|
|
get_license() {
|
|
check_valid_license "$1"
|
|
|
|
check_license_conflict
|
|
|
|
user_license="$(echo "$1" | sed "$LICENSE_SED")"
|
|
|
|
if [ ! -f "$LICENSE_DIR"/"$user_license" ]; then
|
|
error "No licence by the name of '$1'"
|
|
list_licenses
|
|
error 'Use of of the above'
|
|
|
|
exit 5
|
|
elif [ -f ./LICENSE ] || [ -f ./UNLICENSE ]; then
|
|
info "Found license: $(show_license)"
|
|
yn 'Switch licenses ?'
|
|
fi
|
|
|
|
l_name='LICENSE'
|
|
[ "$(head -n1 "$LICENSE_DIR"/"$user_license")" = 'UNLICENSE' ] && l_name='UNLICENSE'
|
|
|
|
[ -f "$l_name" ] && yn "Overwrite $l_name ?"
|
|
cp -fL "$LICENSE_DIR"/"$user_license" "$l_name"
|
|
|
|
sed -i "$l_name" \
|
|
-e "s/{{PROJECT_NAME}}/$(sed_escape "$(basename "$PWD")")/g" \
|
|
-e "s/{{CURRENT_YEAR}}/$(sed_escape "$(date '+%Y')")/g" \
|
|
-e "s/{{AUTHOR_NAME}}/$(sed_escape "$AUTHOR_NAME")/g" \
|
|
-e "s/{{AUTHOR_EMAIL}}/$(sed_escape "$AUTHOR_EMAIL")/g" \
|
|
-e "s/{{AUTHOR_WEBSITE}}/$(sed_escape "$AUTHOR_WEBSITE")/g"
|
|
|
|
check_license_conflict
|
|
|
|
info "Current license now is set to $(show_license)"
|
|
}
|
|
|
|
license_picker() {
|
|
depend 'awk'
|
|
depend 'fzf'
|
|
|
|
license="$(list_licenses |
|
|
awk '{ print $2 }' |
|
|
sed "$LICENSE_SED" |
|
|
FZF_DEFAULT_OPTS='' fzf --layout=reverse --height=20 --no-mouse -i --preview "cat $LICENSE_DIR/{}" || echo '')"
|
|
|
|
if [ -z "$license" ]; then
|
|
license_picker
|
|
return
|
|
fi
|
|
|
|
get_license "@$license"
|
|
}
|
|
|
|
search_license() {
|
|
for lic in $(list_licenses | awk '{ print $2 }' | sed "$LICENSE_SED"); do
|
|
if echo "$lic $(head -n8 "$LICENSE_DIR"/"$lic")" | grep -iq "$1"; then
|
|
einfo "@$lic"
|
|
fi
|
|
done
|
|
}
|
|
|
|
remove_license() {
|
|
einfo 'Are you sure you want to unlicense this project ?'
|
|
yn
|
|
|
|
rm -f UNLICENSE LICENSE 2>/dev/null || true
|
|
info "Current license now is set to $(show_license)"
|
|
}
|
|
|
|
templating_help() {
|
|
{
|
|
echo 'Templating'
|
|
echo ''
|
|
echo 'To template a license you need to create a file named'
|
|
echo "the same like you want to refer to your license, let's say \`hello\` in this example"
|
|
echo "so now create a file called hello in '$LICENSE_DIR/hello'"
|
|
echo ''
|
|
echo 'Now you can make your license there, now onto templating'
|
|
echo ''
|
|
echo 'The templating "language" is pretty simple, all syntax goes in {{...}}'
|
|
echo 'So the variables are:'
|
|
echo ' * {{PROJECT_NAME}} -- The current project name (basename of current directory)'
|
|
echo ' * {{CURRENT_YEAR}} -- The current year'
|
|
echo " * {{AUTHOR_NAME}} -- The author's full name"
|
|
echo " * {{AUTHOR_EMAIL}} -- The author's email"
|
|
echo " * {{AUTHOR_WEBSITE}} -- The author's website"
|
|
echo ''
|
|
echo 'Example of a template: https://raw.githubusercontent.com/TruncatedDinosour/dotfiles-cleaned/gentoo/dotfiles/config/licenses/ArAr2'
|
|
} | lless
|
|
}
|
|
|
|
new_template() {
|
|
if [ ! "$1" ]; then
|
|
printf 'License name/alias (spaces will be removed) -- '
|
|
read -r ln
|
|
else
|
|
ln="$1"
|
|
fi
|
|
|
|
[ -z "$ln" ] && (
|
|
error 'Cannot leave license name empty'
|
|
exit 7
|
|
)
|
|
|
|
ln="$LICENSE_DIR/$(echo "$ln" | tr -d ' ' | head -c250)"
|
|
|
|
if [ -f "$ln" ]; then
|
|
yn 'This license already exists, do you want to overwrite it ?'
|
|
fi
|
|
|
|
editor="${EDITOR:-}"
|
|
|
|
if [ -z "$editor" ]; then
|
|
printf 'Editor to open file in -- '
|
|
read -r editor
|
|
fi
|
|
|
|
[ -z "$editor" ] && (
|
|
error 'Cannot leave editor empty'
|
|
exit 8
|
|
)
|
|
|
|
depend "$(basename "$editor")"
|
|
|
|
set -x
|
|
$editor "$ln"
|
|
set +x
|
|
|
|
[ -f "$ln" ] && einfo "License '$(basename "$ln")' saved"
|
|
}
|
|
|
|
delete_license() {
|
|
check_valid_license "$1"
|
|
|
|
einfo "Delete license $1 ?"
|
|
yn && rm "$LICENSE_DIR"/"$(echo "$1" | sed "$LICENSE_SED")"
|
|
}
|
|
|
|
new_config() {
|
|
einfo "This will overwite your config, are you sure you want do do that ?"
|
|
yn
|
|
|
|
make_new_config
|
|
info 'New config made and saved'
|
|
}
|
|
|
|
main() {
|
|
if [ -f "$HOME/.config/license.conf" ]; then
|
|
# shellcheck disable=1091
|
|
. "$HOME/.config/license.conf"
|
|
else
|
|
warn 'No configuration file found. Creating it.'
|
|
make_new_config
|
|
exit 4
|
|
fi
|
|
|
|
if [ ! -d "$LICENSE_DIR" ]; then
|
|
# shellcheck disable=2088
|
|
warn "'$LICENSE_DIR' does not exist. Creating it."
|
|
mkdir -p "$LICENSE_DIR"
|
|
fi
|
|
|
|
[ -z "$1" ] && (
|
|
usage >&2
|
|
exit 1
|
|
)
|
|
|
|
ffind "$LICENSE_DIR" -not -name . -not -path "$LICENSE_DIR" -prune -not -type f -exec rm -R {} +
|
|
|
|
check_license_conflict
|
|
|
|
case "$1" in
|
|
help | h) usage ;;
|
|
list-licenses | l) list_licenses ;;
|
|
current-license | c) einfo "$(show_license)" ;;
|
|
pick-license | p) license_picker ;;
|
|
preview-license | P)
|
|
check_valid_license "$2"
|
|
lless "$LICENSE_DIR"/"$(echo "$2" | sed "$LICENSE_SED")" 2>/dev/null || einfo "License $2 not found"
|
|
;;
|
|
remove-license | r) remove_license ;;
|
|
search-license | s) search_license "$2" ;;
|
|
template-help | T) templating_help ;;
|
|
new-template | t) new_template "$2" ;;
|
|
delete-license | R)
|
|
tmp_l=0
|
|
|
|
for lic in "$@"; do
|
|
if [ "$tmp_l" = 0 ]; then
|
|
tmp_l=1
|
|
continue
|
|
fi
|
|
|
|
delete_license "$lic"
|
|
done
|
|
;;
|
|
new-config | C) new_config ;;
|
|
check-conflict | k) check_license_conflict ;;
|
|
|
|
@*) check_valid_license "$1" && get_license "$1" ;;
|
|
*) error "Subcommand $1 is not known." && usage && exit 2 ;;
|
|
esac
|
|
}
|
|
|
|
main "$@"
|