[devscripts] 01/02: Merge tag 'v2.15.9' into jessie-backports

James McCoy jamessan at debian.org
Sat Nov 14 03:12:19 UTC 2015


This is an automated email from the git hooks/post-receive script.

jamessan pushed a commit to branch jessie-backports
in repository devscripts.

commit 4531be1391aeeec788350cebf36ba7a7505f405c
Author: James McCoy <jamessan at debian.org>
Date:   Fri Nov 13 21:49:37 2015 -0500

    Merge tag 'v2.15.9' into jessie-backports
    
    tagging package devscripts version 2.15.9
---
 debian/changelog                          |  90 +++++++
 debian/control                            |   2 +-
 debian/lintian-overrides                  |   3 -
 po4a/po/de.po                             |  73 ++---
 scripts/annotate-output.sh                |  21 +-
 scripts/bts.pl                            |   2 +-
 scripts/build-rdeps.pl                    |   6 +-
 scripts/chdist.pl                         |  20 ++
 scripts/dd-list.1                         |   8 +-
 scripts/dd-list.pl                        |  87 +++++-
 scripts/debchange.pl                      |  28 +-
 scripts/debcheckout.pl                    |  11 +-
 scripts/debcommit.pl                      |   5 +-
 scripts/getbuildlog.sh                    |   1 -
 scripts/licensecheck.pl                   |  43 ++-
 scripts/mergechanges.1                    |   5 +-
 scripts/mergechanges.sh                   |  67 +++--
 scripts/mk-origtargz.pl                   |  11 +-
 scripts/origtargz.pl                      |   4 +-
 scripts/tagpending.pl                     |  35 +--
 scripts/uscan.pl                          | 100 +++++--
 scripts/uupdate.1                         |   3 +
 scripts/uupdate.sh                        |  76 +++++-
 scripts/wrap-and-sort                     |   5 +-
 test/Makefile                             |   2 +
 test/dd-list/sources                      | 157 +++++++++++
 test/licensecheck/duplicated-copyright.rb |  43 +++
 test/test_dd-list                         |  18 +-
 test/test_debchange                       |   6 +-
 test/test_licensecheck                    |   4 +
 test/test_uscan                           |  65 ++++-
 test/test_uscan_mangle                    | 432 ++++++++++++++++++++++++++++++
 32 files changed, 1229 insertions(+), 204 deletions(-)

diff --git a/debian/changelog b/debian/changelog
index 64cb42a..a7f42c6 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,93 @@
+devscripts (2.15.9) unstable; urgency=medium
+
+  [ Joachim Breitner ]
+  * mk-origtargz:
+    + Work around tar --delete not working unless piping. This should
+      make the support for Excluded-Files more reliable.
+      Thanks to Felix Natter for identifying the problem and solution.
+  * debcommit:
+    + Detect git repositories even if .git is a file instead of a directory,
+      as it can be the case with "git worktree" worktrees.
+  * origtargz: Call rm -rf with "--", so that files starting with - are not
+    considered arguments by rm.
+
+  [ James McCoy ]
+  * bts:
+    + Add reference to pts-subscribe(1) in bts(1).  (Closes: #794689)
+  * tagpending:
+    + Fix warning when there are no fixed bugs in the changelog.  (Closes:
+      #795470)
+    + Avoid querying the BTS when there are no bugs closed in the changelog.
+  * mergechanges:
+    + Add -S/--source argument to skip all binary packages.  Thanks to Ansgar
+      Burchardt for the patch.  (Closes: #795573)
+  * debchange:
+    + Only emit "no orig tarball" for non-native packages.  (Closes: #797018)
+  * debcheckout:
+    + Clarify documentation of -f option.  Thanks to Daniel Shahaf for the
+      patch!  (Closes: #797265)
+  * annotate-output:
+    + Optimize the case of FORMAT not containing any date format codes.
+      Thanks to Stefan Fritsch for the patch.  (Closes: #799553)
+  * build-rdeps:
+    + Avoid recursing into apt's lists directory.  Only the top-level files
+      are interesting and this avoids a “Permission denied” warning with apt
+      versions that restrict access to the lists/partial directory.  Thanks to
+      James Cowgill for the patch.  (Closes: #798252)
+  * wrap-and-sort:
+    + Avoid modifying an empty file.  Thanks to Chris Lamb for the patch.
+      (Closes: #789579)
+  * dd-list:
+    + Omit information from stanzas with “Extra-Source-Only: yes”.
+    + Use only the information from the most recent version of a package
+      within each sources file.  (Closes: #788820)
+    + Enable reading sources data from gz or bzip2 compressed files.  If the
+      --dctrl switch is being used, the -z switch is needed to enabled
+       decompression.  Compressed files specified with the -s switch will
+       automatically be handled if using a .gz/.bz2 extension.
+
+  [ Dominique Dumont ]
+  * licensecheck:
+    * added --text option to avoid scanning binary files (Closes: #797562)
+    * use 'file' command to decide whether to scan a file or
+      not (instead of testing file suffix)
+    * remove trailing '#' from © information
+    * store only first © block to avoid duplicated information
+    * remove '\' from © information (useful for nroff files)
+
+  [ Adam D. Barratt ]
+  * getbuildlog:
+    + Stop downloading logs from debian-ports explicitly, now that it has
+      been merged into buildd.debian.org and downloading from both locations
+      causes duplicate downloads.  (Closes: #796506)
+
+  [ Dmitry Shachnev ]
+  * uscan: Use https protocol for pypi.debian.net redirector, now that it
+    is available.  (Closes: #796880)
+
+  [ Osamu Aoki ]
+  * uscan:
+    + Ensure the version field in the watch line is defined, rather than
+      "true" before using it in a comparison.  The enables the use of 0 as a
+      value for the version.  (Closes: #796984)
+
+  [ Gunnar Wolf ]
+  * debchange:
+    + Allow the current preferred security upload targets
+      (wheezy|jessie|stretch)-security instead of their changing
+      counterparts (oldstable|stable|testing)-security (Closes: #797084)
+
+  [ Antonio Terceiro ]
+  * chdist:
+    + Add support for running apt-file
+  * debian/lintian-overrides: remove overrides for false positives that had
+    been fixed in lintian
+
+  [ Christoph Berg ]
+  * debcheckout: Add auth mapping for git://github.com.
+
+ -- James McCoy <jamessan at debian.org>  Mon, 05 Oct 2015 21:00:08 -0400
+
 devscripts (2.15.8~bpo8+1) jessie-backports; urgency=medium
 
   * Rebuild for jessie-backports.
diff --git a/debian/control b/debian/control
index b913203..4a8d23b 100644
--- a/debian/control
+++ b/debian/control
@@ -33,7 +33,7 @@ Build-Depends: bash-completion,
                xsltproc,
                xz-utils,
                zip
-XS-Testsuite: autopkgtest
+Testsuite: autopkgtest
 Vcs-Browser: https://anonscm.debian.org/cgit/collab-maint/devscripts.git
 Vcs-Git: git://anonscm.debian.org/collab-maint/devscripts.git
 
diff --git a/debian/lintian-overrides b/debian/lintian-overrides
index d9396ac..646f453 100644
--- a/debian/lintian-overrides
+++ b/debian/lintian-overrides
@@ -1,5 +1,2 @@
 # "debsnap: grab packages from http://snapshot.debian.org" isn't a homepage
 devscripts: description-possibly-contains-homepage http://snapshot.debian.org
-# using dh causes useless ldconfig calls to be added to post{inst,rm}
-devscripts: postinst-has-useless-call-to-ldconfig
-devscripts: postrm-has-useless-call-to-ldconfig
diff --git a/po4a/po/de.po b/po4a/po/de.po
index 2a18004..310cd6b 100644
--- a/po4a/po/de.po
+++ b/po4a/po/de.po
@@ -1,14 +1,14 @@
 # Translation of the devscripts documentation to German.
 # This file is distributed under the same license as the devscripts package.
 # Copyright (C) Christoph Lameter, Julian Gilbey, Klee Dienes.
-# Copyright (C) of this file Chris Leick <c.leick at vollbio.de>, 2012-2014.
+# Copyright (C) of this file Chris Leick <c.leick at vollbio.de>, 2012-2015.
 #
 msgid ""
 msgstr ""
 "Project-Id-Version: devscripts 2.14.6\n"
 "Report-Msgid-Bugs-To: devscripts at packages.debian.org\n"
 "POT-Creation-Date: 2014-12-23 08:54-0400\n"
-"PO-Revision-Date: 2014-09-23 21:32+0200\n"
+"PO-Revision-Date: 2015-08-09 20:54+0200\n"
 "Last-Translator: Chris Leick <c.leick at vollbio.de>\n"
 "Language-Team: de <debian-l10n-german at lists.debian.org>\n"
 "Language: de\n"
@@ -4105,36 +4105,29 @@ msgstr "B<--sign=>I<Schlüsselkennung>"
 
 #. type: Plain text
 #: ../scripts/cowpoke.1:125
-#, fuzzy
-#| msgid ""
-#| "This option will override any B<BUILD_OPTS> specified for a chroot in the "
-#| "cowpoke configuration files."
 msgid ""
 "Specify the key to sign packages with.  This will override any B<SIGN_KEYID> "
 "specified for a chroot in the cowpoke configuration files."
 msgstr ""
-"Diese Option wird jede für eine Chroot in den Cowpoke-Konfigurationsdateien "
-"angegebene B<BUILD_OPTS> außer Kraft setzen."
+"gibt den Schlüssel an, mit dem Pakete signiert werden. Dies wird jedes "
+"B<SIGN_KEYID>, das für eine Chroot in den Cowpoke-Konfigurationsdateien "
+"angegeben wurde, außer Kraft setzen."
 
 #. type: TP
 #: ../scripts/cowpoke.1:126
-#, fuzzy, no-wrap
-#| msgid "B<--dupload>, B<--dput>"
+#, no-wrap
 msgid "B<--upload=>I<queue>"
-msgstr "B<--dupload>, B<--dput>"
+msgstr "B<--upload=>I<Warteschlange>"
 
 #. type: Plain text
 #: ../scripts/cowpoke.1:130
-#, fuzzy
-#| msgid ""
-#| "This option will override any B<BUILD_OPTS> specified for a chroot in the "
-#| "cowpoke configuration files."
 msgid ""
 "Specify the dput queue to upload signed packages to.  This will override any "
 "B<UPLOAD_QUEUE> specified for a chroot in the cowpoke configuration files."
 msgstr ""
-"Diese Option wird jede für eine Chroot in den Cowpoke-Konfigurationsdateien "
-"angegebene B<BUILD_OPTS> außer Kraft setzen."
+"gibt die Dput-Warteschlange an, in die signierte Pakete hochgeladen werden. "
+"Dies wird jede B<UPLOAD_QUEUE>, die für eine Chroot in den "
+"Cowpoke-Konfigurationsdateien angegeben wurde, außer Kraft setzen."
 
 #. type: Plain text
 #: ../scripts/cowpoke.1:134
@@ -4303,15 +4296,6 @@ msgstr "B<SIGN_KEYID>"
 
 #. type: Plain text
 #: ../scripts/cowpoke.1:194
-#, fuzzy
-#| msgid ""
-#| "If this option is set, it is expected to contain the gpg key ID to pass "
-#| "to B<debsign>(1) if the packages are to be remotely signed.  You will be "
-#| "prompted to confirm whether you wish to sign the packages after all "
-#| "builds are complete.  If this option is unset or an empty string, no "
-#| "attempt to sign packages will be made.  It may be overridden on an "
-#| "I<arch> and I<dist> specific basis using the "
-#| "I<arch>B<_>I<dist>B<_SIGN_KEYID> option described below."
 msgid ""
 "If this option is set, it is expected to contain the gpg key ID to pass to "
 "B<debsign>(1) if the packages are to be remotely signed.  You will be "
@@ -4329,7 +4313,8 @@ msgstr ""
 "kein Versuch unternommen, Pakete zu signieren. Sie kann auf einer "
 "I<architektur>- oder I<distribution>sspezifischen Basis mittels der weiter "
 "unten beschriebenen Option I<Architektur>B<_>I<Distribution>B<_SIGN_KEYID> "
-"außer Kraft gesetzt werden."
+"oder jeweils beim Aufruf mit der Befehlszeilenoption B<--sign> außer Kraft "
+"gesetzt werden."
 
 #. type: TP
 #: ../scripts/cowpoke.1:195
@@ -4339,16 +4324,6 @@ msgstr "B<UPLOAD_QUEUE>"
 
 #. type: Plain text
 #: ../scripts/cowpoke.1:206
-#, fuzzy
-#| msgid ""
-#| "If this option is set, it is expected to contain a 'host' specification "
-#| "for B<dput>(1) which will be used to upload them after they are signed.  "
-#| "You will be prompted to confirm whether you wish to upload the packages "
-#| "after they are signed.  If this option is unset or an empty string, no "
-#| "attempt to upload packages will be made.  If B<SIGN_KEYID> is not set, "
-#| "this option will be ignored entirely.  It may be overridden on an I<arch> "
-#| "and I<dist> specific basis using the I<arch>B<_>I<dist>B<_UPLOAD_QUEUE> "
-#| "option described below."
 msgid ""
 "If this option is set, it is expected to contain a 'host' specification for "
 "B<dput>(1) which will be used to upload them after they are signed.  You "
@@ -4367,8 +4342,8 @@ msgstr ""
 "hochzuladen. Falls B<SIGN_KEYID> nicht gesetzt ist, wird diese Option ganz "
 "ignoriert. Sie kann auf einer I<architektur>- oder "
 "I<distribution>sspezifischen Basis mittels der weiter unten beschriebenen "
-"Option I<Architektur>B<_>I<Distribution>B<_UPLOAD_QUEUE> außer Kraft gesetzt "
-"werden."
+"Option I<Architektur>B<_>I<Distribution>B<_UPLOAD_QUEUE> oder jeweils beim "
+"Aufruf mit der Befehlszeilenoption B<--upload> außer Kraft gesetzt werden."
 
 #. type: TP
 #: ../scripts/cowpoke.1:208
@@ -8885,16 +8860,6 @@ msgstr "B<debdiff> [I<Optionen>] … I<dsc1 dsc2>"
 
 #. type: Plain text
 #: ../scripts/debdiff.1:26
-#, fuzzy
-#| msgid ""
-#| "B<debdiff> takes the names of two Debian package files (I<.deb>s or I<."
-#| "udeb>s) on the command line and compares their contents (considering only "
-#| "the files in the main package, not the maintenance scripts).  It shows "
-#| "which files have been introduced and which removed between the two "
-#| "package files, and is therefore useful for spotting files which may have "
-#| "been inadvertently lost between revisions of the package.  It also checks "
-#| "the file owners and permissions, and compares the control files of the "
-#| "two packages using the B<wdiff> program."
 msgid ""
 "B<debdiff> takes the names of two Debian package files (I<.deb>s or I<."
 "udeb>s) on the command line and compares their contents (considering only "
@@ -8914,7 +8879,8 @@ msgstr ""
 "möglicherweise versehentlich zwischen zwei Revisionen des Pakets verloren "
 "gingen. Es prüft außerdem die Dateibesitzer und Zugriffsrechte und "
 "vergleicht die Steuerdateien der beiden Pakete mittels des Programms "
-"B<wdiff>."
+"B<wdiff>. Falls Sie zwei Debian-Pakete genauer vergleichen wollen, können Sie "
+"das Werkzeug B<debbindiff> benutzen."
 
 #. type: Plain text
 #: ../scripts/debdiff.1:29
@@ -12817,16 +12783,13 @@ msgstr "I<debdiff>(1)"
 
 #. type: Plain text
 #: ../scripts/devscripts.1:69
-#, fuzzy
-#| msgid ""
-#| "compare two versions of a Debian package to check for added and removed "
-#| "files [wdiff, patchutils]"
 msgid ""
 "compare two versions of a Debian package to check for added and removed "
 "files. Use the debbindiff package for deep comparisons. [wdiff, patchutils]"
 msgstr ""
 "vergleicht zwei Versionen eines Debian-Pakets, um es auf hinzugefügte oder "
-"entfernte Dateien hin zu untersuchen. [wdiff, patchutils]"
+"entfernte Dateien hin zu untersuchen. Verwenden Sie für genauere Vergleiche "
+"das Paket »debbindiff«. [wdiff, patchutils]"
 
 #. type: IP
 #: ../scripts/devscripts.1:69
diff --git a/scripts/annotate-output.sh b/scripts/annotate-output.sh
index f260b95..6929faa 100755
--- a/scripts/annotate-output.sh
+++ b/scripts/annotate-output.sh
@@ -32,6 +32,16 @@ addtime ()
 	fi
 }
 
+addprefix ()
+{
+	while IFS= read -r line; do
+		printf "%s: %s\n" "$1" "$line"
+	done
+	if [ ! -z "$line" ]; then
+		printf "%s: %s" "$1" "$line"
+	fi
+}
+
 usage ()
 {
 	echo \
@@ -75,8 +85,15 @@ ERR=$tmp/err
 
 mkfifo $OUT $ERR || exit 1
 
-addtime O < $OUT &
-addtime E < $ERR &
+if [ "${FMT/\%}" != "${FMT}" ] ; then
+	addtime O < $OUT &
+	addtime E < $ERR &
+else
+	# If FMT does not contain a %, use the optimized version that
+	# does not call 'date'.
+	addprefix "${FMT#+} O" < $OUT &
+	addprefix "${FMT#+} E" < $ERR &
+fi
 
 echo "Started $@" | addtime I
 "$@" > $OUT 2> $ERR ; EXIT=$?
diff --git a/scripts/bts.pl b/scripts/bts.pl
index e7d9e68..55bb83a 100755
--- a/scripts/bts.pl
+++ b/scripts/bts.pl
@@ -4143,7 +4143,7 @@ Please see L<https://www.debian.org/Bugs/server-control> for
 more details on how to control the BTS using emails and
 L<https://www.debian.org/Bugs/> for more information about the BTS.
 
-querybts(1), reportbug(1)
+querybts(1), reportbug(1), pts-subscribe(1)
 
 =head1 COPYRIGHT
 
diff --git a/scripts/build-rdeps.pl b/scripts/build-rdeps.pl
index dbbb98f..4cdf548 100755
--- a/scripts/build-rdeps.pl
+++ b/scripts/build-rdeps.pl
@@ -91,7 +91,6 @@ and run apt-get update afterwards or use the update option of this tool.
 use warnings;
 use strict;
 use File::Basename;
-use File::Find;
 use Getopt::Long qw(:config gnu_getopt);
 use Pod::Usage;
 use Data::Dumper;
@@ -307,7 +306,10 @@ if ($opt_distribution) {
 }
 
 # Find sources files
-find(sub { readrelease($_, $1) if /$release_pattern/ }, $sources_path);
+chdir($sources_path);
+for my $release_file (glob "*") {
+	readrelease($release_file, $1) if $release_file =~ /$release_pattern/;
+}
 
 if (!@source_files) {
 	die "$progname: unable to find sources files.\nDid you forget to run apt-get update (or add --update to this command)?";
diff --git a/scripts/chdist.pl b/scripts/chdist.pl
index c50b3fe..21daaa6 100755
--- a/scripts/chdist.pl
+++ b/scripts/chdist.pl
@@ -68,6 +68,10 @@ Run B<apt-get> inside I<DIST>
 
 Run B<apt-cache> inside I<DIST>
 
+=item B<apt-file> I<DIST> <B<update>|B<search>|...>
+
+Run B<apt-file> inside I<DIST>
+
 =item B<apt-rdepends> I<DIST> [...]
 
 Run B<apt-rdepends> inside I<DIST>
@@ -264,6 +268,19 @@ sub aptcmd
     exec($cmd, @args);
 }
 
+sub apt_file
+{
+    my ($dist, @args) = @_;
+    dist_check($dist);
+    my $sources_list = $datadir . '/' . $dist . "/etc/apt/sources.list";
+    my $cache_directory = $datadir . '/' . $dist . "/var/cache/apt/apt-file";
+    unshift(@args,
+      '--sources-list', $sources_list,
+      '--cache', $cache_directory
+    );
+    exec('apt-file', @args);
+}
+
 sub bin2src
 {
     my ($dist, $pkg) = @_;
@@ -666,6 +683,9 @@ given ($command) {
     when ('apt-cache') {
 	aptcmd('apt-cache', @ARGV);
     }
+    when ('apt-file') {
+	apt_file(@ARGV);
+    }
     when ('apt-rdepends') {
 	aptcmd('apt-rdepends', @ARGV);
     }
diff --git a/scripts/dd-list.1 b/scripts/dd-list.1
index b0d253e..dfda038 100644
--- a/scripts/dd-list.1
+++ b/scripts/dd-list.1
@@ -74,9 +74,15 @@ of each listed package.
 If no \fISource:\fP line is given, the \fIPackage:\fP name is used for
 output, which might be a binary package name.
 .TP
+.BR \-z ", " \-\-uncompress
+Try to uncompress the \-\-dctrl input before parsing.  Supported compression
+formats are gz and bzip2.
+.TP
 \fB\-s\fR, \fB\-\-sources\fR \fISources_file\fR
 Read package information from the specified \fISources_file\fRs.  This can be
-given multiple times.
+given multiple times.  The files can be gz or bzip2 compressed.  If the
+filename does not end in \fI.gz\fR or \fI.bz2\fR, then the \fB-z\fR option
+must be used.
 .IP
 If no \fISources_file\fRs are specified, any files matching
 \fI/var/lib/apt/lists/*_source_Sources\fR will be used.
diff --git a/scripts/dd-list.pl b/scripts/dd-list.pl
index bb97302..fb5721f 100755
--- a/scripts/dd-list.pl
+++ b/scripts/dd-list.pl
@@ -24,6 +24,17 @@ use strict;
 use warnings;
 use FileHandle;
 use Getopt::Long qw(:config gnu_getopt);
+use Dpkg::Version;
+
+my $uncompress;
+
+BEGIN {
+    $uncompress = eval {
+	require IO::Uncompress::AnyUncompress;
+	IO::Uncompress::AnyUncompress->import('$AnyUncompressError');
+	1;
+    };
+}
 
 my $version='###VERSION###';
 
@@ -53,10 +64,14 @@ Usage: dd-list [options] [package ...]
     -d, --dctrl
         Read package list in Debian control data from standard input.
 
+    -z, --uncompress
+        Try to uncompress the --dctrl input before parsing.  Supported
+        compression formats are gz and bzip2.
+
     -s, --sources SOURCES_FILE
         Read package information from given SOURCES_FILE instead of all files
         matching /var/lib/apt/lists/*_source_Sources.  Can be specified
-        multiple times.
+        multiple times.  The files can be gz or bzip2 compressed.
 
     -u, --uploaders
         Also list Uploaders of packages, not only the listed Maintainers
@@ -78,6 +93,7 @@ my $use_stdin=0;
 my $use_dctrl=0;
 my $source_files=[];
 my $show_uploaders=1;
+my $opt_uncompress=0;
 my $print_binary=0;
 GetOptions(
     "help|h" => sub { help(); exit },
@@ -85,6 +101,7 @@ GetOptions(
     "dctrl|d" => \$use_dctrl,
     "sources|s:s@" => \$source_files,
     "uploaders|u!" => \$show_uploaders,
+    'z|uncompress' => \$opt_uncompress,
     "print-binary|b" => \$print_binary,
     "version" => sub { print "dd-list version $version\n" })
 or do {
@@ -92,6 +109,11 @@ or do {
     exit(1);
 };
 
+if ($opt_uncompress && !$uncompress) {
+    warn "You must have the libio-compress-perl package installed to use the -z option.\n";
+    exit 1;
+}
+
 my %dict;
 my $errors=0;
 my %package_name;
@@ -107,9 +129,16 @@ sub parsefh
 				 map { "\Q$_\E" }
 				 keys %package_name;
     }
+    my %sources;
     while (<$fh>) {
 	my ($package, $source, $binaries, $maintainer, @uploaders);
 
+	# These source packages are only kept around because of stale binaries
+	# on old archs or due to Built-Using relationships.
+	if (/^Extra-Source-Only:\s+yes/m) {
+	    next;
+	}
+
 	# Binary is shown in _source_Sources and contains all binaries produced by
 	# that source package
 	if (/^Binary:\s+(.*(?:\n .*)*)$/m) {
@@ -135,6 +164,10 @@ sub parsefh
 	    $matches =~ s/\n//g;
 	    @uploaders = split /(?<=>)\s*,\s*/, $matches;
 	}
+	my $version = '0~0~0';
+	if (/^Version:\s+(.*)$/m) {
+	    $version = $1;
+	}
 
 	if (defined $maintainer
 	    && (defined $package || defined $source || defined $binaries)) {
@@ -144,33 +177,53 @@ sub parsefh
 	    if ($check_package) {
 		my @pkgs;
 		if (@pkgs = ($binaries =~ m/$package_names/g)) {
-		    map { $package_name{$_}-- } @pkgs;
+		    $sources{$source}{$version}{binaries} = [@pkgs];
 		}
 		elsif ($source !~ m/$package_names/) {
 		    next;
 		}
-		$package_name{$source}--;
-		@names = $print_binary ? @pkgs : $source;
 	    }
 	    else {
-		@names = $print_binary ? $binaries : $source;
-	    }
-	    push @{$dict{$maintainer}}, @names;
-	    if ($show_uploaders && @uploaders) {
-		foreach my $uploader (@uploaders) {
-		    push @{$dict{$uploader}}, map "$_ (U)", @names;
-		}
+		$sources{$source}{$version}{binaries} = [$binaries];
 	    }
+	    $sources{$source}{$version}{maintainer} = $maintainer;
+	    $sources{$source}{$version}{uploaders} = [@uploaders];
 	}
 	else {
 	    warn "E: parse error in stanza $. of $fname\n";
 	    $errors=1;
 	}
     }
+
+    for my $source (keys %sources) {
+	my @versions = sort map { Dpkg::Version->new($_) } keys %{$sources{$source}};
+	my $version = $versions[-1];
+	my $srcinfo = $sources{$source}{$version};
+	my @names;
+	if ($check_package) {
+	    $package_name{$source}--;
+	    $package_name{$_}-- for @{$srcinfo->{binaries}};
+	}
+	@names = $print_binary ? @{$srcinfo->{binaries}} : $source;
+	push @{$dict{$srcinfo->{maintainer}}}, @names;
+	if ($show_uploaders && @{$srcinfo->{uploaders}}) {
+	    foreach my $uploader (@{$srcinfo->{uploaders}}) {
+		push @{$dict{$uploader}}, map "$_ (U)", @names;
+	    }
+	}
+    }
 }
 
 if ($use_dctrl) {
-    parsefh(\*STDIN, 'STDIN');
+    my $fh;
+    if ($uncompress) {
+	$fh = IO::Uncompress::AnyUncompress->new('-')
+	    or die "E: Unable to decompress STDIN: $AnyUncompressError\n";
+    }
+    else {
+	$fh = \*STDIN;
+    }
+    parsefh($fh, 'STDIN');
 }
 else {
     my @packages;
@@ -193,9 +246,15 @@ else {
     }
 
     foreach my $source (@{$source_files}) {
-	my $fh = FileHandle->new("<$source");
+	my $fh;
+	if ($opt_uncompress || ($uncompress && $source =~ m/\.(?:gz|bz2)$/)) {
+	    $fh = IO::Uncompress::AnyUncompress->new($source);
+	}
+	else {
+	    $fh = FileHandle->new("<$source");
+	}
 	unless (defined $fh) {
-	    warn "E: Couldn't open $fh\n";
+	    warn "E: Couldn't open $source\n";
 	    $errors = 1;
 	    next;
 	}
diff --git a/scripts/debchange.pl b/scripts/debchange.pl
index 4348813..db52b60 100755
--- a/scripts/debchange.pl
+++ b/scripts/debchange.pl
@@ -42,6 +42,7 @@ use Cwd;
 use Dpkg::Vendor qw(get_current_vendor);
 use Dpkg::Changelog::Parse qw(changelog_parse);
 use Dpkg::Control;
+use Dpkg::Version;
 use Devscripts::Compression;
 use Devscripts::Debbugs;
 use POSIX qw(locale_h strftime);
@@ -471,7 +472,7 @@ if ($vendor eq 'Ubuntu' and ($opt_n or $opt_bn or $opt_qa or $opt_bpo)) {
 # Check the distro name given.
 if (defined $opt_D) {
     if ($vendor eq 'Debian') {
-	unless ($opt_D =~ /^(experimental|unstable|UNRELEASED|((old)?stable|testing)(-proposed-updates|-security)?|proposed-updates)$/) {
+	unless ($opt_D =~ /^(experimental|unstable|UNRELEASED|((old)?stable|testing)(-proposed-updates)?|proposed-updates|(wheezy|jessie|stretch)-security)$/) {
 	    my $deb_info = get_debian_distro_info();
 	    my ($oldstable_backports, $stable_backports) = ("", "");
 	    if ($deb_info == 0) {
@@ -1554,19 +1555,18 @@ copy("$changelog_path.dch","$changelog_path") or
 if ((basename(cwd()) =~ m%^\Q$PACKAGE\E-\Q$UVERSION\E$%) &&
     !$opt_p && !$opt_create) {
     # Find the current version number etc.
-    my ($new_version, $new_sversion, $new_uversion);
+    my $v;
     my $changelog = changelog_parse();
     if (exists $changelog->{Version}) {
-	$new_version = $changelog->{Version};
+	$v = Dpkg::Version->new($changelog->{Version});
     }
 
     fatal "No version number in debian/changelog!"
-	unless defined $new_version;
+	unless $v;
 
-    # Is this a native Debian package, i.e., does it have a - in the
-    # version number?
-    $new_version =~ s/^\d+://;  # remove epoch
-    ($new_uversion=$new_version) =~ s/-[^-]*$//;  # remove revision
+    my ($new_version, $new_uversion);
+    $new_version = $v->as_string(omit_epoch => 1);
+    $new_uversion = $v->as_string(omit_epoch => 1, omit_revision => 1);
 
     if ($new_uversion ne $UVERSION) {
 	# Then we rename the directory
@@ -1575,11 +1575,13 @@ if ((basename(cwd()) =~ m%^\Q$PACKAGE\E-\Q$UVERSION\E$%) &&
 	} else {
 	    warn "$progname warning: Couldn't rename directory: $!\n";
 	}
-	# And check whether a new orig tarball exists
-	my @origs = glob("../$PACKAGE\_$new_uversion.*");
-	my $num_origs = grep { /^..\/\Q$PACKAGE\E_\Q$new_uversion\E\.orig\.tar\.$compression_re$/ } @origs;
-	if ($num_origs == 0) {
-	    warn "$progname warning: no orig tarball found for the new version.\n";
+	if (!$v->is_native()) {
+	    # And check whether a new orig tarball exists
+	    my @origs = glob("../$PACKAGE\_$new_uversion.*");
+	    my $num_origs = grep { /^..\/\Q$PACKAGE\E_\Q$new_uversion\E\.orig\.tar\.$compression_re$/ } @origs;
+	    if ($num_origs == 0) {
+		warn "$progname warning: no orig tarball found for the new version.\n";
+	    }
 	}
     }
 }
diff --git a/scripts/debcheckout.pl b/scripts/debcheckout.pl
index 4a28f36..3477f8a 100755
--- a/scripts/debcheckout.pl
+++ b/scripts/debcheckout.pl
@@ -80,6 +80,9 @@ for Subversion repositories hosted on alioth this means that
 S<I<svn+ssh://svn.debian.org/...>> will be used instead of
 S<I<svn://svn.debian.org/...>>.
 
+There are built-in rules for alioth.debian.org and github.com. Other hosts
+can be configured using B<DEBCHECKOUT_AUTH_URLS>.
+
 =item B<-d>, B<--details>
 
 Only print a list of detailed information about the package
@@ -119,7 +122,7 @@ should be one of the currently supported repository types.
 Specify the login name to be used in authenticated mode (see B<-a>). This option
 implies B<-a>: you don't need to specify both.
 
-=item B<-f>, B<--file>
+=item B<-f> I<FILE>, B<--file> I<FILE>
 
 Specify that the named file should be extracted from the repository and placed
 in the destination directory. May be used more than once to extract multiple
@@ -448,13 +451,17 @@ sub set_auth($$$$) {
     my $user_url = $url;
 
     # Adjust urls from new-style anonymous access to old-style and then deal
-    # with adjusting for authentication
+    # with adjusting for authentication on alioth
     $url =~ s@(?:alioth\.debian\.org/(?:anonscm/bzr|scm/loggerhead/bzr)|anonscm\.debian\.org/bzr(?:/bzr)?)@bzr.debian.org/bzr@;
     $url =~ s@(?:alioth\.debian\.org/anonscm/darcs|anonscm\.debian\.org/darcs)@darcs.debian.org/darcs@;
     $url =~ s at git://anonscm\.debian\.org at git://git.debian.org@;
     $url =~ s@(?:alioth\.debian\.org/anonscm/git|anonscm\.debian\.org/git)@git.debian.org/git@;
     $url =~ s@(?:alioth\.debian\.org/anonscm/hg|anonscm\.debian\.org/hg)@hg.debian.org/hg@;
     $url =~ s at svn://(?:scm\.alioth|anonscm)\.debian\.org at svn://svn.debian.org@;
+
+    # other providers
+    $url =~ s!git://github\.com/!git\@github.com:!;
+
     given ($repo_type) {
 	when ("bzr") {
 	    $url =~ s|^[\w+]+://(bzr\.debian\.org)/(.*)|bzr+ssh://$user$1/bzr/$2|;
diff --git a/scripts/debcommit.pl b/scripts/debcommit.pl
index 352bdcd..7bf6d95 100755
--- a/scripts/debcommit.pl
+++ b/scripts/debcommit.pl
@@ -448,7 +448,8 @@ sub getprog {
     if (-d ".bzr") {
 	return "bzr";
     }
-    if (-d ".git") {
+    if (-e ".git") {
+	# With certain forms of git checkouts, .git can be a file instead of a directory
 	return "git";
     }
     if (-d ".hg") {
@@ -474,7 +475,7 @@ sub getprog {
 	if (-d "$dir/.bzr") {
 	    return "bzr";
 	}
-	if (-d "$dir/.git") {
+	if (-e "$dir/.git") {
 	    return "git";
 	}
 	if (-d "$dir/.hg") {
diff --git a/scripts/getbuildlog.sh b/scripts/getbuildlog.sh
index 6a8c107..0e3bc00 100755
--- a/scripts/getbuildlog.sh
+++ b/scripts/getbuildlog.sh
@@ -149,4 +149,3 @@ arch=$ARCH&ver=$LASTVERSION&stamp=[[:digit:]]+"
 }
 
 getbuildlog https://buildd.debian.org
-getbuildlog http://buildd.debian-ports.org
diff --git a/scripts/licensecheck.pl b/scripts/licensecheck.pl
index 78d9fd7..3d1ff2e 100755
--- a/scripts/licensecheck.pl
+++ b/scripts/licensecheck.pl
@@ -74,7 +74,11 @@ recursively.
 Specify a pattern against which filenames will be matched in order to
 decide which files to check the license of.
 
-The default includes common source files.
+=item B<-t>, B<--text>
+
+By default, all files are parsed, including binary files. This option
+limits the parsed files to mime type C<text/*> and C<application/xml>.
+The mime type is given by C<file> command.
 
 =item B<--copyright>
 
@@ -131,6 +135,16 @@ General Public License, version 2 or later.
 
 Adam D. Barratt <adam at adam-barratt.org.uk>
 
+=head1 SEE ALSO
+
+=over
+
+=item *
+
+L<file>
+
+=back
+
 =cut
 
 # see http://stackoverflow.com/questions/6162484/why-does-modern-perl-avoid-utf-8-by-default/6163129#6163129
@@ -169,9 +183,6 @@ my $default_ignore_regex = qr!
 \.shelf|_MTN|\.bzr(?:\.backup|tags)?)(?:$|/.*$)
 !x;
 
-my $default_check_regex = '\.(c(c|pp|xx)?|h(h|pp|xx)?|S|f(77|90)?|go|groovy|scala|clj|p(l|m)|xs|sh|php|py(|x)|rb|java|js|vala|el|sc(i|e)|cs|pas|inc|dtd|xsl|mod|m|tex|mli?|(c|l)?hs)$';
-
-
 # also used to cleanup
 my $copyright_indicator_regex
     = qr!
@@ -210,6 +221,7 @@ my %OPT=(
     recursive      => 0,
     copyright      => 0,
     machine        => 0,
+    text           => 0,
 );
 
 my $def_lines = 60;
@@ -267,14 +279,16 @@ GetOptions(\%OPT,
            "machine|m",
            "noconf|no-conf",
            "recursive|r",
+	   "text|t",
            "verbose!",
            "version|v",
 ) or die "Usage: $progname [options] filelist\nRun $progname --help for more details\n";
 
 $OPT{'lines'} = $def_lines if $OPT{'lines'} !~ /^[1-9][0-9]*$/;
 my $ignore_regex = length($OPT{ignore}) ? qr/$OPT{ignore}/ : $default_ignore_regex;
-$OPT{'check'} = $default_check_regex if ! length $OPT{'check'};
-my $check_regex = qr/$OPT{check}/;
+
+my $check_regex ;
+$check_regex = qr/$OPT{check}/ if length $OPT{check};
 
 if ($OPT{'noconf'}) {
     fatal("--no-conf is only acceptable as the first command-line option!");
@@ -302,14 +316,14 @@ while (@ARGV) {
 
 	while (my $found = <$FIND>) {
 	    chomp ($found);
-	    next unless $found =~ $check_regex;
+	    next if ( $check_regex and $found !~ $check_regex );
 	    # Skip empty files
 	    next if (-z $found);
 	    push @files, $found unless $found =~ $ignore_regex;
 	}
 	close $FIND;
     } else {
-	next unless ($files_count == 1) or $file =~ $check_regex;
+	next unless ($files_count == 1) or ( $check_regex and $file =~ $check_regex);
 	push @files, $file unless $file =~ $ignore_regex;
     }
 }
@@ -336,6 +350,7 @@ while (@files) {
 	chomp $mime;
 	warn "$0 warning: cannot parse file '$file' with mime type '$mime'\n";
 	$charset = 'maybe-binary';
+	next if $OPT{text};
     }
 
     open (my $F, '<' ,$file) or die "Unable to access $file\n";
@@ -376,6 +391,7 @@ sub extract_copyright {
     my @c = split /\n/, clean_comments($content);
 
     my %copyrights;
+    my $lines_after_copyright_block = 0;
 
     while (@c) {
 	my $line = shift @c ;
@@ -388,6 +404,11 @@ sub extract_copyright {
 	    $copyright_match =~ s/\s+/ /g;
 	    $copyrights{lc("$copyright_match")} = "$copyright_match";
         }
+	elsif (scalar keys %copyrights) {
+	    # skip remaining lines if a copyright blocks was found more than 5 lines ago.
+	    # so a copyright block may contain up to 5 blank lines, but no more
+	    last if $lines_after_copyright_block++ > 5;
+	}
     }
     return %copyrights;
 }
@@ -408,8 +429,8 @@ sub parse_copyright {
                 $match =~ s/$copyright_indicator_regex//igx;
                 $match =~ s/^\s+//;
                 $match =~ s/\s{2,}/ /g;
-                $match =~ s/\\@/@/g;
-                $match =~ s/\s*\*\s*$//;
+		$match =~ s/\\//g; # de-cruft nroff files
+                $match =~ s/\s*[*#]\s*$//;
                 $copyright = $match;
             }
         }
@@ -466,7 +487,7 @@ Valid options are:
                             (Default: $def_lines)
    --check, -c            Specify a pattern indicating which files should
                              be checked
-                             (Default: '$default_check_regex')
+                             (Default: All text and xml files)
    --machine, -m          Display in a machine readable way (good for awk)
    --recursive, -r        Add the contents of directories recursively
    --copyright            Also display the file's copyright
diff --git a/scripts/mergechanges.1 b/scripts/mergechanges.1
index f6253fa..f815862 100644
--- a/scripts/mergechanges.1
+++ b/scripts/mergechanges.1
@@ -2,7 +2,7 @@
 .SH NAME
 mergechanges \- merge multiple changes files
 .SH SYNOPSIS
-\fBmergechanges\fR [\fB\-d\fR] [\fB\-f\fR] [\fB\-i\fR] \fIfile1 file2\fR [\fIfile\fR...]
+\fBmergechanges\fR [\fB\-d\fR] [\fB\-f\fR] [\fB\-S\fR] [\fB\-i\fR] \fIfile1 file2\fR [\fIfile\fR...]
 .SH DESCRIPTION
 \fBmergechanges\fR merges two or more \fI.changes\fR files, merging
 the Architecture, Description and Files (and Checksums-*, if present)
@@ -22,6 +22,9 @@ input files will be deleted.
 If the \fB\-i\fR or \fB\-\-indep\fR option is given, source packages
 and architecture-independent (Architecture: all) packages are included
 in the output, but architecture-dependent packages are not.
+.PP
+If the \fB\-S\fR or \fB\-\-source\fR option is given, only source packages
+are included in the output.
 .SH AUTHOR
 Gergely Nagy <algernon at debian.org>,
 modifications by Julian Gilbey <jdg at debian.org>,
diff --git a/scripts/mergechanges.sh b/scripts/mergechanges.sh
index 86a1747..1e07622 100755
--- a/scripts/mergechanges.sh
+++ b/scripts/mergechanges.sh
@@ -24,17 +24,18 @@ set -e
 PROGNAME=`basename $0`
 
 synopsis () {
-    echo "Usage: $PROGNAME [-h|--help|--version] [-d] [-i|--indep] [-f] <file1> <file2> [<file> ...]"
+    echo "Usage: $PROGNAME [-h|--help|--version] [-d] [-S|--source] [-i|--indep] [-f] <file1> <file2> [<file> ...]"
 }
 
 usage () {
     synopsis
-    echo <<EOT
+    cat <<EOT
   Merge the changes files <file1>, <file2>, ....  Output on stdout
   unless -f option given, in which case, output to
   <package>_<version>_multi.changes in the same directory as <file1>.
   If -i is given, only source and architecture-independent packages
-  are included in the output."
+  are included in the output.
+  If -S is given, only the source package is included in the output.
 EOT
 }
 
@@ -51,7 +52,8 @@ GNU General Public License, version 2 or later."
 # Commandline parsing
 FILE=0
 DELETE=0
-INDEP_ONLY=0
+REMOVE_ARCHDEP=0
+REMOVE_INDEP=0
 
 while [ $# -gt 0 ]; do
     case "$1" in
@@ -72,7 +74,12 @@ while [ $# -gt 0 ]; do
 	    shift
 	    ;;
 	-i|--indep)
-	    INDEP_ONLY=1
+	    REMOVE_ARCHDEP=1
+	    shift
+	    ;;
+	-S|--source)
+	    REMOVE_ARCHDEP=1
+	    REMOVE_INDEP=1
 	    shift
 	    ;;
 	-*)
@@ -104,33 +111,45 @@ done
 # and merge them, sorting out duplicates. Skip architectures
 # other than all and source if desired.
 ARCHS=$(grep -h "^Architecture: " "$@" | sed -e "s,^Architecture: ,," | tr ' ' '\n' | sort -u)
-if test ${INDEP_ONLY} = 1; then
+if test ${REMOVE_ARCHDEP} = 1; then
     ARCHS=$(echo "$ARCHS" | grep -E '^(all|source)$')
 fi
+if test ${REMOVE_INDEP} = 1; then
+    ARCHS=$(echo "$ARCHS" | grep -vxF all)
+fi
 ARCHS=$(echo "$ARCHS" | tr '\n' ' ' | sed 's/ $//')
 
 checksum_uniq() {
     local line
     local IFS=
-    if test ${INDEP_ONLY} = 1; then
-        while read line; do
-            case "$line" in
-                (*.dsc|*.diff.gz|*.tar.*|*_all.deb|*_all.udeb)
-                    # source or architecture-independent
-                    echo "$line"
-                    ;;
-                (*.deb|*.udeb)
-                    # architecture-specific, ignore
-                    ;;
-                (*)
-                    echo "Unrecognised file, is it architecture-dependent?" >&2
-                    echo "$line" >&2
-                    exit 1
-                    ;;
-            esac
-        done | awk '{if(arr[$NF] != 1){arr[$NF] = 1; print;}}'
+    if test ${REMOVE_ARCHDEP} = 1 -o ${REMOVE_INDEP} = 1; then
+	while read line; do
+	    case "$line" in
+		(*.dsc|*.diff.gz|*.tar.*)
+		    # source
+		    echo "$line"
+		    ;;
+		(*_all.deb|*_all.udeb)
+		    # architecture-indep
+		    if test ${REMOVE_INDEP} = 0; then
+			echo "$line"
+		    fi
+		    ;;
+		(*.deb|*.udeb)
+		    # architecture-specific
+		    if test ${REMOVE_ARCHDEP} = 0; then
+			echo "$line"
+		    fi
+		    ;;
+		(*)
+		    echo "Unrecognised file, is it architecture-dependent?" >&2
+		    echo "$line" >&2
+		    exit 1
+		    ;;
+	    esac
+	done | awk '{if(arr[$NF] != 1){arr[$NF] = 1; print;}}'
     else
-        awk '{if(arr[$NF] != 1){arr[$NF] = 1; print;}}'
+	awk '{if(arr[$NF] != 1){arr[$NF] = 1; print;}}'
     fi
 }
 
diff --git a/scripts/mk-origtargz.pl b/scripts/mk-origtargz.pl
index 0126132..ef2c75e 100755
--- a/scripts/mk-origtargz.pl
+++ b/scripts/mk-origtargz.pl
@@ -470,8 +470,15 @@ if ($deletecount) {
 if ($do_repack || $deletecount) {
     decompress_archive($upstream_tar, $destfiletar);
     unlink $upstream_tar if $mode eq "rename";
-    spawn(exec => ['tar', '--delete', '--file', $destfiletar, @to_delete ],
-	  wait_child => 1) if scalar(@to_delete) > 0;
+    # We have to use piping because --delete is broken otherwise, as documented
+    # at https://www.gnu.org/software/tar/manual/html_node/delete.html
+    if (@to_delete > 0) {
+	spawn(exec => ['tar', '--delete', @to_delete ],
+	      from_file => $destfiletar,
+	      to_file => $destfiletar . ".tmp",
+	      wait_child => 1) if scalar(@to_delete) > 0;
+	move ($destfiletar . ".tmp", $destfiletar);
+    }
     compress_archive($destfiletar, $destfile, $compression);
 
     # Symlink no longer makes sense
diff --git a/scripts/origtargz.pl b/scripts/origtargz.pl
index ee20715..4c404a5 100755
--- a/scripts/origtargz.pl
+++ b/scripts/origtargz.pl
@@ -317,7 +317,7 @@ sub clean_checkout ()
 		push @rm, $file;
 	}
 	close DIR;
-	system ('rm', '-rf', @rm);
+	system ('rm', '-rf', '--', @rm);
 }
 
 sub unpack_tarball ($)
@@ -349,7 +349,7 @@ sub unpack_tarball ($)
 	opendir DIR, $directory or die "opendir $directory: $!";
 	foreach my $file (readdir DIR) {
 		if ($file eq 'debian') {
-			system ('rm', '-rf', "$directory/$file");
+			system ('rm', '-rf', '--', "$directory/$file");
 			next;
 		} elsif ($file eq '.' or $file eq '..') {
 			next;
diff --git a/scripts/tagpending.pl b/scripts/tagpending.pl
index fde1a04..cbf789a 100755
--- a/scripts/tagpending.pl
+++ b/scripts/tagpending.pl
@@ -155,7 +155,10 @@ if (! -f 'debian/changelog') {
 
 my $changelog = changelog_parse(%opt_to);
 my $source = $changelog->{Source};
-my @closes = split ' ', $changelog->{Closes};
+my @closes;
+if ($changelog->{Closes}) {
+    @closes = split ' ', $changelog->{Closes};
+}
 my @lines = split /\n/, $changelog->{Changes};
 my $header = $lines[1];
 my $changes = join "\n", grep /^ {3}[^[]/, @lines;
@@ -166,25 +169,27 @@ $changes .= "   *";
 
 my $pending;
 my $open;
+my %bugs = map { $_ => 1 } @closes;
 
-if ($opt_online) {
-    if (!Devscripts::Debbugs::have_soap()) {
-	die "$progname: The libsoap-lite-perl package is required for online operation; aborting.\n";
-    }
+if (%bugs) {
+    if ($opt_online) {
+	if (!Devscripts::Debbugs::have_soap()) {
+	    die "$progname: The libsoap-lite-perl package is required for online operation; aborting.\n";
+	}
 
-    eval {
-	$pending = Devscripts::Debbugs::select( "src:$source", "status:open", "status:forwarded", "tag:pending" );
-	$open = Devscripts::Debbugs::select( "src:$source", "status:open", "status:forwarded" );
-    };
+	eval {
+	    $pending = Devscripts::Debbugs::select( "src:$source", "status:open", "status:forwarded", "tag:pending" );
+	    $open = Devscripts::Debbugs::select( "src:$source", "status:open", "status:forwarded" );
+	};
 
-    if ($@) {
-	die "$@\nUse --force to tag all bugs anyway.\n";
+	if ($@) {
+	    die "$@\nUse --force to tag all bugs anyway.\n";
+	}
     }
-}
 
-my %bugs = map { $_ => 1} @closes;
-if ($pending) {
-    %bugs = ( %bugs, map { $_ => 1} @{$pending} );
+    if ($pending) {
+	%bugs = ( %bugs, map { $_ => 1 } @{$pending} );
+    }
 }
 
 my $bug;
diff --git a/scripts/uscan.pl b/scripts/uscan.pl
index bfb7211..89ee442 100755
--- a/scripts/uscan.pl
+++ b/scripts/uscan.pl
@@ -121,6 +121,11 @@ Options:
                    Specify the version which the upstream release must
                    match in order to be considered, rather than using the
                    release with the highest version
+    --download-debversion VERSION
+		   Specify the Debian package version to download the
+		   corresponding upstream release version.  The
+		   dversionmangle and uversionmangle rules are
+		   considered.
     --download-current-version
                    Download the currently packaged version
     --package PACKAGE
@@ -177,6 +182,7 @@ my $destdir = "..";
 my $download = 1;
 my $download_version;
 my $force_download = 0;
+my $badversion = 0;
 my $report = 0; # report even on up-to-date packages?
 my $repack = 0; # repack .tar.bz2, .tar.lzma, .tar.xz or .zip to .tar.gz
 my $default_compression = 'gzip' ;
@@ -285,7 +291,7 @@ my ($opt_h, $opt_v, $opt_destdir, $opt_download, $opt_force_download,
     $opt_repack_compression, $opt_exclusion, $opt_copyright_file);
 my ($opt_verbose, $opt_level, $opt_regex, $opt_noconf);
 my ($opt_package, $opt_uversion, $opt_watchfile, $opt_dehs, $opt_timeout);
-my $opt_download_version;
+my ($opt_download_version, $opt_download_debversion);
 my $opt_user_agent;
 my $opt_download_current_version;
 
@@ -294,6 +300,7 @@ GetOptions("help" => \$opt_h,
 	   "destdir=s" => \$opt_destdir,
 	   "download!" => \$opt_download,
 	   "download-version=s" => \$opt_download_version,
+	   "download-debversion=s" => \$opt_download_debversion,
 	   "force-download" => \$opt_force_download,
 	   "report" => sub { $opt_download = 0; },
 	   "report-status" => sub { $opt_download = 0; $opt_report = 1; },
@@ -361,7 +368,6 @@ $dehs = $opt_dehs if defined $opt_dehs;
 $exclusion = $opt_exclusion if defined $opt_exclusion;
 $copyright_file = $opt_copyright_file if defined $opt_copyright_file;
 $user_agent_string = $opt_user_agent if defined $opt_user_agent;
-$download_version = $opt_download_version if defined $opt_download_version;
 
 if (defined $opt_level) {
     if ($opt_level =~ /^[012]$/) { $check_dirname_level = $opt_level; }
@@ -802,33 +808,33 @@ sub process_watchline ($$$$$$)
 
 	    my @opts = split /,/, $opts;
 	    foreach my $opt (@opts) {
-		if ($opt eq 'pasv' or $opt eq 'passive') {
+		if ($opt =~ /^\s*pasv\s*$/ or $opt =~ /^\s*passive\s*$/) {
 		    $options{'pasv'}=1;
 		}
-		elsif ($opt eq 'active' or $opt eq 'nopasv'
-		       or $opt eq 'nopassive') {
+		elsif ($opt =~ /^\s*active\s*$/ or $opt =~ /^\s*nopasv\s*$/
+		       or $opt =~ /^s*nopassive\s*$/) {
 		    $options{'pasv'}=0;
 		}
-		elsif ($opt =~ /^repacksuffix\s*=\s*(.+)/) {
+		elsif ($opt =~ /^\s*repacksuffix\s*=\s*(.+?)\s*$/) {
 		    $options{'repacksuffix'} = $1;
 		}
-		elsif ($opt =~ /^uversionmangle\s*=\s*(.+)/) {
+		elsif ($opt =~ /^\s*uversionmangle\s*=\s*(.+?)\s*$/) {
 		    @{$options{'uversionmangle'}} = split /;/, $1;
 		}
-		elsif ($opt =~ /^dversionmangle\s*=\s*(.+)/) {
+		elsif ($opt =~ /^\s*dversionmangle\s*=\s*(.+?)\s*$/) {
 		    @{$options{'dversionmangle'}} = split /;/, $1;
 		}
-		elsif ($opt =~ /^versionmangle\s*=\s*(.+)/) {
+		elsif ($opt =~ /^\s*versionmangle\s*=\s*(.+?)\s*$/) {
 		    @{$options{'uversionmangle'}} = split /;/, $1;
 		    @{$options{'dversionmangle'}} = split /;/, $1;
 		}
-		elsif ($opt =~ /^filenamemangle\s*=\s*(.+)/) {
+		elsif ($opt =~ /^\s*filenamemangle\s*=\s*(.+?)\s*$/) {
 		    @{$options{'filenamemangle'}} = split /;/, $1;
 		}
-		elsif ($opt =~ /^downloadurlmangle\s*=\s*(.+)/) {
+		elsif ($opt =~ /^\s*downloadurlmangle\s*=\s*(.+?)\s*$/) {
 		    @{$options{'downloadurlmangle'}} = split /;/, $1;
 		}
-		elsif ($opt =~ /^pgpsigurlmangle\s*=\s*(.+)/) {
+		elsif ($opt =~ /^\s*pgpsigurlmangle\s*=\s*(.+?)\s*$/) {
 		    @{$options{'pgpsigurlmangle'}} = split /;/, $1;
 		}
 		else {
@@ -847,7 +853,7 @@ sub process_watchline ($$$$$$)
 	    (undef, $lastversion, $action) = split ' ', $line, 3;
 	}
 
-	if ((!$lastversion or $lastversion eq 'debian') and not defined $pkg_version) {
+	if ((! defined $lastversion or $lastversion eq 'debian') and not defined $pkg_version) {
 	    uscan_warn "$progname warning: Unable to determine current version\n  in $watchfile, skipping:\n  $line\n";
 	    return 1;
 	}
@@ -894,7 +900,7 @@ sub process_watchline ($$$$$$)
 	    $filepattern .= '(?:\?.*)?';
 	}
 	# Handle pypi.python.org addresses specially
-	$base =~ s%^https?://pypi\.python\.org/packages/source/./%http://pypi.debian.net/%;
+	$base =~ s%^https?://pypi\.python\.org/packages/source/./%https://pypi.debian.net/%;
 
 	if ($base =~ m%^(\w+://[^/]+)%) {
 	    $site = $1;
@@ -914,8 +920,7 @@ sub process_watchline ($$$$$$)
 	$basedir =~ s%^\w+://[^/]+/%/%;
 	$pattern = "(?:(?:$site)?" . quotemeta($basedir) . ")?$filepattern";
     }
-
-    if (! $lastversion or $lastversion eq 'debian') {
+    if (! defined $lastversion or $lastversion eq 'debian') {
 	if (defined $pkg_version) {
 	    $lastversion=$pkg_version;
 	} else {
@@ -923,10 +928,20 @@ sub process_watchline ($$$$$$)
 	    return 1;
 	}
     }
+    if (defined $opt_download_debversion) {
+	$lastversion = $opt_download_debversion;
+	$lastversion =~ s/-[^-]+$//;  # revision
+	$lastversion =~ s/^\d+://;    # epoch
+	print STDERR "$progname debug: specified debversion to download: $lastversion\n" if $debug;
+    } else {
+	print STDERR "$progname debug: last pristine tarball version: $lastversion\n" if $debug;
+    }
     # And mangle it if requested
+    print STDERR "$progname debug: last pristine tarball version: $lastversion\n" if $debug;
     my $mangled_lastversion;
     $mangled_lastversion = $lastversion;
     foreach my $pat (@{$options{'dversionmangle'}}) {
+	print STDERR "$progname debug: dversionmangle rule $pat\n" if $debug;
 	if (! safe_replace(\$mangled_lastversion, $pat)) {
 	    uscan_warn "$progname: In $watchfile, potentially"
 	      . " unsafe or malformed dversionmangle"
@@ -936,9 +951,25 @@ sub process_watchline ($$$$$$)
 	    return 1;
 	}
     }
-    if($opt_download_current_version) {
+    print STDERR "$progname debug: dversionmangled last version: $mangled_lastversion\n" if $debug;
+    if($opt_download_version) {
+	$download_version = $opt_download_version;
+	$force_download = 1;
+	$badversion = 1;
+	print STDERR "$progname debug: Force to download the specified version: $download_version\n" if $debug;
+    } elsif (defined $opt_download_debversion) {
+	$download_version = $mangled_lastversion;
+	$force_download = 1;
+	$badversion = 1;
+	print STDERR "$progname debug: Force to download the specified debversion (dversionmangled): $download_version\n" if $debug;
+    } elsif($opt_download_current_version) {
 	$download_version = $mangled_lastversion;
 	$force_download = 1;
+	$badversion = 1;
+	print STDERR "$progname debug: Force to download the current version: $download_version\n" if $debug;
+    } else {
+	# $download_version = undef;
+	print STDERR "$progname debug: Last pristine tarball version (dversionmangled): $mangled_lastversion\n" if $debug;
     }
 
     # Check all's OK
@@ -968,8 +999,7 @@ sub process_watchline ($$$$$$)
 
 	@redirections = @{$user_agent->get_redirections};
 
-	print STDERR "$progname debug: redirections: @redirections\n"
-	    if $debug;
+	print STDERR "$progname debug: redirections: @redirections\n" if ($debug and  @redirections);
 
 	foreach my $_redir (@redirections) {
 	    my $base_dir = $_redir;
@@ -994,7 +1024,7 @@ sub process_watchline ($$$$$$)
 	}
 
 	my $content = $response->content;
-	print STDERR "$progname debug: received content:\n$content\[End of received content]\n"
+	print STDERR "$progname debug: received content:\n$content\n[End of received content]\n"
 	    if $debug;
 
 	if ($content =~ m%^<[?]xml%i &&
@@ -1040,6 +1070,7 @@ sub process_watchline ($$$$$$)
 			    join(".", map { $_ if defined($_) }
 			 	$href =~ m&^$_pattern$&);
 			foreach my $pat (@{$options{'uversionmangle'}}) {
+			    print STDERR "$progname debug: uversionmangle rule $pat\n" if $debug;
 			    if (! safe_replace(\$mangled_version, $pat)) {
 				uscan_warn "$progname: In $watchfile, potentially"
 			 	 . " unsafe or malformed uversionmangle"
@@ -1063,6 +1094,7 @@ sub process_watchline ($$$$$$)
 		my @vhrefs = grep { $$_[0] eq $download_version } @hrefs;
 		if (@vhrefs) {
 		    ($newversion, $newfile) = @{$vhrefs[0]};
+		    print STDERR "$progname debug: Found remote URL matiching the requested version.\n" if $debug;
 		} else {
 		    uscan_warn "$progname warning: In $watchfile no matching hrefs for version $download_version"
 			. " in watch line\n  $line\n";
@@ -1074,6 +1106,7 @@ sub process_watchline ($$$$$$)
 	    }
 	} else {
 	    uscan_warn "$progname warning: In $watchfile,\n  no matching hrefs for watch line\n  $line\n";
+	    print STDERR "$progname debug: Picked URL matiching the newest version.\n" if $debug;
 	    return 1;
 	}
     }
@@ -1100,7 +1133,7 @@ sub process_watchline ($$$$$$)
 	}
 
 	my $content = $response->content;
-	print STDERR "$progname debug: received content:\n$content\[End of received content]\n"
+	print STDERR "$progname debug: received content:\n$content\n[End of received content]\n"
 	    if $debug;
 
 	# FTP directory listings either look like:
@@ -1118,6 +1151,7 @@ sub process_watchline ($$$$$$)
 		my $file = $1;
 		my $mangled_version = join(".", $file =~ m/^$pattern$/);
 		foreach my $pat (@{$options{'uversionmangle'}}) {
+		    print STDERR "$progname debug: uversionmangle rule $pat\n" if $debug;
 		    if (! safe_replace(\$mangled_version, $pat)) {
 			uscan_warn "$progname: In $watchfile, potentially"
 			  . " unsafe or malformed uversionmangle"
@@ -1137,6 +1171,7 @@ sub process_watchline ($$$$$$)
 		    my $file = $1;
 		    my $mangled_version = join(".", $file =~ m/^$filepattern$/);
 		    foreach my $pat (@{$options{'uversionmangle'}}) {
+			print STDERR "$progname debug: uversionmangle rule $pat\n" if $debug;
 			if (! safe_replace(\$mangled_version, $pat)) {
 			    uscan_warn "$progname: In $watchfile, potentially"
 			      . " unsafe or malformed uversionmangle"
@@ -1195,12 +1230,15 @@ EOF
 	    return 1;
 	}
     }
+    print STDERR "$progname debug: new version $newversion\n" if $debug;
+    print STDERR "$progname debug: new filename $newfile\n" if $debug;
 
     my $newfile_base=basename($newfile);
     if (exists $options{'filenamemangle'}) {
         $newfile_base=$newfile;
     }
     foreach my $pat (@{$options{'filenamemangle'}}) {
+	print STDERR "$progname debug: filenamemangle rule $pat\n" if $debug;
 	if (! safe_replace(\$newfile_base, $pat)) {
 	    uscan_warn "$progname: In $watchfile, potentially"
 	      . " unsafe or malformed filenamemangle"
@@ -1218,6 +1256,7 @@ EOF
 	    $newfile_base = "$pkg-$newversion.download";
 	}
     }
+    print STDERR "$progname debug: filenamemangled new filename $newfile_base\n" if $debug;
 
     # So what have we got to report now?
     my $upstream_url;
@@ -1285,6 +1324,7 @@ EOF
 	$upstream_url =~ s/&/&/g;
 	if (exists $options{'downloadurlmangle'}) {
 	    foreach my $pat (@{$options{'downloadurlmangle'}}) {
+		print STDERR "$progname debug: downloadurlmangle rule $pat\n" if $debug;
 		if (! safe_replace(\$upstream_url, $pat)) {
 		    uscan_warn "$progname: In $watchfile, potentially"
 		      . " unsafe or malformed downloadurlmangle"
@@ -1300,10 +1340,12 @@ EOF
 	# FTP site
 	$upstream_url = "$base$newfile";
     }
+    print STDERR "$progname debug: downloadurlmangled upstream URL $upstream_url\n" if $debug;
 
     if (exists $options{'pgpsigurlmangle'}) {
 	$pgpsig_url = $upstream_url;
 	foreach my $pat (@{$options{'pgpsigurlmangle'}}) {
+	    print STDERR "$progname debug: pgpsigurlmangle rule $pat\n" if $debug;
 	    if (! safe_replace(\$pgpsig_url, $pat)) {
 		uscan_warn "$progname: In $watchfile, potentially"
 		  . " unsafe or malformed pgpsigurlmangle"
@@ -1313,6 +1355,7 @@ EOF
 		return 1;
 	    }
 	}
+	print STDERR "$progname debug: pgpsigurlmangled upstream URL $pgpsig_url\n" if $debug;
     }
 
     $dehs_tags{'debian-uversion'} = $lastversion;
@@ -1517,9 +1560,10 @@ EOF
 	      to_string => \$mk_origtargz_out,
 	      wait_child => 1);
 	chomp($mk_origtargz_out);
-	$path = $1 if $mk_origtargz_out =~ /Successfully .* (?:to|as) ([^,]+)\.$/;
+	$path = $1 if $mk_origtargz_out =~ /Successfully .* (?:to|as) ([^,]+)(?:,.*)?\.$/;
 	$path = $1 if $mk_origtargz_out =~ /Leaving (.*) where it is/;
 	$target = basename($path);
+	$newversion = $1 if $target =~ m/[^_]+_(.+)\.orig\.tar\.(?:gz|bz2|lzma|xz)$/;
     }
 
     if ($dehs) {
@@ -1544,8 +1588,14 @@ EOF
 	my @cmd = shellwords($action);
 
 	# Any symlink requests are already handled by uscan
-	if ($action =~ /^uupdate(\s|$)/) {
+	if ($cmd[0] eq "uupdate") {
 	    push @cmd, "--no-symlink";
+	    if ($verbose) {
+		push @cmd, "--verbose";
+	    }
+	    if ($badversion) {
+		push @cmd, "-b";
+	    }
 	}
 
 	if ($watch_version > 1) {
@@ -1620,7 +1670,7 @@ sub newest_dir ($$$$$) {
 	}
 
 	my $content = $response->content;
-	print STDERR "$progname debug: received content:\n$content\[End of received content\]\n"
+	print STDERR "$progname debug: received content:\n$content\n[End of received content\]\n"
 	    if $debug;
 	# We need this horrid stuff to handle href=foo type
 	# links.  OK, bad HTML, but we have to handle it nonetheless.
@@ -1679,7 +1729,7 @@ sub newest_dir ($$$$$) {
 	}
 
 	my $content = $response->content;
-	print STDERR "$progname debug: received content:\n$content\[End of received content]\n"
+	print STDERR "$progname debug: received content:\n$content\n[End of received content]\n"
 	    if $debug;
 
 	# FTP directory listings either look like:
diff --git a/scripts/uupdate.1 b/scripts/uupdate.1
index 41c86ca..e795d4d 100644
--- a/scripts/uupdate.1
+++ b/scripts/uupdate.1
@@ -72,6 +72,9 @@ Simply create a symlink when moving a new upstream \fI.tar.gz\fR
 archive to the new \fI<package>_<version>.orig.tar.gz\fR location.
 This is the default behaviour.
 .TP
+.B \-\-verbose
+Give verbose output.
+.TP
 \fB\-\-no\-symlink\fR
 Copy the upstream \fI.tar.gz\fR to the new location instead of making
 a symlink.
diff --git a/scripts/uupdate.sh b/scripts/uupdate.sh
index e037327..158480c 100755
--- a/scripts/uupdate.sh
+++ b/scripts/uupdate.sh
@@ -51,6 +51,9 @@ For a patch file:
 Options are:
    --upstream-version <version>, -v <version>
                       specify version number of upstream package
+   --force-bad-version, -b
+                      Force a version number to be less than the current one
+                      (e.g., when backporting).
    --rootcmd <gain-root-command>, -r <gain-root-command>
                       which command to be used to become root
                       for package-building
@@ -63,6 +66,7 @@ Options are:
    --no-conf, --noconf
                       Don't read devscripts config files;
                       must be the first option given
+   --verbose          Give verbose output
 
 $PROGNAME [--help|--version]
   show this message or give version information.
@@ -99,6 +103,7 @@ mustsetvar () {
 MPATTERN='^(?:[a-zA-Z][a-zA-Z0-9]*(?:-|_|\.))+(\d+\.(?:\d+\.)*\d+)$'
 
 STATUS=0
+BADVERSION=""
 
 # Boilerplate: set config variables
 DEFAULT_UUPDATE_ROOTCMD=
@@ -170,9 +175,11 @@ fi
 
 TEMP=$(getopt -s bash -o v:p:r:ubs \
         --long upstream-version:,patch:,rootcmd: \
+        --long force-bad-version \
 	--long pristine,no-pristine,nopristine \
 	--long symlink,no-symlink,nosymlink \
 	--long no-conf,noconf \
+	--long verbose \
 	--long help,version -n "$PROGNAME" -- "$@") || (usage >&2; exit 1)
 
 eval set -- $TEMP
@@ -180,6 +187,8 @@ eval set -- $TEMP
 # Process Parameters
 while [ "$1" ]; do
     case $1 in
+    --force-bad-version|-b)
+	BADVERSION="-b" ;;
     --upstream-version|-v)
 	shift; NEW_VERSION="$1" ;;
     --patch|-p)
@@ -197,6 +206,8 @@ while [ "$1" ]; do
     --no-conf|--noconf)
 	echo "$PROGNAME: $1 is only acceptable as the first command-line option!" >&2
 	exit 1 ;;
+    --verbose)
+	UUPDATE_VERBOSE=yes ;;
     --help) usage; exit 0 ;;
     --version) version; exit 0 ;;
     --)	shift; break ;;
@@ -237,11 +248,25 @@ mustsetvar VERSION "`dpkg-parsechangelog -SVersion`" "source version"
 # Get epoch and upstream version
 eval `echo "$VERSION" | perl -ne '/^(?:(\d+):)?(.*)/; print "SVERSION=$2\nEPOCH=$1\n";'`
 
-UVERSION=`expr "$SVERSION" : '\(.*\)-[0-9a-zA-Z.+~]*$'` ||
-{
+if [ -n "$UUPDATE_VERBOSE" ]; then
+    echo "PATCH       = \"$PATCH\" is the name of the patch file" >&2
+    echo "ARCHIVE     = \"$ARCHIVE\" is the name of the next tarball" >&2
+    echo "NEW_VERSION = \"$NEW_VERSION\" is the next pristine tarball version" >&2
+    echo "PACKAGE     = \"$PACKAGE\" is in the top of debian/changelog" >&2
+    echo "VERSION     = \"$VERSION\" is in the top of debian/changelog" >&2
+    echo "EPOCH       = \"$EPOCH\" is epoch part of \$VERSION" >&2
+    echo "SVERSION    = \"$SVERSION\" is w/o-epoch part of \$VERSION" >&2
+fi
+
+UVERSION=`expr "$SVERSION" : '\(.*\)-[0-9a-zA-Z.+~]*$'`
+if [ -z "$UVERSION" ]; then
     echo "$PROGNAME: a native Debian package cannot take upstream updates" >&2
     exit 1
-}
+fi
+
+if [ -n "$UUPDATE_VERBOSE" ]; then
+    echo "UVERSION    = \"$UVERSION\" the upstream portion w/o-epoch of \$VERSION" >&2
+fi
 
 # Save pwd before we goes walkabout
 OPWD=`pwd`
@@ -339,7 +364,7 @@ if [ "$PATCH" ]; then
     fi
 
     # Sanity check
-    if dpkg --compare-versions "$NEW_VERSION-$SUFFIX" le "$VERSION"; then
+    if [ -z "$BADVERSION" ] && dpkg --compare-versions "$NEW_VERSION-$SUFFIX" le "$VERSION"; then
 	echo "$PROGNAME: new version $NEW_VERSION-$SUFFIX <= current version $VERSION; aborting!" >&2
 	exit 1
     fi
@@ -462,7 +487,7 @@ if [ "$PATCH" ]; then
 	    STATUS=1
 	fi
 	chmod a+x debian/rules
-	debchange -v "$NEW_VERSION-$SUFFIX" "New upstream release"
+	debchange $BADVERSION -v "$NEW_VERSION-$SUFFIX" "New upstream release"
 	echo "Remember: Your current directory is the OLD sourcearchive!"
 	echo "Do a \"cd ../$PACKAGE-$SNEW_VERSION\" to see the new package"
 	exit
@@ -551,7 +576,7 @@ else
     fi
 
     # Sanity check
-    if dpkg --compare-versions "$NEW_VERSION-$SUFFIX" le "$VERSION"; then
+    if [ -z "$BADVERSION" ] && dpkg --compare-versions "$NEW_VERSION-$SUFFIX" le "$VERSION"; then
 	echo "$PROGNAME: new version $NEW_VERSION-$SUFFIX <= current version $VERSION; aborting!" >&2
 	exit 1
     fi
@@ -723,6 +748,33 @@ else
 	DIFF="../${PACKAGE}_$SVERSION.debian.tar.xz"
 	DIFFTYPE=tar
 	DIFFUNPACK="tar --xz -xf"
+    else
+	# non-native package and missing diff.gz/debian.tar.xz.
+	cd $OPWD
+	if [ ! -d debian ]; then
+	    echo "$PROGNAME: None of *.diff.gz, *.debian.tar.xz, or debian/* found. failed;" >&2
+	    echo "aborting..." >&2
+	    exit 1
+	fi
+	if [ -d debian/source -a -r debian/source/format ]; then
+	    if [ "`cat debian/source/format`" = "3.0 (quilt)" ]; then
+		# This is convenience for VCS users.
+		echo "$PROGNAME: debian/source/format is \"3.0 (quilt)\"." >&2
+		echo "$PROGNAME: Auto-generating ${PACKAGE}_$SVERSION.debian.tar.xz" >&2
+		tar --xz -cf ../${PACKAGE}_$SVERSION.debian.tar.xz debian
+		DIFF="../${PACKAGE}_$SVERSION.debian.tar.xz"
+		DIFFTYPE=tar
+		DIFFUNPACK="tar --xz -xf"
+	    else
+		echo "$PROGNAME: debian/source/format isn't \"3.0 (quilt)\"." >&2
+		echo "$PROGNAME: Skip auto-generating ${PACKAGE}_$SVERSION.debian.tar.xz" >&2
+	    fi
+	else
+	    echo "$PROGNAME: debian/source/format is missing." >&2
+	    echo "$PROGNAME: Skip auto-generating ${PACKAGE}_$SVERSION.debian.tar.xz" >&2
+	fi
+	# return back to upstream source
+	cd ../$PACKAGE-$SNEW_VERSION
     fi
 
     if [ "$DIFFTYPE" = diff ]; then
@@ -825,6 +877,9 @@ else
 	    echo "to debian.upstream/ and use the Debian version" >&2
 	    mv debian debian.upstream
 	fi
+	if [ -n "$UUPDATE_VERBOSE" ]; then
+	    echo "-- Use ${DIFF} to create the new debian/ directory." >&2
+	fi
 	if $DIFFUNPACK $DIFF; then
 	    echo "Unpacking the debian/ directory from version $VERSION worked fine."
 	else
@@ -835,8 +890,13 @@ else
 	echo "$PROGNAME: could not find {diff|debian.tar}.{gz|bz2|lzma|xz} from version $VERSION to apply!" >&2
 	exit 1
     fi
-    chmod a+x debian/rules
-    debchange -v "$NEW_VERSION-$SUFFIX" New upstream release
+    if [ -f debian/rules ]; then
+	chmod a+x debian/rules
+    fi
+    if [ -n "$UUPDATE_VERBOSE" ]; then
+	echo "-- New upstream release=$NEW_VERSION-$SUFFIX" >&2
+    fi
+    debchange $BADVERSION -v "$NEW_VERSION-$SUFFIX" "New upstream release"
     echo "Remember: Your current directory is the OLD sourcearchive!"
     echo "Do a \"cd ../$PACKAGE-$SNEW_VERSION\" to see the new package"
 fi
diff --git a/scripts/wrap-and-sort b/scripts/wrap-and-sort
index f3a7e55..98a4bb5 100755
--- a/scripts/wrap-and-sort
+++ b/scripts/wrap-and-sort
@@ -145,7 +145,10 @@ class Install(object):
 
 def remove_trailing_whitespaces(filename):
     assert os.path.isfile(filename), "%s does not exist." % (filename)
-    content = open(filename).read().rstrip() + "\n"
+    content = open(filename).read()
+    if len(content) == 0:
+        return
+    content = content.rstrip() + "\n"
     lines = content.split("\n")
     lines = [l.rstrip() for l in lines]
     new_content = "\n".join(lines)
diff --git a/test/Makefile b/test/Makefile
index 0ff65cb..202b6a6 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -6,6 +6,7 @@ test:
 	./test_debdiff
 	./test_licensecheck
 	./test_uscan
+	./test_uscan_mangle
 	./test_mk-origtargz
 
 test-installed:
@@ -16,6 +17,7 @@ test-installed:
 	./test_debdiff --installed
 	./test_licensecheck --installed
 	./test_uscan --installed
+	./test_uscan_mangle --installed
 	./test_mk-origtargz --installed
 
 online-test:
diff --git a/test/dd-list/sources b/test/dd-list/sources
index 1075361..e314539 100644
--- a/test/dd-list/sources
+++ b/test/dd-list/sources
@@ -26,3 +26,160 @@ Homepage: http://www.vim.org/
 Directory: pool/main/v/vim
 Priority: source
 Section: editors
+
+Package: bzip2
+Binary: libbz2-1.0, libbz2-dev, bzip2, bzip2-doc
+Version: 1.0.6-7
+Maintainer: Anibal Monsalve Salazar <anibal at debian.org>
+Uploaders: Santiago Ruano Rincón <santiago at debian.org>, Jorge Ernesto Guevara Cuenca <jguevara at debiancolombia.org>
+Build-Depends: gcc-multilib [amd64 i386 kfreebsd-amd64 powerpc ppc64 s390 sparc] | gcc-4.1 (<< 4.1.2) [amd64 i386 kfreebsd-amd64 powerpc ppc64 s390 sparc], dpkg-dev (>= 1.16.0), debhelper (>= 9), dh-exec
+Build-Depends-Indep: texinfo
+Architecture: any all
+Standards-Version: 3.9.5
+Format: 3.0 (quilt)
+Files:
+ d4850752a3386592ae416b3fd6fc2c3a 2261 bzip2_1.0.6-7.dsc
+ 2a1df12bd405cc86790291797673753c 708737 bzip2_1.0.6.orig.tar.bz2
+ 3bc252d3eb0a16a4f5950fac8deb7bb1 59542 bzip2_1.0.6-7.debian.tar.bz2
+Vcs-Browser: http://git.debian.org/?p=collab-maint/bzip2.git
+Vcs-Git: git://git.debian.org/collab-maint/bzip2.git
+Checksums-Sha1:
+ f970fefd8f7cb4a02ec74d3ecc21c31068201b5c 2261 bzip2_1.0.6-7.dsc
+ 3725a0554fa6bb654ef2728fef36bc06aed4e388 708737 bzip2_1.0.6.orig.tar.bz2
+ e5169afbee8f9ee603c253e03421364819a14c12 59542 bzip2_1.0.6-7.debian.tar.bz2
+Checksums-Sha256:
+ 098b7e38d1d634fc361847602bf85753dadeca121b9531f6dba2614b16e0637c 2261 bzip2_1.0.6-7.dsc
+ d70a9ccd8bdf47e302d96c69fecd54925f45d9c7b966bb4ef5f56b770960afa7 708737 bzip2_1.0.6.orig.tar.bz2
+ 17e030ccb2908d15553c1510869e09d8ef41b5f8e72c7c65d1d5503396a5bd3a 59542 bzip2_1.0.6-7.debian.tar.bz2
+Homepage: http://www.bzip.org/
+Package-List: 
+ bzip2 deb utils standard arch=any
+ bzip2-doc deb doc optional arch=all
+ libbz2-1.0 deb libs important arch=any
+ libbz2-dev deb libdevel optional arch=any
+Extra-Source-Only: yes
+Directory: pool/main/b/bzip2
+Priority: source
+Section: utils
+
+Package: bzip2
+Binary: libbz2-1.0, libbz2-dev, bzip2, bzip2-doc
+Version: 1.0.6-8
+Maintainer: Anibal Monsalve Salazar <anibal at debian.org>
+Uploaders: Santiago Ruano Rincón <santiago at debian.org>
+Build-Depends: dpkg-dev (>= 1.16.0), debhelper (>= 9), dh-exec
+Build-Depends-Indep: texinfo
+Architecture: any all
+Standards-Version: 3.9.6
+Format: 3.0 (quilt)
+Files:
+ 7709d3c0a7715bf4f61cc74adc10ee5a 2042 bzip2_1.0.6-8.dsc
+ 2a1df12bd405cc86790291797673753c 708737 bzip2_1.0.6.orig.tar.bz2
+ 72b1174a04f96b62c1f50391c8f41488 59494 bzip2_1.0.6-8.debian.tar.bz2
+Vcs-Browser: http://git.debian.org/?p=collab-maint/bzip2.git
+Vcs-Git: git://git.debian.org/collab-maint/bzip2.git
+Checksums-Sha1:
+ 8bb35859d49d012e1464db621e740e1702a5ad14 2042 bzip2_1.0.6-8.dsc
+ 3725a0554fa6bb654ef2728fef36bc06aed4e388 708737 bzip2_1.0.6.orig.tar.bz2
+ 78c527bdc6eb5727b79d401ebf3ddf2b175af91f 59494 bzip2_1.0.6-8.debian.tar.bz2
+Checksums-Sha256:
+ 46df0e8112487065532829f2340ffd6ca64d46b6ab01b0000694751d3e67fb11 2042 bzip2_1.0.6-8.dsc
+ d70a9ccd8bdf47e302d96c69fecd54925f45d9c7b966bb4ef5f56b770960afa7 708737 bzip2_1.0.6.orig.tar.bz2
+ 60fe87fd3942c385e5921786255a27daf9a962ebc7301a60dfd8d1e1a5c8ce78 59494 bzip2_1.0.6-8.debian.tar.bz2
+Homepage: http://www.bzip.org/
+Package-List: 
+ bzip2 deb utils standard arch=any
+ bzip2-doc deb doc optional arch=all
+ libbz2-1.0 deb libs important arch=any
+ libbz2-dev deb libdevel optional arch=any
+Directory: pool/main/b/bzip2
+Priority: source
+Section: utils
+
+Package: subversion
+Binary: subversion, subversion-dbg, libsvn1, libsvn-dev, libsvn-doc, libapache2-mod-svn, libapache2-svn, python-subversion, subversion-tools, libsvn-java, libsvn-perl, ruby-svn, libsvn-ruby1.8
+Version: 1.8.13-1
+Maintainer: Peter Samuelson <peter at p12n.org>
+Uploaders: Troy Heber <troyh at debian.org>, James McCoy <jamessan at debian.org>
+Build-Depends: debhelper (>= 8), libserf-dev (>= 1.2), zlib1g-dev, libapr1-dev, libaprutil1-dev, libdb5.3-dev, libsasl2-dev, apache2-dev, dh-apache2, libsqlite3-dev (>= 3.7.12), libgnome-keyring-dev, libdbus-1-dev, kdelibs5-dev, quilt, doxygen, autotools-dev, autoconf, libtool-bin, swig, python-all-dev, perl, libperl-dev, ruby, ruby-dev, default-jdk, junit
+Build-Conflicts: libsvn-dev (<< 1.8~), ruby-test-unit
+Architecture: any all
+Standards-Version: 3.9.5
+Format: 1.0
+Files:
+ 4b08c636bc2c67f22cce2f27f04e4bba 3105 subversion_1.8.13-1.dsc
+ 8065b3698d799507fb72dd7926ed32b6 9326793 subversion_1.8.13.orig.tar.gz
+ 4e2ea3b225f551ec470796203bd14803 270351 subversion_1.8.13-1.diff.gz
+Vcs-Browser: http://anonscm.debian.org/viewvc/pkg-subversion/src/1.8.x/
+Vcs-Svn: svn://anonscm.debian.org/pkg-subversion/src/1.8.x/
+Checksums-Sha1:
+ 80a8c73f36c57d476989d949f31cf1504631e5fb 3105 subversion_1.8.13-1.dsc
+ 437cf662b7ed27d2254aa7ca334fdd74b49262ef 9326793 subversion_1.8.13.orig.tar.gz
+ be7fdefbc914b305c38698897f2d061b93942b79 270351 subversion_1.8.13-1.diff.gz
+Checksums-Sha256:
+ 26fb93f8adf42cf1bc3afae7890a4bbfff32d860dcb805eb20d8013bffe3e063 3105 subversion_1.8.13-1.dsc
+ 17e8900a877ac9f0d5ef437c20df437fec4eb2c5cb9882609d2277e2312da52c 9326793 subversion_1.8.13.orig.tar.gz
+ 7cf687a60566f4f41ea70f6e028253880ea0d2b52d6dead5ba99c9e298a8245d 270351 subversion_1.8.13-1.diff.gz
+Homepage: http://subversion.apache.org/
+Package-List: 
+ libapache2-mod-svn deb httpd optional arch=any
+ libapache2-svn deb oldlibs extra arch=all
+ libsvn-dev deb libdevel extra arch=any
+ libsvn-doc deb doc extra arch=all
+ libsvn-java deb java optional arch=any
+ libsvn-perl deb perl optional arch=any
+ libsvn-ruby1.8 deb oldlibs extra arch=all
+ libsvn1 deb libs optional arch=any
+ python-subversion deb python optional arch=any
+ ruby-svn deb ruby optional arch=any
+ subversion deb vcs optional arch=any
+ subversion-dbg deb debug extra arch=any
+ subversion-tools deb vcs extra arch=any
+Testsuite: autopkgtest
+Directory: pool/main/s/subversion
+Priority: source
+Section: vcs
+
+Package: subversion
+Binary: subversion, subversion-dbg, libsvn1, libsvn-dev, libsvn-doc, libapache2-mod-svn, libapache2-svn, python-subversion, subversion-tools, libsvn-java, libsvn-perl, ruby-svn, libsvn-ruby1.8
+Version: 1.9.2-1
+Maintainer: Peter Samuelson <peter at p12n.org>
+Uploaders: James McCoy <jamessan at debian.org>
+Build-Depends: apache2-dev (>= 2.4.16), autoconf, autotools-dev, bash-completion, debhelper (>= 8), default-jdk (>= 2:1.6) [!hurd-i386 !kfreebsd-amd64 !kfreebsd-i386 !hppa !m68k !sparc !sparc64], dh-apache2, dh-python, doxygen, junit [!hurd-i386 !kfreebsd-amd64 !kfreebsd-i386 !hppa !m68k !sparc !sparc64], kdelibs5-dev, libapr1-dev, libaprutil1-dev, libdb5.3-dev, libdbus-1-dev, libgnome-keyring-dev, libperl-dev, libsasl2-dev, libserf-dev (>= 1.3.4), libsqlite3-dev (>= 3.7.12), libtool, pe [...]
+Build-Conflicts: libsvn-dev (<< 1.9~)
+Architecture: any all
+Standards-Version: 3.9.5
+Format: 1.0
+Files:
+ ead24ca2537b45470a38ff0c568f371b 3259 subversion_1.9.2-1.dsc
+ c3f4a2d2f21c565617e97f7640c3c81d 10625378 subversion_1.9.2.orig.tar.gz
+ 939a431c1f383a8b93a38c05982c32d8 2418695 subversion_1.9.2-1.diff.gz
+Vcs-Browser: http://anonscm.debian.org/viewvc/pkg-subversion/src/1.9.x/
+Vcs-Svn: svn://anonscm.debian.org/pkg-subversion/src/1.9.x/
+Checksums-Sha1:
+ 48a7fc952190b738f307e85fb87737f173d49dd4 3259 subversion_1.9.2-1.dsc
+ 4c57828c07d21b4777a058f0d3dc973652d18ce9 10625378 subversion_1.9.2.orig.tar.gz
+ aa869fff7dc7116fd4dafc344cd21ca52bbe00c5 2418695 subversion_1.9.2-1.diff.gz
+Checksums-Sha256:
+ 0020561afd37b3cf20661c7e5da23fde210a1cc70ddfd679604216bb0cb368e4 3259 subversion_1.9.2-1.dsc
+ 6fe6ef49114e9ca2942063e339ce886078612c4e6cc58f268a2ff4db4cf0cf19 10625378 subversion_1.9.2.orig.tar.gz
+ 8deef11131ab873821696e83a1bc2fd175773f52fb8619257073896fdb200187 2418695 subversion_1.9.2-1.diff.gz
+Homepage: http://subversion.apache.org/
+Package-List: 
+ libapache2-mod-svn deb httpd optional arch=any
+ libapache2-svn deb oldlibs extra arch=all
+ libsvn-dev deb libdevel extra arch=any
+ libsvn-doc deb doc extra arch=all
+ libsvn-java deb java optional arch=any
+ libsvn-perl deb perl optional arch=any
+ libsvn-ruby1.8 deb oldlibs extra arch=all
+ libsvn1 deb libs optional arch=any
+ python-subversion deb python optional arch=any
+ ruby-svn deb ruby optional arch=any
+ subversion deb vcs optional arch=any
+ subversion-dbg deb debug extra arch=any
+ subversion-tools deb vcs extra arch=any
+Testsuite: autopkgtest
+Directory: pool/main/s/subversion
+Priority: source
+Section: vcs
diff --git a/test/licensecheck/duplicated-copyright.rb b/test/licensecheck/duplicated-copyright.rb
new file mode 100644
index 0000000..b7fef8a
--- /dev/null
+++ b/test/licensecheck/duplicated-copyright.rb
@@ -0,0 +1,43 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs        #
+#                                                                            #
+# Licensed under the Apache License, Version 2.0 (the "License"); you may    #
+# not use this file except in compliance with the License. You may obtain    #
+# a copy of the License at                                                   #
+#                                                                            #
+# http://www.apache.org/licenses/LICENSE-2.0                                 #
+#                                                                            #
+# Unless required by applicable law or agreed to in writing, software        #
+# distributed under the License is distributed on an "AS IS" BASIS,          #
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+# See the License for the specific language governing permissions and        #
+# limitations under the License.                                             #
+#--------------------------------------------------------------------------- #
+
+require 'cli_helper'
+
+begin
+    require 'opennebula'
+rescue Exception => e
+    puts "Error: "+e.message.to_s
+    exit(-1)
+end
+
+include OpenNebula
+
+module OpenNebulaHelper
+    ONE_VERSION=<<-EOT
+OpenNebula #{OpenNebula::VERSION}
+Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may
+not use this file except in compliance with the License. You may obtain
+a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+EOT
+
+    if ONE_LOCATION
+        TABLE_CONF_PATH=ONE_LOCATION+"/etc/cli"
+    else
+        TABLE_CONF_PATH="/etc/one/cli"
+    end
+
diff --git a/test/test_dd-list b/test/test_dd-list
index e9619ac..a92b0b7 100755
--- a/test/test_dd-list
+++ b/test/test_dd-list
@@ -15,19 +15,31 @@
 # You should have received a copy of the GNU General Public License
 # along with this program. If not, see <http://www.gnu.org/licenses/>.
 
+WORKDIR="$(readlink -f "${0%/*}")"
+
 if test "$1" = --installed; then
     COMMAND=dd-list
     shift
 else
-    COMMAND="../scripts/dd-list.pl"
+    COMMAND="$WORKDIR/../scripts/dd-list.pl"
 fi
 
-WORKDIR="$(readlink -f "${0%/*}")"
-
 testBinariesFromSameSource() {
   $COMMAND -s ${WORKDIR}/dd-list/sources vim-gtk vim-nox 2>&1 >/dev/null
   rc=$?
   assertEquals 'packages found' 0 $rc
 }
 
+testExtraSourceOnlyIgnored() {
+  $COMMAND -s ${WORKDIR}/dd-list/sources bzip2 >$SHUNIT_TMPDIR/extra-source.out
+
+  assertFalse 'Jorge listed as uploader' "grep -q Jorge $SHUNIT_TMPDIR/extra-source.out"
+}
+
+testUseOnlyLatestVersion() {
+  $COMMAND -s ${WORKDIR}/dd-list/sources subversion >$SHUNIT_TMPDIR/latest-version.out
+
+  assertFalse 'Troy Heber listed as uploader'  "grep -q Troy $SHUNIT_TMPDIR/latest-version.out"
+}
+
 . shunit2
diff --git a/test/test_debchange b/test/test_debchange
index 867a38c..30721e4 100755
--- a/test/test_debchange
+++ b/test/test_debchange
@@ -82,17 +82,17 @@ checkUbuntuVersion() {
 }
 
 testDebianDistributions() {
+    checkDebianDistribution "jessie-security"
+    checkDebianDistribution "wheezy-security"
+    checkDebianDistribution "stretch-security"
     checkDebianDistribution "experimental"
     checkDebianDistribution "oldstable"
     checkDebianDistribution "oldstable-proposed-updates"
-    checkDebianDistribution "oldstable-security"
     checkDebianDistribution "proposed-updates"
     checkDebianDistribution "stable"
     checkDebianDistribution "stable-proposed-updates"
-    checkDebianDistribution "stable-security"
     checkDebianDistribution "testing"
     checkDebianDistribution "testing-proposed-updates"
-    checkDebianDistribution "testing-security"
     checkDebianDistribution "UNRELEASED"
 }
 
diff --git a/test/test_licensecheck b/test/test_licensecheck
index 0b22d57..9c8fb33 100755
--- a/test/test_licensecheck
+++ b/test/test_licensecheck
@@ -64,6 +64,10 @@ testMultiLineDeclaration() {
     license2 "-m --copyright" "texinfo.tex" "GPL (v3 or later)	1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc."
 }
 
+testDuplicatedCopyright() {
+    license2 "-m --copyright" "duplicated-copyright.rb" "Apache (v2.0)	2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs"
+}
+
 testLGPL() {
     license "lgpl-2.1.c" "LGPL (v2.1)"
     license "lgpl-2.1.h" "LGPL (v2.1)"
diff --git a/test/test_uscan b/test/test_uscan
index 8637b6e..ea8e082 100755
--- a/test/test_uscan
+++ b/test/test_uscan
@@ -16,21 +16,37 @@
 # version 3 can be found in the /usr/share/common-licenses/GPL-3 file.
 
 test_dir=$(readlink -f "${0%/*}")
+
+SUFFIX="1"
+if which dpkg-vendor >/dev/null 2>&1; then
+    case "$(dpkg-vendor --query Vendor 2>/dev/null)" in
+	"Ubuntu")
+	    SUFFIX="0ubuntu1"
+	    ;;
+    esac
+fi
+
 if test "$1" = --installed; then
     COMMAND="uscan --no-conf --compression=xz"
     shift
 else
     top_srcdir=$(readlink -f "${0%/*}/..")
-    make -C "$top_srcdir/scripts" uscan mk-origtargz
+    make -C "$top_srcdir/scripts" uscan mk-origtargz uupdate
     PATH="$top_srcdir/scripts:$PATH"
     PERL5LIB="$top_srcdir/lib"
     export PERL5LIB
     COMMAND="uscan --no-conf --compression=xz"
 fi
 
+COMMANDDEHS="$COMMAND --dehs"
+
+# comment out for debug
+#COMMAND="$COMMAND --debug"
+
 cleanup(){
     kill -9 $(cat $TMPDIR/repo/pid)
     rm -rf $TMPDIR
+    echo ""
 }
 
 spawnHttpServer(){
@@ -93,7 +109,8 @@ END
     ( cd $TMPDIR/repo ;
       tar cfa $PKG-1.$from_ext * )
 
-    OUTPUT=$( (cd $TMPDIR/$PKG ; $COMMAND --dehs --repack --compression=$to_comp) 2>&1 )
+    OUTPUT=$( (cd $TMPDIR/$PKG ; $COMMANDDEHS --repack --compression=$to_comp) 2>&1 )
+    assertEquals "uscan: exit_code!=0 but exit_code=0" "$?" "0"
 
     TARBALL=${PKG}_1.orig.tar.$to_comp
     if [ "$from_ext" != "tar.$to_comp" ]
@@ -151,7 +168,8 @@ END
     ( cd $TMPDIR/repo ;
       zip -q -r $PKG-1.zip * )
 
-    OUTPUT=$( (cd $TMPDIR/$PKG ; $COMMAND --dehs --repack --compression=$to_comp) )
+    OUTPUT=$( (cd $TMPDIR/$PKG ; $COMMANDDEHS --repack --compression=$to_comp) )
+    assertEquals "uscan: exit_code!=0 but exit_code=0" "$?" "0"
 
     TARBALL=${PKG}_1.orig.tar.$to_comp
     assertTrue 'unrepacked zipfile present' "[ -f $TMPDIR/${PKG}-1.zip ]"
@@ -179,11 +197,11 @@ helperCreateRepo () {
 
     cat <<END > $PKG/debian/watch
 version=3
-${OPTS}http://localhost:$PORT/$PKG-(\d).tar.gz
+${OPTS}http://localhost:$PORT/$PKG-(\d).tar.gz debian $SCRIPT
 END
 
     cat <<END > $PKG/debian/changelog
-$PKG (0-1) unstable; urgency=low
+$PKG (0+dfsg1-$SUFFIX) unstable; urgency=low
 
   * Initial release
 
@@ -198,6 +216,10 @@ Files-Excluded: exclude-this
  */js/jquery.js
  ;?echo?baz;?#
 END
+    if [ -n "$SRCFORMAT" ]; then
+	mkdir -p $PKG/debian/source
+	echo "$SRCFORMAT" > $PKG/debian/source/format
+    fi
 
     mkdir -p repo
     touch repo/include-this
@@ -239,15 +261,18 @@ testFileExclusion() {
 
     (
       cd $TMPDIR
-      OPTS="opts=repacksuffix=+dfsg1 "
+      OPTS="opts=repacksuffix=+dfsg1,dversionmangle=s/\+dfsg\d*$// "
+      SCRIPT="uupdate"
+      SRCFORMAT="3.0 (quilt)"
       helperCreateRepo
       cd repo
       tar cfz $PKG-1.tar.gz * .hidden )
 
     (cd $TMPDIR/$PKG ; $COMMAND)
+    assertEquals "uscan: exit_code!=0 but exit_code=0" "$?" "0"
 
     TARBALL=${PKG}_1+dfsg1.orig.tar.gz
-    assertTrue 'downloaded tarfile not present' "[ -f $TMPDIR/${PKG}-1.tar.gz ]"
+    assertTrue 'downloaded tarfile not present' "[ -f $TMPDIR/${PKG}-$SUFFIX.tar.gz ]"
     assertTrue 'pristine tarball is not created' "[ -f $TMPDIR/$TARBALL ]"
     assertFalse 'pristine tarball is a symlink (nothing repacked?)' "[ -L $TMPDIR/$TARBALL ]"
     assertNotNull 'pristine tarball is not gzip-compressed' \
@@ -256,11 +281,16 @@ testFileExclusion() {
 
     helperTestContent
 
+    # check uupdate
+    assertTrue 'pristine tarball is not extracted' "[ -f $TMPDIR/${PKG}-1+dfsg1/debian/changelog ]"
+    DVERSION=`dpkg-parsechangelog -l$TMPDIR/${PKG}-1+dfsg1/debian/changelog -SVersion`
+    assertEquals "uscan: Version should be 1+dfsg1-$SUFFIX but $DVERSION" "$DVERSION" "1+dfsg1-$SUFFIX"
+
     cleanup
 
 }
 
-# the same, but run from a separate directory
+# the same, but run from a separate directory (no way for uupdate, just download)
 testFileExclusionSeparateDir() {
 
     PKG=foo
@@ -270,15 +300,19 @@ testFileExclusionSeparateDir() {
 
     (
       cd $TMPDIR
-      OPTS="opts=repacksuffix=+dfsg1 "
+      SCRIPT=""
+      OPTS="opts=repacksuffix=+dfsg1,dversionmangle=s/\+dfsg\d*$// "
       helperCreateRepo
       cd repo
       tar cfz $PKG-1.tar.gz * .hidden )
 
     mkdir $TMPDIR/otherdir
     (
-    	cd $TMPDIR/otherdir; $COMMAND --package $PKG --force-download --upstream-version 1 --watchfile ../$PKG/debian/watch --copyright-file ../$PKG/debian/copyright
-   )
+	cd $TMPDIR/otherdir; 
+	$COMMAND --package $PKG --force-download --upstream-version 1 \
+		--watchfile ../$PKG/debian/watch --copyright-file ../$PKG/debian/copyright
+    )
+    assertEquals "uscan: exit_code!=0 but exit_code=0" "$?" "0"
 
     TARBALL=${PKG}_1+dfsg1.orig.tar.gz
     assertTrue 'downloaded tarfile not present' "[ -f $TMPDIR/${PKG}-1.tar.gz ]"
@@ -305,16 +339,18 @@ testFileExclusionZipToTar() {
 
     (
       cd $TMPDIR
+      SRCFORMAT="3.0 (quilt)"
       helperCreateRepo
       cat <<END > $PKG/debian/watch
 version=3
-opts=repacksuffix=+dfsg1 http://localhost:$PORT/$PKG-(\d).zip
+opts=repacksuffix=+dfsg1,dversionmangle=s/\+dfsg\d*$// http://localhost:$PORT/$PKG-(\d).zip debian uupdate
 END
 
       cd repo
       zip -q -r $PKG-1.zip * .hidden )
 
     (cd $TMPDIR/$PKG ; $COMMAND --repack)
+    assertEquals "uscan: exit_code!=0 but exit_code=0" "$?" "0"
 
     TARBALL=${PKG}_1+dfsg1.orig.tar.xz
     assertTrue 'unrepacked zipfile not present' "[ -f $TMPDIR/${PKG}-1.zip ]"
@@ -324,6 +360,11 @@ END
     CONTENTS="$(tar atf $TMPDIR/$TARBALL)"
     helperTestContent
 
+    # check uupdate
+    assertTrue 'pristine tarball is not extracted' "[ -f $TMPDIR/${PKG}-1+dfsg1/debian/changelog ]"
+    DVERSION=`dpkg-parsechangelog -l$TMPDIR/${PKG}-1+dfsg1/debian/changelog -SVersion`
+    assertEquals "uscan: Version should be 1+dfsg1-$SUFFIX but $DVERSION" "$DVERSION" "1+dfsg1-$SUFFIX"
+
     cleanup
 
 }
diff --git a/test/test_uscan_mangle b/test/test_uscan_mangle
new file mode 100755
index 0000000..4e2cc11
--- /dev/null
+++ b/test/test_uscan_mangle
@@ -0,0 +1,432 @@
+#!/bin/sh
+
+# Copyright (C) 2013, Rafael Laboissiere <rafael at laboissiere.net>
+#
+# 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.
+#
+# On Debian systems, the complete text of the GNU General Public License
+# version 3 can be found in the /usr/share/common-licenses/GPL-3 file.
+
+test_dir=$(readlink -f "${0%/*}")
+
+# Operation mode
+if test "$1" = --installed; then
+    COMMAND="uscan --no-conf --compression=xz"
+    shift
+else
+    top_srcdir=$(readlink -f "${0%/*}/..")
+    make -C "$top_srcdir/scripts" uscan mk-origtargz uupdate
+    PATH="$top_srcdir/scripts:$PATH"
+    PERL5LIB="$top_srcdir/lib"
+    export PERL5LIB
+    COMMAND="uscan --no-conf --compression=xz"
+fi
+
+REPOPATH=repo
+POOLPATH=pool
+
+# Initial Debian revision value is distribution dependent
+SUFFIX="1"
+if which dpkg-vendor >/dev/null 2>&1; then
+    case "$(dpkg-vendor --query Vendor 2>/dev/null)" in
+	"Ubuntu")
+	    SUFFIX="0ubuntu1"
+	    ;;
+    esac
+fi
+
+# set safe defaults
+WEBSCRIPT=":"
+DEBUGECHO=":"
+DEBUGLSLR=":"
+# comment out for debug
+#COMMAND="$COMMAND --debug"
+#DEBUGECHO=echo
+#DEBUGLSLR="ls -laR"
+
+cleanup(){
+    kill -9 $(cat $TMPDIR/$REPOPATH/pid)
+    rm -rf $TMPDIR
+    echo ""
+}
+
+spawnHttpServer(){
+    (
+	mkdir -p $TMPDIR/$REPOPATH
+	cd $TMPDIR/$REPOPATH
+	python "$test_dir/uscan/server.py" &
+	echo $! > pid
+	while ! [ -s port ]; do
+	    :
+	done
+    )
+}
+
+trap cleanup 1 2 3 13 15
+
+containsName(){
+  echo "$1" | fgrep -q "$2"
+  echo $?
+}
+
+. "${0%/*}/shunit2-helper-functions.sh"
+
+# The following tests do the following: (1) create a minimal Debian package
+# directory, containing minimal files debian/{changelog,watch,copyright},
+# (2) create a minimal repository, containing a tarball (built on the fly),
+# (3) start an HTTP server that works offline, using the SimpleHTTPServer
+# module of Python, and (4) run uscan inside that minimal universe.
+
+# make debian/ in `pwd`
+# debian/watch contains $WATCHVER and $WATCHLINE with template URL updated
+makeDebianDir() {
+    DEBNAME=$1 # Debian source package name
+    DEBVER=$2  # DEbian source package version
+    mkdir -p debian/source
+
+    cat <<END > debian/rules
+%:
+	dh $@
+END
+chmod 755 debian/rules
+
+    cat <<END > debian/changelog
+$DEBNAME ($DEBVER) unstable; urgency=low
+
+  * Release of the $DEBNAME package $DEBVER.
+
+ -- Joe Developer <jd at debian.org>  Mon, 02 Nov 2013 22:21:31 -0100
+END
+    # debian/source/format
+    case $DEBVER in
+	*-*) # non-native package
+	    echo "3.0 (quilt)" > debian/source/format
+	     ;;
+	*) # native package
+	    echo "3.0 (native)" > debian/source/format
+	     ;;
+    esac
+    # debian/copyright
+    echo "Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/" \
+	> debian/copyright
+    # debian/watch
+    echo "version=$WATCHVER" > debian/watch
+    echo "$WATCHLINE" | sed -e "s,@@@url@@@,http://localhost:${PORT}/,g" - \
+	>> debian/watch
+}
+
+# make tarball in $REPOPATH/$POOLPATH
+makeUpstreamTar() {
+    UPNAME=$1 # Upstream package name
+    UPVER=$2  # upstream package version
+    COMPRESSION=${3:-gz} # archve compression type
+    TYPE=${4:-non-native} # set this if native-type upstream
+    OLDDIR=`pwd`
+    mkdir -p $TMPDIR/$REPOPATH/$POOLPATH/$UPNAME-$UPVER
+    cd $TMPDIR/$REPOPATH/$POOLPATH
+    touch $UPNAME-$UPVER/$UPNAME-$UPVER
+    if [ "$TYPE" = "native" ]; then
+	cd $TMPDIR/$REPOPATH/$POOLPATH/$UPNAME-$UPVER
+	makeDebianDir $UPNAME $UPVER
+	cd $TMPDIR/$REPOPATH/$POOLPATH
+    fi
+    case $COMPRESSION in
+	gz|gzip) tar -czf $UPNAME-$UPVER.tar.gz $UPNAME-$UPVER
+	    ;;
+	bz2|bzip2) tar --bzip2 -cf $UPNAME-$UPVER.tar.bz2 $UPNAME-$UPVER
+	    ;;
+	xz) tar --xz -cf $UPNAME-$UPVER.tar.xz $UPNAME-$UPVER
+	    ;;
+	zip)zip -r $UPNAME-$UPVER.zip $UPNAME-$UPVER
+	    ;;
+	*)  echo "Wrong compression mode: $COMPRESSION"
+	    exit 1
+	    ;;
+	esac
+    cd $OLDDIR
+}
+
+# setup a common watch file test environment
+helperWatch() {
+    SITESCRIPT=$1
+    VEROLD=$2
+    VERNEW=$3
+    PREFIX=$4
+    TMPDIR=$(mktemp -d)
+    ORIGDIR=`pwd`
+    cd $TMPDIR
+    # start HTTP server with its root at $TMPDIR/$REPOPATH
+    spawnHttpServer
+    PORT=$(cat $TMPDIR/$REPOPATH/port)
+    $DEBUGECHO " ***** http://localhost:$PORT started showing $TMPDIR/$REPOPATH *****"
+    # make web site
+    $SITESCRIPT
+    # make local $VEROLD source tree
+    tar -xzf $TMPDIR/$REPOPATH/$POOLPATH/${PKG}-${VEROLD}.tar.gz
+    if [ -n "$PREFIX" ]; then
+	mv $TMPDIR/${PKG}-${VEROLD} $TMPDIR/${PKG}-${PREFIX}${VEROLD}
+    fi
+    mv $TMPDIR/${PKG}-${PREFIX}${VEROLD} $TMPDIR/${PKG}
+    cd $TMPDIR/${PKG}
+    if [ ! -d debian ]; then
+	makeDebianDir $PKG ${PREFIX}${VEROLD}-$SUFFIX
+    fi
+    $COMMAND
+    assertEquals "uscan: exit_code!=0 but exit_code=0" "$?" "0"
+    cd $TMPDIR
+    UTARBALL=${PKG}-${VERNEW}.tar.gz
+    STARBALL=${PKG}_${PREFIX}${VERNEW}.orig.tar.gz
+    assertTrue "$UTARBALL missing: $WATCHLINE" "[ -f $UTARBALL ]"
+    assertTrue "$STARBALL missing: $WATCHLINE" "[ -f $STARBALL ]"
+    # check uupdate
+    if [ "$UUPDATE" = "uupdate" ]; then
+	assertTrue 'pristine tarball is not extracted' "[ -f $TMPDIR/${PKG}-${PREFIX}${VERNEW}/debian/changelog ]"
+	DVERSION=`dpkg-parsechangelog -l$TMPDIR/${PKG}-${PREFIX}${VERNEW}/debian/changelog -SVersion`
+	assertEquals "uscan: Version should be ${PREFIX}${VERNEW}-$SUFFIX but $DVERSION" "$DVERSION" "${PREFIX}${VERNEW}-$SUFFIX"
+    fi
+    $DEBUGLSLR
+    cd $ORIGDIR
+    cleanup
+}
+
+# populate pool directory
+sitePoolNative() {
+    makeUpstreamTar $PKG 0.0 gz native
+    makeUpstreamTar $PKG 1.0 gz native
+    makeUpstreamTar $PKG 2.0 gz native
+    mkdir -p $TMPDIR/$REPOPATH/123/foo/ooo/
+    mkdir -p $TMPDIR/$REPOPATH/124/foo/ooo/
+    mkdir -p $TMPDIR/$REPOPATH/125/foo/ooo/
+    ln -sf ../../../$POOLPATH/${PKG}-0.0.tar.gz $TMPDIR/$REPOPATH/123/foo/ooo/${PKG}-0.0.tar.gz
+    ln -sf ../../../$POOLPATH/${PKG}-1.0.tar.gz $TMPDIR/$REPOPATH/124/foo/ooo/${PKG}-1.0.tar.gz
+    ln -sf ../../../$POOLPATH/${PKG}-2.0.tar.gz $TMPDIR/$REPOPATH/125/foo/ooo/${PKG}-2.0.tar.gz
+}
+
+sitePoolNonNative() {
+    makeUpstreamTar $PKG 0.0 gz non-native
+    makeUpstreamTar $PKG 1.0 gz non-native
+    makeUpstreamTar $PKG 2.0 gz non-native
+    mkdir -p $TMPDIR/$REPOPATH/123/foo/ooo/
+    mkdir -p $TMPDIR/$REPOPATH/124/foo/ooo/
+    mkdir -p $TMPDIR/$REPOPATH/125/foo/ooo/
+    ln -sf ../../../$POOLPATH/${PKG}-0.0.tar.gz $TMPDIR/$REPOPATH/123/foo/ooo/${PKG}-0.0.tar.gz
+    ln -sf ../../../$POOLPATH/${PKG}-1.0.tar.gz $TMPDIR/$REPOPATH/124/foo/ooo/${PKG}-1.0.tar.gz
+    ln -sf ../../../$POOLPATH/${PKG}-2.0.tar.gz $TMPDIR/$REPOPATH/125/foo/ooo/${PKG}-2.0.tar.gz
+}
+
+# hide siteNative behind a web page
+siteWebNative() {
+    sitePoolNative
+    cat <<END > $TMPDIR/$REPOPATH/index.html
+<html>
+<head>
+  <meta charset="utf-8">
+</head>
+<body>
+<a href="/123/foo/ooo/$PKG-0.0.tar.gz">Very old</a> <br/ >
+<a href="/124/foo/ooo/$PKG-1.0.tar.gz">A bit OLD</a> <br />
+<a href="/125/foo/ooo/$PKG-2.0.tar.gz">Latest</a> <br />
+</body>
+<html>
+END
+}
+
+siteWebNonNative() {
+    sitePoolNonNative
+    cat <<END > $TMPDIR/$REPOPATH/index.html
+<html>
+<head>
+  <meta charset="utf-8">
+</head>
+<body>
+<a href="/123/foo/ooo/$PKG-0.0.tar.gz">Very old</a> <br/ >
+<a href="/124/foo/ooo/$PKG-1.0.tar.gz">A bit OLD</a> <br />
+<a href="/125/foo/ooo/$PKG-2.0.tar.gz">Latest</a> <br />
+</body>
+<html>
+END
+}
+
+siteWebNonNativeR() {
+    makeUpstreamTar $PKG 0.0 gz non-native
+    makeUpstreamTar $PKG 1.0 gz non-native
+    makeUpstreamTar $PKG 2.0 gz non-native
+    mkdir -p $TMPDIR/$REPOPATH/123/foo/ooo/
+    mkdir -p $TMPDIR/$REPOPATH/124/foo/ooo/
+    mkdir -p $TMPDIR/$REPOPATH/125/foo/ooo/
+    ln -sf ../../../$POOLPATH/${PKG}-0.0.tar.gz $TMPDIR/$REPOPATH/125/foo/ooo/${PKG}-0.0.tar.gz
+    ln -sf ../../../$POOLPATH/${PKG}-1.0.tar.gz $TMPDIR/$REPOPATH/124/foo/ooo/${PKG}-1.0.tar.gz
+    ln -sf ../../../$POOLPATH/${PKG}-2.0.tar.gz $TMPDIR/$REPOPATH/123/foo/ooo/${PKG}-2.0.tar.gz
+    cat <<END > $TMPDIR/$REPOPATH/index.html
+<html>
+<head>
+  <meta charset="utf-8">
+</head>
+<body>
+<a href="/125/foo/ooo/$PKG-0.0.tar.gz">Very old</a> <br/ >
+<a href="/124/foo/ooo/$PKG-1.0.tar.gz">A bit OLD</a> <br />
+<a href="/123/foo/ooo/$PKG-2.0.tar.gz">Latest</a> <br />
+</body>
+<html>
+END
+}
+
+sitePrWebNonNative() {
+    sitePoolNonNative
+    cat <<END > $TMPDIR/$REPOPATH/index.html
+<html>
+<head>
+  <meta charset="utf-8">
+</head>
+<body>
+<a href="/123/boo/xxx/boo-0.0.tar.gz">Very old</a> <br/ >
+<a href="/124/boo/xxx/boo-1.0.tar.gz">A bit OLD</a> <br />
+<a href="/125/boo/xxx/boo-2.0.tar.gz">Latest</a> <br />
+</body>
+<html>
+END
+}
+
+siteWebNonNativeLarge() {
+    makeUpstreamTar $PKG 19990101 gz non-native
+    makeUpstreamTar $PKG 20000101 gz non-native
+    makeUpstreamTar $PKG 20010101 gz non-native
+    mkdir -p $REPOPATH/123/foo/ooo/
+    mkdir -p $REPOPATH/124/foo/ooo/
+    mkdir -p $REPOPATH/125/foo/ooo/
+    ln -sf ../../../$POOLPATH/${PKG}-19990101.tar.gz $TMPDIR/$REPOPATH/123/foo/ooo/${PKG}-19990101.tar.gz
+    ln -sf ../../../$POOLPATH/${PKG}-20000101.tar.gz $TMPDIR/$REPOPATH/124/foo/ooo/${PKG}-20000101.tar.gz
+    ln -sf ../../../$POOLPATH/${PKG}-20010101.tar.gz $TMPDIR/$REPOPATH/125/foo/ooo/${PKG}-20010101.tar.gz
+    cat <<END > $TMPDIR/$REPOPATH/index.html
+<html>
+<head>
+  <meta charset="utf-8">
+</head>
+<body>
+<a href="/123/foo/ooo/$PKG-19990101.tar.gz">Very old</a> <br/ >
+<a href="/124/foo/ooo/$PKG-20000101.tar.gz">A bit OLD</a> <br />
+<a href="/125/foo/ooo/$PKG-20010101.tar.gz">Latest</a> <br />
+</body>
+<html>
+END
+}
+
+siteXmlNonNative() {
+    sitePoolNonNative
+    cat <<END > $TMPDIR/$REPOPATH/index.html
+<html>
+<head>
+  <meta charset="utf-8">
+</head>
+<body>
+<Key>/123/foo/ooo/$PKG-0.0.tar.gz</Key> <br/ >
+<Key>/124/foo/ooo/$PKG-1.0.tar.gz</Key> <br />
+<Key>/125/foo/ooo/$PKG-2.0.tar.gz</Key> <br />
+</body>
+<html>
+END
+}
+
+# test a watch files
+
+testWatch3Native() {
+    PKG=foo
+    WATCHVER="3"
+    WATCHLINE='@@@url@@@/(\d+)/(.+)/(.+)/'$PKG'-([\.\d]+).tar.gz debian'
+    helperWatch sitePoolNative 1.0 2.0
+}
+
+testWatch3NonNative() {
+    PKG=foo
+    WATCHVER="3"
+    WATCHLINE='@@@url@@@(\d+)/(.+)/(.+)/ '$PKG'-([\.\d]+).tar.gz debian uupdate'
+    helperWatch sitePoolNonNative 1.0 2.0
+}
+
+testWatch3WebNative() {
+    PKG=foo
+    WATCHVER="3"
+    WATCHLINE='@@@url@@@ (?:.*)/'$PKG'-([\d\.]+).tar.gz debian'
+    helperWatch siteWebNative 1.0 2.0
+}
+
+testWatch3WebNonNative() {
+    PKG=foo
+    WATCHVER="3"
+    WATCHLINE='@@@url@@@/ (?:.*)/'$PKG'-([\.\d]+).tar.gz debian uupdate'
+    helperWatch siteWebNonNative 1.0 2.0
+}
+
+testWatch3WebNonNativeR() {
+    PKG=foo
+    WATCHVER="3"
+    WATCHLINE='@@@url@@@/ (?:.*)/'$PKG'-([\.\d]+).tar.gz debian uupdate'
+    helperWatch siteWebNonNativeR 1.0 2.0
+}
+
+testWatch3PrWebNonNative() {
+    PKG=foo
+    WATCHVER="3"
+    WATCHLINE='opts="downloadurlmangle = s%boo/xxx%foo/ooo% ; s%boo-%foo-%, \
+                     filenamemangle    = s%.*boo-(.*)%foo-$1% " \
+    @@@url@@@/ (?:.*)/boo-([\d\.]+).tar.gz \
+    debian uupdate'
+    helperWatch sitePrWebNonNative 1.0 2.0
+}
+
+testWatch3WebNonNativeDlCurrent() {
+    PKG=foo
+    COMMANDOLD="$COMMAND"
+    COMMAND="$COMMAND --download-current-version"
+    WATCHVER="3"
+    WATCHLINE='@@@url@@@/ (?:.*)/'$PKG'-([\.\d]+).tar.gz debian uupdate'
+    helperWatch siteWebNonNative 1.0 1.0
+    COMMAND="$COMMANDOLD"
+}
+testWatch3WebNonNativeDlUversion() {
+    PKG=foo
+    COMMANDOLD="$COMMAND"
+    COMMAND="$COMMAND --download-version 0.0"
+    WATCHVER="3"
+    WATCHLINE='@@@url@@@/ (?:.*)/'$PKG'-([\.\d]+).tar.gz debian uupdate'
+    helperWatch siteWebNonNative 1.0 0.0
+    COMMAND="$COMMANDOLD"
+}
+testWatch3WebNonNativeDlDversion() {
+    PKG=foo
+    COMMANDOLD="$COMMAND"
+    COMMAND="$COMMAND --download-debversion 0.0-1"
+    WATCHVER="3"
+    WATCHLINE='@@@url@@@/ (?:.*)/'$PKG'-([\.\d]+).tar.gz debian uupdate'
+    helperWatch siteWebNonNative 1.0 0.0
+    COMMAND="$COMMANDOLD"
+}
+## Debian version is 0.19990101 for future proof while upstream is 19990101
+#testWatch3WebNonNativeLarge() {
+#    PKG=foo
+#    WATCHVER="3"
+#    WATCHLINE='opts=" dversionmangle = s/0\.(.*)/$1/ , \
+#	oversionmangle = s/(.*)/0.$1/" \
+#	@@@url@@@  (?:.*)/'$PKG'-([\.\d]+).tar.gz debian uupdate'
+#    helperWatch siteWebNonNativeLarge 20000101 20010101 0.
+#}
+#
+## test for pagemangle
+#testWatch3XmlNonNative() {
+#    PKG=foo
+#    WATCHVER="3"
+#    WATCHLINE='opts="pagemangle = \
+#	s%<Key>([^<]*)</Key>%<Key><a href=\"$1\">$1</a></Key>%g" \
+#	@@@url@@@/ (?:.*)/'$PKG'-([\d\.]+).tar.gz debian uupdate'
+#    helperWatch siteXmlNonNative 1.0 2.0
+#}
+
+. shunit2

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/collab-maint/devscripts.git



More information about the devscripts-devel mailing list