1
0
mirror of https://codeberg.org/kiss-community/kiss synced 2024-10-03 15:00:53 -06:00
kiss/kiss-new
2019-06-29 01:33:02 +03:00

150 lines
4.5 KiB
Bash
Executable File

#!/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.
#
# Where possible the package manager should "error first".
# Check things first, die is necessary and continue if all is well.
#
# 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"
}
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
}
args() {
# Parse script arguments manually. POSIX 'sh' has no 'getopts'
# 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.
# 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.
while [ "$1" ]; do
case $1 in
# Build the list of packages.
b*)
;;
# List installed packages.
l*)
shift
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
;;
esac
done
}
main() {
kiss=${0##*/}
args "$@"
}
main "$@"