summaryrefslogtreecommitdiffstats
path: root/scripts/debsign.sh
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 20:32:59 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 20:32:59 +0000
commit4d57e0a8dab2139a631a21aab862487481548702 (patch)
treef7cea0b9939e2ecb7a301de6c83bada29452046d /scripts/debsign.sh
parentInitial commit. (diff)
downloaddevscripts-upstream.tar.xz
devscripts-upstream.zip
Adding upstream version 2.23.7.upstream/2.23.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rwxr-xr-xscripts/debsign.sh870
1 files changed, 870 insertions, 0 deletions
diff --git a/scripts/debsign.sh b/scripts/debsign.sh
new file mode 100755
index 0000000..15b0dfc
--- /dev/null
+++ b/scripts/debsign.sh
@@ -0,0 +1,870 @@
+#!/bin/sh
+
+# This program is designed to GPG sign .dsc, .buildinfo, or .changes
+# files (or any combination of these) in the form needed for a legal
+# Debian upload. It is based in part on dpkg-buildpackage.
+
+# Debian GNU/Linux debsign. Copyright (C) 1999 Julian Gilbey.
+# Modifications to work with GPG by Joseph Carter and Julian Gilbey
+#
+# 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 2 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/>.
+
+# Abort if anything goes wrong
+set -e
+
+PROGNAME=${0##*/}
+PRECIOUS_FILES=0
+MODIFIED_CONF_MSG='Default settings modified by devscripts configuration files:'
+HAVE_SIGNED=""
+NUM_SIGNED=0
+
+# Temporary directories
+signingdir=""
+remotefilesdir=""
+
+trap cleanup_tmpdir EXIT
+
+# --- Functions
+
+mksigningdir() {
+ if [ -z "$signingdir" ]; then
+ signingdir="$(mktemp -dt debsign.XXXXXXXX)" || {
+ echo "$PROGNAME: Can't create temporary directory" >&2
+ echo "Aborting..." >&2
+ exit 1
+ }
+ fi
+}
+
+mkremotefilesdir() {
+ if [ -z "$remotefilesdir" ]; then
+ remotefilesdir="$(mktemp -dt debsign.XXXXXXXX)" || {
+ echo "$PROGNAME: Can't create temporary directory" >&2
+ echo "Aborting..." >&2
+ exit 1
+ }
+ fi
+}
+
+usage() {
+ echo \
+"Usage: debsign [options] [changes, buildinfo, dsc or commands file]
+ Options:
+ -r [username@]remotehost
+ The machine on which the files live. If given, then a
+ changes file with full pathname (or relative to the
+ remote home directory) must be given as the main
+ argument in the rest of the command line.
+ -k<keyid> The key to use for signing
+ -p<sign-command> The command to use for signing
+ -e<maintainer> Sign using key of <maintainer> (takes precedence over -m)
+ -m<maintainer> The same as -e
+ -S Use changes file made for source-only upload
+ -a<arch> Use changes file made for Debian target architecture <arch>
+ -t<target> Use changes file made for GNU target architecture <target>
+ --multi Use most recent multiarch .changes file found
+ --re-sign Re-sign if the file is already signed.
+ --no-re-sign Don't re-sign if the file is already signed.
+ --debs-dir <directory>
+ The location of the files to be signed when called from
+ within a source tree (default "..")
+ --no-conf, --noconf
+ Don't read devscripts config files;
+ must be the first option given
+ --help Show this message
+ --version Show version and copyright information
+ If an explicit filename is specified, it along with any child .buildinfo and
+ .dsc files are signed. Otherwise, debian/changelog is parsed to find the
+ changes file.
+
+$MODIFIED_CONF_MSG"
+}
+
+version() {
+ echo \
+"This is debsign, from the Debian devscripts package, version ###VERSION###
+This code is copyright 1999 by Julian Gilbey, all rights reserved.
+This program comes with ABSOLUTELY NO WARRANTY.
+You are free to redistribute this code under the terms of the
+GNU General Public License, version 2 or later."
+}
+
+temp_filename() {
+ local filename
+
+ if ! [ -w "$(dirname "$1")" ]; then
+ filename=$(mktemp -t "$(basename "$1").$2.XXXXXXXXXX") || {
+ echo "$PROGNAME: Unable to create temporary file; aborting" >&2
+ exit 1
+ }
+ else
+ filename="$1.$2"
+ fi
+
+ echo "$filename"
+}
+
+to_bool() {
+ if "$@"; then echo true; else echo false; fi
+}
+
+movefile() {
+ if [ -w "$(dirname "$2")" ]; then
+ mv -f -- "$1" "$2"
+ else
+ cat "$1" > "$2"
+ rm -f "$1"
+ fi
+}
+
+cleanup_tmpdir() {
+ if [ -n "$remotefilesdir" ] && [ -d "$remotefilesdir" ]; then
+ if [ "$PRECIOUS_FILES" -gt 0 ]; then
+ echo "$PROGNAME: aborting with $PRECIOUS_FILES signed files in $remotefilesdir" >&2
+ # Only produce the warning once...
+ PRECIOUS_FILES=0
+ else
+ cd ..
+ rm -rf "$remotefilesdir"
+ fi
+ fi
+
+ if [ -n "$signingdir" ] && [ -d "$signingdir" ]; then
+ rm -rf "$signingdir"
+ fi
+}
+
+mustsetvar() {
+ if [ "x$2" = x ]
+ then
+ echo >&2 "$PROGNAME: unable to determine $3"
+ exit 1
+ else
+ # echo "$PROGNAME: $3 is $2"
+ eval "$1=\"\$2\""
+ fi
+}
+
+# This takes two arguments: the name of the file to sign and the
+# key or maintainer name to use. NOTE: this usage differs from that
+# of dpkg-buildpackage, because we do not know all of the necessary
+# information when this function is read first.
+signfile() {
+ local type="$1"
+ local file="$2"
+ local signas="$3"
+ local savestty=$(stty -g 2>/dev/null) || true
+ mksigningdir
+ UNSIGNED_FILE="$signingdir/$(basename "$file")"
+ ASCII_SIGNED_FILE="${UNSIGNED_FILE}.asc"
+ (cat "$file" ; echo "") > "$UNSIGNED_FILE"
+
+ gpgversion=$($signcommand --version | head -n 1 | cut -d' ' -f3)
+ gpgmajorversion=$(echo $gpgversion | cut -d. -f1)
+ gpgminorversion=$(echo $gpgversion | cut -d. -f2)
+
+ if [ $gpgmajorversion -gt 1 -o $gpgminorversion -ge 4 ]
+ then
+ $signcommand --no-auto-check-trustdb \
+ --local-user "$signas" --clearsign \
+ --list-options no-show-policy-urls \
+ --armor --textmode --output "$ASCII_SIGNED_FILE"\
+ "$UNSIGNED_FILE" || \
+ { SAVESTAT=$?
+ echo "$PROGNAME: $signcommand error occurred! Aborting...." >&2
+ stty $savestty 2>/dev/null || true
+ exit $SAVESTAT
+ }
+ else
+ $signcommand --local-user "$signas" --clearsign \
+ --no-show-policy-url \
+ --armor --textmode --output "$ASCII_SIGNED_FILE" \
+ "$UNSIGNED_FILE" || \
+ { SAVESTAT=$?
+ echo "$PROGNAME: $signcommand error occurred! Aborting...." >&2
+ stty $savestty 2>/dev/null || true
+ exit $SAVESTAT
+ }
+ fi
+ stty $savestty 2>/dev/null || true
+ echo
+ PRECIOUS_FILES=$(($PRECIOUS_FILES + 1))
+ HAVE_SIGNED="${HAVE_SIGNED:+${HAVE_SIGNED}, }$type"
+ NUM_SIGNED=$((NUM_SIGNED + 1))
+ movefile "$ASCII_SIGNED_FILE" "$file"
+}
+
+withecho() {
+ echo " $@"
+ "$@"
+}
+
+file_is_already_signed() {
+ test "$(head -n 1 "$1")" = "-----BEGIN PGP SIGNED MESSAGE-----"
+}
+
+unsignfile() {
+ UNSIGNED_FILE="$(temp_filename "$1" "unsigned")"
+
+ sed -e '1,/^$/d; /^$/,$d' "$1" > "$UNSIGNED_FILE"
+ movefile "$UNSIGNED_FILE" "$1"
+}
+
+# Has the dsc file already been signed, perhaps from a previous, partially
+# successful invocation of debsign? We give the user the option of
+# resigning the file or accepting it as is. Returns success if already
+# and failure if the file needs signing. Parameters: $1=filename,
+# $2=file type for message (e.g. "changes", "commands")
+check_already_signed() {
+ file_is_already_signed "$1" || return 1
+
+ local resign
+ if [ "$opt_re_sign" = "true" ]; then
+ resign="true"
+ elif [ "$opt_re_sign" = "false" ]; then
+ resign="false"
+ else
+ response=n
+ if [ -z "$DEBSIGN_ALWAYS_RESIGN" ]; then
+ printf "The .$2 file is already signed.\nWould you like to use the current signature? [Yn]"
+ read response
+ fi
+ case $response in
+ [Nn]*) resign="true" ;;
+ *) resign="false" ;;
+ esac
+ fi
+
+ [ "$resign" = "true" ] || \
+ return 0
+
+ withecho unsignfile "$1"
+ return 1
+}
+
+# --- main script
+
+# Unset GREP_OPTIONS for sanity
+unset GREP_OPTIONS
+
+# Boilerplate: set config variables
+DEFAULT_DEBSIGN_ALWAYS_RESIGN=
+DEFAULT_DEBSIGN_PROGRAM=
+DEFAULT_DEBSIGN_MAINT=
+DEFAULT_DEBSIGN_KEYID=
+DEFAULT_DEBRELEASE_DEBS_DIR=..
+VARS="DEBSIGN_ALWAYS_RESIGN DEBSIGN_PROGRAM DEBSIGN_MAINT"
+VARS="$VARS DEBSIGN_KEYID DEBRELEASE_DEBS_DIR"
+
+if [ "$1" = "--no-conf" -o "$1" = "--noconf" ]; then
+ shift
+ MODIFIED_CONF_MSG="$MODIFIED_CONF_MSG
+ (no configuration files read)"
+
+ # set defaults
+ for var in $VARS; do
+ eval "$var=\$DEFAULT_$var"
+ done
+else
+ # Run in a subshell for protection against accidental errors
+ # in the config files
+ eval $(
+ set +e
+ for var in $VARS; do
+ eval "$var=\$DEFAULT_$var"
+ done
+
+ for file in /etc/devscripts.conf ~/.devscripts
+ do
+ [ -r $file ] && . $file
+ done
+
+ set | grep -E '^(DEBSIGN|DEBRELEASE|DEVSCRIPTS)_')
+
+ # We do not replace this with a default directory to avoid accidentally
+ # signing a broken package
+ DEBRELEASE_DEBS_DIR="$(echo "${DEBRELEASE_DEBS_DIR%/}" | sed -e 's%/\+%/%g')"
+
+ # set config message
+ MODIFIED_CONF=''
+ for var in $VARS; do
+ eval "if [ \"\$$var\" != \"\$DEFAULT_$var\" ]; then
+ MODIFIED_CONF_MSG=\"\$MODIFIED_CONF_MSG
+ $var=\$$var\";
+ MODIFIED_CONF=yes;
+ fi"
+ done
+
+ if [ -z "$MODIFIED_CONF" ]; then
+ MODIFIED_CONF_MSG="$MODIFIED_CONF_MSG
+ (none)"
+ fi
+fi
+
+maint="$DEBSIGN_MAINT"
+signkey="$DEBSIGN_KEYID"
+debsdir="$DEBRELEASE_DEBS_DIR"
+debsdir_warning="config file specified DEBRELEASE_DEBS_DIR directory $DEBRELEASE_DEBS_DIR does not exist!"
+
+signcommand=''
+if [ -n "$DEBSIGN_PROGRAM" ]; then
+ signcommand="$DEBSIGN_PROGRAM"
+else
+ if command -v gpg > /dev/null; then
+ signcommand=gpg
+ elif command -v gpg2 > /dev/null; then
+ signcommand=gpg2
+ fi
+fi
+
+TEMP=$(getopt -n "$PROGNAME" -o 'p:m:e:k:Sa:t:r:h' \
+ -l 'multi,re-sign,no-re-sign,debs-dir:' \
+ -l 'noconf,no-conf,help,version' \
+ -- "$@") || (rc=$?; usage >&2; exit $rc)
+
+eval set -- "$TEMP"
+
+while true
+do
+ case "$1" in
+ -p) signcommand="$2"; shift ;;
+ -m) maint="$2"; shift ;;
+ -e) maint="$2"; shift ;;
+ -k) signkey="$2"; shift ;;
+ -S) sourceonly="true" ;;
+ -a) targetarch="$2"; shift ;;
+ -t) targetgnusystem="$2"; shift ;;
+ --multi) multiarch="true" ;;
+ --re-sign) opt_re_sign="true" ;;
+ --no-re-sign) opt_re_sign="false" ;;
+ -r) remotehost=$2; shift
+ # Allow for the [user@]host:filename format
+ hostpart="${remotehost%:*}"
+ filepart="${remotehost#*:}"
+ if [ -n "$filepart" -a "$filepart" != "$remotehost" ]; then
+ remotehost="$hostpart"
+ set -- "$@" "$filepart"
+ fi
+ ;;
+ --debs-dir)
+ shift
+ opt_debsdir="$(echo "${1%/}" | sed -e 's%/\+%/%g')"
+ debsdir_warning="could not find directory $opt_debsdir!"
+ ;;
+ --no-conf|--noconf)
+ echo "$PROGNAME: $1 is only acceptable as the first command-line option!" >&2
+ exit 1 ;;
+ -h|--help)
+ usage; exit 0 ;;
+ --version)
+ version; exit 0 ;;
+ --) shift; break ;;
+ esac
+ shift
+done
+
+debsdir=${opt_debsdir:-$debsdir}
+
+if [ -z "$signcommand" ]; then
+ echo "Could not find a signing program!" >&2
+ exit 1
+fi
+
+if echo "${signkey}" | grep -E -qs '^(0x)?[a-zA-Z0-9]{8}$'; then
+ echo "Refusing to sign with short key ID '$signkey'!" >&2
+ exit 1
+fi
+
+if echo "${signkey}" | grep -E -qs '^(0x)?[a-zA-Z0-9]{16}$'; then
+ echo "long key IDs are discouraged; please use key fingerprints instead" >&2
+fi
+
+ensure_local_copy() {
+ local remotehost="$1"
+ local remotefile="$2"
+ local file="$3"
+ local type="$4"
+ if [ -n "$remotehost" ]
+ then
+ if [ ! -f "$file" ]
+ then
+ withecho scp "$remotehost:$remotefile" "$file"
+ fi
+ fi
+
+ if [ ! -f "$file" -o ! -r "$file" ]
+ then
+ echo "$PROGNAME: Can't find or can't read $type file $file!" >&2
+ exit 1
+ fi
+}
+
+fixup_control() {
+ local filter_out="$1"
+ local childtype="$2"
+ local parenttype="$3"
+ local child="$4"
+ local parent="$5"
+ test -r "$child" || {
+ echo "$PROGNAME: Can't read .$childtype file $child!" >&2
+ return 1
+ }
+
+ local md5=$(md5sum "$child" | cut -d' ' -f1)
+ local sha1=$(sha1sum "$child" | cut -d' ' -f1)
+ local sha256=$(sha256sum "$child" | cut -d' ' -f1)
+ perl -i -pe 'BEGIN {
+ '" \$file='$child'; \$md5='$md5'; "'
+ '" \$sha1='$sha1'; \$sha256='$sha256'; "'
+ $size=(-s $file); ($base=$file) =~ s|.*/||;
+ $infiles=0; $inmd5=0; $insha1=0; $insha256=0; $format="";
+ }
+ if(/^Format:\s+(.*)/) {
+ $format=$1;
+ die "Unrecognised .$parenttype format: $format\n"
+ unless $format =~ /^\d+(\.\d+)*$/;
+ ($major, $minor) = split(/\./, $format);
+ $major+=0;$minor+=0;
+ die "Unsupported .$parenttype format: $format\n"
+ if('"$filter_out"');
+ }
+ /^Files:/i && ($infiles=1,$inmd5=0,$insha1=0,$insha256=0);
+ if(/^Checksums-Sha1:/i) {$insha1=1;$infiles=0;$inmd5=0;$insha256=0;}
+ elsif(/^Checksums-Sha256:/i) {
+ $insha256=1;$infiles=0;$inmd5=0;$insha1=0;
+ } elsif(/^Checksums-Md5:/i) {
+ $inmd5=1;$infiles=0;$insha1=0;$insha256=0;
+ } elsif(/^Checksums-.*?:/i) {
+ die "Unknown checksum format: $_\n";
+ }
+ /^\s*$/ && ($infiles=0,$inmd5=0,$insha1=0,$insha256=0);
+ if ($infiles &&
+ /^ (\S+) (\d+) (\S+) (\S+) \Q$base\E\s*$/) {
+ $_ = " $md5 $size $3 $4 $base\n";
+ $infiles=0;
+ }
+ if ($inmd5 &&
+ /^ (\S+) (\d+) \Q$base\E\s*$/) {
+ $_ = " $md5 $size $base\n";
+ $inmd5=0;
+ }
+ if ($insha1 &&
+ /^ (\S+) (\d+) \Q$base\E\s*$/) {
+ $_ = " $sha1 $size $base\n";
+ $insha1=0;
+ }
+ if ($insha256 &&
+ /^ (\S+) (\d+) \Q$base\E\s*$/) {
+ $_ = " $sha256 $size $base\n";
+ $insha256=0;
+ }' "$parent"
+}
+
+fixup_buildinfo() {
+ fixup_control '($major != 0 or $minor > 2) and ($major != 1 or $minor > 0)' dsc buildinfo "$@"
+}
+
+fixup_changes() {
+ local childtype="$1"
+ shift
+ fixup_control '$major!=1 or $minor > 8 or $minor < 7' $childtype changes "$@"
+}
+
+withtempfile() {
+ local filetype="$1"
+ local mainfile="$2"
+ shift 2
+ local temp_file="$(temp_filename "$mainfile" "temp")"
+ cp "$mainfile" "$temp_file"
+ if "$@" "$temp_file"; then
+ if ! cmp -s "$mainfile" "$temp_file"; then
+ # emulate output of "withecho" but on the mainfile
+ echo " $@" "$mainfile" >&2
+ fi
+ movefile "$temp_file" "$mainfile"
+ else
+ rm "$temp_file"
+ echo "$PROGNAME: Error processing .$filetype file (see above)" >&2
+ exit 1
+ fi
+}
+
+guess_signas() {
+ if [ -n "$maint" ]
+ then maintainer="$maint"
+ # Try the new "Changed-By:" field first
+ else maintainer=$(sed -n 's/^Changed-By: //p' $1)
+ fi
+ if [ -z "$maintainer" ]
+ then maintainer=$(sed -n 's/^Maintainer: //p' $1)
+ fi
+
+ echo "${signkey:-$maintainer}"
+}
+
+maybesign_dsc() {
+ local signas="$1"
+ local remotehost="$2"
+ local dsc="$3"
+
+ if check_already_signed "$dsc" dsc; then
+ echo "Leaving current signature unchanged." >&2
+ return
+ fi
+
+ withecho signfile dsc "$dsc" "$signas"
+
+ if [ -n "$remotehost" ]
+ then
+ withecho scp "$dsc" "$remotehost:$remotedir"
+ PRECIOUS_FILES=$(($PRECIOUS_FILES - 1))
+ fi
+}
+
+maybesign_buildinfo() {
+ local signas="$1"
+ local remotehost="$2"
+ local buildinfo="$3"
+ local dsc="$4"
+
+ if check_already_signed "$buildinfo" "buildinfo"; then
+ echo "Leaving current signature unchanged." >&2
+ return
+ fi
+
+ if [ -n "$dsc" ]; then
+ maybesign_dsc "$signas" "$remotehost" "$dsc"
+ withtempfile buildinfo "$buildinfo" fixup_buildinfo "$dsc"
+ fi
+
+ withecho signfile buildinfo "$buildinfo" "$signas"
+
+ if [ -n "$remotehost" ]
+ then
+ withecho scp "$buildinfo" "$remotehost:$remotedir"
+ PRECIOUS_FILES=$(($PRECIOUS_FILES - 1))
+ fi
+}
+
+maybesign_changes() {
+ local signas="$1"
+ local remotehost="$2"
+ local changes="$3"
+ local buildinfo="$4"
+ local dsc="$5"
+
+ if check_already_signed "$changes" "changes"; then
+ echo "Leaving current signature unchanged." >&2
+ return
+ fi
+
+ hasdsc="$(to_bool [ -n "$dsc" ])"
+ hasbuildinfo="$(to_bool [ -n "$buildinfo" ])"
+
+ if $hasbuildinfo; then
+ # assume that this will also sign the same dsc if it's available
+ maybesign_buildinfo "$signas" "$remotehost" "$buildinfo" "$dsc"
+ elif $hasdsc; then
+ maybesign_dsc "$signas" "$remotehost" "$dsc"
+ fi
+
+ if $hasdsc; then
+ withtempfile changes "$changes" fixup_changes dsc "$dsc"
+ fi
+ if $hasbuildinfo; then
+ withtempfile changes "$changes" fixup_changes buildinfo "$buildinfo"
+ fi
+ withecho signfile changes "$changes" "$signas"
+
+ if [ -n "$remotehost" ]
+ then
+ withecho scp "$changes" "$remotehost:$remotedir"
+ PRECIOUS_FILES=$(($PRECIOUS_FILES - 1))
+ fi
+}
+
+report_signed() {
+ if [ $NUM_SIGNED -eq 1 ]; then
+ echo "Successfully signed $HAVE_SIGNED file"
+ elif [ $NUM_SIGNED -gt 0 ]; then
+ echo "Successfully signed $HAVE_SIGNED files"
+ fi
+}
+
+dosigning() {
+ # Do we have to download the changes file?
+ if [ -n "$remotehost" ]
+ then
+ mkremotefilesdir
+ cd "$remotefilesdir"
+
+ remotechanges=$changes
+ remotebuildinfo=$buildinfo
+ remotedsc=$dsc
+ remotecommands=$commands
+ changes=$(basename "$changes")
+ buildinfo=$(basename "$buildinfo")
+ dsc=$(basename "$dsc")
+ commands=$(basename "$commands")
+
+ if [ -n "$changes" ]; then
+ if [ ! -f "$changes" ]; then
+ # Special handling for changes to support supplying a glob
+ # and downloading all matching changes files (c.f., #491627)
+ withecho scp "$remotehost:$remotechanges" .
+ fi
+ fi
+
+ if [ -n "$changes" ] && echo "$changes" | grep -qE '[][*?]'
+ then
+ for changes in $changes
+ do
+ dsc=
+ buildinfo=
+ printf "\n"
+ dosigning;
+ done
+ exit 0;
+ fi
+ fi
+
+ if [ -n "$commands" ] # sign .commands file
+ then
+ ensure_local_copy "$remotehost" "$remotecommands" "$commands" commands
+ check_already_signed "$commands" commands && {
+ echo "Leaving current signature unchanged." >&2
+ return
+ }
+
+ # simple validator for .commands files, see
+ # ftp://ftp.upload.debian.org/pub/UploadQueue/README
+ perl -ne 'BEGIN { $uploader = 0; $incommands = 0; }
+ END { exit $? if $?;
+ if ($uploader && $incommands) { exit 0; }
+ else { die ".commands file missing Uploader or Commands field\n"; }
+ }
+ sub checkcommands {
+ chomp($line=$_[0]);
+ if ($line =~ m%^\s*reschedule\s+[^\s/]+\.changes\s+[0-9]+-day\s*$%) { return 0; }
+ if ($line =~ m%^\s*cancel\s+[^\s/]+\.changes\s*$%) { return 0; }
+ if ($line =~ m%^\s*rm(\s+(?:DELAYED/[0-9]+-day/)?[^\s/]+)+\s*$%) { return 0; }
+ if ($line eq "") { return 0; }
+ die ".commands file has invalid Commands line: $line\n";
+ }
+ if (/^Uploader:/) {
+ if ($uploader) { die ".commands file has too many Uploader fields!\n"; }
+ $uploader++;
+ } elsif (! $incommands && s/^Commands:\s*//) {
+ $incommands=1; checkcommands($_);
+ } elsif ($incommands == 1) {
+ if (s/^\s+//) { checkcommands($_); }
+ elsif (/./) { die ".commands file: extra stuff after Commands field!\n"; }
+ else { $incommands = 2; }
+ } else {
+ next if /^\s*$/;
+ if (/./) { die ".commands file: extra stuff after Commands field!\n"; }
+ }' $commands || {
+ echo "$PROGNAME: .commands file appears to be invalid. see:
+ftp://ftp.upload.debian.org/pub/UploadQueue/README
+for valid format" >&2;
+ exit 1; }
+
+ if [ -n "$maint" ]
+ then maintainer="$maint"
+ else
+ maintainer=$(sed -n 's/^Uploader: //p' $commands)
+ if [ -z "$maintainer" ]
+ then
+ echo "Unable to parse Uploader, .commands file invalid."
+ exit 1
+ fi
+ fi
+
+ signas="${signkey:-$maintainer}"
+
+ withecho signfile commands "$commands" "$signas"
+
+ if [ -n "$remotehost" ]
+ then
+ withecho scp "$commands" "$remotehost:$remotedir"
+ PRECIOUS_FILES=$(($PRECIOUS_FILES - 1))
+ fi
+
+ report_signed
+
+ elif [ -n "$changes" ]
+ then
+ ensure_local_copy "$remotehost" "$remotechanges" "$changes" changes
+ derive_childfile "$changes" dsc
+ if [ -n "$dsc" ]
+ then
+ ensure_local_copy "$remotehost" "${remotedir}$dsc" "$dsc" dsc
+ fi
+ derive_childfile "$changes" buildinfo
+ if [ -n "$buildinfo" ]
+ then
+ ensure_local_copy "$remotehost" "${remotedir}$buildinfo" "$buildinfo" buildinfo
+ fi
+ signas="$(guess_signas "$changes")"
+ maybesign_changes "$signas" "$remotehost" \
+ "$changes" "$buildinfo" "$dsc"
+ report_signed
+
+ elif [ -n "$buildinfo" ]
+ then
+ ensure_local_copy "$remotehost" "$remotebuildinfo" "$buildinfo" buildinfo
+ derive_childfile "$buildinfo" dsc
+ if [ -n "$dsc" ]
+ then
+ ensure_local_copy "$remotehost" "${remotedir}$dsc" "$dsc" dsc
+ fi
+ signas="$(guess_signas "$buildinfo")"
+ maybesign_buildinfo "$signas" "$remotehost" \
+ "$buildinfo" "$dsc"
+ report_signed
+
+ else
+ ensure_local_copy "$remotehost" "$remotedsc" "$dsc" dsc
+ signas="$(guess_signas "$dsc")"
+ maybesign_dsc "$signas" "$remotehost" "$dsc"
+ report_signed
+
+ fi
+}
+
+derive_childfile() {
+ local base="$1"
+ local ext="$2"
+
+ local fname dir
+ fname="$(sed -n '/^\(Checksum\|Files\)/,/^\(Checksum\|Files\)/s/.*[ ]\([^ ]*\.'"$ext"'\)$/\1/p' "$base" | head -n1)"
+ if [ -n "$fname" ]
+ then
+ get_dirname "$base" dir
+ eval "$ext=\"${dir}$fname\""
+ else
+ eval "$ext="
+ fi
+}
+
+get_dirname() {
+ local path="$1"
+ local varname="$2"
+
+ local d
+ d="$(dirname "$path")"
+
+ if [ "$d" = "." ]
+ then
+ d=""
+ else
+ d="$d/"
+ fi
+
+ eval "$varname=\"$d\""
+}
+
+# If there is a command-line parameter, it is the name of a .changes file
+# If not, we must be at the top level of a source tree and will figure
+# out its name from debian/changelog
+case $# in
+ 0) # We have to parse debian/changelog to find the current version
+ # check sanity of debsdir
+ if ! [ -d "$debsdir" ]; then
+ echo "$PROGNAME: $debsdir_warning" >&2
+ exit 1
+ fi
+ if [ -n "$remotehost" ]; then
+ echo "$PROGNAME: Need to specify a remote file location when giving -r!" >&2
+ exit 1
+ fi
+ if [ ! -r debian/changelog ]; then
+ echo "$PROGNAME: Must be run from top of source dir or a .changes file given as arg" >&2
+ exit 1
+ fi
+
+ mustsetvar package "`dpkg-parsechangelog -SSource`" "source package"
+ mustsetvar version "`dpkg-parsechangelog -SVersion`" "source version"
+
+ if [ "x$sourceonly" = x ]
+ then
+ if [ -n "$targetarch" ] && [ -n "$targetgnusystem" ]; then
+ mustsetvar arch "$(dpkg-architecture "-a${targetarch}" "-t${targetgnusystem}" -qDEB_HOST_ARCH)" "build architecture"
+ elif [ -n "$targetarch" ]; then
+ mustsetvar arch "$(dpkg-architecture "-a${targetarch}" -qDEB_HOST_ARCH)" "build architecture"
+ elif [ -n "$targetgnusystem" ]; then
+ mustsetvar arch "$(dpkg-architecture "-t${targetgnusystem}" -qDEB_HOST_ARCH)" "build architecture"
+ else
+ mustsetvar arch "$(dpkg-architecture -qDEB_HOST_ARCH)" "build architecture"
+ fi
+ else
+ arch=source
+ fi
+
+ sversion=$(echo "$version" | perl -pe 's/^\d+://')
+ pva="${package}_${sversion}_${arch}"
+ changes="$debsdir/$pva.changes"
+ if [ -n "$multiarch" -o ! -r $changes ]; then
+ changes=$(ls "$debsdir/${package}_${sversion}_*+*.changes" "$debsdir/${package}_${sversion}_multi.changes" 2>/dev/null | head -1)
+ # TODO: dpkg-cross does not yet do buildinfo, so don't worry about it here
+ if [ -z "$multiarch" ]; then
+ if [ -n "$changes" ]; then
+ echo "$PROGNAME: could not find normal .changes file but found multiarch file:" >&2
+ echo " $changes" >&2
+ echo "Using this changes file instead." >&2
+ else
+ echo "$PROGNAME: Can't find or can't read changes file $changes!" >&2
+ exit 1
+ fi
+ elif [ -n "$multiarch" -a -z "$changes" ]; then
+ echo "$PROGNAME: could not find any multiarch .changes file with name" >&2
+ echo "$debsdir/${package}_${sversion}_*.changes" >&2
+ exit 1
+ fi
+ fi
+ derive_childfile "$changes" dsc
+ derive_childfile "$changes" buildinfo
+ dosigning;
+ ;;
+
+ *) while [ $# -gt 0 ]; do
+ changes=
+ buildinfo=
+ dsc=
+ commands=
+ case "$1" in
+ *.dsc)
+ dsc=$1
+ ;;
+ *.buildinfo)
+ buildinfo=$1
+ ;;
+ *.changes)
+ changes=$1
+ ;;
+ *.commands)
+ commands=$1
+ ;;
+ *)
+ echo "$PROGNAME: Only a .changes, .buildinfo, .dsc or .commands file is allowed as argument!" >&2
+ exit 1 ;;
+ esac
+ get_dirname "$1" remotedir
+ dosigning
+ shift
+ done
+ ;;
+esac
+
+exit 0