New, improved dpkg-source script
Changes:
* Now supports `debian-special' archives. These contain an empty
diff as the first thing and do not have a revision (this allows the
program to recognise them as being distinct both from ordinary
tarfiles and from `normal' source files). In order to create one
you have to pass an empty string for the revision argument
(omitting it is just too easy).
* Fixed bug involving set -e and $? - thanks to Raul Miller.
* Checks, I think, that the archive won't modify anything except
the files it's extracting.
This is pretty close, I think, to being shippable. I might write a
manpage for it and include it in the next dpkg release.
I propose that we require that all source packages in the 1.1 release
are in this format. If we can't track down a package maintainer we'll
have to find the original source ourselves, unfortunately - but better
to do this once.
NOTE TO PACKAGE MAINTAINERS: DO NOT TAKE ANY ACTION YET apart from
trying out this script and thinking about this scheme and commenting,
&c. If and when a change is required you will be told separately :-).
Ian.
#!/bin/sh
#
unset GZIP
set -e
ec=1
trap 'rm -f -- "$tmpfile" "$tmpfile2"; exit $ec' 0
display-usage () {
cat <<'END'
Usage:
dpkg-source --unpack <package>-<version>-<revision>.tar.gz
(Creates <package>-<version>/* and <package>-<version>.orig/*.)
dpkg-source --build <directory> <revision>
(Builds <directory>-<revision>.tar.gz from <directory> and <directory>.orig;
<directory> is usually <package>-<version>.
If <revision> is the empty string builds a straightforward tarfile.)
Both use the files
<package>-<version>-<revision>.diff
<package>-<version>-<revision>.tar
END
}
signal-error () { echo >&2 "$0: $*"; exit 1; }
bad-usage () { echo >&2 "$0: bad usage: $*"; display-usage; exit 1; }
corrupted () { echo >&2 "$0: corrupted archive $tar (second $secondname, $*)"; exit 1; }
if [ "x$1" = x--build ]
then
[ $# = 3 ] || bad-usage '--build takes a <directory> and a <revision>'
directory="$2"
revision="$3"
test -d "$directory" || signal-error "<directory> is not a directory"
if [ "x$revision" != x ]
then
echo "building upstream $directory with revision $revision"
tar="$directory-$revision.tar"
test -d "$directory.orig" || \
signal-error "<directory> is not a directory"
tmpfile="$directory-$revision.diff"
rm -f -- "$tmpfile"
set +e
diff -aruN -- "$directory.orig" "$directory" >"$tmpfile"
test $? = 0 -o $? = 1 || exit 1
set -e
directory="$directory.orig"
else
echo "building $directory with no upstream version"
tar="$directory.tar"
tmpfile="$directory.diff"
rm -f -- "$tmpfile"
touch -- "$tmpfile"
fi
tar -cf "$tar" -- "$tmpfile" "$directory"
gzip -9f -- "$tar"
rm -- "$tmpfile"
elif [ "x$1" = x--unpack ]
then
[ $# = 2 ] || bad-usage '--unpack takes a <pkg>-<ver>-<rev>.tar.gz'
tar="$2"
tmpfile="`basename \"$tar\"`.dpkg-src-tmp"
rm -f -- "$tmpfile"
gunzip -f <"$tar" >"$tmpfile"
tmpfile2="${tmpfile}2"
tar -tf "$tmpfile" >"$tmpfile2"
firstname="`sed -n 1p <\"$tmpfile2\"`"
secondname="`sed -n 2p <\"$tmpfile2\"`"
case "$firstname" in */*) corrupted "first $firstname has \`/'" ;; esac
secondname="`echo \"x$secondname\" | sed -e 's/^x//; s,/\?$,/,'`"
N="$secondname" perl -ne <"$tmpfile2" '
exit 1 if $.>2 && substr($_,0,length($ENV{"N"})) ne $ENV{"N"};
exit 1 if m,/\.\./, || m,/\.\.$,;
' || corrupted 'some file(s) not in directory'
rm -- "$tmpfile2"
revision="`echo \"x$firstname\" | sed -e 's/\.diff$//; s/^x.*-//'`"
basename="`echo \"x$secondname\" | sed -e 's/^x//; s,/$,,; s/\.orig$//;'`"
if [ "x$secondname" = "x$basename/" ]
then
revision=""
tmpfile2="$basename.diff"
test "x$firstname" = "x$basename.diff" || \
corrupted "base $basename; first $firstname != $basename.diff"
echo "archive contains package $basename with no upstream version"
rm -rf -- "$basename" "$tmpfile2"
tar -xf "$tmpfile"
else
echo "archive contains upstream $basename with revision $revision"
revision="-$revision"
tmpfile2="$basename$revision.diff"
test "x$firstname" = "x$basename$revision.diff" || \
corrupted "base $base, rev $revision;" \
"first $firstname != $x$basename$revision.diff"
test "x$secondname" = "x$basename.orig/" || \
corrupted "base $basename; second $secondname != $basename.orig"
rm -rf -- "$basename" "$basename.orig" "$tmpfile2"
tar -xf "$tmpfile"
N="$basename/" perl -ne <"$tmpfile2" '
next unless m/^\-\-\- / || m/^\+\+\+ /;
$n=$ENV{"N"}; $n.= ".orig" if m/^\-\-\- /;
exit 1 if substr($_,4,length($n)) ne $n;
exit 1 if m,/\.\./, || m,/\.\.\s+\w+ \w+ \d+ \d+:\d+:\d+ \d+$,;
' || corrupted 'some patch(es) not in directory'
mv "$basename.orig" "$basename"
rm -- "$tmpfile2"
tar -xf "$tmpfile"
srcext=.dpkg-src-orig
patch -d "$basename" -p1 -s -u -t -F 0 -b $srcext <"$tmpfile2"
find "./$basename" -name '*'$srcext -print0 >"$tmpfile"
xargs <"$tmpfile" -0r rm --
fi
rm -- "$tmpfile" "$tmpfile2"
else
bad-usage 'no --build or --unpack'
fi
ec=0
Reply to: