kiss/kiss

1593 lines
45 KiB
Plaintext
Raw Normal View History

2020-05-09 18:25:38 +00:00
#!/bin/sh
# shellcheck source=/dev/null
#
2020-09-11 14:38:02 +00:00
# This is a simple package manager written in POSIX shell for use
2020-02-19 21:46:59 +00:00
# in KISS Linux (https://k1ss.org).
2019-08-19 17:07:50 +00:00
#
2020-05-12 08:46:14 +00:00
# Created by Dylan Araps.
2019-06-13 14:48:08 +00:00
2019-09-21 17:22:56 +00:00
log() {
printf '%b%s %b%s%b %s\n' \
2020-05-13 14:44:50 +00:00
"$lcol" "${3:-->}" "${lclr}${2:+$lcol2}" "$1" "$lclr" "$2" >&2
2019-09-21 17:22:56 +00:00
}
2019-06-13 14:48:08 +00:00
die() {
2020-05-07 11:46:50 +00:00
log "$1" "$2" "${3:-ERROR}"
2019-06-13 14:48:08 +00:00
exit 1
}
2020-02-18 19:28:35 +00:00
prompt() {
[ "$1" ] && log "$1"
2020-09-11 14:38:02 +00:00
2020-02-18 19:28:35 +00:00
log "Continue?: Press Enter to continue or Ctrl+C to abort here"
[ "$KISS_PROMPT" = 0 ] || read -r _
2019-09-22 11:35:07 +00:00
}
2020-01-30 07:27:25 +00:00
as_root() {
2020-09-09 13:52:18 +00:00
[ "$uid" = 0 ] || log "Using '${su:=su}' (to become ${user:=root})"
case ${su##*/} in
2020-09-14 13:41:21 +00:00
doas | sudo | sls)
2020-09-09 12:03:57 +00:00
"$su" -u "$user" -- env "$@"
;;
su)
"$su" -c "env $* <&3" "$user" 3<&0 </dev/tty
;;
*)
2020-09-27 08:57:52 +00:00
die "invalid KISS_SU value '$su' (valid: doas, sudo, sls, su)"
2020-09-09 12:03:57 +00:00
;;
2020-01-30 12:42:29 +00:00
esac
2020-01-27 08:06:56 +00:00
}
2020-09-27 06:52:03 +00:00
contains() {
_sep=${3:- }
case "${_sep}${1}${_sep}" in
*"${_sep}${2}${_sep}"*)
return 0
;;
esac
return 1
}
file_owner() {
read -r _ _ user _ <<EOF
$(ls -ld "$1")
EOF
2020-09-11 14:38:02 +00:00
id -u "${user:=root}" >/dev/null 2>&1 || user=root
}
2020-09-27 08:57:52 +00:00
run_user_hook() {
2020-09-11 14:58:16 +00:00
set -- "${1:-null}" "${2:-null}" "${3:-null}"
2020-09-09 12:03:57 +00:00
case ${KISS_HOOK:--}$1 in
2020-09-27 08:57:52 +00:00
# Provide a default post-build hook to remove files and directories
# for things we don't support out of the box. One can simply define
# their own hook to override this behavior.
2020-09-09 12:03:57 +00:00
-post-build)
2020-09-12 14:32:33 +00:00
rm -rf \
"$3/usr/share/gettext" \
"$3/usr/share/polkit-1" \
"$3/usr/share/locale" \
"$3/usr/share/info"
2020-09-09 12:03:57 +00:00
;;
[!-]*)
2020-09-11 14:58:16 +00:00
TYPE=$1 PKG=$2 DEST=$3 . "$KISS_HOOK"
2020-09-09 12:03:57 +00:00
;;
esac
}
2020-09-27 08:57:52 +00:00
run_repo_hook() {
# Execute hooks which have the executable permission set, cat hooks which
# don't. Allows packages which only need to display a message to avoid
# executing any code.
_hook=${3:-"$sys_db/$2/$1"}
[ -f "$_hook" ] ||
2020-09-27 08:57:52 +00:00
return 0
log "$2" "running $1 hook"
if [ -x "$_hook" ]; then
"$_hook"
2020-09-27 08:57:52 +00:00
else
cat "$_hook"
2020-09-27 08:57:52 +00:00
fi
}
decompress() {
2020-09-11 14:58:16 +00:00
case ${1##*.} in
bz2) bzip2 -dc ;;
lzma) lzma -dc ;;
lz) lzip -dc ;;
tar) cat ;;
tgz | gz) gzip -dc ;;
txz | xz) xz -dc ;;
zst) zstd -dc ;;
esac < "$1"
}
sh256() {
# There's no standard utility to generate sha256 checksums.
2020-09-11 14:58:16 +00:00
# This unifies various tools using the first available.
[ -e "$1" ] || return 0
2020-09-09 12:03:57 +00:00
hash=$(
sha256sum "$1" ||
sha256 -r "$1" ||
openssl dgst -sha256 -r "$1" ||
shasum -a 256 "$1" ||
digest -a sha256 "$1"
) 2>/dev/null
2020-05-13 07:28:16 +00:00
printf '%s\n' "${hash%% *}"
}
2020-09-26 05:08:10 +00:00
pkg_owner() {
set +f
2020-09-27 08:57:52 +00:00
[ "$3" ] ||
set -- "$1" "$2" "$sys_db"/*/manifest
2020-09-27 08:57:52 +00:00
2020-10-03 05:20:21 +00:00
pkg_owner=$(grep "$@")
pkg_owner=${pkg_owner%/*}
pkg_owner=${pkg_owner##*/}
2020-09-27 08:57:52 +00:00
set -f
[ "$pkg_owner" ]
2020-09-26 05:08:10 +00:00
}
2019-06-29 20:38:35 +00:00
pkg_lint() {
pkg_find "$1"
cd "$repo_dir"
2019-06-29 20:38:35 +00:00
read -r _ release 2>/dev/null < version ||
2020-10-03 08:42:58 +00:00
die "$1" "version file not found"
[ "$release" ] ||
2020-09-27 08:57:52 +00:00
die "$1" "release field not found in version file"
[ -x build ] ||
2020-09-27 08:57:52 +00:00
die "$1" "build file not found or not executable"
[ -f sources ] ||
2020-09-27 08:57:52 +00:00
log "$1" "sources file not found" WARN
2019-06-18 08:05:15 +00:00
}
pkg_find() {
2020-05-21 07:38:07 +00:00
# Figure out which repository a package belongs to by searching for
# directories matching the package name in $KISS_PATH/*.
2020-09-23 18:48:08 +00:00
_query=$1
_paths=${2:-"$KISS_PATH:$sys_db"}
_print=$3
_type=${4:--d}
2020-09-23 18:48:08 +00:00
IFS=:
set --
2019-10-01 19:40:23 +00:00
2020-09-23 18:48:08 +00:00
# Globbing is disabled, splitting is intentional.
for _path in $_paths; do
set +f
2020-09-14 09:41:28 +00:00
# Globbing enabled for search.
2020-09-23 18:48:08 +00:00
for _path2 in "$_path"/${_query%%/*}; do
test "$_type" "$_path2" &&
set -f -- "$@" "$_path2"
2020-03-23 09:41:32 +00:00
done
done
2019-06-13 16:40:50 +00:00
2020-04-20 09:14:25 +00:00
unset IFS
2020-09-12 14:33:55 +00:00
repo_dir=$1
2020-03-23 10:05:54 +00:00
2020-09-12 08:09:46 +00:00
[ "$1" ] || {
2020-09-27 08:57:52 +00:00
log "Package '$_query' not in any repository" '' ERROR
2020-09-12 08:09:46 +00:00
return 1
}
2019-06-13 16:40:50 +00:00
2020-09-23 18:48:08 +00:00
[ -z "$_print" ] ||
printf '%s\n' "$@"
2019-06-13 16:40:50 +00:00
}
2020-09-12 14:35:10 +00:00
pkg_list() {
2020-09-26 14:13:24 +00:00
[ -d "$sys_db/$1" ] || {
2020-09-27 08:57:52 +00:00
log "$1" "not installed" ERROR
2020-09-26 14:13:24 +00:00
return 1
2020-09-11 16:02:58 +00:00
}
2019-06-29 20:38:35 +00:00
2020-09-26 14:13:24 +00:00
read -r _ver 2>/dev/null < "$sys_db/$1/version" ||
_ver=null
2020-09-11 16:02:58 +00:00
2020-09-26 14:13:24 +00:00
printf '%s\n' "$1 $_ver"
2020-09-12 14:35:10 +00:00
}
2019-06-13 14:48:08 +00:00
pkg_cache() {
2020-05-23 06:25:41 +00:00
# Find the tarball of a package using a glob. Use the first found match
2020-10-03 03:43:36 +00:00
# of '<pkg_name>[#@]<pkg_version><pkg_release>.tar.*'.
pkg_find "$1"
read -r version release 2>/dev/null < "$repo_dir/version"
2020-09-11 16:02:58 +00:00
set +f
set -f -- "$bin_dir/$1"[#@]"$version-$release.tar."*
2020-09-11 16:02:58 +00:00
# Prefer '@' to '#' in tarball names.
[ -f "$2" ] && shift
tar_file=$1
[ -f "$1" ]
}
2019-06-13 14:48:08 +00:00
pkg_sources() {
2020-05-21 07:38:07 +00:00
# Download any remote package sources. The existence of local files is
# also checked.
pkg_find "$1"
[ -f "$repo_dir/sources" ] || return 0
2020-09-27 08:57:52 +00:00
log "$1" "fetching sources"
2020-09-14 13:30:59 +00:00
mkdir -p "$src_dir/$1"
cd "$src_dir/$1"
2019-06-29 20:38:35 +00:00
2020-01-16 21:45:12 +00:00
while read -r src dest || [ "$src" ]; do
2020-09-12 14:36:10 +00:00
if [ -z "${src##\#*}" ]; then
2020-09-12 08:25:05 +00:00
continue
2020-02-14 16:06:47 +00:00
2020-09-12 14:36:10 +00:00
elif [ -z "${src##git+*}" ]; then
2020-09-14 13:13:15 +00:00
printf 'found git %s\n' "${src##git+}"
2020-09-12 14:36:10 +00:00
2020-02-14 16:06:47 +00:00
elif [ -f "${src##*/}" ]; then
2020-09-14 13:13:15 +00:00
printf 'found cached %s\n' "${src##*/}"
2019-09-23 06:30:34 +00:00
elif [ -z "${src##*://*}" ]; then
2020-09-14 13:13:15 +00:00
printf 'downloading %s\n' "$src"
2020-02-11 15:33:38 +00:00
curl "$src" -fLo "${src##*/}" || {
2019-09-23 06:30:34 +00:00
rm -f "${src##*/}"
2020-09-27 08:57:52 +00:00
die "$1" "failed to download $src"
2019-09-23 06:30:34 +00:00
}
elif [ -e "$repo_dir/$src" ]; then
2020-09-14 13:13:15 +00:00
printf 'found relative %s\n' "$src"
elif [ -e "/$src" ]; then
2020-09-14 13:13:15 +00:00
printf 'found absolute %s\n' "$src"
2019-09-23 06:30:34 +00:00
else
2020-09-27 08:57:52 +00:00
die "$1" "no local file '$src'"
2019-09-23 06:30:34 +00:00
fi
done < "$repo_dir/sources"
2019-06-13 14:48:08 +00:00
}
pkg_extract() {
2020-05-21 07:38:07 +00:00
# Extract all source archives to the build directory and copy over any
# local repository files.
pkg_find "$1"
[ -f "$repo_dir/sources" ] || return 0
2020-09-27 08:57:52 +00:00
log "$1" "extracting sources"
2019-06-29 20:38:35 +00:00
2019-11-16 19:53:41 +00:00
while read -r src dest || [ "$src" ]; do
2019-09-10 08:20:05 +00:00
mkdir -p "$mak_dir/$1/$dest" && cd "$mak_dir/$1/$dest"
2019-06-29 20:38:35 +00:00
2020-09-12 14:36:49 +00:00
case $src in
2020-09-14 13:30:59 +00:00
\#* | '')
2020-09-12 14:36:49 +00:00
# Comments and blank lines.
;;
git+*)
2020-10-01 07:10:01 +00:00
url=${src##git+}
com=${url##*[@#]}
com=${com#"${url%[#@]*}"}
2020-09-27 08:57:52 +00:00
log "$1" "cloning ${url%[#@]*}"; {
git init
git remote add origin "${url%[#@]*}"
2020-10-01 07:10:01 +00:00
git fetch -t --depth 1 origin "$com" || git fetch -t
git -c advice.detachedHead=0 checkout "${com:-FETCH_HEAD}"
2020-09-27 08:57:52 +00:00
} || die "$1" "failed to clone $src"
;;
2020-01-16 21:45:12 +00:00
2020-05-11 14:34:57 +00:00
*://*.tar|*://*.tar.??|*://*.tar.???|*://*.tar.????|*://*.t?z)
decompress "$src_dir/$1/${src##*/}" \
> "$tmp_dir/.tar"
2020-05-08 19:15:16 +00:00
tar xf "$tmp_dir/.tar" ||
2020-09-27 08:57:52 +00:00
die "$1" "failed to extract ${src##*/}"
2020-05-23 06:30:45 +00:00
# Iterate over all directories in the first level of the
# tarball's manifest. This does the equivalent to GNU tar's
2020-09-14 13:30:59 +00:00
# '--strip-components 1' in a portable way.
tar tf "$tmp_dir/.tar" | while IFS=/ read -r dir _; do
# Handles tarballs with './' as top-level directory.
[ -d "${dir#.}" ] || continue
# Avoid naming conflicts.
2020-06-10 06:45:46 +00:00
mv -f "$dir" "$pid-$dir"
# First attempt to move all files up a directory level,
# if any files/directories fail (due to mv's lack of
# directory merge capability), simply do the exercise
# again and copy-merge the remaining files/directories.
2020-05-14 07:18:51 +00:00
#
2020-07-09 11:43:38 +00:00
# We can't use '-exec {} +' with any arguments between
2020-05-14 07:18:51 +00:00
# the '{}' and '+' as this is not POSIX. We must also
# use '$0' and '$@' to reference all arguments.
{
2020-06-10 06:45:46 +00:00
find "$pid-$dir/." ! -name . -prune \
2020-05-14 07:18:51 +00:00
-exec sh -c 'mv -f "$0" "$@" .' {} + ||
2020-06-10 06:45:46 +00:00
find "$pid-$dir/." ! -name . -prune \
2020-05-14 07:18:51 +00:00
-exec sh -c 'cp -fRp "$0" "$@" .' {} +
} 2>/dev/null
# Clean up after ourselves.
2020-06-10 06:45:46 +00:00
rm -rf "$pid-$dir"
done
# Clean up after ourselves.
rm -f "$tmp_dir/.tar"
;;
2019-09-23 06:30:34 +00:00
2020-04-14 14:52:39 +00:00
*://*.zip)
unzip "$src_dir/$1/${src##*/}" ||
2020-09-27 08:57:52 +00:00
die "$1" "failed to extract ${src##*/}"
2020-04-14 14:52:39 +00:00
;;
*)
# Local directory (relative).
if [ -d "$repo_dir/$src" ]; then
cp -Rf "$repo_dir/$src/." .
# Local directory (absolute).
elif [ -d "/$src" ]; then
cp -Rf "/$src/." .
# Local file (relative).
elif [ -f "$repo_dir/$src" ]; then
2020-05-21 14:28:33 +00:00
cp -f "$repo_dir/$src" .
2019-09-23 06:30:34 +00:00
# Local file (absolute).
elif [ -f "/$src" ]; then
cp -f "/$src" .
# Remote file.
elif [ -f "$src_dir/$1/${src##*/}" ]; then
cp -f "$src_dir/$1/${src##*/}" .
else
2020-09-12 15:08:33 +00:00
die "$1" "file $src not found"
fi
;;
esac
done < "$repo_dir/sources"
2019-06-13 14:48:08 +00:00
}
2019-06-29 20:38:35 +00:00
pkg_depends() {
2020-07-07 21:51:40 +00:00
# Resolve all dependencies and generate an ordered list. The deepest
# dependencies are listed first and then the parents in reverse order.
contains "$deps" "$1" || {
2020-09-22 12:39:25 +00:00
pkg_find "$1" 2>/dev/null ||:
2019-09-15 06:15:32 +00:00
2019-09-16 06:26:15 +00:00
# Recurse through the dependencies of the child packages.
2020-09-14 12:30:50 +00:00
[ -f "$repo_dir/depends" ] &&
while read -r dep _ || [ "$dep" ]; do
2020-10-03 08:18:02 +00:00
case $dep-$2 in
[!#]*-filter)
pkg_depends "$dep" "$2"
;;
2020-09-14 19:28:14 +00:00
[!#]*)
2020-10-03 08:18:02 +00:00
pkg_list "$dep" >/dev/null 2>&1 ||
pkg_depends "$dep"
2020-09-14 12:29:53 +00:00
;;
esac
done < "$repo_dir/depends"
# After child dependencies are added to the list,
# add the package which depends on them.
[ "$2" = explicit ] || deps="$deps $1"
}
2019-06-29 20:38:35 +00:00
}
pkg_order() {
# Sort a list of packages based on dependence.
for _pkg do
pkg_depends "$_pkg" filter
done
for _pkg in $deps; do
contains "$*" "$_pkg" &&
order="$order $_pkg" redro="$_pkg $redro"
done
deps=
}
2019-06-13 14:48:08 +00:00
pkg_strip() {
2020-05-21 07:38:07 +00:00
# Strip package binaries and libraries. This saves space on the system as
# well as on the tarballs we ship for installation.
2020-08-15 07:27:35 +00:00
[ -f "$mak_dir/$pkg/nostrip" ] || [ "$KISS_STRIP" = 0 ] && return
2019-06-13 14:48:08 +00:00
2020-09-27 08:57:52 +00:00
log "$1" "stripping binaries and libraries"
2019-06-29 20:38:35 +00:00
2020-05-24 13:56:30 +00:00
# Strip only files matching the below ELF types. This uses 'od' to print
2020-05-24 16:42:44 +00:00
# the first 18 bytes of the file. This is the location of the ELF header
# (up to the ELF type) and contains the type information we need.
2020-05-24 13:56:30 +00:00
#
# Static libraries (.a) are in reality AR archives which contain ELF
2020-05-24 16:42:44 +00:00
# objects. We simply read from the same 18 bytes and assume that the AR
# header equates to an archive containing objects (.o).
2020-05-24 16:22:13 +00:00
#
2020-05-24 16:42:44 +00:00
# Example ELF output ('003' is ELF type):
2020-05-24 16:22:13 +00:00
# 0000000 177 E L F 002 001 001 \0 \0 \0 \0 \0 \0 \0 \0 \0
# 0000020 003 \0
# 0000022
#
# Example AR output (.a):
# 0000000 ! < a r c h > \n /
# 0000020
# 0000022
2020-05-21 15:06:32 +00:00
find "$pkg_dir/$1" -type f | while read -r file; do
2020-05-25 15:37:57 +00:00
case $(od -A o -t c -N 18 "$file") in
2020-05-24 14:50:28 +00:00
# REL (object files (.o), static libraries (.a)).
2020-09-14 13:41:21 +00:00
*177*E*L*F*0000020\ 001\ * | *\!*\<*a*r*c*h*\>*)
2020-05-24 16:22:13 +00:00
strip -g -R .comment -R .note "$file"
2020-09-14 13:30:59 +00:00
printf 'stripped debug .%s\n' "${file##"$pkg_dir/$1"}"
2020-05-24 16:22:13 +00:00
;;
# EXEC (binaries), DYN (shared libraries).
# Shared libraries keep global symbols in a separate ELF section
# called '.dynsym'. '--strip-all/-s' does not touch the dynamic
# symbol entries which makes this safe to do.
2020-05-24 16:34:05 +00:00
*177*E*L*F*0000020\ 00[23]\ *)
2020-05-24 16:22:13 +00:00
strip -s -R .comment -R .note "$file"
printf 'stripped all .%s\n' "${file##"$pkg_dir/$1"}"
2020-05-24 16:22:13 +00:00
;;
2020-05-24 13:56:30 +00:00
esac
2020-05-21 15:06:32 +00:00
done 2>/dev/null ||:
2019-06-13 14:48:08 +00:00
}
pkg_fix_deps() {
2020-05-21 07:38:07 +00:00
# Dynamically look for missing runtime dependencies by checking each
# binary and library with 'ldd'. This catches any extra libraries and or
# dependencies pulled in by the package's build suite.
2020-09-27 08:57:52 +00:00
log "$1" "looking for dependencies (using ${elf_cmd##*/})"
cd "$pkg_dir/$1/$pkg_db/$1"
2020-09-12 15:10:16 +00:00
set +f
set -f -- "$sys_db/"*/manifest
2020-03-23 10:40:38 +00:00
2020-05-25 04:43:33 +00:00
: >> depends
2020-01-12 17:55:12 +00:00
2020-03-23 10:40:38 +00:00
find "$pkg_dir/${PWD##*/}/" -type f 2>/dev/null |
2020-01-12 17:55:12 +00:00
while read -r file; do
2020-09-26 06:27:51 +00:00
case $elf_cmd in
*readelf)
"$elf_cmd" -d "$file"
;;
*)
2020-09-26 06:15:46 +00:00
ldd -- "$file"
;;
esac 2>/dev/null |
while read -r line; do
case $line in
*NEEDED*\[*\] | *'=>'*)
# readelf: 0x0000 (NEEDED) Shared library: [libjson-c.so.5]
line=${line##*[}
line=${line%%]*}
# ldd: libjson-c.so.5 => /lib/libjson-c.so.5 ...
line=${line##*=> }
line=${line%% *}
# Skip files owned by libc and POSIX.
case ${line##*/} in
ld-* |\
lib[cm].so* |\
libdl.so* |\
libpthread.so* |\
librt.so* |\
libtrace.so* |\
2020-09-26 06:15:46 +00:00
libxnet.so* |\
ldd)
continue
;;
2020-09-26 06:15:46 +00:00
*)
# Skip file if owned by current package
pkg_owner -l "/${line#/}\$" "$PWD/manifest" &&
2020-09-26 06:15:46 +00:00
continue
pkg_owner -l "/${line#/}\$" "$@" &&
printf '%s\n' "$pkg_owner"
;;
esac
2020-09-25 19:38:05 +00:00
;;
esac
done ||:
2020-09-14 13:41:21 +00:00
done |
sort -uk1,1 depends - > "$tmp_dir/.fixdeps"
2020-03-08 22:14:06 +00:00
diff -U 3 depends - < "$tmp_dir/.fixdeps" ||:
2020-05-22 10:13:22 +00:00
mv -f "$tmp_dir/.fixdeps" depends
if [ -s depends ]; then
pkg_manifest "${PWD##*/}"
else
rm -f depends
fi
}
2019-06-29 20:38:35 +00:00
pkg_manifest() (
2020-02-07 11:27:45 +00:00
# This function runs as a sub-shell to avoid having to 'cd' back to the
2019-06-29 20:38:35 +00:00
# prior directory before being able to continue.
2020-09-14 13:30:59 +00:00
cd "${2:-"$pkg_dir"}/$1"
2019-06-29 20:38:35 +00:00
2019-09-21 16:03:11 +00:00
# find: Print all files and directories and append '/' to directories.
# sed: Remove the first character in each line (./dir -> /dir) and
# remove all lines which only contain '.'.
2020-09-14 13:30:59 +00:00
find . -type d -exec printf '%s/\n' {} + -o -print |
sort -r |
sed '/^\.\/$/d;ss.ss' > "${2:-"$pkg_dir"}/$1/$pkg_db/$1/manifest"
2019-06-29 20:38:35 +00:00
)
2019-06-13 14:48:08 +00:00
2020-10-03 07:08:57 +00:00
pkg_manifest_replace() {
# Replace a line with another in manifest files.
while IFS= read -r _line; do
case $_line in
"$1")
printf '%s\n' "$2"
;;
*)
printf '%s\n' "$_line"
;;
esac
done < "$sys_db/$3/manifest" |
sort -r > "$tmp_dir/.sed"
mv -f "$tmp_dir/.sed" "$sys_db/$3/manifest"
}
2020-09-14 11:33:05 +00:00
pkg_manifest_verify() {
# Ensure that everything listed in the manifest exists in the tarball.
while read -r line; do
[ -h "./$line" ] ||
[ -e "./$line" ] ||
man_err="$man_err$line, "
done < "$1"
[ -z "$man_err" ] ||
2020-09-27 08:57:52 +00:00
die "$pkg" "files in manifest missing from tarball: ${man_err%, }"
2020-09-14 11:33:05 +00:00
}
2020-02-05 08:56:25 +00:00
pkg_etcsums() (
2020-02-07 11:27:45 +00:00
# This function runs as a sub-shell to avoid having to 'cd' back to the
2020-02-05 08:56:25 +00:00
# prior directory before being able to continue.
[ -d "$pkg_dir/$1/etc" ] || return 0
2020-05-16 12:20:53 +00:00
cd "$pkg_dir/$1"
2020-02-05 08:56:25 +00:00
2020-05-30 10:18:29 +00:00
# This can't be a simple 'find -exec' as 'sh256' is a shell function
# and not a real command of any kind. This is the shell equivalent.
find etc -type f | sort | while read -r line; do
sh256 "$line"
done > "$pkg_dir/$1/$pkg_db/$1/etcsums"
2020-02-05 08:56:25 +00:00
)
kiss: Various portability fixes. - Added POSIX shell implementation of the 'readlink' utility for use _only_ when the 'readlink' utility is not available. - Made tar usage more portable. All that is left now is the removal of --strip-components 1 for full (presumed) portability. - Swapped from sha256sum to shasum as it's more portable. This is still not a full solution. Here's a checklist of where we currently are: POSIX Core utilities (depends coreutils) - [x] sh (POSIX) - [x] find (POSIX) -type f, -type d, -exec {} [+;], -o, -print, ! - [x] ls (POSIX) -l, -d - [x] sed (POSIX) -n, s/<search>/<replace>/g, /<delete>/d - [x] grep (POSIX) -l, -F, -x, -f, -q, -v - [x] sort (POSIX) -r, -u, -k - [x] tee (POSIX) - [x] date (POSIX) - [x] mkdir (POSIX) -p - [x] rm (POSIX) -f, -r - [x] rmdir (POSIX) - [x] cp (POSIX) -f, -P, -p, -L, -R - [x] mv (POSIX) -f - [x] chown (POSIX) -h - [x] diff (POSIX) -U BSD utilities - [x] install (BSD, not POSIX) (still portable) -o, -g, -m, -d Misc - [x] readlink (NOT POSIX) (fallback shell implementation) - [x] su* (sudo, doas, su) (in order, optional) - [x] git (downloads from git) (must link to curl) Compiler/libc utilities (depends cc & libc) - [x] readelf (Part of compiler toolchain) (GNU, LLVM or elfutils) - [x] strip (Part of compiler toolchain) (GNU, LLVM or elfutils) - [x] ldd (Part of libc) Tarball compression - [ ] tar (must have --strip-components) (busybox, GNU, libarchive)) - [x] bzip2 (widely used) -d, -z - [x] xz (widely used) -d, -z, -c, -T - [x] gzip (widely used) -d, -6 - [x] zstd (optional) -d, -z, -c - [x] unzip (optional) - [ ] shasum (checksums) (NO standard. Portable across Linux/BSD)
2020-04-30 16:38:37 +00:00
pkg_tar() (
pkg_find "$1"
read -r version release < "$repo_dir/version"
2019-06-29 20:38:35 +00:00
2020-09-14 17:35:56 +00:00
# Avoid tar -C (not portable).
kiss: Various portability fixes. - Added POSIX shell implementation of the 'readlink' utility for use _only_ when the 'readlink' utility is not available. - Made tar usage more portable. All that is left now is the removal of --strip-components 1 for full (presumed) portability. - Swapped from sha256sum to shasum as it's more portable. This is still not a full solution. Here's a checklist of where we currently are: POSIX Core utilities (depends coreutils) - [x] sh (POSIX) - [x] find (POSIX) -type f, -type d, -exec {} [+;], -o, -print, ! - [x] ls (POSIX) -l, -d - [x] sed (POSIX) -n, s/<search>/<replace>/g, /<delete>/d - [x] grep (POSIX) -l, -F, -x, -f, -q, -v - [x] sort (POSIX) -r, -u, -k - [x] tee (POSIX) - [x] date (POSIX) - [x] mkdir (POSIX) -p - [x] rm (POSIX) -f, -r - [x] rmdir (POSIX) - [x] cp (POSIX) -f, -P, -p, -L, -R - [x] mv (POSIX) -f - [x] chown (POSIX) -h - [x] diff (POSIX) -U BSD utilities - [x] install (BSD, not POSIX) (still portable) -o, -g, -m, -d Misc - [x] readlink (NOT POSIX) (fallback shell implementation) - [x] su* (sudo, doas, su) (in order, optional) - [x] git (downloads from git) (must link to curl) Compiler/libc utilities (depends cc & libc) - [x] readelf (Part of compiler toolchain) (GNU, LLVM or elfutils) - [x] strip (Part of compiler toolchain) (GNU, LLVM or elfutils) - [x] ldd (Part of libc) Tarball compression - [ ] tar (must have --strip-components) (busybox, GNU, libarchive)) - [x] bzip2 (widely used) -d, -z - [x] xz (widely used) -d, -z, -c, -T - [x] gzip (widely used) -d, -6 - [x] zstd (optional) -d, -z, -c - [x] unzip (optional) - [ ] shasum (checksums) (NO standard. Portable across Linux/BSD)
2020-04-30 16:38:37 +00:00
cd "$pkg_dir/$1"
2020-04-24 08:04:05 +00:00
# Create a tarball from the contents of the built package.
tar cf - . | case ${KISS_COMPRESS:-gz} in
2020-09-27 06:45:25 +00:00
bz2) bzip2 -z ;;
gz) gzip -6 ;;
lzma) lzma -z ;;
lz) lzip -z ;;
xz) xz -zT 0 ;;
zst) zstd -z ;;
esac > "$bin_dir/$1@$version-$release.tar.${KISS_COMPRESS:-gz}"
2019-06-29 20:38:35 +00:00
2020-09-27 08:57:52 +00:00
run_user_hook post-package "$1"
kiss: Various portability fixes. - Added POSIX shell implementation of the 'readlink' utility for use _only_ when the 'readlink' utility is not available. - Made tar usage more portable. All that is left now is the removal of --strip-components 1 for full (presumed) portability. - Swapped from sha256sum to shasum as it's more portable. This is still not a full solution. Here's a checklist of where we currently are: POSIX Core utilities (depends coreutils) - [x] sh (POSIX) - [x] find (POSIX) -type f, -type d, -exec {} [+;], -o, -print, ! - [x] ls (POSIX) -l, -d - [x] sed (POSIX) -n, s/<search>/<replace>/g, /<delete>/d - [x] grep (POSIX) -l, -F, -x, -f, -q, -v - [x] sort (POSIX) -r, -u, -k - [x] tee (POSIX) - [x] date (POSIX) - [x] mkdir (POSIX) -p - [x] rm (POSIX) -f, -r - [x] rmdir (POSIX) - [x] cp (POSIX) -f, -P, -p, -L, -R - [x] mv (POSIX) -f - [x] chown (POSIX) -h - [x] diff (POSIX) -U BSD utilities - [x] install (BSD, not POSIX) (still portable) -o, -g, -m, -d Misc - [x] readlink (NOT POSIX) (fallback shell implementation) - [x] su* (sudo, doas, su) (in order, optional) - [x] git (downloads from git) (must link to curl) Compiler/libc utilities (depends cc & libc) - [x] readelf (Part of compiler toolchain) (GNU, LLVM or elfutils) - [x] strip (Part of compiler toolchain) (GNU, LLVM or elfutils) - [x] ldd (Part of libc) Tarball compression - [ ] tar (must have --strip-components) (busybox, GNU, libarchive)) - [x] bzip2 (widely used) -d, -z - [x] xz (widely used) -d, -z, -c, -T - [x] gzip (widely used) -d, -6 - [x] zstd (optional) -d, -z, -c - [x] unzip (optional) - [ ] shasum (checksums) (NO standard. Portable across Linux/BSD)
2020-04-30 16:38:37 +00:00
)
2019-06-13 14:48:08 +00:00
2019-06-29 20:38:35 +00:00
pkg_build() {
2020-05-16 06:26:34 +00:00
# Mark packages passed on the command-line separately from those
# detected as dependencies. We need to treat explicitly passed packages
# differently from those pulled in as dependencies.
#
# This also resolves all dependencies and stores the result in '$deps'.
# Any duplicates are also filtered out.
2020-09-09 13:52:18 +00:00
for pkg do
contains "$explicit" "$pkg" || {
2020-09-14 09:05:11 +00:00
pkg_depends "$pkg" explicit
explicit="$explicit $pkg"
2020-09-09 13:52:18 +00:00
}
done
2019-09-13 18:25:33 +00:00
2020-09-22 12:39:25 +00:00
# If not an update, ignore the cache and build everything given
# on the command-line. If this is an update, use the cache.
2020-01-11 12:07:21 +00:00
[ "$pkg_update" ] || explicit_build=$explicit
2019-09-13 20:52:15 +00:00
2020-05-16 06:26:34 +00:00
# If an explicit package is a dependency of another explicit package,
# remove it from the explicit list as it needs to be installed as a
# dependency.
2020-09-09 13:52:18 +00:00
for pkg do
2020-09-22 12:39:25 +00:00
contains "$deps" "$pkg" ||
explicit2="$explicit2 $pkg"
2019-09-13 18:25:33 +00:00
done
2020-05-16 06:36:07 +00:00
explicit=$explicit2
2020-09-22 12:39:25 +00:00
# Intentional, globbing disabled.
2019-09-20 14:54:12 +00:00
# shellcheck disable=2046,2086
2019-09-15 06:15:32 +00:00
set -- $deps $explicit
2020-09-22 12:39:25 +00:00
[ "$#" -gt 1 ] || [ "$pkg_update" = 1 ] &&
prompt "Building $*"
2019-07-11 06:14:17 +00:00
2020-03-26 12:53:03 +00:00
for pkg do pkg_lint "$pkg"; done
2020-09-27 08:57:52 +00:00
log "checking for pre-built dependencies"
# Install any pre-built dependencies if they exist in the binary
# directory and are up to date.
2020-09-09 13:52:18 +00:00
for pkg do
! contains "$explicit_build" "$pkg" && pkg_cache "$pkg" && {
2020-09-27 08:57:52 +00:00
log "$pkg" "installing binary from cache"
2020-09-22 12:11:30 +00:00
2020-09-23 08:55:42 +00:00
# False positive.
# shellcheck disable=2030
2020-09-22 12:11:30 +00:00
(
export KISS_FORCE=1
2020-09-22 12:11:30 +00:00
args i "$tar_file"
)
2020-03-21 11:54:48 +00:00
2020-09-09 13:52:18 +00:00
# Remove the now installed package from the build list.
shift
}
done
2019-06-29 20:38:35 +00:00
2020-03-21 11:48:05 +00:00
for pkg do pkg_sources "$pkg"; done
2020-09-14 18:05:57 +00:00
for pkg do pkg_verify "$pkg"; done
2019-06-13 14:48:08 +00:00
2019-07-03 13:35:14 +00:00
# Finally build and create tarballs for all passed packages and
# dependencies.
2020-06-11 08:06:43 +00:00
for pkg do
2020-09-27 08:57:52 +00:00
log "$pkg" "building package ($((in+=1))/$#)"
2020-01-03 07:10:41 +00:00
2020-09-27 08:57:52 +00:00
run_user_hook pre-extract "$pkg" "$pkg_dir/$pkg"
2019-09-16 07:37:50 +00:00
pkg_extract "$pkg"
pkg_find "$pkg"
2019-06-17 07:18:36 +00:00
2020-05-21 07:38:07 +00:00
# Install built packages to a directory under the package name to
# avoid collisions with other packages.
mkdir -p "$pkg_dir/$pkg/$pkg_db" "$mak_dir/$pkg"
cd "$mak_dir/$pkg"
2019-09-01 11:50:15 +00:00
2020-05-21 07:38:07 +00:00
# Log the version so we can pass it to the package build file.
read -r build_version _ < "$repo_dir/version"
2020-09-27 08:57:52 +00:00
log "$pkg" "starting build"
run_user_hook pre-build "$pkg" "$pkg_dir/$pkg"
2020-05-21 07:38:07 +00:00
# Call the build script, log the output to the terminal and to a file.
# There's no PIPEFAIL in POSIX shelll so we must resort to tricks like
# killing the script ourselves.
2020-09-27 06:10:05 +00:00
{
"$repo_dir/build" "$pkg_dir/$pkg" "$build_version" 2>&1 || {
log "$pkg" "build failed"
log "$pkg" "log stored to $log_dir/$pkg-$pid-${date##*-}"
2020-09-27 06:10:05 +00:00
run_user_hook build-fail "$pkg" "$pkg_dir/$pkg"
pkg_clean
kill 0
}
} | tee "$log_dir/$pkg-$pid-${date##*-}"
2020-01-28 08:08:15 +00:00
2020-05-21 07:38:07 +00:00
# Delete the log file if the build succeeded to prevent the directory
# from filling very quickly with useless logs.
[ "$KISS_KEEPLOG" = 1 ] || rm -f "$log_dir/$pkg-$pid-${date##*-}"
2019-06-29 20:38:35 +00:00
2020-05-21 07:38:07 +00:00
# Copy the repository files to the package directory. This acts as the
# database entry.
2019-10-22 08:54:04 +00:00
cp -LRf "$repo_dir" "$pkg_dir/$pkg/$pkg_db/"
2019-06-29 20:38:35 +00:00
2020-09-27 08:57:52 +00:00
run_user_hook post-build "$pkg" "$pkg_dir/$pkg"
kiss: Remove .la files from all packages. These files are unneeded and become a source of errors when an autotools build references a non-existing .la file. This was the case with a recent update to freetype-harfbuzz. The files are required by libtool to do libtool things, however libtool works just fine without them. These files are safe to remove according to upstream and other distributions have already been doing this for a while. > https://www.gnu.org/software/automake/faq/autotools-faq.html > > 3.1 What are these .la files for and can I safely remove them? > > portable encoding of static and shared library names and dependencies. > > removing usually only works OK if done in directories which the > runtime linker searches by default anyway (otherwise you might need > to set LD_LIBRARY_PATH or an equivalent variable) and only on systems > where the runtime linker loads indirect library dependencies > automatically (includes GNU/Linux, GNU, Solaris). It is recommended that you remove all .la files from your system if manually updating the package manager to the latest version. Running 'kiss update' will automatically handle this for you. The following script will be run on post-install to clean up the .la files. This can also be run manually. Executing this script will do nothing if the system is already clean. #!/bin/sh find "$KISS_ROOT/usr/lib" \ ! -type d \ -name \*.la \ -exec rm -f -- {} + find "$KISS_ROOT/var/db/kiss/installed" \ ! -type d \ -name manifest \ -exec sed -i '/.*\.la$/d' {} + This commit also brings back the removal of charset.alias which was a part of the default KISS_HOOK prior. It makes much more sense for it to live alongside this change.
2020-07-27 23:58:11 +00:00
# Remove all .la files from the packages. They're unneeded and cause
# issues when a package stops providing one. This recently caused an
# issue with harfbuzz (See: 05096e5a4dc6db5d202342f538d067d87ae7135e).
find "$pkg_dir/$pkg/usr/lib" \
-name \*.la \
-exec rm -f {} + \
2>/dev/null ||:
kiss: Remove .la files from all packages. These files are unneeded and become a source of errors when an autotools build references a non-existing .la file. This was the case with a recent update to freetype-harfbuzz. The files are required by libtool to do libtool things, however libtool works just fine without them. These files are safe to remove according to upstream and other distributions have already been doing this for a while. > https://www.gnu.org/software/automake/faq/autotools-faq.html > > 3.1 What are these .la files for and can I safely remove them? > > portable encoding of static and shared library names and dependencies. > > removing usually only works OK if done in directories which the > runtime linker searches by default anyway (otherwise you might need > to set LD_LIBRARY_PATH or an equivalent variable) and only on systems > where the runtime linker loads indirect library dependencies > automatically (includes GNU/Linux, GNU, Solaris). It is recommended that you remove all .la files from your system if manually updating the package manager to the latest version. Running 'kiss update' will automatically handle this for you. The following script will be run on post-install to clean up the .la files. This can also be run manually. Executing this script will do nothing if the system is already clean. #!/bin/sh find "$KISS_ROOT/usr/lib" \ ! -type d \ -name \*.la \ -exec rm -f -- {} + find "$KISS_ROOT/var/db/kiss/installed" \ ! -type d \ -name manifest \ -exec sed -i '/.*\.la$/d' {} + This commit also brings back the removal of charset.alias which was a part of the default KISS_HOOK prior. It makes much more sense for it to live alongside this change.
2020-07-27 23:58:11 +00:00
# Endless source of conflicts.
rm -f "$pkg_dir/$pkg/usr/lib/charset.alias"
kiss: Remove .la files from all packages. These files are unneeded and become a source of errors when an autotools build references a non-existing .la file. This was the case with a recent update to freetype-harfbuzz. The files are required by libtool to do libtool things, however libtool works just fine without them. These files are safe to remove according to upstream and other distributions have already been doing this for a while. > https://www.gnu.org/software/automake/faq/autotools-faq.html > > 3.1 What are these .la files for and can I safely remove them? > > portable encoding of static and shared library names and dependencies. > > removing usually only works OK if done in directories which the > runtime linker searches by default anyway (otherwise you might need > to set LD_LIBRARY_PATH or an equivalent variable) and only on systems > where the runtime linker loads indirect library dependencies > automatically (includes GNU/Linux, GNU, Solaris). It is recommended that you remove all .la files from your system if manually updating the package manager to the latest version. Running 'kiss update' will automatically handle this for you. The following script will be run on post-install to clean up the .la files. This can also be run manually. Executing this script will do nothing if the system is already clean. #!/bin/sh find "$KISS_ROOT/usr/lib" \ ! -type d \ -name \*.la \ -exec rm -f -- {} + find "$KISS_ROOT/var/db/kiss/installed" \ ! -type d \ -name manifest \ -exec sed -i '/.*\.la$/d' {} + This commit also brings back the removal of charset.alias which was a part of the default KISS_HOOK prior. It makes much more sense for it to live alongside this change.
2020-07-27 23:58:11 +00:00
2020-05-21 07:38:07 +00:00
# Create the manifest file early and make it empty. This ensures that
# the manifest is added to the manifest.
2019-07-19 22:14:46 +00:00
: > "$pkg_dir/$pkg/$pkg_db/$pkg/manifest"
2019-06-26 16:27:36 +00:00
# Same for etcsums if /etc exists in package.
[ -d "$pkg_dir/$pkg/etc" ] &&
: > "$pkg_dir/$pkg/$pkg_db/$pkg/etcsums"
2020-02-05 08:56:25 +00:00
pkg_strip "$pkg"
pkg_manifest "$pkg"
pkg_fix_deps "$pkg"
pkg_etcsums "$pkg"
pkg_tar "$pkg"
2019-06-26 16:27:36 +00:00
2020-09-27 08:57:52 +00:00
log "$pkg" "successfully built package"
2019-08-24 09:10:15 +00:00
2020-09-27 08:57:52 +00:00
# Install built package if not marked explicit or this
# is a system update. This runs in a subshell.
! contains "$explicit" "$pkg" || [ "$pkg_update" ] && (
log "$pkg" "marked for install"
2020-09-22 12:11:30 +00:00
2020-09-27 08:57:52 +00:00
# False positive.
# shellcheck disable=2030,2031
export KISS_FORCE=1
2020-09-22 12:11:30 +00:00
args i "$pkg"
)
done
2019-06-29 20:38:35 +00:00
2020-09-27 08:57:52 +00:00
log "successfully built all packages"
2019-06-29 20:38:35 +00:00
}
pkg_checksums() {
pkg_find "$1"
[ -f "$repo_dir/sources" ] || return 0
while read -r src _ || [ "$src" ]; do
# Skip comments, blank lines and git sources.
if [ -z "${src##\#*}" ] || [ -z "${src##git+*}" ]; then
2020-09-14 19:31:22 +00:00
continue
# Remote source.
elif [ -z "${src##*://*}" ]; then
sh256 "$src_dir/$1/${src##*/}"
# Skip directories.
elif [ -d "$repo_dir/$src" ] || [ -d "/$src" ]; then
2020-09-14 19:31:22 +00:00
continue
# Local file (relative).
elif [ -f "$repo_dir/$src" ]; then
sh256 "$repo_dir/$src"
# Local file (absolute).
elif [ -f "/$src" ]; then
sh256 "/$src"
fi
2020-09-27 08:57:52 +00:00
done < "$repo_dir/sources" || die "$1" "failed to generate checksums"
2019-06-29 20:38:35 +00:00
}
2020-09-14 19:32:58 +00:00
pkg_checksum_save() {
2020-09-14 19:26:58 +00:00
# Generate and save checksums to file.
2020-09-14 19:32:58 +00:00
pkg_find "$1"
2020-09-14 19:26:58 +00:00
[ -f "$repo_dir/sources" ] ||
2020-09-14 19:32:58 +00:00
return 0
2020-09-14 19:26:58 +00:00
2020-09-14 19:32:58 +00:00
sums=$(pkg_checksums "$1")
2020-09-14 19:26:58 +00:00
[ "$sums" ] || {
2020-09-27 08:57:52 +00:00
log "$1" "nothing to do"
2020-09-14 19:32:58 +00:00
return 0
2020-09-14 19:26:58 +00:00
}
# False positive ('>> file' with no command).
# shellcheck disable=2188
printf '%s\n' "$sums" |
if 2>/dev/null >> "$repo_dir/checksums"; then
tee "$repo_dir/checksums"
else
file_owner "$repo_dir"
2020-09-27 08:57:52 +00:00
log "$1" "need permissions to generate checksums"
2020-09-14 19:26:58 +00:00
as_root tee "$repo_dir/checksums"
fi
2020-09-27 08:57:52 +00:00
log "$1" "generated checksums"
2020-09-14 19:26:58 +00:00
}
2020-02-08 18:36:58 +00:00
pkg_verify() {
2020-05-21 07:38:07 +00:00
# Verify all package checksums. This is achieved by generating a new set
# of checksums and then comparing those with the old set.
2020-09-14 18:05:57 +00:00
pkg_find "$pkg"
2020-09-14 18:05:57 +00:00
[ -f "$repo_dir/sources" ] ||
return 0
2020-09-14 18:05:57 +00:00
sum_sys=$(pkg_checksums "$pkg")
2020-09-14 18:05:57 +00:00
[ "$sum_sys" ] ||
return 0
2020-09-14 18:05:57 +00:00
[ -f "$repo_dir/checksums" ] ||
die "$pkg" "checksums file missing"
2020-02-08 18:36:58 +00:00
2020-09-14 18:05:57 +00:00
sum_pkg=$(cut -b 1-64 < "$repo_dir/checksums")
2020-05-16 06:26:34 +00:00
2020-09-14 18:05:57 +00:00
[ "$sum_sys" = "$sum_pkg" ] ||
2020-09-27 08:57:52 +00:00
die "$pkg" "checksum mismatch"
2020-02-08 18:36:58 +00:00
}
2019-06-29 20:38:35 +00:00
pkg_conflicts() {
2020-05-16 06:26:34 +00:00
# Filter the tarball's manifest and select only files. Resolve all
# symlinks in file paths as well.
2020-09-09 13:52:18 +00:00
while read -r file; do
file=$KISS_ROOT/${file#/}
2020-09-14 18:24:35 +00:00
case $file in
*[!/])
cd -P "${file%/*}" 2>/dev/null ||
PWD=${file%/*}
2020-09-14 18:24:35 +00:00
printf '%s\n' "${PWD#"$KISS_ROOT"}/${file##*/}"
;;
esac
done < "$tar_dir/$1/$pkg_db/$1/manifest" > "$tmp_dir/.manifest"
2020-01-06 05:49:52 +00:00
2020-05-16 06:26:34 +00:00
set +f
set -f "$sys_db"/*/manifest
2020-01-06 05:49:52 +00:00
2020-05-16 06:26:34 +00:00
# Generate a list of all installed package manifests and remove the
2020-09-14 18:24:35 +00:00
# current package from the list.
2020-09-09 13:52:18 +00:00
for manifest do
shift
2020-09-14 18:15:03 +00:00
[ "$sys_db/$pkg/manifest" = "$manifest" ] &&
continue
2020-05-16 06:26:34 +00:00
set -- "$@" "$manifest"
done
2020-01-28 15:00:29 +00:00
[ "$#" != 0 ] || return 0
2020-09-14 18:24:35 +00:00
# Store the list of found conflicts in a file for reuse.
2020-10-03 05:20:21 +00:00
grep -Fxf "$tmp_dir/.manifest" -- "$@" 2>/dev/null \
> "$tmp_dir/.conflicts" ||:
2020-05-06 19:31:54 +00:00
if [ "$KISS_CHOICE" != 0 ] && [ -s "$tmp_dir/.conflicts" ]; then
2020-09-14 18:24:35 +00:00
# Choices are dynamically created and destroyed.
2020-01-28 12:07:08 +00:00
#
2020-09-14 18:24:35 +00:00
# All file conflicts are installed to the choices directory
# rather than their original destination. The package's
# manifest is updated to reflect this.
2020-01-28 12:07:08 +00:00
#
2020-09-14 18:24:35 +00:00
# Swapping between choices just moves the locations of two
# files around. The file in the system is copied to the
# choices directory and the choice is moved to the system
# (overwriting the remaining prior copy)
2020-03-11 17:36:31 +00:00
while IFS=: read -r _ con; do
2020-09-27 08:57:52 +00:00
pkg_owner -lFx "$con" ||:
printf 'alternative %s (currently %s)\n' "$con" "${pkg_owner:-?}"
2020-01-28 12:07:08 +00:00
# Create the "choices" directory inside of the tarball.
# This directory will store the conflicting file.
2020-09-14 18:15:03 +00:00
mkdir -p "$tar_dir/$pkg/${cho_dir:=var/db/kiss/choices}"
2020-01-28 12:07:08 +00:00
# Construct the file name of the "db" entry of the
# conflicting file. (pkg_name>usr>bin>ls)
2020-09-14 18:24:35 +00:00
con_name=$(printf %s "$pkg$con" | sed 's|/|>|g')
2020-01-28 12:07:08 +00:00
# Move the conflicting file to the choices directory
# and name it according to the format above.
2020-09-14 18:15:03 +00:00
mv -f "$tar_dir/$pkg/$con" \
2020-09-14 18:24:35 +00:00
"$tar_dir/$pkg/$cho_dir/$con_name" 2>/dev/null || {
2020-02-11 10:04:44 +00:00
log "File must be in ${con%/*} and not a symlink to it"
2020-09-14 18:24:35 +00:00
log "This can occur when a binary is installed to"
2020-02-11 10:04:44 +00:00
log "/sbin instead of /usr/bin (example)"
2020-09-14 18:24:35 +00:00
log "Before this file can be used as an alternative,"
2020-09-14 18:15:03 +00:00
log "this must be fixed in $pkg. Contact the maintainer"
2020-09-14 18:24:35 +00:00
die "by finding their details via kiss-maintainer" "" "!>"
2020-02-11 10:04:44 +00:00
}
done < "$tmp_dir/.conflicts"
2020-02-06 12:24:21 +00:00
2020-09-27 08:57:52 +00:00
# Update manifest file.
2020-09-14 18:15:03 +00:00
pkg_manifest "$pkg" "$tar_dir" 2>/dev/null
elif [ -s "$tmp_dir/.conflicts" ]; then
2020-09-14 18:15:03 +00:00
log "Package '$pkg' conflicts with another package" "" "!>"
log "Run 'KISS_CHOICE=1 kiss i $pkg' to add conflicts" "" "!>"
2020-05-07 11:46:50 +00:00
die "as alternatives." "" "!>"
2020-01-28 15:00:29 +00:00
fi
2019-06-13 14:48:08 +00:00
}
2020-01-28 13:07:11 +00:00
pkg_swap() {
# Swap between package alternatives.
2020-01-28 13:07:11 +00:00
pkg_list "$1" >/dev/null
2020-09-25 14:33:57 +00:00
# pkg_name + /path/to/file -> pkg_name>path>to>file
alt=$(
printf %s "$1$2" |
sed 's|/|>|g'
)
cd "$sys_db/../choices"
2020-01-28 13:07:11 +00:00
if [ ! -f "$alt" ] && [ ! -h "$alt" ]; then
2020-09-27 08:57:52 +00:00
die "alternative '$1 $2' doesn't exist"
elif [ -f "$2" ]; then
2020-10-03 07:08:57 +00:00
# Figure out which package owns the file we are going to swap.
2020-09-27 08:57:52 +00:00
pkg_owner -lFx "$2" ||
die "file '$2' exists on filesystem but isn't owned"
2020-09-26 05:08:10 +00:00
cp -Pf "$KISS_ROOT/$2" "$pkg_owner>${alt#*>}"
2020-10-03 07:08:57 +00:00
pkg_manifest_replace \
"$2" "/$cho_db/$pkg_owner>${alt#*>}" "$pkg_owner"
fi
mv -f "$alt" "$KISS_ROOT/$2"
2020-04-29 07:12:09 +00:00
2020-10-03 07:08:57 +00:00
pkg_manifest_replace \
"/$cho_db/$alt" "$2" "$1"
2020-04-29 07:12:09 +00:00
2020-09-26 05:08:10 +00:00
printf '%s is now provided by %s (was %s)\n' "$2" "$1" "$pkg_owner"
2020-01-28 13:07:11 +00:00
}
2020-04-22 06:18:12 +00:00
pkg_install_files() {
2020-05-21 07:38:07 +00:00
# Reverse the manifest file so that we start shallow and go deeper as we
# iterate over each item. This is needed so that directories are created
# going down the tree.
2020-04-22 14:51:42 +00:00
sort "$2/$pkg_db/${2##*/}/manifest" |
2020-04-22 16:35:17 +00:00
while read -r line; do
[ -d "$KISS_ROOT/$line" ] || test "$1" "$KISS_ROOT/$line" &&
continue
2020-05-01 16:26:36 +00:00
rwx=$(ls -ld "$2/$line") oct='' b='' o=0
2020-04-28 04:43:54 +00:00
# Convert the output of 'ls' (rwxrwx---) to octal. This is a
# 1-9 loop with the second digit being the value of the field.
2020-09-09 13:52:18 +00:00
for c in 14 22 31 44 52 61 74 82 91; do
rwx=${rwx#?}
2020-05-01 16:26:36 +00:00
case $rwx in
2020-05-25 04:45:55 +00:00
[rwx]*): "$((o+=${c#?}))" ;;
[st]*): "$((o+=1))" "$((b+=4 / (${c%?}/3)))" ;;
[ST]*): "$((b+=1))" ;;
2020-04-28 04:43:54 +00:00
esac
case $((${c%?} % 3)) in
0) oct=$oct$o o=0
esac
2020-04-28 04:43:54 +00:00
done
# Copy files and create directories (preserving permissions).
2020-09-14 12:02:04 +00:00
case $line in
/etc/?*[!/])
pkg_etc_file "$2" "${line#/}"
2020-09-14 12:02:04 +00:00
;;
2020-05-01 16:26:36 +00:00
*/)
mkdir -m "$oct" "$KISS_ROOT/$line"
2020-04-26 08:00:28 +00:00
;;
2020-04-22 06:37:46 +00:00
2020-06-10 03:42:23 +00:00
*)
cp -fP "$2/$line" "$KISS_ROOT/$line"
# This prepends $b which represents sticky bit,
# setuid, setfgid, etc.
[ -h "$KISS_ROOT/$line" ] ||
chmod "$b$oct" "$KISS_ROOT/$line"
;;
2020-04-22 16:29:55 +00:00
esac
2020-05-30 10:18:29 +00:00
done ||:
2020-09-14 12:02:04 +00:00
pkg_etc_cnt=0
2020-04-22 06:18:12 +00:00
}
2020-05-21 07:55:29 +00:00
pkg_remove_files() {
# Remove a file list from the system. This function runs during package
# installation and package removal. Combining the removals in these two
# functions allows us to stop duplicating code.
while read -r file; do
case $file in
/etc/?*[!/])
sum_sys=$(sh256 "$KISS_ROOT/$file") ||:
2020-10-03 05:20:21 +00:00
sum_old=$(grep -F "$sum_sys" "$tmp_dir/.etcsums") ||:
[ "$sum_sys" = "$sum_old" ] || {
printf 'Skipping %s (modified)\n' "$file"
continue
}
;;
esac 2>/dev/null
file=$KISS_ROOT/$file
2020-05-21 07:55:29 +00:00
# Remove files.
if [ -f "$file" ] && [ ! -h "$file" ]; then
2020-05-21 07:55:29 +00:00
rm -f "$file"
# Remove file symlinks.
elif [ -h "$file" ] && [ ! -d "$file" ]; then
2020-05-21 07:55:29 +00:00
rm -f "$file"
# Remove directories if empty.
elif [ -d "$file" ] && [ ! -h "$file" ]; then
2020-05-21 07:55:29 +00:00
rmdir "$file" 2>/dev/null ||:
fi
done ||:
}
2020-09-14 12:02:04 +00:00
pkg_etc_file() {
pkg_etc_cnt=$((pkg_etc_cnt + 1))
2020-03-25 10:21:10 +00:00
sum_new=$(sh256 "$1/$2") 2>/dev/null ||:
sum_sys=$(cd "$KISS_ROOT/"; sh256 "$2") 2>/dev/null ||:
sum_old=$(awk "NR == $pkg_etc_cnt" "$tmp_dir/.etcsums") 2>/dev/null ||:
2020-09-14 12:02:04 +00:00
# Use a case statement to easily compare three strings at
# the same time. Pretty nifty.
case ${sum_old:-null}${sum_sys:-null}${sum_new} in
# old = Y, sys = X, new = Y
"${sum_new}${sum_sys}${sum_old}")
return 0
;;
2020-03-25 10:21:10 +00:00
2020-09-14 12:02:04 +00:00
# old = X, sys = X, new = X
# old = X, sys = Y, new = Y
# old = X, sys = X, new = Y
"${sum_old}${sum_old}${sum_old}"|\
"${sum_old:-null}${sum_sys}${sum_sys}"|\
"${sum_sys}${sum_old}"*)
new=
;;
2020-03-25 10:21:10 +00:00
2020-09-14 12:02:04 +00:00
# All other cases.
*)
2020-09-14 12:59:48 +00:00
printf 'Saving /%s as /%s.new\n' "$2" "$2"
2020-09-14 12:02:04 +00:00
new=.new
;;
esac
cp -fP "$1/$2" "$KISS_ROOT/${2}${new}"
2020-09-14 12:02:04 +00:00
}
2020-03-25 10:21:10 +00:00
2019-06-13 14:48:08 +00:00
pkg_remove() {
2020-05-21 07:38:07 +00:00
# Remove a package and all of its files. The '/etc' directory is handled
# differently and configuration files are *not* overwritten.
2020-09-12 08:09:46 +00:00
pkg_list "$1" >/dev/null
2020-09-23 08:55:42 +00:00
# False positive.
# shellcheck disable=2031
2020-09-27 08:57:52 +00:00
[ "$KISS_FORCE" = 1 ] || (
cd "$sys_db"
set +f
2020-10-03 05:20:21 +00:00
! grep -lFx "$1" -- */depends
2020-01-29 13:03:18 +00:00
) || die "$1" "can't remove package, others depend on it"
2019-07-26 16:21:44 +00:00
# Block being able to abort the script with 'Ctrl+C' during removal.
2020-05-21 07:38:07 +00:00
# Removes all risk of the user aborting a package removal leaving an
# incomplete package installed.
2019-07-04 15:32:53 +00:00
trap '' INT
2020-09-27 08:57:52 +00:00
run_repo_hook pre-remove "$1"
run_user_hook pre-remove "$1" "$sys_db/$pkg"
# Make a backup of the etcsums file (if it exists).
cp -f "$sys_db/$1/etcsums" "$tmp_dir/.etcsums" 2>/dev/null ||:
2020-07-29 16:03:02 +00:00
2020-09-27 08:57:52 +00:00
log "$1" "removing package"
2020-05-21 07:55:29 +00:00
pkg_remove_files < "$sys_db/$1/manifest"
2019-07-26 16:21:44 +00:00
# Reset 'trap' to its original value. Removal is done so
2019-07-04 15:32:53 +00:00
# we no longer need to block 'Ctrl+C'.
trap pkg_clean EXIT INT
2020-09-27 08:57:52 +00:00
log "$1" "removed successfully"
2019-06-13 14:48:08 +00:00
}
2019-06-29 20:38:35 +00:00
pkg_install() {
2020-04-24 08:04:05 +00:00
# Install a built package tarball.
#
2020-09-14 12:08:18 +00:00
# 1. Install package overwriting any existing files.
# 2. Diff old manifest against new one and remove any files which exist in
# the old instance of the package but not the new one.
# 3. Install package again, verifying all files and repairing any damage
# done by #2.
2019-06-14 05:58:09 +00:00
2020-09-14 12:08:18 +00:00
# Handle tarball vs cache lookup (pkg_cache).
2020-09-27 08:57:52 +00:00
case $1 in
*.tar.*)
[ -f "$1" ] ||
die "tarball '$1' does not exist"
tar_file=$1
pkg=${1##*/}
pkg=${pkg%#*}
;;
2019-06-29 20:38:35 +00:00
2020-09-27 08:57:52 +00:00
*)
pkg_find "$1"
pkg_cache "$1" 2>/dev/null ||
die "package '$1' has not yet been built"
;;
esac
2019-06-29 20:38:35 +00:00
2020-09-14 11:33:05 +00:00
mkdir -p "$tar_dir/$pkg"
cd "$tar_dir/$pkg"
2019-06-29 20:38:35 +00:00
2020-06-10 08:23:34 +00:00
decompress "$tar_file" | tar xf -
2019-07-04 14:43:10 +00:00
2020-09-14 12:08:18 +00:00
[ -f "./$pkg_db/$pkg/manifest" ] ||
2020-09-27 08:57:52 +00:00
die "invalid tarball '$tar_file'"
2020-09-23 08:55:42 +00:00
# False positive.
# shellcheck disable=2031
[ "$KISS_FORCE" = 1 ] || {
2020-09-14 11:33:05 +00:00
pkg_manifest_verify "$pkg_db/$pkg/manifest"
[ -f "$pkg_db/$pkg/depends" ] && {
while read -r dep dep_type || [ "$dep" ]; do
case "$dep ${dep_type:-null}" in
[!#]*\ null)
pkg_list "$dep" >/dev/null 2>&1 ||
dep_err="$dep_err$dep, "
;;
esac
done < "$pkg_db/$pkg/depends"
2020-09-14 11:33:05 +00:00
[ -z "$dep_err" ] ||
2020-09-27 08:57:52 +00:00
die "$pkg" "missing ${dep_err%, }"
}
2020-03-26 13:00:29 +00:00
}
2019-07-05 06:34:06 +00:00
2020-09-27 08:57:52 +00:00
run_user_hook pre-install "$pkg" "$tar_dir/$pkg"
log "$pkg" "transforming package conflicts into alternatives"
2020-09-14 11:33:05 +00:00
pkg_conflicts "$pkg"
2020-01-28 12:07:08 +00:00
2020-09-14 12:08:18 +00:00
# Block Ctrl+C during installation.
trap '' INT
2019-07-21 08:14:34 +00:00
# If the package is already installed (and this is an upgrade) make a
# backup of the manifest and etcsums files.
cp -f "$sys_db/$pkg/manifest" "$tmp_dir/.manifest" 2>/dev/null ||:
cp -f "$sys_db/$pkg/etcsums" "$tmp_dir/.etcsums" 2>/dev/null ||:
2020-09-27 08:57:52 +00:00
log "$pkg" "installing package"
2020-09-14 11:33:05 +00:00
pkg_install_files -z "$tar_dir/$pkg"
2020-10-03 05:20:21 +00:00
grep -vFxf "$sys_db/$pkg/manifest" "$tmp_dir/.manifest" \
2020-10-03 03:43:36 +00:00
2>/dev/null | pkg_remove_files
2019-06-29 20:38:35 +00:00
2020-09-27 08:57:52 +00:00
log "$pkg" "verifying installation"
2020-09-14 11:33:05 +00:00
pkg_install_files -e "$tar_dir/$pkg"
2019-07-22 08:01:37 +00:00
trap pkg_clean EXIT INT
2020-09-27 08:57:52 +00:00
run_repo_hook post-install "$pkg"
run_user_hook post-install "$pkg" "$sys_db/$pkg"
2020-09-27 08:57:52 +00:00
log "$pkg" "installed successfully"
2019-06-13 14:48:08 +00:00
}
sys_update() {
2019-06-29 20:38:35 +00:00
# Check all installed packages for updates. So long as the installed
# version and the version in the repositories differ, it's considered
# an update.
2020-09-27 08:57:52 +00:00
log "updating repositories"
# Create a list of all repositories.
2020-09-14 12:09:50 +00:00
# Intentional behavior.
# shellcheck disable=2031,2046,2086
2020-09-12 15:04:30 +00:00
{
IFS=:
set -- $KISS_PATH
unset IFS
}
2020-05-21 07:38:07 +00:00
# Update each repository in '$KISS_PATH'.
2020-03-21 11:48:05 +00:00
for repo do
2020-02-06 12:06:51 +00:00
cd "$repo"
2019-08-14 09:58:14 +00:00
case $(git remote 2>/dev/null) in
"")
log "$repo" " "
printf 'Skipping git pull, not a repository\n'
;;
2019-08-14 09:58:14 +00:00
*)
cd "$(git rev-parse --show-toplevel)"
git_root=$(git rev-parse --show-superproject-working-tree)
2020-09-12 15:04:30 +00:00
cd "${git_root:-.}"
contains "$repos" "$PWD" : || {
repos="$repos:$PWD"
# Display a tick if signing is enabled for this repository.
case $(git config merge.verifySignatures) in
true) log "$PWD" "[signed] " ;;
*) log "$PWD" " " ;;
esac
if [ -w "$PWD" ] && [ "$uid" != 0 ]; then
git pull
git submodule update --remote --init -f
else
2020-09-27 08:57:52 +00:00
[ "$uid" = 0 ] ||
log "$PWD" "need permissions to update"
# Find out the owner of the repository and spawn
# git as this user below.
#
# This prevents 'git' from changing the original
# ownership of files and directories in the rare
# case that the repository is owned by a 3rd user.
(
file_owner "$PWD"
# We're in a repository which is owned by a 3rd
# user. Not root or the current user.
[ "$user" = root ] ||
2020-09-27 08:57:52 +00:00
log "dropping to $user for pull"
# Nesting is deep and line is long.
git_cmd="
git pull && git submodule update --remote --init -f
"
2020-09-25 14:33:57 +00:00
# 'su' requires that command be quoted.
case $su in *su)
git_cmd="'$git_cmd'"
esac
as_root sh -c "$git_cmd"
)
fi
}
;;
esac
2019-10-04 10:47:25 +00:00
run_repo_hook update "$PWD" update
done
2020-09-27 08:57:52 +00:00
log "checking for new package versions"
2020-05-16 05:10:37 +00:00
set +f --
2020-09-25 14:33:57 +00:00
for _pkg in "$sys_db/"*; do
pkg_find "${_pkg##*/}"
2020-09-25 14:33:57 +00:00
read -r db_ver db_rel < "$_pkg/version"
read -r re_ver re_rel < "$repo_dir/version"
2019-06-29 20:38:35 +00:00
2020-05-21 08:42:33 +00:00
[ "$db_ver-$db_rel" = "$re_ver-$re_rel" ] || {
2020-09-25 14:33:57 +00:00
printf '%s %s-%s -> %s-%s\n' \
"${_pkg##*/}" \
"$db_ver" "$db_rel" \
"$re_ver" "$re_rel"
set -- "$@" "${_pkg##*/}"
2019-07-11 06:14:17 +00:00
}
2019-06-13 14:48:08 +00:00
done
2019-07-11 06:14:17 +00:00
2020-02-06 11:55:01 +00:00
set -f
2020-05-16 05:10:37 +00:00
contains "$*" kiss && {
2020-09-27 08:57:52 +00:00
log "detected package manager update"
prompt "the package manager will be updated first"
2020-01-30 07:27:25 +00:00
pkg_build kiss
args i kiss
2020-09-27 08:57:52 +00:00
log "updated the package manager"
log "re-run 'kiss u' to update your system"
exit 0
}
2020-05-16 05:10:37 +00:00
[ "$1" ] || {
2020-09-27 08:57:52 +00:00
log "system up-to-date"
2019-07-11 06:14:17 +00:00
return
}
2020-09-12 14:40:05 +00:00
pkg_update=1
pkg_order "$@"
# Intentional, globbing disabled.
# shellcheck disable=2086
pkg_build $order
2019-06-13 14:48:08 +00:00
}
2019-06-29 20:38:35 +00:00
pkg_clean() {
2020-05-21 07:38:07 +00:00
# Clean up on exit or error. This removes everything related to the build.
2020-09-14 09:31:53 +00:00
[ "$KISS_DEBUG" = 1 ] ||
rm -rf "$tmp_dir"
2019-06-29 20:38:35 +00:00
}
2019-06-15 06:19:20 +00:00
2019-06-29 20:38:35 +00:00
args() {
2020-05-21 07:38:07 +00:00
# Parse script arguments manually. 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-08-19 18:45:19 +00:00
action=$1
2020-05-24 18:05:13 +00:00
shift "$(($# != 0))"
2019-08-19 18:45:19 +00:00
2020-09-14 09:22:25 +00:00
case $action in
b|build|c|checksum|d|download|i|install|r|remove)
[ "$1" ] || {
2020-09-14 12:02:04 +00:00
# Intentional.
# shellcheck disable=2031
export KISS_PATH=${PWD%/*}:$KISS_PATH
set -- "${PWD##*/}"
}
2020-09-14 12:02:04 +00:00
for arg do
case $arg in
*'*'*|*'!'*|*'['*|*']'*|*' '*|*' '*)
2020-09-27 08:57:52 +00:00
die "argument '$arg' contains '!*[] \t'"
2020-09-14 12:02:04 +00:00
;;
esac
done
2020-09-14 09:22:25 +00:00
;;
2020-05-18 08:44:24 +00:00
esac
# Rerun the script as root with a fixed environment if needed. We sadly
# can't run singular functions as root so this is needed.
2020-09-23 08:55:42 +00:00
#
# False positive.
# shellcheck disable=2031
2020-09-14 09:22:25 +00:00
case $action in
a|alternatives|i|install|r|remove)
[ -z "$1" ] || [ -w "$KISS_ROOT/" ] || [ "$uid" = 0 ] || {
as_root \
HOME="$HOME" \
XDG_CACHE_HOME="$XDG_CACHE_HOME" \
KISS_CHOICE="$KISS_CHOICE" \
KISS_COLOR="$KISS_COLOR" \
KISS_FORCE="$KISS_FORCE" \
KISS_PATH="$KISS_PATH" \
KISS_PID="$KISS_PID" \
KISS_ROOT="$KISS_ROOT" \
KISS_TMPDIR="$KISS_TMPDIR" \
"$0" "$action" "$@"
2020-09-14 09:22:25 +00:00
return
}
;;
2019-08-19 18:45:19 +00:00
esac
2019-06-29 20:38:35 +00:00
2020-05-21 07:38:07 +00:00
# Actions can be abbreviated to their first letter. This saves keystrokes
# once you memorize the commands.
2019-08-19 18:45:19 +00:00
case $action in
2020-01-28 12:16:01 +00:00
a|alternatives)
2020-09-14 19:26:58 +00:00
case $1 in
-)
while read -r pkg path; do
pkg_swap "$pkg" "$path"
done
;;
2020-01-28 12:16:01 +00:00
2020-09-14 19:26:58 +00:00
'')
set +f
2020-09-14 19:26:58 +00:00
# Go over each alternative and format the file
# name for listing. (pkg_name>usr>bin>ls)
for pkg in "$sys_db/../choices"/*; do
printf '%s\n' "${pkg##*/}"
2020-09-14 19:26:58 +00:00
done |
2020-09-14 19:26:58 +00:00
sed 's|>| /|; s|>|/|g; /\*/d'
;;
2020-09-14 19:26:58 +00:00
*)
pkg_swap "$1" "$2"
2020-09-14 19:26:58 +00:00
;;
esac
;;
2020-09-14 19:26:58 +00:00
b|build)
pkg_build "${@:?No packages installed}"
;;
2020-09-14 19:26:58 +00:00
c|checksum)
for pkg do
pkg_lint "$pkg"
done
2020-04-28 03:26:36 +00:00
2020-09-14 19:26:58 +00:00
for pkg do
pkg_sources "$pkg"
done
2020-09-14 19:26:58 +00:00
for pkg do
2020-09-14 19:32:58 +00:00
pkg_checksum_save "$pkg"
2020-09-14 19:26:58 +00:00
done
;;
2019-06-29 20:38:35 +00:00
2020-09-14 19:26:58 +00:00
d|download)
for pkg do
pkg_sources "$pkg"
2019-07-21 11:21:47 +00:00
done
2019-06-29 20:38:35 +00:00
;;
2020-09-12 14:40:05 +00:00
i|install)
pkg_order "$@"
for pkg in $order; do
2020-09-12 14:40:05 +00:00
pkg_install "$pkg"
done
;;
2019-06-29 20:38:35 +00:00
2020-09-14 19:26:58 +00:00
l|list)
2020-09-26 14:13:24 +00:00
[ "$1" ] || {
cd "$sys_db"
set +f
set -f -- *
}
for pkg do
pkg_list "$pkg"
done
2020-09-14 19:26:58 +00:00
;;
2020-09-12 14:40:05 +00:00
r|remove)
pkg_order "$@"
for pkg in $redro; do
2020-09-12 14:40:05 +00:00
pkg_remove "$pkg"
done
2019-06-29 20:38:35 +00:00
;;
2020-09-14 19:26:58 +00:00
s|search)
for pkg do
2020-09-23 18:48:08 +00:00
pkg_find "$pkg" '' all
2020-09-14 19:26:58 +00:00
done
;;
u|update)
sys_update
2020-09-14 19:26:58 +00:00
;;
v|version)
2020-09-26 14:13:24 +00:00
printf '6.0.0\n'
2020-09-14 19:26:58 +00:00
;;
2019-06-29 20:38:35 +00:00
2020-09-08 14:07:55 +00:00
'')
log 'kiss [a|b|c|d|i|l|r|s|u|v] [pkg]...'
log 'alternatives List and swap to alternatives'
log 'build Build a package'
log 'checksum Generate checksums'
2020-06-10 07:18:47 +00:00
log 'download Pre-download all sources'
log 'install Install a package'
log 'list List installed packages'
log 'remove Remove a package'
log 'search Search for a package'
2020-05-16 16:00:44 +00:00
log 'update Update the system'
2020-09-08 14:07:55 +00:00
log 'version Package manager version'
printf '\nRun "kiss help-ext" to see all actions\n'
;;
help-ext)
2020-09-27 08:57:52 +00:00
log 'extensions (kiss-* in PATH)'
2020-09-23 18:48:08 +00:00
pkg_find kiss-\* "$PATH" all -x |
while read -r file; do
name=${file#*/kiss-}
2020-09-23 18:48:08 +00:00
contains "$list" "$name" || {
list="$list $name"
2020-09-23 18:48:08 +00:00
printf '%-15s ' "$name"
sed -n 's/^# *//;2p' "$file"
}
done
2019-06-29 20:38:35 +00:00
;;
2019-07-24 22:33:12 +00:00
*)
2020-09-23 18:48:08 +00:00
pkg_find "kiss-$action*" "$PATH" '' -x 2>/dev/null ||
die "'kiss $action' is not a valid command"
"$repo_dir" "$@"
;;
2019-06-13 14:48:08 +00:00
esac
}
main() {
2020-05-09 18:25:38 +00:00
# Globally disable globbing and enable exit-on-error.
set -ef
# Allow the user to disable colors in output via an environment variable.
# Check this once so as to not slow down printing.
2020-09-23 18:48:08 +00:00
[ "$KISS_COLOR" = 0 ] || {
lcol='\033[1;33m'
lcol2='\033[1;34m'
lclr='\033[m'
}
2019-06-29 20:38:35 +00:00
# The PID of the current shell process is used to isolate directories
# to each specific KISS instance. This allows multiple package manager
# instances to be run at once. Store the value in another variable so
# that it doesn't change beneath us.
2020-09-26 14:13:24 +00:00
pid=${KISS_PID:-"$$"}
2019-06-13 15:11:59 +00:00
2019-06-29 20:38:35 +00:00
# Catch errors and ensure that build files and directories are cleaned
# up before we die. This occurs on 'Ctrl+C' as well as success and error.
2019-06-29 20:38:35 +00:00
trap pkg_clean EXIT INT
2019-06-13 14:48:08 +00:00
2020-05-21 07:38:07 +00:00
# Figure out which 'sudo' command to use based on the user's choice or what
# is available on the system.
2020-09-22 12:11:30 +00:00
su=${KISS_SU:-"$(
2020-09-22 12:39:25 +00:00
command -v sudo ||
command -v doas ||
2020-09-22 12:11:30 +00:00
command -v sls
)"} || su=su
2020-09-25 19:38:05 +00:00
# Figure out which utility is available to dump elf information.
elf_cmd=${KISS_ELF:="$(
2020-09-25 22:35:09 +00:00
command -v readelf ||
command -v eu-readelf ||
command -v llvm-readelf
)"} || elf_cmd=ldd
2020-09-25 19:38:05 +00:00
2020-05-21 07:38:07 +00:00
# Store the date and time of script invocation to be used as the name of
# the log files the package manager creates uring builds.
date=$(date +%Y-%m-%d-%H:%M:%S)
2020-01-28 08:08:15 +00:00
2020-02-10 18:02:45 +00:00
# Make note of the user's current ID to do root checks later on.
# This is used enough to warrant a place here.
uid=$(id -u)
2020-05-21 08:47:13 +00:00
# Define some paths which we will then use throughout the script.
2020-05-23 07:05:19 +00:00
sys_db=$KISS_ROOT/${pkg_db:=var/db/kiss/installed}
2020-10-03 07:08:57 +00:00
cho_db=${pkg_db%%/installed}/choices
# Ensure that the KISS_ROOT doesn't end with a '/'.
KISS_ROOT=${KISS_ROOT%"${KISS_ROOT##*[!/]}"}
2019-09-10 12:43:34 +00:00
# This allows for automatic setup of a KISS chroot and will
# do nothing on a normal system.
mkdir -p "$KISS_ROOT/" 2>/dev/null ||:
2019-09-10 12:43:34 +00:00
# Create cache directories and define variables.
mkdir -p \
"${cac_dir:="${XDG_CACHE_HOME:-"${HOME:?HOME is null}/.cache"}/kiss"}" \
"${src_dir:="$cac_dir/sources"}" \
"${log_dir:="$cac_dir/logs/${date%-*}"}" \
"${bin_dir:="$cac_dir/bin"}" \
"${tmp_dir:="${KISS_TMPDIR:="$cac_dir/proc"}/$pid"}" \
"${mak_dir:="$tmp_dir/build"}" \
"${pkg_dir:="$tmp_dir/pkg"}" \
"${tar_dir:="$tmp_dir/extract"}"
2019-07-03 13:35:14 +00:00
2019-06-13 14:48:08 +00:00
args "$@"
}
main "$@"