602
|
1 |
# Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
|
|
2 |
# All rights reserved.
|
|
3 |
# This component and the accompanying materials are made available
|
|
4 |
# under the terms of the License "Eclipse Public License v1.0"
|
|
5 |
# which accompanies this distribution, and is available
|
|
6 |
# at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
|
7 |
#
|
|
8 |
# Initial Contributors:
|
|
9 |
# Nokia Corporation - initial contribution.
|
|
10 |
#
|
|
11 |
# Contributors:
|
|
12 |
#
|
|
13 |
# Description:
|
|
14 |
#
|
|
15 |
#
|
|
16 |
# Description:
|
|
17 |
# RelTransfer::Export.pm
|
|
18 |
#
|
|
19 |
|
|
20 |
package RelTransfer::Export;
|
|
21 |
|
|
22 |
use strict;
|
|
23 |
use ExportData;
|
|
24 |
use Utils;
|
|
25 |
use Cwd;
|
|
26 |
|
|
27 |
use RelTransfer;
|
|
28 |
use vars qw(@ISA);
|
|
29 |
@ISA=("RelTransfer");
|
|
30 |
|
|
31 |
#
|
|
32 |
# Constructor
|
|
33 |
#
|
|
34 |
|
|
35 |
sub Initialize {
|
|
36 |
my $self = shift;
|
|
37 |
|
|
38 |
$self->SUPER::Initialize();
|
|
39 |
$self->{exportData} = ExportData->New(exports_file => $self->{iniData}->ExportDataFile(),
|
|
40 |
verbose => $self->{verbose});
|
|
41 |
|
|
42 |
#check to see if all the pgp keys used for exporting exist on the public keyring
|
|
43 |
my @pgpKeys = @{$self->{iniData}->PgpEncryptionKeys};
|
|
44 |
unless (@pgpKeys) {
|
|
45 |
die "Error: No PGP encrypting keys defined in reltools.ini\n";
|
|
46 |
}
|
|
47 |
push @pgpKeys, @{$self->{exportData}->AllPgpKeys};
|
|
48 |
foreach my $pgpKey (@pgpKeys) {
|
|
49 |
unless ($self->{crypt}->PublicKeyExists($pgpKey)) {
|
|
50 |
die "Error: PGP key $pgpKey is required for exporting but does not exist on public keyring\n";
|
|
51 |
}
|
|
52 |
}
|
|
53 |
}
|
|
54 |
|
|
55 |
#
|
|
56 |
# Public methods
|
|
57 |
#
|
|
58 |
|
|
59 |
sub CheckExportable {
|
|
60 |
my $self = shift;
|
|
61 |
my $comp = shift;
|
|
62 |
my $ver = shift;
|
|
63 |
|
|
64 |
unless ($self->ReleaseExistsInLocalArchive($comp, $ver)) {
|
|
65 |
die "Error: $comp $ver does not exist in local archive\n";
|
|
66 |
}
|
|
67 |
unless ($self->{exportData}->ComponentIsExportable($comp)) {
|
|
68 |
print "Warning: component \"$comp\" is not defined in export table.\n";
|
|
69 |
}
|
|
70 |
}
|
|
71 |
|
|
72 |
sub TransferRelease {
|
|
73 |
my $self = shift;
|
|
74 |
my $comp = shift;
|
|
75 |
my $ver = shift;
|
|
76 |
|
|
77 |
if ($self->{verbose}) {
|
|
78 |
print "\nExporting $comp $ver...\n";
|
|
79 |
}
|
|
80 |
|
|
81 |
#check to see if ok to export
|
|
82 |
unless ($self->ReleaseExistsInLocalArchive($comp, $ver)) {
|
|
83 |
die "Error: $comp $ver does not exist in local archive\n";
|
|
84 |
}
|
|
85 |
|
|
86 |
my $releaseExists = $self->ReleaseExistsOnRemoteSite($comp, $ver);
|
|
87 |
unless ($self->{exportData}->ComponentIsExportable($comp)) {
|
|
88 |
if (not $releaseExists or $self->{force}) {
|
|
89 |
die "Error: cannot export $comp: not defined in export table\n";
|
|
90 |
}
|
|
91 |
else {
|
|
92 |
if ($self->{verbose}) {
|
|
93 |
print "$comp $ver already exported to remote site\n";
|
|
94 |
}
|
|
95 |
return 0;
|
|
96 |
}
|
|
97 |
}
|
|
98 |
else {
|
|
99 |
if ($releaseExists and not $self->{force}) {
|
|
100 |
if ($self->{verbose}) {
|
|
101 |
print "$comp $ver already exported to remote site\n";
|
|
102 |
}
|
|
103 |
return 0;
|
|
104 |
}
|
|
105 |
}
|
|
106 |
|
|
107 |
#encrypt, zip and then send release to remote site
|
|
108 |
eval {
|
|
109 |
my $localdir = $self->PathData->LocalArchivePathForExistingComponent($comp, $ver);
|
|
110 |
print "Local directory for \"$comp\" \"$ver\" is \"$localdir\"\n" if ($self->{verbose});
|
|
111 |
$self->EncryptReleaseFiles($comp, $ver, $localdir);
|
|
112 |
$self->ZipEncryptedReleaseFiles($comp, $ver);
|
|
113 |
$self->SendZippedReleaseFile($comp, $ver, $localdir);
|
|
114 |
return 1 if ($self->{dummy});
|
|
115 |
my $localsize = $self->SizeOfNewlyZippedFile($comp, $ver);
|
|
116 |
my $remotesize = $self->SizeOfRemoteFile($comp, $ver);
|
|
117 |
$self->CompareSizes($localsize, $remotesize, $comp, $ver);
|
|
118 |
};
|
|
119 |
if ($@) {
|
|
120 |
my $error = $@;
|
|
121 |
$self->CleanupTempDir();
|
|
122 |
die $error;
|
|
123 |
}
|
|
124 |
|
|
125 |
#optionally send a log file to the remote site
|
|
126 |
if (defined $self->{iniData}->RemoteLogsDir) {
|
|
127 |
eval {
|
|
128 |
$self->SendLogFile($comp, $ver);
|
|
129 |
};
|
|
130 |
if ($@) {
|
|
131 |
print "Warning: Export of log file failed. $@\n";
|
|
132 |
}
|
|
133 |
}
|
|
134 |
|
|
135 |
#delete all the files in the temporary directory
|
|
136 |
$self->CleanupTempDir();
|
|
137 |
|
|
138 |
if ($self->{verbose}) {
|
|
139 |
print "$comp $ver successfully exported to remote site.\n";
|
|
140 |
}
|
|
141 |
return 1;
|
|
142 |
}
|
|
143 |
|
|
144 |
sub ExamineExportedRelease {
|
|
145 |
my $self = shift;
|
|
146 |
my $comp = shift;
|
|
147 |
my $ver = shift;
|
|
148 |
|
|
149 |
unless ($self->ReleaseExistsInLocalArchive($comp, $ver)) {
|
|
150 |
die "Error: $comp $ver does not exist in local archive\n";
|
|
151 |
}
|
|
152 |
|
|
153 |
eval {
|
|
154 |
my $localdir = $self->PathData->LocalArchivePathForExistingComponent($comp, $ver);
|
|
155 |
my $remotesize = $self->SizeOfRemoteFile($comp, $ver);
|
|
156 |
$self->EncryptReleaseFiles($comp, $ver, $localdir);
|
|
157 |
$self->ZipEncryptedReleaseFiles($comp, $ver);
|
|
158 |
my $localsize = $self->SizeOfNewlyZippedFile($comp, $ver);
|
|
159 |
$self->CompareSizes($localsize, $remotesize, $comp, $ver);
|
|
160 |
};
|
|
161 |
if ($@) {
|
|
162 |
my $error = $@;
|
|
163 |
$self->CleanupTempDir();
|
|
164 |
die $error;
|
|
165 |
}
|
|
166 |
|
|
167 |
$self->CleanupTempDir();
|
|
168 |
}
|
|
169 |
|
|
170 |
#
|
|
171 |
# Private methods
|
|
172 |
#
|
|
173 |
|
|
174 |
sub CompareSizes {
|
|
175 |
my $self = shift;
|
|
176 |
my $localsize = shift;
|
|
177 |
my $remotesize = shift;
|
|
178 |
my $comp = shift; # comp and ver are just used for error messages
|
|
179 |
my $ver = shift;
|
|
180 |
|
|
181 |
my $diff = abs ($remotesize - $localsize);
|
|
182 |
if ($diff == 0) {
|
|
183 |
return; # disappointingly rare
|
|
184 |
} elsif ($diff <=8) {
|
|
185 |
print "Warning: the size of the exported $comp $ver is slightly different ($remotesize) to the local copy ($localsize): difference $diff. This may be due to the way the remote site reports sizes, or the randomness of PGP encryption.\n" if ($self->{verbose});
|
|
186 |
} else {
|
|
187 |
die "Error: $comp $ver exported file size ($remotesize) differs from local copy ($localsize)\n";
|
|
188 |
}
|
|
189 |
}
|
|
190 |
|
|
191 |
sub SizeOfNewlyZippedFile {
|
|
192 |
my $self = shift;
|
|
193 |
my $comp = shift;
|
|
194 |
my $ver = shift;
|
|
195 |
|
|
196 |
my $tempDir = Utils::TempDir();
|
|
197 |
my $zipName = "$tempDir/$comp$ver.zip";
|
|
198 |
die "Error: newly zipped file \"$zipName\" for $comp $ver didn't exist\n" unless -e $zipName;
|
|
199 |
return -s $zipName;
|
|
200 |
}
|
|
201 |
|
|
202 |
sub SizeOfRemoteFile {
|
|
203 |
my $self = shift;
|
|
204 |
my $comp = shift;
|
|
205 |
my $ver = shift;
|
|
206 |
|
|
207 |
die "No component name provided to SizeOfRemoteFile" unless $comp;
|
|
208 |
die "No version for $comp provided to SizeOfRemoteFile" unless $ver;
|
|
209 |
|
|
210 |
my $remoteFile = $self->PathData->RemoteArchivePathForExistingComponent($comp, $ver, $self->{remoteSite})."/$comp$ver.zip";
|
|
211 |
die "Error: $comp $ver didn't exist on the remote site\n" unless $remoteFile;
|
|
212 |
return $self->{remoteSite}->FileSize($remoteFile);
|
|
213 |
}
|
|
214 |
|
|
215 |
sub EncryptReleaseFiles {
|
|
216 |
my $self = shift;
|
|
217 |
my $comp = shift;
|
|
218 |
my $ver = shift;
|
|
219 |
my $relDir = shift;
|
|
220 |
my $tempDir = Utils::TempDir();
|
|
221 |
|
|
222 |
my %excludedKeys;
|
|
223 |
@excludedKeys{@{$self->{exportData}->AllPgpKeys()}} = ();
|
|
224 |
|
|
225 |
#encrypt release files using pgp keys from export table and reltools.ini
|
|
226 |
opendir(RELDIR, $relDir) or die "Error: Cannot open $relDir\n";
|
|
227 |
while (defined(my $file = readdir RELDIR)) {
|
|
228 |
my @pgpKeys;
|
|
229 |
next if ($file =~ /^\.\.?$/);
|
|
230 |
|
|
231 |
if ($file =~ /^(exports)([a-z])\.zip$/i or $file =~ /^(exports)([a-z])\.txt$/i) {
|
|
232 |
@pgpKeys = @{$self->{exportData}->PgpKeysForExports($comp, $2)};
|
|
233 |
}
|
|
234 |
elsif ($file =~ /^(source)([a-z])\.zip$/i or $file =~ /^(source)([a-z])\.txt$/i) {
|
|
235 |
if($self->{excludeSource}) {
|
|
236 |
print "Skipping the encryption of source file $file (in directory \"$relDir\")\n" if ($self->{verbose});
|
|
237 |
next;
|
|
238 |
}
|
|
239 |
@pgpKeys = @{$self->{exportData}->PgpKeysForSource($comp, $2)};
|
|
240 |
}
|
|
241 |
elsif ( $file =~ /^reldata$/i ){
|
|
242 |
@pgpKeys = @{$self->{exportData}->PgpKeysForRelData($comp)};
|
|
243 |
}
|
|
244 |
elsif ($file =~ /^binaries.zip$/i or $self->IsBinaryZipRequired($comp, $ver, $file)) {
|
|
245 |
@pgpKeys = @{$self->{exportData}->PgpKeysForBinaries($comp)};
|
|
246 |
}
|
|
247 |
else {
|
|
248 |
die "Error: Unexpected release file \"$file\" in $comp $ver\n";
|
|
249 |
}
|
|
250 |
|
|
251 |
#do the encryption
|
|
252 |
if (@pgpKeys) {
|
|
253 |
push @pgpKeys, @{$self->{iniData}->PgpEncryptionKeys}; #encrypt with users keys aswell
|
|
254 |
print "Encrypting \"$file\" (in directory \"$relDir\") to keys @pgpKeys\n" if ($self->{verbose});
|
|
255 |
# Warning: productisation scripts may depend on the format of the above line.
|
|
256 |
$self->{crypt}->Encrypt("$relDir/$file", "$tempDir/$file.pgp", \@pgpKeys) unless ($self->{dummy});
|
|
257 |
|
|
258 |
#Remove the keys that have been used from the list of keys which have been excluded for this release
|
|
259 |
delete @excludedKeys{@pgpKeys};
|
|
260 |
}
|
|
261 |
}
|
|
262 |
closedir(RELDIR);
|
|
263 |
|
|
264 |
# DEF104279 The exclude keyword in the CBR export table breaks the exported archive.
|
|
265 |
# All keys which are not used for this release will be used to encrypt a file called exclude.txt
|
|
266 |
# When the release is imported it will not give the unable to decrypt any part error
|
|
267 |
# as it can decrypt the exclude.txt file.
|
|
268 |
|
|
269 |
if (keys %excludedKeys) {
|
|
270 |
# Create an exclude.txt in the reldir
|
|
271 |
open (EXCLUDE, ">$tempDir/exclude.txt");
|
|
272 |
print EXCLUDE "If you can decrypt this file then this release has been excluded for you based on your PGP key\n";
|
|
273 |
close EXCLUDE;
|
|
274 |
|
|
275 |
$self->{crypt}->Encrypt("$tempDir/exclude.txt", "$tempDir/exclude.txt.pgp", \@{[keys %excludedKeys]}) unless ($self->{dummy});
|
|
276 |
}
|
|
277 |
}
|
|
278 |
|
|
279 |
sub IsBinaryZipRequired {
|
|
280 |
my $self = shift;
|
|
281 |
my $comp = shift;
|
|
282 |
my $ver = shift;
|
|
283 |
my $zip = shift;
|
|
284 |
|
|
285 |
# If the required_binaries keyword isn't used, we need all builds
|
|
286 |
return 1 unless defined $self->{iniData}->RequiredBinaries($comp);
|
|
287 |
|
|
288 |
unless ($zip =~ /^binaries_(.*)\.zip$/) {
|
|
289 |
die "Error: Unexpected file \"$zip\" in $comp $ver\n";
|
|
290 |
}
|
|
291 |
my $category = $1;
|
|
292 |
foreach my $requiredBinary (@{$self->{iniData}->RequiredBinaries($comp)}) {
|
|
293 |
if ($category =~ /^$requiredBinary/) {
|
|
294 |
return 1;
|
|
295 |
}
|
|
296 |
}
|
|
297 |
return 0;
|
|
298 |
}
|
|
299 |
|
|
300 |
sub ZipEncryptedReleaseFiles {
|
|
301 |
my $self = shift;
|
|
302 |
my $comp = shift;
|
|
303 |
my $ver = shift;
|
|
304 |
|
|
305 |
if ($self->{verbose}) {
|
|
306 |
print "Zipping encrypted files to $comp$ver.zip ...\n";
|
|
307 |
}
|
|
308 |
|
|
309 |
#build up list of pgp encrypted files in TEMP_DIR
|
|
310 |
my $tempDir = Utils::TempDir();
|
|
311 |
opendir(TEMPDIR, $tempDir);
|
|
312 |
my @encryptedFiles = grep {/\.pgp$/} readdir TEMPDIR;
|
|
313 |
closedir(TEMPDIR);
|
|
314 |
|
|
315 |
unless (@encryptedFiles || $self->{dummy}) {
|
|
316 |
die "Error: No encrypted files exist in $tempDir\n";
|
|
317 |
}
|
|
318 |
|
|
319 |
#zip list of pgp encrypted files (archive only, no compression)
|
|
320 |
my $origDir = getcwd();
|
|
321 |
chdir($tempDir);
|
|
322 |
my $zipName = "$tempDir/$comp$ver.zip";
|
|
323 |
print "Zipping @encryptedFiles to \"$zipName\"\n";
|
|
324 |
eval {
|
|
325 |
Utils::ZipList($zipName, \@encryptedFiles, $self->{verbose} > 1, 1) unless ($self->{dummy});
|
|
326 |
};
|
|
327 |
chdir ($origDir);
|
|
328 |
if ($@) {
|
|
329 |
die $@;
|
|
330 |
}
|
|
331 |
}
|
|
332 |
|
|
333 |
sub SendZippedReleaseFile {
|
|
334 |
my $self = shift;
|
|
335 |
my $comp = shift;
|
|
336 |
my $ver = shift;
|
|
337 |
my $localdir = shift;
|
|
338 |
|
|
339 |
my $localFile = Utils::TempDir()."/$comp$ver.zip";
|
|
340 |
my $remoteFile = $self->PathData->RemoteArchivePathForExportingComponent($comp, $ver, $localdir, $self->{remoteSite})."/$comp$ver.zip";
|
|
341 |
|
|
342 |
print "Sending \"$localFile\" to \"$remoteFile\"\n" if ($self->{verbose});
|
|
343 |
$self->{remoteSite}->SendFile($localFile, $remoteFile) unless ($self->{dummy});
|
|
344 |
}
|
|
345 |
|
|
346 |
sub SendLogFile {
|
|
347 |
my $self = shift;
|
|
348 |
my $comp = shift;
|
|
349 |
my $ver = shift;
|
|
350 |
|
|
351 |
|
|
352 |
my $localLogFile = Utils::TempDir()."/$comp$ver.log";
|
|
353 |
my $remoteLogFile = $self->{iniData}->RemoteLogsDir($comp)."/$comp$ver.log";
|
|
354 |
|
|
355 |
if ($self->{verbose}) {
|
|
356 |
print "Sending $comp $ver log file to remote site \"$remoteLogFile\"\n";
|
|
357 |
}
|
|
358 |
|
|
359 |
return if ($self->{dummy});
|
|
360 |
|
|
361 |
#create empty log file
|
|
362 |
open LOG, ">$localLogFile" or die "Error: Cannot open $localLogFile for writing\n";
|
|
363 |
close LOG;
|
|
364 |
|
|
365 |
#send log file to the remote site
|
|
366 |
$self->{remoteSite}->SendFile($localLogFile, $remoteLogFile);
|
|
367 |
|
|
368 |
unlink $localLogFile;
|
|
369 |
}
|
|
370 |
|
|
371 |
1;
|
|
372 |
|
|
373 |
__END__
|
|
374 |
|
|
375 |
=head1 NAME
|
|
376 |
|
|
377 |
RelTransfer::Export.pm - Export releases to the remote site
|
|
378 |
|
|
379 |
=head1 SYNOPSIS
|
|
380 |
|
|
381 |
use RelTransfer::Export;
|
|
382 |
|
|
383 |
$exporter = RelTransfer::Export->New(ini_data => $iniData,
|
|
384 |
force => 1;
|
|
385 |
verbose => 1);
|
|
386 |
|
|
387 |
$exporter->TransferRelease('componentname', 'componentversion');
|
|
388 |
|
|
389 |
=head1 DESCRIPTION
|
|
390 |
|
|
391 |
Implements the abstract TransferRelease method from the C<RelTransfer> base class module which transfers a release from the local archive to the remote site.
|
|
392 |
|
|
393 |
=head1 INTERFACE
|
|
394 |
|
|
395 |
=head2 New
|
|
396 |
|
|
397 |
Passed an argument list in the form of hash key value pairs. The supported arguments are...
|
|
398 |
|
|
399 |
ini_data => $iniData_object
|
|
400 |
force => $force_integer
|
|
401 |
verbose => $verbosity_integer
|
|
402 |
|
|
403 |
Returns a reference to a C<RelTransfer::Export> object.
|
|
404 |
|
|
405 |
=head2 TransferRelease
|
|
406 |
|
|
407 |
Passed a component name and version number. Performs the following steps:
|
|
408 |
|
|
409 |
=over 4
|
|
410 |
|
|
411 |
=item *
|
|
412 |
|
|
413 |
Check to see if the release can or needs to be exported. If the component does not exist in the users export table no attempt will be made to export it. If the component is listed in the export table but the release already exists on the remote site then, again, no attempt will be made to export it (unless the C<force> member variable is set to a nonzero value)
|
|
414 |
|
|
415 |
=item *
|
|
416 |
|
|
417 |
Encrypt the release files (ie source zips, binaries zip and reldata file). The keys used to encrypt the files depend on the data stored in the users export table
|
|
418 |
|
|
419 |
=item *
|
|
420 |
|
|
421 |
Create a zip archive (without compression) of the encrypted files
|
|
422 |
|
|
423 |
=item *
|
|
424 |
|
|
425 |
Send the release zip file to the remote site
|
|
426 |
|
|
427 |
=item *
|
|
428 |
|
|
429 |
If a remote logs dir is defined in the F<reltools.ini> file send an empty log file to the remote site
|
|
430 |
|
|
431 |
=back
|
|
432 |
|
|
433 |
=head2 ExamineExportedRelease
|
|
434 |
|
|
435 |
This goes through most of the same stages above, but instead of actually transferring the zip file, it will ensure that the size of the existing file on the remote site matches that which is expected.
|
|
436 |
|
|
437 |
=head1 KNOWN BUGS
|
|
438 |
|
|
439 |
None
|
|
440 |
|
|
441 |
=head1 COPYRIGHT
|
|
442 |
|
|
443 |
Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
|
|
444 |
All rights reserved.
|
|
445 |
This component and the accompanying materials are made available
|
|
446 |
under the terms of the License "Eclipse Public License v1.0"
|
|
447 |
which accompanies this distribution, and is available
|
|
448 |
at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
|
449 |
|
|
450 |
Initial Contributors:
|
|
451 |
Nokia Corporation - initial contribution.
|
|
452 |
|
|
453 |
Contributors:
|
|
454 |
|
|
455 |
Description:
|
|
456 |
|
|
457 |
|
|
458 |
=cut
|