#!/bin/bash export LC_ALL=C . /usr/share/scratchpkg/functions || exit 1 source_check() { url_stat=0 for sources in ${source[@]}; do if [ $(echo $sources | grep -E "(ftp|http|https)://") ]; then if [ $(echo $sources | grep -E "::(ftp|http|https)://") ]; then uri=$(echo "$sources" | awk -F '::' '{print $2}') else uri="$sources" fi fi echo -ne "Checking $uri ... " wget --spider -q "$uri" if [ $? = 0 ]; then echo -e ${GREEN}OK${CRESET} else url_stat=$? echo -e ${RED}FAILED${CRESET} fi done return ${url_stat} } updatemdsum() { if [ -z $source ]; then msgwarn "source=() is empty, no need md5sum." return 0 fi for um in $(seq 0 $((${#source[@]} - 1))); do if [ $(echo ${source[$um]} | grep -E "(ftp|http|https)://") ]; then if [ $(echo ${source[$um]} | grep -E "::(ftp|http|https)://") ]; then sourcename="$SOURCE_DIR/$(echo ${source[$um]} | awk -F '::' '{print $1}')" else sourcename="$SOURCE_DIR/$(echo ${source[$um]} | rev | cut -d / -f 1 | rev)" fi else sourcename="${source[$um]}" fi needupdatechecksum="$needupdatechecksum $sourcename" done for file in ${needupdatechecksum[@]}; do if [ ! -f $file ]; then missingsource+=($file) fi done if [ "${#missingsource[@]}" -gt 0 ]; then msg "Missing source:" for ms in ${missingsource[@]}; do msg2 "$ms" done return 1 fi echo -e "md5sum=($(md5sum $needupdatechecksum | awk '{ print $1 }'))" } checkmdsum() { if [ -z $md5sum ]; then msgwarn "md5sum=() is empty, please provide it." return 0 fi if [ "${#source[@]}" != "${#md5sum[@]}" ]; then msgerr "Total source and md5sums different." return 1 fi for s in $(seq 0 $((${#source[@]} - 1))); do if [ $(echo ${source[$s]} | grep -E "(ftp|http|https)://") ]; then if [ $(echo ${source[$s]} | grep -E "::(ftp|http|https)://") ]; then sourcename=$SOURCE_DIR/$(echo ${source[$s]} | awk -F '::' '{print $1}') else sourcename=$SOURCE_DIR/$(echo ${source[$s]} | rev | cut -d / -f 1 | rev) fi else sourcename="${source[$s]}" fi sum=$(md5sum "$sourcename" | awk '{ print $1 }') if [ "$sum" != "${md5sum[$s]}" ] && [ "SKIP" != "${md5sum[$s]}" ]; then errormdsum+=($sourcename) fi done if [ "${#errormdsum[@]}" -gt 0 ]; then msgerr "md5sum mismatch:" for mismatch in ${errormdsum[@]}; do msg2 "$mismatch" done return 1 fi } getsource() { for sources in ${source[@]}; do if [ $(echo $sources | grep -E "(ftp|http|https)://") ]; then downloadsource $sources fi done } downloadsource(){ if [ $(echo $1 | grep -E "::(ftp|http|https)://") ]; then tarballname=$(echo $1 | awk -F '::' '{print $1}') tarballurl=$(echo $1 | awk -F '::' '{print $2}') else tarballname=$(echo $1 | rev | cut -d / -f 1 | rev) tarballurl=$1 fi WGETCMD="wget --passive-ftp --no-directories --tries=3 --waitretry=3 --output-document=$SOURCE_DIR/$tarballname.partial" WGETRESUME="wget -c --passive-ftp --no-directories --tries=3 --waitretry=3 --output-document=$SOURCE_DIR/$tarballname.partial" if [ -n $1 ]; then if [ "$REDOWNLOAD_SOURCE" ]; then if [ -f $SOURCE_DIR/$tarballname ]; then rm $SOURCE_DIR/$tarballname fi fi if [ -f $SOURCE_DIR/$tarballname ]; then msg "Source file ${GREEN}$tarballname${CRESET} found." else checktool wget if [ -f $SOURCE_DIR/$tarballname.partial ]; then msg "Resuming ${GREEN}$1${CRESET}." $WGETRESUME $tarballurl && mv $SOURCE_DIR/$tarballname.partial $SOURCE_DIR/$tarballname || exitscript1 else msg "Downloading ${GREEN}$1${CRESET}." $WGETCMD $tarballurl && mv $SOURCE_DIR/$tarballname.partial $SOURCE_DIR/$tarballname || exitscript1 fi fi fi } preparesource() { SRC=$WORK_DIR/$name/src PKG=$WORK_DIR/$name/pkg [ -d "$WORK_DIR/$name" ] && rm -fr "$WORK_DIR/$name" mkdir -p $SRC $PKG if [ "${#source[@]}" -gt 0 ]; then msg "Preparing sources..." for sources in ${source[@]}; do if [ $(echo $sources | grep -E "(ftp|http|https)://") ]; then if [ $(echo $sources | grep -E "::(ftp|http|https)://") ]; then tarballname=$(echo $sources | awk -F '::' '{print $1}') else tarballname=$(echo $sources | rev | cut -d / -f 1 | rev) fi NO_EXTRACT="" for i in ${noextract[@]}; do if [ "$i" = "$tarballname" ]; then NO_EXTRACT=yes msg "Preparing ${GREEN}$tarballname${CRESET}..." && cp $SOURCE_DIR/$tarballname $SRC || ERROR_PREPARE_SOURCE+=($tarballname) break fi done if [ ! "$NO_EXTRACT" ]; then case $tarballname in *.tar|*.tar.gz|*.tar.Z|*.tgz|*.tar.bz2|*.tbz2|*.tar.xz|*.txz|*.tar.lzma|*.zip|*.rpm) COMMAND="$EXTPROG -p -o -C $SRC -xf $SOURCE_DIR/$tarballname" MODE="Unpacking" ;; *) COMMAND="cp $SOURCE_DIR/$tarballname $SRC" MODE="Preparing" ;; esac msg2 "$MODE ${GREEN}$tarballname${CRESET}..." $COMMAND if [ $? != 0 ]; then msgerr "$MODE ${RED}$tarballname${CRESET} failed." clearworkdir exitscript1 fi fi else msg2 "Preparing ${GREEN}$sources${CRESET}..." && cp $sources $SRC || ERROR_PREPARE_SOURCE+=($sources) fi done fi if [ "${#ERROR_PREPARE_SOURCE[@]}" -gt 0 ]; then msgerr "Failed prepared source:" for err in ${ERROR_PREPARE_SOURCE[@]}; do msg2 $err done clearworkdir exitscript1 fi } loadspkgbuild() { if [ -f $BUILD_SCRIPT ]; then getpkginfo else msgerr "No $BUILD_SCRIPT found." exitscript1 fi } buildpackage() { msg "Start build ${GREEN}$name-$version-$release${CRESET}." pushd $SRC (exec &> >(tee -i $LOG_DIR/$name.log); echo "$name-$version"; echo $(date); set -e -x; build) if [ $? != 0 ]; then msgerr "Build ${RED}$PKGNAME${CRESET} failed." clearworkdir exitscript1 else msg "Successfully build ${GREEN}$name-$version-$release${CRESET}." fi popd } runpreinstall() { if [ "`type -t pre_install`" = "function" ]; then pre_install "$version" && PREINSTALL_STATUS=OK || PREINSTALL_STATUS=KO fi } packaging() { [ -f $name.install ] && cp $name.install $PKG/.pkginstall [ -f readme ] && cp readme $PKG/.pkgreadme pushd $PKG if check_options purge y; then purgefiles fi if check_options emptydirs n; then removeemptydirs fi if check_options docs n && [[ -n ${DOC_DIRS[*]} ]]; then removedocs fi if check_options libtool n; then removelibtool fi if check_options strip y; then strip_files fi if check_options zipman y && [[ -n ${MAN_DIRS[*]} ]]; then compressinfomanpages fi echo "# Generated by buildpkg" > .pkginfo echo "# `date`" >> .pkginfo echo "name = $name" >> .pkginfo echo "version = $version" >> .pkginfo echo "release = $release" >> .pkginfo [ -n "$description" ] && echo "description = $description" >> .pkginfo [ -n "$backup" ] && for b in ${backup[@]}; do echo "backup = $b" >> .pkginfo; done [ -n "$conflict" ] && for c in ${conflict[@]}; do echo "conflict = $c" >> .pkginfo; done [ -n "$depends" ] && for d in ${depends[@]}; do echo "depends = $d" >> .pkginfo; done [ -n "$makedepends" ] && for md in ${makedepends[@]}; do echo "makedepends = $md" >> .pkginfo; done [ -n "$noextract" ] && echo "noextract = $noextract" >> .pkginfo msg "Packaging ${GREEN}$name-$version-$release${CRESET}..." for file in .pkginstall .pkgreadme; do if [ -f $file ]; then addtotar+=($file) fi done tar -c -J -p -f $PACKAGE_DIR/$PKGNAME * .pkginfo "${addtotar[@]}" if [ $? != 0 ]; then msgerr "Packaging ${RED}$PKGNAME${CRESET} failed." if [ -f $PACKAGE_DIR/$PKGNAME ]; then rm $PACKAGE_DIR/$PKGNAME fi exitscript1 else pkgsize="$(ls -lh $PACKAGE_DIR/$PKGNAME | awk '{print $5}')" $EXTPROG -t -v -f $PACKAGE_DIR/$PKGNAME msg "Successfully create package ${GREEN}$PKGNAME${CRESET}. (${pkgsize})" fi case $PREINSTALL_STATUS in OK) msg "preinstall : ${GREEN}OK${CRESET}" ;; KO) msg "preinstall : ${RED}FAIL${CRESET}" ;; esac popd } buildpkg() { # lock build process prevent simultaneous build lockbuild getsource if [ ! "$IGNORE_MDSUM" ]; then checkmdsum || exitscript1 fi preparesource [ "$UPGRADE_PKG" ] && NO_PREINSTALL=yes if [ ! "$NO_PREINSTALL" ]; then runpreinstall NO_PREINSTALL=yes fi if check_options makeflags n; then unset "MAKEFLAGS" elif check_options makeflags y; then export MAKEFLAGS fi if check_options buildflags n; then unset CFLAGS CXXFLAGS elif check_options buildflags y; then export CFLAGS CXXFLAGS fi buildpackage if [ "$FORCE_REBUILD" ]; then if [ -f $PACKAGE_DIR/$PKGNAME ]; then rm $PACKAGE_DIR/$PKGNAME fi fi packaging clearworkdir } checkdeps() { for dep in ${depends[@]}; do if [ ! -d $INDEX_DIR/$dep ]; then if [ "$INSTALL_PKG" -o "$DEP_INSTALL" ]; then scratch -i -p $dep --no-orphan-check || exit 1 else MSDEP+=($dep) fi fi done for makedep in ${makedepends[@]}; do if [ ! -d $INDEX_DIR/$makedep ]; then if [ "$INSTALL_PKG" -o "$DEP_INSTALL" ]; then scratch -i -p $makedep --no-orphan-check || exit 1 else MSMKDEP+=($makedep) fi fi done if [ "${#MSDEP[@]}" -gt 0 ] || [ "${#MSMKDEP[@]}" -gt 0 ]; then msg "Missing dependencies:" for msd in ${MSDEP[@]}; do msg2 "$msd" done for msmkd in ${MSMKDEP[@]}; do msg2 "$msmkd ${CYAN}(make)${CRESET}" done exitscript1 fi } # remove lock file and exit 1 exitscript1() { if [ -f /tmp/spkg.$name.lock ]; then rm /tmp/spkg.$name.lock fi exit 1 } # remove lock file and exit 0 exitscript0() { if [ -f /tmp/spkg.$name.lock ]; then rm /tmp/spkg.$name.lock fi exit 0 } # create lock file in /tmp prevent for build same package simultaneously lockbuild() { if [ ! -f /tmp/spkg.$name.lock ]; then touch /tmp/spkg.$name.lock fi } updatepkgdepends() { # only installed depends will count as depends for dep in ${depends[@]}; do if [ -d $INDEX_DIR/$dep ]; then newdep+=($dep) fi done depends="${newdep[@]}" # only installed makedepends will count as makedepends for mdep in ${makedepends[@]}; do if [ -d $INDEX_DIR/$mdep ]; then newmdep+=($mdep) fi done makedepends="${newmdep[@]}" } 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 } 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) } clearworkdir() { if [ ! "$KEEP_WORK" ]; then if [ ! -z $name ]; then if [ -d $WORK_DIR/$name ]; then rm -fr $WORK_DIR/$name fi fi fi } interrupted() { #echo "" #msg "${YELLOW}Interrupted!${CRESET}" clearworkdir exitscript1 } help() { cat << EOF Usage: buildpkg [ ] Options: -i, --install install package into system -u, --upgrade upgrade 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-color disable color --no-backup skip backup when upgrading package --dep install missing dependencies -fr, --force-rebuild rebuild package -im, --ignore-mdsum skip md5sum checking -um, --update-mdsum update md5sum -cm, --check-mdsum calculate and print md5sum for source file -do, --download-only download only source file -eo, --extract-only extract only source file -kw, --keep-work keep working directory -rd, --redownload re-download source file -cs, --check-source check dead url for sources -sd, --source-dir override directory path for sources -pd, --package-dir override directory path for compiled package -h, --help show this help message Example: buildpkg -fr -kw -i this will force rebuild, install package and keep working directory Note: * use buildpkg without any options will only download source and build package by using other default options * buildpkg need run inside port directory EOF } parse_options() { while [ "$1" ]; do case $1 in -i | --install) INSTALL_PKG=yes ;; -u | --upgrade) UPGRADE_PKG=yes; OPTS+=($1) ;; -r | --reinstall) REINSTALL_PKG=yes; OPTS+=($1) ;; -id | --ignore-dependency) IGNORE_DEP=yes; OPTS+=($1) ;; -ic | --ignore-conflict) OPTS+=($1) ;; --no-preinstall) NO_PREINSTALL=yes; OPTS+=($1) ;; --no-postinstall) OPTS+=($1) ;; --no-preupgrade) OPTS+=($1) ;; --no-postupgrade) OPTS+=($1) ;; -v | --verbose) OPTS+=($1) ;; --no-color) NOCOLOR=yes; OPTS+=($1) ;; --no-backup) OPTS+=($1) ;; --dep) DEP_INSTALL=yes; OPTS+=($1) ;; --no-orphan-check) NO_ORPHAN_CHECK=yes; OPTS+=($1) ;; -fr | --force-rebuild) FORCE_REBUILD=yes ;; -im | --ignore-mdsum) IGNORE_MDSUM=yes ;; -um | --update-mdsum) UPDATE_MDSUM=yes ;; -do | --download-only) DOWNLOAD_ONLY=yes ;; -eo | --extract-only) EXTRACT_ONLY=yes ;; -kw | --keep-work) KEEP_WORK=yes ;; -rd | --redownload) REDOWNLOAD_SOURCE=yes ;; -cs | --check-source) SOURCE_CHECK=yes ;; -h | --help) SHOWHELP=yes ;; -sd | --source-dir) testinput "$2" && SOURCE_DIR="$2" || exit 1; shift ;; -pd | --package-dir) testinput "$2" && PACKAGE_DIR="$2" || exit 1; shift ;; *) msg "Invalid option!"; exit 1 ;; esac shift done } main() { parse_options "$@" # disable colour if [ "$NOCOLOR" ]; then nocolor fi # show help page if [ "$SHOWHELP" ]; then help exit 0 fi # source spkgbuild loadspkgbuild # show help page if [ "$SOURCE_CHECK" ]; then source_check || exit $? exit 0 fi # check required directory checkdirexist "$WORK_DIR" "$SOURCE_DIR" "$PACKAGE_DIR" "$LOG_DIR" checkdirwrite "$WORK_DIR" "$SOURCE_DIR" "$PACKAGE_DIR" "$LOG_DIR" checkdirread "$WORK_DIR" "$SOURCE_DIR" "$PACKAGE_DIR" "$LOG_DIR" if [ "$INSTALL_PKG" ] || [ "$UPGRADE_PKG" ] || [ "$REINSTALL_PKG" ]; then NO_ORPHAN_CHECK=yes fi # check the required field in spkgbuild if [ -z "$name" ]; then msgerr "'name' is empty!" exit 1 elif [ "$(basename `pwd`)" != "$name" ]; then msgerr "Port name and Directory name is different!" exit 1 elif [ -z "$version" ]; then msgerr "'version' is empty!" exit 1 elif [ -z "$release" ]; then msgerr "'release' is empty!" exit 1 elif [ "`type -t build`" != "function" ]; then msgerr "'build' function not exist!" exit 1 fi PKGNAME="$name-$version-$release.spkg.txz" # calculate & print md5sum if [ "$UPDATE_MDSUM" ]; then updatemdsum exit 0 fi # check for lock file if [ -f /tmp/spkg.$name.lock ]; then msgerr "Cant build same package simultaneously." msgerr "remove ${YELLOW}/tmp/spkg.$name.lock${CRESET} if no build process for ${YELLOW}$name.${CRESET}" exit 1 fi # download source only if [ "$DOWNLOAD_ONLY" ]; then getsource exit 0 fi # extract source only if [ "$EXTRACT_ONLY" ]; then getsource preparesource exit 0 fi # build package if [ -f $PACKAGE_DIR/$PKGNAME ] && [ ! "$FORCE_REBUILD" ]; then # if package txz exist and not force rebuild if [ ! "$INSTALL_PKG" ] && [ ! "$REINSTALL_PKG" ] && [ ! "$UPGRADE_PKG" ]; then msg "${GREEN}$PKGNAME${CRESET} is up-to-date." exitscript0 fi else # dependency check if [ ! "$IGNORE_DEP" ]; then checkdeps else updatepkgdepends fi [ -f $name.install ] && . $name.install buildpkg IGNORE_DEP=yes if [ ! "$NO_ORPHAN_CHECK" ]; then checkneworphan fi fi # install package if [ "$INSTALL_PKG" ] || [ "$REINSTALL_PKG" ] || [ "$UPGRADE_PKG" ]; then installpkg $PACKAGE_DIR/$PKGNAME ${OPTS[@]} || exitscript1 fi exitscript0 } trap "interrupted" SIGHUP SIGINT SIGQUIT SIGTERM main "$@"