Adding side stream changes to Maemian. Working to integrate full upstream libraries...
[maemian] / nokia-lintian / unpack / list-udebpkg
1 #!/usr/bin/perl -w
2 # list-udebpkg -- lintian helper script
3
4 # Copyright (C) 1998 Christian Schwarz
5 # Copyright (C) 2004 Frank Lichtenheld
6
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
11
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16
17 # You should have received a copy of the GNU General Public License
18 # along with this program.  If not, you can find it on the World Wide
19 # Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free
20 # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
21 # MA 02110-1301, USA.
22
23 use strict;
24
25 # turn file buffering off:
26 $| = 1;
27
28 # parse command line options
29 if ($#ARGV == -1) {
30     print "list-udebpkg [-v] <output-list-file>\n";
31     print "options:\n";
32     print "   -v  verbose\n";
33     exit 0;
34 }
35
36 my $verbose = 0;
37 my $output_file = undef;
38 my $pkgdata = undef; # WTF?
39
40 while (my $arg = shift) {
41     if ($arg =~ s,^-,,o) {
42         if ($arg eq 'v') {
43             $verbose = 1;
44         } else {
45             print STDERR "error: unknown command line argument: $arg\n";
46             exit 1;
47         }
48     } else {
49         if ($output_file) {
50             print STDERR "error: too many command line arguments: $arg\n";
51             exit 1;
52         }
53         $output_file = $arg;
54     }
55 }
56
57 unless ($output_file) {
58     print STDERR "error: no output file specified\n";
59     exit 1;
60 }
61
62 # import perl libraries
63 use lib "$ENV{'LINTIAN_ROOT'}/lib";
64 use Read_pkglists;
65 use vars qw(%udeb_info $UDEBLIST_FORMAT); # from the above
66 use Pipeline;
67 use Util;
68
69 # get variables out of environment
70 my $LINTIAN_ARCHIVEDIR = $ENV{'LINTIAN_ARCHIVEDIR'};
71 my $LINTIAN_DIST = $ENV{'LINTIAN_DIST'};
72 my $LINTIAN_ARCH = $ENV{'LINTIAN_ARCH'};
73 my $LINTIAN_SECTION = $ENV{'LINTIAN_SECTION'};
74 my $LINTIAN_LAB = $ENV{'LINTIAN_LAB'};
75
76 # read old list file (this command does nothing if the file does not exist)
77 read_udeb_list($output_file,1);
78
79 my %pkgfile;
80 # map filenames to package names
81 for my $pkg (keys %udeb_info) {
82     $pkgfile{$udeb_info{$pkg}->{'file'}} = $pkg;
83 }
84
85 # open output file
86 open(OUT, '>', $output_file)
87     or fail("cannot open list file $output_file for writing: $!");
88 print OUT "$UDEBLIST_FORMAT\n";
89
90 # parse Packages file to get list of packages
91 my $packages = "$LINTIAN_ARCHIVEDIR/dists/$LINTIAN_DIST/$LINTIAN_SECTION/".
92                "debian-installer/binary-$LINTIAN_ARCH/Packages";
93 if (-e $packages) {
94     print "N: Parsing $packages ...\n" if $verbose;
95     open(IN, '<', $packages) or fail("cannot open Packages file $packages: $!");
96 } elsif (-e "$packages.gz") {
97     print "N: Parsing $packages.gz ...\n" if $verbose;
98     open(IN, '-|', 'gzip', '-dc', "$packages.gz")
99         or fail("cannot open Packages file $packages.gz: $!");
100 } else {
101     fail("No packages file $packages");
102 }
103
104 my $line;
105 my %packages;
106 my $total = 0;
107
108 while (!eof(IN)) {
109     do { $line = <IN> } until ($line =~ m/^Architecture: (.*)$/m);
110     my $arch = $1;
111     do { $line = <IN> } until ($line =~ m/^Filename: (.*)$/m);
112     my $deb_file = $1;
113     do { $line = <IN> } until ($line =~ m/^\s*$/m);
114
115     my @stat;
116     # get timestamp...
117     unless (@stat = stat "$LINTIAN_ARCHIVEDIR/$deb_file") {
118         print "E: general: cannot stat $LINTIAN_ARCHIVEDIR/$deb_file\n";
119         next;
120     }
121     my $timestamp = $stat[9];
122     my ($status, $pkg, $data);
123
124     # was package already included in last list?
125     if (exists $pkgfile{$deb_file}) {
126         # yes!
127         $pkg = $pkgfile{$deb_file};
128         $data = $udeb_info{$pkg};
129
130         # file changed since last run?
131         if ($timestamp == $data->{'timestamp'}) {
132             # no.
133             $status = 'unchanged';
134         } else {
135             $status = 'changed';
136             delete $udeb_info{$pkg};
137         }
138     } else {
139         # new package, get info
140         $status = 'new';
141     }
142
143     if (($status eq 'new') or ($status eq 'changed')) {
144         if (defined $pkgdata) {
145             # avoid collecting the info twice
146             $data = $pkgdata;
147         } else {
148             $data = &safe_get_deb_info($deb_file);
149         }
150         next if not defined $data;
151         $pkg = $data->{'package'};
152     }
153
154     # check for duplicates
155     if (exists $packages{$pkg}) {
156         print "E: general: duplicate-udeb-package $pkg\n";
157         next;
158     }
159
160     # write entry to output file
161     print OUT join(';',
162                    $pkg,
163                    $data->{'version'},
164                    $data->{'source'},
165                    $deb_file,
166                    $timestamp,
167                    ),"\n";
168     printf "N: Listed %s udeb package %s %s\n",$status,$pkg,$data->{'version'} if $verbose;
169
170     # remove record from hash
171     delete $udeb_info{$pkg} if $status eq 'unchanged';
172     $packages{$pkg} = 1;
173     $total++;
174 }
175 close(IN) or fail("cannot close input pipe: $!");
176 close(OUT) or fail("cannot close output pipe: $!");
177
178 if ($verbose) {
179     # all packages that are still included in %udeb_info have disappeared from the archive...
180     for my $pkg (sort keys %udeb_info) {
181         print "N: Removed udeb package $pkg from list\n";
182     }
183     printf "N: Listed %d udeb packages\n",$total;
184 }
185
186 exit 0;
187
188 sub safe_get_deb_info {
189     # use eval when calling get_deb_info, since we don't want to `die' just
190     # because of a single broken package
191     my $data;
192     eval { $data = get_deb_info("$LINTIAN_ARCHIVEDIR/$_[0]"); };
193     if ($@) {
194         # error!
195         print STDERR "$@\n";
196         print "E: general: bad-udeb-package $_[0]\n";
197         return undef;
198     }
199     $data->{'source'} or ($data->{'source'} = $data->{'package'});
200     return $data;
201 }