diff options
Diffstat (limited to 'src/deb.sh')
-rwxr-xr-x | src/deb.sh | 333 |
1 files changed, 333 insertions, 0 deletions
diff --git a/src/deb.sh b/src/deb.sh new file mode 100755 index 0000000..1535bf2 --- /dev/null +++ b/src/deb.sh @@ -0,0 +1,333 @@ +#!@@SHELL@@ +# +# DEB - Download, Edit, Build! +# src/deb.sh +# Main program script. +# +# Copyright (C) 2012 Patrick "P. J." McDermott +# +# 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 <http://www.gnu.org/licenses/>. + +COMMANDS='init config update download edit builddsc' +CONFIG_NAMES='mirror distribution component remote buildcmd' + +main() +{ + SCRIPT_NAME="${0}" + + if [ ${#} -lt 1 ]; then + print_usage >&2 + exit 1 + fi + + COMMAND_NAME="${1}" + shift + + if ! echo " ${COMMANDS} " | grep " ${COMMAND_NAME} " > /dev/null 2>&1; then + print_usage >&2 + exit 1 + fi + + CWD="${PWD}" + + cmd_run ${@} +} + +print_usage() +{ + cat <<EOF +Usage: ${SCRIPT_NAME} <command> <arguments> + +Where <command> is one of: + init Initialize a DEB work area + config Get or set a configuration value + update Update the list of source packages + download Download a source package + edit Unpack a source package for editing + builddsc Build an edited source package and debdiff + build Build binary packages + push Synchronize changes with a remote tree +EOF +} + +error() +{ + msg="${1}" + shift + printf "Error: ${msg}\n" ${@} + exit 2 +} + +find_deb_dir() +{ + until [ "${PWD}" = '/' ]; do + if [ -d '.deb' ]; then + DEB_DIR="${PWD}/.deb" + DEB_TREE="${PWD}" + return 0 + fi + cd .. + done + [ ${#} -ge 1 ] && "${1}" && error 'No DEB work area found' + return 1 +} + +config_load() +{ + . "${DEB_DIR}/config" +} + +config_save() +{ + for name in ${CONFIG_NAMES}; do + printf "CONFIG_%s='%s'\n" "${name}" "$(eval echo \$\{CONFIG_${name}\})" + done > "${DEB_DIR}/config" +} + +cmd_run() +{ + "cmd_${COMMAND_NAME}" ${@} +} + +cmd_init() +{ + find_deb_dir false || { + DEB_DIR="${CWD}/.deb" + DEB_TREE="${CWD}" + } + + CONFIG_mirror='http://ftp.debian.org/debian' + CONFIG_distribution='sid' + CONFIG_component='main' + CONFIG_buildcmd='sbuild --build=%mirror% -d %distribution% %opts% %dsc%' + + cd "${DEB_TREE}" + if [ -d .deb ]; then + rm -Rf .deb dsc build pkgs work + mkdir .deb dsc build pkgs work + config_save + printf 'Reinitialized DEB work area in %s.\n' "${DEB_TREE}" + else + mkdir .deb dsc build pkgs work + config_save + printf 'Initialized DEB work area in %s.\n' "${DEB_TREE}" + fi +} + +cmd_config() +{ + find_deb_dir + config_load + + if [ ${#} -ne 1 -a ${#} -ne 2 ]; then + cat >&2 <<EOF +Usage: ${SCRIPT_NAME} ${COMMAND_NAME} <name> [<value>] +EOF + exit 1 + fi + + echo " ${CONFIG_NAMES} " | grep " ${1} " > /dev/null 2>&1 || \ + error 'Invalid configuration name "%s"' "${1}" + + config_name="CONFIG_${1}" + if [ ${#} -eq 1 ]; then + printf '%s\n' "$(eval echo \$\{${config_name}\})" + else + eval "${config_name}=${2}" + config_save + fi +} + +cmd_update() +{ + find_deb_dir + config_load + + if [ ${#} -ne 0 ]; then + cat >&2 <<EOF +Usage: ${SCRIPT_NAME} ${COMMAND_NAME} +EOF + exit 1 + fi + + printf 'Downloading Sources file...\n' + rm -f "${DEB_DIR}/.Sources.bz2" + sources="${CONFIG_mirror}/dists/${CONFIG_distribution}/${CONFIG_component}/source" + sources="${sources}/Sources.bz2" + curl -o "${DEB_DIR}/.Sources.bz2" "${sources}" || error 'Cannot download Sources file' + + printf '\nDecompressing Sources file...\n' + rm -f "${DEB_DIR}/.Sources" + bunzip2 "${DEB_DIR}/.Sources.bz2" || error 'Cannot decompress Sources file' + + total=$(grep ^Package: "${DEB_DIR}/.Sources" | wc -l) + count=0 + + printf '\nReading Sources file...\n' + > "${DEB_DIR}/dsc.list~" + while read line; do + if [ -z "${line}" ]; then + printf '%s %s\n' "${pkg}" "${dir}/${dsc}" >> "${DEB_DIR}/.dsc.list~" + count=$(($count + 1)) + printf "\rFound %${#total}d/%d source packages.%s" \ + "${count}" "${total}" \ + "$([ ${count} -eq ${total} ] && printf ' ' || printf '..')" + continue + fi + if [ "${line#Package: }" != "${line}" ]; then + pkg="${line#Package: }" + continue + fi + if [ "${line#Directory: }" != "${line}" ]; then + dir="${line#Directory: }" + continue + fi + if [ "${line#Files:}" != "${line}" ]; then + while read sum size file; do + if [ "${file%.dsc}" != "${file}" ]; then + dsc="${file}" + break + fi + done + continue + fi + done < "${DEB_DIR}/.Sources" + printf '\n' + + rm "${DEB_DIR}/.Sources" + mv "${DEB_DIR}/.dsc.list~" "${DEB_DIR}/dsc.list" + + printf '\nDone.\n' +} + +cmd_download() +{ + find_deb_dir + config_load + + if [ ${#} -ne 1 ]; then + cat >&2 <<EOF +Usage: ${SCRIPT_NAME} ${COMMAND_NAME} <pkg> +EOF + exit 1 + fi + + [ ! -f "${DEB_DIR}/dsc.list" ] && error 'No source package list found' + + pkg="${1}" + + line="$(grep "^${pkg} " "${DEB_DIR}/dsc.list")" || \ + error 'Package "%s" not found' "${pkg}" + dsc="${line#${pkg} }" + + mkdir -p "${DEB_TREE}/dsc/${pkg}" + cd "${DEB_TREE}/dsc/${pkg}" + + printf 'Downloading source package "%s"...\n' "${pkg}" + dget -d "${CONFIG_mirror}/${dsc}" || error 'Cannot download source package' + + printf '\nDone.\n' +} + +cmd_edit() +{ + find_deb_dir + config_load + + if [ ${#} -ne 1 ]; then + cat >&2 <<EOF +Usage: ${SCRIPT_NAME} ${COMMAND_NAME} <pkg> +EOF + exit 1 + fi + + [ ! -f "${DEB_DIR}/dsc.list" ] && error 'No source package list found' + + pkg="${1}" + + line="$(grep "^${pkg} " "${DEB_DIR}/dsc.list")" || \ + error 'Package "%s" not found' "${pkg}" + dsc="${line#${pkg} }" + dsc="${dsc##*/}" + + [ ! -f "${DEB_TREE}/dsc/${pkg}/${dsc}" ] && \ + error 'Source package "%s" not downloaded' "${pkg}" + + ver="${dsc%.dsc}" + ver="${ver#${pkg}_}" + ver="${ver%-*}" + + mkdir -p "${DEB_TREE}/work/${pkg}" + dpkg-source -x "${DEB_TREE}/dsc/${pkg}/${dsc}" \ + "${DEB_TREE}/work/${pkg}/${pkg}-${ver}" +} + +cmd_builddsc() +{ + find_deb_dir + config_load + + if [ ${#} -ne 1 ]; then + cat >&2 <<EOF +Usage: ${SCRIPT_NAME} ${COMMAND_NAME} <pkg> +EOF + exit 1 + fi + + [ ! -f "${DEB_DIR}/dsc.list" ] && error 'No source package list found' + + pkg="${1}" + + line="$(grep "^${pkg} " "${DEB_DIR}/dsc.list")" || \ + error 'Package "%s" not found' "${pkg}" + dsc="${line#${pkg} }" + dsc="${dsc##*/}" + + ver="${dsc%.dsc}" + ver="${ver#${pkg}_}" + ver="${ver%-*}" + + ver="$(dpkg-parsechangelog \ + -l"${DEB_TREE}/work/${pkg}/${pkg}-${ver}/debian/changelog" | \ + sed -n 's/^Version: \(.*\)$/\1/p')" + base="${pkg}_${ver}" + ver="${ver%-*}" + rev="${ver#${ver}}" + rev="${rev#-}" + + [ ! -d "${DEB_TREE}/work/${pkg}/${pkg}-${ver}" ] && \ + error 'Source package "%s" not unpacked for editing' "${pkg}" + + cd "${DEB_TREE}/work/${pkg}/${pkg}-${ver}" + dpkg-buildpackage -S -us -uc + + cd .. + rm -Rf "${DEB_TREE}/pkgs/${pkg}" + mkdir -p "${DEB_TREE}/pkgs/${pkg}" + + # XXX: This assumes source format 3.0. + mv "${base}.dsc" "${base}_source.changes" "${DEB_TREE}/pkgs/${pkg}" + if [ -n "${rev}" ]; then + cp -p "${pkg}_${ver}.orig.tar.gz" "${DEB_TREE}/pkgs/${pkg}" + mv "${base}.diff.gz" "${DEB_TREE}/pkgs/${pkg}" + else + mv "${base}.tar.gz" "${DEB_TREE}/pkgs/${pkg}" + fi + + debdiff \ + "${DEB_TREE}/dsc/${pkg}/${dsc}" "${DEB_TREE}/pkgs/${pkg}/${base}.dsc" \ + > "${DEB_TREE}/pkgs/${pkg}/${pkg}.debdiff" +} + +main ${@} |