The following commit has been merged in the master branch:
commit 7602026aff2452f6d723a87146340f4ed3e3d863
Author: Guillem Jover <[email protected]>
Date: Wed Jul 1 09:17:47 2009 +0200
dpkg-scansources: Switch to use Dpkg::Cdata
Use our modules instead of duplicating the .dsc parsing code. As a
side effect it now handles properly bogus files.
diff --git a/debian/changelog b/debian/changelog
index b8a07d9..905344d 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -6,6 +6,8 @@ dpkg (1.15.4) UNRELEASED; urgency=low
when the package didn't have such field.
* Do not take into account Revision and Package_Revision fields in dpkg-name
as they have been handled already by “dpkg-deb -I”.
+ * Switch dpkg-scansources to use Dpkg::Cdata instead of duplicating the
+ .dsc parsing code. As a side effect it now handles properly bogus files.
[ Updated dpkg translations ]
* French (Christian Perrier).
diff --git a/scripts/dpkg-scansources.pl b/scripts/dpkg-scansources.pl
index 51ef9ec..6d60fc3 100755
--- a/scripts/dpkg-scansources.pl
+++ b/scripts/dpkg-scansources.pl
@@ -2,6 +2,7 @@
#
# Copyright © 1999 Roderick Schertler
# Copyright © 2002 Wichert Akkerman <[email protected]>
+# Copyright © 2006-2009 Guillem Jover <[email protected]>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -30,6 +31,7 @@ use warnings;
use Dpkg;
use Dpkg::Gettext;
use Dpkg::ErrorHandling;
+use Dpkg::Cdata;
use Dpkg::Checksums;
textdomain("dpkg-dev");
@@ -219,135 +221,34 @@ sub load_src_override {
close SRC_OVERRIDE or syserr(_g("error closing source override file"));
}
-# Given FILENAME (for error reporting) and STRING, drop the PGP info
-# from the string and undo the encoding (if present) and return it.
-
-sub de_pgp {
- my ($file, $s) = @_;
- if ($s =~ s/^-----BEGIN PGP SIGNED MESSAGE-----.*?\n\n//s) {
- unless ($s =~ s/\n
- -----BEGIN\040PGP\040SIGNATURE-----\n
- .*?\n
- -----END\040PGP\040SIGNATURE-----\n
- //xs) {
- warning(_g("%s has PGP start token but not end token"), $file);
- return;
- }
- $s =~ s/^- //mg;
- }
- return $s;
-}
-
-# Load DSC-FILE and return its size, MD5 and translated (de-PGPed)
-# contents.
+# Given PREFIX and DSC-FILE, process the file and returns the fields.
-sub read_dsc {
- my $file = shift;
- my ($size, $nread, $contents);
-
- unless (open FILE, $file) {
- warning(_g("can't read %s: %s"), $file, $!);
- return;
- }
+sub process_dsc {
+ my ($prefix, $file) = @_;
+ my ($source, @binary, $priority, $section, $maintainer_override,
+ $dir);
- $contents = '';
- do {
- $nread = read FILE, $contents, 16*1024, length $contents;
- unless (defined $nread) {
- warning(_g("error reading from %s: %s"), $file, $!);
- return;
- }
- } while $nread > 0;
+ # Parse ‘.dsc’ file.
+ open(CDATA, '<', $file) || syserr(_g("cannot open %s"), $file);
+ my $fields = parsecdata(\*CDATA,
+ sprintf(_g("source control file %s"), $file),
+ allow_pgp => 1);
+ error(_g("parsing an empty file %s"), $file) unless (defined $fields);
+ close(CDATA) || syserr(_g("cannot close %s"), $file);
# Get checksums
+ my $size;
my $sums = {};
getchecksums($file, $sums, \$size);
- unless (close FILE) {
- warning(_g("error closing %s: %s"), $file, $!);
- return;
- }
-
- $contents = de_pgp $file, $contents;
- return unless defined $contents;
+ $source = $fields->{Source};
+ @binary = split /\s*,\s*/, $fields->{Binary};
- return $size, $sums, $contents;
-}
-
-# Given PREFIX and DSC-FILE, process the file and returning the source
-# package name and index record.
-
-sub process_dsc {
- my ($prefix, $file) = @_;
- my ($source, @binary, $priority, $section, $maintainer_override,
- $dir, $dir_field, $dsc_field_start);
+ error(_g("no binary packages specified in %s"), $file) unless (@binary);
- my ($size, $sums, $contents) = read_dsc $file or return;
-
- # Allow blank lines at the end of a file, because the other programs
- # do.
- $contents =~ s/\n\n+\Z/\n/;
-
- if ($contents =~ /^\n/ || $contents =~ /\n\n/) {
- warning(_g("%s invalid (contains blank line)"), $file);
- return;
- }
-
- # Take the $contents and create a list of (possibly multi-line)
- # fields. Fields can be continued by starting the next line with
- # white space. The tricky part is I don't want to modify the data
- # at all, so I can't just collapse continued fields.
- #
- # Implementation is to start from the last line and work backwards
- # to the second. If this line starts with space, append it to the
- # previous line and undef it. When done drop the undef entries.
- my @line = split /\n/, $contents;
- for (my $i = $#line; $i > 0; $i--) {
- if ($line[$i] =~ /^\s/) {
- $line[$i-1] .= "\n$line[$i]";
- $line[$i] = undef;
- }
- }
- my @field = map { "$_\n" } grep { defined } @line;
-
- # Extract information from the record.
- for my $orig_field (@field) {
- my $s = $orig_field;
- $s =~ s/\s+$//;
- $s =~ s/\n\s+/ /g;
- unless ($s =~ s/^([^:\s]+):\s*//) {
- warning(_g("invalid field in %s: %s"), $file, $orig_field);
- return;
- }
- my ($key, $val) = (lc $1, $s);
-
- # $source
- if ($key eq 'source') {
- if (defined $source) {
- warning(_g("duplicate source field in %s"), $file);
- return;
- }
- if ($val =~ /\s/) {
- warning(_g("invalid source field in %s"), $file);
- return;
- }
- $source = $val;
- next;
- }
-
- # @binary
- if ($key eq 'binary') {
- if (@binary) {
- warning(_g("duplicate binary field in %s"), $file);
- return;
- }
- @binary = split /\s*,\s*/, $val;
- unless (@binary) {
- warning(_g("no binary packages specified in %s"), $file);
- return;
- }
- }
- }
+ # Rename the source field to package.
+ $fields->{Package} = $fields->{Source};
+ delete $fields->{Source};
# The priority for the source package is the highest priority of the
# binary packages it produces.
@@ -360,6 +261,7 @@ sub process_dsc {
$priority = $priority_override
? $priority_override->[O_PRIORITY]
: undef;
+ $fields->{Priority} = $priority if defined $priority;
# For the section override, first check for a record from the source
# override file, else use the regular override file.
@@ -367,106 +269,49 @@ sub process_dsc {
$section = $section_override
? $section_override->[O_SECTION]
: undef;
+ $fields->{Section} = $section if defined $section;
# For the maintainer override, use the override record for the first
- # binary.
+ # binary. Modify the maintainer if necessary.
$maintainer_override = $Override{$binary[0]};
+ if ($maintainer_override && defined $maintainer_override->[O_MAINT_TO]) {
+ if (!defined $maintainer_override->[O_MAINT_FROM] ||
+ grep { $fields->{Maintainer} eq $_ }
+ @{ $maintainer_override->[O_MAINT_FROM] }) {
+ $fields->{Maintainer} = $maintainer_override->[O_MAINT_TO];
+ }
+ }
# A directory field will be inserted just before the files field.
$dir = ($file =~ s-(.*)/--) ? $1 : '';
$dir = "$prefix$dir";
$dir =~ s-/+$--;
$dir = '.' if $dir eq '';
- $dir_field .= "Directory: $dir\n";
+ $fields->{Directory} = $dir;
# The files field will get an entry for the .dsc file itself.
- my %listing;
foreach my $alg (@check_supported) {
if ($alg eq "md5") {
- $listing{$alg} = "Files:\n $sums->{$alg} $size $file\n";
+ $fields->{Files} =~ s/^\n/\n $sums->{$alg} $size $file\n/;
} else {
- $listing{$alg} = "Checksum-" . ucfirst($alg) .
- ":\n $sums->{$alg} $size $file\n";
+ my $name = "Checksums-" . ucfirst($alg);
+ $fields->{$name} =~ s/^\n/\n $sums->{$alg} $size $file\n/
+ if defined $fields->{$name};
}
}
- # Loop through @field, doing nececessary processing and building up
- # @new_field.
- my @new_field;
- for (@field) {
- # Rename the source field to package.
- s/^Source:/Package:/i;
-
- # Override the user's priority field.
- if (/^Priority:/i && defined $priority) {
- $_ = "Priority: $priority\n";
- undef $priority;
- }
-
- # Override the user's section field.
- if (/^Section:/i && defined $section) {
- $_ = "Section: $section\n";
- undef $section;
- }
-
- # Insert the directory line just before the files entry, and add
- # the dsc file to the files list.
- if (defined $dir_field && s/^Files:\s*//i) {
- push @new_field, $dir_field;
- $dir_field = undef;
- $_ = " $_" if length;
- $_ = "$listing{md5}$_";
- }
-
- if (/Checksums-(.*):/i) {
- my $alg = lc($1);
- s/Checksums-([^:]*):\s*//i;
- $_ = " $_" if length;
- $_ = "$listing{$alg}$_";
- }
-
- # Modify the maintainer if necessary.
- if ($maintainer_override
- && defined $maintainer_override->[O_MAINT_TO]
- && /^Maintainer:\s*(.*)\n/is) {
- my $maintainer = $1;
- $maintainer =~ s/\n\s+/ /g;
- if (!defined $maintainer_override->[O_MAINT_FROM]
- || grep { $maintainer eq $_ }
- @{ $maintainer_override->[O_MAINT_FROM] }){
- $_ = "Maintainer: $maintainer_override->[O_MAINT_TO]\n";
- }
- }
- }
- continue {
- push @new_field, $_ if defined $_;
- }
-
- # If there was no files entry, add one.
- if (defined $dir_field) {
- push @new_field, $dir_field;
- push @new_field, $dsc_field_start;
- }
-
- # Add the section field if it didn't override one the user supplied.
- if (defined $section) {
- # If the record starts with a package field put it after that,
- # otherwise put it first.
- my $pos = $new_field[0] =~ /^Package:/i ? 1 : 0;
- splice @new_field, $pos, 0, "Section: $section\n";
- }
-
- # Add the priority field if it didn't override one the user supplied.
- if (defined $priority) {
- # If the record starts with a package field put it after that,
- # otherwise put it first.
- my $pos = $new_field[0] =~ /^Package:/i ? 1 : 0;
- splice @new_field, $pos, 0, "Priority: $priority\n";
- }
-
- return $source, join '', @new_field, "\n";
+ return $fields;
}
+# FIXME: Try to reuse from Dpkg::Source::Package
+use Dpkg::Deps qw(@src_dep_fields);
+my @src_fields = (qw(Format Package Binary Architecture Version Origin
+ Maintainer Uploaders Dm-Upload-Allowed Homepage
+ Standards-Version Vcs-Browser Vcs-Arch Vcs-Bzr
+ Vcs-Cvs Vcs-Darcs Vcs-Git Vcs-Hg Vcs-Mtn Vcs-Svn),
+ @src_dep_fields,
+ qw(Directory Files Checksums-Md5 Checksums-Sha1
Checksums-Sha256));
+
sub main {
my (@out);
@@ -485,18 +330,36 @@ sub main {
while (<FIND>) {
chomp;
s-^\./+--;
- my ($source, $out) = process_dsc $prefix, $_ or next;
+
+ my $fields;
+
+ # FIXME: Fix it instead to not die on syntax and general errors?
+ eval {
+ $fields = process_dsc($prefix, $_);
+ };
+ if ($@) {
+ warn $@;
+ next;
+ }
+
+ tied(%{$fields})->set_field_importance(@src_fields);
if ($No_sort) {
- print $out;
+ tied(%{$fields})->output(\*STDOUT);
+ print "\n";
}
else {
- push @out, [$source, $out];
+ push @out, $fields;
}
}
close FIND or error(close_msg, 'find');
if (@out) {
- print map { $_->[1] } sort { $a->[0] cmp $b->[0] } @out;
+ map {
+ tied(%{$_})->output(\*STDOUT);
+ print "\n";
+ } sort {
+ $a->{Package} cmp $b->{Package}
+ } @out;
}
return 0;
--
dpkg's main repository
--
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]