Files
scratchpkg/buildpkg
2018-06-04 22:25:03 +08:00

697 lines
16 KiB
Bash
Executable File

#!/bin/bash
export LC_ALL=C
. /usr/share/scratchpkg/functions || exit 1
backupconf() {
for bkp in ${backup[@]}; do
if [ ! -f $bkp ]; then
msgerr "File '$bkp' not exist!"
exit 1
else
mv $bkp $bkp.spkgnew
fi
done
}
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 "$source" -a -z "$md5sum" ]; then
msgerr "md5sum=() is empty, please provide it."
return 1
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() {
if [ "$UID" != 0 ]; then
msgerr "You must build package as root, or use fakeroot."
exitscript1
fi
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 "Build successfully."
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
if [ "${#backup[@]}" -gt 0 ]; then
backupconf
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 "$noextract" ] && echo "noextract = $noextract" >> .pkginfo
msg2 "Packaging..."
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 failed."
if [ -f $PACKAGE_DIR/$PKGNAME ]; then
rm $PACKAGE_DIR/$PKGNAME
fi
exitscript1
else
pkgsize="$(ls -lh $PACKAGE_DIR/$PKGNAME | awk '{print $5}')"
if [ "$VERBOSE" ]; then
$EXTPROG -t -v -f $PACKAGE_DIR/$PKGNAME
fi
msg "Successfully created package ${GREEN}$PKGNAME${CRESET}. (${pkgsize})"
fi
case $PREINSTALL_STATUS in
OK) msg2 "preinstall : ${GREEN}OK${CRESET}" ;;
KO) msg2 "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
MSDEP+=($dep)
fi
done
for makedep in ${makedepends[@]}; do
if [ ! -d $INDEX_DIR/$makedep ]; then
MSMKDEP+=($makedep)
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[@]}"
}
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> <arguments> ]
Options:
-i, --install install package into system
-u, --upgrade upgrade package
-r, --reinstall reinstall package
-d, --no-dep skip dependency check
-c, --ignore-conflict ignore conflict when installing package
-v, --verbose verbose install process
-f, --force-rebuild rebuild package
-m, --ignore-mdsum skip md5sum checking
-g, --genmdsum generate md5sum
-o, --download-only download only source file
-e, --extract-only extract only source file
-w, --keep-work keep working directory
-h, --help show this help message
--srcdir=<path> override directory path for sources
--pkgdir=<path> override directory path for compiled package
--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 configuration file when upgrading package
--redownload re-download source file
Example:
buildpkg -irw 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
}
extract_opt() {
for opt in $@; do
case $opt in
--*=*) OPTS+=($opt) ;;
--*) OPTS+=($opt) ;;
-*) for (( i=1; i<${#opt}; i++ )); do OPTS+=(-${opt:$i:1}); done ;;
*) OPTS+=($opt) ;;
esac
done
echo "${OPTS[@]}"
}
parse_opts() {
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) ;;
-d | --no-dep) IGNORE_DEP=yes; OPTS+=($1) ;;
-c | --ignore-conflict) OPTS+=($1) ;;
-v | --verbose) VERBOSE=yes; OPTS+=($1) ;;
-f | --force-rebuild) FORCE_REBUILD=yes ;;
-m | --skip-mdsum) IGNORE_MDSUM=yes ;;
-g | --genmdsum) UPDATE_MDSUM=yes ;;
-o | --download) DOWNLOAD_ONLY=yes ;;
-e | --extract) EXTRACT_ONLY=yes ;;
-w | --keep-work) KEEP_WORK=yes ;;
-h | --help) SHOWHELP=yes ;;
--no-preinstall) NO_PREINSTALL=yes; OPTS+=($1) ;;
--no-postinstall) OPTS+=($1) ;;
--no-preupgrade) OPTS+=($1) ;;
--no-postupgrade) OPTS+=($1) ;;
--no-color) NOCOLOR=yes; OPTS+=($1) ;;
--no-backup) OPTS+=($1) ;;
--redownload) REDOWNLOAD_SOURCE=yes ;;
--check-source) SOURCE_CHECK=yes ;;
--srcdir=*) SOURCE_DIR="${1#*=}" ;;
--pkgdir=*) PACKAGE_DIR="${1#*=}" ;;
*) msg "Invalid option! ($1)"; exit 1 ;;
esac
shift
done
}
main() {
parse_opts $(extract_opt $@)
# disable colour
if [ "$NOCOLOR" ]; then
nocolor
fi
# show help page
if [ "$SHOWHELP" ]; then
help
exit 0
fi
if [ -z "$SOURCE_DIR" ]; then
msgerr "Option '--srcdir=' need argument (path)"
exit 1
elif [ -z "$PACKAGE_DIR" ]; then
msgerr "Option '--pkgdir=' need argument (path)"
exit 1
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
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 "$@"