#!/bin/bash die() { echo -e "Exited ${BASH_SOURCE} at line no ${BASH_LINENO}." echo -e "$@" exit 1 } sql() { local sqlcmd="$*" [[ -z ${sqlcmd} ]] && die "no sqlcmd given." sqlite3 -nullvalue 'NULL' -list -separator '|' "${DBFILE}" << EOF || die "error running '$@'" ${sqlcmd}; EOF } mage_setup() { [ ! -d ${MROOT}${INSTALLDB} ] && install -d ${MROOT}${INSTALLDB} [ ! -d ${MROOT}${INSTALLDB}/records ] && install -d ${MROOT}${INSTALLDB}/records # [ ! -f ${MROOT}${VIRTUALDB_FILE} ] && touch ${MROOT}${VIRTUALDB_FILE} [ ! -d ${PKGDIR} ] && install -d ${PKGDIR} [ ! -d ${BUILDDIR} ] && install -d ${BUILDDIR} [ ! -d ${MAGEDIR} ] && install -d ${MAGEDIR} return 0 } dep2pver() { local pver pver="${1##*/}" # cut version only if not virtual or it will cut the name if [[ $(dep2pcat $1) != virtual ]] && \ [[ $2 != virtual ]] then echo "${pver##*-}" fi } ## atoi string atoi() { local pver="$1" local len local value local finalpver # first run a basic char to int on argv len=${#pver} for ((x=0; x < len; x++)) do value="${pver:${x}:1}" case ${value} in a) value=".1.";; b) value=".2.";; c) value=".3.";; d) value=".4.";; e) value=".5.";; f) value=".6.";; g) value=".7.";; h) value=".8.";; i) value=".9.";; j) value=".10.";; k) value=".11.";; l) value=".12.";; m) value=".13.";; n) value=".14.";; o) value=".15.";; p) value=".16.";; q) value=".17.";; r) value=".18.";; s) value=".19.";; t) value=".20.";; u) value=".21.";; v) value=".22.";; w) value=".23.";; x) value=".24.";; y) value=".25.";; z) value=".26.";; _|-|\|) value=".0.";; 0*) value="${value/0/.0.}";; esac # save new var finalpver="${finalpver}${value}" done echo ${finalpver} } ## max_len string1 string2 max_len() { local str1="$1" local str2="$2" local len1 local len2 # substitute spaces str1=$(echo "${str1}" | sed "s:\ ::g") str2=$(echo "${str2}" | sed "s:\ ::g") # bash returns lenghts always +1 len1=$(( ${#str1} -1 )) len2=$(( ${#str2} -1 )) if [[ ${len1} -ge ${len2} ]] then echo "${len1}" else echo "${len2}" fi } # is_higher pver1 pver2 is_higher() { local pver1="$1" local pver2="$2" local fpver local fpver local arr1 local arr2 local maxarrlen local i local x # build to arrays with fixed pvers fpver1=$(atoi ${pver1} | sed "s:\.:\ :g") fpver2=$(atoi ${pver2} | sed "s:\.:\ :g") maxarrlen=$(max_len "${fpver1}" "${fpver2}") # fill array with values declare -i x=0 for i in ${fpver1} do arr1[${x}]="${i}" ((x++)) done # now fill the rest with ZEROS if [[ ${x} -lt ${maxarrlen} ]] then for (( i=x; i>> ${COLDEFAULT}" echo -n "installing (${count_current}/${count_total}): " echo -ne "${COLBLUE}${pcat}/${COLDEFAULT}" echo -e "${COLGREEN}${pname}-${pver}-${pbuild}${COLDEFAULT}" # magefile="${MAGEDIR}/${pcat}/${pname}/${pname}-${pver}-${pbuild}.mage" # source ${magefile} PKGNAME="${pname}-${pver}-${ARCH}-${pbuild}" # abort on sources if no srcinstall if [[ ${PKGTYPE} = sources ]] && [[ ${src_install} != true ]] then echo echo -e "This Package is a Source Package." echo echo -e "Only 'srcinstall' works with this type of packages" echo -en "If you have done a srcinstall before, " echo -e "you will find the files in /usr/src." echo exit 1 fi ## preinstall scripts if [ -n "$(typeset -f preinstall)" ] then echo -e " ${COLBLUE}***${COLDEFAULT} running preinstall ... " preinstall unset preinstall fi if [[ ${src_install} = true ]] then local smage2file # check needed global vars [ -z "${SMAGESCRIPTSDIR}" ] && die "\$SMAGESCRIPTSDIR not set." [ -z "${SOURCEDIR}" ] && die "\$SOURCEDIR not set." [ -z "${BINDIR}" ] && die "\$BINDIR not set." # build the package first if [[ ${MAGEDEBUG} = on ]] then echo M:${pname} echo V:${pver} echo B:${pbuild} fi smage2file=${SMAGESCRIPTSDIR}/${pname}/${pname}-${pver}-${pbuild}.smage2 if [ -f "${smage2file}" ] then echo -e " ${COLBLUE}***${COLDEFAULT} building package from source ... " smage2 ${smage2file} || die "compile failed" else echo echo "$(basename ${SMAGEFILE}) not found." echo "update your smage-tree and try it again." echo die fi fi if [[ ${PKGTYPE} != virtual ]] && \ [[ ${PKGTYPE} != sources ]] then echo -e " ${COLBLUE}***${COLDEFAULT} merging files into system ... " build_doinstall ${PKGNAME} fi ## postinstall scripts if [ -n "$(typeset -f postinstall)" ] then echo -e " ${COLBLUE}***${COLDEFAULT} running postinstall ... " postinstall unset postinstall fi # install a database entry install_database_entry \ --pcat "${pcat}" \ --pname "${pname}" \ --pver "${pver}" \ --pbuild "${pbuild}" \ --pkgname "${PKGNAME}" \ --pkgtype "${PKGTYPE}" \ || die "error in mage_install() running install_database_entry()." # remove the package dir now if [ -d ${BUILDDIR}/${PKGNAME} ] then rm -rf ${BUILDDIR}/${PKGNAME} fi # rebuilds toplevel info node if [[ ${MAGE_INFO_REBUILD} = true ]] then echo -ne "${COLBLUE} *** ${COLDEFAULT}" echo -n "rebuilding top-level info node ... " ${MLIBDIR}/mkinfodir ${MROOT}/usr/share/info \ > ${MROOT}/usr/share/info/dir && \ echo "done." || echo "failure." unset MAGE_INFO_REBUILD fi # rebuilds the enviroment with the content of /etc/env.d if [[ ${MAGE_ENV_REBUILD} = true ]] then echo -ne "${COLBLUE} *** ${COLDEFAULT}" echo -n "rebuilding environment ... " ${MLIBDIR}/env-rebuild.sh > /dev/null && \ echo "done." || echo "failure." unset MAGE_ENV_REBUILD fi xtitleclean echo -ne "${COLBLUE} --- ${COLDEFAULT}" echo -n "package " # echo -ne "${COLBLUE}${pcat}/${COLDEFAULT}" # echo -ne "${COLGREEN}${pname}-${pver}-${pbuild}${COLDEFAULT} " echo "successfully installed." # unset these functions unset -f preinstall unset -f postinstall unset -f preremove unset -f postremove } md5sum_packages() { local list="$@" local magefile local pcat local pname local pkgname local pkgfile local pkgtype local count_current local count_total local pver local pbuild # get count of total packages declare -i count_current=0 declare -i count_total=0 for i in ${list}; do (( count_total++ )); done for magefile in ${list} do pcat=${magefile%%/*} pname=$(magename2pname ${magefile}) pver=$(magename2pver ${magefile}) pbuild=$(magename2pbuild ${magefile}) pkgname="${pname}-${pver}-${ARCH}-${pbuild}" #md5file="${MAGEDIR}/${pcat}/${pname}/md5/${pkgname}.md5" pkgfile="${pkgname}.${PKGSUFFIX}" pkgtype=$(sql "select pkgtype from packages where pname='${pname}' and pver='${pver}' and pbuild='${pbuild/r/}'") md5=$(sql "select packages_info.md5 from packages_info inner join packages on packages_info.pkg_id=packages.id where packages.pname='${pname}' and packages.pver='${pver}' and packages.pbuild='${pbuild/r/}' and arch='${ARCH}'") #echo "DEBUG: ${md5}" (( count_current++ )) xtitle "[ (${count_current}/${count_total}) MD5SUM: ${pkgfile} ]" # abort on virtual pkg if [[ ${pkgtype} = virtual ]] then echo -ne " ${COLBLUE}---${COLDEFAULT}" echo " !md5sum virtual (${count_current}/${count_total}): ${pkgfile/.${PKGSUFFIX}/} ... " continue fi # abort on sources pkg if [[ ${pkgtype} = sources ]] then echo -ne " ${COLBLUE}---${COLDEFAULT}" echo " !md5sum sources (${count_current}/${count_total}): ${pkgfile/.${PKGSUFFIX}/} ... " continue fi # if [ -f "${md5file}" ] # then echo -ne "${COLBLUE} *** ${COLDEFAULT}" echo -ne "checking md5sum (${count_current}/${count_total}): " #( cd ${PKGDIR}; md5sum --check ${md5file}) || die "md5 for ${pkgfile} failed" ( cd ${PKGDIR}; md5sum --check << EOF ;)|| die "md5 for ${pkgfile} failed" ${md5} ${pkgfile} EOF # else # echo -ne "${COLBLUE} --- ${COLDEFAULT}" # echo -e "!! no md5sum file found for ${pkgfile} :(" # fi done # add a crlf for a better view if [ ${count_total} -gt 1 ]; then echo; fi } unpack_packages() { local list="$@" local magefile local pkg local pkgtype local count_current local count_total # get count of total packages declare -i count_current=0 declare -i count_total=0 for i in ${list}; do (( count_total++ )); done for magefile in ${list} do #pkg="$(get_value_from_magefile PKGNAME ${magefile}).${PKGSUFFIX}" #pkgtype="$(get_value_from_magefile PKGTYPE ${magefile})" pname=$(magename2pname ${magefile}) pver=$(magename2pver ${magefile}) pbuild=$(magename2pbuild ${magefile}) pkg="${pname}-${pver}-${ARCH}-${pbuild}.${PKGSUFFIX}" pkgtype=$(sql "select pkgtype from packages where pname='${pname}' and pver='${pver}' and pbuild='${pbuild/r/}'") (( count_current++ )) xtitle "[ (${count_current}/${count_total}) Unpacking ${pkg} ]" # abort on virtual pkg if [[ ${pkgtype} = virtual ]] then echo -ne " ${COLBLUE}---${COLDEFAULT}" echo " !unpack virtual (${count_current}/${count_total}): ${pkg/.${PKGSUFFIX}/} ... " continue fi # abort on sources pkg if [[ ${pkgtype} = sources ]] then echo -ne " ${COLBLUE}---${COLDEFAULT}" echo " !unpack sources (${count_current}/${count_total}): ${pkg/.${PKGSUFFIX}/} ... " continue fi echo -e " ${COLBLUE}***${COLDEFAULT} unpacking (${count_current}/${count_total}): ${pkg} ... " tar xjmf ${PKGDIR}/${pkg} -C ${BUILDDIR} || die "Unpacking package ${pkg}" done # add a crlf for a better view if [ ${count_total} -gt 1 ]; then echo; fi } install_packages() { local list="$@" local pkg local pcat local pname local pver local pbuild local total_pkgs local current_pkg local src_install local uninstall_list # check for --src-install if [[ $1 = --src-install ]] then # remove --src-install from list list=${list/--src-install/} # enable src-install src_install="--src-install" fi # reset MAGE_PROTECT_COUNTER declare -i MAGE_PROTECT_COUNTER=0 export MAGE_PROTECT_COUNTER # get count of total packages declare -i total_pkgs=0 declare -i current_pkg=0 for i in ${list}; do (( total_pkgs++ )); done echo if [[ -n ${MROOT} ]] then echo -ne ${COLRED} echo "!! installing in MROOT=${MROOT}" echo -ne ${COLDEFAULT} echo fi for pkg in ${list} do (( current_pkg++ )) #pcat=$(magename2pcat ${pkg}) pcat="${pkg%%/*}" pname=$(magename2pname ${pkg}) pver=$(magename2pver ${pkg}) pbuild=$(magename2pbuild ${pkg}) mage_install \ --pcat ${pcat} \ --pname ${pname} \ --pver ${pver} \ --pbuild ${pbuild} \ --count-total ${total_pkgs} \ --count-current ${current_pkg} \ ${src_install} # check for allready installed packages and remove them # except the package we have installed uninstall_list="$(get_uninstall_candidates \ --pcat "${pcat}" \ --pname "${pname}" \ --protected ${pcat}/${pname}-${pver}-${pbuild})" # uninstall all packges in uninstall_list if not empty if [ -n "${uninstall_list}" ] then echo uninstall_packages ${uninstall_list} \ || die "install_packges() uninstalling not-needed." fi # crlf for better view in VERBOSE mode #if [[ ${VERBOSE} = on ]]; then echo; fi echo done #echo "DEBUG MAGE_PROTECT_COUNTER=${MAGE_PROTECT_COUNTER}" show_etc_update_mesg } uninstall_packages() { local list="$@" local pcat local pname local pver local pbuild local can_pcat local can_pname local can_ver_list if [[ -n ${MROOT} ]] then echo -ne ${COLRED} echo "!! uninstalling from MROOT=${MROOT}" echo -ne ${COLDEFAULT} echo fi # generate a candidates list for pkg in ${list} do #pcat=$(dep2pcat ${pkg}) pcat="${pkg%%/*}" pname=$(magename2pname ${pkg}) pver=$(magename2pver ${pkg}) pbuild=$(magename2pbuild ${pkg}) can_pcat="${pcat}" can_pname="${pname}" if [ -z "${can_ver_list}" ] then can_ver_list=" ${pver}-${pbuild}" else can_ver_list="${can_ver_list}, ${pver}-${pbuild}" fi done echo -ne "${COLBLUE} --- ${COLDEFAULT}" echo "following candidate(s) will be removed:" echo -ne "${COLBLUE} --- ${COLDEFAULT}" echo -ne "${COLBOLD}${can_pcat}/${can_pname}:${COLDEFAULT}" echo -e "${COLRED} ${can_ver_list} ${COLDEFAULT}" echo if [ ${MAGE_UNINSTALL_TIMEOUT} -gt 0 ] then echo -ne "${COLBLUE} --- ${COLDEFAULT}" echo "( Press [CTRL+C] to abort )" echo -ne "${COLBLUE} --- ${COLDEFAULT}" echo -n "Waiting ${MAGE_UNINSTALL_TIMEOUT} seconds ..." for ((i=MAGE_UNINSTALL_TIMEOUT; i >= 0; i--)) do echo -ne "${COLRED} ${i}${COLDEFAULT}" sleep 1 done echo echo fi for pkg in ${list} do pcat=$(dep2pcat ${pkg}) pname=$(magename2pname ${pkg}) pver=$(magename2pver ${pkg}) pbuild=$(magename2pbuild ${pkg}) mage_uninstall \ --pcat ${pcat} \ --pname ${pname} \ --pver ${pver} \ --pbuild ${pbuild} \ --count-total ${total_pkgs} \ --count-current ${current_pkg} \ ${src_install} # crlf for better view in VERBOSE mode #if [[ ${VERBOSE} = on ]]; then echo; fi echo done } is_installed() { local DBFILE local pkgid local pcat local pname local pbuild local pver # very basic getops for i in $* do case $1 in --pcat|-c) shift; pcat="$1" ;; --pname|-n) shift; pname="$1" ;; --pver|-v) shift; pver="$1" ;; --pbuild|-b) shift; pbuild="$1" ;; esac shift done DBFILE="${MAGE_INSTALL_DB}" pkgid=$(sql "select id from packages where pname='${pname}' and pver='${pver}' and pbuild='${pbuild}'") [[ ! -z ${pkgid} ]] && return 0 return 1 } reverse_depends() { local DBFILE local pname="$1" DBFILE="${MAGE_INSTALL_DB}" sql "select categories.pcat, packages.pname, packages.pver, packages.pbuild from depends inner join packages on packages.id=depends.pkg_id inner join categories on categories.id=packages.pcat_id where depends.pname='${pname}'" } reverse_sdepends() { local DBFILE local pname="$1" DBFILE="${MAGE_INSTALL_DB}" sql "select categories.pcat, packages.pname, packages.pver, packages.pbuild from sdepends inner join packages on packages.id=sdepends.pkg_id inner join categories on categories.id=packages.pcat_id where sdepends.pname='${pname}'" } create_database_layout() { sql "create table categories(id integer primary key, pcat text unique)" sql "create table packages(id integer primary key, pname text, pver text, pbuild text, pcat_id numeric, state text, provide text, pkgtype text )" sql "create table depends(id integer primary key, pkg_id numeric, relation text, pcat_id numeric, pname text, pver text, pbuild text)" sql "create table sdepends(id integer primary key, pkg_id numeric, relation text, pcat_id numeric, pname text, pver text, pbuild text)" sql "create table packages_info(id integer primary key, pkg_id numeric, arch text, md5 text, mtime numeric, homepage text, description text, size numeric)" #sql "create table packages_content(id integer primary key, pkginfo_id numeric, char text, dirs text, files text, pipes text, symlinks text)" sql "create table packages_content(id integer primary key, pkginfo_id numeric, char blob, dirs blob, files blob, pipes blob, symlinks blob)" } install_database_entry() { local pcat local pname local pver local pbuild local pkgtype local pkgname local magefile local dbrecorddir local provide local homepage local description local pkgid local depends local sdepends local relation local depcatid local depname local depver local depbuild local mage_pkg_id local i local install_pkg_id local table # very basic getops for i in $* do case $1 in --pcat|-c) shift; pcat="$1" ;; --pname|-n) shift; pname="$1" ;; --pver|-v) shift; pver="$1" ;; --pbuild|-b) shift; pbuild="$1" ;; --pkgname|-a) shift; pkgname="$1" ;; # --state|-s) shift; state="$1" ;; --pkgtype|-t) shift; pkgtype="$1" ;; esac shift done # sanity checks; abort if not given [[ -z ${pcat} ]] && die "install_database_entry() \$pcat not given." [[ -z ${pname} ]] && die "install_database_entry() \$pname not given." [[ -z ${pver} ]] && die "install_database_entry() \$pver not given." [[ -z ${pbuild} ]] && die "install_database_entry() \$pbuild not given." [[ -z ${pkgname} ]] && die "install_database_entry() \$pkgname not given." # [[ -z ${state} ]] && die "install_database_entry() \$state not given." # check needed global vars [[ -z ${MAGEDIR} ]] && die "install_database_entry() \$MAGEDIR not set." [[ -z ${INSTALLDB} ]] && die "install_database_entry() \$INSTALLDB not set." # first of all convert pbuild to database format (remove the r) pbuild="${pbuild/r/}" # check if # copy all things over over # mage.pkg_id DBFILE="${MAGE_PACKAGES_DB}" mage_pkg_id=$(sql "select id from packages where pname='${pname}' and pver='${pver}' and pbuild='${pbuild}'") DBFILE="${MAGE_INSTALL_DB}" # add pcat to installdb if missing if [[ -z $(sql "select id from categories where pcat='${pcat}'") ]] then sql "insert into categories (pcat) values ('${pcat}')" fi # attach install database # install.categories.id != main.categories.id !!! # so get pcat from pcat_id via inner join. # then query install db which id pcat has and use this one # final phase copies the whole crap to the install db # use some more rows to copy the whole table sqlite3 ${MAGE_PACKAGES_DB} \ "attach database '${MAGE_INSTALL_DB}' as install; insert into install.packages (pcat_id, pname, pver, pbuild, state, provide, pkgtype) select mage_id, main.packages.pname, main.packages.pver, main.packages.pbuild, main.packages.state, main.packages.provide, main.packages.pkgtype from main.packages, (select id as mage_id from install.categories where pcat=( select pcat from main.packages inner join main.categories on main.categories.id=main.packages.pcat_id where main.packages.id='${mage_pkg_id}') ) where main.packages.id=${mage_pkg_id};" # get install db pkg_id install_pkg_id=$(sql "select max(id) from packages") # now copy dependencies # replace pkg with the one from insatll.db for table in depends sdepends do sqlite3 ${MAGE_PACKAGES_DB} \ "attach database '${MAGE_INSTALL_DB}' as install; insert into install.${table} (pkg_id, relation, pcat_id, pname, pver, pbuild) select '${install_pkg_id}', relation, pcat_id, pname, pver, pbuild from main.${table} where pkg_id='${mage_pkg_id}'" done # and now the package infos sqlite3 ${MAGE_PACKAGES_DB} \ "attach database '${MAGE_INSTALL_DB}' as install; insert into install.packages_info (pkg_id, arch, md5, mtime, homepage, description, size) select '${install_pkg_id}', arch, md5, mtime, homepage, description, size from main.packages_info where pkg_id='${mage_pkg_id}' and arch='${ARCH}'" # now install PKGTYPE specific files case ${pkgtype} in virtual) echo ;; sources) echo ;; *) # and finally the package_content # but we first need to know the pkg_info id # because of the arch dependency pkg_info_id=$(sql "select max(id) from packages_info") sql "insert into packages_content (pkginfo_id, char, dirs, files, pipes, symlinks) values('${pkg_info_id}', 'records/${pkg_info_id}/char.bz2', 'records/${pkg_info_id}/dirs.bz2', 'records/${pkg_info_id}/files.bz2', 'records/${pkg_info_id}/pipes.bz2', 'records/${pkg_info_id}/symlinks.bz2')" # create compressed content files entrydir=${BUILDDIR}/${pname}-${pver}-${ARCH}-r${pbuild} local entryfile for entryfile in char dirs files pipes symlinks do install -d $(dirname ${MAGE_INSTALL_DB})/records/${pkg_info_id} cat ${entrydir}/.${entryfile} | bzip2 -9 >> $(dirname ${MAGE_INSTALL_DB})/records/${pkg_info_id}/${entryfile}.bz2 done ;; esac }