#!/bin/bash export LC_ALL=C . /usr/share/scratchpkg/functions || exit 1 spkglock() { if [ ! -f /tmp/spkg.lock ]; then touch /tmp/spkg.lock else rm /tmp/spkg.lock fi } installpkg() { #ignore dependency check if [ ! "$IGNORE_DEP" ]; then #msg2 "Checking package dependencies..." checkdeps fi msg "Installing ${GREEN}$name-$version-$release${CRESET}..." # noextract file into system for noextr in ${NO_EXTRACT[@]}; do excludefile+=(--exclude=$noextr) done #ignore conflict if [ ! "$IGNORE_CONFLICT" ]; then msg2 "Checking package/file conflict..." if [ "$UPGRADE_PKG" ] || [ "$REINSTALL_PKG" ]; then upcheckconflict else checkconflict fi checkpkgconflict fi # create lock file prevent simultaneous install package spkglock # backup conf as set in spkgbuld if upgrade or reinstall package if [ "$UPGRADE_PKG" ] || [ "$REINSTALL_PKG" ]; then if [ ! "$NO_BACKUP" ]; then backupconf fi fi # source .install file inside package if [ $(tar -tf "$PKGNAME" | grep -x ".pkginstall") ] && [ ! "$REINSTALL_PKG" ]; then source <(tar -xf "$PKGNAME" .pkginstall -O) fi # run preinstall script if no --no-preinstall flag and not upgrade package if [ ! "$NO_PREINSTALL" ] && [ ! "$UPGRADE_PKG" ]; then run_preinstall fi # run preupgrade script if package upgrade if [ "$UPGRADE_PKG" ] && [ ! "$NO_PREUPGRADE" ]; then run_preupgrade fi #installing package into system msg2 "Extracting package..." if [ "$VERBOSE_INSTALL" ]; then tar --keep-directory-symlink --no-overwrite-dir -p -x -v -f $PKGNAME -C $ROOT_DIR --exclude=.pkginfo --exclude=.pkginstall --exclude=.pkgreadme ${excludefile[@]} else tar --keep-directory-symlink --no-overwrite-dir -p -x -f $PKGNAME -C $ROOT_DIR --exclude=.pkginfo --exclude=.pkginstall --exclude=.pkgreadme ${excludefile[@]} fi if [ $? != 0 ]; then msgerr "Failed install ${RED}$name-$version-$release${CRESET}." while IFS=' ' read -r line; do pushd $ROOT_DIR rm_silent "$line" || rmdir_silent --ignore-fail-on-non-empty "$line" popd done < <(tar -tf "$PKGNAME" --exclude=.pkginfo --exclude=.pkginstall --exclude=.pkgreadme ${excludefile[@]} | tac) spkglock exit 1 fi if [ "$UPGRADE_PKG" ] || [ "$REINSTALL_PKG" ]; then removeoldfiles fi registerpkg if [ ! "$NO_POSTINSTALL" ] && [ ! "$UPGRADE_PKG" ]; then run_postinstall fi if [ "$UPGRADE_PKG" ] && [ ! "$NO_POSTUPGRADE" ]; then run_postupgrade fi restoreconf case $PREINSTALL_STATUS in OK) msg "preinstall : ${GREEN}OK${CRESET}" ;; KO) msg "preinstall : ${RED}FAIL${CRESET}" ;; esac case $PREUPGRADE_STATUS in OK) msg "preupgrade : ${GREEN}OK${CRESET}" ;; KO) msg "preupgrade : ${RED}FAIL${CRESET}" ;; esac case $POSTINSTALL_STATUS in OK) msg "postinstall : ${GREEN}OK${CRESET}" ;; KO) msg "postinstall : ${RED}FAIL${CRESET}" ;; esac case $POSTUPGRADE_STATUS in OK) msg "postupgrade : ${GREEN}OK${CRESET}" ;; KO) msg "postupgrade : ${RED}FAIL${CRESET}" ;; esac runhooks if [ -f $INDEX_DIR/$name/.pkgreadme ]; then msg "This package has ${GREEN}readme${CRESET}" fi # remove lock file spkglock } removeoldfiles() { TMP_TARLIST="/tmp/$name.tarlist.spkg" tar -tf "$PKGNAME" --exclude=.pkginfo --exclude=.pkginstall --exclude=.pkgreadme ${excludefile[@]} > $TMP_TARLIST msg2 "Removing old files & dirs..." grep -v '/$' $INDEX_DIR/$name/.files | while read line; do if [ ! "$(grep -Fx "$line" $TMP_TARLIST)" ]; then pushd $ROOT_DIR if [ "$VERBOSE_INSTALL" = "yes" ]; then rm_silent "$line" && echo "$line" && OLDFILEREMOVE=yes || msgwarn "Failed remove $line" else rm_silent "$line" && OLDFILEREMOVE=yes || msgwarn "Failed remove $line" fi popd fi done while IFS=' ' read -r line; do if [ ! "$(tac $TMP_TARLIST | grep -x "$line")" ] && [ ! "$(grep -Rx --exclude-dir="$name" -w "$line" "$INDEX_DIR")" ]; then pushd $ROOT_DIR if [ "$VERBOSE_INSTALL" = "yes" ]; then rmdir_silent "$line" && echo "$line" || msgwarn "Failed remove $line" else rmdir_silent "$line" || msgwarn "Failed remove $line" fi popd fi done < <(tac $INDEX_DIR/$name/.files | grep '/$') rm $TMP_TARLIST } registerpkg() { [ ! -d $INDEX_DIR/$name ] && mkdir $INDEX_DIR/$name tar -x -f $PKGNAME -C $INDEX_DIR/$name .pkginfo tar -t -f $PKGNAME --exclude=.pkginfo --exclude=.pkginstall --exclude=.pkgreadme ${excludefile[@]} > $INDEX_DIR/$name/.files tar -x -f $PKGNAME -C $INDEX_DIR/$name .pkginstall .pkgreadme >/dev/null 2>&1 msg "Successfully install ${GREEN}$name-$version-$release${CRESET}." } checkdeps() { for dep in ${depends[@]}; do if [ ! -d $INDEX_DIR/$dep ]; then if [ "$DEP_INSTALL" ]; then scratch -i -p $dep --no-orphan-check || exit 1 else MSGDEP+=($dep) fi fi done if [ "${#MSGDEP[@]}" -gt 0 ]; then msg "Missing dependencies:" for msdp in ${MSGDEP[@]}; do msg2 "$msdp" done exit 1 fi } checkpkgconflict() { for pkg in ${conflict[@]}; do if [ -d $INDEX_DIR/$pkg ]; then msg "Conflict package!: ${YELLOW}$pkg${CRESET}" PKG_CONFLICT=yes fi done if [ "$PKG_CONFLICT" ]; then exit 1 fi } checkconflict() { while IFS=' ' read -r line; do pushd $ROOT_DIR if [ -e "$line" ]; then fileconflict+=(${line}) fi popd done < <(tar -tf "$PKGNAME" --exclude=.pkginfo --exclude=.pkginstall --exclude=.pkgreadme ${excludefile[@]} | grep -v '/$') if [ "${#fileconflict[@]}" -gt 0 ]; then msgerr "File conflict found:" for fc in ${fileconflict[@]}; do msg2 "$fc" done exit 1 fi } upcheckconflict() { while IFS=' ' read -r line; do pushd $ROOT_DIR if [ -e "$line" ]; then if [ ! "$(grep -Fx "$line" "$INDEX_DIR/$name/.files")" ]; then fileconflict+=(${line}) fi fi popd done < <(tar -tf "$PKGNAME" --exclude=.pkginfo --exclude=.pkginstall --exclude=.pkgreadme ${excludefile[@]} | grep -v '/$') if [ "${#fileconflict[@]}" -gt 0 ]; then msgerr "File conflict found:" for fc in ${fileconflict[@]}; do msg2 "$fc" done exit 1 fi } backupconf() { pushd $ROOT_DIR for bkp in ${backup[@]}; do if [ -e $bkp ]; then msg2 "Backup ${PURPLE}$bkp${CRESET}" rm -f $bkp.spkgtmp cp $bkp $bkp.spkgtmp FILEBACKUP+=($bkp) fi done popd } restoreconf() { if [ "${#FILEBACKUP[@]}" -gt 0 ]; then pushd $ROOT_DIR for b in ${FILEBACKUP[@]}; do if [ -e $b ]; then mv $b $b.spkgnew mv $b.spkgtmp $b fi done popd fi } checkoutdate() { if [ "$version-$release" = "$iversion-$irelease" ]; then msg "Package ${GREEN}$name${CRESET} is up-to-date." exit 0 fi } run_preinstall() { if [ "`type -t pre_install`" = "function" ]; then msg "Running preinstall script..." pre_install "$version" && PREINSTALL_STATUS=OK || PREINSTALL_STATUS=KO fi } run_postinstall() { if [ "`type -t post_install`" = "function" ]; then msg "Running postinstall script..." post_install "$version" && POSTINSTALL_STATUS=OK || POSTINSTALL_STATUS=KO fi } run_preupgrade() { if [ "`type -t pre_upgrade`" = "function" ]; then msg "Running preupgrade script..." pre_upgrade "$version" "$iversion" && PREUPGRADE_STATUS=OK || PREUPGRADE_STATUS=KO fi } run_postupgrade() { if [ "`type -t post_upgrade`" = "function" ]; then msg "Running postupgrade script..." post_upgrade "$version" "$iversion" && POSTUPGRADE_STATUS=OK || POSTUPGRADE_STATUS=KO fi } checkneworphan() { for md in ${makedepends[@]}; do removemakedepends $md done if [ "${#saferemove[@]}" -gt 0 ]; then msg "Package safe for remove:" for saferem in ${saferemove[@]}; do msg2 "$saferem" done fi } runhooks() { if [ "$UPGRADE_PKG" ]; then opr=upgrade else opr=install fi if [ "$(ls $HOOK_DIR/*.hook 2>/dev/null)" ]; then for hook in $(ls $HOOK_DIR/*.hook); do description=$(cat "$hook" | grep ^"# description" | sed 's/\://' | cut -d ' ' -f 3-) operation=$(cat "$hook" | grep ^"# operation" | sed 's/\://' | cut -d ' ' -f 3-) target=$(cat "$hook" | grep ^"# target" | sed 's/\://' | cut -d ' ' -f 3-) if [ -n "$description" ] && [ -n "$operation" ] && [ -n "$target" ]; then if [ "$(echo $operation | grep -w "$opr" )" ]; then if [ "$(grep -E $target $INDEX_DIR/$name/.files)" ]; then msg "$description" . $hook if [ "`type -t exechook`" = "function" ]; then exechook fi fi fi fi unset description operation target done fi } removemakedepends() { ORPHAN="yes" for all_installed in $(ls $INDEX_DIR); do depend=$(cat $INDEX_DIR/$all_installed/.pkginfo | grep ^depends | cut -d " " -f3-) for dep in ${depend[@]}; do if [ $dep = $1 ]; then ORPHAN="no" fi done done [ "$ORPHAN" = "yes" ] && [ -d $INDEX_DIR/$1 ] && saferemove+=($1) } help() { cat << EOF Usage: installpkg package.spkg.txz [ ] Options: -u, --upgrade update package -r, --reinstall reinstall package -id, --ignore-dependency skip dependency check -ic, --ignore-conflict ignore conflict when installing package -v, --verbose verbose install process --no-preinstall skip preinstall script before build/install package --no-postinstall skip postinstall script after install package --no-preupgrade skip preupgrade script before upgrade package --no-postupgrade skip postupgrade script after upgrade package --no-backup skip backup when upgrading package --no-orphan-check skip orphaned package check after install package --no-color disable colour for output --dep install missing dependencies -h, --help show this help message Example: installpkg foobar-1.0-1.spkg.txz -u --no-backup upgrade package foobar-1.0-1 without backup its old configuration files EOF } parse_options() { if [ -z "$1" ]; then SHOWHELP=yes else while [ "$1" ]; do case $1 in --dep) DEP_INSTALL=yes ;; -u | --upgrade) UPGRADE_PKG=yes ;; -r | --reinstall) REINSTALL_PKG=yes ;; -id | --ignore-dependency) IGNORE_DEP=yes ;; -ic | --ignore-conflict) IGNORE_CONFLICT=yes ;; -v | --verbose) VERBOSE_INSTALL=yes ;; --no-preinstall) NO_PREINSTALL=yes ;; --no-postinstall) NO_POSTINSTALL=yes ;; --no-preupgrade) NO_PREUPGRADE=yes ;; --no-postupgrade) NO_POSTUPGRADE=yes ;; --no-backup) NO_BACKUP=yes ;; --no-color) NOCOLOR=yes ;; --no-orphan-check) NO_ORPHAN_CHECK=yes ;; *.spkg.txz) PKGNAME="$1" ;; -h | --help) SHOWHELP=yes ;; *) msg "Invalid option!"; exit 1 ;; esac shift done fi } main() { parse_options "$@" # disable colour if [ "$NOCOLOR" ]; then nocolor fi # show help page if [ "$SHOWHELP" ]; then help exit 0 fi ### CHECK EXISTANT OF PACKAGE FILE ### if [ ! -f $PKGNAME ]; then msgerr "Package ${RED}$1${CRESET} not exist!" exit 1 fi ### INTEGRITY OF PACKAGE ### if ! tar -tf $PKGNAME &>/dev/null; then msgerr "Package ${RED}$1${CRESET} is corrupted!" exit 1 fi ### CHECK FOR ROOT ACCESS ### needroot "Installing package" ### CHECK DIRECTORY ### checkdirexist "$INDEX_DIR" checkdirwrite "$INDEX_DIR" checkdirread "$INDEX_DIR" ### CHECK FOR LOCK FILE ### if [ -f /tmp/spkg.lock ]; then msgerr "Cant install/remove package simultaneously." msgerr "remove ${YELLOW}/tmp/spkg.lock${CRESET} if no install/remove package process running." exit 1 fi ### EXTRACT .pkginfo file into /tmp ### BASEPKGNAME=$(basename $PKGNAME) tar -xf $PKGNAME .pkginfo -O > /tmp/spkg.$BASEPKGNAME.pkginfo ### GET NAME, VERSION, RELEASE FROM TMP .pkginfo FILE ### name=$(getinfopkg name $BASEPKGNAME) version=$(getinfopkg version $BASEPKGNAME) release=$(getinfopkg release $BASEPKGNAME) depends=$(getinfopkg depends $BASEPKGNAME) makedepends=$(getinfopkg makedepends $BASEPKGNAME) backup=$(getinfopkg backup $BASEPKGNAME) conflict=$(getinfopkg conflict $BASEPKGNAME) ### REMOVE .pkginfo file from /tmp ### rm -f /tmp/spkg.$BASEPKGNAME.pkginfo ### IF INSTALLED & NO UPGRADE & NO REINSTALL ### if [ -d $INDEX_DIR/$name ] && [ ! "$UPGRADE_PKG" ] && [ ! "$REINSTALL_PKG" ]; then iname=$(installed_pkg_info name $name) iversion=$(installed_pkg_info version $name) irelease=$(installed_pkg_info release $name) msg "Package ${GREEN}$iname-$iversion-$irelease${CRESET} already installed." exit 0 fi ### IF UPGRADE OR REINSTALL PACKAGE ### if [ "$UPGRADE_PKG" ] || [ "$REINSTALL_PKG" ]; then if [ ! -d $INDEX_DIR/$name ]; then msg "Package ${RED}$name${CRESET} is not installed." exit 1 fi iname=$(installed_pkg_info name $name) iversion=$(installed_pkg_info version $name) irelease=$(installed_pkg_info release $name) # UPGRADE PACKAGE if [ "$UPGRADE_PKG" ]; then if [ -f "$INDEX_DIR/$name"/.lock ]; then msgerr "Package '$name' is locked." exit 0 fi checkoutdate msg "Upgrading package: ${YELLOW}$iname-$iversion-$irelease${CRESET} -> ${GREEN}$name-$version-$release${CRESET}" # REINSTALL PACKAGE elif [ "$REINSTALL_PKG" ]; then msg "Reinstall package ${GREEN}$name${CRESET}." fi fi ### INSTALL PACKAGE INTO SYSTEM ### installpkg # check orphan package (usually makedepends package) if [ ! "$NO_ORPHAN_CHECK" ]; then checkneworphan fi # msg2 "Running ldconfig..." if [ -x /sbin/ldconfig ]; then /sbin/ldconfig fi exit 0 } main "$@"