#!/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} $1\n" } msgerr() { printf "${RED}==> ERROR:${CRESET} $1\n" } msginst() { printf "[${GREEN}i${CRESET}] $1\n" } msgmiss() { printf "[${YELLOW}m${CRESET}] $1\n" } msgnoinst() { printf "[-] $1\n" } msgwarn() { printf "${YELLOW}==> WARNING:${CRESET} $1\n" } 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 return 1 # $1 lower than $2 else return 2 # $1 higher than $2 fi } installed_pkg_info() { if isinstalled $2; then grep ^$1 $INDEX_DIR/$2/.pkginfo | cut -d " " -f3- fi } allinstalled() { grep ^name "$INDEX_DIR"/*/.pkginfo | awk '{print $3}' } deps_alias() { [ -f $ALIAS_FILE ] || { echo $@ return } while [ "$1" ]; do getalias=$(grep -w ^$1 $ALIAS_FILE | awk '{print $2}') echo ${getalias:-$1} shift done unset getalias } 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 "$INDEX_DIR/$1/.pkginfo" ] && [ "$(grep $1 $INDEX_DIR/$1/.pkginfo)" ]; then return 0 else return 1 fi } settermtitle() { printf "\033]0;$*\a" } scratch_integrity() { if [ "$1" ]; then cd / if [ -f $INDEX_DIR/$1/.files ]; then cat $INDEX_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 $INDEX_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 $INDEX_DIR/$pkg/.lock ]; then msgerr "Package '$pkg' already locked." else touch $INDEX_DIR/$pkg/.lock && msg "Successfully locked package '$pkg'." fi done } scratch_unlock() { needroot "Unlocking package" for pkg in "$@"; do if ! isinstalled $pkg; then msgerr "Package '$pkg' is not installed." elif [ ! -f $INDEX_DIR/$pkg/.lock ]; then msgerr "Package '$pkg' is not locked." else rm -f $INDEX_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 $INDEX_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 -a ! -name X11 \)) /usr/share/fonts/X11/*; 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 "$INDEX_DIR/$pkg/.files" ] && [ "$(grep ^usr/share/mime/$ $INDEX_DIR/$pkg/.files)" ]; then trig_1=1 break fi done fi # desktop db if [ "$trig_2" != "1" ]; then for pkg in $@; do if [ -s "$INDEX_DIR/$pkg/.files" ] && [ "$(grep ^usr/share/applications/$ $INDEX_DIR/$pkg/.files)" ]; then trig_2=1 break fi done fi # mkfontdir if [ "$trig_3" != "1" ]; then for pkg in $@; do if [ -s "$INDEX_DIR/$pkg/.files" ] && [ "$(grep ^usr/share/fonts/$ $INDEX_DIR/$pkg/.files)" ]; then trig_3=1 break fi done fi # hwdb if [ "$trig_4" != "1" ]; then for pkg in $@; do if [ -s "$INDEX_DIR/$pkg/.files" ] && [ "$(grep ^etc/udev/hwdb.d/$ $INDEX_DIR/$pkg/.files)" ]; then trig_4=1 break fi done fi # icon caches if [ "$trig_5" != "1" ]; then for pkg in $@; do if [ -s "$INDEX_DIR/$pkg/.files" ] && [ "$(grep ^usr/share/icons/$ $INDEX_DIR/$pkg/.files)" ]; then trig_5=1 break fi done fi # gtk3 immodules if [ "$trig_6" != "1" ]; then for pkg in $@; do if [ -s "$INDEX_DIR/$pkg/.files" ] && [ "$(grep ^usr/lib/gtk-3.0/3.0.0/immodules/.*.so $INDEX_DIR/$pkg/.files)" ]; then trig_6=1 break fi done fi # gtk2 immodules if [ "$trig_7" != "1" ]; then for pkg in $@; do if [ -s "$INDEX_DIR/$pkg/.files" ] && [ "$(grep ^usr/lib/gtk-2.0/2.10.0/immodules/.*.so $INDEX_DIR/$pkg/.files)" ]; then trig_7=1 break fi done fi # gsettings schema if [ "$trig_8" != "1" ]; then for pkg in $@; do if [ -s "$INDEX_DIR/$pkg/.files" ] && [ "$(grep ^usr/share/glib-2.0/schemas/$ $INDEX_DIR/$pkg/.files)" ]; then trig_8=1 break fi done fi # gio modules if [ "$trig_9" != "1" ]; then for pkg in $@; do if [ -s "$INDEX_DIR/$pkg/.files" ] && [ "$(grep ^usr/lib/gio/modules/.*.so $INDEX_DIR/$pkg/.files)" ]; then trig_9=1 break fi done fi # gdk-pixbuf if [ "$trig_10" != "1" ]; then for pkg in $@; do if [ -s "$INDEX_DIR/$pkg/.files" ] && [ "$(grep ^usr/lib/gdk-pixbuf-2.0/2.10.0/loaders/.*.so $INDEX_DIR/$pkg/.files)" ]; then trig_10=1 break fi done fi # font caches if [ "$trig_11" != "1" ]; then for pkg in $@; do if [ -s "$INDEX_DIR/$pkg/.files" ] && [ "$(grep ^usr/share/fonts/$ $INDEX_DIR/$pkg/.files)" ]; then trig_11=1 break fi done fi # makedirs if [ "$trig_12" != "1" ]; then for pkg in $@; do if [ -s "$INDEX_DIR/$pkg/.pkgmkdirs" ]; then trig_12=1 break fi done fi } scratch_build() { while [ "$1" ]; do case $1 in -i|-u|-r|-g|-p) ;; -*) 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..." pkgbuild $OPTS || { settermtitle "Building $pkg failed." return 1 } 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 [ ! -e "$INDEX_DIR/$pkg/.lock" ] && getportpath $pkg >/dev/null; 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) if [ "$release" != "$irelease" ] || [ "$version" != "$iversion" ]; then echo $name fi unset iversion irelease version release fi 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 msgwarn "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 "$INDEX_DIR/$pkg/.lock" ] && ITSLOCK="[locked]" outdatemsg="$name $iversion-$irelease => $version-$release $ITSLOCK" newerinstmsg="$name $iversion-$irelease => $version-$release [newer installed] $ITSLOCK" if [ "$version" != "$iversion" ]; then vercomp $version $iversion if [ $? = 2 ]; then echo "$outdatemsg" OUTDATE=yes elif [ $? = 1 ]; then echo "$newerinstmsg" OUTDATE=yes fi elif [ "$release" != "$irelease" ]; then vercomp $release $irelease if [ $? = 2 ]; then echo "$outdatemsg" OUTDATE=yes elif [ $? = 1 ]; then echo "$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 out=$(grep -R "# description" $repo | grep $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_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') lock locking ports prevent upgrade unlock unlock locked ports trigger [ports] run system trigger sync update ports database search find ports in repo outdate print outdated ports cache print and clear old pkg and src caches integrity check installed port integrity help print this help msg Global options: --repo= add custom repo path --nocolor disable colour for output EOF } print_runhelp_msg() { echo "Run '$(basename $0) help' to see available options." exit 2 } BUILD_SCRIPT="spkgbuild" INDEX_DIR="/var/lib/scratchpkg/index" REPO_FILE="/etc/scratchpkg.repo" ALIAS_FILE="/etc/scratchpkg.alias" # default value from pkgbuild SOURCE_DIR="/var/cache/scratchpkg/sources" PACKAGE_DIR="/var/cache/scratchpkg/packages" COMPRESSION_MODE="xz" mode=$1 [ "$mode" ] || { print_runhelp_msg } shift for opt in $@; do case $opt in --nocolor) nocolor;; --repo=*) PORT_REPO="$PORT_REPO ${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 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 $?