#!/bin/sh # shellcheck disable=2094,2103,SC2181 source=/dev/null # # puke - package manager for kiss linux. die() { printf '\033[31mERROR>\033[m %s\n' "$@" >&2 exit 1 } log() { printf '\033[32m=>\033[m %s\n' "$@" } clean() { rm -rf -- "$mak_dir" "$pkg_dir" [ -n "$name" ] && { rm "$rep_dir/$name/.checksums" 2>/dev/null rm "$rep_dir/$name/.manifest" 2>/dev/null } } pkg_setup() { [ -z "$1" ] && die "No package specified." cd "$rep_dir/$1" || die "Package '$1' not in repository." [ -f version ] || die "Version file not found." [ -f sources ] || die "Sources file not found." [ -f build ] || die "Build file not found." read -r version release < version name=$1 pkg=$name\#$version-$release mkdir -p "$src_dir" "$mak_dir" "$pkg_dir/$dbs_dir" \ "$sys_dir" "$bin_dir" || die "Couldn't create directories at '$PWD'". } pkg_depends() { [ -f depends ] && while read -r dependency; do pkg_list "$dependency" || missing="$missing $dependency" done < depends [ -n "$missing" ] && die "Missing dependencies:$missing" } source_type() { [ -f "$1" ] && return 2 [ -f "$src_dir/${1##*/}" ] && return 3 [ -z "${1##git:*}" ] && return 4 [ -z "${1##*://*}" ] && return 5 } pkg_sources() { while read -r src; do source_type "$src" case $? in 2|3) log "Found local ${src##*/}." ;; 4) git clone "${src##git:}" "$mak_dir" ;; 5) log "Downloading '$src'." wget -P "$src_dir" "$src" || die "Failed to download $src." ;; *) die "Source file '$src' not found." ;; esac done < sources } pkg_checksum() { while read -r src; do source_type "$src" case $? in 2) src_path=$src ;; 3) src_path=$src_dir/${src##*/} ;; 4) continue ;; esac cd "${src_path%/*}" >/dev/null sha256sum -- "${src##*/}" || die "Failed to generate checksums." cd - >/dev/null done < sources > "${1-checksums}" } pkg_verify() { pkg_checksum .checksums diff .checksums checksums || die "checksum of sources does not match checksum of package" \ "run '$0 checksum $name' to update checksums" log "Checksums verified." rm .checksums } pkg_extract() { while read -r src; do source_type "$src" case $? in 2) cp -f "$src" "$mak_dir" ;; 4) continue ;; 3) case $src in *.tar|*.tar.??|*.tar.???|*.tar.????|*.tgz) tar xf "$src_dir/${src##*/}" -C "$mak_dir" \ --strip-components 1 || die "Couldn't extract ${src##*/}" ;; esac ;; *) die "${src##*/} not found." esac done < sources } pkg_build() { log "Building $pkg." cd "$mak_dir" set -e errexit . "$OLDPWD/build" set +e errexit cd "$rep_dir/$name" cp -R "$rep_dir/$name" "$pkg_dir/$dbs_dir" touch "$pkg_dir/$dbs_dir/$name/manifest" log "Sucessfully built $pkg." } pkg_manifest() { cd "$pkg_dir" _() { find . -mindepth 1 "$@" | sed 's/^\.//'; } _ -not -type d > "$OLDPWD/manifest" _ -type d | sort -r >> "$OLDPWD/manifest" cp "$OLDPWD/manifest" "$pkg_dir/$dbs_dir/$name" cd - >/dev/null } pkg_tar() { cd "$bin_dir" tar pcvf "$pkg.tar.gz" -C "$pkg_dir" . || die "Failed to create package." log "Package is at $bin_dir/$pkg.tar.gz." } pkg_install() { [ -f "$bin_dir/$pkg.tar.gz" ] || die "Package must be built first." pkg_remove "$name" tar pxvf "$bin_dir/$pkg.tar.gz" -k -C "$sys_dir/" 2>/dev/null [ -f "$sys_dir/$dbs_dir/$name/post-install" ] && . "$sys_dir/$dbs_dir/$name/post-install" log "Installed $pkg" } pkg_remove() { pkg_list "$name" || return 1 cp "$sys_dir/$dbs_dir/$name/manifest" .manifest while read -r file; do [ "${file%/*}" = "/etc" ] && continue path="${sys_dir}${file}" if [ -d "$path" ]; then rmdir "$path" 2>/dev/null else rm -- "$path" || log "Failed to remove $file." fi [ "$?" = 0 ] && log "Removed $file" done < .manifest return 0 } pkg_updates() { git pull cd "$sys_dir/$dbs_dir" for pkg in *; do read -r db_version db_release < "$pkg/version" read -r re_version re_release < "$rep_dir/$pkg/version" [ "$db_version-$db_release" != "$re_version-$re_release" ] && log "NEW $pkg $re_version-$re_release" done } pkg_list() { [ "$1" ] && { [ -d "$sys_dir/$dbs_dir/$1" ] || return 1 && return 0 } for pkg in "$sys_dir/$dbs_dir/"*; do [ -d "$pkg" ] || continue read -r version release < "$pkg/version" log "${pkg##*/} $version-$release" done } args() { case $1 in b*|c*|d*|i*|r*) pkg_setup "$2"; esac case $1 in b*) [ -f checksums ] || die "Checksums missing, run '$0 checksum $name'" pkg_depends pkg_sources pkg_verify pkg_extract pkg_build pkg_manifest pkg_tar ;; c*) pkg_sources pkg_checksum log "Generated checksums." ;; d*) [ -f depends ] && cat depends ;; i*) pkg_install ;; l*) pkg_list "$2" ;; r*) pkg_remove || die "Package '$name' not installed" ;; u*) pkg_updates ;; *) log "$0 [b|c|d|i|l|r|u] [pkg]" \ "build: Build a package." \ "checksum: Generate checksums." \ "depends: See package dependencies." \ "install: Install a package." \ "list: List packages." \ "remove: Remove a package." \ "update: Check for updates." esac } main() { trap clean EXIT INT clean src_dir=$PWD/sources mak_dir=$PWD/build pkg_dir=$PWD/pkg sys_dir=$PWD/sys bin_dir=$PWD/bin rep_dir=$PWD/repo dbs_dir=var/db/puke args "$@" } main "$@"