diff --git a/old/scratch b/old/scratch new file mode 100755 index 0000000..cd3beab --- /dev/null +++ b/old/scratch @@ -0,0 +1,1471 @@ +#!/bin/sh +# +# scratchpkg +# +# Copyright (c) 2018 by Emmett1 (emmett1.2miligrams@gmail.com) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +RED='\e[0;31m' +GREEN='\e[0;32m' +YELLOW='\e[0;33m' +CYAN='\e[0;36m' +PURPLE='\e[0;35m' +CRESET='\e[0m' + +nocolor() { + RED= + GREEN= + YELLOW= + CYAN= + PURPLE= + CRESET= +} + +msg() { + printf "${GREEN}==>${CRESET} %s\n" "$1" +} + +msginst() { + printf "[${GREEN}i${CRESET}] %s\n" "$1" +} + +msgmiss() { + printf "[${YELLOW}m${CRESET}] %s\n" "$1" +} + +msgnoinst() { + printf "[-] %s\n" "$1" +} + +msgerr() { + printf "${RED}==> ERROR:${CRESET} %s\n" "$1" >&2 +} + +msgwarn() { + printf "${YELLOW}==> WARNING:${CRESET} %s\n" "$1" >&2 +} + +needroot() { + if [ "$(id -u)" != 0 ]; then + if [ "$#" -eq 0 ]; then + needroot "This operation" + else + msgerr "$* need root access!" + fi + exit 1 + fi +} + +getportpath() { + for repo in $PORT_REPO; do + if [ -f "$repo/$1/$BUILD_SCRIPT" ]; then + dirname "$repo/$1/$BUILD_SCRIPT" + return 0 + fi + done + return 1 +} + +vercomp() { + if [ "$1" = "$2" ]; then + return 0 # same version + #elif [ "$1" = "$(echo "$1\n$2" | sort -V | head -n1)" ]; then + elif [ "$(printf '%s\n' "$1" "$2" | sort -V | head -n1)" = "$1" ]; then + return 1 # $1 lower than $2 + #echo "1" + else + return 2 # $1 higher than $2 + #echo "2" + fi +} + +installed_pkg_info() { + if isinstalled $2; then + grep ^$1 $PKGDB_DIR/$2/.pkginfo 2>/dev/null | cut -d " " -f3- + fi +} + +allinstalled() { + grep ^name "$PKGDB_DIR"/*/.pkginfo 2>/dev/null | awk '{print $3}' +} + +deps_alias() { + [ -f "$ALIAS_FILE" ] || { + echo $@ + return + } + while [ "$1" ]; do + if [ "$(grep -w ^$1 $ALIAS_FILE)" ]; then + getalias=$(grep -w ^$1 $ALIAS_FILE | awk '{print $2}') + [ "$getalias" ] && echo "$getalias" + else + echo "$1" + fi + shift + unset getalias + done +} + +get_depends() { + ppath=$(getportpath $1) || return 0 + deps=$(grep "^# depends[[:blank:]]*:" $ppath/$BUILD_SCRIPT \ + | sed 's/^# depends[[:blank:]]*:[[:blank:]]*//' \ + | tr ' ' '\n' \ + | awk '!a[$0]++' \ + | sed 's/,//') + deps_alias $deps +} + +confirm() { + printf "$1 (Y/n) " + read -r response + case "$response" in + [Nn][Oo]|[Nn]) echo "$2"; return 2 ;; + *) : ;; + esac + return 0 +} + +checktool() { + if ! command -v $1 >/dev/null; then + msgerr "'$1' not exist in your system!" + exit 1 + fi +} + +needarg() { + [ "$*" ] || { + msgerr "This operation required an arguments!" + exit 1 + } +} + +isinstalled() { + if [ -s "$PKGDB_DIR/$1/.pkginfo" ] && [ "$(grep $1 $PKGDB_DIR/$1/.pkginfo)" ]; then + return 0 + else + return 1 + fi +} + +settermtitle() { + printf "\033]0;$*\a" +} + +scratch_integrity() { + if [ "$1" ]; then + cd / + if [ -f $PKGDB_DIR/$1/.files ]; then + cat $PKGDB_DIR/$1/.files | while read -r line; do + if [ ! -e "$line" ]; then + if [ -L "$line" ]; then + printf "${YELLOW}broken symlink${CRESET} $1: /$line" + else + printf "${RED}file missing${CRESET} $1: /$line" + fi + fi + done + else + echo "Package '$1' not installed." + exit 1 + fi + cd - >/dev/null + else + cd / + for pkg in $(allinstalled); do + cat $PKGDB_DIR/$pkg/.files | while read -r line; do + if [ ! -e "$line" ]; then + if [ -L "$line" ]; then + echo "broken symlink $pkg: /$line" + else + echo "missing file $pkg: /$line" + fi + fi + done + done + cd - >/dev/null + fi +} + +scratch_lock() { + needroot "Locking package" + for pkg in "$@"; do + if ! isinstalled $pkg; then + msgerr "Package '$pkg' is not installed." + elif [ -f $PKGDB_DIR/$pkg/.lock ]; then + msgerr "Package '$pkg' already locked." + else + touch $PKGDB_DIR/$pkg/.lock && msg "Successfully locked package '$pkg'." + fi + done +} + +scratch_locate() { + needarg $@ + for repo in $PORT_REPO; do + grep -R $@ $repo/*/.pkgfiles 2>/dev/null | sed 's/:/ /;s/\/\.pkgfiles//' | awk '{print $1,$4}' | column -t + done +} + +scratch_unlock() { + needroot "Unlocking package" + for pkg in "$@"; do + if ! isinstalled $pkg; then + msgerr "Package '$pkg' is not installed." + elif [ ! -f $PKGDB_DIR/$pkg/.lock ]; then + msgerr "Package '$pkg' is not locked." + else + rm -f $PKGDB_DIR/$pkg/.lock && msg "Successfully unlocked package '$pkg'." + fi + done +} + +scratch_isorphan() { + needarg $@ + for pkg in $(allinstalled); do + if depend=$(get_depends $pkg); then + for dep in $depend; do + if [ $dep = $1 ]; then + return 1 + fi + done + fi + unset depend dep + done + return 0 +} + +scratch_sync() { + checktool httpup + needroot "Updating ports" + + if [ ! -e "$REPO_FILE" ]; then + msgerr "Repo file not found! ($REPO_FILE)" + exit 1 + fi + + grep -Ev '^(#|$)' "$REPO_FILE" | awk '{print $1,$2}' | while read -r repodir repourl; do + if [ "$repodir" ] && [ "$repourl" ]; then + httpup sync $repourl $repodir || { + msgerr "Failed sync from $repourl" + exit 1 + } + fi + done +} + +scratch_trigger() { + needroot "Run trigger" + if [ -z "$*" ]; then + for i in $(seq 12); do + eval trig_$i=1 + done + else + pre_triggers $@ + fi + post_triggers +} + +post_triggers() { + if [ "$trig_12" = 1 ]; then + echo "trigger: Running mkdirs..." + for mkd in $PKGDB_DIR/*/.pkgmkdirs; do + [ -s $mkd ] || continue + grep -Ev '^(#|$)' $mkd | while read -r dir mode uid gid junk; do + if [ -e "$dir" ]; then + if [ "$uid" != '-' ]; then + getent passwd $uid >/dev/null && chown "$uid" "$dir" + fi + if [ "$gid" != '-' ]; then + getent group $gid >/dev/null && chgrp "$gid" "$dir" + fi + if [ "$mode" != '-' ]; then + chmod "$mode" "$dir" + fi + fi + done + done + fi + + if [ "$trig_11" = 1 ] && [ $(command -v fc-cache) ]; then + echo "trigger: Updating fontconfig cache..." + fc-cache -s + fi + + if [ "$trig_10" = 1 ] && [ $(command -v gdk-pixbuf-query-loaders) ]; then + echo "trigger: Probing GDK-Pixbuf loader modules..." + gdk-pixbuf-query-loaders --update-cache + fi + + if [ "$trig_9" = 1 ] && [ $(command -v gio-querymodules) ]; then + echo "trigger: Updating GIO module cache..." + gio-querymodules /usr/lib/gio/modules + fi + + if [ "$trig_8" = 1 ] && [ $(command -v glib-compile-schemas) ]; then + echo "trigger: Compiling GSettings XML schema files..." + glib-compile-schemas /usr/share/glib-2.0/schemas + fi + + if [ "$trig_7" = 1 ] && [ $(command -v gtk-query-immodules-2.0) ]; then + echo "trigger: Probing GTK2 input method modules..." + gtk-query-immodules-2.0 --update-cache + fi + + if [ "$trig_6" = 1 ] && [ $(command -v gtk-query-immodules-3.0) ]; then + echo "trigger: Probing GTK3 input method modules..." + gtk-query-immodules-3.0 --update-cache + fi + + if [ "$trig_5" = 1 ] && [ $(command -v gtk-update-icon-cache) ]; then + echo "trigger: Updating icon theme caches..." + for dir in /usr/share/icons/* ; do + if [ -e $dir/index.theme ]; then + gtk-update-icon-cache -q $dir 2>/dev/null + else + rm -f $dir/icon-theme.cache + rmdir --ignore-fail-on-non-empty $dir + fi + done + fi + + if [ "$trig_4" = 1 ] && [ $(command -v udevadm) ]; then + echo "trigger: Updating hardware database..." + udevadm hwdb --update + fi + + if [ "$trig_3" = 1 ] && [ $(command -v mkfontdir) ] && [ $(command -v mkfontscale) ]; then + echo "trigger: Updating X fontdir indices..." + for dir in $(find /usr/share/fonts -maxdepth 1 -type d \( ! -path /usr/share/fonts \)); do + rm -f $dir/fonts.scale $dir/fonts.dir $dir/.uuid + rmdir --ignore-fail-on-non-empty $dir + [ -d "$dir" ] || continue + mkfontdir $dir + mkfontscale $dir + done + fi + + if [ "$trig_2" = 1 ] && [ $(command -v update-desktop-database) ]; then + echo "trigger: Updating desktop file MIME type cache..." + update-desktop-database --quiet + fi + + if [ "$trig_1" = 1 ] && [ $(command -v update-mime-database) ]; then + echo "trigger: Updating the MIME type database..." + update-mime-database /usr/share/mime + fi +} + +pre_triggers() { + # mime db + if [ "$trig_1" != "1" ]; then + for pkg in $@; do + if [ -s "$PKGDB_DIR/$pkg/.files" ] && [ "$(grep ^usr/share/mime/$ $PKGDB_DIR/$pkg/.files)" ]; then + trig_1=1 + break + fi + done + fi + + # desktop db + if [ "$trig_2" != "1" ]; then + for pkg in $@; do + if [ -s "$PKGDB_DIR/$pkg/.files" ] && [ "$(grep ^usr/share/applications/$ $PKGDB_DIR/$pkg/.files)" ]; then + trig_2=1 + break + fi + done + fi + + # mkfontdir + if [ "$trig_3" != "1" ]; then + for pkg in $@; do + if [ -s "$PKGDB_DIR/$pkg/.files" ] && [ "$(grep ^usr/share/fonts/$ $PKGDB_DIR/$pkg/.files)" ]; then + trig_3=1 + break + fi + done + fi + + # hwdb + if [ "$trig_4" != "1" ]; then + for pkg in $@; do + if [ -s "$PKGDB_DIR/$pkg/.files" ] && [ "$(grep ^etc/udev/hwdb.d/$ $PKGDB_DIR/$pkg/.files)" ]; then + trig_4=1 + break + fi + done + fi + + # icon caches + if [ "$trig_5" != "1" ]; then + for pkg in $@; do + if [ -s "$PKGDB_DIR/$pkg/.files" ] && [ "$(grep ^usr/share/icons/$ $PKGDB_DIR/$pkg/.files)" ]; then + trig_5=1 + break + fi + done + fi + + # gtk3 immodules + if [ "$trig_6" != "1" ]; then + for pkg in $@; do + if [ -s "$PKGDB_DIR/$pkg/.files" ] && [ "$(grep ^usr/lib/gtk-3.0/3.0.0/immodules/.*.so $PKGDB_DIR/$pkg/.files)" ]; then + trig_6=1 + break + fi + done + fi + + # gtk2 immodules + if [ "$trig_7" != "1" ]; then + for pkg in $@; do + if [ -s "$PKGDB_DIR/$pkg/.files" ] && [ "$(grep ^usr/lib/gtk-2.0/2.10.0/immodules/.*.so $PKGDB_DIR/$pkg/.files)" ]; then + trig_7=1 + break + fi + done + fi + + # gsettings schema + if [ "$trig_8" != "1" ]; then + for pkg in $@; do + if [ -s "$PKGDB_DIR/$pkg/.files" ] && [ "$(grep ^usr/share/glib-2.0/schemas/$ $PKGDB_DIR/$pkg/.files)" ]; then + trig_8=1 + break + fi + done + fi + + # gio modules + if [ "$trig_9" != "1" ]; then + for pkg in $@; do + if [ -s "$PKGDB_DIR/$pkg/.files" ] && [ "$(grep ^usr/lib/gio/modules/.*.so $PKGDB_DIR/$pkg/.files)" ]; then + trig_9=1 + break + fi + done + fi + + # gdk-pixbuf + if [ "$trig_10" != "1" ]; then + for pkg in $@; do + if [ -s "$PKGDB_DIR/$pkg/.files" ] && [ "$(grep ^usr/lib/gdk-pixbuf-2.0/2.10.0/loaders/.*.so $PKGDB_DIR/$pkg/.files)" ]; then + trig_10=1 + break + fi + done + fi + + # font caches + if [ "$trig_11" != "1" ]; then + for pkg in $@; do + if [ -s "$PKGDB_DIR/$pkg/.files" ] && [ "$(grep ^usr/share/fonts/$ $PKGDB_DIR/$pkg/.files)" ]; then + trig_11=1 + break + fi + done + fi + + # makedirs + if [ "$trig_12" != "1" ]; then + for pkg in $@; do + if [ -s "$PKGDB_DIR/$pkg/.pkgmkdirs" ]; then + trig_12=1 + break + fi + done + fi +} + +scratch_build() { + while [ "$1" ]; do + case $1 in + -i|-u|-r|-g|-p) ;; + --log) LOG=1;; + -*) OPTS="$OPTS $1";; + *) PKGNAME="$PKGNAME $1";; + esac + shift + done + [ "$PKGNAME" ] || { + echo "Please specify package(s) to build." + return 1 + } + for pkg in $PKGNAME; do + ppath=$(getportpath $pkg) || { + echo "Package '$pkg' not found." + return 1 + } + cd $ppath + settermtitle "Building $pkg..." + if [ "$LOG" ]; then + pkgbuild $OPTS | tee /var/log/pkgbuild.log || { + settermtitle "Building $pkg failed." + return 1 + } + else + pkgbuild $OPTS || { + settermtitle "Building $pkg failed." + return 1 + } + fi + settermtitle "Building $pkg done." + cd - >/dev/null + done +} + +scratch_install() { + needroot "Installing package" + while [ "$1" ]; do + case $1 in + -i|-u) ;; + -r|--reinstall) REINSTALL=1;; + -y|--yes) NOCONFIRM=1;; + -n|--no-dep) NO_DEP=1;; + --exclude=*) EXOPT=$1;; + -*) OPTS="$OPTS $1";; + *) PKGNAME="$PKGNAME $1";; + esac + shift + done + [ "$PKGNAME" ] || { + echo "Please specify package(s) to install." + return 1 + } + # if reinstall, dont calculate dep, just reinstall it then exit + if [ "$REINSTALL" = 1 ]; then + error=0 + for ii in $PKGNAME; do + if [ ! $(getportpath $ii) ]; then + echo "Package '$ii' not found." + elif ! isinstalled $ii; then + echo "Package '$ii' not installed." + else + cd $(getportpath $ii) + settermtitle "Reinstalling $ii..." + pkgbuild $OPTS -r || { + error=1 + break + } + done_pkg="$done_pkg $ii" + cd - >/dev/null + fi + done + settermtitle "Triggering install hook..." + [ "$done_pkg" ] && scratch_trigger $done_pkg + settermtitle "Reinstalling done." + return "$error" + fi + if [ "$NO_DEP" = 1 ]; then + error=0 + for ii in $PKGNAME; do + if [ ! $(getportpath $ii) ]; then + echo "Package '$ii' not found." + elif isinstalled $ii; then + echo "Package '$ii' already installed." + continue + else + cd $(getportpath $ii) + settermtitle "Installing $ii..." + pkgbuild -i $OPTS || { + error=1 + break + } + done_pkg="$done_pkg $ii" + cd - >/dev/null + fi + done + settermtitle "Triggering install hook..." + [ "$done_pkg" ] && scratch_trigger $done_pkg + settermtitle "Installing done." + return "$error" + fi + for i in $PKGNAME; do + if [ ! $(getportpath $i) ]; then + echo "Package '$i' not found." + elif isinstalled $i; then + echo "Package '$i' already installed." + else + IPKG="$IPKG $i" + fi + done + [ "$IPKG" ] || return 0 + echo "Resolving dependencies..." + INST="$(scratch_deplist -q $IPKG $EXOPT)" + if [ "$INST" ]; then + echo + pkgcount=0 + for pkg in $INST; do + pkgcount=$(( pkgcount + 1 )) + printf "[${GREEN}i${CRESET}] $pkg " + done + echo; echo + echo "( $pkgcount install )" + echo + if [ ! "$NOCONFIRM" ]; then + confirm "Continue install package(s)?" "Package installation cancelled." || exit $? + echo + fi + error=0 + count=0 + total=$(echo $INST | wc -w) + for int in $INST; do + count=$(( count + 1 )) + if portpathh=$(getportpath $int); then + cd $portpathh + settermtitle "[ $count/$total ] installing $int..." + pkgbuild -i $OPTS || { + error=1 + count=$(( count - 1 )) + break + } + done_pkg="$done_pkg $int" + cd - >/dev/null + else + msgwarn "Skipping missing package: $int" + fi + unset portpathh + done + settermtitle "Triggering install hook..." + [ "$done_pkg" ] && scratch_trigger $done_pkg + settermtitle "$count/$total package(s) installed." + return "$error" + fi +} + +scratch_remove() { + needroot "Removing package" + while [ "$1" ]; do + case $1 in + -y|--yes) NOCONFIRM=1;; + -*) OPTS="$OPTS $1";; + *) PKGNAME="$PKGNAME $1";; + esac + shift + done + [ "$PKGNAME" ] || { + echo "Please specify package(s) to remove." + return 1 + } + for i in $PKGNAME; do + if ! isinstalled $i; then + echo "Package '$i' not installed." + else + IPKG="$IPKG $i" + fi + done + [ "$IPKG" ] || return 0 + echo "Removing packages..." + echo + pkgcount=0 + count=0 + for pkg in $IPKG; do + pkgcount=$(( pkgcount + 1 )) + printf "[${RED}x${CRESET}] $pkg " + done + echo; echo + echo "( $pkgcount remove )" + echo + [ "$NOCONFIRM" ] || { + confirm "Continue remove package(s)?" "Package removing cancelled." || exit $? + echo + } + for pkg in $IPKG; do + count=$(( count + 1 )) + pre_triggers $pkg + settermtitle "[ $count/$pkgcount ] Removing $pkg..." + pkgdel $pkg $OPTS || { + error=1 + break + } + done + settermtitle "Triggering remove hook..." + post_triggers + settermtitle "$pkgcount package(s) removed." +} + +outdatepkg() { + for pkg in $(allinstalled); do + if [ -f "$MASK_FILE" ] && [ $(grep -Ev '^(#|$| )' $MASK_FILE | grep -w $pkg) ]; then + continue + fi + [ -e "$PKGDB_DIR/$pkg/.lock" ] && continue + getportpath $pkg >/dev/null || continue + . $(getportpath $pkg)/$BUILD_SCRIPT + if [ -z "$name" ] || [ -z "$version" ]; then + continue + fi + iversion=$(installed_pkg_info version $pkg) + irelease=$(installed_pkg_info release $pkg) + if [ "$release" != "$irelease" ] || [ "$version" != "$iversion" ]; then + echo $name + fi + unset iversion irelease version release + done +} + +scratch_sysup() { + needroot "Upgrading package" + while [ "$1" ]; do + case $1 in + -i|-u|-r) ;; + -y|--yes) NOCONFIRM=1;; + -n|--no-dep) NODEP=1;; + --exclude=*) EXOPT=$1;; + -*) OPTS="$OPTS $1";; + esac + shift + done + echo "Checking for outdated packages..." + PKGOUTDATE=$(outdatepkg) + [ "$PKGOUTDATE" ] || { + echo "All packages are up to date." + return 0 + } + [ "$(echo $PKGOUTDATE | tr ' ' '\n' | grep -x scratchpkg)" ] && { + echo + msgerr "Please upgrade 'scratchpkg' first." + return 1 + } + UPGPKG=0 + NEWPKG=0 + if [ "$NODEP" != 1 ]; then + echo "Resolving dependencies..." + DEP=$(scratch_deplist $PKGOUTDATE $EXOPT | awk '{print $2}') + echo + for d in $DEP; do + if [ "$(echo $PKGOUTDATE | tr ' ' '\n' | grep -x $d)" = "$d" ]; then + printf "[${GREEN}u${CRESET}] $d " + WILLINSTALL="$WILLINSTALL $d" + UPGPKG=$(( UPGPKG + 1 )) + elif ! isinstalled $d && [ "$(getportpath "$d")" ]; then + printf "[${CYAN}n${CRESET}] $d " + WILLINSTALL="$WILLINSTALL $d" + NEWPKG=$(( NEWPKG + 1 )) + fi + done + else + echo + for dd in $PKGOUTDATE; do + printf "[${GREEN}u${CRESET}] $dd " + WILLINSTALL="$WILLINSTALL $dd" + UPGPKG=$(( UPGPKG + 1 )) + done + fi + echo; echo + echo "( $UPGPKG upgrade, $NEWPKG new install )" + echo + [ "$NOCONFIRM" ] || { + confirm "Continue upgrade/install these package(s)?" "Package upgrade cancelled." || exit $? + echo + } + error=0 + count=0 + total=$(echo $WILLINSTALL | wc -w) + for inst in $WILLINSTALL; do # install all required dependencies and target packages itself + count=$(( count + 1 )) + cd $(getportpath $inst) + if ! isinstalled $inst; then + settermtitle "[ $count/$total ] Installing $inst..." + pkgbuild -i $OPTS || { + error=1 + count=$(( count - 1 )) + break + } + else + settermtitle "[ $count/$total ] Upgrading $inst..." + pkgbuild -u $OPTS || { + error=1 + count=$(( count - 1 )) + break + } + fi + cd - >/dev/null + done_pkg="$done_pkg $inst" + done + settermtitle "Triggering install hook." + [ "$done_pkg" ] && scratch_trigger $done_pkg + settermtitle "$count/$total package(s) upgraded." + return "$error" +} + +scratch_upgrade() { + needroot "Upgrading package" + while [ "$1" ]; do + case $1 in + -i|-r) ;; + -y|--yes) NOCONFIRM=1;; + -d|--no-dep) NO_DEP=1;; + --exclude=*) EXOPT=$1;; + -*) OPTS="$OPTS $1";; + *) PKGNAME="$PKGNAME $1";; + esac + shift + done + [ "$PKGNAME" ] || { + echo "Please specify package(s) to upgrade." + return 1 + } + for pkg in $PKGNAME; do + if ! isinstalled $pkg; then + echo "Package '$pkg' not installed." + continue + elif [ ! $(getportpath $pkg) ]; then + echo "Package '$pkg' not exist." + continue + else + . $(getportpath $pkg)/$BUILD_SCRIPT + if [ "$(installed_pkg_info version $pkg)-$(installed_pkg_info release $pkg)" = "$version-$release" ]; then + echo "Package '$pkg' is up to date." + continue + fi + fi + upkg="$upkg $pkg" + done + [ "$upkg" ] || return 0 + + UPGPKG=0 + NEWPKG=0 + if [ "$NODEP" != 1 ]; then + echo "Resolving dependencies..." + DEP=$(scratch_deplist $upkg $EXOPT | awk '{print $2}') + echo + for d in $DEP; do + if [ "$(echo $upkg | tr ' ' '\n' | grep -x $d)" = "$d" ]; then + printf "[${GREEN}u${CRESET}] $d " + WILLINSTALL="$WILLINSTALL $d" + UPGPKG=$(( UPGPKG + 1 )) + elif ! isinstalled $d && [ "$(getportpath "$d")" ]; then + printf "[${CYAN}n${CRESET}] $d " + WILLINSTALL="$WILLINSTALL $d" + NEWPKG=$(( NEWPKG + 1 )) + fi + done + else + echo + for dd in $upkg; do + printf "[${GREEN}u${CRESET}] $dd " + WILLINSTALL="$WILLINSTALL $dd" + UPGPKG=$(( UPGPKG + 1 )) + done + fi + echo; echo + echo "( $UPGPKG upgrade, $NEWPKG new install )" + echo + [ "$NOCONFIRM" ] || { + confirm "Continue upgrade/install these package(s)?" "Package upgrade cancelled." || exit $? + echo + } + error=0 + count=0 + total=$(echo $WILLINSTALL | wc -w) + for inst in $WILLINSTALL; do # install all required dependencies and target packages itself + count=$(( count + 1 )) + cd $(getportpath $inst) + if ! isinstalled $inst; then + settermtitle "[ $count/$total ] Installing $inst..." + pkgbuild -i $OPTS || { + error=1 + count=$(( count - 1 )) + break + } + else + settermtitle "[ $count/$total ] Upgrading $inst..." + pkgbuild -u $OPTS || { + error=1 + count=$(( count - 1 )) + break + } + fi + cd - >/dev/null + done_pkg="$done_pkg $inst" + done + settermtitle "Triggering install hook." + [ "$done_pkg" ] && scratch_trigger $done_pkg + settermtitle "$count/$total package(s) upgraded." + return "$error" +} + +scratch_outdate() { + for pkg in $(allinstalled); do + if [ "$(getportpath $pkg)" ]; then + . $(getportpath $pkg)/$BUILD_SCRIPT + if [ -z "$name" ] || [ -z "$version" ]; then + continue + fi + iversion=$(installed_pkg_info version $pkg) + irelease=$(installed_pkg_info release $pkg) + [ -f "$PKGDB_DIR/$pkg/.lock" ] && ITSLOCK="[masked]" + if [ -f "$MASK_FILE" ] && [ $(grep -Ev '^(#|$| )' $MASK_FILE | grep $pkg) ]; then + ITSLOCK="[masked]" + fi + #outdatemsg="$name $iversion-$irelease => $version-$release $ITSLOCK" + #newerinstmsg="$name $iversion-$irelease => $version-$release [newer installed] $ITSLOCK" + outdatemsg="$name ${RED}$iversion-$irelease${CRESET} => ${GREEN}$version-$release${CRESET} ${CYAN}$ITSLOCK${CRESET}" + newerinstmsg="$name ${RED}$iversion-$irelease${CRESET} => ${GREEN}$version-$release${CRESET} ${YELLOW}[newer installed]${CRESET} ${CYAN}$ITSLOCK${CRESET}" + if [ "$version" != "$iversion" ]; then + vercomp $version $iversion + if [ $? = 2 ]; then + echo -e "$outdatemsg" + OUTDATE=yes + elif [ $? = 1 ]; then + echo -e "$newerinstmsg" + OUTDATE=yes + fi + elif [ "$release" != "$irelease" ]; then + vercomp $release $irelease + if [ $? = 2 ]; then + echo -e "$outdatemsg" + OUTDATE=yes + elif [ $? = 1 ]; then + echo -e "$newerinstmsg" + OUTDATE=yes + fi + fi + unset ITSLOCK name version + fi + done + + [ ! "$OUTDATE" ] && msg "All packages are up to date." +} + +scratch_search() { + needarg $@ + arg=$* + for repo in $PORT_REPO; do + [ -d $repo ] || continue + out=$(grep -R "# description" $repo/*/$BUILD_SCRIPT | grep "$arg" | awk -F : '{print $1}' | sort) + [ "$out" ] || continue + found=1 + for line in $out; do + repo=$(echo $line | rev | awk -F / '{print $3}' | rev) + desc=$(grep "^# description[[:blank:]]*:" $line | sed 's/^# description[[:blank:]]*:[[:blank:]]*//') + . $line + if isinstalled $name; then + ins="[${GREEN}*${CRESET}]" + else + ins="[ ]" + fi + printf "$ins ${PURPLE}($repo)${CRESET} $name ${CYAN}$version-$release${CRESET}: $desc\n" + unset repo desc name version release build + done + unset out + done + if [ ! "$found" ]; then + msg "No matching package found." + fi +} + +scratch_cache() { + needroot "Clear old caches" + + allcachepkg=/tmp/.allcachepkg.$$ + allcachesrc=/tmp/.allcachesrc.$$ + keepcachepkg=/tmp/.keepcachepkg.$$ + keepcachesrc=/tmp/.keepcachesrc.$$ + diffcachepkg=/tmp/.diffcachepkg.$$ + diffcachesrc=/tmp/.diffcachesrc.$$ + + [ -f /etc/scratchpkg.conf ] && . /etc/scratchpkg.conf + + touch \ + $allcachepkg \ + $allcachesrc \ + $keepcachepkg \ + $keepcachesrc \ + $diffcachepkg \ + $diffcachesrc + + if [ "$(find $PACKAGE_DIR -mindepth 1 -print -quit 2>/dev/null)" ]; then + for list in "$PACKAGE_DIR"/*; do + basename $list >> "$allcachepkg" + done + fi + + if [ "$(find $SOURCE_DIR -mindepth 1 -print -quit 2>/dev/null)" ]; then + for list in "$SOURCE_DIR"/*; do + basename $list >> "$allcachesrc" + done + fi + + for repo in $PORT_REPO; do + if [ "$(find $repo/*/ -mindepth 1 -print -quit 2>/dev/null)" ]; then # check directory if its not empty + for port in $repo/*/$BUILD_SCRIPT; do + . $port + echo "$name-$version-$release.spkg.tar.$COMPRESSION_MODE" >> "$keepcachepkg" + if [ "$source" ]; then + for src in $source; do + if echo $src | grep -Eq "(ftp|http|https)://"; then + if echo $src | grep -Eq "::(ftp|http|https)://"; then + sourcename="$(echo $src | awk -F '::' '{print $1}')" + else + sourcename="$(echo $src | rev | cut -d / -f 1 | rev)" + fi + echo $sourcename >> "$keepcachesrc" + fi + done + fi + done + fi + done + grep -Fxv -f "$keepcachepkg" "$allcachepkg" > "$diffcachepkg" + grep -Fxv -f "$keepcachesrc" "$allcachesrc" > "$diffcachesrc" + + cat $diffcachepkg + cat $diffcachesrc + + if [ -s "$diffcachepkg" ]; then + cd "$PACKAGE_DIR" + sizepkg=$(du -ch $(cat $diffcachepkg) | grep total | awk '{print $1}') + cd - >/dev/null + else + sizepkg=0M + fi + + if [ -s "$diffcachesrc" ]; then + cd "$SOURCE_DIR" + sizesrc=$(du -ch $(cat $diffcachesrc) | grep total | awk '{print $1}') + cd - >/dev/null + else + sizesrc=0M + fi + + echo "Total package cache size: $sizepkg" + echo "Total source cache size : $sizesrc" + + if [ -s "$diffcachepkg" ] || [ -s "$diffcachesrc" ]; then + echo + confirm "Clear old caches?" "Old caches is kept." && { + for i in $(cat $diffcachepkg); do + [ -e "$PACKAGE_DIR/$i" ] && rm -v "$PACKAGE_DIR/$i" + done + for i in $(cat $diffcachesrc); do + [ -e "$SOURCE_DIR/$i" ] && rm -v "$SOURCE_DIR/$i" + done + } + fi + + rm -f \ + "$allcachepkg" \ + "$allcachesrc" \ + "$keepcachepkg" \ + "$keepcachesrc" \ + "$diffcachepkg" \ + "$diffcachesrc" +} + +scratch_deplist() { + OLDIFS=$IFS + IFS=, + while [ "$1" ]; do + case $1 in + -q|--quick) quick=1;; + --exclude=*) for i in ${1#*=}; do exclude="$exclude $i"; done;; + -*) ;; + *) PKG="$PKG $1";; + esac + shift + done + IFS=$OLDIFS + [ "$PKG" ] || { + echo "Please specify package(s) to list dependencies." + return 1 + } + for p in $PKG; do + if [ "$(getportpath $p)" ]; then + PPKG="$PPKG $p" + else + [ "$quick" = 1 ] || msgerr "Package '$p' not exist." + fi + done + + for p in $PPKG; do + deplist $p + done + + [ "$DEP" ] || return 0 + + if [ "$quick" = 1 ]; then + echo $DEP | tr ' ' '\n' + else + for p in $DEP; do + if isinstalled $p; then + echo "[*] $p" + else + echo "[-] $p" + fi + done + if [ "$MISSINGDEP" ]; then + for m in $MISSINGDEP; do + echo "Missing deps: $m" | sed 's/(/ (/' + done + fi + fi +} + +deplist() { + # skip excluded dependencies + if echo $exclude | tr " " "\n" | grep -qx $1; then + return 0 + fi + + # check currently process for circular dependencies + # for circular dependencies, found first will take precedence + [ "$CHECK" ] && { + if echo $CHECK | tr " " "\n" | grep -qx $1; then + return 0 + fi + } + + # add package to currently process + CHECK="$CHECK $1" + + # check dependencies + for i in $(get_depends $1); do + if [ "$quick" = 1 ] && isinstalled $i; then + continue + else + if ! echo $DEP | tr " " "\n" | grep -qx $i; then + if ! getportpath $i >/dev/null; then + MISSINGDEP="$MISSINGDEP $i($1)" + else + deplist $i + fi + fi + fi + done + + # add dependency to list checked dep + if ! echo $DEP | tr " " "\n" | grep -qx $1; then + if [ "$quick" = 1 ]; then + isinstalled $1 || DEP="$DEP $1" + else + DEP="$DEP $1" + fi + fi + + # delete item from loop process + CHECK=$(echo $CHECK | sed "s/$1//") +} + +scratch_cat() { + needarg $@ + if PPATH=$(getportpath "$1"); then + cat "$PPATH/$BUILD_SCRIPT" + else + msgerr "Port '$1' not exist." + return 1 + fi +} + +scratch_dependent() { + needarg $@ + if [ "$(getportpath $1)" ]; then + grep -R "# depends[[:blank:]]*:" $PORT_REPO \ + | sed "s,:# depends[[:blank:]]*:[[:blank:]]*,#|,;s, ,|,g;s,$,|,g" \ + | grep "|$1|" \ + | awk -F "#" '{print $1}' \ + | rev \ + | awk -F / '{print $2}' \ + | rev + else + msgerr "Port '$1' not exist." + return 1 + fi +} + +scratch_depends() { + needarg $@ + if getportpath "$1" >/dev/null; then + depends=$(get_depends $1) + else + msgerr "Port '$1' not exist." + return 1 + fi + + for dep in $depends; do + if isinstalled $dep; then + msginst "$dep" + elif getportpath $dep >/dev/null; then + msgnoinst "$dep" + else + msgmiss "$dep" + fi + done +} + +scratch_dup() { + dup=$(find $PORT_REPO -type d -print | grep -Exv "($(echo $PORT_REPO | tr ' ' '|'))" | \ + rev | cut -d '/' -f1 | rev | sort | uniq -d) + + if [ "$dup" ]; then + for dp in $dup; do + for repo in $PORT_REPO; do + [ -d $repo/$dp ] && echo "$repo/$dp" + done + done + else + msg "No duplicate ports found." + fi +} + +scratch_foreign() { + for pkg in $(allinstalled); do + if ! getportpath $pkg >/dev/null; then + iname=$(installed_pkg_info name $pkg) + iversion=$(installed_pkg_info version $pkg) + irelease=$(installed_pkg_info release $pkg) + echo "$iname $iversion-$irelease" + fi + unset iname iversion irelease + done +} + +scratch_info() { + needarg $@ + ppath=$(getportpath $1) || return 1 + + . $ppath/$BUILD_SCRIPT + desc=$(grep "^# description[[:blank:]]*:" $ppath/$BUILD_SCRIPT | sed 's/^# description[[:blank:]]*:[[:blank:]]*//') + maint=$(grep "^# maintainer[[:blank:]]*:" $ppath/$BUILD_SCRIPT | sed 's/^# maintainer[[:blank:]]*:[[:blank:]]*//') + deps=$(get_depends $1 | tr '\n' ' ') + + echo "Name: $1" + echo "Path: $ppath" + echo "Version: $version" + echo "Release: $release" + echo "Description: $desc" + echo "Maintainer: $maint" + echo "Dependencies: $deps" +} + +scratch_installed() { + for all in $(allinstalled); do + printf "%s" "$all " + grep -e ^version -e ^release $PKGDB_DIR/$all/.pkginfo | awk '{print $3}' | tr '\n' '-' | sed 's:\-$::' + echo + done +} + +scratch_missingdep() { + for pkg in $(allinstalled); do + if getportpath "$pkg" >/dev/null; then + depends=$(get_depends $pkg) + fi + if [ "$depends" ]; then + for d in $depends; do + if ! isinstalled $d; then + if [ -z "$msd" ]; then + msd="$d" + else + msd="$msd $d" + fi + fi + done + fi + [ "$msd" ] && echo "$pkg: $msd" + unset depends msd + done +} + +scratch_locked() { + for pkg in $(allinstalled); do + [ -f "$PKGDB_DIR/$pkg/.lock" ] && echo "$pkg" + done +} + +scratch_orphan() { + tmpallpkg="/tmp/.pkgquery_allpkg.$$" + tmpalldep="/tmp/.pkgquery_alldep.$$" + for pkg in $(allinstalled); do + echo $pkg >> $tmpallpkg + dep="$dep $(get_depends $pkg)" + done + echo $dep | tr ' ' '\n' | sort | uniq > "$tmpalldep" + grep -xvF -f "$tmpalldep" "$tmpallpkg" + rm "$tmpalldep" "$tmpallpkg" +} + +scratch_path() { + needarg $@ + if PPATH=$(getportpath "$1"); then + echo "$PPATH" + else + msgerr "Port '$1' not exist." + return 1 + fi +} + +scratch_provide() { + needarg $@ + arg=$(echo $1 | sed "s/^\///") + grep -R "$arg" $PKGDB_DIR/*/.files \ + | sed "s:$PKGDB_DIR/::" \ + | sed "s:/.files::" \ + | tr : " " \ + | column -t +} + +scratch_readme() { + needarg $@ + if PPATH=$(getportpath "$1"); then + if [ -f "$PPATH/readme" ]; then + cat "$PPATH/readme" + else + msgerr "Port '$1' does not have readme." + fi + else + msgerr "Port '$1' not exist." + exit 1 + fi +} + +scratch_files() { + needarg $@ + if isinstalled $1; then + cat "$PKGDB_DIR/$1/.files" + else + msg "Package '$1' not installed." + fi +} + +scratch_help() { + cat << EOF +Usage: + $(basename $0) [] + +Options: + install install ports (use pkgbuild arg, except '-i' & '-u') + -r|--reinstall reinstall + -n|--no-dep skip dependencies + -y|--yes skip ask user permission + --exclude=* exclude dependencies, comma separated + + upgrade upgrade ports (use pkgbuild arg, except '-i' & '-r') + -n|--no-dep skip dependencies + -y|--yes skip ask user permission + --exclude=* exclude dependencies, comma separated + + remove remove installed ports (use pkgdel arg) + -y|--yes skip ask user permission + + sysup full system upgrade (use pkgbuild arg, except '-i', '-r' & '-u') + -n|--no-dep skip dependencies + -y|--yes skip ask user permission + --exclude=* exclude dependencies, comma separated + + deplist print all dependencies for ports + -q|--quick skip installed ports + --exclude=* exclude dependencies, comma separated + + build build ports (use pkgbuild arg, except '-i', '-u', '-r', '-g', & '-p') + --log log build process (/var/log/pkgbuild.log) + + lock locking ports prevent upgrade + unlock unlock locked ports + trigger [ports] run system trigger + search find ports in repo + cat print spkgbuild + depends print dependencies + dependent print dependent + path print path in repo + provide print port's provided files + readme print readme file, if exist + files print files installed + info print information + locate print location of files in ports repo + sync update ports database + outdate print outdated ports + cache print and clear old pkg and src caches + integrity check installed port integrity + dup print duplicate ports in repo + installed print all installed ports + locked print loacked ports + missingdep print missing dependencies + orphan print orphan installed ports + foreign print foreign ports + help print this help msg + +Global options: + --append-repo= append custom repo path + --prepend-repo= prepend custom repo path + --repo-file= use custom repo file (default: $REPO_FILE) + --nocolor disable colour for output + +EOF +} + +print_runhelp_msg() { + echo "Run '$(basename $0) help' to see available options." + exit 2 +} + +# check for 'pkgadd', required for package database path +command -v pkgadd >/dev/null 2>&1 || { + echo "'pkgadd' not found in \$PATH!" + exit 1 +} + +mode=$1 + +[ "$mode" ] || { + print_runhelp_msg +} + +shift + +for opt in $@; do + case $opt in + --nocolor) nocolor;; + --repo=*) PORT_REPO="$PORT_REPO ${opt#*=}";; + --repo-file=*) REPO_FILE="${opt#*=}";; + --alias-file=*) ALIAS_FILE="${opt#*=}";; + --*) MAINOPTS="$MAINOPTS $opt";; + -*) char=${#opt}; count=1 + while [ "$count" != "$char" ]; do + count=$((count+1)) + MAINOPTS="$MAINOPTS -$(printf '%s' $opt | cut -c $count)" + done;; + *) MAINOPTS="$MAINOPTS $opt";; + esac + shift +done + +BUILD_SCRIPT="spkgbuild" +PKGDB_DIR="$(pkgadd --print-dbdir)" +REPO_FILE="${REPO_FILE:-/etc/scratchpkg.repo}" +ALIAS_FILE="${ALIAS_FILE:-/etc/scratchpkg.alias}" +MASK_FILE="${MASK_FILE:-/etc/scratchpkg.mask}" + +# default value from pkgbuild +SOURCE_DIR="/var/cache/scratchpkg/sources" +PACKAGE_DIR="/var/cache/scratchpkg/packages" +COMPRESSION_MODE="xz" + +if [ -f "$REPO_FILE" ]; then + for repodir in $(grep -Ev '^(#|$)' "$REPO_FILE" | awk '{print $1}'); do + PORT_REPO="$PORT_REPO $repodir" + done +fi + +if [ "$(command -v scratch_$mode)" ]; then + scratch_$mode $MAINOPTS +else + print_runhelp_msg +fi + +exit $? diff --git a/scratch b/scratch index d97e651..57ef696 100755 --- a/scratch +++ b/scratch @@ -82,7 +82,8 @@ getportpath() { vercomp() { if [ "$1" = "$2" ]; then return 0 # same version - elif [ "$1" = "$(echo "$1\n$2" | sort -V | head -n1)" ]; then + #elif [ "$1" = "$(echo "$1\n$2" | sort -V | head -n1)" ]; then + elif [ "$(printf '%s\n' "$1" "$2" | sort -V | head -n1)" = "$1" ]; then return 1 # $1 lower than $2 else return 2 # $1 higher than $2 @@ -916,24 +917,27 @@ scratch_outdate() { if [ -f "$MASK_FILE" ] && [ $(grep -Ev '^(#|$| )' $MASK_FILE | grep $pkg) ]; then ITSLOCK="[masked]" fi - outdatemsg="$name $iversion-$irelease => $version-$release $ITSLOCK" - newerinstmsg="$name $iversion-$irelease => $version-$release [newer installed] $ITSLOCK" + #outdatemsg="$name $iversion-$irelease => $version-$release $ITSLOCK" + #newerinstmsg="$name $iversion-$irelease => $version-$release [newer installed] $ITSLOCK" + outdatemsg="$name ${RED}$iversion-$irelease${CRESET} => ${GREEN}$version-$release${CRESET} ${CYAN}$ITSLOCK${CRESET}" + newerinstmsg="$name ${RED}$iversion-$irelease${CRESET} => ${GREEN}$version-$release${CRESET} ${YELLOW}[newer installed]${CRESET} ${CYAN}$ITSLOCK${CRESET}" + if [ "$version" != "$iversion" ]; then vercomp $version $iversion if [ $? = 2 ]; then - echo "$outdatemsg" + echo -e "$outdatemsg" OUTDATE=yes elif [ $? = 1 ]; then - echo "$newerinstmsg" + echo -e "$newerinstmsg" OUTDATE=yes fi elif [ "$release" != "$irelease" ]; then vercomp $release $irelease if [ $? = 2 ]; then - echo "$outdatemsg" + echo -e "$outdatemsg" OUTDATE=yes elif [ $? = 1 ]; then - echo "$newerinstmsg" + echo -e "$newerinstmsg" OUTDATE=yes fi fi @@ -970,7 +974,28 @@ scratch_search() { msg "No matching package found." fi } - +scratch_changelog() { + needarg $@ + arg=$* + for repo in $PORT_REPO; do + #echo $repo/$1 + if [[ -d $repo/$1 ]]; + then + found=1 + if [[ -f $repo/$1/CHANGELOG ]]; + then + cat $repo/$1/CHANGELOG; + else + echo "No Changelog Exists" + fi + break + fi + done + if [ ! "$found" ]; + then + msg "No matching package found" + fi +} scratch_cache() { needroot "Clear old caches" @@ -1370,6 +1395,7 @@ Options: trigger [ports] run system trigger search find ports in repo + changelog find changelog in package cat print spkgbuild depends print dependencies dependent print dependent diff --git a/scratch-test.save b/scratch-test.save new file mode 100755 index 0000000..4be1d19 --- /dev/null +++ b/scratch-test.save @@ -0,0 +1,1486 @@ +#!/bin/sh +# +# scratchpkg +# +# Copyright (c) 2018 by Emmett1 (emmett1.2miligrams@gmail.com) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +RED='\e[0;31m' +GREEN='\e[0;32m' +YELLOW='\e[0;33m' +CYAN='\e[0;36m' +PURPLE='\e[0;35m' +CRESET='\e[0m' + +nocolor() { + RED= + GREEN= + YELLOW= + CYAN= + PURPLE= + CRESET= +} + +msg() { + printf "${GREEN}==>${CRESET} %s\n" "$1" +} + +msginst() { + printf "[${GREEN}i${CRESET}] %s\n" "$1" +} + +msgmiss() { + printf "[${YELLOW}m${CRESET}] %s\n" "$1" +} + +msgnoinst() { + printf "[-] %s\n" "$1" +} + +msgerr() { + printf "${RED}==> ERROR:${CRESET} %s\n" "$1" >&2 +} + +msgwarn() { + printf "${YELLOW}==> WARNING:${CRESET} %s\n" "$1" >&2 +} + +needroot() { + if [ "$(id -u)" != 0 ]; then + if [ "$#" -eq 0 ]; then + needroot "This operation" + else + msgerr "$* need root access!" + fi + exit 1 + fi +} + +getportpath() { + for repo in $PORT_REPO; do + if [ -f "$repo/$1/$BUILD_SCRIPT" ]; then + dirname "$repo/$1/$BUILD_SCRIPT" + return 0 + fi + done + return 1 +} + +vercomp() { + if [ "$1" = "$2" ]; then + return 0 # same version + #elif [ "$1" = "$(echo "$1\n$2" | sort -V | head -n1)" ]; then + elif [ "$(printf '%s\n' "$1" "$2" | sort -V | head -n1)" = "$1" ]; then + return 1 # $1 lower than $2 + #echo "1" + else + return 2 # $1 higher than $2 + #echo "2" + fi +} + +installed_pkg_info() { + if isinstalled $2; then + grep ^$1 $PKGDB_DIR/$2/.pkginfo 2>/dev/null | cut -d " " -f3- + fi +} + +allinstalled() { + grep ^name "$PKGDB_DIR"/*/.pkginfo 2>/dev/null | awk '{print $3}' +} + +deps_alias() { + [ -f "$ALIAS_FILE" ] || { + echo $@ + return + } + while [ "$1" ]; do + if [ "$(grep -w ^$1 $ALIAS_FILE)" ]; then + getalias=$(grep -w ^$1 $ALIAS_FILE | awk '{print $2}') + [ "$getalias" ] && echo "$getalias" + else + echo "$1" + fi + shift + unset getalias + done +} + +get_depends() { + ppath=$(getportpath $1) || return 0 + deps=$(grep "^# depends[[:blank:]]*:" $ppath/$BUILD_SCRIPT \ + | sed 's/^# depends[[:blank:]]*:[[:blank:]]*//' \ + | tr ' ' '\n' \ + | awk '!a[$0]++' \ + | sed 's/,//') + deps_alias $deps +} + +confirm() { + printf "$1 (Y/n) " + read -r response + case "$response" in + [Nn][Oo]|[Nn]) echo "$2"; return 2 ;; + *) : ;; + esac + return 0 +} + +checktool() { + if ! command -v $1 >/dev/null; then + msgerr "'$1' not exist in your system!" + exit 1 + fi +} + +needarg() { + [ "$*" ] || { + msgerr "This operation required an arguments!" + exit 1 + } +} + +isinstalled() { + if [ -s "$PKGDB_DIR/$1/.pkginfo" ] && [ "$(grep $1 $PKGDB_DIR/$1/.pkginfo)" ]; then + return 0 + else + return 1 + fi +} + +settermtitle() { + printf "\033]0;$*\a" +} + +scratch_integrity() { + if [ "$1" ]; then + cd / + if [ -f $PKGDB_DIR/$1/.files ]; then + cat $PKGDB_DIR/$1/.files | while read -r line; do + if [ ! -e "$line" ]; then + if [ -L "$line" ]; then + printf "${YELLOW}broken symlink${CRESET} $1: /$line" + else + printf "${RED}file missing${CRESET} $1: /$line" + fi + fi + done + else + echo "Package '$1' not installed." + exit 1 + fi + cd - >/dev/null + else + cd / + for pkg in $(allinstalled); do + cat $PKGDB_DIR/$pkg/.files | while read -r line; do + if [ ! -e "$line" ]; then + if [ -L "$line" ]; then + echo "broken symlink $pkg: /$line" + else + echo "missing file $pkg: /$line" + fi + fi + done + done + cd - >/dev/null + fi +} + +scratch_lock() { + needroot "Locking package" + for pkg in "$@"; do + if ! isinstalled $pkg; then + msgerr "Package '$pkg' is not installed." + elif [ -f $PKGDB_DIR/$pkg/.lock ]; then + msgerr "Package '$pkg' already locked." + else + touch $PKGDB_DIR/$pkg/.lock && msg "Successfully locked package '$pkg'." + fi + done +} + +scratch_locate() { + needarg $@ + for repo in $PORT_REPO; do + grep -R $@ $repo/*/.pkgfiles 2>/dev/null | sed 's/:/ /;s/\/\.pkgfiles//' | awk '{print $1,$4}' | column -t + done +} + +scratch_unlock() { + needroot "Unlocking package" + for pkg in "$@"; do + if ! isinstalled $pkg; then + msgerr "Package '$pkg' is not installed." + elif [ ! -f $PKGDB_DIR/$pkg/.lock ]; then + msgerr "Package '$pkg' is not locked." + else + rm -f $PKGDB_DIR/$pkg/.lock && msg "Successfully unlocked package '$pkg'." + fi + done +} + +scratch_isorphan() { + needarg $@ + for pkg in $(allinstalled); do + if depend=$(get_depends $pkg); then + for dep in $depend; do + if [ $dep = $1 ]; then + return 1 + fi + done + fi + unset depend dep + done + return 0 +} + +scratch_sync() { + checktool httpup + needroot "Updating ports" + + if [ ! -e "$REPO_FILE" ]; then + msgerr "Repo file not found! ($REPO_FILE)" + exit 1 + fi + + grep -Ev '^(#|$)' "$REPO_FILE" | awk '{print $1,$2}' | while read -r repodir repourl; do + if [ "$repodir" ] && [ "$repourl" ]; then + httpup sync $repourl $repodir || { + msgerr "Failed sync from $repourl" + exit 1 + } + fi + done +} + +scratch_trigger() { + needroot "Run trigger" + if [ -z "$*" ]; then + for i in $(seq 12); do + eval trig_$i=1 + done + else + pre_triggers $@ + fi + post_triggers +} + +post_triggers() { + if [ "$trig_12" = 1 ]; then + echo "trigger: Running mkdirs..." + for mkd in $PKGDB_DIR/*/.pkgmkdirs; do + [ -s $mkd ] || continue + grep -Ev '^(#|$)' $mkd | while read -r dir mode uid gid junk; do + if [ -e "$dir" ]; then + if [ "$uid" != '-' ]; then + getent passwd $uid >/dev/null && chown "$uid" "$dir" + fi + if [ "$gid" != '-' ]; then + getent group $gid >/dev/null && chgrp "$gid" "$dir" + fi + if [ "$mode" != '-' ]; then + chmod "$mode" "$dir" + fi + fi + done + done + fi + + if [ "$trig_11" = 1 ] && [ $(command -v fc-cache) ]; then + echo "trigger: Updating fontconfig cache..." + fc-cache -s + fi + + if [ "$trig_10" = 1 ] && [ $(command -v gdk-pixbuf-query-loaders) ]; then + echo "trigger: Probing GDK-Pixbuf loader modules..." + gdk-pixbuf-query-loaders --update-cache + fi + + if [ "$trig_9" = 1 ] && [ $(command -v gio-querymodules) ]; then + echo "trigger: Updating GIO module cache..." + gio-querymodules /usr/lib/gio/modules + fi + + if [ "$trig_8" = 1 ] && [ $(command -v glib-compile-schemas) ]; then + echo "trigger: Compiling GSettings XML schema files..." + glib-compile-schemas /usr/share/glib-2.0/schemas + fi + + if [ "$trig_7" = 1 ] && [ $(command -v gtk-query-immodules-2.0) ]; then + echo "trigger: Probing GTK2 input method modules..." + gtk-query-immodules-2.0 --update-cache + fi + + if [ "$trig_6" = 1 ] && [ $(command -v gtk-query-immodules-3.0) ]; then + echo "trigger: Probing GTK3 input method modules..." + gtk-query-immodules-3.0 --update-cache + fi + + if [ "$trig_5" = 1 ] && [ $(command -v gtk-update-icon-cache) ]; then + echo "trigger: Updating icon theme caches..." + for dir in /usr/share/icons/* ; do + if [ -e $dir/index.theme ]; then + gtk-update-icon-cache -q $dir 2>/dev/null + else + rm -f $dir/icon-theme.cache + rmdir --ignore-fail-on-non-empty $dir + fi + done + fi + + if [ "$trig_4" = 1 ] && [ $(command -v udevadm) ]; then + echo "trigger: Updating hardware database..." + udevadm hwdb --update + fi + + if [ "$trig_3" = 1 ] && [ $(command -v mkfontdir) ] && [ $(command -v mkfontscale) ]; then + echo "trigger: Updating X fontdir indices..." + for dir in $(find /usr/share/fonts -maxdepth 1 -type d \( ! -path /usr/share/fonts \)); do + rm -f $dir/fonts.scale $dir/fonts.dir $dir/.uuid + rmdir --ignore-fail-on-non-empty $dir + [ -d "$dir" ] || continue + mkfontdir $dir + mkfontscale $dir + done + fi + + if [ "$trig_2" = 1 ] && [ $(command -v update-desktop-database) ]; then + echo "trigger: Updating desktop file MIME type cache..." + update-desktop-database --quiet + fi + + if [ "$trig_1" = 1 ] && [ $(command -v update-mime-database) ]; then + echo "trigger: Updating the MIME type database..." + update-mime-database /usr/share/mime + fi +} + +pre_triggers() { + # mime db + if [ "$trig_1" != "1" ]; then + for pkg in $@; do + if [ -s "$PKGDB_DIR/$pkg/.files" ] && [ "$(grep ^usr/share/mime/$ $PKGDB_DIR/$pkg/.files)" ]; then + trig_1=1 + break + fi + done + fi + + # desktop db + if [ "$trig_2" != "1" ]; then + for pkg in $@; do + if [ -s "$PKGDB_DIR/$pkg/.files" ] && [ "$(grep ^usr/share/applications/$ $PKGDB_DIR/$pkg/.files)" ]; then + trig_2=1 + break + fi + done + fi + + # mkfontdir + if [ "$trig_3" != "1" ]; then + for pkg in $@; do + if [ -s "$PKGDB_DIR/$pkg/.files" ] && [ "$(grep ^usr/share/fonts/$ $PKGDB_DIR/$pkg/.files)" ]; then + trig_3=1 + break + fi + done + fi + + # hwdb + if [ "$trig_4" != "1" ]; then + for pkg in $@; do + if [ -s "$PKGDB_DIR/$pkg/.files" ] && [ "$(grep ^etc/udev/hwdb.d/$ $PKGDB_DIR/$pkg/.files)" ]; then + trig_4=1 + break + fi + done + fi + + # icon caches + if [ "$trig_5" != "1" ]; then + for pkg in $@; do + if [ -s "$PKGDB_DIR/$pkg/.files" ] && [ "$(grep ^usr/share/icons/$ $PKGDB_DIR/$pkg/.files)" ]; then + trig_5=1 + break + fi + done + fi + + # gtk3 immodules + if [ "$trig_6" != "1" ]; then + for pkg in $@; do + if [ -s "$PKGDB_DIR/$pkg/.files" ] && [ "$(grep ^usr/lib/gtk-3.0/3.0.0/immodules/.*.so $PKGDB_DIR/$pkg/.files)" ]; then + trig_6=1 + break + fi + done + fi + + # gtk2 immodules + if [ "$trig_7" != "1" ]; then + for pkg in $@; do + if [ -s "$PKGDB_DIR/$pkg/.files" ] && [ "$(grep ^usr/lib/gtk-2.0/2.10.0/immodules/.*.so $PKGDB_DIR/$pkg/.files)" ]; then + trig_7=1 + break + fi + done + fi + + # gsettings schema + if [ "$trig_8" != "1" ]; then + for pkg in $@; do + if [ -s "$PKGDB_DIR/$pkg/.files" ] && [ "$(grep ^usr/share/glib-2.0/schemas/$ $PKGDB_DIR/$pkg/.files)" ]; then + trig_8=1 + break + fi + done + fi + + # gio modules + if [ "$trig_9" != "1" ]; then + for pkg in $@; do + if [ -s "$PKGDB_DIR/$pkg/.files" ] && [ "$(grep ^usr/lib/gio/modules/.*.so $PKGDB_DIR/$pkg/.files)" ]; then + trig_9=1 + break + fi + done + fi + + # gdk-pixbuf + if [ "$trig_10" != "1" ]; then + for pkg in $@; do + if [ -s "$PKGDB_DIR/$pkg/.files" ] && [ "$(grep ^usr/lib/gdk-pixbuf-2.0/2.10.0/loaders/.*.so $PKGDB_DIR/$pkg/.files)" ]; then + trig_10=1 + break + fi + done + fi + + # font caches + if [ "$trig_11" != "1" ]; then + for pkg in $@; do + if [ -s "$PKGDB_DIR/$pkg/.files" ] && [ "$(grep ^usr/share/fonts/$ $PKGDB_DIR/$pkg/.files)" ]; then + trig_11=1 + break + fi + done + fi + + # makedirs + if [ "$trig_12" != "1" ]; then + for pkg in $@; do + if [ -s "$PKGDB_DIR/$pkg/.pkgmkdirs" ]; then + trig_12=1 + break + fi + done + fi +} + +scratch_build() { + while [ "$1" ]; do + case $1 in + -i|-u|-r|-g|-p) ;; + --log) LOG=1;; + -*) OPTS="$OPTS $1";; + *) PKGNAME="$PKGNAME $1";; + esac + shift + done + [ "$PKGNAME" ] || { + echo "Please specify package(s) to build." + return 1 + } + for pkg in $PKGNAME; do + ppath=$(getportpath $pkg) || { + echo "Package '$pkg' not found." + return 1 + } + cd $ppath + settermtitle "Building $pkg..." + if [ "$LOG" ]; then + pkgbuild $OPTS | tee /var/log/pkgbuild.log || { + settermtitle "Building $pkg failed." + return 1 + } + else + pkgbuild $OPTS || { + settermtitle "Building $pkg failed." + return 1 + } + fi + settermtitle "Building $pkg done." + cd - >/dev/null + done +} + +scratch_install() { + needroot "Installing package" + while [ "$1" ]; do + case $1 in + -i|-u) ;; + -r|--reinstall) REINSTALL=1;; + -y|--yes) NOCONFIRM=1;; + -n|--no-dep) NO_DEP=1;; + --exclude=*) EXOPT=$1;; + -*) OPTS="$OPTS $1";; + *) PKGNAME="$PKGNAME $1";; + esac + shift + done + [ "$PKGNAME" ] || { + echo "Please specify package(s) to install." + return 1 + } + # if reinstall, dont calculate dep, just reinstall it then exit + if [ "$REINSTALL" = 1 ]; then + error=0 + for ii in $PKGNAME; do + if [ ! $(getportpath $ii) ]; then + echo "Package '$ii' not found." + elif ! isinstalled $ii; then + echo "Package '$ii' not installed." + else + cd $(getportpath $ii) + settermtitle "Reinstalling $ii..." + pkgbuild $OPTS -r || { + error=1 + break + } + done_pkg="$done_pkg $ii" + cd - >/dev/null + fi + done + settermtitle "Triggering install hook..." + [ "$done_pkg" ] && scratch_trigger $done_pkg + settermtitle "Reinstalling done." + return "$error" + fi + if [ "$NO_DEP" = 1 ]; then + error=0 + for ii in $PKGNAME; do + if [ ! $(getportpath $ii) ]; then + echo "Package '$ii' not found." + elif isinstalled $ii; then + echo "Package '$ii' already installed." + continue + else + cd $(getportpath $ii) + settermtitle "Installing $ii..." + pkgbuild -i $OPTS || { + error=1 + break + } + done_pkg="$done_pkg $ii" + cd - >/dev/null + fi + done + settermtitle "Triggering install hook..." + [ "$done_pkg" ] && scratch_trigger $done_pkg + settermtitle "Installing done." + return "$error" + fi + for i in $PKGNAME; do + if [ ! $(getportpath $i) ]; then + echo "Package '$i' not found." + elif isinstalled $i; then + echo "Package '$i' already installed." + else + IPKG="$IPKG $i" + fi + done + [ "$IPKG" ] || return 0 + echo "Resolving dependencies..." + INST="$(scratch_deplist -q $IPKG $EXOPT)" + if [ "$INST" ]; then + echo + pkgcount=0 + for pkg in $INST; do + pkgcount=$(( pkgcount + 1 )) + printf "[${GREEN}i${CRESET}] $pkg " + done + echo; echo + echo "( $pkgcount install )" + echo + if [ ! "$NOCONFIRM" ]; then + confirm "Continue install package(s)?" "Package installation cancelled." || exit $? + echo + fi + error=0 + count=0 + total=$(echo $INST | wc -w) + for int in $INST; do + count=$(( count + 1 )) + if portpathh=$(getportpath $int); then + cd $portpathh + settermtitle "[ $count/$total ] installing $int..." + pkgbuild -i $OPTS || { + error=1 + count=$(( count - 1 )) + break + } + done_pkg="$done_pkg $int" + cd - >/dev/null + else + msgwarn "Skipping missing package: $int" + fi + unset portpathh + done + settermtitle "Triggering install hook..." + [ "$done_pkg" ] && scratch_trigger $done_pkg + settermtitle "$count/$total package(s) installed." + return "$error" + fi +} + +scratch_remove() { + needroot "Removing package" + while [ "$1" ]; do + case $1 in + -y|--yes) NOCONFIRM=1;; + -*) OPTS="$OPTS $1";; + *) PKGNAME="$PKGNAME $1";; + esac + shift + done + [ "$PKGNAME" ] || { + echo "Please specify package(s) to remove." + return 1 + } + for i in $PKGNAME; do + if ! isinstalled $i; then + echo "Package '$i' not installed." + else + IPKG="$IPKG $i" + fi + done + [ "$IPKG" ] || return 0 + echo "Removing packages..." + echo + pkgcount=0 + count=0 + for pkg in $IPKG; do + pkgcount=$(( pkgcount + 1 )) + printf "[${RED}x${CRESET}] $pkg " + done + echo; echo + echo "( $pkgcount remove )" + echo + [ "$NOCONFIRM" ] || { + confirm "Continue remove package(s)?" "Package removing cancelled." || exit $? + echo + } + for pkg in $IPKG; do + count=$(( count + 1 )) + pre_triggers $pkg + settermtitle "[ $count/$pkgcount ] Removing $pkg..." + pkgdel $pkg $OPTS || { + error=1 + break + } + done + settermtitle "Triggering remove hook..." + post_triggers + settermtitle "$pkgcount package(s) removed." +} + +outdatepkg() { + for pkg in $(allinstalled); do + if [ -f "$MASK_FILE" ] && [ $(grep -Ev '^(#|$| )' $MASK_FILE | grep -w $pkg) ]; then + continue + fi + [ -e "$PKGDB_DIR/$pkg/.lock" ] && continue + getportpath $pkg >/dev/null || continue + . $(getportpath $pkg)/$BUILD_SCRIPT + if [ -z "$name" ] || [ -z "$version" ]; then + continue + fi + iversion=$(installed_pkg_info version $pkg) + irelease=$(installed_pkg_info release $pkg) + if [ "$release" != "$irelease" ] || [ "$version" != "$iversion" ]; then + echo $name + fi + unset iversion irelease version release + done +} + +scratch_sysup() { + needroot "Upgrading package" + while [ "$1" ]; do + case $1 in + -i|-u|-r) ;; + -y|--yes) NOCONFIRM=1;; + -n|--no-dep) NODEP=1;; + --exclude=*) EXOPT=$1;; + -*) OPTS="$OPTS $1";; + esac + shift + done + echo "Checking for outdated packages..." + PKGOUTDATE=$(outdatepkg) + [ "$PKGOUTDATE" ] || { + echo "All packages are up to date." + return 0 + } + [ "$(echo $PKGOUTDATE | tr ' ' '\n' | grep -x scratchpkg)" ] && { + echo + msgerr "Please upgrade 'scratchpkg' first." + return 1 + } + UPGPKG=0 + NEWPKG=0 + if [ "$NODEP" != 1 ]; then + echo "Resolving dependencies..." + DEP=$(scratch_deplist $PKGOUTDATE $EXOPT | awk '{print $2}') + echo + for d in $DEP; do + if [ "$(echo $PKGOUTDATE | tr ' ' '\n' | grep -x $d)" = "$d" ]; then + printf "[${GREEN}u${CRESET}] $d " + WILLINSTALL="$WILLINSTALL $d" + UPGPKG=$(( UPGPKG + 1 )) + elif ! isinstalled $d && [ "$(getportpath "$d")" ]; then + printf "[${CYAN}n${CRESET}] $d " + WILLINSTALL="$WILLINSTALL $d" + NEWPKG=$(( NEWPKG + 1 )) + fi + done + else + echo + for dd in $PKGOUTDATE; do + printf "[${GREEN}u${CRESET}] $dd " + WILLINSTALL="$WILLINSTALL $dd" + UPGPKG=$(( UPGPKG + 1 )) + done + fi + echo; echo + echo "( $UPGPKG upgrade, $NEWPKG new install )" + echo + [ "$NOCONFIRM" ] || { + confirm "Continue upgrade/install these package(s)?" "Package upgrade cancelled." || exit $? + echo + } + error=0 + count=0 + total=$(echo $WILLINSTALL | wc -w) + for inst in $WILLINSTALL; do # install all required dependencies and target packages itself + count=$(( count + 1 )) + cd $(getportpath $inst) + if ! isinstalled $inst; then + settermtitle "[ $count/$total ] Installing $inst..." + pkgbuild -i $OPTS || { + error=1 + count=$(( count - 1 )) + break + } + else + settermtitle "[ $count/$total ] Upgrading $inst..." + pkgbuild -u $OPTS || { + error=1 + count=$(( count - 1 )) + break + } + fi + cd - >/dev/null + done_pkg="$done_pkg $inst" + done + settermtitle "Triggering install hook." + [ "$done_pkg" ] && scratch_trigger $done_pkg + settermtitle "$count/$total package(s) upgraded." + return "$error" +} + +scratch_upgrade() { + needroot "Upgrading package" + while [ "$1" ]; do + case $1 in + -i|-r) ;; + -y|--yes) NOCONFIRM=1;; + -d|--no-dep) NO_DEP=1;; + --exclude=*) EXOPT=$1;; + -*) OPTS="$OPTS $1";; + *) PKGNAME="$PKGNAME $1";; + esac + shift + done + [ "$PKGNAME" ] || { + echo "Please specify package(s) to upgrade." + return 1 + } + for pkg in $PKGNAME; do + if ! isinstalled $pkg; then + echo "Package '$pkg' not installed." + continue + elif [ ! $(getportpath $pkg) ]; then + echo "Package '$pkg' not exist." + continue + else + . $(getportpath $pkg)/$BUILD_SCRIPT + if [ "$(installed_pkg_info version $pkg)-$(installed_pkg_info release $pkg)" = "$version-$release" ]; then + echo "Package '$pkg' is up to date." + continue + fi + fi + upkg="$upkg $pkg" + done + [ "$upkg" ] || return 0 + + UPGPKG=0 + NEWPKG=0 + if [ "$NODEP" != 1 ]; then + echo "Resolving dependencies..." + DEP=$(scratch_deplist $upkg $EXOPT | awk '{print $2}') + echo + for d in $DEP; do + if [ "$(echo $upkg | tr ' ' '\n' | grep -x $d)" = "$d" ]; then + printf "[${GREEN}u${CRESET}] $d " + WILLINSTALL="$WILLINSTALL $d" + UPGPKG=$(( UPGPKG + 1 )) + elif ! isinstalled $d && [ "$(getportpath "$d")" ]; then + printf "[${CYAN}n${CRESET}] $d " + WILLINSTALL="$WILLINSTALL $d" + NEWPKG=$(( NEWPKG + 1 )) + fi + done + else + echo + for dd in $upkg; do + printf "[${GREEN}u${CRESET}] $dd " + WILLINSTALL="$WILLINSTALL $dd" + UPGPKG=$(( UPGPKG + 1 )) + done + fi + echo; echo + echo "( $UPGPKG upgrade, $NEWPKG new install )" + echo + [ "$NOCONFIRM" ] || { + confirm "Continue upgrade/install these package(s)?" "Package upgrade cancelled." || exit $? + echo + } + error=0 + count=0 + total=$(echo $WILLINSTALL | wc -w) + for inst in $WILLINSTALL; do # install all required dependencies and target packages itself + count=$(( count + 1 )) + cd $(getportpath $inst) + if ! isinstalled $inst; then + settermtitle "[ $count/$total ] Installing $inst..." + pkgbuild -i $OPTS || { + error=1 + count=$(( count - 1 )) + break + } + else + settermtitle "[ $count/$total ] Upgrading $inst..." + pkgbuild -u $OPTS || { + error=1 + count=$(( count - 1 )) + break + } + fi + cd - >/dev/null + done_pkg="$done_pkg $inst" + done + settermtitle "Triggering install hook." + [ "$done_pkg" ] && scratch_trigger $done_pkg + settermtitle "$count/$total package(s) upgraded." + return "$error" +} + +scratch_outdate() { + for pkg in $(allinstalled); do + if [ "$(getportpath $pkg)" ]; then + . $(getportpath $pkg)/$BUILD_SCRIPT + if [ -z "$name" ] || [ -z "$version" ]; then + continue + fi + iversion=$(installed_pkg_info version $pkg) + irelease=$(installed_pkg_info release $pkg) + [ -f "$PKGDB_DIR/$pkg/.lock" ] && ITSLOCK="[masked]" + if [ -f "$MASK_FILE" ] && [ $(grep -Ev '^(#|$| )' $MASK_FILE | grep $pkg) ]; then + ITSLOCK="[masked]" + fi + #outdatemsg="$name $iversion-$irelease => $version-$release $ITSLOCK" + #newerinstmsg="$name $iversion-$irelease => $version-$release [newer installed] $ITSLOCK" + outdatemsg="$name ${RED}$iversion-$irelease${CRESET} => ${GREEN}$version-$release${CRESET} ${CYAN}$ITSLOCK${CRESET}" + newerinstmsg="$name ${RED}$iversion-$irelease${CRESET} => ${GREEN}$version-$release${CRESET} ${YELLOW}[newer installed]${CRESET} ${CYAN}$ITSLOCK${CRESET}" + if [ "$version" != "$iversion" ]; then + vercomp $version $iversion + if [ $? = 2 ]; then + echo -e "$outdatemsg" + OUTDATE=yes + elif [ $? = 1 ]; then + echo -e "$newerinstmsg" + OUTDATE=yes + fi + elif [ "$release" != "$irelease" ]; then + vercomp $release $irelease + if [ $? = 2 ]; then + echo -e "$outdatemsg" + OUTDATE=yes + elif [ $? = 1 ]; then + echo -e "$newerinstmsg" + OUTDATE=yes + fi + fi + unset ITSLOCK name version + fi + done + + [ ! "$OUTDATE" ] && msg "All packages are up to date." +} + +scratch_search() { + needarg $@ + arg=$* + for repo in $PORT_REPO; do + [ -d $repo ] || continue + out=$(grep -R "# description" $repo/*/$BUILD_SCRIPT | grep "$arg" | awk -F : '{print $1}' | sort) + [ "$out" ] || continue + found=1 + for line in $out; do + repo=$(echo $line | rev | awk -F / '{print $3}' | rev) + desc=$(grep "^# description[[:blank:]]*:" $line | sed 's/^# description[[:blank:]]*:[[:blank:]]*//') + . $line + if isinstalled $name; then + ins="[${GREEN}*${CRESET}]" + else + ins="[ ]" + fi + printf "$ins ${PURPLE}($repo)${CRESET} $name ${CYAN}$version-$release${CRESET}: $desc\n" + unset repo desc name version release build + done + unset out + done + if [ ! "$found" ]; then + msg "No matching package found." + fi +} +scratch_changelog() { + needarg $@ + echo $PORT_REPO $! + if PPATH=$($PORT_REPO "$1"); then + if [ -f "$PPATH/CHANGELOG" ]; then + cat "$PPATH/readme" + else + msgerr "Port '$1' does not have readme." + fi + else + msgerr "Port '$1' not exist." + exit 1 + fi +} + + +scratch_cache() { + needroot "Clear old caches" + + allcachepkg=/tmp/.allcachepkg.$$ + allcachesrc=/tmp/.allcachesrc.$$ + keepcachepkg=/tmp/.keepcachepkg.$$ + keepcachesrc=/tmp/.keepcachesrc.$$ + diffcachepkg=/tmp/.diffcachepkg.$$ + diffcachesrc=/tmp/.diffcachesrc.$$ + + [ -f /etc/scratchpkg.conf ] && . /etc/scratchpkg.conf + + touch \ + $allcachepkg \ + $allcachesrc \ + $keepcachepkg \ + $keepcachesrc \ + $diffcachepkg \ + $diffcachesrc + + if [ "$(find $PACKAGE_DIR -mindepth 1 -print -quit 2>/dev/null)" ]; then + for list in "$PACKAGE_DIR"/*; do + basename $list >> "$allcachepkg" + done + fi + + if [ "$(find $SOURCE_DIR -mindepth 1 -print -quit 2>/dev/null)" ]; then + for list in "$SOURCE_DIR"/*; do + basename $list >> "$allcachesrc" + done + fi + + for repo in $PORT_REPO; do + if [ "$(find $repo/*/ -mindepth 1 -print -quit 2>/dev/null)" ]; then # check directory if its not empty + for port in $repo/*/$BUILD_SCRIPT; do + . $port + echo "$name-$version-$release.spkg.tar.$COMPRESSION_MODE" >> "$keepcachepkg" + if [ "$source" ]; then + for src in $source; do + if echo $src | grep -Eq "(ftp|http|https)://"; then + if echo $src | grep -Eq "::(ftp|http|https)://"; then + sourcename="$(echo $src | awk -F '::' '{print $1}')" + else + sourcename="$(echo $src | rev | cut -d / -f 1 | rev)" + fi + echo $sourcename >> "$keepcachesrc" + fi + done + fi + done + fi + done + grep -Fxv -f "$keepcachepkg" "$allcachepkg" > "$diffcachepkg" + grep -Fxv -f "$keepcachesrc" "$allcachesrc" > "$diffcachesrc" + + cat $diffcachepkg + cat $diffcachesrc + + if [ -s "$diffcachepkg" ]; then + cd "$PACKAGE_DIR" + sizepkg=$(du -ch $(cat $diffcachepkg) | grep total | awk '{print $1}') + cd - >/dev/null + else + sizepkg=0M + fi + + if [ -s "$diffcachesrc" ]; then + cd "$SOURCE_DIR" + sizesrc=$(du -ch $(cat $diffcachesrc) | grep total | awk '{print $1}') + cd - >/dev/null + else + sizesrc=0M + fi + + echo "Total package cache size: $sizepkg" + echo "Total source cache size : $sizesrc" + + if [ -s "$diffcachepkg" ] || [ -s "$diffcachesrc" ]; then + echo + confirm "Clear old caches?" "Old caches is kept." && { + for i in $(cat $diffcachepkg); do + [ -e "$PACKAGE_DIR/$i" ] && rm -v "$PACKAGE_DIR/$i" + done + for i in $(cat $diffcachesrc); do + [ -e "$SOURCE_DIR/$i" ] && rm -v "$SOURCE_DIR/$i" + done + } + fi + + rm -f \ + "$allcachepkg" \ + "$allcachesrc" \ + "$keepcachepkg" \ + "$keepcachesrc" \ + "$diffcachepkg" \ + "$diffcachesrc" +} + +scratch_deplist() { + OLDIFS=$IFS + IFS=, + while [ "$1" ]; do + case $1 in + -q|--quick) quick=1;; + --exclude=*) for i in ${1#*=}; do exclude="$exclude $i"; done;; + -*) ;; + *) PKG="$PKG $1";; + esac + shift + done + IFS=$OLDIFS + [ "$PKG" ] || { + echo "Please specify package(s) to list dependencies." + return 1 + } + for p in $PKG; do + if [ "$(getportpath $p)" ]; then + PPKG="$PPKG $p" + else + [ "$quick" = 1 ] || msgerr "Package '$p' not exist." + fi + done + + for p in $PPKG; do + deplist $p + done + + [ "$DEP" ] || return 0 + + if [ "$quick" = 1 ]; then + echo $DEP | tr ' ' '\n' + else + for p in $DEP; do + if isinstalled $p; then + echo "[*] $p" + else + echo "[-] $p" + fi + done + if [ "$MISSINGDEP" ]; then + for m in $MISSINGDEP; do + echo "Missing deps: $m" | sed 's/(/ (/' + done + fi + fi +} + +deplist() { + # skip excluded dependencies + if echo $exclude | tr " " "\n" | grep -qx $1; then + return 0 + fi + + # check currently process for circular dependencies + # for circular dependencies, found first will take precedence + [ "$CHECK" ] && { + if echo $CHECK | tr " " "\n" | grep -qx $1; then + return 0 + fi + } + + # add package to currently process + CHECK="$CHECK $1" + + # check dependencies + for i in $(get_depends $1); do + if [ "$quick" = 1 ] && isinstalled $i; then + continue + else + if ! echo $DEP | tr " " "\n" | grep -qx $i; then + if ! getportpath $i >/dev/null; then + MISSINGDEP="$MISSINGDEP $i($1)" + else + deplist $i + fi + fi + fi + done + + # add dependency to list checked dep + if ! echo $DEP | tr " " "\n" | grep -qx $1; then + if [ "$quick" = 1 ]; then + isinstalled $1 || DEP="$DEP $1" + else + DEP="$DEP $1" + fi + fi + + # delete item from loop process + CHECK=$(echo $CHECK | sed "s/$1//") +} + +scratch_cat() { + needarg $@ + if PPATH=$(getportpath "$1"); then + cat "$PPATH/$BUILD_SCRIPT" + else + msgerr "Port '$1' not exist." + return 1 + fi +} + +scratch_dependent() { + needarg $@ + if [ "$(getportpath $1)" ]; then + grep -R "# depends[[:blank:]]*:" $PORT_REPO \ + | sed "s,:# depends[[:blank:]]*:[[:blank:]]*,#|,;s, ,|,g;s,$,|,g" \ + | grep "|$1|" \ + | awk -F "#" '{print $1}' \ + | rev \ + | awk -F / '{print $2}' \ + | rev + else + msgerr "Port '$1' not exist." + return 1 + fi +} + +scratch_depends() { + needarg $@ + if getportpath "$1" >/dev/null; then + depends=$(get_depends $1) + else + msgerr "Port '$1' not exist." + return 1 + fi + + for dep in $depends; do + if isinstalled $dep; then + msginst "$dep" + elif getportpath $dep >/dev/null; then + msgnoinst "$dep" + else + msgmiss "$dep" + fi + done +} + +scratch_dup() { + dup=$(find $PORT_REPO -type d -print | grep -Exv "($(echo $PORT_REPO | tr ' ' '|'))" | \ + rev | cut -d '/' -f1 | rev | sort | uniq -d) + + if [ "$dup" ]; then + for dp in $dup; do + for repo in $PORT_REPO; do + [ -d $repo/$dp ] && echo "$repo/$dp" + done + done + else + msg "No duplicate ports found." + fi +} + +scratch_foreign() { + for pkg in $(allinstalled); do + if ! getportpath $pkg >/dev/null; then + iname=$(installed_pkg_info name $pkg) + iversion=$(installed_pkg_info version $pkg) + irelease=$(installed_pkg_info release $pkg) + echo "$iname $iversion-$irelease" + fi + unset iname iversion irelease + done +} + +scratch_info() { + needarg $@ + ppath=$(getportpath $1) || return 1 + + . $ppath/$BUILD_SCRIPT + desc=$(grep "^# description[[:blank:]]*:" $ppath/$BUILD_SCRIPT | sed 's/^# description[[:blank:]]*:[[:blank:]]*//') + maint=$(grep "^# maintainer[[:blank:]]*:" $ppath/$BUILD_SCRIPT | sed 's/^# maintainer[[:blank:]]*:[[:blank:]]*//') + deps=$(get_depends $1 | tr '\n' ' ') + + echo "Name: $1" + echo "Path: $ppath" + echo "Version: $version" + echo "Release: $release" + echo "Description: $desc" + echo "Maintainer: $maint" + echo "Dependencies: $deps" +} + +scratch_installed() { + for all in $(allinstalled); do + printf "%s" "$all " + grep -e ^version -e ^release $PKGDB_DIR/$all/.pkginfo | awk '{print $3}' | tr '\n' '-' | sed 's:\-$::' + echo + done +} + +scratch_missingdep() { + for pkg in $(allinstalled); do + if getportpath "$pkg" >/dev/null; then + depends=$(get_depends $pkg) + fi + if [ "$depends" ]; then + for d in $depends; do + if ! isinstalled $d; then + if [ -z "$msd" ]; then + msd="$d" + else + msd="$msd $d" + fi + fi + done + fi + [ "$msd" ] && echo "$pkg: $msd" + unset depends msd + done +} + +scratch_locked() { + for pkg in $(allinstalled); do + [ -f "$PKGDB_DIR/$pkg/.lock" ] && echo "$pkg" + done +} + +scratch_orphan() { + tmpallpkg="/tmp/.pkgquery_allpkg.$$" + tmpalldep="/tmp/.pkgquery_alldep.$$" + for pkg in $(allinstalled); do + echo $pkg >> $tmpallpkg + dep="$dep $(get_depends $pkg)" + done + echo $dep | tr ' ' '\n' | sort | uniq > "$tmpalldep" + grep -xvF -f "$tmpalldep" "$tmpallpkg" + rm "$tmpalldep" "$tmpallpkg" +} + +scratch_path() { + needarg $@ + if PPATH=$(getportpath "$1"); then + echo "$PPATH" + else + msgerr "Port '$1' not exist." + return 1 + fi +} + +scratch_provide() { + needarg $@ + arg=$(echo $1 | sed "s/^\///") + grep -R "$arg" $PKGDB_DIR/*/.files \ + | sed "s:$PKGDB_DIR/::" \ + | sed "s:/.files::" \ + | tr : " " \ + | column -t +} + +scratch_readme() { + needarg $@ + if PPATH=$(getportpath "$1"); then + if [ -f "$PPATH/readme" ]; then + cat "$PPATH/readme" + else + msgerr "Port '$1' does not have readme." + fi + else + msgerr "Port '$1' not exist." + exit 1 + fi +} + +scratch_files() { + needarg $@ + if isinstalled $1; then + cat "$PKGDB_DIR/$1/.files" + else + msg "Package '$1' not installed." + fi +} + +scratch_help() { + cat << EOF +Usage: + $(basename $0) [] + +Options: + install install ports (use pkgbuild arg, except '-i' & '-u') + -r|--reinstall reinstall + -n|--no-dep skip dependencies + -y|--yes skip ask user permission + --exclude=* exclude dependencies, comma separated + + upgrade upgrade ports (use pkgbuild arg, except '-i' & '-r') + -n|--no-dep skip dependencies + -y|--yes skip ask user permission + --exclude=* exclude dependencies, comma separated + + remove remove installed ports (use pkgdel arg) + -y|--yes skip ask user permission + + sysup full system upgrade (use pkgbuild arg, except '-i', '-r' & '-u') + -n|--no-dep skip dependencies + -y|--yes skip ask user permission + --exclude=* exclude dependencies, comma separated + + deplist print all dependencies for ports + -q|--quick skip installed ports + --exclude=* exclude dependencies, comma separated + + build build ports (use pkgbuild arg, except '-i', '-u', '-r', '-g', & '-p') + --log log build process (/var/log/pkgbuild.log) + + lock locking ports prevent upgrade + unlock unlock locked ports + trigger [ports] run system trigger + search find ports in repo + cat print spkgbuild + depends print dependencies + dependent print dependent + path print path in repo + provide print port's provided files + readme print readme file, if exist + files print files installed + info print information + locate print location of files in ports repo + sync update ports database + outdate print outdated ports + cache print and clear old pkg and src caches + integrity check installed port integrity + dup print duplicate ports in repo + installed print all installed ports + locked print loacked ports + missingdep print missing dependencies + orphan print orphan installed ports + foreign print foreign ports + help print this help msg + +Global options: + --append-repo= append custom repo path + --prepend-repo= prepend custom repo path + --repo-file= use custom repo file (default: $REPO_FILE) + --nocolor disable colour for output + +EOF +} + +print_runhelp_msg() { + echo "Run '$(basename $0) help' to see available options." + exit 2 +} + +# check for 'pkgadd', required for package database path +command -v pkgadd >/dev/null 2>&1 || { + echo "'pkgadd' not found in \$PATH!" + exit 1 +} + +mode=$1 + +[ "$mode" ] || { + print_runhelp_msg +} + +shift + +for opt in $@; do + case $opt in + --nocolor) nocolor;; + --repo=*) PORT_REPO="$PORT_REPO ${opt#*=}";; + --repo-file=*) REPO_FILE="${opt#*=}";; + --alias-file=*) ALIAS_FILE="${opt#*=}";; + --*) MAINOPTS="$MAINOPTS $opt";; + -*) char=${#opt}; count=1 + while [ "$count" != "$char" ]; do + count=$((count+1)) + MAINOPTS="$MAINOPTS -$(printf '%s' $opt | cut -c $count)" + done;; + *) MAINOPTS="$MAINOPTS $opt";; + esac + shift +done + +BUILD_SCRIPT="spkgbuild" +PKGDB_DIR="$(pkgadd --print-dbdir)" +REPO_FILE="${REPO_FILE:-/etc/scratchpkg.repo}" +ALIAS_FILE="${ALIAS_FILE:-/etc/scratchpkg.alias}" +MASK_FILE="${MASK_FILE:-/etc/scratchpkg.mask}" + +# default value from pkgbuild +SOURCE_DIR="/var/cache/scratchpkg/sources" +PACKAGE_DIR="/var/cache/scratchpkg/packages" +COMPRESSION_MODE="xz" + +if [ -f "$REPO_FILE" ]; then + for repodir in $(grep -Ev '^(#|$)' "$REPO_FILE" | awk '{print $1}'); do + PORT_REPO="$PORT_REPO $repodir" + done +fi + +if [ "$(command -v scratch_$mode)" ]; then + scratch_$mode $MAINOPTS +else + print_runhelp_msg +fi + +exit $? diff --git a/scratchpkg.mask b/scratchpkg.mask index 8a7e346..cd14888 100644 --- a/scratchpkg.mask +++ b/scratchpkg.mask @@ -1,3 +1,4 @@ # # /etc/scratchpkg.mask : exclude packages from sysup # + diff --git a/scratchpkg.repo b/scratchpkg.repo index 4be77ea..6236b04 100644 --- a/scratchpkg.repo +++ b/scratchpkg.repo @@ -4,7 +4,42 @@ # format: # # -# example: -# /usr/ports/core https://raw.githubusercontent.com/emmett1/ports/master/core -# /usr/ports/localports -# \ No newline at end of file + +#Core +/usr/Voncloft-OS/core https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/core +/usr/Voncloft-OS/hardware https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/hardware +#/usr/Voncloft-OS/multilib https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/multilib + +#DE +/usr/Voncloft-OS/cinnamon https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/cinnamon +/usr/Voncloft-OS/displaym https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/displaym +/usr/Voncloft-OS/kde https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/kde +/usr/Voncloft-OS/kf5 https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/kf5 +/usr/Voncloft-OS/lxde https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/lxde +/usr/Voncloft-OS/mate https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/mate +/usr/Voncloft-OS/plasma https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/plasma +/usr/Voncloft-OS/qt https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/qt +/usr/Voncloft-OS/xfce https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/xfce +/usr/Voncloft-OS/xorg https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/xorg + + +#Programming +/usr/Voncloft-OS/compilers https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/compilers +/usr/Voncloft-OS/libs https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/libs +/usr/Voncloft-OS/perl https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/perl +/usr/Voncloft-OS/python https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/python +/usr/Voncloft-OS/ruby-gems https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/ruby-gems + +#Router +/usr/Voncloft-OS/boot-scripts-server https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/boot-scripts-server +/usr/Voncloft-OS/firewall https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/firewall +/usr/Voncloft-OS/networking https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/networking +/usr/Voncloft-OS/server https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/server + +#Programs +/usr/Voncloft-OS/extra https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/extra +/usr/Voncloft-OS/fonts https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/fonts +/usr/Voncloft-OS/kde-apps https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/kde-apps +/usr/Voncloft-OS/media https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/media +/usr/Voncloft-OS/nonfree https://raw.githubusercontent.com/voncloft/Voncloft-OS/master/nonfree +