#!/bin/sh # # 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" } source_type() { [ -f "$1" ] && return 2 [ -f "$src_dir/${1##*/}" ] && return 3 [ -z "${1##git:*}" ] && return 4 [ -z "${1##*://*}" ] && return 5 } pkg_setup() { cd "$rep_dir/$1" || die "Package '$1' not in repository." [ -f sources ] || die "Sources file not found." [ -x build ] || die "Build file not found or not executable." read -r ver rel < version || die "Version file not found." pkg=${name:=$1}\#$ver-$rel mkdir -p "$src_dir" "$mak_dir" "$pkg_dir/$dbs_dir" "$sys_dir" "$bin_dir" || die "Couldn't create directories at $PWD." } pkg_depends() { while read -r dep; do pkg_list "$dep" || missing="$missing $dep" done 2>/dev/null < depends [ -n "$missing" ] && die "Missing dependencies:$missing" } 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.") done < sources > "${1-checksums}" } pkg_verify() { pkg_checksum /dev/stdout | diff checksums - || die "Checksums of sources do not match checksums of package." \ "Run '$0 checksum $name' to update checksums" log "Checksums verified." } pkg_extract() { while read -r src; do source_type "$src" case $? in 2) cp -f "$src" "$mak_dir" ;; 4) ;; 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() { (set -e errexit; cd "$mak_dir"; "$OLDPWD/build" "$pkg_dir" ) || die "Build failed." cp -R "$rep_dir/$name" "$pkg_dir/$dbs_dir" log "Sucessfully built $pkg." 2> "$pkg_dir/$dbs_dir/$name/manifest" } pkg_manifest() { find "$pkg_dir" -mindepth 1 | sed "s|^$pkg_dir||" | sort -r > manifest cp manifest "$pkg_dir/$dbs_dir/$name" } pkg_tar() { tar pcvf "$bin_dir/$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 while read -r file; do if [ "${file%/*}" = "/etc" ]; then false elif [ -d "$sys_dir$file" ]; then rmdir "$sys_dir$file" 2>/dev/null else rm -- "$sys_dir$file" || log "Failed to remove $file." fi && log "Removed $file" ||: done < "$sys_dir/$dbs_dir/$name/manifest" } pkg_updates() { for item in "$sys_dir/$dbs_dir/"*; do read -r db_ver db_rel < "$item/version" read -r re_ver re_rel < "$rep_dir/${item##*/}/version" [ "$db_ver-$db_rel" != "$re_ver-$re_rel" ] && printf '%s\n' "${item##*/} $re_ver-$re_rel" done } pkg_list() { [ "$1" ] && { [ -d "$sys_dir/$dbs_dir/$1" ]; return "$?"; } for item in "$sys_dir/$dbs_dir/"*; do [ -d "$item" ] || continue read -r version release < "$item/version" printf '%s\n' "${item##*/} $version-$release" done } args() { case $1 in b*|c*|d*|i*|r*) pkg_setup "${2-null}"; 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 src_dir=$PWD/sources mak_dir=$PWD/build pkg_dir=$PWD/pkg sys_dir=$PUKE_ROOT bin_dir=$PWD/bin rep_dir=$PWD/repo dbs_dir=var/db/puke args "$@" } main "$@"