#!@@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 . COMMANDS='init config update download edit builddsc push' 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 < Where 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" ${@} >&2 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" } get_dsc_url() { [ ! -f "${DEB_DIR}/dsc.list" ] && error 'No source package list found' _pkg="${1}" _dscurl=$(grep "^${_pkg} " "${DEB_DIR}/dsc.list" | tail -n 1) || \ error 'Package "%s" not found' "${pkg}" echo "${_dscurl#${_pkg} }" } get_dsc_name() { _pkg="${1}" _dscurl="$(get_dsc_url "${pkg}")" echo "${_dscurl##*/}" } prompt_bool() { _def="${1}" _prompt="${2}" shift 2 [ "${_def}" = y ] && _yn='[Y/n]' || _yn='[y/N]' printf "${_prompt} ${_yn} " $@ read _val [ "${_val}" = y ] && return 0 [ "${_val}" = n ] && return 1 [ "${_def}" = y ] && return 0 || return 1 } 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 prompt_bool n 'DEB work area exists. Reinitialize?' || exit rm -Rf .deb dsc builds pkgs work mkdir .deb dsc builds pkgs work config_save printf 'Reinitialized DEB work area in %s.\n' "${DEB_TREE}" else mkdir .deb dsc builds 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 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 < "${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 exit 1 fi pkg="${1}" # Get URL to DSC file. dscurl="$(get_dsc_url "${pkg}")" # Create clean destination for source package files. rm -Rf "${DEB_TREE}/dsc/${pkg}" mkdir -p "${DEB_TREE}/dsc/${pkg}" cd "${DEB_TREE}/dsc/${pkg}" # Download source package files. printf 'Downloading source package "%s"...\n' "${pkg}" dget -d "${CONFIG_mirror}/${dscurl}" || error 'Cannot download source package' printf '\nDone.\n' } cmd_edit() { find_deb_dir config_load if [ ${#} -ne 1 ]; then cat >&2 < EOF exit 1 fi pkg="${1}" # Get name of DSC file. dsc="$(get_dsc_name "${pkg}")" # Ensure that source package is downloaded. [ ! -f "${DEB_TREE}/dsc/${pkg}/${dsc}" ] && \ error 'Source package "%s" not downloaded' "${pkg}" ver="${dsc%.dsc}" ver="${ver#${pkg}_}" ver="${ver%-*}" # Check if source package is already unpacked. if [ -d "${DEB_TREE}/work/${pkg}/${pkg}-${ver}" ]; then prompt_bool n \ 'Source package "%s" already unpacked for editing. Remove?' \ "${pkg}" || exit fi # Create clean work area for source package. rm -Rf "${DEB_TREE}/work/${pkg}" mkdir -p "${DEB_TREE}/work/${pkg}" # Unpack source package. 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 exit 1 fi pkg="${1}" # Find source package in internal list. dsc="$(get_dsc_name "${pkg}")" # Ensure that source package is unpacked. [ ! -d "${DEB_TREE}/work/${pkg}/${pkg}-*" ] && \ error 'Source package "%s" not unpacked for editing' "${pkg}" # Get source package version from internal list. oldverrev="${dsc%.dsc}" oldverrev="${oldverrev#${pkg}_}" # Get source package version from work area. verrev="$(dpkg-parsechangelog \ -l"${DEB_TREE}/work/${pkg}/${pkg}-*/debian/changelog" | \ sed -n 's/^Version: \(.*\)$/\1/p')" pkgverrev="${pkg}_${verrev}" ver="${verrev%-*}" rev="${verrev#*-}" # Ensure that an NMU was made. dpkg --compare-versions "${verrev}" gt "${oldverrev}" || \ error 'Version not incremented' # Build source package. cd "${DEB_TREE}/work/${pkg}/${pkg}-*" dpkg-buildpackage -S -us -uc # Make a clean source package destination. cd .. rm -Rf "${DEB_TREE}/pkgs/${pkg}" mkdir -p "${DEB_TREE}/pkgs/${pkg}" # Copy source package files. while read line; do if [ "${line#Files:}" != "${line}" ]; then while read sum size file; do case "${file}" in *.orig.tar.*) cp -p "${file}" "${DEB_TREE}/pkgs/${pkg}" ;; *) mv "${file}" "${DEB_TREE}/pkgs/${pkg}" done fi done < "${pkgverrev}.dsc" mv "${pkgverrev}.dsc" "${pkgverrev}_source.changes" "${DEB_TREE}/pkgs/${pkg}" # Generate patch. debdiff \ "${DEB_TREE}/dsc/${pkg}/${dsc}" "${DEB_TREE}/pkgs/${pkg}/${pkgverrev}.dsc" \ > "${DEB_TREE}/pkgs/${pkg}/${pkg}.debdiff" } cmd_push() { find_deb_dir config_load if [ ${#} -ne 0 ]; then cat >&2 <