line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package PPM; |
2
|
|
|
|
|
|
|
require 5.004; |
3
|
|
|
|
|
|
|
require Exporter; |
4
|
2
|
|
|
2
|
|
1908
|
use vars qw( $VERSION ); |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
161
|
|
5
|
|
|
|
|
|
|
$VERSION = '0.01_01'; |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
@ISA = qw(Exporter); |
8
|
|
|
|
|
|
|
@EXPORT = qw(PPMdat PPMERR InstalledPackageProperties ListOfRepositories |
9
|
|
|
|
|
|
|
RemoveRepository AddRepository GetPPMOptions SetPPMOptions InstallPackage |
10
|
|
|
|
|
|
|
RemovePackage VerifyPackage UpgradePackage RepositoryPackages |
11
|
|
|
|
|
|
|
RepositoryPackageProperties QueryInstalledPackages |
12
|
|
|
|
|
|
|
RepositorySummary ServerSearch PPMShell); |
13
|
|
|
|
|
|
|
|
14
|
2
|
|
|
2
|
|
1296
|
use LWP::UserAgent; |
|
2
|
|
|
|
|
84227
|
|
|
2
|
|
|
|
|
61
|
|
15
|
2
|
|
|
2
|
|
8433
|
use LWP::Simple; |
|
2
|
|
|
|
|
52572
|
|
|
2
|
|
|
|
|
18
|
|
16
|
|
|
|
|
|
|
|
17
|
2
|
|
|
2
|
|
732
|
use File::Basename; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
154
|
|
18
|
2
|
|
|
2
|
|
1309
|
use File::Copy; |
|
2
|
|
|
|
|
4639
|
|
|
2
|
|
|
|
|
123
|
|
19
|
2
|
|
|
2
|
|
13
|
use File::Path; |
|
2
|
|
|
|
|
2
|
|
|
2
|
|
|
|
|
91
|
|
20
|
2
|
|
|
2
|
|
10
|
use File::Spec; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
28
|
|
21
|
2
|
|
|
2
|
|
1449
|
use ExtUtils::Install; |
|
2
|
|
|
|
|
34640
|
|
|
2
|
|
|
|
|
141
|
|
22
|
2
|
|
|
2
|
|
13
|
use Cwd; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
94
|
|
23
|
2
|
|
|
2
|
|
9
|
use Config; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
74
|
|
24
|
2
|
|
|
2
|
|
1269
|
use PPM::RelocPerl; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
82
|
|
25
|
|
|
|
|
|
|
|
26
|
2
|
|
|
2
|
|
860
|
use PPM::XML::PPD; |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
92
|
|
27
|
2
|
|
|
2
|
|
1312
|
use PPM::XML::PPMConfig; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
52
|
|
28
|
2
|
|
|
2
|
|
503
|
use XML::Parser; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
use Archive::Tar; |
30
|
|
|
|
|
|
|
use Archive::Zip; |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
use strict; |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
if ($] <= 5.008) { |
35
|
|
|
|
|
|
|
require SOAP::Lite; |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
my $useDocTools; # Generate HTML documentation after installing a package |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
BEGIN { |
41
|
|
|
|
|
|
|
if (eval "require ActivePerl::DocTools") { |
42
|
|
|
|
|
|
|
import ActivePerl::DocTools; |
43
|
|
|
|
|
|
|
$useDocTools++; |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
#set Debug to 1 to debug PPMdat file reading |
48
|
|
|
|
|
|
|
# 2 to debug parsing PPDs |
49
|
|
|
|
|
|
|
# |
50
|
|
|
|
|
|
|
# values may be or'ed together. |
51
|
|
|
|
|
|
|
# |
52
|
|
|
|
|
|
|
my $Debug = 0; |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
my ($PPMERR, $PPM_ver, $CPU, $OS_VALUE, $OS_VERSION, $LANGUAGE); |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
# options from data file. |
57
|
|
|
|
|
|
|
my %options; |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
my $TraceStarted = 0; |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# true if we're running from ppm.pl, as opposed to VPM, etc. |
62
|
|
|
|
|
|
|
my $PPMShell; |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
my %repositories; |
65
|
|
|
|
|
|
|
my %cached_ppd_list; |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
# Keys for this hash are package names. It is filled in by a successful |
68
|
|
|
|
|
|
|
# call to read_config(). Each package is a hash with the following keys: |
69
|
|
|
|
|
|
|
# LOCATION, INST_DATE, INST_ROOT, INST_PACKLIST and INST_PPD. |
70
|
|
|
|
|
|
|
my %installed_packages = (); |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# Keys for this hash are CODEBASE, INSTALL_HREF, INSTALL_EXEC, |
73
|
|
|
|
|
|
|
# INSTALL_SCRIPT, NAME, VERSION, TITLE, ABSTRACT, LICENSE, AUTHOR, |
74
|
|
|
|
|
|
|
# UNINSTALL_HREF, UNINSTALL_EXEC, UNINSTALL_SCRIPT, PERLCORE_VER and DEPEND. |
75
|
|
|
|
|
|
|
# It is filled in after a successful call to parsePPD(). |
76
|
|
|
|
|
|
|
my %current_package = (); |
77
|
|
|
|
|
|
|
my @current_package_stack; |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
# this may get overridden by the config file. |
80
|
|
|
|
|
|
|
my @required_packages = qw(PPM SOAP-Lite libnet Archive-Tar Compress-Zlib |
81
|
|
|
|
|
|
|
libwww-perl XML-Parser XML-Element); |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
# Packages that can't be upgraded on Win9x |
84
|
|
|
|
|
|
|
my @Win9x_denied = qw(xml-parser compress-zlib); |
85
|
|
|
|
|
|
|
my %Win9x_denied; |
86
|
|
|
|
|
|
|
@Win9x_denied{@Win9x_denied} = (); |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
# ppm.xml location is in the environment variable 'PPM_DAT', else it is in |
89
|
|
|
|
|
|
|
# [Perl]/site/lib, else it is in the same place as this script. |
90
|
|
|
|
|
|
|
my ($basename, $path) = fileparse($0); |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
if (defined $ENV{'PPM_DAT'} && -f $ENV{'PPM_DAT'}) |
93
|
|
|
|
|
|
|
{ |
94
|
|
|
|
|
|
|
$PPM::PPMdat = $ENV{'PPM_DAT'}; |
95
|
|
|
|
|
|
|
} |
96
|
|
|
|
|
|
|
elsif (-f "$Config{'installsitelib'}/ppm.xml") |
97
|
|
|
|
|
|
|
{ |
98
|
|
|
|
|
|
|
$PPM::PPMdat = "$Config{'installsitelib'}/ppm.xml"; |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
elsif (-f "$Config{'installprivlib'}/ppm.xml") |
101
|
|
|
|
|
|
|
{ |
102
|
|
|
|
|
|
|
$PPM::PPMdat = "$Config{'installprivlib'}/ppm.xml"; |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
elsif (-f $path . "/ppm.xml") |
105
|
|
|
|
|
|
|
{ |
106
|
|
|
|
|
|
|
$PPM::PPMdat = $path . $PPM::PPMdat; |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
else |
109
|
|
|
|
|
|
|
{ |
110
|
|
|
|
|
|
|
&Trace("Failed to load PPM_DAT file") if $options{'TRACE'}; |
111
|
|
|
|
|
|
|
print "Failed to load PPM_DAT file\n"; |
112
|
|
|
|
|
|
|
return -1; |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
&Trace("Using config file: $PPM::PPMdat") if $options{'TRACE'}; |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
my $init = 0; |
118
|
|
|
|
|
|
|
chmod(0600, $PPM::PPMdat); |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
# add -5.d to archname for Perl >= 5.8 |
121
|
|
|
|
|
|
|
my $varchname = $Config{archname}; |
122
|
|
|
|
|
|
|
if ($] >= 5.008) { |
123
|
|
|
|
|
|
|
my $vstring = sprintf "%vd", $^V; |
124
|
|
|
|
|
|
|
$vstring =~ s/\.\d+$//; |
125
|
|
|
|
|
|
|
$varchname .= "-$vstring"; |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
# |
129
|
|
|
|
|
|
|
# Exported subs |
130
|
|
|
|
|
|
|
# |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
sub InstalledPackageProperties |
133
|
|
|
|
|
|
|
{ |
134
|
|
|
|
|
|
|
my %ret_hash; |
135
|
|
|
|
|
|
|
read_config(); |
136
|
|
|
|
|
|
|
foreach (keys %installed_packages) { |
137
|
|
|
|
|
|
|
parsePPD(%{ $installed_packages{$_}{'INST_PPD'} } ); |
138
|
|
|
|
|
|
|
$ret_hash{$_}{'NAME'} = $_; |
139
|
|
|
|
|
|
|
$ret_hash{$_}{'DATE'} = $installed_packages{$_}{'INST_DATE'}; |
140
|
|
|
|
|
|
|
$ret_hash{$_}{'TITLE'} = $current_package{'TITLE'}; |
141
|
|
|
|
|
|
|
$ret_hash{$_}{'AUTHOR'} = $current_package{'AUTHOR'}; |
142
|
|
|
|
|
|
|
$ret_hash{$_}{'VERSION'} = $current_package{'VERSION'}; |
143
|
|
|
|
|
|
|
$ret_hash{$_}{'ABSTRACT'} = $current_package{'ABSTRACT'}; |
144
|
|
|
|
|
|
|
$ret_hash{$_}{'PERLCORE_VER'} = $current_package{'PERLCORE_VER'}; |
145
|
|
|
|
|
|
|
foreach my $dep (keys %{$current_package{'DEPEND'}}) { |
146
|
|
|
|
|
|
|
push @{$ret_hash{$_}{'DEPEND'}}, $dep; |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
return %ret_hash; |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
sub ListOfRepositories |
153
|
|
|
|
|
|
|
{ |
154
|
|
|
|
|
|
|
my %reps; |
155
|
|
|
|
|
|
|
read_config(); |
156
|
|
|
|
|
|
|
foreach (keys %repositories) { |
157
|
|
|
|
|
|
|
$reps{$_} = $repositories{$_}{'LOCATION'}; |
158
|
|
|
|
|
|
|
} |
159
|
|
|
|
|
|
|
return %reps; |
160
|
|
|
|
|
|
|
} |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
sub RemoveRepository |
163
|
|
|
|
|
|
|
{ |
164
|
|
|
|
|
|
|
my %argv = @_; |
165
|
|
|
|
|
|
|
my $repository = $argv{'repository'}; |
166
|
|
|
|
|
|
|
my $save = $argv{'save'}; |
167
|
|
|
|
|
|
|
read_config(); |
168
|
|
|
|
|
|
|
foreach (keys %repositories) { |
169
|
|
|
|
|
|
|
if ($_ =~ /^\Q$repository\E$/) { |
170
|
|
|
|
|
|
|
&Trace("Removed repository $repositories{$repository}") |
171
|
|
|
|
|
|
|
if $options{'TRACE'}; |
172
|
|
|
|
|
|
|
delete $repositories{$repository}; |
173
|
|
|
|
|
|
|
last; |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
} |
176
|
|
|
|
|
|
|
save_options() if $save; |
177
|
|
|
|
|
|
|
} |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
sub AddRepository |
180
|
|
|
|
|
|
|
{ |
181
|
|
|
|
|
|
|
my %argv = @_; |
182
|
|
|
|
|
|
|
my $repository = $argv{'repository'}; |
183
|
|
|
|
|
|
|
my $save = $argv{'save'}; |
184
|
|
|
|
|
|
|
my $location = $argv{'location'}; |
185
|
|
|
|
|
|
|
my $username = $argv{'username'}; |
186
|
|
|
|
|
|
|
my $password = $argv{'password'}; |
187
|
|
|
|
|
|
|
my $summaryfile = $argv{'summaryfile'}; |
188
|
|
|
|
|
|
|
read_config(); |
189
|
|
|
|
|
|
|
$repositories{$repository}{'LOCATION'} = $location; |
190
|
|
|
|
|
|
|
$repositories{$repository}{'USERNAME'} = $username if defined $username; |
191
|
|
|
|
|
|
|
$repositories{$repository}{'PASSWORD'} = $password if defined $password; |
192
|
|
|
|
|
|
|
$repositories{$repository}{'SUMMARYFILE'} = $summaryfile |
193
|
|
|
|
|
|
|
if defined $summaryfile; |
194
|
|
|
|
|
|
|
&Trace("Added repository $location") if $options{'TRACE'}; |
195
|
|
|
|
|
|
|
save_options() if $save; |
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
sub GetPPMOptions |
199
|
|
|
|
|
|
|
{ |
200
|
|
|
|
|
|
|
read_config(); |
201
|
|
|
|
|
|
|
return %options; |
202
|
|
|
|
|
|
|
} |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
sub SetPPMOptions |
205
|
|
|
|
|
|
|
{ |
206
|
|
|
|
|
|
|
my %argv = @_; |
207
|
|
|
|
|
|
|
%options = %{$argv{'options'}}; |
208
|
|
|
|
|
|
|
save_options() if $argv{'save'}; |
209
|
|
|
|
|
|
|
} |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
sub UpgradePackage |
212
|
|
|
|
|
|
|
{ |
213
|
|
|
|
|
|
|
my %argv = @_; |
214
|
|
|
|
|
|
|
my $package = $argv{'package'}; |
215
|
|
|
|
|
|
|
my $location = $argv{'location'}; |
216
|
|
|
|
|
|
|
return VerifyPackage("package" => $package, "location" => $location, |
217
|
|
|
|
|
|
|
"upgrade" => 1); |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
# Returns 1 on success, 0 and sets $PPMERR on failure. |
221
|
|
|
|
|
|
|
sub InstallPackage |
222
|
|
|
|
|
|
|
{ |
223
|
|
|
|
|
|
|
my %argv = @_; |
224
|
|
|
|
|
|
|
my $package = $argv{'package'}; |
225
|
|
|
|
|
|
|
my $location = $argv{'location'}; |
226
|
|
|
|
|
|
|
my $root = $argv{'root'} || $options{'ROOT'} || undef; |
227
|
|
|
|
|
|
|
my ($PPDfile, %PPD); |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
read_config(); |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
if (!defined($package) && -d "blib" && -f "Makefile") { |
232
|
|
|
|
|
|
|
unless (open MAKEFILE, "< Makefile") { |
233
|
|
|
|
|
|
|
$PPM::PPMERR = "Couldn't open Makefile for reading: $!"; |
234
|
|
|
|
|
|
|
return 0; |
235
|
|
|
|
|
|
|
} |
236
|
|
|
|
|
|
|
while () { |
237
|
|
|
|
|
|
|
if (/^DISTNAME\s*=\s*(\S+)/) { |
238
|
|
|
|
|
|
|
$package = $1; |
239
|
|
|
|
|
|
|
$PPDfile = "$1.ppd"; |
240
|
|
|
|
|
|
|
last; |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
} |
243
|
|
|
|
|
|
|
close MAKEFILE; |
244
|
|
|
|
|
|
|
unless (defined $PPDfile) { |
245
|
|
|
|
|
|
|
$PPM::PPMERR = "Couldn't determine local package name"; |
246
|
|
|
|
|
|
|
return 0; |
247
|
|
|
|
|
|
|
} |
248
|
|
|
|
|
|
|
system("$Config{make} ppd"); |
249
|
|
|
|
|
|
|
return 0 unless (%PPD = getPPDfile('package' => $PPDfile)); |
250
|
|
|
|
|
|
|
parsePPD(%PPD); |
251
|
|
|
|
|
|
|
$options{'CLEAN'} = 0; |
252
|
|
|
|
|
|
|
goto InstallBlib; |
253
|
|
|
|
|
|
|
} |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
unless (%PPD = getPPDfile('package' => $package, |
256
|
|
|
|
|
|
|
'location' => $location, 'PPDfile' => \$PPDfile)) { |
257
|
|
|
|
|
|
|
&Trace("Could not locate a PPD file for package $package") |
258
|
|
|
|
|
|
|
if $options{'TRACE'}; |
259
|
|
|
|
|
|
|
$PPM::PPMERR = "Could not locate a PPD file for package $package"; |
260
|
|
|
|
|
|
|
return 0; |
261
|
|
|
|
|
|
|
} |
262
|
|
|
|
|
|
|
if ($Config{'osname'} eq 'MSWin32' && |
263
|
|
|
|
|
|
|
!&Win32::IsWinNT && exists $Win9x_denied{lc($package)}) { |
264
|
|
|
|
|
|
|
$PPM::PPMERR = "Package '$package' cannot be installed with PPM on Win9x--see http://www.ActiveState.com/ppm for details"; |
265
|
|
|
|
|
|
|
return 0; |
266
|
|
|
|
|
|
|
} |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
parsePPD(%PPD); |
269
|
|
|
|
|
|
|
if (!$current_package{'CODEBASE'} && !$current_package{'INSTALL_HREF'}) { |
270
|
|
|
|
|
|
|
&Trace("Read a PPD for '$package', but it is not intended for this build of Perl ($varchname)") |
271
|
|
|
|
|
|
|
if $options{'TRACE'}; |
272
|
|
|
|
|
|
|
$PPM::PPMERR = "Read a PPD for '$package', but it is not intended for this build of Perl ($varchname)"; |
273
|
|
|
|
|
|
|
return 0; |
274
|
|
|
|
|
|
|
} |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
if (defined $current_package{'DEPEND'}) { |
277
|
|
|
|
|
|
|
push(@current_package_stack, [%current_package]); |
278
|
|
|
|
|
|
|
foreach my $dep (keys %{$current_package{'DEPEND'}}) { |
279
|
|
|
|
|
|
|
# Has PPM already installed it? |
280
|
|
|
|
|
|
|
unless ($installed_packages{$dep}) { |
281
|
|
|
|
|
|
|
# Has *anybody* installed it, or is it part of core Perl? |
282
|
|
|
|
|
|
|
my $p = $dep; |
283
|
|
|
|
|
|
|
$p =~ s@-@/@g; |
284
|
|
|
|
|
|
|
my $found = grep -f, map "$_/$p.pm", @INC; |
285
|
|
|
|
|
|
|
unless ($found) { |
286
|
|
|
|
|
|
|
&Trace("Installing dependency '$dep'...") |
287
|
|
|
|
|
|
|
if $options{'TRACE'}; |
288
|
|
|
|
|
|
|
unless (!InstallPackage("package" => $dep, |
289
|
|
|
|
|
|
|
"location" => $location)) { |
290
|
|
|
|
|
|
|
&Trace("Error installing dependency: $PPM::PPMERR") |
291
|
|
|
|
|
|
|
if $options{'TRACE'}; |
292
|
|
|
|
|
|
|
$PPM::PPMERR = "Error installing dependency: $PPM::PPMERR\n"; |
293
|
|
|
|
|
|
|
return 0 unless ($options{'FORCE_INSTALL'}); |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
} |
296
|
|
|
|
|
|
|
} |
297
|
|
|
|
|
|
|
# make sure minimum version is installed, if necessary |
298
|
|
|
|
|
|
|
elsif (defined $current_package{'DEPEND'}{$dep}) { |
299
|
|
|
|
|
|
|
my @comp = |
300
|
|
|
|
|
|
|
split (',', cpan2ppd_version($current_package{'DEPEND'}{$dep})); |
301
|
|
|
|
|
|
|
# parsePPD fills in %current_package |
302
|
|
|
|
|
|
|
push(@current_package_stack, [%current_package]); |
303
|
|
|
|
|
|
|
parsePPD(%{$installed_packages{$dep}{'INST_PPD'}}); |
304
|
|
|
|
|
|
|
my @inst = |
305
|
|
|
|
|
|
|
split (',', cpan2ppd_version($current_package{'VERSION'})); |
306
|
|
|
|
|
|
|
foreach(0..3) { |
307
|
|
|
|
|
|
|
if ($comp[$_] > $inst[$_]) { |
308
|
|
|
|
|
|
|
VerifyPackage("package" => $dep, "upgrade" => 1); |
309
|
|
|
|
|
|
|
last; |
310
|
|
|
|
|
|
|
} |
311
|
|
|
|
|
|
|
last if ($comp[$_] < $inst[$_]); |
312
|
|
|
|
|
|
|
} |
313
|
|
|
|
|
|
|
%current_package = @{pop @current_package_stack}; |
314
|
|
|
|
|
|
|
} |
315
|
|
|
|
|
|
|
} |
316
|
|
|
|
|
|
|
%current_package = @{pop @current_package_stack}; |
317
|
|
|
|
|
|
|
} |
318
|
|
|
|
|
|
|
my ($basename, $path) = fileparse($PPDfile); |
319
|
|
|
|
|
|
|
# strip the trailing path separator |
320
|
|
|
|
|
|
|
my $chr = substr($path, -1, 1); |
321
|
|
|
|
|
|
|
chop $path if ($chr eq '/' || $chr eq '\\'); |
322
|
|
|
|
|
|
|
if ($path =~ /^file:\/\/.*\|/i) { |
323
|
|
|
|
|
|
|
# $path is a local directory, let's avoid LWP by changing |
324
|
|
|
|
|
|
|
# it to a pathname. |
325
|
|
|
|
|
|
|
$path =~ s@^file://@@i; |
326
|
|
|
|
|
|
|
$path =~ s@^localhost/@@i; |
327
|
|
|
|
|
|
|
$path =~ s@\|@:@; |
328
|
|
|
|
|
|
|
} |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
# get the code and put it in build_dir |
331
|
|
|
|
|
|
|
my $install_dir = "$options{'BUILDDIR'}/$current_package{'NAME'}-$$"; |
332
|
|
|
|
|
|
|
File::Path::rmtree($install_dir,0,0); |
333
|
|
|
|
|
|
|
unless (-d $install_dir || File::Path::mkpath($install_dir, 0, 0755)) { |
334
|
|
|
|
|
|
|
&Trace("Could not create $install_dir: $!") if $options{'TRACE'}; |
335
|
|
|
|
|
|
|
$PPM::PPMERR = "Could not create $install_dir: $!"; |
336
|
|
|
|
|
|
|
return 0; |
337
|
|
|
|
|
|
|
} |
338
|
|
|
|
|
|
|
$basename = fileparse($current_package{'CODEBASE'}); |
339
|
|
|
|
|
|
|
# CODEBASE is a URL |
340
|
|
|
|
|
|
|
if ($current_package{'CODEBASE'} =~ m@^...*://@i) { |
341
|
|
|
|
|
|
|
return 0 unless read_href('href' => "$current_package{'CODEBASE'}", |
342
|
|
|
|
|
|
|
'target' => "$install_dir/$basename", 'request' => "GET", |
343
|
|
|
|
|
|
|
'progress' => 1); |
344
|
|
|
|
|
|
|
} |
345
|
|
|
|
|
|
|
# CODEBASE is a full pathname |
346
|
|
|
|
|
|
|
elsif (-f $current_package{'CODEBASE'}) { |
347
|
|
|
|
|
|
|
&Trace("Copying $current_package{'CODEBASE'} to $install_dir/$basename") |
348
|
|
|
|
|
|
|
if $options{'TRACE'} > 1; |
349
|
|
|
|
|
|
|
copy($current_package{'CODEBASE'}, "$install_dir/$basename"); |
350
|
|
|
|
|
|
|
} |
351
|
|
|
|
|
|
|
# CODEBASE is relative to the directory location of the PPD |
352
|
|
|
|
|
|
|
elsif (-f "$path/$current_package{'CODEBASE'}") { |
353
|
|
|
|
|
|
|
&Trace("Copying $path/$current_package{'CODEBASE'} to $install_dir/$basename") if $options{'TRACE'} > 1; |
354
|
|
|
|
|
|
|
copy("$path/$current_package{'CODEBASE'}", "$install_dir/$basename"); |
355
|
|
|
|
|
|
|
} |
356
|
|
|
|
|
|
|
# CODEBASE is relative to the URL location of the PPD |
357
|
|
|
|
|
|
|
else { |
358
|
|
|
|
|
|
|
return 0 unless read_href('target' => "$install_dir/$basename", |
359
|
|
|
|
|
|
|
'href' => "$path/$current_package{'CODEBASE'}", |
360
|
|
|
|
|
|
|
'request' => 'GET', 'progress' => 1); |
361
|
|
|
|
|
|
|
} |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
my $cwd = getcwd(); |
364
|
|
|
|
|
|
|
$cwd .= "/" if $cwd =~ /[a-z]:$/i; |
365
|
|
|
|
|
|
|
chdir($install_dir); |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
my ($tarzip, $have_zip); |
368
|
|
|
|
|
|
|
if ($basename =~ /\.zip$/i) { |
369
|
|
|
|
|
|
|
$have_zip = 1; |
370
|
|
|
|
|
|
|
$tarzip = Archive::Zip->new($basename); |
371
|
|
|
|
|
|
|
$tarzip->extractTree(); |
372
|
|
|
|
|
|
|
} |
373
|
|
|
|
|
|
|
elsif ($basename =~ /\.gz$/i) { |
374
|
|
|
|
|
|
|
$tarzip = Archive::Tar->new($basename,1); |
375
|
|
|
|
|
|
|
} |
376
|
|
|
|
|
|
|
else { |
377
|
|
|
|
|
|
|
$tarzip = Archive::Tar->new($basename,0); |
378
|
|
|
|
|
|
|
} |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
if ($have_zip) { |
381
|
|
|
|
|
|
|
$basename =~ /(.*).zip/i; |
382
|
|
|
|
|
|
|
} |
383
|
|
|
|
|
|
|
else { |
384
|
|
|
|
|
|
|
$tarzip->extract($tarzip->list_files); |
385
|
|
|
|
|
|
|
$basename =~ /(.*).tar/i; |
386
|
|
|
|
|
|
|
} |
387
|
|
|
|
|
|
|
chdir($1); |
388
|
|
|
|
|
|
|
RelocPerl('.') if ($Config{'osname'} ne 'MSWin32'); |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
InstallBlib: |
391
|
|
|
|
|
|
|
my $inst_archlib = $Config{installsitearch}; |
392
|
|
|
|
|
|
|
my $inst_root = $Config{prefix}; |
393
|
|
|
|
|
|
|
my $packlist = File::Spec->catfile("$Config{installsitearch}/auto", |
394
|
|
|
|
|
|
|
split(/-/, $current_package{'NAME'}), ".packlist"); |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
# copied from ExtUtils::Install |
397
|
|
|
|
|
|
|
my $INST_LIB = File::Spec->catdir(File::Spec->curdir,"blib","lib"); |
398
|
|
|
|
|
|
|
my $INST_ARCHLIB = File::Spec->catdir(File::Spec->curdir,"blib","arch"); |
399
|
|
|
|
|
|
|
my $INST_BIN = File::Spec->catdir(File::Spec->curdir,'blib','bin'); |
400
|
|
|
|
|
|
|
my $INST_SCRIPT = File::Spec->catdir(File::Spec->curdir,'blib','script'); |
401
|
|
|
|
|
|
|
my $INST_MAN1DIR = File::Spec->catdir(File::Spec->curdir,'blib','man1'); |
402
|
|
|
|
|
|
|
my $INST_MAN3DIR = File::Spec->catdir(File::Spec->curdir,'blib','man3'); |
403
|
|
|
|
|
|
|
my $INST_HTMLDIR = File::Spec->catdir(File::Spec->curdir,'blib','html'); |
404
|
|
|
|
|
|
|
my $INST_HTMLHELPDIR = File::Spec->catdir(File::Spec->curdir,'blib','htmlhelp'); |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
my $inst_script = $Config{installscript}; |
407
|
|
|
|
|
|
|
my $inst_man1dir = $Config{installman1dir}; |
408
|
|
|
|
|
|
|
my $inst_man3dir = $Config{installman3dir}; |
409
|
|
|
|
|
|
|
my $inst_bin = $Config{installbin}; |
410
|
|
|
|
|
|
|
my $inst_htmldir = $Config{installhtmldir}; |
411
|
|
|
|
|
|
|
my $inst_htmlhelpdir = $Config{installhtmlhelpdir}; |
412
|
|
|
|
|
|
|
my $inst_lib = $Config{installsitelib}; |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
if (defined $root && $root !~ /^\Q$inst_root\E$/i) { |
415
|
|
|
|
|
|
|
$packlist =~ s/\Q$inst_root/$root\E/i; |
416
|
|
|
|
|
|
|
$inst_lib =~ s/\Q$inst_root/$root\E/i; |
417
|
|
|
|
|
|
|
$inst_archlib =~ s/\Q$inst_root/$root\E/i; |
418
|
|
|
|
|
|
|
$inst_bin =~ s/\Q$inst_root/$root\E/i; |
419
|
|
|
|
|
|
|
$inst_script =~ s/\Q$inst_root/$root\E/i; |
420
|
|
|
|
|
|
|
$inst_man1dir =~ s/\Q$inst_root/$root\E/i; |
421
|
|
|
|
|
|
|
$inst_man3dir =~ s/\Q$inst_root/$root\E/i; |
422
|
|
|
|
|
|
|
$inst_root = $root; |
423
|
|
|
|
|
|
|
} |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
while (1) { |
426
|
|
|
|
|
|
|
my $cwd = getcwd(); |
427
|
|
|
|
|
|
|
$cwd .= "/" if $cwd =~ /[a-z]:$/i; |
428
|
|
|
|
|
|
|
&Trace("Calling ExtUtils::Install::install") if $options{'TRACE'} > 1; |
429
|
|
|
|
|
|
|
eval { |
430
|
|
|
|
|
|
|
ExtUtils::Install::install({ |
431
|
|
|
|
|
|
|
"read" => $packlist, "write" => $packlist, |
432
|
|
|
|
|
|
|
$INST_LIB => $inst_lib, $INST_ARCHLIB => $inst_archlib, |
433
|
|
|
|
|
|
|
$INST_BIN => $inst_bin, $INST_SCRIPT => $inst_script, |
434
|
|
|
|
|
|
|
$INST_MAN1DIR => $inst_man1dir, $INST_MAN3DIR => $inst_man3dir, |
435
|
|
|
|
|
|
|
$INST_HTMLDIR => $inst_htmldir, |
436
|
|
|
|
|
|
|
$INST_HTMLHELPDIR => $inst_htmlhelpdir},0,0,0); |
437
|
|
|
|
|
|
|
}; |
438
|
|
|
|
|
|
|
# install might have croaked in another directory |
439
|
|
|
|
|
|
|
chdir($cwd); |
440
|
|
|
|
|
|
|
# Can't remove some DLLs, but we can rename them and try again. |
441
|
|
|
|
|
|
|
if ($@ && $@ =~ /Cannot forceunlink (\S+)/) { |
442
|
|
|
|
|
|
|
&Trace("$@...attempting rename") if $options{'TRACE'}; |
443
|
|
|
|
|
|
|
my $oldname = $1; |
444
|
|
|
|
|
|
|
$oldname =~ s/:$//; |
445
|
|
|
|
|
|
|
my $newname = $oldname . "." . time(); |
446
|
|
|
|
|
|
|
unless (rename($oldname, $newname)) { |
447
|
|
|
|
|
|
|
&Trace("$!") if $options{'TRACE'}; |
448
|
|
|
|
|
|
|
$PPM::PPMERR = $@; |
449
|
|
|
|
|
|
|
return 0; |
450
|
|
|
|
|
|
|
} |
451
|
|
|
|
|
|
|
} |
452
|
|
|
|
|
|
|
# Some other error |
453
|
|
|
|
|
|
|
elsif($@) { |
454
|
|
|
|
|
|
|
&Trace("$@") if $options{'TRACE'}; |
455
|
|
|
|
|
|
|
$PPM::PPMERR = $@; |
456
|
|
|
|
|
|
|
return 0; |
457
|
|
|
|
|
|
|
} |
458
|
|
|
|
|
|
|
else { last; } |
459
|
|
|
|
|
|
|
} |
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
#rebuild the html TOC |
462
|
|
|
|
|
|
|
Trace("Calling ActivePerl::DocTools::WriteTOC()") if $options{'TRACE'} > 1; |
463
|
|
|
|
|
|
|
ActivePerl::DocTools::WriteTOC() if $useDocTools; |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
if (defined $current_package{'INSTALL_SCRIPT'}) { |
466
|
|
|
|
|
|
|
run_script("script" => $current_package{'INSTALL_SCRIPT'}, |
467
|
|
|
|
|
|
|
"scriptHREF" => $current_package{'INSTALL_HREF'}, |
468
|
|
|
|
|
|
|
"exec" => $current_package{'INSTALL_EXEC'}, |
469
|
|
|
|
|
|
|
"inst_root" => $inst_root, "inst_archlib" => $inst_archlib); |
470
|
|
|
|
|
|
|
} |
471
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
chdir($cwd); |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
# ask to store this location as default for this package? |
475
|
|
|
|
|
|
|
PPMdat_add_package($path, $packlist, $inst_root); |
476
|
|
|
|
|
|
|
# if 'install.ppm' exists, don't remove; system() |
477
|
|
|
|
|
|
|
# has probably not finished with it yet. |
478
|
|
|
|
|
|
|
if ($options{'CLEAN'} && !-f "$install_dir/install.ppm") { |
479
|
|
|
|
|
|
|
File::Path::rmtree($install_dir,0,0); |
480
|
|
|
|
|
|
|
} |
481
|
|
|
|
|
|
|
&Trace("Package $package successfully installed") if $options{'TRACE'}; |
482
|
|
|
|
|
|
|
reread_config(); |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
return 1; |
485
|
|
|
|
|
|
|
} |
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
# Returns a hash with key $location, and elements of arrays of package names. |
488
|
|
|
|
|
|
|
# Uses '%repositories' if $location is not specified. |
489
|
|
|
|
|
|
|
sub RepositoryPackages |
490
|
|
|
|
|
|
|
{ |
491
|
|
|
|
|
|
|
my %argv = @_; |
492
|
|
|
|
|
|
|
my $location = $argv{'location'}; |
493
|
|
|
|
|
|
|
my %ppds; |
494
|
|
|
|
|
|
|
if (defined $location) { |
495
|
|
|
|
|
|
|
@{$ppds{$location}} = list_available("location" => $location); |
496
|
|
|
|
|
|
|
} |
497
|
|
|
|
|
|
|
else { |
498
|
|
|
|
|
|
|
read_config(); # need repositories |
499
|
|
|
|
|
|
|
foreach (keys %repositories) { |
500
|
|
|
|
|
|
|
$location = $repositories{$_}{'LOCATION'}; |
501
|
|
|
|
|
|
|
@{$ppds{$location}} = list_available("location" => $location); |
502
|
|
|
|
|
|
|
} |
503
|
|
|
|
|
|
|
} |
504
|
|
|
|
|
|
|
return %ppds; |
505
|
|
|
|
|
|
|
} |
506
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
sub RepositoryPackageProperties |
508
|
|
|
|
|
|
|
{ |
509
|
|
|
|
|
|
|
my %argv = @_; |
510
|
|
|
|
|
|
|
my $location = $argv{'location'}; |
511
|
|
|
|
|
|
|
my $package = $argv{'package'}; |
512
|
|
|
|
|
|
|
my %PPD; |
513
|
|
|
|
|
|
|
read_config(); |
514
|
|
|
|
|
|
|
unless (%PPD = getPPDfile('package' => $package, 'location' => $location)) { |
515
|
|
|
|
|
|
|
&Trace("RepositoryPackageProperties: Could not locate a PPD file for package $package") if $options{'TRACE'}; |
516
|
|
|
|
|
|
|
$PPM::PPMERR = "Could not locate a PPD file for package $package"; |
517
|
|
|
|
|
|
|
return; |
518
|
|
|
|
|
|
|
} |
519
|
|
|
|
|
|
|
parsePPD(%PPD); |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
my %ret_hash = map { $_ => $current_package{$_} } |
522
|
|
|
|
|
|
|
qw(NAME TITLE AUTHOR VERSION ABSTRACT PERLCORE_VER); |
523
|
|
|
|
|
|
|
foreach my $dep (keys %{$current_package{'DEPEND'}}) { |
524
|
|
|
|
|
|
|
push @{$ret_hash{'DEPEND'}}, $dep; |
525
|
|
|
|
|
|
|
} |
526
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
return %ret_hash; |
528
|
|
|
|
|
|
|
} |
529
|
|
|
|
|
|
|
|
530
|
|
|
|
|
|
|
# Returns 1 on success, 0 and sets $PPMERR on failure. |
531
|
|
|
|
|
|
|
sub RemovePackage |
532
|
|
|
|
|
|
|
{ |
533
|
|
|
|
|
|
|
my %argv = @_; |
534
|
|
|
|
|
|
|
my $package = $argv{'package'}; |
535
|
|
|
|
|
|
|
my $force = $argv{'force'}; |
536
|
|
|
|
|
|
|
my %PPD; |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
read_config(); |
539
|
|
|
|
|
|
|
unless ($installed_packages{$package}) { |
540
|
|
|
|
|
|
|
my $pattern = $package; |
541
|
|
|
|
|
|
|
undef $package; |
542
|
|
|
|
|
|
|
# Do another lookup, ignoring case |
543
|
|
|
|
|
|
|
foreach (keys %installed_packages) { |
544
|
|
|
|
|
|
|
if (/^$pattern$/i) { |
545
|
|
|
|
|
|
|
$package = $_; |
546
|
|
|
|
|
|
|
last; |
547
|
|
|
|
|
|
|
} |
548
|
|
|
|
|
|
|
} |
549
|
|
|
|
|
|
|
unless ($package) { |
550
|
|
|
|
|
|
|
&Trace("Package '$pattern' has not been installed by PPM") |
551
|
|
|
|
|
|
|
if $options{'TRACE'}; |
552
|
|
|
|
|
|
|
$PPM::PPMERR = "Package '$pattern' has not been installed by PPM"; |
553
|
|
|
|
|
|
|
return 0; |
554
|
|
|
|
|
|
|
} |
555
|
|
|
|
|
|
|
} |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
# Don't let them remove PPM itself, libnet, Archive-Tar, etc. |
558
|
|
|
|
|
|
|
# but we can force removal if we're upgrading |
559
|
|
|
|
|
|
|
unless ($force) { |
560
|
|
|
|
|
|
|
foreach (@required_packages) { |
561
|
|
|
|
|
|
|
if ($_ eq $package) { |
562
|
|
|
|
|
|
|
&Trace("Package '$package' is required by PPM and cannot be removed") if $options{'TRACE'}; |
563
|
|
|
|
|
|
|
$PPM::PPMERR = "Package '$package' is required by PPM and cannot be removed"; |
564
|
|
|
|
|
|
|
return 0; |
565
|
|
|
|
|
|
|
} |
566
|
|
|
|
|
|
|
} |
567
|
|
|
|
|
|
|
} |
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
my $install_dir = "$options{'BUILDDIR'}/$package"; |
570
|
|
|
|
|
|
|
|
571
|
|
|
|
|
|
|
%PPD = %{ $installed_packages{$package}{'INST_PPD'} }; |
572
|
|
|
|
|
|
|
parsePPD(%PPD); |
573
|
|
|
|
|
|
|
my $cwd = getcwd(); |
574
|
|
|
|
|
|
|
$cwd .= "/" if $cwd =~ /[a-z]:$/i; |
575
|
|
|
|
|
|
|
if (defined $current_package{'UNINSTALL_SCRIPT'}) { |
576
|
|
|
|
|
|
|
if (!chdir($install_dir)) { |
577
|
|
|
|
|
|
|
&Trace("Could not chdir() to $install_dir: $!") if $options{'TRACE'}; |
578
|
|
|
|
|
|
|
$PPM::PPMERR = "Could not chdir() to $install_dir: $!"; |
579
|
|
|
|
|
|
|
return 0; |
580
|
|
|
|
|
|
|
} |
581
|
|
|
|
|
|
|
run_script("script" => $current_package{'UNINSTALL_SCRIPT'}, |
582
|
|
|
|
|
|
|
"scriptHREF" => $current_package{'UNINSTALL_HREF'}, |
583
|
|
|
|
|
|
|
"exec" => $current_package{'UNINSTALL_EXEC'}); |
584
|
|
|
|
|
|
|
chdir($cwd); |
585
|
|
|
|
|
|
|
} |
586
|
|
|
|
|
|
|
else { |
587
|
|
|
|
|
|
|
if (-f $installed_packages{$package}{'INST_PACKLIST'}) { |
588
|
|
|
|
|
|
|
&Trace("Calling ExtUtils::Install::uninstall") |
589
|
|
|
|
|
|
|
if $options{'TRACE'} > 1; |
590
|
|
|
|
|
|
|
eval { |
591
|
|
|
|
|
|
|
ExtUtils::Install::uninstall("$installed_packages{$package}{'INST_PACKLIST'}", 0, 0); |
592
|
|
|
|
|
|
|
}; |
593
|
|
|
|
|
|
|
warn $@ if $@; |
594
|
|
|
|
|
|
|
} |
595
|
|
|
|
|
|
|
} |
596
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
#rebuild the html TOC |
598
|
|
|
|
|
|
|
Trace("Calling ActivePerl::DocTools::WriteTOC()") if $options{'TRACE'} > 1; |
599
|
|
|
|
|
|
|
ActivePerl::DocTools::WriteTOC() if $useDocTools; |
600
|
|
|
|
|
|
|
|
601
|
|
|
|
|
|
|
File::Path::rmtree($install_dir,0,0); |
602
|
|
|
|
|
|
|
PPMdat_remove_package($package); |
603
|
|
|
|
|
|
|
&Trace("Package $package removed") if $options{'TRACE'}; |
604
|
|
|
|
|
|
|
reread_config(); |
605
|
|
|
|
|
|
|
return 1; |
606
|
|
|
|
|
|
|
} |
607
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
# returns "0" if package is up-to-date; "1" if an upgrade is available; |
609
|
|
|
|
|
|
|
# undef and sets $PPMERR on error; and the new VERSION string if a package |
610
|
|
|
|
|
|
|
# was upgraded. |
611
|
|
|
|
|
|
|
sub VerifyPackage |
612
|
|
|
|
|
|
|
{ |
613
|
|
|
|
|
|
|
my %argv = @_; |
614
|
|
|
|
|
|
|
my $package = $argv{'package'}; |
615
|
|
|
|
|
|
|
my $location = $argv{'location'}; |
616
|
|
|
|
|
|
|
my $upgrade = $argv{'upgrade'}; |
617
|
|
|
|
|
|
|
my $force = $argv{'force'}; |
618
|
|
|
|
|
|
|
my ($installedPPDfile, $comparePPDfile, %installedPPD, %comparePPD); |
619
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
read_config(); |
621
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
unless ($installed_packages{$package}) { |
623
|
|
|
|
|
|
|
my $pattern = $package; |
624
|
|
|
|
|
|
|
undef $package; |
625
|
|
|
|
|
|
|
# Do another lookup, ignoring case |
626
|
|
|
|
|
|
|
foreach (keys %installed_packages) { |
627
|
|
|
|
|
|
|
if (/^$pattern$/i) { |
628
|
|
|
|
|
|
|
$package = $_; |
629
|
|
|
|
|
|
|
last; |
630
|
|
|
|
|
|
|
} |
631
|
|
|
|
|
|
|
} |
632
|
|
|
|
|
|
|
unless ($package) { |
633
|
|
|
|
|
|
|
&Trace("Package '$pattern' has not been installed by PPM") if $options{'TRACE'}; |
634
|
|
|
|
|
|
|
$PPM::PPMERR = "Package '$pattern' has not been installed by PPM"; |
635
|
|
|
|
|
|
|
return undef; |
636
|
|
|
|
|
|
|
} |
637
|
|
|
|
|
|
|
} |
638
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
%installedPPD = %{ $installed_packages{$package}{'INST_PPD'} }; |
640
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
unless (%comparePPD = getPPDfile('package' => $package, |
642
|
|
|
|
|
|
|
'location' => $location)) { |
643
|
|
|
|
|
|
|
&Trace("VerifyPackage: Could not locate a PPD file for $package") |
644
|
|
|
|
|
|
|
if $options{'TRACE'}; |
645
|
|
|
|
|
|
|
$PPM::PPMERR = "Could not locate a PPD file for $package"; |
646
|
|
|
|
|
|
|
return; |
647
|
|
|
|
|
|
|
} |
648
|
|
|
|
|
|
|
|
649
|
|
|
|
|
|
|
parsePPD(%installedPPD); |
650
|
|
|
|
|
|
|
my @installed_version = |
651
|
|
|
|
|
|
|
split (',', cpan2ppd_version($current_package{'VERSION'})); |
652
|
|
|
|
|
|
|
my $inst_root = $installed_packages{$package}{'INST_ROOT'}; |
653
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
parsePPD(%comparePPD); |
655
|
|
|
|
|
|
|
unless ($current_package{'CODEBASE'} || $current_package{'INSTALL_HREF'}) { |
656
|
|
|
|
|
|
|
&Trace("Read a PPD for '$package', but it is not intended for this build of Perl ($varchname)") |
657
|
|
|
|
|
|
|
if $options{'TRACE'}; |
658
|
|
|
|
|
|
|
$PPM::PPMERR = "Read a PPD for '$package', but it is not intended for this build of Perl ($varchname)"; |
659
|
|
|
|
|
|
|
return undef; |
660
|
|
|
|
|
|
|
} |
661
|
|
|
|
|
|
|
my @compare_version |
662
|
|
|
|
|
|
|
= split (',', cpan2ppd_version($current_package{'VERSION'})); |
663
|
|
|
|
|
|
|
my $available; |
664
|
|
|
|
|
|
|
foreach(0..3) { |
665
|
|
|
|
|
|
|
next if $installed_version[$_] == $compare_version[$_]; |
666
|
|
|
|
|
|
|
$available++ if $installed_version[$_] < $compare_version[$_]; |
667
|
|
|
|
|
|
|
last; |
668
|
|
|
|
|
|
|
} |
669
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
if ($available || $force) { |
671
|
|
|
|
|
|
|
&Trace("Upgrade to $package is available") if $options{'TRACE'} > 1; |
672
|
|
|
|
|
|
|
if ($upgrade) { |
673
|
|
|
|
|
|
|
if ($Config{'osname'} eq 'MSWin32' && |
674
|
|
|
|
|
|
|
!&Win32::IsWinNT && exists $Win9x_denied{lc($package)}) { |
675
|
|
|
|
|
|
|
$PPM::PPMERR = "Package '$package' cannot be upgraded with PPM on Win9x--see http://www.ActiveState.com/ppm for details"; |
676
|
|
|
|
|
|
|
return undef; |
677
|
|
|
|
|
|
|
} |
678
|
|
|
|
|
|
|
|
679
|
|
|
|
|
|
|
# need to remember the $location, because once we remove the |
680
|
|
|
|
|
|
|
# package, it's unavailable. |
681
|
|
|
|
|
|
|
$location = $installed_packages{$package}{'LOCATION'} unless $location; |
682
|
|
|
|
|
|
|
unless (getPPDfile('package' => $package, |
683
|
|
|
|
|
|
|
'location' => $location)) { |
684
|
|
|
|
|
|
|
&Trace("VerifyPackage: Could not locate a PPD file for $package") if $options{'TRACE'}; |
685
|
|
|
|
|
|
|
$PPM::PPMERR = "Could not locate a PPD file for $package"; |
686
|
|
|
|
|
|
|
return undef; |
687
|
|
|
|
|
|
|
} |
688
|
|
|
|
|
|
|
RemovePackage("package" => $package, "force" => 1); |
689
|
|
|
|
|
|
|
InstallPackage("package" => $package, "location" => $location, |
690
|
|
|
|
|
|
|
"root" => $inst_root) or return undef; |
691
|
|
|
|
|
|
|
return $current_package{'VERSION'}; |
692
|
|
|
|
|
|
|
} |
693
|
|
|
|
|
|
|
return 1; |
694
|
|
|
|
|
|
|
} |
695
|
|
|
|
|
|
|
# package is up to date |
696
|
|
|
|
|
|
|
return 0; |
697
|
|
|
|
|
|
|
} |
698
|
|
|
|
|
|
|
|
699
|
|
|
|
|
|
|
# Changes where the packages are installed. |
700
|
|
|
|
|
|
|
# Returns previous root on success, undef and sets $PPMERR on failure. |
701
|
|
|
|
|
|
|
sub chroot |
702
|
|
|
|
|
|
|
{ |
703
|
|
|
|
|
|
|
my %argv = @_; |
704
|
|
|
|
|
|
|
my $location = $argv{'location'}; |
705
|
|
|
|
|
|
|
|
706
|
|
|
|
|
|
|
unless (-d $location) { |
707
|
|
|
|
|
|
|
&Trace("'$location' does not exist.") if $options{'TRACE'}; |
708
|
|
|
|
|
|
|
$PPM::PPMERR = "'$location' does not exist.\n"; |
709
|
|
|
|
|
|
|
return undef; |
710
|
|
|
|
|
|
|
} |
711
|
|
|
|
|
|
|
|
712
|
|
|
|
|
|
|
my $previous_root = $options{'ROOT'} || $Config{'prefix'}; |
713
|
|
|
|
|
|
|
$options{'ROOT'} = $location; |
714
|
|
|
|
|
|
|
return $previous_root; |
715
|
|
|
|
|
|
|
} |
716
|
|
|
|
|
|
|
|
717
|
|
|
|
|
|
|
sub QueryInstalledPackages |
718
|
|
|
|
|
|
|
{ |
719
|
|
|
|
|
|
|
my %argv = @_; |
720
|
|
|
|
|
|
|
my $ignorecase = $options{'IGNORECASE'} || $argv{'ignorecase'}; |
721
|
|
|
|
|
|
|
my $searchtag = uc $argv{'searchtag'} || undef; |
722
|
|
|
|
|
|
|
my ($searchRE, $package, %ret_hash); |
723
|
|
|
|
|
|
|
if (defined $argv{'searchRE'}) { |
724
|
|
|
|
|
|
|
$searchRE = $argv{'searchRE'}; |
725
|
|
|
|
|
|
|
$searchRE = "(?i)$searchRE" if $ignorecase; |
726
|
|
|
|
|
|
|
eval { $searchRE =~ /$searchRE/ }; |
727
|
|
|
|
|
|
|
if ($@) { |
728
|
|
|
|
|
|
|
&Trace("'$searchRE': invalid regular expression.") if $options{'TRACE'}; |
729
|
|
|
|
|
|
|
$PPM::PPMERR = "'$searchRE': invalid regular expression."; |
730
|
|
|
|
|
|
|
return (); |
731
|
|
|
|
|
|
|
} |
732
|
|
|
|
|
|
|
} |
733
|
|
|
|
|
|
|
|
734
|
|
|
|
|
|
|
read_config(); |
735
|
|
|
|
|
|
|
foreach $package (keys %installed_packages) { |
736
|
|
|
|
|
|
|
my $results = $package; |
737
|
|
|
|
|
|
|
if (defined $searchtag) { |
738
|
|
|
|
|
|
|
my %Package = %{ $installed_packages{$package} }; |
739
|
|
|
|
|
|
|
parsePPD( %{ $Package{'INST_PPD'} } ); |
740
|
|
|
|
|
|
|
$results = $current_package{$searchtag}; |
741
|
|
|
|
|
|
|
} |
742
|
|
|
|
|
|
|
|
743
|
|
|
|
|
|
|
$ret_hash{$package} = $results |
744
|
|
|
|
|
|
|
if (!defined $searchRE || ($results =~ /$searchRE/)); |
745
|
|
|
|
|
|
|
} |
746
|
|
|
|
|
|
|
|
747
|
|
|
|
|
|
|
return %ret_hash; |
748
|
|
|
|
|
|
|
} |
749
|
|
|
|
|
|
|
|
750
|
|
|
|
|
|
|
# Returns a summary of available packages for all repositories. |
751
|
|
|
|
|
|
|
# Returned hash has the following structure: |
752
|
|
|
|
|
|
|
# |
753
|
|
|
|
|
|
|
# $hash{repository}{package_name}{NAME} |
754
|
|
|
|
|
|
|
# $hash{repository}{package_name}{VERSION} |
755
|
|
|
|
|
|
|
# etc. |
756
|
|
|
|
|
|
|
# |
757
|
|
|
|
|
|
|
sub RepositorySummary { |
758
|
|
|
|
|
|
|
my %argv = @_; |
759
|
|
|
|
|
|
|
my $location = $argv{'location'}; |
760
|
|
|
|
|
|
|
my (%summary, %locations); |
761
|
|
|
|
|
|
|
|
762
|
|
|
|
|
|
|
# If we weren't given the location of a repository to query the summary |
763
|
|
|
|
|
|
|
# for, check all of the repositories that we know about. |
764
|
|
|
|
|
|
|
unless ($location) { |
765
|
|
|
|
|
|
|
read_config(); # need repositories |
766
|
|
|
|
|
|
|
foreach (keys %repositories) { |
767
|
|
|
|
|
|
|
$locations{$repositories{$_}{'LOCATION'}} = |
768
|
|
|
|
|
|
|
$repositories{$_}{'SUMMARYFILE'}; |
769
|
|
|
|
|
|
|
} |
770
|
|
|
|
|
|
|
} |
771
|
|
|
|
|
|
|
# Otherwise, we were given a repository to query, figure out where we can |
772
|
|
|
|
|
|
|
# find the summary file for that repository. |
773
|
|
|
|
|
|
|
else { |
774
|
|
|
|
|
|
|
foreach (keys %repositories) { |
775
|
|
|
|
|
|
|
if ($location =~ /\Q$repositories{$_}{'LOCATION'}\E/i) { |
776
|
|
|
|
|
|
|
$locations{$repositories{$_}{'LOCATION'}} = |
777
|
|
|
|
|
|
|
$repositories{$_}{'SUMMARYFILE'}; |
778
|
|
|
|
|
|
|
last; |
779
|
|
|
|
|
|
|
} |
780
|
|
|
|
|
|
|
} |
781
|
|
|
|
|
|
|
} |
782
|
|
|
|
|
|
|
|
783
|
|
|
|
|
|
|
# Check all of the summary file locations that we were able to find. |
784
|
|
|
|
|
|
|
foreach $location (keys %locations) { |
785
|
|
|
|
|
|
|
my $summaryfile = $locations{$location}; |
786
|
|
|
|
|
|
|
unless ($summaryfile) { |
787
|
|
|
|
|
|
|
&Trace("RepositorySummary: No summary available from $location.") |
788
|
|
|
|
|
|
|
if $options{'TRACE'}; |
789
|
|
|
|
|
|
|
$PPM::PPMERR = "No summary available from $location.\n"; |
790
|
|
|
|
|
|
|
next; |
791
|
|
|
|
|
|
|
} |
792
|
|
|
|
|
|
|
my $data; |
793
|
|
|
|
|
|
|
if ($location =~ m@^...*://@i) { |
794
|
|
|
|
|
|
|
next unless ($data = read_href("request" => 'GET', |
795
|
|
|
|
|
|
|
"href" => "$location/$summaryfile")); |
796
|
|
|
|
|
|
|
} else { |
797
|
|
|
|
|
|
|
local $/; |
798
|
|
|
|
|
|
|
next if (!open (DATAFILE, "$location/$summaryfile")); |
799
|
|
|
|
|
|
|
$data = ; |
800
|
|
|
|
|
|
|
close(DATAFILE); |
801
|
|
|
|
|
|
|
} |
802
|
|
|
|
|
|
|
$summary{$location} = parse_summary($data); |
803
|
|
|
|
|
|
|
} |
804
|
|
|
|
|
|
|
|
805
|
|
|
|
|
|
|
return %summary; |
806
|
|
|
|
|
|
|
} |
807
|
|
|
|
|
|
|
|
808
|
|
|
|
|
|
|
# Returns the same structure as RepositorySummary() above. |
809
|
|
|
|
|
|
|
sub ServerSearch |
810
|
|
|
|
|
|
|
{ |
811
|
|
|
|
|
|
|
my %argv = @_; |
812
|
|
|
|
|
|
|
my $location = $argv{'location'}; |
813
|
|
|
|
|
|
|
my $searchRE = $argv{'searchRE'}; |
814
|
|
|
|
|
|
|
my $searchtag = $argv{'searchtag'}; |
815
|
|
|
|
|
|
|
my $data; |
816
|
|
|
|
|
|
|
my %summary; |
817
|
|
|
|
|
|
|
|
818
|
|
|
|
|
|
|
return unless $location =~ m#^(http://.*)\?(urn:.*)#i; |
819
|
|
|
|
|
|
|
my ($proxy, $uri) = ($1, $2); |
820
|
|
|
|
|
|
|
my $client = SOAP::Lite -> uri($uri) -> proxy($proxy); |
821
|
|
|
|
|
|
|
eval { $data = $client -> |
822
|
|
|
|
|
|
|
search_ppds($varchname, $searchRE, $searchtag) -> result; }; |
823
|
|
|
|
|
|
|
if ($@) { |
824
|
|
|
|
|
|
|
&Trace("Error searching repository '$proxy': $@") |
825
|
|
|
|
|
|
|
if $options{'TRACE'}; |
826
|
|
|
|
|
|
|
$PPM::PPMERR = "Error searching repository '$proxy': $@\n"; |
827
|
|
|
|
|
|
|
return; |
828
|
|
|
|
|
|
|
} |
829
|
|
|
|
|
|
|
|
830
|
|
|
|
|
|
|
$summary{$location} = parse_summary($data); |
831
|
|
|
|
|
|
|
return %summary; |
832
|
|
|
|
|
|
|
} |
833
|
|
|
|
|
|
|
|
834
|
|
|
|
|
|
|
# |
835
|
|
|
|
|
|
|
# Internal subs |
836
|
|
|
|
|
|
|
# |
837
|
|
|
|
|
|
|
|
838
|
|
|
|
|
|
|
sub parse_summary |
839
|
|
|
|
|
|
|
{ |
840
|
|
|
|
|
|
|
my $data = shift; |
841
|
|
|
|
|
|
|
my (%summary, @parsed); |
842
|
|
|
|
|
|
|
|
843
|
|
|
|
|
|
|
# take care of '&' |
844
|
|
|
|
|
|
|
$data =~ s/&(?!\w+;)/&/go; |
845
|
|
|
|
|
|
|
|
846
|
|
|
|
|
|
|
my $parser = new XML::Parser( Style => 'Objects', |
847
|
|
|
|
|
|
|
Pkg => 'PPM::XML::RepositorySummary' ); |
848
|
|
|
|
|
|
|
eval { @parsed = @{ $parser->parse( $data ) } }; |
849
|
|
|
|
|
|
|
if ($@) { |
850
|
|
|
|
|
|
|
&Trace("parse_summary: content of summary file is not valid") |
851
|
|
|
|
|
|
|
if $options{'TRACE'}; |
852
|
|
|
|
|
|
|
$PPM::PPMERR = |
853
|
|
|
|
|
|
|
"parse_summary: content of summary file is not valid: $!\n"; |
854
|
|
|
|
|
|
|
return; |
855
|
|
|
|
|
|
|
} |
856
|
|
|
|
|
|
|
|
857
|
|
|
|
|
|
|
|
858
|
|
|
|
|
|
|
my $packages = ${$parsed[0]}{Kids}; |
859
|
|
|
|
|
|
|
|
860
|
|
|
|
|
|
|
foreach my $package (@{$packages}) { |
861
|
|
|
|
|
|
|
my $elem_type = ref $package; |
862
|
|
|
|
|
|
|
$elem_type =~ s/.*:://; |
863
|
|
|
|
|
|
|
next if ($elem_type eq 'Characters'); |
864
|
|
|
|
|
|
|
|
865
|
|
|
|
|
|
|
if ($elem_type eq 'SOFTPKG') { |
866
|
|
|
|
|
|
|
my %ret_hash; |
867
|
|
|
|
|
|
|
parsePPD(%{$package}); |
868
|
|
|
|
|
|
|
%ret_hash = map { $_ => $current_package{$_} } |
869
|
|
|
|
|
|
|
qw(NAME TITLE AUTHOR VERSION ABSTRACT PERLCORE_VER); |
870
|
|
|
|
|
|
|
foreach my $dep (keys %{$current_package{'DEPEND'}}) { |
871
|
|
|
|
|
|
|
push @{$ret_hash{'DEPEND'}}, $dep; |
872
|
|
|
|
|
|
|
} |
873
|
|
|
|
|
|
|
$summary{$current_package{'NAME'}} = \%ret_hash; |
874
|
|
|
|
|
|
|
} |
875
|
|
|
|
|
|
|
} |
876
|
|
|
|
|
|
|
return \%summary; |
877
|
|
|
|
|
|
|
} |
878
|
|
|
|
|
|
|
|
879
|
|
|
|
|
|
|
sub save_options |
880
|
|
|
|
|
|
|
{ |
881
|
|
|
|
|
|
|
read_config(); |
882
|
|
|
|
|
|
|
my %PPMConfig; |
883
|
|
|
|
|
|
|
# Read in the existing PPM configuration file |
884
|
|
|
|
|
|
|
return unless (%PPMConfig = getPPDfile('package' => $PPM::PPMdat, |
885
|
|
|
|
|
|
|
'parsertype' => 'PPM::XML::PPMConfig')); |
886
|
|
|
|
|
|
|
|
887
|
|
|
|
|
|
|
# Remove all of the declarations for REPOSITORY and PPMPRECIOUS; |
888
|
|
|
|
|
|
|
# we'll output these from the lists we've got in memory instead. |
889
|
|
|
|
|
|
|
foreach my $idx (0 .. @{$PPMConfig{Kids}}) { |
890
|
|
|
|
|
|
|
my $elem = $PPMConfig{Kids}[$idx]; |
891
|
|
|
|
|
|
|
my $elem_type = ref $elem; |
892
|
|
|
|
|
|
|
if ($elem_type =~ /::REPOSITORY$|::PPMPRECIOUS$/o) { |
893
|
|
|
|
|
|
|
splice( @{$PPMConfig{Kids}}, $idx, 1 ); |
894
|
|
|
|
|
|
|
redo; # Restart again so we don't miss any |
895
|
|
|
|
|
|
|
} |
896
|
|
|
|
|
|
|
} |
897
|
|
|
|
|
|
|
|
898
|
|
|
|
|
|
|
# Traverse the info we read in and replace the values in it with the new |
899
|
|
|
|
|
|
|
# config options that we've got. |
900
|
|
|
|
|
|
|
foreach my $elem (@{ $PPMConfig{Kids} }) { |
901
|
|
|
|
|
|
|
my $elem_type = ref $elem; |
902
|
|
|
|
|
|
|
$elem_type =~ s/.*:://; |
903
|
|
|
|
|
|
|
next if ($elem_type ne 'OPTIONS'); |
904
|
|
|
|
|
|
|
%{$elem} = map { $_ => $options{$_} } keys %options; |
905
|
|
|
|
|
|
|
# This bit of ugliness is necessary for historical (VPM) reasons |
906
|
|
|
|
|
|
|
delete $elem->{FORCE_INSTALL}; |
907
|
|
|
|
|
|
|
$elem->{FORCEINSTALL} = $options{'FORCE_INSTALL'}; |
908
|
|
|
|
|
|
|
} |
909
|
|
|
|
|
|
|
|
910
|
|
|
|
|
|
|
# Find out where the package listings start and insert our PPMPRECIOUS and |
911
|
|
|
|
|
|
|
# updated list of REPOSITORYs. |
912
|
|
|
|
|
|
|
foreach my $idx (0 .. @{$PPMConfig{Kids}}) { |
913
|
|
|
|
|
|
|
my $elem = $PPMConfig{Kids}[$idx]; |
914
|
|
|
|
|
|
|
my $elem_type = ref $elem; |
915
|
|
|
|
|
|
|
$elem_type =~ s/.*:://; |
916
|
|
|
|
|
|
|
next unless (($elem_type eq 'PACKAGE') or |
917
|
|
|
|
|
|
|
($idx == $#{$PPMConfig{Kids}})); |
918
|
|
|
|
|
|
|
|
919
|
|
|
|
|
|
|
# Insert our PPMPRECIOUS |
920
|
|
|
|
|
|
|
my $chardata = new PPM::XML::PPMConfig::Characters; |
921
|
|
|
|
|
|
|
$chardata->{Text} = join( ';', @required_packages ); |
922
|
|
|
|
|
|
|
my $precious = new PPM::XML::PPMConfig::PPMPRECIOUS; |
923
|
|
|
|
|
|
|
push( @{$precious->{Kids}}, $chardata ); |
924
|
|
|
|
|
|
|
splice( @{$PPMConfig{Kids}}, $idx, 0, $precious ); |
925
|
|
|
|
|
|
|
|
926
|
|
|
|
|
|
|
# Insert the list of repositories we've got |
927
|
|
|
|
|
|
|
my $rep_name; |
928
|
|
|
|
|
|
|
foreach $rep_name (keys %repositories) { |
929
|
|
|
|
|
|
|
my $repository = new PPM::XML::PPMConfig::REPOSITORY; |
930
|
|
|
|
|
|
|
%{$repository} = |
931
|
|
|
|
|
|
|
map { $_ => $repositories{$rep_name}{$_} } |
932
|
|
|
|
|
|
|
keys %{$repositories{$rep_name}}; |
933
|
|
|
|
|
|
|
$repository->{'NAME'} = $rep_name; |
934
|
|
|
|
|
|
|
splice( @{$PPMConfig{Kids}}, $idx, 0, $repository ); |
935
|
|
|
|
|
|
|
} |
936
|
|
|
|
|
|
|
last; |
937
|
|
|
|
|
|
|
} |
938
|
|
|
|
|
|
|
# Take the data structure we've got and bless it into a PPMCONFIG object so |
939
|
|
|
|
|
|
|
# that we can output it. |
940
|
|
|
|
|
|
|
my $cfg = bless \%PPMConfig, 'PPM::XML::PPMConfig::PPMCONFIG'; |
941
|
|
|
|
|
|
|
|
942
|
|
|
|
|
|
|
# Open the output file and output the PPM config file |
943
|
|
|
|
|
|
|
unless (open( DAT, ">$PPM::PPMdat" )) { |
944
|
|
|
|
|
|
|
&Trace("open of $PPM::PPMdat failed: $!") if $options{'TRACE'}; |
945
|
|
|
|
|
|
|
$PPM::PPMERR = "open of $PPM::PPMdat failed: $!\n"; |
946
|
|
|
|
|
|
|
return 1; |
947
|
|
|
|
|
|
|
} |
948
|
|
|
|
|
|
|
my $oldout = select DAT; |
949
|
|
|
|
|
|
|
$cfg->output(); |
950
|
|
|
|
|
|
|
select $oldout; |
951
|
|
|
|
|
|
|
close( DAT ); |
952
|
|
|
|
|
|
|
&Trace("Wrote config file") if $options{'TRACE'} > 1; |
953
|
|
|
|
|
|
|
} |
954
|
|
|
|
|
|
|
|
955
|
|
|
|
|
|
|
# Gets a listing of all of the packages available in the repository. If an |
956
|
|
|
|
|
|
|
# argument of 'location' is provided in %argv, it is used as the repository to |
957
|
|
|
|
|
|
|
# query. This method returns to the caller a complete list of all of the |
958
|
|
|
|
|
|
|
# available packages at the repository in a list context, returning 'undef' if |
959
|
|
|
|
|
|
|
# any errors occurred. |
960
|
|
|
|
|
|
|
sub list_available |
961
|
|
|
|
|
|
|
{ |
962
|
|
|
|
|
|
|
my %argv = @_; |
963
|
|
|
|
|
|
|
my $location = $argv{'location'}; |
964
|
|
|
|
|
|
|
my @ppds; |
965
|
|
|
|
|
|
|
|
966
|
|
|
|
|
|
|
if ($location =~ /^file:\/\/.*\|/i) { |
967
|
|
|
|
|
|
|
# $location is a local directory, let's avoid LWP by changing |
968
|
|
|
|
|
|
|
# it to a pathname. |
969
|
|
|
|
|
|
|
$location =~ s@^file://@@i; |
970
|
|
|
|
|
|
|
$location =~ s@^localhost/@@i; |
971
|
|
|
|
|
|
|
$location =~ s@\|@:@; |
972
|
|
|
|
|
|
|
} |
973
|
|
|
|
|
|
|
|
974
|
|
|
|
|
|
|
# URL in UNC notation |
975
|
|
|
|
|
|
|
if ($location =~ /^file:\/\/\/\//i) { |
976
|
|
|
|
|
|
|
$location =~ s@^file://@@i; |
977
|
|
|
|
|
|
|
} |
978
|
|
|
|
|
|
|
|
979
|
|
|
|
|
|
|
# directory or UNC |
980
|
|
|
|
|
|
|
if (-d $location || $location =~ /^\\\\/ || $location =~ /^\/\//) { |
981
|
|
|
|
|
|
|
opendir(PPDDIR, $location) or return undef; |
982
|
|
|
|
|
|
|
my ($file); |
983
|
|
|
|
|
|
|
@ppds = grep { /\.ppd$/i && -f "$location/$_" } readdir(PPDDIR); |
984
|
|
|
|
|
|
|
foreach $file (@ppds) { |
985
|
|
|
|
|
|
|
$file =~ s/\.ppd//i; |
986
|
|
|
|
|
|
|
} |
987
|
|
|
|
|
|
|
} |
988
|
|
|
|
|
|
|
elsif ($location =~ m@^...*://@i) { |
989
|
|
|
|
|
|
|
if ($cached_ppd_list{$location}) { |
990
|
|
|
|
|
|
|
return @{$cached_ppd_list{$location}}; |
991
|
|
|
|
|
|
|
} |
992
|
|
|
|
|
|
|
|
993
|
|
|
|
|
|
|
# If we're accessing a SOAP server, do things differently than we would |
994
|
|
|
|
|
|
|
# for FTP, HTTP, etc. |
995
|
|
|
|
|
|
|
if ($location =~ m#^(http://.*)\?(.*)#i) { |
996
|
|
|
|
|
|
|
my ($proxy, $uri) = ($1, $2); |
997
|
|
|
|
|
|
|
my $client = SOAP::Lite -> uri($uri) -> proxy($proxy); |
998
|
|
|
|
|
|
|
eval { @ppds = $client->packages()->paramsout }; |
999
|
|
|
|
|
|
|
if ($@) { |
1000
|
|
|
|
|
|
|
&Trace("Package list from '$proxy' failed: $@") |
1001
|
|
|
|
|
|
|
if $options{'TRACE'}; |
1002
|
|
|
|
|
|
|
$PPM::PPMERR = |
1003
|
|
|
|
|
|
|
"Package list from repository '$proxy' failed: $@\n"; |
1004
|
|
|
|
|
|
|
return; |
1005
|
|
|
|
|
|
|
} |
1006
|
|
|
|
|
|
|
} |
1007
|
|
|
|
|
|
|
else { |
1008
|
|
|
|
|
|
|
return unless (my $doc = read_href("href" => $location, |
1009
|
|
|
|
|
|
|
"request" => 'GET')); |
1010
|
|
|
|
|
|
|
|
1011
|
|
|
|
|
|
|
if ($doc =~ /^/) { |
1012
|
|
|
|
|
|
|
# read an IIS format directory listing |
1013
|
|
|
|
|
|
|
@ppds = grep { /\.ppd/i } split(' ', $doc); |
1014
|
|
|
|
|
|
|
foreach my $file (@ppds) { |
1015
|
|
|
|
|
|
|
$file =~ s/\.ppd<.*$//is; |
1016
|
|
|
|
|
|
|
$file =~ s@.*>@@is; |
1017
|
|
|
|
|
|
|
} |
1018
|
|
|
|
|
|
|
} |
1019
|
|
|
|
|
|
|
elsif ($doc =~ /\n\n |
1020
|
|
|
|
|
|
|
# read output of default.prk over an HTTP connection |
1021
|
|
|
|
|
|
|
@ppds = grep { /^$/ } split('\n', $doc); |
1022
|
|
|
|
|
|
|
foreach my $file (@ppds) { |
1023
|
|
|
|
|
|
|
if ($file =~ /^$/) { |
1024
|
|
|
|
|
|
|
$file = $1; |
1025
|
|
|
|
|
|
|
} |
1026
|
|
|
|
|
|
|
} |
1027
|
|
|
|
|
|
|
} |
1028
|
|
|
|
|
|
|
else { |
1029
|
|
|
|
|
|
|
# read an Apache format directory listing |
1030
|
|
|
|
|
|
|
@ppds = grep { /\.ppd/i } split('\n', $doc); |
1031
|
|
|
|
|
|
|
foreach my $file (@ppds) { |
1032
|
|
|
|
|
|
|
$file =~ s/^.*>(.*?)\.ppd<.*$/$1/i; |
1033
|
|
|
|
|
|
|
} |
1034
|
|
|
|
|
|
|
} |
1035
|
|
|
|
|
|
|
} |
1036
|
|
|
|
|
|
|
|
1037
|
|
|
|
|
|
|
# All done, take the list of PPDs that we've queried and cache it for |
1038
|
|
|
|
|
|
|
# later re-use, then return it to the caller. |
1039
|
|
|
|
|
|
|
@{$cached_ppd_list{$location}} = sort @ppds; |
1040
|
|
|
|
|
|
|
return @{$cached_ppd_list{$location}}; |
1041
|
|
|
|
|
|
|
} |
1042
|
|
|
|
|
|
|
return sort @ppds; |
1043
|
|
|
|
|
|
|
} |
1044
|
|
|
|
|
|
|
|
1045
|
|
|
|
|
|
|
my ($response, $bytes_transferred); |
1046
|
|
|
|
|
|
|
|
1047
|
|
|
|
|
|
|
sub read_href |
1048
|
|
|
|
|
|
|
{ |
1049
|
|
|
|
|
|
|
my %argv = @_; |
1050
|
|
|
|
|
|
|
my $href = $argv{'href'}; |
1051
|
|
|
|
|
|
|
my $request = $argv{'request'}; |
1052
|
|
|
|
|
|
|
my $target = $argv{'target'}; |
1053
|
|
|
|
|
|
|
my $progress = $argv{'progress'}; # display status of binary transfers |
1054
|
|
|
|
|
|
|
my ($proxy_user, $proxy_pass); |
1055
|
|
|
|
|
|
|
# If this is a SOAP URL, handle it differently than FTP/HTTP/file. |
1056
|
|
|
|
|
|
|
if ($href =~ m#^(http://.*)\?(.*)#i) { |
1057
|
|
|
|
|
|
|
my ($proxy, $uri) = ($1, $2); |
1058
|
|
|
|
|
|
|
my $fcn; |
1059
|
|
|
|
|
|
|
if ($uri =~ m#(.*:/.*)/(.+?)$#) { |
1060
|
|
|
|
|
|
|
($uri, $fcn) = ($1, $2); |
1061
|
|
|
|
|
|
|
} |
1062
|
|
|
|
|
|
|
my $client = SOAP::Lite -> uri($uri) -> proxy($proxy); |
1063
|
|
|
|
|
|
|
if ($fcn eq 'fetch_summary') { |
1064
|
|
|
|
|
|
|
my $summary = eval { $client->fetch_summary()->result; }; |
1065
|
|
|
|
|
|
|
if ($@) { |
1066
|
|
|
|
|
|
|
&Trace("Error getting summary from repository '$proxy': $@") |
1067
|
|
|
|
|
|
|
if $options{'TRACE'}; |
1068
|
|
|
|
|
|
|
$PPM::PPMERR = |
1069
|
|
|
|
|
|
|
"Error getting summary from repository '$proxy': $@\n"; |
1070
|
|
|
|
|
|
|
return; |
1071
|
|
|
|
|
|
|
} |
1072
|
|
|
|
|
|
|
return $summary; |
1073
|
|
|
|
|
|
|
} |
1074
|
|
|
|
|
|
|
$fcn =~ s/\.ppd$//i; |
1075
|
|
|
|
|
|
|
my $ppd = eval { $client->fetch_ppd($fcn)->result }; |
1076
|
|
|
|
|
|
|
if ($@) { |
1077
|
|
|
|
|
|
|
&Trace("Error fetching '$fcn' from repository '$proxy': $@") |
1078
|
|
|
|
|
|
|
if $options{'TRACE'}; |
1079
|
|
|
|
|
|
|
$PPM::PPMERR = |
1080
|
|
|
|
|
|
|
"Error fetching '$fcn' from repository '$proxy': $@\n"; |
1081
|
|
|
|
|
|
|
return; |
1082
|
|
|
|
|
|
|
} |
1083
|
|
|
|
|
|
|
return $ppd; |
1084
|
|
|
|
|
|
|
# todo: write to disk file if $target |
1085
|
|
|
|
|
|
|
} |
1086
|
|
|
|
|
|
|
# Otherwise it's a standard URL, go ahead and request it using LWP. |
1087
|
|
|
|
|
|
|
my $ua = new LWP::UserAgent; |
1088
|
|
|
|
|
|
|
$ua->agent($ENV{HTTP_proxy_agent} || ("$0/0.1 " . $ua->agent)); |
1089
|
|
|
|
|
|
|
if (defined $ENV{HTTP_proxy}) { |
1090
|
|
|
|
|
|
|
$proxy_user = $ENV{HTTP_proxy_user}; |
1091
|
|
|
|
|
|
|
$proxy_pass = $ENV{HTTP_proxy_pass}; |
1092
|
|
|
|
|
|
|
&Trace("read_href: calling env_proxy: $ENV{'HTTP_proxy'}") |
1093
|
|
|
|
|
|
|
if $options{'TRACE'} > 1; |
1094
|
|
|
|
|
|
|
$ua->env_proxy; |
1095
|
|
|
|
|
|
|
} |
1096
|
|
|
|
|
|
|
my $req = new HTTP::Request $request => $href; |
1097
|
|
|
|
|
|
|
if (defined $proxy_user && defined $proxy_pass) { |
1098
|
|
|
|
|
|
|
&Trace("read_href: calling proxy_authorization_basic($proxy_user, $proxy_pass)") if $options{'TRACE'} > 1; |
1099
|
|
|
|
|
|
|
$req->proxy_authorization_basic("$proxy_user", "$proxy_pass"); |
1100
|
|
|
|
|
|
|
} |
1101
|
|
|
|
|
|
|
|
1102
|
|
|
|
|
|
|
# Do we need to do authorization? |
1103
|
|
|
|
|
|
|
# This is a hack, but will have to do for now. |
1104
|
|
|
|
|
|
|
foreach (keys %repositories) { |
1105
|
|
|
|
|
|
|
if ($href =~ /^$repositories{$_}{'LOCATION'}/i) { |
1106
|
|
|
|
|
|
|
my $username = $repositories{$_}{'USERNAME'}; |
1107
|
|
|
|
|
|
|
my $password = $repositories{$_}{'PASSWORD'}; |
1108
|
|
|
|
|
|
|
if (defined $username && defined $password) { |
1109
|
|
|
|
|
|
|
&Trace("read_href: calling proxy_authorization_basic($username, $password)") if $options{'TRACE'} > 1; |
1110
|
|
|
|
|
|
|
$req->authorization_basic($username, $password); |
1111
|
|
|
|
|
|
|
last; |
1112
|
|
|
|
|
|
|
} |
1113
|
|
|
|
|
|
|
} |
1114
|
|
|
|
|
|
|
} |
1115
|
|
|
|
|
|
|
|
1116
|
|
|
|
|
|
|
($response, $bytes_transferred) = (undef, 0); |
1117
|
|
|
|
|
|
|
if ($progress) { |
1118
|
|
|
|
|
|
|
# display the 'progress indicator' |
1119
|
|
|
|
|
|
|
$ua->request($req, \&lwp_callback, |
1120
|
|
|
|
|
|
|
($options{'DOWNLOADSTATUS'} || 4096)); |
1121
|
|
|
|
|
|
|
print "\n" if ($PPM::PPMShell && $options{'DOWNLOADSTATUS'}); |
1122
|
|
|
|
|
|
|
} |
1123
|
|
|
|
|
|
|
else { |
1124
|
|
|
|
|
|
|
$response = $ua->request($req); |
1125
|
|
|
|
|
|
|
} |
1126
|
|
|
|
|
|
|
if ($response && $response->is_success) { |
1127
|
|
|
|
|
|
|
if ($target) { |
1128
|
|
|
|
|
|
|
unless (open(OUT, ">$target")) { |
1129
|
|
|
|
|
|
|
&Trace("read_href: Couldn't open $target for writing") |
1130
|
|
|
|
|
|
|
if $options{'TRACE'}; |
1131
|
|
|
|
|
|
|
$PPM::PPMERR = "Couldn't open $target for writing\n"; |
1132
|
|
|
|
|
|
|
return; |
1133
|
|
|
|
|
|
|
} |
1134
|
|
|
|
|
|
|
binmode(OUT); |
1135
|
|
|
|
|
|
|
print OUT $response->content; |
1136
|
|
|
|
|
|
|
close(OUT); |
1137
|
|
|
|
|
|
|
} |
1138
|
|
|
|
|
|
|
return $response->content; |
1139
|
|
|
|
|
|
|
} |
1140
|
|
|
|
|
|
|
if ($response) { |
1141
|
|
|
|
|
|
|
&Trace("read_href: Error reading $href: " . $response->code . " " . |
1142
|
|
|
|
|
|
|
$response->message) if $options{'TRACE'}; |
1143
|
|
|
|
|
|
|
$PPM::PPMERR = "Error reading $href: " . $response->code . " " . |
1144
|
|
|
|
|
|
|
$response->message . "\n"; |
1145
|
|
|
|
|
|
|
} |
1146
|
|
|
|
|
|
|
else { |
1147
|
|
|
|
|
|
|
&Trace("read_href: Error reading $href") if $options{'TRACE'}; |
1148
|
|
|
|
|
|
|
$PPM::PPMERR = "Error reading $href\n"; |
1149
|
|
|
|
|
|
|
} |
1150
|
|
|
|
|
|
|
return; |
1151
|
|
|
|
|
|
|
} |
1152
|
|
|
|
|
|
|
|
1153
|
|
|
|
|
|
|
sub lwp_callback |
1154
|
|
|
|
|
|
|
{ |
1155
|
|
|
|
|
|
|
my ($data, $res, $protocol) = @_; |
1156
|
|
|
|
|
|
|
$response = $res; |
1157
|
|
|
|
|
|
|
$response->add_content($data); |
1158
|
|
|
|
|
|
|
$bytes_transferred += length($data); |
1159
|
|
|
|
|
|
|
print "Bytes transferred: $bytes_transferred\r" |
1160
|
|
|
|
|
|
|
if ($PPM::PPMShell && $options{'DOWNLOADSTATUS'}); |
1161
|
|
|
|
|
|
|
} |
1162
|
|
|
|
|
|
|
|
1163
|
|
|
|
|
|
|
sub reread_config |
1164
|
|
|
|
|
|
|
{ |
1165
|
|
|
|
|
|
|
%current_package = (); |
1166
|
|
|
|
|
|
|
%installed_packages = (); |
1167
|
|
|
|
|
|
|
$init = 0; |
1168
|
|
|
|
|
|
|
read_config(); |
1169
|
|
|
|
|
|
|
} |
1170
|
|
|
|
|
|
|
|
1171
|
|
|
|
|
|
|
# returns 0 on success, 1 and sets $PPMERR on error. |
1172
|
|
|
|
|
|
|
sub PPMdat_add_package |
1173
|
|
|
|
|
|
|
{ |
1174
|
|
|
|
|
|
|
my ($location, $packlist, $inst_root) = @_; |
1175
|
|
|
|
|
|
|
my $package = $current_package{'NAME'}; |
1176
|
|
|
|
|
|
|
my $time_str = localtime; |
1177
|
|
|
|
|
|
|
|
1178
|
|
|
|
|
|
|
# If we already have this package installed, remove it from the PPM |
1179
|
|
|
|
|
|
|
# Configuration file so we can put the new one in. |
1180
|
|
|
|
|
|
|
if (defined $installed_packages{$package} ) { |
1181
|
|
|
|
|
|
|
# remove the existing entry for this package. |
1182
|
|
|
|
|
|
|
PPMdat_remove_package($package); |
1183
|
|
|
|
|
|
|
} |
1184
|
|
|
|
|
|
|
|
1185
|
|
|
|
|
|
|
# Build the new SOFTPKG data structure for this package we're adding. |
1186
|
|
|
|
|
|
|
my $softpkg = |
1187
|
|
|
|
|
|
|
new PPM::XML::PPMConfig::SOFTPKG( NAME => $package, |
1188
|
|
|
|
|
|
|
VERSION => $current_package{VERSION} |
1189
|
|
|
|
|
|
|
); |
1190
|
|
|
|
|
|
|
|
1191
|
|
|
|
|
|
|
if (defined $current_package{TITLE}) { |
1192
|
|
|
|
|
|
|
my $chardata = new PPM::XML::PPMConfig::Characters( |
1193
|
|
|
|
|
|
|
Text => $current_package{TITLE} ); |
1194
|
|
|
|
|
|
|
my $newelem = new PPM::XML::PPMConfig::TITLE; |
1195
|
|
|
|
|
|
|
push( @{$newelem->{Kids}}, $chardata ); |
1196
|
|
|
|
|
|
|
push( @{$softpkg->{Kids}}, $newelem ); |
1197
|
|
|
|
|
|
|
} |
1198
|
|
|
|
|
|
|
|
1199
|
|
|
|
|
|
|
if (defined $current_package{ABSTRACT}) { |
1200
|
|
|
|
|
|
|
my $chardata = new PPM::XML::PPMConfig::Characters( |
1201
|
|
|
|
|
|
|
Text => $current_package{ABSTRACT}); |
1202
|
|
|
|
|
|
|
my $newelem = new PPM::XML::PPMConfig::ABSTRACT; |
1203
|
|
|
|
|
|
|
push( @{$newelem->{Kids}}, $chardata ); |
1204
|
|
|
|
|
|
|
push( @{$softpkg->{Kids}}, $newelem ); |
1205
|
|
|
|
|
|
|
} |
1206
|
|
|
|
|
|
|
|
1207
|
|
|
|
|
|
|
if (defined $current_package{AUTHOR}) { |
1208
|
|
|
|
|
|
|
my $chardata = new PPM::XML::PPMConfig::Characters( |
1209
|
|
|
|
|
|
|
Text => $current_package{AUTHOR} ); |
1210
|
|
|
|
|
|
|
my $newelem = new PPM::XML::PPMConfig::AUTHOR; |
1211
|
|
|
|
|
|
|
push( @{$newelem->{Kids}}, $chardata ); |
1212
|
|
|
|
|
|
|
push( @{$softpkg->{Kids}}, $newelem ); |
1213
|
|
|
|
|
|
|
} |
1214
|
|
|
|
|
|
|
|
1215
|
|
|
|
|
|
|
if (defined $current_package{LICENSE}) { |
1216
|
|
|
|
|
|
|
my $chardata = new PPM::XML::PPMConfig::Characters( |
1217
|
|
|
|
|
|
|
Text => $current_package{LICENSE}); |
1218
|
|
|
|
|
|
|
my $newelem = new PPM::XML::PPMConfig::LICENSE; |
1219
|
|
|
|
|
|
|
push( @{$newelem->{Kids}}, $chardata ); |
1220
|
|
|
|
|
|
|
push( @{$softpkg->{Kids}}, $newelem ); |
1221
|
|
|
|
|
|
|
} |
1222
|
|
|
|
|
|
|
|
1223
|
|
|
|
|
|
|
my $impl = new PPM::XML::PPMConfig::IMPLEMENTATION; |
1224
|
|
|
|
|
|
|
push( @{$softpkg->{Kids}}, $impl ); |
1225
|
|
|
|
|
|
|
|
1226
|
|
|
|
|
|
|
if (defined $current_package{PERLCORE_VER}) { |
1227
|
|
|
|
|
|
|
my $newelem = new PPM::XML::PPMConfig::PERLCORE( |
1228
|
|
|
|
|
|
|
VERSION => $current_package{PERLCORE_VER} ); |
1229
|
|
|
|
|
|
|
push( @{$impl->{Kids}}, $newelem ); |
1230
|
|
|
|
|
|
|
} |
1231
|
|
|
|
|
|
|
|
1232
|
|
|
|
|
|
|
foreach (keys %{$current_package{DEPEND}}) { |
1233
|
|
|
|
|
|
|
my $newelem = new PPM::XML::PPMConfig::DEPENDENCY( |
1234
|
|
|
|
|
|
|
NAME => $_, VERSION => $current_package{DEPEND}{$_} ); |
1235
|
|
|
|
|
|
|
push( @{$impl->{Kids}}, $newelem ); |
1236
|
|
|
|
|
|
|
} |
1237
|
|
|
|
|
|
|
|
1238
|
|
|
|
|
|
|
my $codebase = new PPM::XML::PPMConfig::CODEBASE( |
1239
|
|
|
|
|
|
|
HREF => $current_package{CODEBASE} ); |
1240
|
|
|
|
|
|
|
push( @{$impl->{Kids}}, $codebase ); |
1241
|
|
|
|
|
|
|
|
1242
|
|
|
|
|
|
|
my $inst = new PPM::XML::PPMConfig::INSTALL; |
1243
|
|
|
|
|
|
|
push( @{$impl->{Kids}}, $inst ); |
1244
|
|
|
|
|
|
|
if (defined $current_package{INSTALL_EXEC}) |
1245
|
|
|
|
|
|
|
{ $inst->{EXEC} = $current_package{INSTALL_EXEC}; } |
1246
|
|
|
|
|
|
|
if (defined $current_package{INSTALL_HREF}) |
1247
|
|
|
|
|
|
|
{ $inst->{HREF} = $current_package{INSTALL_HREF}; } |
1248
|
|
|
|
|
|
|
if (defined $current_package{INSTALL_SCRIPT}) { |
1249
|
|
|
|
|
|
|
my $chardata = new PPM::XML::PPMConfig::Characters( |
1250
|
|
|
|
|
|
|
Text => $current_package{INSTALL_SCRIPT} ); |
1251
|
|
|
|
|
|
|
push( @{$inst->{Kids}}, $chardata ); |
1252
|
|
|
|
|
|
|
} |
1253
|
|
|
|
|
|
|
|
1254
|
|
|
|
|
|
|
my $uninst = new PPM::XML::PPMConfig::UNINSTALL; |
1255
|
|
|
|
|
|
|
push( @{$impl->{Kids}}, $uninst ); |
1256
|
|
|
|
|
|
|
if (defined $current_package{UNINSTALL_EXEC}) |
1257
|
|
|
|
|
|
|
{ $uninst->{EXEC} = $current_package{UNINSTALL_EXEC}; } |
1258
|
|
|
|
|
|
|
if (defined $current_package{UNINSTALL_HREF}) |
1259
|
|
|
|
|
|
|
{ $uninst->{HREF} = $current_package{UNINSTALL_HREF}; } |
1260
|
|
|
|
|
|
|
if (defined $current_package{UNINSTALL_SCRIPT}) { |
1261
|
|
|
|
|
|
|
my $chardata = new PPM::XML::PPMConfig::Characters( |
1262
|
|
|
|
|
|
|
Text => $current_package{UNINSTALL_SCRIPT} ); |
1263
|
|
|
|
|
|
|
push( @{$uninst->{Kids}}, $chardata ); |
1264
|
|
|
|
|
|
|
} |
1265
|
|
|
|
|
|
|
|
1266
|
|
|
|
|
|
|
# Then, build the PACKAGE object and stick the SOFTPKG inside of it. |
1267
|
|
|
|
|
|
|
my $pkg = new PPM::XML::PPMConfig::PACKAGE( NAME => $package ); |
1268
|
|
|
|
|
|
|
|
1269
|
|
|
|
|
|
|
if ($location) { |
1270
|
|
|
|
|
|
|
my $chardata = new PPM::XML::PPMConfig::Characters( Text => $location ); |
1271
|
|
|
|
|
|
|
my $newelem = new PPM::XML::PPMConfig::LOCATION; |
1272
|
|
|
|
|
|
|
push( @{$newelem->{Kids}}, $chardata ); |
1273
|
|
|
|
|
|
|
push( @{$pkg->{Kids}}, $newelem ); |
1274
|
|
|
|
|
|
|
} |
1275
|
|
|
|
|
|
|
|
1276
|
|
|
|
|
|
|
if ($packlist) { |
1277
|
|
|
|
|
|
|
my $chardata = new PPM::XML::PPMConfig::Characters( Text => $packlist ); |
1278
|
|
|
|
|
|
|
my $newelem = new PPM::XML::PPMConfig::INSTPACKLIST; |
1279
|
|
|
|
|
|
|
push( @{$newelem->{Kids}}, $chardata ); |
1280
|
|
|
|
|
|
|
push( @{$pkg->{Kids}}, $newelem ); |
1281
|
|
|
|
|
|
|
} |
1282
|
|
|
|
|
|
|
|
1283
|
|
|
|
|
|
|
if ($inst_root) { |
1284
|
|
|
|
|
|
|
my $chardata = new PPM::XML::PPMConfig::Characters( Text => $inst_root ); |
1285
|
|
|
|
|
|
|
my $newelem = new PPM::XML::PPMConfig::INSTROOT; |
1286
|
|
|
|
|
|
|
push( @{$newelem->{Kids}}, $chardata ); |
1287
|
|
|
|
|
|
|
push( @{$pkg->{Kids}}, $newelem ); |
1288
|
|
|
|
|
|
|
} |
1289
|
|
|
|
|
|
|
|
1290
|
|
|
|
|
|
|
if ($time_str) { |
1291
|
|
|
|
|
|
|
my $chardata = new PPM::XML::PPMConfig::Characters( Text => $time_str); |
1292
|
|
|
|
|
|
|
my $newelem = new PPM::XML::PPMConfig::INSTDATE; |
1293
|
|
|
|
|
|
|
push( @{$newelem->{Kids}}, $chardata ); |
1294
|
|
|
|
|
|
|
push( @{$pkg->{Kids}}, $newelem ); |
1295
|
|
|
|
|
|
|
} |
1296
|
|
|
|
|
|
|
|
1297
|
|
|
|
|
|
|
my $instppd = new PPM::XML::PPMConfig::INSTPPD; |
1298
|
|
|
|
|
|
|
push( @{$instppd->{Kids}}, $softpkg ); |
1299
|
|
|
|
|
|
|
push( @{$pkg->{Kids}}, $instppd ); |
1300
|
|
|
|
|
|
|
|
1301
|
|
|
|
|
|
|
# Now that we've got the structure built, read in the existing PPM |
1302
|
|
|
|
|
|
|
# Configuration file, add this to it, and spit it back out. |
1303
|
|
|
|
|
|
|
my %PPMConfig; |
1304
|
|
|
|
|
|
|
return 1 unless (%PPMConfig = getPPDfile('package' => $PPM::PPMdat, |
1305
|
|
|
|
|
|
|
'parsertype' => 'PPM::XML::PPMConfig')); |
1306
|
|
|
|
|
|
|
push( @{$PPMConfig{Kids}}, $pkg ); |
1307
|
|
|
|
|
|
|
my $cfg = bless \%PPMConfig, 'PPM::XML::PPMConfig::PPMCONFIG'; |
1308
|
|
|
|
|
|
|
|
1309
|
|
|
|
|
|
|
unless (open( DAT, ">$PPM::PPMdat" )) { |
1310
|
|
|
|
|
|
|
&Trace("open of $PPM::PPMdat failed: $!") if $options{'TRACE'}; |
1311
|
|
|
|
|
|
|
$PPM::PPMERR = "open of $PPM::PPMdat failed: $!\n"; |
1312
|
|
|
|
|
|
|
return 1; |
1313
|
|
|
|
|
|
|
} |
1314
|
|
|
|
|
|
|
my $oldout = select DAT; |
1315
|
|
|
|
|
|
|
$cfg->output(); |
1316
|
|
|
|
|
|
|
select $oldout; |
1317
|
|
|
|
|
|
|
close( DAT ); |
1318
|
|
|
|
|
|
|
&Trace("PPMdat_add_package: wrote $PPM::PPMdat") if $options{'TRACE'} > 1; |
1319
|
|
|
|
|
|
|
|
1320
|
|
|
|
|
|
|
return 0; |
1321
|
|
|
|
|
|
|
} |
1322
|
|
|
|
|
|
|
|
1323
|
|
|
|
|
|
|
# returns 0 on success, 1 and sets $PPMERR on error. |
1324
|
|
|
|
|
|
|
sub PPMdat_remove_package |
1325
|
|
|
|
|
|
|
{ |
1326
|
|
|
|
|
|
|
my $package = shift; |
1327
|
|
|
|
|
|
|
|
1328
|
|
|
|
|
|
|
# Read in the existing PPM configuration file |
1329
|
|
|
|
|
|
|
my %PPMConfig; |
1330
|
|
|
|
|
|
|
return 1 unless (%PPMConfig = getPPDfile('package' => $PPM::PPMdat, |
1331
|
|
|
|
|
|
|
'parsertype' => 'PPM::XML::PPMConfig')); |
1332
|
|
|
|
|
|
|
|
1333
|
|
|
|
|
|
|
# Try to find the package that we're supposed to be removing, and yank it |
1334
|
|
|
|
|
|
|
# out of the list of installed packages. |
1335
|
|
|
|
|
|
|
foreach my $idx (0 .. @{$PPMConfig{Kids}}) { |
1336
|
|
|
|
|
|
|
my $elem = $PPMConfig{Kids}[$idx]; |
1337
|
|
|
|
|
|
|
my $elem_type = ref $elem; |
1338
|
|
|
|
|
|
|
next if ($elem_type !~ /::PACKAGE$/o); |
1339
|
|
|
|
|
|
|
next if ($elem->{NAME} ne $package); |
1340
|
|
|
|
|
|
|
splice( @{$PPMConfig{Kids}}, $idx, 1 ); |
1341
|
|
|
|
|
|
|
} |
1342
|
|
|
|
|
|
|
|
1343
|
|
|
|
|
|
|
# Take the data structure we've got and bless it into a PPMCONFIG object so |
1344
|
|
|
|
|
|
|
# that we can output it again. |
1345
|
|
|
|
|
|
|
my $cfg = bless \%PPMConfig, 'PPM::XML::PPMConfig::PPMCONFIG'; |
1346
|
|
|
|
|
|
|
|
1347
|
|
|
|
|
|
|
# Now that we've removed the package, save the configuration file back out. |
1348
|
|
|
|
|
|
|
unless (open( DAT, ">$PPM::PPMdat" )) { |
1349
|
|
|
|
|
|
|
$PPM::PPMERR = "open of $PPM::PPMdat failed: $!\n"; |
1350
|
|
|
|
|
|
|
return 1; |
1351
|
|
|
|
|
|
|
} |
1352
|
|
|
|
|
|
|
my $oldout = select DAT; |
1353
|
|
|
|
|
|
|
$cfg->output(); |
1354
|
|
|
|
|
|
|
select $oldout; |
1355
|
|
|
|
|
|
|
close( DAT ); |
1356
|
|
|
|
|
|
|
&Trace("PPMdat_remove_package: wrote $PPM::PPMdat") |
1357
|
|
|
|
|
|
|
if $options{'TRACE'} > 1; |
1358
|
|
|
|
|
|
|
return 0; |
1359
|
|
|
|
|
|
|
} |
1360
|
|
|
|
|
|
|
|
1361
|
|
|
|
|
|
|
# Run $script using system(). If $scriptHREF is specified, its contents are |
1362
|
|
|
|
|
|
|
# used as the script. If $exec is specified, the script is saved to a |
1363
|
|
|
|
|
|
|
# temporary file and executed by $exec. |
1364
|
|
|
|
|
|
|
sub run_script |
1365
|
|
|
|
|
|
|
{ |
1366
|
|
|
|
|
|
|
my %argv = @_; |
1367
|
|
|
|
|
|
|
my $script = $argv{'script'}; |
1368
|
|
|
|
|
|
|
my $scriptHREF = $argv{'scriptHREF'}; |
1369
|
|
|
|
|
|
|
my $exec = $argv{'exec'}; |
1370
|
|
|
|
|
|
|
my $inst_root = $argv{'inst_root'}; |
1371
|
|
|
|
|
|
|
my $inst_archlib = $argv{'inst_archlib'}; |
1372
|
|
|
|
|
|
|
my (@commands, $tmpname); |
1373
|
|
|
|
|
|
|
|
1374
|
|
|
|
|
|
|
if ($scriptHREF) { |
1375
|
|
|
|
|
|
|
if ($exec) { |
1376
|
|
|
|
|
|
|
# store in a temp file. |
1377
|
|
|
|
|
|
|
$tmpname = "$options{'BUILDDIR'}/PPM-" . time(); |
1378
|
|
|
|
|
|
|
LWP::Simple::getstore($scriptHREF, $tmpname); |
1379
|
|
|
|
|
|
|
} |
1380
|
|
|
|
|
|
|
else { |
1381
|
|
|
|
|
|
|
my $doc = LWP::Simple::get $scriptHREF; |
1382
|
|
|
|
|
|
|
if (!defined $doc) { |
1383
|
|
|
|
|
|
|
&Trace("run_script: get $scriptHREF failed") |
1384
|
|
|
|
|
|
|
if $options{'TRACE'} > 1; |
1385
|
|
|
|
|
|
|
return 0; |
1386
|
|
|
|
|
|
|
} |
1387
|
|
|
|
|
|
|
@commands = split("\n", $doc); |
1388
|
|
|
|
|
|
|
} |
1389
|
|
|
|
|
|
|
} |
1390
|
|
|
|
|
|
|
else { |
1391
|
|
|
|
|
|
|
if (-f $script) { |
1392
|
|
|
|
|
|
|
$tmpname = $script; |
1393
|
|
|
|
|
|
|
} |
1394
|
|
|
|
|
|
|
else { |
1395
|
|
|
|
|
|
|
# change any escaped chars |
1396
|
|
|
|
|
|
|
$script =~ s/</
|
1397
|
|
|
|
|
|
|
$script =~ s/>/>/gi; |
1398
|
|
|
|
|
|
|
|
1399
|
|
|
|
|
|
|
@commands = split(';;', $script); |
1400
|
|
|
|
|
|
|
if ($exec) { |
1401
|
|
|
|
|
|
|
# store in a temp file. |
1402
|
|
|
|
|
|
|
$tmpname = "$options{'BUILDDIR'}/PPM-" . time(); |
1403
|
|
|
|
|
|
|
open(TMP, ">$tmpname"); |
1404
|
|
|
|
|
|
|
foreach my $command (@commands) { |
1405
|
|
|
|
|
|
|
print TMP "$command\n"; |
1406
|
|
|
|
|
|
|
} |
1407
|
|
|
|
|
|
|
close(TMP); |
1408
|
|
|
|
|
|
|
} |
1409
|
|
|
|
|
|
|
} |
1410
|
|
|
|
|
|
|
} |
1411
|
|
|
|
|
|
|
$ENV{'PPM_INSTROOT'} = $inst_root; |
1412
|
|
|
|
|
|
|
$ENV{'PPM_INSTARCHLIB'} = $inst_archlib; |
1413
|
|
|
|
|
|
|
if ($exec) { |
1414
|
|
|
|
|
|
|
$exec = $^X if ($exec =~ /^PPM_PERL$/i); |
1415
|
|
|
|
|
|
|
if ($Config{'osname'} eq 'MSWin32') { |
1416
|
|
|
|
|
|
|
$exec = Win32::GetShortPathName($exec) if $exec =~ / /; |
1417
|
|
|
|
|
|
|
$exec = "start $exec"; |
1418
|
|
|
|
|
|
|
} |
1419
|
|
|
|
|
|
|
system("$exec $tmpname"); |
1420
|
|
|
|
|
|
|
} |
1421
|
|
|
|
|
|
|
else { |
1422
|
|
|
|
|
|
|
for my $command (@commands) { |
1423
|
|
|
|
|
|
|
system($command); |
1424
|
|
|
|
|
|
|
} |
1425
|
|
|
|
|
|
|
} |
1426
|
|
|
|
|
|
|
} |
1427
|
|
|
|
|
|
|
|
1428
|
|
|
|
|
|
|
sub parsePPD |
1429
|
|
|
|
|
|
|
{ |
1430
|
|
|
|
|
|
|
my %PPD = @_; |
1431
|
|
|
|
|
|
|
my $pkg; |
1432
|
|
|
|
|
|
|
|
1433
|
|
|
|
|
|
|
%current_package = (); |
1434
|
|
|
|
|
|
|
|
1435
|
|
|
|
|
|
|
# Get the package name and version from the attributes and stick it |
1436
|
|
|
|
|
|
|
# into the 'current package' global var |
1437
|
|
|
|
|
|
|
$current_package{NAME} = $PPD{NAME}; |
1438
|
|
|
|
|
|
|
$current_package{VERSION} = $PPD{VERSION}; |
1439
|
|
|
|
|
|
|
|
1440
|
|
|
|
|
|
|
# Get all the information for this package and put it into the 'current |
1441
|
|
|
|
|
|
|
# package' global var. |
1442
|
|
|
|
|
|
|
my $got_implementation = 0; |
1443
|
|
|
|
|
|
|
my $elem; |
1444
|
|
|
|
|
|
|
|
1445
|
|
|
|
|
|
|
foreach $elem (@{$PPD{Kids}}) { |
1446
|
|
|
|
|
|
|
my $elem_type = ref $elem; |
1447
|
|
|
|
|
|
|
$elem_type =~ s/.*:://; |
1448
|
|
|
|
|
|
|
next if ($elem_type eq 'Characters'); |
1449
|
|
|
|
|
|
|
|
1450
|
|
|
|
|
|
|
if ($elem_type eq 'TITLE') { |
1451
|
|
|
|
|
|
|
# Get the package title out of our _only_ char data child |
1452
|
|
|
|
|
|
|
$current_package{TITLE} = $elem->{Kids}[0]{Text}; |
1453
|
|
|
|
|
|
|
} |
1454
|
|
|
|
|
|
|
elsif ($elem_type eq 'LICENSE') { |
1455
|
|
|
|
|
|
|
# Get the HREF for the license out of our attribute |
1456
|
|
|
|
|
|
|
$current_package{LICENSE} = $elem->{HREF}; |
1457
|
|
|
|
|
|
|
} |
1458
|
|
|
|
|
|
|
elsif ($elem_type eq 'ABSTRACT') { |
1459
|
|
|
|
|
|
|
# Get the package abstract out of our _only_ char data child |
1460
|
|
|
|
|
|
|
$current_package{ABSTRACT} = $elem->{Kids}[0]{Text}; |
1461
|
|
|
|
|
|
|
} |
1462
|
|
|
|
|
|
|
elsif ($elem_type eq 'AUTHOR') { |
1463
|
|
|
|
|
|
|
# Get the authors name out of our _only_ char data child |
1464
|
|
|
|
|
|
|
$current_package{AUTHOR} = $elem->{Kids}[0]{Text}; |
1465
|
|
|
|
|
|
|
} |
1466
|
|
|
|
|
|
|
elsif ($elem_type eq 'IMPLEMENTATION') { |
1467
|
|
|
|
|
|
|
# If we don't have a valid implementation yet, check if this is |
1468
|
|
|
|
|
|
|
# it. |
1469
|
|
|
|
|
|
|
next if ($got_implementation); |
1470
|
|
|
|
|
|
|
$got_implementation = implementation( @{ $elem->{Kids} } ); |
1471
|
|
|
|
|
|
|
} |
1472
|
|
|
|
|
|
|
elsif ($elem_type eq 'REQUIRE' or $elem_type eq 'PROVIDE') { |
1473
|
|
|
|
|
|
|
# we don't use these yet |
1474
|
|
|
|
|
|
|
next; |
1475
|
|
|
|
|
|
|
} |
1476
|
|
|
|
|
|
|
else { |
1477
|
|
|
|
|
|
|
&Trace("Unknown element '$elem_type' found inside SOFTPKG") if $options{'TRACE'}; |
1478
|
|
|
|
|
|
|
die "Unknown element '$elem_type' found inside SOFTPKG."; |
1479
|
|
|
|
|
|
|
} |
1480
|
|
|
|
|
|
|
} # End of "for each child element inside the PPD" |
1481
|
|
|
|
|
|
|
|
1482
|
|
|
|
|
|
|
if ($options{'TRACE'} > 3 and (%current_package) ) { |
1483
|
|
|
|
|
|
|
&Trace("Read a PPD:"); |
1484
|
|
|
|
|
|
|
foreach my $elem (keys %current_package) { |
1485
|
|
|
|
|
|
|
&Trace("\t$elem:\t$current_package{$elem}"); |
1486
|
|
|
|
|
|
|
} |
1487
|
|
|
|
|
|
|
} |
1488
|
|
|
|
|
|
|
|
1489
|
|
|
|
|
|
|
if (($Debug & 2) and (%current_package)) { |
1490
|
|
|
|
|
|
|
print "Read a PPD...\n"; |
1491
|
|
|
|
|
|
|
foreach my $elem (keys %current_package) |
1492
|
|
|
|
|
|
|
{ print "\t$elem:\t$current_package{$elem}\n"; } |
1493
|
|
|
|
|
|
|
} |
1494
|
|
|
|
|
|
|
} |
1495
|
|
|
|
|
|
|
|
1496
|
|
|
|
|
|
|
# Tests the passed IMPLEMENTATION for suitability on the current platform. |
1497
|
|
|
|
|
|
|
# Fills in the CODEBASE, INSTALL_HREF, INSTALL_EXEC, INSTALL_SCRIPT, |
1498
|
|
|
|
|
|
|
# UNINSTALL_HREF, UNINSTALL_EXEC, UNINSTALL_SCRIPT and DEPEND keys of |
1499
|
|
|
|
|
|
|
# %current_package. Returns 1 on success, 0 otherwise. |
1500
|
|
|
|
|
|
|
sub implementation |
1501
|
|
|
|
|
|
|
{ |
1502
|
|
|
|
|
|
|
my @impl = @_; |
1503
|
|
|
|
|
|
|
|
1504
|
|
|
|
|
|
|
# Declare the tmp vars we're going to use to hold onto things. |
1505
|
|
|
|
|
|
|
my ($ImplProcessor, $ImplOS, $ImplOSVersion, $ImplLanguage, $ImplCodebase); |
1506
|
|
|
|
|
|
|
my ($ImplInstallHREF, $ImplInstallEXEC, $ImplInstallScript); |
1507
|
|
|
|
|
|
|
my ($ImplUninstallHREF, $ImplUninstallEXEC, $ImplUninstallScript); |
1508
|
|
|
|
|
|
|
my ($ImplArch, $ImplPerlCoreVer, %ImplDepend, %ImplRequire, %ImplProvide); |
1509
|
|
|
|
|
|
|
|
1510
|
|
|
|
|
|
|
my $elem; |
1511
|
|
|
|
|
|
|
foreach $elem (@impl) { |
1512
|
|
|
|
|
|
|
my $elem_type = ref $elem; |
1513
|
|
|
|
|
|
|
$elem_type =~ s/.*:://; |
1514
|
|
|
|
|
|
|
next if ($elem_type eq 'Characters'); |
1515
|
|
|
|
|
|
|
|
1516
|
|
|
|
|
|
|
if ($elem_type eq 'CODEBASE') { |
1517
|
|
|
|
|
|
|
# Get the reference to the codebase out of our attributes. |
1518
|
|
|
|
|
|
|
$ImplCodebase = $elem->{HREF}; |
1519
|
|
|
|
|
|
|
} |
1520
|
|
|
|
|
|
|
elsif ($elem_type eq 'DEPENDENCY') { |
1521
|
|
|
|
|
|
|
# Get the name of any dependencies we have out of our attributes. |
1522
|
|
|
|
|
|
|
# Dependencies in old PPDs might not have version info. |
1523
|
|
|
|
|
|
|
$ImplDepend{$elem->{NAME}} = (defined $elem->{VERSION} && $elem->{VERSION} ne "") ? $elem->{VERSION} : "0,0,0,0"; |
1524
|
|
|
|
|
|
|
} |
1525
|
|
|
|
|
|
|
elsif ($elem_type eq 'PROVIDE') { |
1526
|
|
|
|
|
|
|
# Get the name of any provides we have out of our attributes. |
1527
|
|
|
|
|
|
|
# Provides in old PPDs might not have version info. |
1528
|
|
|
|
|
|
|
$ImplProvide{$elem->{NAME}} = (defined $elem->{VERSION} && $elem->{VERSION} ne "") ? $elem->{VERSION} : "0"; |
1529
|
|
|
|
|
|
|
} |
1530
|
|
|
|
|
|
|
elsif ($elem_type eq 'REQUIRE') { |
1531
|
|
|
|
|
|
|
# Get the name of any provides we have out of our attributes. |
1532
|
|
|
|
|
|
|
# Provides in old PPDs might not have version info. |
1533
|
|
|
|
|
|
|
$ImplRequire{$elem->{NAME}} = (defined $elem->{VERSION} && $elem->{VERSION} ne "") ? $elem->{VERSION} : "0"; |
1534
|
|
|
|
|
|
|
} |
1535
|
|
|
|
|
|
|
elsif ($elem_type eq 'LANGUAGE') { |
1536
|
|
|
|
|
|
|
# Get the language out of our attributes (if we don't already have |
1537
|
|
|
|
|
|
|
# the right one). |
1538
|
|
|
|
|
|
|
if ($ImplLanguage && ($ImplLanguage ne $LANGUAGE)) |
1539
|
|
|
|
|
|
|
{ $ImplLanguage = $elem->{VALUE}; } |
1540
|
|
|
|
|
|
|
} |
1541
|
|
|
|
|
|
|
elsif ($elem_type eq 'ARCHITECTURE') { |
1542
|
|
|
|
|
|
|
$ImplArch = $elem->{VALUE}; |
1543
|
|
|
|
|
|
|
} |
1544
|
|
|
|
|
|
|
elsif ($elem_type eq 'OS') { |
1545
|
|
|
|
|
|
|
# Get the OS value out of our attribute. |
1546
|
|
|
|
|
|
|
$ImplOS = $elem->{VALUE}; |
1547
|
|
|
|
|
|
|
} |
1548
|
|
|
|
|
|
|
elsif ($elem_type eq 'OSVERSION') { |
1549
|
|
|
|
|
|
|
# Get the OS version value out of our attribute |
1550
|
|
|
|
|
|
|
$ImplOSVersion = $elem->{VALUE}; |
1551
|
|
|
|
|
|
|
} |
1552
|
|
|
|
|
|
|
elsif ($elem_type eq 'PERLCORE') { |
1553
|
|
|
|
|
|
|
# Get the compiled Perl core value out of our attributes |
1554
|
|
|
|
|
|
|
$ImplPerlCoreVer = $elem->{VERSION}; |
1555
|
|
|
|
|
|
|
} |
1556
|
|
|
|
|
|
|
elsif ($elem_type eq 'PROCESSOR') { |
1557
|
|
|
|
|
|
|
# Get the processor value out of our attribute |
1558
|
|
|
|
|
|
|
$ImplProcessor = $elem->{VALUE}; |
1559
|
|
|
|
|
|
|
} |
1560
|
|
|
|
|
|
|
elsif ($elem_type eq 'INSTALL') { |
1561
|
|
|
|
|
|
|
# Get anything which might have been an attribute |
1562
|
|
|
|
|
|
|
$ImplInstallHREF = $elem->{HREF}; |
1563
|
|
|
|
|
|
|
$ImplInstallEXEC = $elem->{EXEC}; |
1564
|
|
|
|
|
|
|
# Get any raw Perl script out of here (if we've got any) |
1565
|
|
|
|
|
|
|
if ( (exists $elem->{Kids}) and (exists $elem->{Kids}[0]{Text}) ) |
1566
|
|
|
|
|
|
|
{ $ImplInstallScript = $elem->{Kids}[0]{Text}; } |
1567
|
|
|
|
|
|
|
} |
1568
|
|
|
|
|
|
|
elsif ($elem_type eq 'UNINSTALL') { |
1569
|
|
|
|
|
|
|
# Get anything which might have been an attribute |
1570
|
|
|
|
|
|
|
$ImplUninstallHREF = $elem->{HREF}; |
1571
|
|
|
|
|
|
|
$ImplUninstallEXEC = $elem->{EXEC}; |
1572
|
|
|
|
|
|
|
# Get any raw Perl script out of here (if we've got any) |
1573
|
|
|
|
|
|
|
if ( (exists $elem->{Kids}) and (exists $elem->{Kids}[0]{Text}) ) |
1574
|
|
|
|
|
|
|
{ $ImplUninstallScript = $elem->{Kids}[0]{Text}; } |
1575
|
|
|
|
|
|
|
} |
1576
|
|
|
|
|
|
|
else { |
1577
|
|
|
|
|
|
|
die "Unknown element '$elem_type' found inside of IMPLEMENTATION."; |
1578
|
|
|
|
|
|
|
} |
1579
|
|
|
|
|
|
|
} # end of 'for every element inside IMPLEMENTATION' |
1580
|
|
|
|
|
|
|
|
1581
|
|
|
|
|
|
|
# Check to see if we've found a valid IMPLEMENTATION for the target |
1582
|
|
|
|
|
|
|
# machine. |
1583
|
|
|
|
|
|
|
return 0 if ((defined $ImplArch) and ($ImplArch ne $varchname)); |
1584
|
|
|
|
|
|
|
return 0 if ((defined $ImplProcessor) and ($ImplProcessor ne $CPU)); |
1585
|
|
|
|
|
|
|
return 0 if ((defined $ImplLanguage) and ($ImplLanguage ne $LANGUAGE)); |
1586
|
|
|
|
|
|
|
return 0 if ((defined $ImplOS) and ($ImplOS ne $OS_VALUE)); |
1587
|
|
|
|
|
|
|
return 0 if ((defined $ImplOSVersion) and ($ImplOSVersion ne $OS_VERSION)); |
1588
|
|
|
|
|
|
|
|
1589
|
|
|
|
|
|
|
# Got a valid IMPLEMENTATION, stuff all the values we just read in into the |
1590
|
|
|
|
|
|
|
# 'current package' global var. |
1591
|
|
|
|
|
|
|
$current_package{PERLCORE_VER} = $ImplPerlCoreVer |
1592
|
|
|
|
|
|
|
if (defined $ImplPerlCoreVer); |
1593
|
|
|
|
|
|
|
$current_package{CODEBASE} = $ImplCodebase |
1594
|
|
|
|
|
|
|
if (defined $ImplCodebase); |
1595
|
|
|
|
|
|
|
$current_package{INSTALL_HREF} = $ImplInstallHREF |
1596
|
|
|
|
|
|
|
if (defined $ImplInstallHREF); |
1597
|
|
|
|
|
|
|
$current_package{INSTALL_EXEC} = $ImplInstallEXEC |
1598
|
|
|
|
|
|
|
if (defined $ImplInstallEXEC); |
1599
|
|
|
|
|
|
|
$current_package{INSTALL_SCRIPT} = $ImplInstallScript |
1600
|
|
|
|
|
|
|
if (defined $ImplInstallScript); |
1601
|
|
|
|
|
|
|
$current_package{UNINSTALL_HREF} = $ImplUninstallHREF |
1602
|
|
|
|
|
|
|
if (defined $ImplUninstallHREF); |
1603
|
|
|
|
|
|
|
$current_package{UNINSTALL_EXEC} = $ImplUninstallEXEC |
1604
|
|
|
|
|
|
|
if (defined $ImplUninstallEXEC); |
1605
|
|
|
|
|
|
|
$current_package{UNINSTALL_SCRIPT} = $ImplUninstallScript |
1606
|
|
|
|
|
|
|
if (defined $ImplUninstallScript); |
1607
|
|
|
|
|
|
|
%{$current_package{DEPEND}} = %ImplDepend |
1608
|
|
|
|
|
|
|
if (%ImplDepend); |
1609
|
|
|
|
|
|
|
|
1610
|
|
|
|
|
|
|
return 1; |
1611
|
|
|
|
|
|
|
} |
1612
|
|
|
|
|
|
|
|
1613
|
|
|
|
|
|
|
sub getPPDfile |
1614
|
|
|
|
|
|
|
{ |
1615
|
|
|
|
|
|
|
my %argv = @_; |
1616
|
|
|
|
|
|
|
my $package = $argv{'package'}; |
1617
|
|
|
|
|
|
|
my $parsertype = $argv{'parsertype'} || 'PPM::XML::PPD'; |
1618
|
|
|
|
|
|
|
my $location = $argv{'location'}; |
1619
|
|
|
|
|
|
|
my $PPDfile = $argv{'PPDfile'}; |
1620
|
|
|
|
|
|
|
my (%PPD, $contents); |
1621
|
|
|
|
|
|
|
|
1622
|
|
|
|
|
|
|
if (defined($location)) { |
1623
|
|
|
|
|
|
|
if ($location =~ /[^\/]$/) { $location .= "/"; } |
1624
|
|
|
|
|
|
|
$package = $location . $package . ".ppd"; |
1625
|
|
|
|
|
|
|
} |
1626
|
|
|
|
|
|
|
|
1627
|
|
|
|
|
|
|
if ($package =~ /^file:\/\/.*\|/i) { |
1628
|
|
|
|
|
|
|
# $package is a local directory, let's avoid LWP by changing |
1629
|
|
|
|
|
|
|
# it to a pathname. |
1630
|
|
|
|
|
|
|
$package =~ s@^file://@@i; |
1631
|
|
|
|
|
|
|
$package =~ s@^localhost/@@i; |
1632
|
|
|
|
|
|
|
$package =~ s@\|@:@; |
1633
|
|
|
|
|
|
|
} |
1634
|
|
|
|
|
|
|
# full path to a file? |
1635
|
|
|
|
|
|
|
if (-f $package) { |
1636
|
|
|
|
|
|
|
local $/; |
1637
|
|
|
|
|
|
|
unless (open (DATAFILE, $package)) { |
1638
|
|
|
|
|
|
|
&Trace("getPPDfile: open of $package failed") if $options{'TRACE'}; |
1639
|
|
|
|
|
|
|
$PPM::PPMERR = "open of $package failed: $!\n"; |
1640
|
|
|
|
|
|
|
return; |
1641
|
|
|
|
|
|
|
} |
1642
|
|
|
|
|
|
|
$contents = ; |
1643
|
|
|
|
|
|
|
close(DATAFILE); |
1644
|
|
|
|
|
|
|
$$PPDfile = $package; |
1645
|
|
|
|
|
|
|
} |
1646
|
|
|
|
|
|
|
# URL? |
1647
|
|
|
|
|
|
|
elsif ($package =~ m@^...*://@i) { |
1648
|
|
|
|
|
|
|
return unless ($contents = read_href("href" => $package, |
1649
|
|
|
|
|
|
|
"request" => 'GET')); |
1650
|
|
|
|
|
|
|
$$PPDfile = $package; |
1651
|
|
|
|
|
|
|
} |
1652
|
|
|
|
|
|
|
# does the package have a in $PPM::PPMdat? |
1653
|
|
|
|
|
|
|
elsif ($installed_packages{$package}) { |
1654
|
|
|
|
|
|
|
$location = $installed_packages{$package}{'LOCATION'}; |
1655
|
|
|
|
|
|
|
if ($location =~ /[^\/]$/) { $location .= "/"; } |
1656
|
|
|
|
|
|
|
$$PPDfile = $location . $package . ".ppd"; |
1657
|
|
|
|
|
|
|
return %PPD if (%PPD = getPPDfile('package' => $$PPDfile, |
1658
|
|
|
|
|
|
|
'parsertype' => $parsertype)); |
1659
|
|
|
|
|
|
|
undef $$PPDfile; |
1660
|
|
|
|
|
|
|
} |
1661
|
|
|
|
|
|
|
|
1662
|
|
|
|
|
|
|
# None of the above, search the repositories. |
1663
|
|
|
|
|
|
|
unless ($PPDfile && $$PPDfile) { |
1664
|
|
|
|
|
|
|
foreach (keys %repositories) { |
1665
|
|
|
|
|
|
|
my $location = $repositories{$_}{'LOCATION'}; |
1666
|
|
|
|
|
|
|
if ($location =~ /[^\/]$/) { $location .= "/"; } |
1667
|
|
|
|
|
|
|
$$PPDfile = $location . $package . ".ppd"; |
1668
|
|
|
|
|
|
|
return %PPD if (%PPD = getPPDfile('package' => $$PPDfile, |
1669
|
|
|
|
|
|
|
'parsertype' => $parsertype, 'PPDfile' => \$$PPDfile)); |
1670
|
|
|
|
|
|
|
undef $$PPDfile; |
1671
|
|
|
|
|
|
|
} |
1672
|
|
|
|
|
|
|
return unless $$PPDfile; |
1673
|
|
|
|
|
|
|
} |
1674
|
|
|
|
|
|
|
|
1675
|
|
|
|
|
|
|
# take care of '&' |
1676
|
|
|
|
|
|
|
$contents =~ s/&(?!\w+;)/&/go; |
1677
|
|
|
|
|
|
|
|
1678
|
|
|
|
|
|
|
my $parser = new XML::Parser( Style => 'Objects', Pkg => $parsertype ); |
1679
|
|
|
|
|
|
|
my @parsed; |
1680
|
|
|
|
|
|
|
eval { @parsed = @{ $parser->parse( $contents ) } }; |
1681
|
|
|
|
|
|
|
if ($@) { |
1682
|
|
|
|
|
|
|
&Trace("getPPDfile: content of $$PPDfile is not valid") if $options{'TRACE'}; |
1683
|
|
|
|
|
|
|
$PPM::PPMERR = "content of $$PPDfile is not valid: $!\n"; |
1684
|
|
|
|
|
|
|
return; |
1685
|
|
|
|
|
|
|
} |
1686
|
|
|
|
|
|
|
|
1687
|
|
|
|
|
|
|
return if (!$parsed[0]->rvalidate( \&PPM::parse_err )); |
1688
|
|
|
|
|
|
|
|
1689
|
|
|
|
|
|
|
return %{$parsed[0]}; |
1690
|
|
|
|
|
|
|
} |
1691
|
|
|
|
|
|
|
|
1692
|
|
|
|
|
|
|
# Spits out the error from parsing, and sets our global error message |
1693
|
|
|
|
|
|
|
# accordingly. |
1694
|
|
|
|
|
|
|
sub parse_err |
1695
|
|
|
|
|
|
|
{ |
1696
|
|
|
|
|
|
|
&Trace("parse_err: @_") if $options{'TRACE'}; |
1697
|
|
|
|
|
|
|
warn @_; |
1698
|
|
|
|
|
|
|
$PPM::PPMERR = 'Errors found while parsing document.'; |
1699
|
|
|
|
|
|
|
} |
1700
|
|
|
|
|
|
|
|
1701
|
|
|
|
|
|
|
# reads and parses the PPM data file $PPM::PPMdat. Stores config information in |
1702
|
|
|
|
|
|
|
# $PPM_ver, $build_dir, %repositories, $CPU, $OS_VALUE, and $OS_VERSION. |
1703
|
|
|
|
|
|
|
# Stores information about individual packages in the hash %installed_packages. |
1704
|
|
|
|
|
|
|
sub read_config |
1705
|
|
|
|
|
|
|
{ |
1706
|
|
|
|
|
|
|
return if $init++; |
1707
|
|
|
|
|
|
|
|
1708
|
|
|
|
|
|
|
my %PPMConfig; |
1709
|
|
|
|
|
|
|
return unless (%PPMConfig = getPPDfile('package' => $PPM::PPMdat, |
1710
|
|
|
|
|
|
|
'parsertype' => 'PPM::XML::PPMConfig')); |
1711
|
|
|
|
|
|
|
|
1712
|
|
|
|
|
|
|
foreach my $elem (@{$PPMConfig{Kids}}) { |
1713
|
|
|
|
|
|
|
my $subelem = ref $elem; |
1714
|
|
|
|
|
|
|
$subelem =~ s/.*:://; |
1715
|
|
|
|
|
|
|
next if ($subelem eq 'Characters'); |
1716
|
|
|
|
|
|
|
|
1717
|
|
|
|
|
|
|
if ($subelem eq 'PPMVER') { |
1718
|
|
|
|
|
|
|
# Get the value out of our _only_ character data element. |
1719
|
|
|
|
|
|
|
$PPM_ver = $elem->{Kids}[0]{Text}; |
1720
|
|
|
|
|
|
|
} |
1721
|
|
|
|
|
|
|
elsif ($subelem eq 'PPMPRECIOUS') { |
1722
|
|
|
|
|
|
|
# Get the value out of our _only_ character data element. |
1723
|
|
|
|
|
|
|
@required_packages = split( ';', $elem->{Kids}[0]{Text} ); |
1724
|
|
|
|
|
|
|
} |
1725
|
|
|
|
|
|
|
elsif ($subelem eq 'PLATFORM') { |
1726
|
|
|
|
|
|
|
# Get values out of our attributes |
1727
|
|
|
|
|
|
|
$CPU = $elem->{CPU}; |
1728
|
|
|
|
|
|
|
$OS_VALUE = $elem->{OSVALUE}; |
1729
|
|
|
|
|
|
|
$OS_VERSION = $elem->{OSVERSION}; |
1730
|
|
|
|
|
|
|
$LANGUAGE = $elem->{LANGUAGE}; |
1731
|
|
|
|
|
|
|
} |
1732
|
|
|
|
|
|
|
elsif ($subelem eq 'REPOSITORY') { |
1733
|
|
|
|
|
|
|
# Get a repository out of the element attributes |
1734
|
|
|
|
|
|
|
my ($name); |
1735
|
|
|
|
|
|
|
$name = $elem->{NAME}; |
1736
|
|
|
|
|
|
|
$repositories{ $name }{'LOCATION'} = $elem->{LOCATION}; |
1737
|
|
|
|
|
|
|
$repositories{ $name }{'USERNAME'} = $elem->{USERNAME}; |
1738
|
|
|
|
|
|
|
$repositories{ $name }{'PASSWORD'} = $elem->{PASSWORD}; |
1739
|
|
|
|
|
|
|
$repositories{ $name }{'SUMMARYFILE'} = $elem->{SUMMARYFILE}; |
1740
|
|
|
|
|
|
|
} |
1741
|
|
|
|
|
|
|
elsif ($subelem eq 'OPTIONS') { |
1742
|
|
|
|
|
|
|
# Get our options out of the element attributes |
1743
|
|
|
|
|
|
|
# |
1744
|
|
|
|
|
|
|
# Previous versions of the ppm.xml had "Yes/No" values |
1745
|
|
|
|
|
|
|
# for some of these options. Change these to "1/0" if we |
1746
|
|
|
|
|
|
|
# encounter them. |
1747
|
|
|
|
|
|
|
$options{'IGNORECASE'} = |
1748
|
|
|
|
|
|
|
($elem->{IGNORECASE} && $elem->{IGNORECASE} ne 'No'); |
1749
|
|
|
|
|
|
|
$options{'CLEAN'} = ($elem->{CLEAN} && $elem->{CLEAN} ne 'No'); |
1750
|
|
|
|
|
|
|
$options{'CONFIRM'} = |
1751
|
|
|
|
|
|
|
($elem->{CONFIRM} && $elem->{CONFIRM} ne 'No'); |
1752
|
|
|
|
|
|
|
$options{'DOWNLOADSTATUS'} = |
1753
|
|
|
|
|
|
|
defined $elem->{DOWNLOADSTATUS} ? $elem->{DOWNLOADSTATUS} : "0"; |
1754
|
|
|
|
|
|
|
$options{'FORCE_INSTALL'} = |
1755
|
|
|
|
|
|
|
($elem->{FORCEINSTALL} && $elem->{FORCEINSTALL} ne 'No'); |
1756
|
|
|
|
|
|
|
$options{'ROOT'} = $elem->{ROOT}; |
1757
|
|
|
|
|
|
|
$options{'MORE'} = $elem->{MORE}; |
1758
|
|
|
|
|
|
|
$options{'TRACE'} = defined $elem->{TRACE} ? $elem->{TRACE} : "0"; |
1759
|
|
|
|
|
|
|
$options{'TRACEFILE'} = |
1760
|
|
|
|
|
|
|
defined $elem->{TRACEFILE} ? $elem->{TRACEFILE} : "PPM.LOG"; |
1761
|
|
|
|
|
|
|
$options{'VERBOSE'} = |
1762
|
|
|
|
|
|
|
defined $elem->{VERBOSE} ? $elem->{VERBOSE} : "1"; |
1763
|
|
|
|
|
|
|
|
1764
|
|
|
|
|
|
|
$options{'BUILDDIR'} = $elem->{BUILDDIR}; |
1765
|
|
|
|
|
|
|
# Strip trailing separator |
1766
|
|
|
|
|
|
|
my $chr = substr( $options{'BUILDDIR'}, -1, 1 ); |
1767
|
|
|
|
|
|
|
chop $options{'BUILDDIR'} if ($chr eq '/' || $chr eq '\\'); |
1768
|
|
|
|
|
|
|
if ($options{'TRACE'} && !$TraceStarted) { |
1769
|
|
|
|
|
|
|
$options{'TRACEFILE'} = "PPM.log" if (!defined $options{'TRACEFILE'}); |
1770
|
|
|
|
|
|
|
open(PPMTRACE, ">>$options{'TRACEFILE'}"); |
1771
|
|
|
|
|
|
|
my $oldfh = select(PPMTRACE); |
1772
|
|
|
|
|
|
|
$| = 1; |
1773
|
|
|
|
|
|
|
select($oldfh); |
1774
|
|
|
|
|
|
|
&Trace("starting up..."); |
1775
|
|
|
|
|
|
|
$TraceStarted = 1; |
1776
|
|
|
|
|
|
|
} |
1777
|
|
|
|
|
|
|
} |
1778
|
|
|
|
|
|
|
elsif ($subelem eq 'PACKAGE') { |
1779
|
|
|
|
|
|
|
# Get our package name out of our attributes |
1780
|
|
|
|
|
|
|
my $pkg = $elem->{NAME}; |
1781
|
|
|
|
|
|
|
|
1782
|
|
|
|
|
|
|
# Gather the information on this package from the child elements. |
1783
|
|
|
|
|
|
|
my ($loc, $instdate, $root, $packlist, $ppd); |
1784
|
|
|
|
|
|
|
foreach my $child (@{$elem->{Kids}}) { |
1785
|
|
|
|
|
|
|
my $child_type = ref $child; |
1786
|
|
|
|
|
|
|
$child_type =~ s/.*:://; |
1787
|
|
|
|
|
|
|
next if ($child_type eq 'Characters'); |
1788
|
|
|
|
|
|
|
|
1789
|
|
|
|
|
|
|
if ($child_type eq 'LOCATION') |
1790
|
|
|
|
|
|
|
{ $loc = $child->{Kids}[0]{Text}; } |
1791
|
|
|
|
|
|
|
elsif ($child_type eq 'INSTDATE') |
1792
|
|
|
|
|
|
|
{ $instdate = $child->{Kids}[0]{Text}; } |
1793
|
|
|
|
|
|
|
elsif ($child_type eq 'INSTROOT') |
1794
|
|
|
|
|
|
|
{ $root = $child->{Kids}[0]{Text}; } |
1795
|
|
|
|
|
|
|
elsif ($child_type eq 'INSTPACKLIST') |
1796
|
|
|
|
|
|
|
{ $packlist = $child->{Kids}[0]{Text}; } |
1797
|
|
|
|
|
|
|
elsif ($child_type eq 'INSTPPD') |
1798
|
|
|
|
|
|
|
{ |
1799
|
|
|
|
|
|
|
# Find the SOFTPKG inside here and hang onto it |
1800
|
|
|
|
|
|
|
my $tmp; |
1801
|
|
|
|
|
|
|
foreach $tmp (@{$child->{Kids}}) |
1802
|
|
|
|
|
|
|
{ |
1803
|
|
|
|
|
|
|
if ((ref $tmp) =~ /::SOFTPKG$/o) |
1804
|
|
|
|
|
|
|
{ $ppd = $tmp; } |
1805
|
|
|
|
|
|
|
} |
1806
|
|
|
|
|
|
|
} |
1807
|
|
|
|
|
|
|
else |
1808
|
|
|
|
|
|
|
{ |
1809
|
|
|
|
|
|
|
die "Unknown element inside of $pkg PACKAGE; $child"; |
1810
|
|
|
|
|
|
|
} |
1811
|
|
|
|
|
|
|
} |
1812
|
|
|
|
|
|
|
|
1813
|
|
|
|
|
|
|
my %package_details = ( LOCATION => $loc, |
1814
|
|
|
|
|
|
|
INST_DATE => $instdate, |
1815
|
|
|
|
|
|
|
INST_ROOT => $root, |
1816
|
|
|
|
|
|
|
INST_PACKLIST => $packlist, |
1817
|
|
|
|
|
|
|
INST_PPD => $ppd); |
1818
|
|
|
|
|
|
|
$installed_packages{$pkg} = \%package_details; |
1819
|
|
|
|
|
|
|
} |
1820
|
|
|
|
|
|
|
else |
1821
|
|
|
|
|
|
|
{ |
1822
|
|
|
|
|
|
|
die "Unknown element found in PPD_DAT file; $subelem"; |
1823
|
|
|
|
|
|
|
} |
1824
|
|
|
|
|
|
|
} |
1825
|
|
|
|
|
|
|
if ($Debug & 1) { |
1826
|
|
|
|
|
|
|
print "This is ppm, version $PPM_ver.\nRepository locations:\n"; |
1827
|
|
|
|
|
|
|
foreach (keys %repositories) { |
1828
|
|
|
|
|
|
|
print "\t$_: $repositories{$_}{'LOCATION'}\n" |
1829
|
|
|
|
|
|
|
} |
1830
|
|
|
|
|
|
|
print "Platform is $OS_VALUE version $OS_VERSION on a $CPU CPU.\n"; |
1831
|
|
|
|
|
|
|
print "Packages will be built in $options{'BUILDDIR'}\n"; |
1832
|
|
|
|
|
|
|
print "Commands will " . ($options{'CONFIRM'} ? "" : "not ") . |
1833
|
|
|
|
|
|
|
"be confirmed.\n"; |
1834
|
|
|
|
|
|
|
print "Temporary files will " . ($options{'CLEAN'} ? "" : "not ") . |
1835
|
|
|
|
|
|
|
"be deleted.\n"; |
1836
|
|
|
|
|
|
|
print "Installations will " . ($options{'FORCE_INSTALL'} ? "" : "not ") |
1837
|
|
|
|
|
|
|
. "continue if a dependency cannot be installed.\n"; |
1838
|
|
|
|
|
|
|
print "Screens will " . ($options{'MORE'} > 0 ? |
1839
|
|
|
|
|
|
|
"pause after each $options{'MORE'} lines.\n" : |
1840
|
|
|
|
|
|
|
"not pause after the screen is full.\n"); |
1841
|
|
|
|
|
|
|
print "Tracing info will " . ($options{'TRACE'} > 0 ? |
1842
|
|
|
|
|
|
|
"be written to $options{'TRACEFILE'}.\n" : "not be written.\n"); |
1843
|
|
|
|
|
|
|
print "Case-" . ($options{'IGNORECASE'} ? "in" : "") . |
1844
|
|
|
|
|
|
|
"sensitive searches will be performed.\n"; |
1845
|
|
|
|
|
|
|
|
1846
|
|
|
|
|
|
|
foreach my $pkg (keys %installed_packages) { |
1847
|
|
|
|
|
|
|
print "\nFound installed package $pkg, " . |
1848
|
|
|
|
|
|
|
"installed on $installed_packages{$pkg}{INST_DATE}\n" . |
1849
|
|
|
|
|
|
|
"in directory root $installed_packages{$pkg}{INST_ROOT} " . |
1850
|
|
|
|
|
|
|
"from $installed_packages{$pkg}{'LOCATION'}.\n\n"; |
1851
|
|
|
|
|
|
|
} |
1852
|
|
|
|
|
|
|
} |
1853
|
|
|
|
|
|
|
} |
1854
|
|
|
|
|
|
|
|
1855
|
|
|
|
|
|
|
sub Trace |
1856
|
|
|
|
|
|
|
{ |
1857
|
|
|
|
|
|
|
print PPMTRACE "$0: @_ at ", scalar localtime(), "\n"; |
1858
|
|
|
|
|
|
|
} |
1859
|
|
|
|
|
|
|
|
1860
|
|
|
|
|
|
|
# Converts a cpan-type of version string (eg, I<1.23>) into a ppd one |
1861
|
|
|
|
|
|
|
# of the form I<1,23,0,0>: |
1862
|
|
|
|
|
|
|
|
1863
|
|
|
|
|
|
|
sub cpan2ppd_version { |
1864
|
|
|
|
|
|
|
my $v = shift; |
1865
|
|
|
|
|
|
|
return $v if ($v =~ /,/); |
1866
|
|
|
|
|
|
|
return join ',', (split (/\./, $v), (0)x4)[0..3]; |
1867
|
|
|
|
|
|
|
} |
1868
|
|
|
|
|
|
|
|
1869
|
|
|
|
|
|
|
1; |
1870
|
|
|
|
|
|
|
|
1871
|
|
|
|
|
|
|
__END__ |