[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: