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