Fix concise-xs.t following the changes to B::Deparse.
[p5sagit/p5-mst-13.2.git] / lib / ExtUtils / Packlist.pm
CommitLineData
93cd2f30 1package ExtUtils::Packlist;
17f410f9 2
57b1a898 3use 5.00503;
93cd2f30 4use strict;
5use Carp qw();
57b1a898 6use vars qw($VERSION);
3a465856 7$VERSION = '1.38';
8$VERSION = eval $VERSION;
93cd2f30 9
10# Used for generating filehandle globs. IO::File might not be available!
11my $fhname = "FH1";
12
3a465856 13=begin _undocumented
14
15=item mkfh()
16
17Make a filehandle. Same kind of idea as Symbol::gensym().
18
19=end _undocumented
20
21=cut
22
93cd2f30 23sub mkfh()
24{
25no strict;
26my $fh = \*{$fhname++};
27use strict;
28return($fh);
29}
30
31sub new($$)
32{
33my ($class, $packfile) = @_;
34$class = ref($class) || $class;
35my %self;
36tie(%self, $class, $packfile);
37return(bless(\%self, $class));
38}
39
40sub TIEHASH
41{
42my ($class, $packfile) = @_;
43my $self = { packfile => $packfile };
44bless($self, $class);
45$self->read($packfile) if (defined($packfile) && -f $packfile);
46return($self);
47}
48
49sub STORE
50{
51$_[0]->{data}->{$_[1]} = $_[2];
52}
53
54sub FETCH
55{
56return($_[0]->{data}->{$_[1]});
57}
58
59sub FIRSTKEY
60{
61my $reset = scalar(keys(%{$_[0]->{data}}));
62return(each(%{$_[0]->{data}}));
63}
64
65sub NEXTKEY
66{
67return(each(%{$_[0]->{data}}));
68}
69
70sub EXISTS
71{
72return(exists($_[0]->{data}->{$_[1]}));
73}
74
75sub DELETE
76{
77return(delete($_[0]->{data}->{$_[1]}));
78}
79
80sub CLEAR
81{
82%{$_[0]->{data}} = ();
83}
84
85sub DESTROY
86{
87}
88
89sub read($;$)
90{
91my ($self, $packfile) = @_;
92$self = tied(%$self) || $self;
93
94if (defined($packfile)) { $self->{packfile} = $packfile; }
95else { $packfile = $self->{packfile}; }
96Carp::croak("No packlist filename specified") if (! defined($packfile));
97my $fh = mkfh();
98open($fh, "<$packfile") || Carp::croak("Can't open file $packfile: $!");
99$self->{data} = {};
100my ($line);
101while (defined($line = <$fh>))
102 {
103 chomp $line;
411cc70a 104 my ($key, @kvs) = $line;
105 if ($key =~ /^(.*?)( \w+=.*)$/)
106 {
107 $key = $1;
108 @kvs = split(' ', $2);
109 }
9b604809 110 $key =~ s!/\./!/!g; # Some .packlists have spurious '/./' bits in the paths
93cd2f30 111 if (! @kvs)
112 {
113 $self->{data}->{$key} = undef;
114 }
115 else
116 {
117 my ($data) = {};
118 foreach my $kv (@kvs)
119 {
120 my ($k, $v) = split('=', $kv);
121 $data->{$k} = $v;
122 }
123 $self->{data}->{$key} = $data;
124 }
125 }
126close($fh);
127}
128
129sub write($;$)
130{
131my ($self, $packfile) = @_;
132$self = tied(%$self) || $self;
133if (defined($packfile)) { $self->{packfile} = $packfile; }
134else { $packfile = $self->{packfile}; }
135Carp::croak("No packlist filename specified") if (! defined($packfile));
136my $fh = mkfh();
137open($fh, ">$packfile") || Carp::croak("Can't open file $packfile: $!");
138foreach my $key (sort(keys(%{$self->{data}})))
139 {
140 print $fh ("$key");
141 if (ref($self->{data}->{$key}))
142 {
143 my $data = $self->{data}->{$key};
144 foreach my $k (sort(keys(%$data)))
145 {
146 print $fh (" $k=$data->{$k}");
147 }
148 }
149 print $fh ("\n");
150 }
151close($fh);
152}
153
154sub validate($;$)
155{
156my ($self, $remove) = @_;
157$self = tied(%$self) || $self;
158my @missing;
159foreach my $key (sort(keys(%{$self->{data}})))
160 {
161 if (! -e $key)
162 {
163 push(@missing, $key);
164 delete($self->{data}{$key}) if ($remove);
165 }
166 }
167return(@missing);
168}
169
9b604809 170sub packlist_file($)
171{
172my ($self) = @_;
173$self = tied(%$self) || $self;
174return($self->{packfile});
175}
176
93cd2f30 1771;
178
179__END__
180
181=head1 NAME
182
183ExtUtils::Packlist - manage .packlist files
184
185=head1 SYNOPSIS
186
187 use ExtUtils::Packlist;
188 my ($pl) = ExtUtils::Packlist->new('.packlist');
189 $pl->read('/an/old/.packlist');
190 my @missing_files = $pl->validate();
191 $pl->write('/a/new/.packlist');
192
193 $pl->{'/some/file/name'}++;
194 or
195 $pl->{'/some/other/file/name'} = { type => 'file',
196 from => '/some/file' };
197
198=head1 DESCRIPTION
199
200ExtUtils::Packlist provides a standard way to manage .packlist files.
201Functions are provided to read and write .packlist files. The original
202.packlist format is a simple list of absolute pathnames, one per line. In
203addition, this package supports an extended format, where as well as a filename
204each line may contain a list of attributes in the form of a space separated
205list of key=value pairs. This is used by the installperl script to
206differentiate between files and links, for example.
207
208=head1 USAGE
209
210The hash reference returned by the new() function can be used to examine and
211modify the contents of the .packlist. Items may be added/deleted from the
212.packlist by modifying the hash. If the value associated with a hash key is a
213scalar, the entry written to the .packlist by any subsequent write() will be a
214simple filename. If the value is a hash, the entry written will be the
215filename followed by the key=value pairs from the hash. Reading back the
216.packlist will recreate the original entries.
217
218=head1 FUNCTIONS
219
bbc7dcd2 220=over 4
93cd2f30 221
222=item new()
223
224This takes an optional parameter, the name of a .packlist. If the file exists,
225it will be opened and the contents of the file will be read. The new() method
226returns a reference to a hash. This hash holds an entry for each line in the
227.packlist. In the case of old-style .packlists, the value associated with each
228key is undef. In the case of new-style .packlists, the value associated with
229each key is a hash containing the key=value pairs following the filename in the
230.packlist.
231
232=item read()
233
234This takes an optional parameter, the name of the .packlist to be read. If
235no file is specified, the .packlist specified to new() will be read. If the
236.packlist does not exist, Carp::croak will be called.
237
238=item write()
239
240This takes an optional parameter, the name of the .packlist to be written. If
241no file is specified, the .packlist specified to new() will be overwritten.
242
243=item validate()
244
245This checks that every file listed in the .packlist actually exists. If an
246argument which evaluates to true is given, any missing files will be removed
247from the internal hash. The return value is a list of the missing files, which
248will be empty if they all exist.
249
9b604809 250=item packlist_file()
251
252This returns the name of the associated .packlist file
253
93cd2f30 254=back
255
ddf41153 256=head1 EXAMPLE
257
258Here's C<modrm>, a little utility to cleanly remove an installed module.
259
260 #!/usr/local/bin/perl -w
261
262 use strict;
263 use IO::Dir;
264 use ExtUtils::Packlist;
265 use ExtUtils::Installed;
266
267 sub emptydir($) {
268 my ($dir) = @_;
269 my $dh = IO::Dir->new($dir) || return(0);
270 my @count = $dh->read();
271 $dh->close();
272 return(@count == 2 ? 1 : 0);
273 }
274
275 # Find all the installed packages
276 print("Finding all installed modules...\n");
277 my $installed = ExtUtils::Installed->new();
278
279 foreach my $module (grep(!/^Perl$/, $installed->modules())) {
280 my $version = $installed->version($module) || "???";
281 print("Found module $module Version $version\n");
282 print("Do you want to delete $module? [n] ");
283 my $r = <STDIN>; chomp($r);
284 if ($r && $r =~ /^y/i) {
285 # Remove all the files
286 foreach my $file (sort($installed->files($module))) {
287 print("rm $file\n");
288 unlink($file);
289 }
290 my $pf = $installed->packlist($module)->packlist_file();
291 print("rm $pf\n");
292 unlink($pf);
293 foreach my $dir (sort($installed->directory_tree($module))) {
294 if (emptydir($dir)) {
295 print("rmdir $dir\n");
296 rmdir($dir);
297 }
298 }
299 }
300 }
301
93cd2f30 302=head1 AUTHOR
303
304Alan Burlison <Alan.Burlison@uk.sun.com>
305
306=cut