#!/bin/bash # Part of SMLinux distribution # Script to generate HTML tables containing package build summary for given # section directories # Absolute path to original build logs BUILDLOGPATH="/root/buildlogs" if [ "$SM_ARCH" = "aarch64" ] ; then ARCHDESC="built for ARM64 i.e. Raspberry Pi 3 64bit or higher" elif [ "$SM_ARCH" = "x86_64" ] ; then ARCHDESC="built for x86_64" fi # Function to generate usage options genusage() { cat << EOF ${0##*/} is a tool to generate HTML, TXT report files and databases from build logs. It first moves the build logs to the destination build directory and then generates HTML and TXT files depending on the SECTION NAME as first argument and SMLinux version number passed as second argument. For databases it uses sqlite3 and stores the database in $HOME This program takes three arguments. Usage: ${0##*/} [ -h/ | | Example: ${0##*/} base 1.0 x86_64 Options: -h Display this help screen. OR Pass name of the section directory to generate reports from. Pass the SMLinux version number Pass CPU architecture (x86_64 or aarch64) EOF } # If/else to check if first argument is set. IF it isn't, invoke genusage # function and exit if [ -z "$1" ] ; then genusage exit 0 elif [ "$1" = "-h" ] || [ "$1" = "-help" ] || [ "$1" = "--help" ] ; then genusage exit 0 elif [ -n "$1" ] && [ -d "$BUILDLOGPATH/$1" ] ; then SECTION="$1" else echo "'"$BUILDLOGPATH"' does not have directory by the name of '"$1"'" exit 1 fi # Define $SM_SMLVER, i.e. the smlinux version from the third user-provided argument. if [ -n "$2" ] ; then SM_SMLVER="$2" else echo "Kindly pass SMLinux version number as a second argument. Exiting!" exit 1 fi if [ -n "$3" ] ; then SM_ARCH="$3" else echo "Kindly pass CPU architecture as a third argument. Exiting!" exit 1 fi # Define path to source code SOURCEPATH="/root/smlinux/smlinux-$SM_SMLVER/source/$SECTION/" # Define path to packages PACKAGEPATH="/root/smlinux/smlinux-$SM_SMLVER/packages/$SM_ARCH/$SECTION" # Define directory path where you want to place the generated HTML file in FINALPATH="/root/reports/smlinux-$SM_SMLVER" # Define directory path where TXT reports will be stored FINALTXTRPATH="$FINALPATH/txt/$SM_ARCH/$SECTION" # Define tarball directory TARBALLPATH="$FINALPATH/tarballs/$SM_ARCH/$SECTION/smlinux-$SECTION-$SM_ARCH" # Define database file 1 DBFILE="/root/filepkgsearch.db" DISCARDFILES=( README COPYING LICENSE LICENCE SMBuild CHANGES TODO AUTHORS \ ChangeLog THANKS ABOUT-NLS CHANGELOG COPYRIGHT FAQ THANKS NEWS INSTALL \ doinst.sh slack-desc slack-required "\.txt" "\.info" "\.gz" "\.url" "\.test" "\.m4" "\.md" "\.cmake" "\.tex" "\.xml" "\.jpg" "\.css" "\.pyo" "\.pyc" \ "\.gif" "\.rgba" "\.icc" "\.svg" "\.page" "\.js" "\.ps" "\.strings" "\.c" \ "\.cxx" "\.cpp" "\.htm" "\.html" "\.mo" "\.po" "\.png" "\.page" "\.js" ) inarray() { local n=$1 h shift for h ; do [[ $n = "$h" ]] && return done return 1 } # Don't populate the database with files from these packages IGNOREPACKAGES=( "boost" "kernel-source" "adwaita-icon-theme" "faenza-icon-theme" \ "cmake" "cython" "docbook" "guile" "iso-codes" "vim" "gnome-themes-extra" "aisleriot" "dia" \ "gimp" "xfwm4-themes" "xfce4-panel" "mariadb" ) # Create essential directories mkdir -p $FINALTXTRPATH $TARBALLPATH # Enter build log directory cd $BUILDLOGPATH/$SECTION # Now that we are inside the build log directory, check if the package build # log exists in the final build log directory, and if it doesn't, copy it # from here. for PACKAGELOGFILE in *-$SM_ARCH.log.txt ; do # First rsync all package log files into the tarball path if [ ! -f "$TARBALLPATH"/"$PACKAGELOGFILE" ] ; then rsync "$PACKAGELOGFILE" "$TARBALLPATH/" # Then if $PACKAGELOGFILE does not exist in $FINALTXTRPATH, rsync the # logfiles into it if [ ! -f "$FINALTXTRPATH/$PACKAGELOGFILE" ] ; then echo "Copying $PACKAGELOGFILE from $BUILDLOGPATH/$SECTION into $FINALTXTRPATH..." rsync "$PACKAGELOGFILE" "$FINALTXTRPATH/" fi fi done # Copy the section build log file too as it contains the section build tie if [ ! -f "$FINALTXTRPATH"/"$SECTION-$SM_ARCH".log.txt ] ; then rsync "$BUILDLOGPATH/$SECTION-$SM_ARCH.log.txt" \ "$FINALTXTRPATH/$SECTION-$SM_ARCH.log.txt" fi SECTIONBUILDFILE="$FINALTXTRPATH/$SECTION-$SM_ARCH.log.txt" #TOTALSECTIONTIME="$(grep -w "Section build time" $SECTIONBUILDFILE | awk '{$1=$2=$3=$4=$5="" ; print $0}' | sed 's/ //g' )" TOTALSECTIONTIME="$(grep -w "Section build time" $SECTIONBUILDFILE | awk '{$1=$2=$3=$4=$5="" ; print $0}' | sed 's/ //' )" # Discard SECTIONBUILDFILE since it's too huge rm -f $SECTIONBUILDFILE # Enter $FINALTXTRPATH for getting RAM usage cd $FINALTXTRPATH ##### FOR NOW, manually echo 0 into /tmp/COUNTNUM if adding multiple sections. And remember to delete /tmp/COUNTNUM at the end. # We use 'for f in base xorg gtk extra net xfce ; do ./genreports $f 1.0 aarch64 ; done' to add multiple sections, and if we # uncomment echo "0" line , we'll toss out the COUNTNUM file when the individual section is done. We certainly don't want that to happen # because we need ID uniqueness. # Uncomment this if adding only one section. #rm -fv /tmp/COUNTNUM #echo "0" > /tmp/COUNTNUM #rm -fv "$DBFILE" # Create basic table for DBFILE sqlite3 "$DBFILE" 'CREATE TABLE IF NOT EXISTS pkgnames (pkg_id INTEGER PRIMARY KEY, pkg_name varchar(25), pkg_ver varchar(25), pkg_tag varchar(10), pkg_section varchar(20), pkg_arch varchar(10), sm_ver varchar(5));' sqlite3 "$DBFILE" 'CREATE TABLE IF NOT EXISTS filelist (file_id INTEGER, filepath TEXT NOT NULL, filename TEXT NOT NULL, FOREIGN KEY (file_id) REFERENCES pkgnames (pkg_id));' sqlite3 "$DBFILE" 'CREATE TABLE IF NOT EXISTS pkgdeps (pkg_did INTEGER, depname TEXT NOT NULL, FOREIGN KEY (pkg_did) REFERENCES pkgnames (pkg_id));' sqlite3 "$DBFILE" 'create table IF NOT EXISTS bldstats ( pkg_uid INTEGER, pkg_uname varchar(25), pkg_uver varchar(25), pkg_utag varchar(10), pkg_usection varchar(20), pkg_uarch varchar(10), sm_uver varchar(5), bld_time varchar(25), pkg_contents varchar(100), src_size varchar(100), inst_size varchar(100), up_url varchar(200), FOREIGN KEY (pkg_uid) REFERENCES pkgnames (pkg_id));' #sqlite3 "$DBFILE" 'create table IF NOT EXISTS sectionbuildtime ( pkg_section varchar(20), pkg_arch varchar(10), sm_ver varchar(5), totalbuildtime varchar(15) );' # Loop through any .log files we can find inside the final section log directory for LOGFILE in *.log.txt ; do # Discard distcc arguments sed -i '/Distcc Args:/d' $LOGFILE if [ "$LOGFILE" != "$SECTION.log.txt" ] ; then echo "Processing log file $LOGFILE for individual database output..." SQLCOUNT0="$(cat /tmp/COUNTNUM)" SQLCOUNT="$(( $SQLCOUNT0 + 1 ))" echo "$SQLCOUNT" > /tmp/COUNTNUM cat /tmp/COUNTNUM # Get package name # cut out any white spaces using https://linuxhint.com/trim_string_bash/ # and sed 's/ //g'. # Package name PACKAGENAME="$(tail -n 30 $LOGFILE | grep -w "PACKAGE" | awk -F"'" '{print $2}')" # Get package version PACKAGEVERSION="$(tail -n 30 $LOGFILE | grep -w "PACKAGE" | awk -F"'" '{print $4}')" # Get package tag PACKAGETAG="$(tail -n 30 $LOGFILE | grep -w "PACKAGE" | awk -F"'" '{print $6}')" # Get total time TOTALTIME="$(tail -n 30 $LOGFILE | grep -w "Total Time:" | awk '{$1=$2="" ; print $0}' | sed -e 's@(.*@@g' -e 's/ //')" # Get package contents PACKAGECONTENTS0="$(tail -n 30 $LOGFILE | grep -w "Package Has" | awk '{$1=$2="" ; print $0}' | sed -e 's/ //')" PACKAGECONTENTS="$(tail -n 30 $LOGFILE | grep -w "Package Has" | awk '{$1=$2="" ; print $0}' | sed -e 's@directories@dirs@g' -e 's/ //')" # Get URL of the package's project webpage PACKAGEURLFILE="$SOURCEPATH/$PACKAGENAME/PROJECTURL" if [ -s "$PACKAGEURLFILE" ] ; then URLPATH="$(cat $PACKAGEURLFILE)" elif [ ! -s "$PACKAGEURLFILE" ] && [ -f "$PACKAGEURLFILE" ] ; then URLPATH="$(echo "File PROJECTURL was found but is empty inside $PACKAGENAME source directory")" elif [ ! -s "$PACKAGEURLFILE" ] && [ ! -f "$PACKAGEURLFILE" ] ; then URLPATH="$(echo "File PROJECTURL does not exist inside $PACKAGENAME source directory")" fi PACKAGEDEPSFILE="$SOURCEPATH/$PACKAGENAME/slack-required" DEPSFILE="/tmp/$PACKAGENAME.DEPS" if [ -s "$PACKAGEDEPSFILE" ] ; then DEPSFILE="/tmp/$PACKAGENAME.DEPS" awk '{print $1}' "$PACKAGEDEPSFILE" > "$DEPSFILE" elif [ ! -s "$PACKAGEDEPSFILE" ] && [ -f "$PACKAGEDEPSFILE" ] ; then echo "slack-required-empty" > "$DEPSFILE" elif [ ! -s "$PACKAGEDEPSFILE" ] && [ ! -f "$PACKAGEDEPSFILE" ] ; then echo "slack-required-does-not-exist!" > "$DEPSFILE" fi # Get compressed and uncompressed size of the source code. SOURCESIZE="$(tail -n 30 $LOGFILE | grep -w "Source Size" | awk '{$1=$2="" ; print $0}' | sed -e 's/ //')" # Get compressed and uncompressed size of the package installer size PACKAGESIZE="$(tail -n 30 $LOGFILE | grep -w "Package Size" | awk '{$1=$2="" ; print $0}' | sed -e 's/ //')" # Define section package path for storing list of files per package PACKAGECONTENTDETAILFILE="$FINALTXTRPATH/$PACKAGENAME-$PACKAGEVERSION-$PACKAGETAG-$SECTION-$SM_ARCH.pkgcontents.txt" # Use tar to list the files and output it into PACKAGECONTENTDETAILFILE if [ -f "$PACKAGEPATH"/"$PACKAGENAME-$PACKAGEVERSION-$SM_ARCH-$PACKAGETAG.tlz" ] && \ #[[ ! "${IGNOREPACKAGES[@]}" = "${PACKAGENAME}" ]] ; then ! inarray "$PACKAGENAME" "${IGNOREPACKAGES[@]}" ; then tar tvf "$PACKAGEPATH"/"$PACKAGENAME-$PACKAGEVERSION-$SM_ARCH-$PACKAGETAG.tlz" | awk '{print $6}' > "$PACKAGECONTENTDETAILFILE" elif [ ! -f "$PACKAGEPATH"/"$PACKAGENAME-$PACKAGEVERSION-$SM_ARCH-$PACKAGETAG.tlz" ] ; then if [ -f "$PACKAGEPATH"/"$PACKAGENAME-$PACKAGEVERSION-noarch-$PACKAGETAG.tlz" ] && \ #[[ ! "${IGNOREPACKAGES[@]}" =~ "${PACKAGENAME}" ]] ; then ! inarray "$PACKAGENAME" "${IGNOREPACKAGES[@]}" ; then tar tvf "$PACKAGEPATH"/"$PACKAGENAME-$PACKAGEVERSION-noarch-$PACKAGETAG.tlz" | awk '{print $6}' > "$PACKAGECONTENTDETAILFILE" else echo "Installer file $PACKAGEPATH"/"$PACKAGENAME-$PACKAGEVERSION-$SM_ARCH-$PACKAGETAG.tlz does not exist!" echo "Installer for package $PACKAGENAME not found" >> ~/NOTFOUND fi fi # Begin conditional check #if [[ ! "${IGNOREPACKAGES[@]}" =~ "${PACKAGENAME}" ]] && [ -f "$PACKAGECONTENTDETAILFILE" ] ; then if ! inarray "$PACKAGENAME" "${IGNOREPACKAGES[@]}" && [ -f "$PACKAGECONTENTDETAILFILE" ] ; then # Remove empty/blank lines. sed -i '/^$/d' "$PACKAGECONTENTDETAILFILE" for files in ${DISCARDFILES[@]} ; do sed -i "/$files/d" "$PACKAGECONTENTDETAILFILE" done # Remove all lines that have a trailing slash which means that it's a directory sed -i '/\/$/d' "$PACKAGECONTENTDETAILFILE" sqlite3 "$DBFILE" 'INSERT INTO pkgnames ( pkg_id, pkg_name, pkg_ver, pkg_tag, pkg_section, pkg_arch, sm_ver ) VALUES ( '"'$SQLCOUNT'"', '"'$PACKAGENAME'"', '"'$PACKAGEVERSION'"', '"'$PACKAGETAG'"', '"'$SECTION'"', '"'$SM_ARCH'"', '"'$SM_SMLVER'"' );' while IFS= read -r line do FULLPATH="$(echo $line)" JUSTNAME="$(basename $line)" sqlite3 "$DBFILE" 'INSERT INTO filelist (file_id, filepath, filename) VALUES ('"'$SQLCOUNT'"', '"'$FULLPATH'"', '"'$JUSTNAME'"' );' done < "$PACKAGECONTENTDETAILFILE" while IFS= read -r line do DEPNAME="$(echo $line)" sqlite3 "$DBFILE" 'INSERT INTO pkgdeps (pkg_did, depname) VALUES ('"'$SQLCOUNT'"', '"'$DEPNAME'"' );' done < "$DEPSFILE" rm -f $DEPSFILE # We don't want this in the above loop sqlite3 "$DBFILE" 'INSERT INTO bldstats ( pkg_uid, pkg_uname, pkg_uver, pkg_utag, pkg_usection, pkg_uarch, sm_uver, bld_time, pkg_contents, src_size, inst_size, up_url ) VALUES ( '"'$SQLCOUNT'"', '"'$PACKAGENAME'"', '"'$PACKAGEVERSION'"', '"'$PACKAGETAG'"', '"'$SECTION'"', '"'$SM_ARCH'"', '"'$SM_SMLVER'"', '"'$TOTALTIME'"','"'$PACKAGECONTENTS'"', '"'$SOURCESIZE'"', '"'$PACKAGESIZE'"', '"'$URLPATH'"' );' fi # We'll grab $PACKAGECONTENTDETAILFILE for our tarball #if [[ ! "${IGNOREPACKAGES[@]}" =~ "${PACKAGENAME}" ]] ; then if ! inarray "$PACKAGENAME" "${IGNOREPACKAGES[@]}" ; then cp $PACKAGECONTENTDETAILFILE $TARBALLPATH/ fi fi done #sqlite3 "$DBFILE" 'INSERT INTO sectionbuildtime ( pkg_section, pkg_arch, sm_ver, totalbuildtime ) values ( '"'$SECTION'"', '"'$SM_ARCH'"', '"'$SM_SMLVER'"', '"'$TOTALSECTIONTIME'"' );' # Generate TXT stuff echo "Generating summary file in TXT format..." # Autodefine $TXTFILE TXTFILE="$(echo $FINALTXTRPATH/smlinux-$SECTION-$SM_ARCH.txt)" # Enter into $BUILDLOGPATH/$SECTION cd $BUILDLOGPATH/$SECTION cat << EOF > $TXTFILE SMLinux Cumulative Build Report for '$SECTION' section packages This TXT report was generated on $(date --rfc-email) from package build log files Total Section Build Time was $TOTALSECTIONTIME Section directory '$SECTION' has $(ls | wc -l) packages $ARCHDESC EOF printf "| %-40s | %-12s | %-15s | %-40s | %-12s |\n" "Package Name" "Compile Time" "RAM / Swap Used" "Package Contents" "Package Size" >> $TXTFILE # cd into $FINALTXTRPATH's section directory where we can find our stuff # Loop through any .log files we can find cd $FINALTXTRPATH for LOGFILE in *.log.txt ; do echo "Processing log file $LOGFILE for TXT output..." if [ "$LOGFILE" != "$SECTION.log.txt" ] ; then # Remove white spaces and get package names # https://linuxhint.com/trim_string_bash/ PACKAGENAME="$(tail -n 30 $LOGFILE | grep -w "PACKAGE" | awk -F"'" '{print $2}' | sed -e "s@'@@g")" # Get package version PACKAGEVERSION="$(tail -n 30 $LOGFILE | grep -w "PACKAGE" | awk -F"'" '{print $4}')" # Get total time #TOTALTIME="$(tail -n 30 $LOGFILE | grep -w "Total Time:" | awk '{$1=$2="" ; print $0}' | sed -e 's@(.*@@g' -e 's/ //g')" TOTALTIME="$(tail -n 30 $LOGFILE | grep -w "Total Time:" | awk '{$1=$2="" ; print $0}' | sed -e 's@(.*@@g' -e 's/ //')" # Get package contents PACKAGECONTENTS="$(tail -n 30 $LOGFILE | grep -w "Package Has" | awk '{$1=$2="" ; print $0}' | sed -e 's@directories@dirs@g' -e 's/ //')" # Get final package size FINALSIZE="$(tail -n 30 $LOGFILE | grep -w "Package Size" | awk '{print $6}')" printf "| %-40s | %-12s | %-15s | %-40s | %-12s |\n" "$PACKAGENAME $PACKAGEVERSION" "$TOTALTIME" "$PACKAGECONTENTS" "$FINALSIZE" >> $TXTFILE fi done echo "...done" # Tarball related stuff again. We waited for TXTFILE to be formed. Now copy # it over into $TARBALLPATH echo "Generating smlinux-$SECTION.tar.gz inside the parent directory of $TARBALLPATH..." cp $TXTFILE $TARBALLPATH/ cd $TARBALLPATH/.. tar czf smlinux-$SECTION-$SM_ARCH.tar.gz smlinux-$SECTION-$SM_ARCH # Discard the directory if [ "$?" = "0" ] ; then rm -rf smlinux-$SECTION-$SM_ARCH echo "...done" exit 0 else echo "Failed to generate smlinux-$SECTION-$SM_ARCH.tar.gz. Exiting!" exit 1 fi