2019-06-28 15:26:43 -06:00
|
|
|
#!/bin/sh -e
|
|
|
|
#
|
|
|
|
# This is a simple package manager written in POSIX 'sh' for
|
|
|
|
# KISS Linux utlizing the core unix utilites where needed.
|
|
|
|
#
|
|
|
|
# The script runs with 'set -e' enabled. It will exit on any
|
|
|
|
# non-zero return code. This ensures that no function continues
|
|
|
|
# if it fails at any point.
|
|
|
|
#
|
|
|
|
# Keep in mind that this involves extra code in the case where
|
|
|
|
# an error is optional or required.
|
|
|
|
#
|
2019-06-28 16:33:02 -06:00
|
|
|
# Where possible the package manager should "error first".
|
|
|
|
# Check things first, die is necessary and continue if all is well.
|
|
|
|
#
|
2019-06-28 15:26:43 -06:00
|
|
|
# The code below conforms to shellcheck's rules. However, some
|
|
|
|
# lint errors *are* disabled as they relate to unexpected
|
|
|
|
# behavior (which we do expect).
|
|
|
|
#
|
|
|
|
# KISS is available under the MIT license.
|
|
|
|
#
|
|
|
|
# - Dylan Araps.
|
|
|
|
|
|
|
|
die() {
|
|
|
|
# Print a message and exit with '1' (error).
|
|
|
|
printf '\033[31m!>\033[m %s\n' "$@" >&2
|
|
|
|
exit 1
|
|
|
|
}
|
|
|
|
|
|
|
|
log() {
|
|
|
|
# Print a message with a colorful arrow to distinguish
|
|
|
|
# from other output.
|
|
|
|
printf '\033[32m=>\033[m %s\n' "$@"
|
|
|
|
}
|
|
|
|
|
|
|
|
pkg_search() {
|
|
|
|
# Figure out which repository a package belongs to by
|
|
|
|
# searching for directories matching the package name
|
|
|
|
# in $KISS_PATH/*.
|
|
|
|
[ "$KISS_PATH" ] || \
|
|
|
|
die "\$KISS_PATH needs to be set." \
|
|
|
|
"Example: KISS_PATH=/packages/core:/packages/extra:/packages/xorg" \
|
|
|
|
"Repositories will be searched in the configured order." \
|
|
|
|
"The variable should work just like \$PATH."
|
|
|
|
|
|
|
|
# Disable globbing with 'set -f' to ensure that the unquoted
|
|
|
|
# variable doesn't expand into anything nasty.
|
|
|
|
# shellcheck disable=2086,2046
|
|
|
|
{
|
|
|
|
set -f
|
|
|
|
set -- "$1" $(IFS=:; find $KISS_PATH -maxdepth 1 -name "$1")
|
|
|
|
set +f
|
|
|
|
}
|
|
|
|
|
|
|
|
# A package may also not be found due to a repository not being
|
|
|
|
# readable by the current user. Either way, we need to die here.
|
|
|
|
[ -z "$2" ] && die "Package '$1' not in any repository."
|
|
|
|
|
|
|
|
printf '%s\n' "$2"
|
|
|
|
}
|
|
|
|
|
2019-06-28 16:33:02 -06:00
|
|
|
pkg_list() {
|
|
|
|
# List installed packages. As the format is files and
|
|
|
|
# diectories, this just involves a simple for loop and
|
|
|
|
# file read.
|
|
|
|
|
|
|
|
# Changing directories is similar to storing the full
|
|
|
|
# full path in a variable, only there is no variable as
|
|
|
|
# you can access children relatively.
|
|
|
|
cd "$KISS_ROOT/var/db/kiss" || \
|
|
|
|
die "KISS database doesn't exist or is inaccessible."
|
|
|
|
|
|
|
|
# Optional arguments can be passed to check for specific
|
|
|
|
# packages. If no arguments are passed, list all. As we
|
|
|
|
# loop over '$@', if there aren't any arguments we can
|
|
|
|
# just set the directory contents to the argument list.
|
|
|
|
[ "$1" ] || set -- *
|
|
|
|
|
|
|
|
# Loop over each version file and warn if one doesn't exist.
|
|
|
|
# Supress errors from 'read' as we print our own message.
|
|
|
|
for pkg; do
|
|
|
|
[ -d "$pkg" ] || {
|
|
|
|
log "Package '$pkg' is not installed."
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
[ -f "$pkg/version" ] || {
|
|
|
|
log "Warning: Package '$pkg' has no version file."
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
read -r version release < "$pkg/version" &&
|
|
|
|
printf '%s\n' "${pkg%/*} $version-$release"
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
2019-06-28 15:26:43 -06:00
|
|
|
args() {
|
|
|
|
# Parse script arguments manually. POSIX 'sh' has no 'getopts'
|
2019-06-28 16:33:02 -06:00
|
|
|
# or equivalent built in. This is rather easy to do in our case
|
|
|
|
# since the first argument is always an "action" and the arguments
|
|
|
|
# that follow are all package names.
|
2019-06-28 15:26:43 -06:00
|
|
|
|
2019-06-28 16:33:02 -06:00
|
|
|
# Actions can be abbreviated to their first letter. This saves
|
|
|
|
# keystrokes once you memorize themand it also has the side-effect
|
|
|
|
# of "correcting" spelling mistakes assuming the first letter is
|
|
|
|
# right.
|
2019-06-28 15:26:43 -06:00
|
|
|
while [ "$1" ]; do
|
2019-06-28 16:33:02 -06:00
|
|
|
case $1 in
|
|
|
|
# Build the list of packages.
|
2019-06-28 15:26:43 -06:00
|
|
|
b*)
|
2019-06-28 16:33:02 -06:00
|
|
|
|
|
|
|
;;
|
|
|
|
|
|
|
|
# List installed packages.
|
|
|
|
l*)
|
2019-06-28 15:26:43 -06:00
|
|
|
shift
|
2019-06-28 16:33:02 -06:00
|
|
|
pkg_list "$@"
|
|
|
|
exit
|
|
|
|
;;
|
|
|
|
|
|
|
|
# Print version and exit.
|
|
|
|
v*)
|
|
|
|
log "$kiss 0.1.10"
|
|
|
|
exit
|
|
|
|
;;
|
|
|
|
|
|
|
|
# Catch all invalid arguments as well as
|
|
|
|
# any help related flags (-h, --help, help).
|
|
|
|
*)
|
|
|
|
log "$kiss [b|c|i|l|r|u] [pkg]" \
|
|
|
|
"build: Build a package." \
|
|
|
|
"checksum: Generate checksums." \
|
|
|
|
"install: Install a package (Runs build if needed)." \
|
|
|
|
"list: List packages." \
|
|
|
|
"remove: Remove a package." \
|
|
|
|
"update: Check for updates."
|
|
|
|
exit
|
2019-06-28 15:26:43 -06:00
|
|
|
;;
|
|
|
|
esac
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
|
|
|
main() {
|
|
|
|
kiss=${0##*/}
|
|
|
|
|
|
|
|
args "$@"
|
|
|
|
}
|
|
|
|
|
|
|
|
main "$@"
|