You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openoffice.apache.org by af...@apache.org on 2013/12/13 13:05:16 UTC
svn commit: r1550699 [2/2] - in /openoffice/trunk/main:
instsetoo_native/util/ solenv/bin/ solenv/bin/modules/installer/
solenv/bin/modules/installer/patch/ solenv/bin/modules/installer/windows/
Modified: openoffice/trunk/main/solenv/bin/patch_tool.pl
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/solenv/bin/patch_tool.pl?rev=1550699&r1=1550698&r2=1550699&view=diff
==============================================================================
--- openoffice/trunk/main/solenv/bin/patch_tool.pl (original)
+++ openoffice/trunk/main/solenv/bin/patch_tool.pl Fri Dec 13 12:05:15 2013
@@ -38,6 +38,8 @@ use installer::patch::Msi;
use installer::patch::ReleasesList;
use installer::patch::Version;
+#use Carp::Always;
+
use strict;
@@ -64,6 +66,10 @@ use strict;
The version that is to be patched.
--target-version <major>.<minor>.<micro>
The version after the patch has been applied.
+ --language <language-code>
+ Language of the installation sets.
+ --package-format
+ Only the package format 'msi' is supported at the moment.
=head1 DESCRIPTION
@@ -80,7 +86,6 @@ use strict;
=cut
-# my $ImageFamily = "MNPapps";
# The ImageFamily name has to have 1-8 alphanumeric characters.
my $ImageFamily = "AOO";
my $SourceImageName = "Source";
@@ -90,21 +95,26 @@ my $TargetImageName = "Target";
sub ProcessCommandline ()
{
- my $arguments = {
+ my $context = {
'product-name' => undef,
'output-path' => undef,
'data-path' => undef,
'lst-file' => undef,
'source-version' => undef,
- 'target-version' => undef};
+ 'target-version' => undef,
+ 'language' => undef,
+ 'package-format' => undef
+ };
if ( ! GetOptions(
- "product-name=s", \$arguments->{'product-name'},
- "output-path=s", \$arguments->{'output-path'},
- "data-path=s" => \$arguments->{'data-path'},
- "lst-file=s" => \$arguments->{'lst-file'},
- "source-version:s" => \$arguments->{'source-version'},
- "target-version:s" => \$arguments->{'target-version'}
+ "product-name=s", \$context->{'product-name'},
+ "output-path=s", \$context->{'output-path'},
+ "data-path=s" => \$context->{'data-path'},
+ "lst-file=s" => \$context->{'lst-file'},
+ "source-version:s" => \$context->{'source-version'},
+ "target-version:s" => \$context->{'target-version'},
+ "language=s" => \$context->{'language'},
+ "package-format=s" => \$context->{'package-format'}
))
{
pod2usage(2);
@@ -112,14 +122,9 @@ sub ProcessCommandline ()
# Only the command should be left in @ARGV.
pod2usage(2) unless scalar @ARGV == 1;
- $arguments->{'command'} = shift @ARGV;
-
- # At the moment we only support patches on windows. When this
- # is extended in the future we need the package format as an
- # argument.
- $arguments->{'package-format'} = "msi";
+ $context->{'command'} = shift @ARGV;
- return $arguments;
+ return $context;
}
@@ -181,46 +186,28 @@ sub ProvideInstallationSets ($$)
-sub GetLanguages ()
+sub IsLanguageValid ($$$)
{
- # The set of languages is taken from the WITH_LANG environment variable.
- # If that is missing or is empty then the default 'en-US' is used instead.
- my @languages = ("en-US");
- my $with_lang = $ENV{'WITH_LANG'};
- if (defined $with_lang && $with_lang ne "")
- {
- @languages = split(/\s+/, $with_lang);
- }
- return @languages;
-}
-
-
+ my ($context, $release_data, $language) = @_;
+ my $normalized_language = installer::languages::get_normalized_language($language);
-sub FindValidLanguages ($$$)
-{
- my ($context, $release_data, $languages) = @_;
-
- my @valid_languages = ();
- foreach my $language (@$languages)
+ if ( ! ProvideInstallationSets($context, $language))
{
- if ( ! ProvideInstallationSets($context, $language))
- {
- installer::logger::PrintError(" '%s' has no target installation set\n", $language);
- }
- elsif ( ! defined $release_data->{$language})
- {
- installer::logger::PrintError(" '%s' is not a released language for version %s\n",
- $language,
- $context->{'source-version'});
- }
- else
- {
- push @valid_languages, $language;
- }
+ installer::logger::PrintError(" '%s' has no target installation set\n", $language);
+ return 0;
+ }
+ elsif ( ! defined $release_data->{$normalized_language})
+ {
+ installer::logger::PrintError(" '%s' is not a released language for version %s\n",
+ $language,
+ $context->{'source-version'});
+ return 0;
+ }
+ else
+ {
+ return 1;
}
-
- return @valid_languages;
}
@@ -327,6 +314,19 @@ sub DetermineVersions ($$)
}
$context->{'source-version'} = $last_release;
}
+
+ if (defined $context->{'source-version'})
+ {
+ $context->{'source-version-dash'} = installer::patch::Version::ArrayToDirectoryName(
+ installer::patch::Version::StringToNumberArray(
+ $context->{'source-version'}));
+ }
+ if (defined $context->{'target-version'})
+ {
+ $context->{'target-version-dash'} = installer::patch::Version::ArrayToDirectoryName(
+ installer::patch::Version::StringToNumberArray(
+ $context->{'target-version'}));
+ }
}
@@ -352,7 +352,7 @@ sub CheckUpgradeCode($$)
}
else
{
- $installer::logger::Info->printf("OK: UpgradeCode values are identical\n");
+ $installer::logger::Info->printf("OK: UpgradeCode values are different\n");
return 1;
}
}
@@ -382,7 +382,7 @@ sub CheckProductCode($$)
}
else
{
- $installer::logger::Info->printf("OK: ProductCode properties differ\n");
+ $installer::logger::Info->printf("OK: ProductCodes are identical\n");
return 1;
}
}
@@ -501,25 +501,60 @@ sub CheckNewFiles($$)
# Create data structures for fast lookup.
my %source_file_map = map {$_->GetValue("File") => $_} @{$source_file_table->GetAllRows()};
- my @target_files = map {$_->GetValue("File")} @{$target_file_table->GetAllRows()};
+ my %target_files_map = map {$_->GetValue("File") => $_} @{$target_file_table->GetAllRows()};
# Search for added files (files in target that where not in source).
- my $added_file_count = 0;
- foreach my $uniquename (@target_files)
+ my @added_files = ();
+ foreach my $uniquename (keys %target_files_map)
{
if ( ! defined $source_file_map{$uniquename})
{
- ++$added_file_count;
+ push @added_files, $target_files_map{$uniquename};
}
}
- if ($added_file_count > 0)
+ if (scalar @added_files > 0)
{
- $installer::logger::Info->printf("Warning: %d files have been added\n", $added_file_count);
+ $installer::logger::Info->printf("Warning: %d files have been added\n", scalar @added_files);
- $installer::logger::Info->printf("Check for new files being part of new components is not yet implemented\n");
-
- return 1;
+ # Prepare component tables and hashes.
+ my $source_component_table = $source_msi->GetTable("Component");
+ my $target_component_table = $target_msi->GetTable("Component");
+ die unless defined $source_component_table && defined $target_component_table;
+ my %source_component_map = map {$_->GetValue('Component') => $_} @{$source_component_table->GetAllRows()};
+ my %target_component_map = map {$_->GetValue('Component') => $_} @{$target_component_table->GetAllRows()};
+
+ my @new_files_with_existing_components = ();
+ foreach my $target_file_row (@added_files)
+ {
+ $installer::logger::Info->printf(" %s (%s)\n",
+ $target_file_row->GetValue("FileName"),
+ $target_file_row->GetValue("File"));
+
+ # Get target component for target file.
+ my $target_component = $target_file_row->GetValue('Component_');
+
+ # Check that the component is not part of the source components.
+ if (defined $source_component_map{$target_component})
+ {
+ push @new_files_with_existing_components, $target_file_row;
+ }
+ }
+
+ if (scalar @new_files_with_existing_components > 0)
+ {
+ $installer::logger::Info->printf(
+ "Error: %d new files have existing components (which must also be new)\n",
+ scalar @new_files_with_existing_components);
+ return 0;
+ }
+ else
+ {
+ $installer::logger::Info->printf(
+ "OK: all %d new files also have new components\n",
+ scalar @added_files);
+ return 1;
+ }
}
else
{
@@ -531,13 +566,96 @@ sub CheckNewFiles($$)
-=head2 CheckComponentSets($source_msi, $target_msi)
+=head2 CheckFeatureSets($source_msi, $target_msi)
+
+ Features must not be removed but can be added.
+ Parent features of new features also have to be new.
+
+=cut
+sub CheckFeatureSets($$)
+{
+ my ($source_msi, $target_msi) = @_;
+
+ # Get the 'Feature' tables.
+ my $source_feature_table = $source_msi->GetTable("Feature");
+ my $target_feature_table = $target_msi->GetTable("Feature");
+
+ # Create data structures for fast lookup.
+ my %source_feature_map = map {$_->GetValue("Feature") => $_} @{$source_feature_table->GetAllRows()};
+ my %target_feature_map = map {$_->GetValue("Feature") => $_} @{$target_feature_table->GetAllRows()};
+
+ # Check that no feature has been removed.
+ my @removed_features = ();
+ foreach my $feature_name (keys %source_feature_map)
+ {
+ if ( ! defined $target_feature_map{$feature_name})
+ {
+ push @removed_features, $feature_name;
+ }
+ }
+ if (scalar @removed_features > 0)
+ {
+ # There are removed features.
+ $installer::logger::Info->printf(
+ "Error: %d features have been removed:\n",
+ scalar @removed_features);
+ $installer::logger::Info->printf(" %s\n", join(", ", @removed_features));
+ return 0;
+ }
+
+ # Check that added features belong to new parent features.
+ my @added_features = ();
+ foreach my $feature_name (keys %target_feature_map)
+ {
+ if ( ! defined $source_feature_map{$feature_name})
+ {
+ push @added_features, $feature_name;
+ }
+ }
+
+ if (scalar @added_features > 0)
+ {
+ $installer::logger::Info->printf("Warning: %d features have been addded\n", scalar @added_features);
+
+ my @new_features_with_existing_parents = ();
+ foreach my $new_feature (@added_features)
+ {
+ my $target_feature = $target_feature_map{$new_feature};
+ if (defined $source_feature_map{$target_feature->{'Feature_Parent'}})
+ {
+ push @new_features_with_existing_parents, $target_feature;
+ }
+ }
+
+ if (scalar @new_features_with_existing_parents > 0)
+ {
+ $installer::logger::Info->printf(
+ "Error: %d new features have existing parents (which also must be new)\n",
+ scalar @new_features_with_existing_parents);
+ return 0;
+ }
+ else
+ {
+ $installer::logger::Info->printf(
+ "OK: parents of all new features are also new\n");
+ return 1;
+ }
+ }
+
+ $installer::logger::Info->printf("OK: feature sets in source and target are compatible\n");
+ return 1;
+}
+
+
+
+
+=head2 CheckRemovedComponents($source_msi, $target_msi)
Components must not be removed but can be added.
Features of added components have also to be new.
=cut
-sub CheckComponentSets($$)
+sub CheckRemovedComponents ($$)
{
my ($source_msi, $target_msi) = @_;
@@ -558,7 +676,12 @@ sub CheckComponentSets($$)
push @removed_components, $componentname;
}
}
- if (scalar @removed_components > 0)
+ if (scalar @removed_components == 0)
+ {
+ $installer::logger::Info->printf("OK: no removed components\n");
+ return 1;
+ }
+ else
{
# There are removed components.
@@ -587,48 +710,115 @@ sub CheckComponentSets($$)
return 0;
}
}
+}
+
+
+
+
+sub GetTableAndMap ($$$)
+{
+ my ($msi, $table_name, $index_column) = @_;
+
+ my $table = $msi->GetTable($table_name);
+ my %map = map {$_->GetValue($index_column) => $_} @{$table->GetAllRows()};
+
+ return ($table, \%map);
+}
+
+
+=head2 CheckAddedComponents($source_msi, $target_msi)
+
+ Components can be added.
+ Features of added components have also to be new.
+
+=cut
+sub CheckAddedComponents ($$)
+{
+ my ($source_msi, $target_msi) = @_;
+
+ # Get the 'Component' tables and maps.
+ my ($source_component_table, $source_component_map)
+ = GetTableAndMap($source_msi, "Component", "Component");
+ my ($target_component_table, $target_component_map)
+ = GetTableAndMap($target_msi, "Component", "Component");
# Check that added components belong to new features.
my @added_components = ();
- foreach my $componentname (keys %target_component_map)
+ foreach my $componentname (keys %$target_component_map)
{
- if ( ! defined $source_component_map{$componentname})
+ if ( ! defined $source_component_map->{$componentname})
{
push @added_components, $componentname;
}
}
- if (scalar @added_components > 0)
+ if (scalar @added_components == 0)
{
- # Check if any of them is not a registry component.
- my $is_file_component_removed = 0;
- foreach my $componentname (@removed_components)
- {
- if ($componentname !~ /^registry/)
- {
- $is_file_component_removed = 1;
- }
- }
-
- if ($is_file_component_removed)
- {
- $installer::logger::Info->printf(
- "Warning: %d components have been addded\n",
- scalar @added_components);
- $installer::logger::Info->printf(
- "Test for new components belonging to new features has not yet been implemented\n");
- return 0;
- }
- else
- {
- $installer::logger::Info->printf(
- "Warning: %d components have been addded, all of them registry components\n",
- scalar @added_components);
- }
+ $installer::logger::Info->printf("OK: no new components\n");
+ return 1;
}
+ else
+ {
+ $installer::logger::Info->printf(
+ "Warning: %d components have been addded\n",
+ scalar @added_components);
+
+ # Check that the referencing features are also new.
+ my $target_feature_component_table = $target_msi->GetTable("FeatureComponents");
+
+ my $error = 0;
+ foreach my $component_name (@added_components)
+ {
+ my @feature_names = ();
+ foreach my $feature_component_row (@{$target_feature_component_table->GetAllRows()})
+ {
+ if ($feature_component_row->GetValue("Component_") eq $component_name)
+ {
+ my $feature_name = $feature_component_row->GetValue("Feature_");
+ push @feature_names, $feature_name;
+ }
+ }
+ if (scalar @feature_names == 0)
+ {
+ $installer::logger::Info->printf("Error: no feature found for component '%s'\n", $component_name);
+ $error = 1;
+ }
+ else
+ {
+ # Check that the referenced features are new and have new parents (if they have parents).
+ my ($source_feature_table, $source_feature_map)
+ = GetTableAndMap($source_msi, "Feature", "Feature");
+ my ($target_feature_table, $target_feature_map)
+ = GetTableAndMap($target_msi, "Feature", "Feature");
+ foreach my $feature_name (@feature_names)
+ {
+ $installer::logger::Info->printf(" component '%s' -> feature '%s'\n",
+ $component_name,
+ $feature_name);
+ my $source_feature_row = $source_feature_map->{$feature_name};
+ if (defined $source_feature_row)
+ {
+ $installer::logger::Info->printf("Warning(Error?): feature of new component is not new\n");
+ $error = 1;
+ }
+ else
+ {
+ # Feature is new. Check that the parent feature is also new.
+ my $target_feature_row = $target_feature_map->{$feature_name};
+ my $parent_feature_name = $target_feature_row->GetValue("Feature_Parent");
+ if ($parent_feature_name ne "" && defined $source_feature_map->{$parent_feature_name})
+ {
+ $installer::logger::Info->printf("Warning(Error?): parent feature of new component is not new\n");
+ $error = 1;
+ }
+ }
+ }
+ }
+ }
- $installer::logger::Info->printf("OK: component sets in source and target are compatible\n");
- return 1;
+# return !$error;
+ return 1;
+ }
}
@@ -962,6 +1152,131 @@ sub CheckComponentKeyPath ($$)
+sub GetMissingReferences ($$$$$)
+{
+ my ($table, $key, $map, $what, $report_key) = @_;
+
+ my @missing_references = ();
+
+ foreach my $row (@{$table->GetAllRows()})
+ {
+ my $value = $row->GetValue($key);
+ if ($value ne "" && ! defined $map->{$value})
+ {
+ push @missing_references, [$what, $row->GetValue($report_key), $value];
+ }
+ }
+
+ return @missing_references;
+}
+
+
+
+
+=head CheckAllReferences ($msi)
+
+ Check references from files and registry entries to components,
+ from components to features, and between features.
+
+=cut
+
+sub CheckAllReferences ($)
+{
+ my ($msi) = @_;
+
+ # Set up tables and maps for easy iteration and fast lookups.
+
+ my $feature_table = $msi->GetTable("Feature");
+ my $component_table = $msi->GetTable("Component");
+ my $feature_component_table = $msi->GetTable("FeatureComponents");
+ my $file_table = $msi->GetTable("File");
+ my $registry_table = $msi->GetTable("Registry");
+ my $directory_table = $msi->GetTable("Directory");
+
+ my %feature_map = map {$_->GetValue("Feature") => $_} @{$feature_table->GetAllRows()};
+ my %component_map = map {$_->GetValue("Component") => $_} @{$component_table->GetAllRows()};
+ my %directory_map = map {$_->GetValue("Directory") => $_} @{$directory_table->GetAllRows()};
+
+ my @missing_references = ();
+
+ # Check references from files and registry entries to components.
+ push @missing_references, GetMissingReferences(
+ $file_table,
+ "Component_",
+ \%component_map,
+ "file->component",
+ "File");
+ push @missing_references, GetMissingReferences(
+ $registry_table,
+ "Component_",
+ \%component_map,
+ "registry->component",
+ "Registry");
+
+ # Check references between features and components.
+ push @missing_references, GetMissingReferences(
+ $feature_component_table,
+ "Feature_",
+ \%feature_map,
+ "component->feature",
+ "Component_");
+ push @missing_references, GetMissingReferences(
+ $feature_component_table,
+ "Component_",
+ \%component_map,
+ "feature->component",
+ "Feature_");
+
+ # Check references between features.
+ push @missing_references, GetMissingReferences(
+ $feature_table,
+ 'Feature_Parent',
+ \%feature_map,
+ "feature->feature",
+ 'Feature');
+
+ # Check references between directories.
+ push @missing_references, GetMissingReferences(
+ $directory_table,
+ 'Directory_Parent',
+ \%directory_map,
+ "directory->directory",
+ 'Directory');
+
+ # Check references from components to directories.
+ push @missing_references, GetMissingReferences(
+ $component_table,
+ 'Directory_',
+ \%directory_map,
+ "component->directory",
+ 'Component');
+
+ # Check references from components to files (via the .
+
+ # Report the result.
+ if (scalar @missing_references > 0)
+ {
+ $installer::logger::Info->printf("Error: there are %d missing references\n", scalar @missing_references);
+ foreach my $reference (@missing_references)
+ {
+ $installer::logger::Info->printf(" %s : %s -> %s\n",
+ $reference->[0],
+ $reference->[1],
+ $reference->[2]);
+ }
+ return 0;
+ }
+ else
+ {
+ $installer::logger::Info->printf("OK: all references are OK\n");
+ return 1;
+
+ }
+}
+
+
+
+
sub Check ($$$$)
{
my ($source_msi, $target_msi, $variables, $product_name) = @_;
@@ -971,22 +1286,37 @@ sub Check ($$$$)
my $result = 1;
- $result &&= CheckUpgradeCode($source_msi, $target_msi);
- $result &&= CheckProductCode($source_msi, $target_msi);
- $result &&= CheckBuildIdCode($source_msi, $target_msi);
- $result &&= CheckProductName($source_msi, $target_msi);
- $result &&= CheckRemovedFiles($source_msi, $target_msi);
- $result &&= CheckNewFiles($source_msi, $target_msi);
- $result &&= CheckComponentSets($source_msi, $target_msi);
- $result &&= CheckComponentValues($source_msi, $target_msi, $variables);
- $result &&= CheckFileSequence($source_msi, $target_msi);
- $result &&= CheckFileSequenceUnique($source_msi, $target_msi);
- $result &&= CheckFileSequenceHoles($source_msi, $target_msi);
- $result &&= CheckRegistryItems($source_msi, $target_msi, $product_name);
- $result &&= CheckComponentKeyPath($source_msi, $target_msi);
+ # Using &= below to avoid lazy evaluation. Even if there are errors, all checks shall be run.
+ $result &= CheckUpgradeCode($source_msi, $target_msi);
+ $result &= CheckProductCode($source_msi, $target_msi);
+ $result &= CheckBuildIdCode($source_msi, $target_msi);
+ $result &= CheckProductName($source_msi, $target_msi);
+ $result &= CheckRemovedFiles($source_msi, $target_msi);
+ $result &= CheckNewFiles($source_msi, $target_msi);
+ $result &= CheckFeatureSets($source_msi, $target_msi);
+ $result &= CheckRemovedComponents($source_msi, $target_msi);
+ $result &= CheckAddedComponents($source_msi, $target_msi);
+ $result &= CheckComponentValues($source_msi, $target_msi, $variables);
+ $result &= CheckFileSequence($source_msi, $target_msi);
+ $result &= CheckFileSequenceUnique($source_msi, $target_msi);
+ $result &= CheckFileSequenceHoles($source_msi, $target_msi);
+ $result &= CheckRegistryItems($source_msi, $target_msi, $product_name);
+ $result &= CheckComponentKeyPath($source_msi, $target_msi);
+ $result &= CheckAllReferences($target_msi);
$installer::logger::Info->decrease_indentation();
+ if ($result)
+ {
+ $installer::logger::Info->printf("OK: Source and target releases are compatible.\n");
+ }
+ else
+ {
+ $installer::logger::Info->printf("Error: Source and target releases are not compatible.\n");
+ $installer::logger::Info->printf(" => Can not create patch.\n");
+ $installer::logger::Info->printf(" Did you create the target installation set with 'release=t' ?\n");
+ }
+
return $result;
}
@@ -1232,8 +1562,8 @@ sub CreatePcp ($$$$$$%)
}
my $pcp = installer::patch::Msi->new(
$pcp_filename,
- undef,
- undef,
+ $target_msi->{'version'},
+ $target_msi->{'is_current_version'},
$language,
$context->{'product-name'});
@@ -1281,7 +1611,6 @@ sub ShowLog ($$$$)
"/o", "'".installer::patch::Tools::ToWindowsPath($destination_path)."'");
printf("running command $command\n");
my $response = qx($command);
- printf("response is '%s'\n", $response);
my @candidates = glob($destination_path . "/Details*");
foreach my $candidate (@candidates)
{
@@ -1306,8 +1635,8 @@ sub ShowLog ($$$$)
close $in;
close $out;
- my $URL = $new_name;
- $URL =~ s/\/c\//c|\//;
+ my $URL = File::Spec->rel2abs($new_name);
+ $URL =~ s/\/cygdrive\/(.)\//$1|\//;
$URL =~ s/^(.):/$1|/;
$URL = "file:///". $URL;
$installer::logger::Info->printf("open %s in your browser to see the log messages\n", $URL);
@@ -1344,13 +1673,17 @@ sub CreateMsp ($)
|| die ("can not create temporary path ".$temporary_msimsp_path);
}
$installer::logger::Info->printf("running msimsp.exe, that will take a while\n");
+ my $create_performance_log = 0;
my $command = join(" ",
"msimsp.exe",
"-s", "'".installer::patch::Tools::ToWindowsPath($pcp->{'filename'})."'",
"-p", "'".installer::patch::Tools::ToWindowsPath($pcp->{'msp_filename'})."'",
"-l", "'".installer::patch::Tools::ToWindowsPath($log_filename)."'",
"-f", "'".installer::patch::Tools::ToWindowsPath($temporary_msimsp_path)."'");
-# "-lp", MsiTools::ToEscapedWindowsPath($performance_log_filename),
+ if ($create_performance_log)
+ {
+ $command .= " -lp " . MsiTools::ToEscapedWindowsPath($performance_log_filename);
+ }
$installer::logger::Info->printf("running command %s\n", $command);
my $response = qx($command);
$installer::logger::Info->printf("response of msimsp is %s\n", $response);
@@ -1361,7 +1694,60 @@ sub CreateMsp ($)
# Show the log file that was created by the msimsp.exe command.
ShowLog($log_path, $log_filename, $log_basename, "msp creation");
- ShowLog($log_path, $performance_log_filename, $performance_log_basename, "msp creation perf");
+ if ($create_performance_log)
+ {
+ ShowLog($log_path, $performance_log_filename, $performance_log_basename, "msp creation perf");
+ }
+}
+
+
+sub ProvideMsis ($$$)
+{
+ my ($context, $variables, $language) = @_;
+
+ # 2a. Provide .msi and .cab files and unpack .cab for the source release.
+ $installer::logger::Info->printf("locating source package (%s)\n", $context->{'source-version'});
+ $installer::logger::Info->increase_indentation();
+ if ( ! installer::patch::InstallationSet::ProvideUnpackedCab(
+ $context->{'source-version'},
+ 0,
+ $language,
+ "msi",
+ $context->{'product-name'}))
+ {
+ die "could not provide unpacked .cab file";
+ }
+ my $source_msi = installer::patch::Msi->FindAndCreate(
+ $context->{'source-version'},
+ 0,
+ $language,
+ $context->{'product-name'});
+ die unless defined $source_msi;
+ die unless $source_msi->IsValid();
+ $installer::logger::Info->decrease_indentation();
+
+ # 2b. Provide .msi and .cab files and unpacked .cab for the target release.
+ $installer::logger::Info->printf("locating target package (%s)\n", $context->{'target-version'});
+ $installer::logger::Info->increase_indentation();
+ if ( ! installer::patch::InstallationSet::ProvideUnpackedCab(
+ $context->{'target-version'},
+ 1,
+ $language,
+ "msi",
+ $context->{'product-name'}))
+ {
+ die;
+ }
+ my $target_msi = installer::patch::Msi->FindAndCreate(
+ $context->{'target-version'},
+ 0,
+ $language,
+ $context->{'product-name'});
+ die unless defined $target_msi;
+ die unless $target_msi->IsValid();
+ $installer::logger::Info->decrease_indentation();
+
+ return ($source_msi, $target_msi);
}
@@ -1400,57 +1786,23 @@ sub CreatePatch ($$)
->{$context->{'package-format'}};
# 1. Determine the set of languages for which we can create patches.
- my @requested_languages = GetLanguages();
- my @valid_languages = FindValidLanguages($context, $release_data, \@requested_languages);
- $installer::logger::Info->printf("of the requested languages '%s' are valid: '%s'\n",
- join("', '", @requested_languages),
- join("', '", @valid_languages));
- foreach my $language (@valid_languages)
+ my $language = $context->{'language'};
+ my %no_ms_lang_locale_map = map {$_=>1} @installer::globals::noMSLocaleLangs;
+ if (defined $no_ms_lang_locale_map{$language})
{
- $installer::logger::Info->printf("processing language '%s'\n", $language);
- $installer::logger::Info->increase_indentation();
+ $language = "en-US_".$language;
+ }
- # 2a. Provide .msi and .cab files and unpacke .cab for the source release.
- $installer::logger::Info->printf("locating source package (%s)\n", $context->{'source-version'});
+ if ( ! IsLanguageValid($context, $release_data, $language))
+ {
+ $installer::logger::Info->printf("can not create patch for language '%s'\n", $language);
+ }
+ else
+ {
+ $installer::logger::Info->printf("processing language '%s'\n", $language);
$installer::logger::Info->increase_indentation();
- if ( ! installer::patch::InstallationSet::ProvideUnpackedCab(
- $context->{'source-version'},
- 0,
- $language,
- "msi",
- $context->{'product-name'}))
- {
- die "could not provide unpacked .cab file";
- }
- my $source_msi = installer::patch::Msi->FindAndCreate(
- $context->{'source-version'},
- 0,
- $language,
- $context->{'product-name'});
- die unless $source_msi->IsValid();
- $installer::logger::Info->decrease_indentation();
-
- # 2b. Provide .msi and .cab files and unpacke .cab for the target release.
- $installer::logger::Info->printf("locating target package (%s)\n", $context->{'target-version'});
- $installer::logger::Info->increase_indentation();
- if ( ! installer::patch::InstallationSet::ProvideUnpackedCab(
- $context->{'target-version'},
- 1,
- $language,
- "msi",
- $context->{'product-name'}))
- {
- die;
- }
- my $target_msi = installer::patch::Msi->FindAndCreate(
- $context->{'target-version'},
- 0,
- $language,
- $context->{'product-name'});
- die unless defined $target_msi;
- die unless $target_msi->IsValid();
- $installer::logger::Info->decrease_indentation();
+ my ($source_msi, $target_msi) = ProvideMsis($context, $variables, $language);
# Trigger reading of tables.
foreach my $table_name (("File", "Component", "Registry"))
@@ -1463,15 +1815,8 @@ sub CreatePatch ($$)
# 3. Check if the source and target msis fullfil all necessary requirements.
if ( ! Check($source_msi, $target_msi, $variables, $context->{'product-name'}))
{
- $installer::logger::Info->printf("Error: Source and target releases are not compatible.\n");
- $installer::logger::Info->printf(" => Can not create patch.\n");
- $installer::logger::Info->printf(" Did you create the target installation set with 'release=t' ?\n");
exit(1);
}
- else
- {
- $installer::logger::Info->printf("OK: Source and target releases are compatible.\n");
- }
# Provide the base path for creating .pcp and .mcp file.
my $msp_path = File::Spec->catfile(
@@ -1479,12 +1824,12 @@ sub CreatePatch ($$)
$context->{'product-name'},
"msp",
sprintf("%s_%s",
- installer::patch::Version::ArrayToDirectoryName(
- installer::patch::Version::StringToNumberArray(
- $source_msi->{'version'})),
- installer::patch::Version::ArrayToDirectoryName(
- installer::patch::Version::StringToNumberArray(
- $target_msi->{'version'}))),
+ installer::patch::Version::ArrayToDirectoryName(
+ installer::patch::Version::StringToNumberArray(
+ $source_msi->{'version'})),
+ installer::patch::Version::ArrayToDirectoryName(
+ installer::patch::Version::StringToNumberArray(
+ $target_msi->{'version'}))),
$language
);
File::Path::make_path($msp_path) unless -d $msp_path;
@@ -1508,6 +1853,58 @@ sub CreatePatch ($$)
+
+sub CheckPatchCompatability ($$)
+{
+ my ($context, $variables) = @_;
+
+ $installer::logger::Info->printf("patch will update product %s from %s to %s\n",
+ $context->{'product-name'},
+ $context->{'source-version'},
+ $context->{'target-version'});
+
+ my $release_data = installer::patch::ReleasesList::Instance()
+ ->{$context->{'source-version'}}
+ ->{$context->{'package-format'}};
+
+ # 1. Determine the set of languages for which we can create patches.
+ my $language = $context->{'language'};
+ my %no_ms_lang_locale_map = map {$_=>1} @installer::globals::noMSLocaleLangs;
+ if (defined $no_ms_lang_locale_map{$language})
+ {
+ $language = "en-US_".$language;
+ }
+
+ if ( ! IsLanguageValid($context, $release_data, $language))
+ {
+ $installer::logger::Info->printf("can not create patch for language '%s'\n", $language);
+ }
+ else
+ {
+ $installer::logger::Info->printf("processing language '%s'\n", $language);
+ $installer::logger::Info->increase_indentation();
+
+ my ($source_msi, $target_msi) = ProvideMsis($context, $variables, $language);
+
+ # Trigger reading of tables.
+ foreach my $table_name (("File", "Component", "Registry"))
+ {
+ $source_msi->GetTable($table_name);
+ $target_msi->GetTable($table_name);
+ $installer::logger::Info->printf("read %s table (source and target\n", $table_name);
+ }
+
+ # 3. Check if the source and target msis fullfil all necessary requirements.
+ if ( ! Check($source_msi, $target_msi, $variables, $context->{'product-name'}))
+ {
+ exit(1);
+ }
+ }
+}
+
+
+
+
=cut ApplyPatch ($context, $variables)
This is for testing only.
@@ -1522,7 +1919,6 @@ sub ApplyPatch ($$)
$context->{'product-name'},
$context->{'source-version'},
$context->{'target-version'});
- my @languages = GetLanguages();
my $source_version_dirname = installer::patch::Version::ArrayToDirectoryName(
installer::patch::Version::StringToNumberArray(
@@ -1531,41 +1927,45 @@ sub ApplyPatch ($$)
installer::patch::Version::StringToNumberArray(
$context->{'target-version'}));
- foreach my $language (@languages)
+ my $language = $context->{'language'};
+ my %no_ms_lang_locale_map = map {$_=>1} @installer::globals::noMSLocaleLangs;
+ if (defined $no_ms_lang_locale_map{$language})
{
- my $msp_filename = File::Spec->catfile(
- $context->{'output-path'},
- $context->{'product-name'},
- "msp",
- $source_version_dirname . "_" . $target_version_dirname,
- $language,
- "openoffice.msp");
- if ( ! -f $msp_filename)
- {
- $installer::logger::Info->printf("%s does not point to a valid file\n", $msp_filename);
- next;
- }
-
- my $log_path = File::Spec->catfile(dirname($msp_filename), "log");
- my $log_basename = "apply-msp";
- my $log_filename = File::Spec->catfile($log_path, $log_basename.".log");
+ $language = "en-US_".$language;
+ }
+
+ my $msp_filename = File::Spec->catfile(
+ $context->{'output-path'},
+ $context->{'product-name'},
+ "msp",
+ $source_version_dirname . "_" . $target_version_dirname,
+ $language,
+ "openoffice.msp");
+ if ( ! -f $msp_filename)
+ {
+ $installer::logger::Info->printf("%s does not point to a valid file\n", $msp_filename);
+ next;
+ }
- my $command = join(" ",
- "msiexec.exe",
- "/update", "'".installer::patch::Tools::ToWindowsPath($msp_filename)."'",
- "/L*xv!", "'".installer::patch::Tools::ToWindowsPath($log_filename)."'",
- "REINSTALL=ALL",
+ my $log_path = File::Spec->catfile(dirname($msp_filename), "log");
+ my $log_basename = "apply-msp";
+ my $log_filename = File::Spec->catfile($log_path, $log_basename.".log");
+
+ my $command = join(" ",
+ "msiexec.exe",
+ "/update", "'".installer::patch::Tools::ToWindowsPath($msp_filename)."'",
+ "/L*xv!", "'".installer::patch::Tools::ToWindowsPath($log_filename)."'",
+ "REINSTALL=ALL",
# "REINSTALLMODE=vomus",
- "REINSTALLMODE=omus",
- "MSIENFORCEUPGRADECOMPONENTRULES=1");
+ "REINSTALLMODE=omus",
+ "MSIENFORCEUPGRADECOMPONENTRULES=1");
- printf("executing command %s\n", $command);
- my $response = qx($command);
- Encode::from_to($response, "UTF16LE", "UTF8");
- printf("response was '%s'\n", $response);
+ printf("executing command %s\n", $command);
+ my $response = qx($command);
+ Encode::from_to($response, "UTF16LE", "UTF8");
+ printf("response was '%s'\n", $response);
- ShowLog($log_path, $log_filename, $log_basename, "msp application");
- }
+ ShowLog($log_path, $log_filename, $log_basename, "msp application");
}
@@ -1802,12 +2202,17 @@ sub UpdateReleasesXML($$)
sub main ()
{
- installer::logger::SetupSimpleLogging(undef);
my $context = ProcessCommandline();
+ installer::logger::starttime();
+ $installer::logger::Global->add_timestamp("starting logging");
+# installer::logger::SetupSimpleLogging(undef);
+
die "ERROR: list file is not defined, please use --lst-file option"
unless defined $context->{'lst-file'};
die "ERROR: product name is not defined, please use --product-name option"
unless defined $context->{'product-name'};
+ die sprintf("ERROR: package format %s is not supported", $context->{'package-format'})
+ unless defined $context->{'package-format'} ne "msi";
my ($variables, undef, undef) = installer::ziplist::read_openoffice_lst_file(
$context->{'lst-file'},
@@ -1815,6 +2220,22 @@ sub main ()
undef);
DetermineVersions($context, $variables);
+ if ($context->{'command'} =~ /create|check/)
+ {
+ $installer::logger::Lang->set_filename(
+ File::Spec->catfile(
+ $context->{'output-path'},
+ $context->{'product-name'},
+ "msp",
+ $context->{'source-version-dash'} . "_" . $context->{'target-version-dash'},
+ $context->{'language'},
+ "log",
+ "patch-creation.log"));
+ $installer::logger::Lang->copy_lines_from($installer::logger::Global);
+ $installer::logger::Lang->set_forward(undef);
+ $installer::logger::Info->set_forward($installer::logger::Lang);
+ }
+
if ($context->{'command'} eq "create")
{
CreatePatch($context, $variables);
@@ -1827,6 +2248,10 @@ sub main ()
{
UpdateReleasesXML($context, $variables);
}
+ elsif ($context->{'command'} eq "check")
+ {
+ CheckPatchCompatability($context, $variables);
+ }
}
Modified: openoffice/trunk/main/solenv/bin/release_prepare.pl
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/solenv/bin/release_prepare.pl?rev=1550699&r1=1550698&r2=1550699&view=diff
==============================================================================
--- openoffice/trunk/main/solenv/bin/release_prepare.pl (original)
+++ openoffice/trunk/main/solenv/bin/release_prepare.pl Fri Dec 13 12:05:15 2013
@@ -32,7 +32,7 @@ use Getopt::Long;
use Pod::Usage;
use Digest;
-use Carp::Always;
+#use Carp::Always;
use strict;