diff options
author | Aaron Ball <nullspoon@oper.io> | 2018-02-05 08:50:27 -0700 |
---|---|---|
committer | Aaron Ball <nullspoon@oper.io> | 2018-02-05 08:56:11 -0700 |
commit | 0021b9976350a078e3efed10fc36031ac8f73d95 (patch) | |
tree | eb60452a9966e988a29161170e30f259bc4bffdf /pkgself.sh | |
download | pkgself-0021b9976350a078e3efed10fc36031ac8f73d95.tar.gz pkgself-0021b9976350a078e3efed10fc36031ac8f73d95.tar.xz |
Initial commit
Currently packages binary, creates payload index, etc. Installer
executes specified run script and cleans itself up after run.
NOTE: installer-header.sh is not released under any license at this
time, as it is packaged with other people's code. Pkgself.sh is however
GPLv3.
Diffstat (limited to 'pkgself.sh')
-rwxr-xr-x | pkgself.sh | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/pkgself.sh b/pkgself.sh new file mode 100755 index 0000000..8a0d28e --- /dev/null +++ b/pkgself.sh @@ -0,0 +1,147 @@ +#!/usr/bin/env bash +# Pkgself builds self-extracting installers +# Copyright (C) 2018 Aaron Ball <nullspoon@oper.io> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +set -e + +download_src() { + local file + + for src in ${source[@]}; do + # Set the file path buffer for better error messages + # This will store local files verbatim, but remote files will be parsed out + # of their URIs + file="${src}" + + # Download http files + if [ "${src:0:4}" == "http" ] || [ "${src:0:3}" == "ftp" ]; then + file="$(basename ${src})" + if [ ! -f "${file}" ]; then + printf "Downloading %s\n" "${file}" + curl -k -L -q -# "${src}" -o "${file}" + fi + elif [ "${src:0:1}" == "/" ] && [ -f "${src}" ]; then + file="$(basename ${src})" + if [ ! -f "${file}" ]; then + printf "Copying local file '%s'\n" "$(basename ${src})" + cp "${src}" "$(basename ${src})" + fi + elif [ "${src:0:6}" == "ssh://" ]; then + file="$(basename ${src})" + if [ ! -f "${file}" ]; then + printf "Downloading %s\n" "${file}" + scp "${src:6}" "${file}" + fi + fi + + if [ -e "${file}" ]; then + cp -r "${file}" "${PKGSRC}/${file}" + else + printf "Error: Source '%s' does not exist\n" "${file}" + return 1 + fi + done +} + + +main() { + local pkg=${1} + local pkgdir # Path to the parent directory of the Pkgfile + local tmp # Path to the temp directory containing build resource + local output # Path to the output file + + # Get the absolute path to the Pkgfile parent directory + pkgdir="$(cd $(dirname ${pkg}) && pwd)" + # Convert pkg to absolute path + pkg="${pkgdir}/$(basename ${pkg})" + tmp="$(mktemp -d /tmp/builder-XXXXXX)" + export PKGSRC=${tmp}/src + export PKG=${tmp}/pkg + mkdir -p "${PKGSRC}" + mkdir -p "${PKG}" + + # Source and validate the Pkgfile + source ${pkg} + if [ -z "${name}" ]; then + printf "Variable 'name' is required in Pkgfile\n" + return 1 + fi + if [ -z "${version}" ]; then + printf "Variable 'version' is required in Pkgfile\n" + return 1 + fi + if [ -z "${release}" ]; then + printf "Variable 'release' is required in Pkgfile\n" + return 1 + fi + if [ "$(type -t build)" != 'function' ]; then + printf "Function 'build' is required in Pkgfile\n" + return 1 + fi + + # Build the output filename + local output="${pkgdir}/${name}#${version}-${release}.sh" + + # Copy the installer header script into the tmp directory, with the right name + cp install-header.sh "${output}" + # Copy the run script into the tmp dir + install "${pkgdir}/run.sh" "${PKGSRC}/run.sh" + + # Download all the source files (if needed) + cd "${pkgdir}" + for src in ${source[@]}; do + download_src "${src}" + done + + cd "${PKGSRC}" + build + + cd "${tmp}" + + printf "Reticulating splines...\n" + + headsize=$(wc -c < ${output}) + + # Compress and calculate byte size for run.sh + xz -c ${PKGSRC}/run.sh > ${tmp}/run.sh.xz + runsize="$(wc -c < ${tmp}/run.sh.xz)" + + # Compress and calculate byte size for payload + tar -c "$(basename ${PKG})" | xz -v > ${PKG}.tar.xz + payloadsize="$(wc -c < ${PKG}.tar.xz)" + + + # Print space padded values to meet expected character length. + # Expected length: 8 + 8 + 12 + 2 == 30 + # 1. header: 8 byte digits allows a 95 MB header + # 2. run script: 8 byte digits allows a 95 MB run script + # 3. payload: 12 byte digits allows for a 931 GB file + lens="$(printf '%8s %8s %12s' ${headsize} ${runsize} ${payloadsize})" + + # Interpolate chunk lengths + # This space between ( and ) must be 60 chars so as to not change the header + # lenth after interpolation. + sed -i "s/LENS=(.*)/LENS=(${lens})/g" "${output}" + + # Append chunks to output file + cat "${tmp}/run.sh.xz" >> "${output}" + cat "${PKG}.tar.xz" >> "${output}" + + # Cleanup + rm -rf ${tmp} +} + +main ${@} |