#!/bin/bash XI_ROOT=$(pwd) PKGS_OUTPUT=$XI_ROOT/xipkgs PRIV_KEY=$XI_ROOT/keychain/xi.pem ERROR="\033[0;31m" INFO="\033[0;34m" PASS="\033[0;32m" NEUTRAL="\033[0;33m" RESET="\033[0m" MAKEFLAGS="-j11" alias make="make $MAKEFLAGS" extract () { FILE=$1 echo extracting $FILE case "${FILE#*.}" in "tar.gz" ) tar -zxf $FILE ;; "tar.lz" ) tar --lzip -xf "$FILE" ;; "zip" ) unzip $FILE ;; * ) tar -xf $FILE ;; esac } pkgname () { echo $(basename $1 .xibuild) } xibuild () { BUILD_FILE=${@: -1} BUILD_HASH=$(md5sum $BUILD_FILE | cut -f1 -d" ") cd $XI_ROOT [[ $# = 0 ]] && usage && return 1 [ ! -f "$BUILD_FILE" ] && echo "$BUILD_FILE not found" && return 1 BUILD_FILE_PATH=$(realpath $BUILD_FILE) clean () { # clean up rm -rf $PKG_BUILD_DIR rmdir $XI_ROOT/tmp > /dev/null 2>&1 } prepare () { echo "Passing missing prepare stage" } build () { printf "\tpassing missing build stage..." } check () { echo "Passing missing check stage" } package () { echo "Passing missing package stage" } BRANCH=HEAD source $BUILD_FILE PKG_NAME=$(pkgname $BUILD_FILE) LOGFILE=$XI_ROOT/logs/$PKG_NAME.log PKG_FILE=$PKGS_OUTPUT/$PKG_NAME.xipkg PKG_BUILD_DIR=$XI_ROOT/tmp/$PKG_NAME PKG_DEST=$XI_ROOT/tmp/$PKG_NAME.package # make sure build dir is clean before starting rm -rf $PKG_BUILD_DIR # make the directories mkdir -p $PKG_BUILD_DIR mkdir -p $PKG_DEST mkdir -p $PKGS_OUTPUT mkdir -p $XI_ROOT/logs date > $LOGFILE echo "Build log for $PKG_NAME from $BUILD_FILE\n" >> $LOGFILE printf "\033[0;36m====> $PKG_NAME.xipkg$RESET\n" | tee -a $LOGFILE cd $PKG_BUILD_DIR # fetch, build then package the package ############ if [ ! -z ${SOURCE+x} ]; then # try get the commit hash for the package if git ls-remote -q $SOURCE &> /dev/null; then VER_HASH=$(git ls-remote $SOURCE $BRANCH ) elif hg identify $SOURCE &> /dev/null; then VER_HASH=$(hg identify $SOURCE) else VER_HASH=$(curl -Ls $SOURCE | md5sum) fi VER_HASH=$(echo $VER_HASH | awk '{ print $1 }') # If we already have this package, don't waste our time if [ -f "$PKG_FILE.info" ] && [ -f "$PKG_FILE" ]; then EXISTING_HASH=$(grep -a "VER_HASH" $PKG_FILE.info | sed "s/VER_HASH=//") echo "Comparing $EXISTING_HASH to $VER_HASH" >> $LOGFILE printf "$INFO\tvalidating commit hash..."; EXISTING_BUILD_HASH=$(md5sum $PKGS_OUTPUT/$PKG_NAME.xibuild | cut -f1 -d" ") if [ "$EXISTING_HASH" = "$VER_HASH" ] && [ "$EXISTING_BUILD_HASH" = "$BUILD_HASH" ]; then printf "$NEUTRAL package exists$RESET\n" echo "exists $PKG_NAME $DESC" >> $REPORT_LOG rm $LOGFILE return; else printf "$NEUTRAL package outdated\n" fi fi printf "$INFO\tfetching package..."; if git ls-remote -q $SOURCE $BRANCH &> /dev/null; then git clone $SOURCE . >> $LOGFILE 2>&1 && printf "$PASS fetched $(du -sh $PKG_BUILD_DIR | awk '{ print $1 }') source\n" || return 1; git checkout $BRANCH >> $LOGFILE 2>&1 elif hg identify $SOURCE &> /dev/null; then hg clone $SOURCE . >> $LOGFILE 2>&1 && printf "$PASS fetched $(du -sh $PKG_BUILD_DIR | awk '{ print $1 }') source\n" || return 1; else DOWNLOADED=$(basename $SOURCE) curl -Ls $SOURCE > $DOWNLOADED extract $DOWNLOADED >> $LOGFILE 2>&1 && printf "$PASS fetched $(du -sh $PKG_BUILD_DIR | awk '{ print $1 }') source\n" || return 1; cd $(ls -d */) fi else SOURCE="none" fi printf "\033[0;34m\tpreparing package...\033[0m"; prepare >> $LOGFILE 2>&1 && printf "$PASS prepared\n" || return 1; printf "$INFO\tbuilding package..."; build >> $LOGFILE 2>&1 && printf "$PASS built\n" || return 1; printf "\033[0;34m\ttesting package...\033[0m"; check >> $LOGFILE 2>&1 && printf "$PASS checked\n" || return 1; printf "\033[0;34m\tpackaging package...\033[0m"; package >> $LOGFILE 2>&1 && printf "$PASS packaged\n" || return 1; # add postinstall script if command -v postinstall > /dev/null; then POSTINSTALL=$(type postinstall | sed '1,3d;$d') if [ ${#POSTINSTALL} != 0 ]; then POST_DIR=$PKG_DEST/var/lib/xipkg/postinstall mkdir -p $POST_DIR echo "#!/bin/sh" > $POST_DIR/$PKG_NAME.sh echo $POSTINSTALL >> $POST_DIR/$PKG_NAME.sh fi fi # go back to root, make things easier cd $XI_ROOT if [ -z "$(ls -A $PKG_DEST)" ] && [ ! $SOURCE = "none" ]; then printf "$FAIL!!!Package is empty!!!$RESET\n" return 1; fi printf "$INFO\tarchiving package..."; tar -C $PKG_DEST -cvzf $PKG_FILE ./ >> $LOGFILE 2>&1 && printf "$PASS archived to $(du -sh $PKG_FILE | awk '{ print $1 }')\n" || return 1; # create info file printf "$INFO\tcreating xipkg.info..."; PKG_INFO=$PKGS_OUTPUT/$PKG_NAME.xipkg.info cp $BUILD_FILE $PKGS_OUTPUT/$PKG_NAME.xibuild echo "" > $PKG_INFO echo "NAME=$PKG_NAME" >> $PKG_INFO echo "DESCRIPTION=$DESC" >> $PKG_INFO echo "PKG_FILE=$PKG_NAME.xipkg" >> $PKG_INFO echo "CHECKSUM=$(md5sum $PKG_FILE | awk '{ print $1 }')" >> $PKG_INFO echo "VER_HASH=$VER_HASH" >> $PKG_INFO echo "SOURCE=$SOURCE" >> $PKG_INFO echo "DATE=$(date)" >> $PKG_INFO echo "DEPS=(${DEPS[*]})" >> $PKG_INFO printf "$INFOsigning..."; # sign the package if [ -f "$PRIV_KEY" ]; then echo "SIGNATURE=" >> $PKG_INFO openssl dgst -sign $PRIV_KEY $PKG_FILE >> $PKG_INFO else echo "SIGNATURE=">> $PKG_INFO echo "unsigned">> $PKG_INFO >&2 printf "$ERROR WARNING! No private key: unsigned packages!\n" fi printf "$PASS signed\n"; printf "$PASS successfully built $PKG_NAME to $(basename $PKG_FILE)$RESET\n" clean echo "new $PKG_NAME $DESC" >> $REPORT_LOG unset SOURCE DESC DEPS install package check return 0 } usage () { cat << EOF usage: $0 [-h] [-o output-dir] [-r working_root] [-k private_key.pem] build_file.xibuild -h display this help message -o set the output dir for the xipkg files (default: $PWD/xipkgs) -r set the working root for all log and tmp files (default: $PWD) -k set the private key used to sign packages (default: $PWD/keychain/xi.pem) EOF } build-all () { FILES=$@ while test $# -gt 0; do case "$1" in "-o" ) shift PKGS_OUTPUT=$PWD/$1 ;; "-r" ) shift XI_ROOT=$PWD/$1 ;; "-k" ) shift PRIV_KEY=$PWD/$1 ;; "-h" ) usage ;; * ) REPORT_LOG=$XI_ROOT/xibuild.report.log BUILD_FILE=$1 if xibuild $BUILD_FILE; then printf "$RESET" else printf "$ERROR error! See log$RESET\n" echo "fail $PKG_NAME $DESC" >> $REPORT_LOG fi cd $XI_ROOT ;; esac shift done } if [ $# -gt 0 ]; then build-all $@ | tee -a xibuild.log else usage; return 1 fi