The following commit has been merged in the master branch:
commit aebc5a505b982637460ed45afb6ec641a68b42df
Author: Christoph Berg <[email protected]>
Date:   Mon Jun 13 16:18:52 2011 +0200

    dscextract: new script, extracts a single file from a Debian source package.

diff --git a/README b/README
index 43fb238..d8212f7 100644
--- a/README
+++ b/README
@@ -152,6 +152,8 @@ And now, in mostly alphabetical order, the scripts:
   when trying to determine the packages needed in the Build-Depends etc.
   lines in the debian/control file. [build-essential, strace]
 
+- dscextract: extracts a single file from a Debian source package. [patchutils]
+
 - dscverify: check the signature and MD5 sums of a dsc file against the most
   current Debian keyring on your system. [gnupg, debian-keyring,
   libdigest-md5-perl]
diff --git a/debian/changelog b/debian/changelog
index 12cdde9..7bea0bd 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -16,6 +16,10 @@ devscripts (2.11.1) UNRELEASED; urgency=low
   * debsnap: Allow -a to be specified multiple times.  Thanks to Timo Juhani
     Lindfors for the suggestion.
 
+  [ Christoph Berg ]
+  * dscextract: new script, extracts a single file from a Debian source
+    package.
+
  -- David Prévot <[email protected]>  Wed, 08 Jun 2011 12:16:32 -0400
 
 devscripts (2.11.0) unstable; urgency=low
diff --git a/debian/control b/debian/control
index 57ab76f..1979541 100644
--- a/debian/control
+++ b/debian/control
@@ -150,6 +150,7 @@ Description: scripts to make the life of a Debian Package 
maintainer easier
     control field needed [build-essential, strace]
   - diff2patches: extract patches from a .diff.gz file placing them  under
     debian/ or, if present, debian/patches [patchutils]
+  - dscextract: extract a single file from a Debian source package [patchutils]
   - dscverify: verify the integrity of a Debian package from the
     .changes or .dsc files [gnupg, debian-keyring, libdigest-md5-perl]
   - edit-patch: add/edit a patch for a source package and commit the changes
diff --git a/po4a/devscripts-po4a.conf b/po4a/devscripts-po4a.conf
index e1d081a..6c7ff28 100644
--- a/po4a/devscripts-po4a.conf
+++ b/po4a/devscripts-po4a.conf
@@ -74,6 +74,8 @@
        fr:fr/dpkg-genbuilddeps.fr.1 add_fr:add_fr/translator_man.add
 [type:man] ../doc/edit-patch.1 \
         fr:fr/edit-patch.fr.1 add_fr:add_fr/translator_man.add
+[type:man] ../scripts/dscextract.1 \
+       fr:fr/dscextract.fr.1 add_fr:add_fr/translator_man.add
 [type:man] ../scripts/dscverify.1 \
        fr:fr/dscverify.fr.1 add_fr:add_fr/translator_man.add
 [type:man] ../scripts/getbuildlog.1 \
diff --git a/scripts/dscextract.1 b/scripts/dscextract.1
new file mode 100644
index 0000000..6e3c63d
--- /dev/null
+++ b/scripts/dscextract.1
@@ -0,0 +1,33 @@
+.TH DSCEXTRACT 1 "Debian Utilities" "DEBIAN" \" -*- nroff -*-
+.SH NAME
+dscextract \- extract a single file from a Debian source package
+.SH SYNOPSIS
+\fBdscextract\fR [\fIoptions\fR] \fIdscfile\fR \fIfile\fR
+.SH DESCRIPTION
+\fBdscextract\fR reads a single file from a Debian source package.  The idea is
+to only look into .diff.gz files (source format 1.0) or .debian.tar.gz/bz2
+files (source format 3.0) where possible, hence avoiding to unpack large
+tarballs.  It is most useful for files in the debian/ subdirectory.
+
+\fIfile\fP is relative to the first level directory contained in the package,
+i.e. with the first component stripped.
+.SH OPTIONS
+.TP
+.B \fB\-f
+"Fast" mode. For source format 1.0, avoid to fall back scanning the 
.orig.tar.gz
+file if \fIfile\fR was not found in the .diff.gz.  (For 3.0 packages, it is
+assumed that debian/* are exactly the contents of debian.tar.gz/bz2.)
+.SH "EXIT STATUS"
+.TP
+0
+\fIfile\fR was extracted.
+.TP
+1
+\fIfile\fR was not found in the source package.
+.TP
+2
+An error occured, like \fIdscfile\fR was not found.
+.SH EXAMPLE
+dscextract dds_2.1.1+ddd105-2.dsc debian/watch || test $? = 1
+.SH AUTHOR
+\fBdscextract\fR was written by Christoph Berg <[email protected]>.
diff --git a/scripts/dscextract.sh b/scripts/dscextract.sh
new file mode 100755
index 0000000..aac45ee
--- /dev/null
+++ b/scripts/dscextract.sh
@@ -0,0 +1,122 @@
+#!/bin/sh
+
+#   dscextract.sh - Extract a single file from a Debian source package
+#   Copyright (C) 2011 Christoph Berg <[email protected]>
+#
+#   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, write to the Free Software
+#   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+
+set -eu
+
+die () {
+       echo "$*" >&2
+       exit 2
+}
+
+FAST=""
+while getopts "f" opt ; do
+       case $opt in
+               f) FAST=yes ;;
+               *) exit 2 ;;
+       esac
+done
+# shift away args
+shift $(($OPTIND - 1))
+
+[ $# = 2 ] || die "Usage: $(basename $0) <dsc> <file>"
+DSC="$1"
+test -e "$DSC" || die "$DSC not found"
+FILE="$2"
+
+DSCDIR=$(dirname "$DSC")
+WORKDIR=$(mktemp -d --tmpdir dscextract.XXXXXX)
+trap "rm -rf $WORKDIR" 0 2 3 15
+
+if DIFFGZ=$(egrep '^ [0-9a-f]{32,64} [0-9]+ [^ ]+\.diff\.(gz|bz2)$' "$DSC") ; 
then
+       DIFFGZ=$(echo "$DIFFGZ" | cut -d ' ' -f 4 | head -n 1)
+       test -e "$DSCDIR/$DIFFGZ" || die "$DSCDIR/$DIFFGZ: not found"
+       filterdiff -p1 -i "$FILE" -z "$DSCDIR/$DIFFGZ" > "$WORKDIR/patch"
+       if test -s "$WORKDIR/patch" ; then
+               # case 1: file found in .diff.gz
+               if ! grep -q '^@@ -0,0 ' "$WORKDIR/patch" ; then
+                       # case 1a: patch requires original file
+                       ORIGTGZ=$(egrep '^ [0-9a-f]{32,64} [0-9]+ [^ 
]+\.orig\.tar\.(gz|bz2)$' "$DSC") || die "no orig.tar.gz found in $DSC"
+                       ORIGTGZ=$(echo "$ORIGTGZ" | cut -d ' ' -f 4 | head -n 1)
+                       case $ORIGTGZ in
+                               *.gz) ZIP=--gzip ;;
+                               *.bz2) ZIP=--bzip2 ;;
+                       esac
+                       test -e "$DSCDIR/$ORIGTGZ" || die "$DSCDIR/$ORIGTGZ not 
found"
+                       tar --extract --to-stdout --gzip --file 
"$DSCDIR/$ORIGTGZ" --wildcards "*/$FILE" > "$WORKDIR/output" 2>/dev/null || :
+                       test -s "$WORKDIR/output" || die "$FILE not found in 
$DSCDIR/$ORIGTGZ, but required by patch"
+               fi
+               patch --silent "$WORKDIR/output" < "$WORKDIR/patch"
+               test -s "$WORKDIR/output" || die "patch $FILE did not produce 
any output"
+               cat "$WORKDIR/output"
+               exit 0
+       elif [ "$FAST" ] ; then
+               # in fast mode, don't bother looking into .orig.tar.gz
+               exit 1
+       fi
+fi
+
+if DEBIANTARGZ=$(egrep '^ [0-9a-f]{32,64} [0-9]+ [^ 
]+\.debian\.tar\.(gz|bz2)$' "$DSC") ; then
+       case $FILE in
+               debian/*)
+                       DEBIANTARGZ=$(echo "$DEBIANTARGZ" | cut -d ' ' -f 4 | 
head -n 1)
+                       test -e "$DSCDIR/$DEBIANTARGZ" || die 
"$DSCDIR/$DEBIANTARGZ not found"
+                       case $DEBIANTARGZ in
+                               *.gz) ZIP=--gzip ;;
+                               *.bz2) ZIP=--bzip2 ;;
+                       esac
+                       tar --extract --to-stdout $ZIP --file 
"$DSCDIR/$DEBIANTARGZ" "$FILE" > "$WORKDIR/output" 2>/dev/null || :
+                       test -s "$WORKDIR/output" || exit 1
+                       # case 2a: file found in .debian.tar.gz
+                       cat "$WORKDIR/output"
+                       exit 0
+                       # for 3.0 format, no need to look in other places here
+                       ;;
+               *)
+                       ORIGTGZ=$(egrep '^ [0-9a-f]{32,64} [0-9]+ [^ 
]+\.orig\.tar\.(gz|bz2)$' "$DSC") || die "no orig.tar.gz found in $DSC"
+                       ORIGTGZ=$(echo "$ORIGTGZ" | cut -d ' ' -f 4 | head -n 1)
+                       test -e "$DSCDIR/$ORIGTGZ" || die "$DSCDIR/$ORIGTGZ not 
found"
+                       case $ORIGTGZ in
+                               *.gz) ZIP=--gzip ;;
+                               *.bz2) ZIP=--bzip2 ;;
+                       esac
+                       tar --extract --to-stdout $ZIP --file 
"$DSCDIR/$ORIGTGZ" --wildcards --no-wildcards-match-slash "*/$FILE" > 
"$WORKDIR/output" 2>/dev/null || :
+                       test -s "$WORKDIR/output" || exit 1
+                       # case 2b: file found in .orig.tar.gz
+                       # TODO: apply patches from debian.tar.gz
+                       cat "$WORKDIR/output"
+                       exit 0
+                       ;;
+       esac
+fi
+
+if TARGZ=$(egrep '^ [0-9a-f]{32,64} [0-9]+ [^ ]+\.tar\.(gz|bz2)$' "$DSC") ; 
then
+       TARGZ=$(echo "$TARGZ" | cut -d ' ' -f 4 | head -n 1)
+       test -e "$DSCDIR/$TARGZ" || die "$DSCDIR/$TARGZ not found"
+       case $TARGZ in
+               *.gz) ZIP=--gzip ;;
+               *.bz2) ZIP=--bzip2 ;;
+       esac
+       tar --extract --to-stdout $ZIP --file "$DSCDIR/$TARGZ" --wildcards 
--no-wildcards-match-slash "*/$FILE" > "$WORKDIR/output" 2>/dev/null || :
+       test -s "$WORKDIR/output" || exit 1
+       # case 3: file found in .tar.gz or .orig.tar.gz
+       cat "$WORKDIR/output"
+       exit 0
+fi
+
+exit 1

-- 
Git repository for devscripts


-- 
To unsubscribe, send mail to [email protected].

Reply via email to