#!@@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()
{
_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
[ ! -f "${DEB_DIR}/dsc.list" ] && error 'No source package list found'
pkg="${1}"
dscurl="$(get_dsc_url "${pkg}")"
rm -Rf "${DEB_TREE}/dsc/${pkg}"
mkdir -p "${DEB_TREE}/dsc/${pkg}"
cd "${DEB_TREE}/dsc/${pkg}"
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
[ ! -f "${DEB_DIR}/dsc.list" ] && error 'No source package list found'
pkg="${1}"
dsc="$(get_dsc_name "${pkg}")"
[ ! -f "${DEB_TREE}/dsc/${pkg}/${dsc}" ] && \
error 'Source package "%s" not downloaded' "${pkg}"
ver="${dsc%.dsc}"
ver="${ver#${pkg}_}"
ver="${ver%-*}"
rm -Rf "${DEB_TREE}/work/${pkg}"
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
exit 1
fi
[ ! -f "${DEB_DIR}/dsc.list" ] && error 'No source package list found'
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
cp -p "${file}" "${DEB_TREE}/pkgs/${pkg}"
done
fi
done < "${pkgverrev}.dsc"
cp -p "${pkgverrev}.dsc" "${pkgverrev}_source.changes" "${DEB_TREE}/pkgs/${pkg}"
# Generate patch.
debdiff \
"${DEB_TREE}/dsc/${pkg}/${dsc}" "${DEB_TREE}/pkgs/${pkg}/${base}.dsc" \
> "${DEB_TREE}/pkgs/${pkg}/${pkg}.debdiff"
}
cmd_push()
{
find_deb_dir
config_load
if [ ${#} -ne 0 ]; then
cat >&2 <