patch_tool.pl (9f91b7e3) | patch_tool.pl (d575d58f) |
---|---|
1#!/usr/bin/perl -w 2 3#************************************************************** 4# 5# Licensed to the Apache Software Foundation (ASF) under one 6# or more contributor license agreements. See the NOTICE file 7# distributed with this work for additional information 8# regarding copyright ownership. The ASF licenses this file --- 241 unchanged lines hidden (view full) --- 250 # Make sure that the downloadable installation set (.exe) is present in ext_sources/. 251 my $filename = File::Spec->catfile($ext_sources_path, $basename); 252 if ( -f $filename) 253 { 254 PrintInfo("%s is already present in ext_sources/. Nothing to do\n", $basename); 255 } 256 else 257 { | 1#!/usr/bin/perl -w 2 3#************************************************************** 4# 5# Licensed to the Apache Software Foundation (ASF) under one 6# or more contributor license agreements. See the NOTICE file 7# distributed with this work for additional information 8# regarding copyright ownership. The ASF licenses this file --- 241 unchanged lines hidden (view full) --- 250 # Make sure that the downloadable installation set (.exe) is present in ext_sources/. 251 my $filename = File::Spec->catfile($ext_sources_path, $basename); 252 if ( -f $filename) 253 { 254 PrintInfo("%s is already present in ext_sources/. Nothing to do\n", $basename); 255 } 256 else 257 { |
258 return 0 if ! installer::patch::Download($language, $release_data, $location, $basename, $filename); | 258 return 0 if ! installer::patch::InstallationSet::Download( 259 $language, 260 $release_data, 261 $filename); |
259 return 0 if ! -f $filename; 260 } 261 262 # Unpack the installation set. 263 if ( -d $unpacked_path) 264 { 265 # Take the existence of the destination path as proof that the 266 # installation set was successfully unpacked before. --- 849 unchanged lines hidden (view full) --- 1116 "Value", $uuid_string 1117 ); 1118 $installer::logger::Info->printf("created new PatchGUID %s\n", $uuid_string); 1119 1120 # Prevent sequence table from being generated. 1121 $table->SetRow( 1122 "*Name", "SEQUENCE_DATA_GENERATION_DISABLED", 1123 "Value", 1); | 262 return 0 if ! -f $filename; 263 } 264 265 # Unpack the installation set. 266 if ( -d $unpacked_path) 267 { 268 # Take the existence of the destination path as proof that the 269 # installation set was successfully unpacked before. --- 849 unchanged lines hidden (view full) --- 1119 "Value", $uuid_string 1120 ); 1121 $installer::logger::Info->printf("created new PatchGUID %s\n", $uuid_string); 1122 1123 # Prevent sequence table from being generated. 1124 $table->SetRow( 1125 "*Name", "SEQUENCE_DATA_GENERATION_DISABLED", 1126 "Value", 1); |
1127 1128 # We don't provide file size and hash values. 1129 # This value is set to make this fact explicit (0 should be the default). 1130 $table->SetRow( 1131 "*Name", "TrustMsi", 1132 "Value", 0); |
|
1124} 1125 1126 1127 1128 1129sub SetupImageFamiliesTable ($) 1130{ 1131 my ($pcp) = @_; --- 220 unchanged lines hidden (view full) --- 1352 1353 # Show the log file that was created by the msimsp.exe command. 1354 ShowLog($log_path, $log_filename, $log_basename, "msp creation"); 1355 ShowLog($log_path, $performance_log_filename, $performance_log_basename, "msp creation perf"); 1356} 1357 1358 1359 | 1133} 1134 1135 1136 1137 1138sub SetupImageFamiliesTable ($) 1139{ 1140 my ($pcp) = @_; --- 220 unchanged lines hidden (view full) --- 1361 1362 # Show the log file that was created by the msimsp.exe command. 1363 ShowLog($log_path, $log_filename, $log_basename, "msp creation"); 1364 ShowLog($log_path, $performance_log_filename, $performance_log_basename, "msp creation perf"); 1365} 1366 1367 1368 |
1369 1370=head CreatePatch($context, $variables) 1371 1372 Create MSP patch files for all relevant languages. 1373 The different steps are: 1374 1. Determine the set of languages for which both the source and target installation sets are present. 1375 Per language: 1376 2. Unpack CAB files (for source and target). 1377 3. Check if source and target releases are compatible. 1378 4. Create the PCP driver file. 1379 5. Create the MSP patch file. 1380 1381=cut |
|
1360sub CreatePatch ($$) 1361{ 1362 my ($context, $variables) = @_; 1363 1364 $installer::logger::Info->printf("patch will update product %s from %s to %s\n", 1365 $context->{'product-name'}, 1366 $context->{'source-version'}, 1367 $context->{'target-version'}); --- 4 unchanged lines hidden (view full) --- 1372 { 1373 exit(1); 1374 } 1375 1376 my $release_data = installer::patch::ReleasesList::Instance() 1377 ->{$context->{'source-version'}} 1378 ->{$context->{'package-format'}}; 1379 | 1382sub CreatePatch ($$) 1383{ 1384 my ($context, $variables) = @_; 1385 1386 $installer::logger::Info->printf("patch will update product %s from %s to %s\n", 1387 $context->{'product-name'}, 1388 $context->{'source-version'}, 1389 $context->{'target-version'}); --- 4 unchanged lines hidden (view full) --- 1394 { 1395 exit(1); 1396 } 1397 1398 my $release_data = installer::patch::ReleasesList::Instance() 1399 ->{$context->{'source-version'}} 1400 ->{$context->{'package-format'}}; 1401 |
1380 # Create a patch for each language. | 1402 # 1. Determine the set of languages for which we can create patches. |
1381 my @requested_languages = GetLanguages(); 1382 my @valid_languages = FindValidLanguages($context, $release_data, \@requested_languages); 1383 $installer::logger::Info->printf("of the requested languages '%s' are valid: '%s'\n", 1384 join("', '", @requested_languages), 1385 join("', '", @valid_languages)); 1386 foreach my $language (@valid_languages) 1387 { 1388 $installer::logger::Info->printf("processing language '%s'\n", $language); 1389 $installer::logger::Info->increase_indentation(); 1390 | 1403 my @requested_languages = GetLanguages(); 1404 my @valid_languages = FindValidLanguages($context, $release_data, \@requested_languages); 1405 $installer::logger::Info->printf("of the requested languages '%s' are valid: '%s'\n", 1406 join("', '", @requested_languages), 1407 join("', '", @valid_languages)); 1408 foreach my $language (@valid_languages) 1409 { 1410 $installer::logger::Info->printf("processing language '%s'\n", $language); 1411 $installer::logger::Info->increase_indentation(); 1412 |
1391 # Provide .msi and .cab files and unpacke .cab for the source release. | 1413 # 2a. Provide .msi and .cab files and unpacke .cab for the source release. |
1392 $installer::logger::Info->printf("locating source package (%s)\n", $context->{'source-version'}); 1393 $installer::logger::Info->increase_indentation(); 1394 if ( ! installer::patch::InstallationSet::ProvideUnpackedCab( 1395 $context->{'source-version'}, 1396 0, 1397 $language, 1398 "msi", 1399 $context->{'product-name'})) --- 4 unchanged lines hidden (view full) --- 1404 $context->{'source-version'}, 1405 0, 1406 $language, 1407 $context->{'product-name'}); 1408 die unless $source_msi->IsValid(); 1409 1410 $installer::logger::Info->decrease_indentation(); 1411 | 1414 $installer::logger::Info->printf("locating source package (%s)\n", $context->{'source-version'}); 1415 $installer::logger::Info->increase_indentation(); 1416 if ( ! installer::patch::InstallationSet::ProvideUnpackedCab( 1417 $context->{'source-version'}, 1418 0, 1419 $language, 1420 "msi", 1421 $context->{'product-name'})) --- 4 unchanged lines hidden (view full) --- 1426 $context->{'source-version'}, 1427 0, 1428 $language, 1429 $context->{'product-name'}); 1430 die unless $source_msi->IsValid(); 1431 1432 $installer::logger::Info->decrease_indentation(); 1433 |
1412 # Provide .msi and .cab files and unpacke .cab for the target release. | 1434 # 2b. Provide .msi and .cab files and unpacke .cab for the target release. |
1413 $installer::logger::Info->printf("locating target package (%s)\n", $context->{'target-version'}); 1414 $installer::logger::Info->increase_indentation(); 1415 if ( ! installer::patch::InstallationSet::ProvideUnpackedCab( 1416 $context->{'target-version'}, 1417 1, 1418 $language, 1419 "msi", 1420 $context->{'product-name'})) --- 12 unchanged lines hidden (view full) --- 1433 # Trigger reading of tables. 1434 foreach my $table_name (("File", "Component", "Registry")) 1435 { 1436 $source_msi->GetTable($table_name); 1437 $target_msi->GetTable($table_name); 1438 $installer::logger::Info->printf("read %s table (source and target\n", $table_name); 1439 } 1440 | 1435 $installer::logger::Info->printf("locating target package (%s)\n", $context->{'target-version'}); 1436 $installer::logger::Info->increase_indentation(); 1437 if ( ! installer::patch::InstallationSet::ProvideUnpackedCab( 1438 $context->{'target-version'}, 1439 1, 1440 $language, 1441 "msi", 1442 $context->{'product-name'})) --- 12 unchanged lines hidden (view full) --- 1455 # Trigger reading of tables. 1456 foreach my $table_name (("File", "Component", "Registry")) 1457 { 1458 $source_msi->GetTable($table_name); 1459 $target_msi->GetTable($table_name); 1460 $installer::logger::Info->printf("read %s table (source and target\n", $table_name); 1461 } 1462 |
1441 # Check if the source and target msis fullfil all necessary requirements. | 1463 # 3. Check if the source and target msis fullfil all necessary requirements. |
1442 if ( ! Check($source_msi, $target_msi, $variables, $context->{'product-name'})) 1443 { 1444 $installer::logger::Info->printf("Error: Source and target releases are not compatible.\n"); 1445 $installer::logger::Info->printf(" => Can not create patch.\n"); 1446 $installer::logger::Info->printf(" Did you create the target installation set with 'release=t' ?\n"); 1447 exit(1); 1448 } 1449 else --- 12 unchanged lines hidden (view full) --- 1462 $source_msi->{'version'})), 1463 installer::patch::Version::ArrayToDirectoryName( 1464 installer::patch::Version::StringToNumberArray( 1465 $target_msi->{'version'}))), 1466 $language 1467 ); 1468 File::Path::make_path($msp_path) unless -d $msp_path; 1469 | 1464 if ( ! Check($source_msi, $target_msi, $variables, $context->{'product-name'})) 1465 { 1466 $installer::logger::Info->printf("Error: Source and target releases are not compatible.\n"); 1467 $installer::logger::Info->printf(" => Can not create patch.\n"); 1468 $installer::logger::Info->printf(" Did you create the target installation set with 'release=t' ?\n"); 1469 exit(1); 1470 } 1471 else --- 12 unchanged lines hidden (view full) --- 1484 $source_msi->{'version'})), 1485 installer::patch::Version::ArrayToDirectoryName( 1486 installer::patch::Version::StringToNumberArray( 1487 $target_msi->{'version'}))), 1488 $language 1489 ); 1490 File::Path::make_path($msp_path) unless -d $msp_path; 1491 |
1470 # Create the .pcp file that drives the msimsp.exe command. | 1492 # 4. Create the .pcp file that drives the msimsp.exe command. |
1471 my $pcp = CreatePcp( 1472 $source_msi, 1473 $target_msi, 1474 $language, 1475 $context, 1476 $msp_path, 1477 $pcp_schema_filename, | 1493 my $pcp = CreatePcp( 1494 $source_msi, 1495 $target_msi, 1496 $language, 1497 $context, 1498 $msp_path, 1499 $pcp_schema_filename, |
1478 "Properties/Name:DontRemoveTempFolderWhenFinished" => "Value:1", 1479 "Properties/Name:SEQUENCE_DATA_GENERATION_DISABLED" => "Value:1", 1480 "Properties/Name:TrustMsi" => "Value:0", 1481 "Properties/Name:ProductName" => "Value:OOO341"); | 1500 "Properties/Name:DontRemoveTempFolderWhenFinished" => "Value:1"); |
1482 | 1501 |
1483 # Finally create the msp. | 1502 # 5. Finally create the msp. |
1484 CreateMsp($pcp); 1485 1486 $installer::logger::Info->decrease_indentation(); 1487 } 1488} 1489 1490 1491 | 1503 CreateMsp($pcp); 1504 1505 $installer::logger::Info->decrease_indentation(); 1506 } 1507} 1508 1509 1510 |
1511=cut ApplyPatch ($context, $variables) |
|
1492 | 1512 |
1513 This is for testing only. 1514 The patch is applied and (extensive) log information is created and transformed into HTML format. 1515 1516=cut |
|
1493sub ApplyPatch ($$) 1494{ 1495 my ($context, $variables) = @_; 1496 1497 $installer::logger::Info->printf("will apply patches that update product %s from %s to %s\n", 1498 $context->{'product-name'}, 1499 $context->{'source-version'}, 1500 $context->{'target-version'}); --- 41 unchanged lines hidden (view full) --- 1542 1543 ShowLog($log_path, $log_filename, $log_basename, "msp application"); 1544 } 1545} 1546 1547 1548 1549 | 1517sub ApplyPatch ($$) 1518{ 1519 my ($context, $variables) = @_; 1520 1521 $installer::logger::Info->printf("will apply patches that update product %s from %s to %s\n", 1522 $context->{'product-name'}, 1523 $context->{'source-version'}, 1524 $context->{'target-version'}); --- 41 unchanged lines hidden (view full) --- 1566 1567 ShowLog($log_path, $log_filename, $log_basename, "msp application"); 1568 } 1569} 1570 1571 1572 1573 |
1574=head2 DownloadFile ($url) 1575 1576 A simpler version of InstallationSet::Download(). It is simple because it is used to 1577 setup the $release_data structure that is used by InstallationSet::Download(). 1578 1579=cut 1580sub DownloadFile ($) 1581{ 1582 my ($url) = shift; 1583 1584 my $agent = LWP::UserAgent->new(); 1585 $agent->timeout(120); 1586 $agent->show_progress(0); 1587 1588 my $file_content = ""; 1589 my $last_was_redirect = 0; 1590 my $bytes_read = 0; 1591 $agent->add_handler('response_redirect' 1592 => sub{ 1593 $last_was_redirect = 1; 1594 return; 1595 }); 1596 $agent->add_handler('response_data' 1597 => sub{ 1598 if ($last_was_redirect) 1599 { 1600 $last_was_redirect = 0; 1601 # Throw away the data we got so far. 1602 $file_content = ""; 1603 } 1604 my($response,$agent,$h,$data)=@_; 1605 $file_content .= $data; 1606 }); 1607 $agent->get($url); 1608 1609 return $file_content; 1610} 1611 1612 1613 1614 1615sub CreateReleaseItem ($$$) 1616{ 1617 my ($language, $exe_filename, $msi) = @_; 1618 1619 die "can not open installation set at ".$exe_filename unless -f $exe_filename; 1620 1621 open my $in, "<", $exe_filename; 1622 my $sha256_checksum = new Digest("SHA-256")->addfile($in)->hexdigest(); 1623 close $in; 1624 1625 my $filesize = -s $exe_filename; 1626 1627 # Get the product code property from the msi and strip the enclosing braces. 1628 my $product_code = $msi->GetTable("Property")->GetValue("Property", "ProductCode", "Value"); 1629 $product_code =~ s/(^{|}$)//g; 1630 my $upgrade_code = $msi->GetTable("Property")->GetValue("Property", "UpgradeCode", "Value"); 1631 $upgrade_code =~ s/(^{|}$)//g; 1632 my $build_id = $msi->GetTable("Property")->GetValue("Property", "PRODUCTBUILDID", "Value"); 1633 1634 return { 1635 'language' => $language, 1636 'checksum-type' => "sha256", 1637 'checksum-value' => $sha256_checksum, 1638 'file-size' => $filesize, 1639 'product-code' => $product_code, 1640 'upgrade-code' => $upgrade_code, 1641 'build-id' => $build_id 1642 }; 1643} 1644 1645 1646 1647 1648sub GetReleaseItemForCurrentBuild ($$$) 1649{ 1650 my ($context, $language, $exe_basename) = @_; 1651 1652 # Target version is the current version. 1653 # Search instsetoo_native for the installation set. 1654 my $filename = File::Spec->catfile( 1655 $context->{'output-path'}, 1656 $context->{'product-name'}, 1657 $context->{'package-format'}, 1658 "install", 1659 $language."_download", 1660 $exe_basename); 1661 1662 printf(" current : %s\n", $filename); 1663 if ( ! -f $filename) 1664 { 1665 printf("ERROR: can not find %s\n", $filename); 1666 return undef; 1667 } 1668 else 1669 { 1670 my $msi = installer::patch::Msi->FindAndCreate( 1671 $context->{'target-version'}, 1672 1, 1673 $language, 1674 $context->{'product-name'}); 1675 return CreateReleaseItem($language, $filename, $msi); 1676 } 1677} 1678 1679 1680 1681sub GetReleaseItemForOldBuild ($$$$) 1682{ 1683 my ($context, $language, $exe_basename, $url_template) = @_; 1684 1685 # Use ext_sources/ as local cache for archive.apache.org 1686 # and search these for the installation set. 1687 1688 my $version = $context->{'target-version'}; 1689 my $package_format = $context->{'package-format'}; 1690 my $releases_list = installer::patch::ReleasesList::Instance(); 1691 1692 my $url = $url_template; 1693 $url =~ s/%L/$language/g; 1694 $releases_list->{$version}->{$package_format}->{$language}->{'URL'} = $url; 1695 1696 if ( ! installer::patch::InstallationSet::ProvideUnpackedExe( 1697 $version, 1698 0, 1699 $language, 1700 $package_format, 1701 $context->{'product-name'})) 1702 { 1703 # Can not provide unpacked EXE. 1704 return undef; 1705 } 1706 else 1707 { 1708 my $exe_filename = File::Spec->catfile( 1709 $ENV{'TARFILE_LOCATION'}, 1710 $exe_basename); 1711 my $msi = installer::patch::Msi->FindAndCreate( 1712 $version, 1713 0, 1714 $language, 1715 $context->{'product-name'}); 1716 return CreateReleaseItem($language, $exe_filename, $msi); 1717 } 1718} 1719 1720 1721 1722 1723sub UpdateReleasesXML($$) 1724{ 1725 my ($context, $variables) = @_; 1726 1727 my $releases_list = installer::patch::ReleasesList::Instance(); 1728 my $output_filename = File::Spec->catfile( 1729 $context->{'output-path'}, 1730 "misc", 1731 "releases.xml"); 1732 1733 my $target_version = $context->{'target-version'}; 1734 my %version_hash = map {$_=>1} @{$releases_list->{'releases'}}; 1735 my $item_hash = undef; 1736 if ( ! defined $version_hash{$context->{'target-version'}}) 1737 { 1738 # Target version is not yet present. Add it and print message that asks caller to check order. 1739 push @{$releases_list->{'releases'}}, $target_version; 1740 printf("adding data for new version %s to list of released versions.\n", $target_version); 1741 printf("please check order of releases in $output_filename\n"); 1742 $item_hash = {}; 1743 } 1744 else 1745 { 1746 printf("adding data for existing version %s to releases.xml\n", $target_version); 1747 $item_hash = $releases_list->{$target_version}->{$context->{'package-format'}}; 1748 } 1749 $releases_list->{$target_version} = {$context->{'package-format'} => $item_hash}; 1750 1751 my @languages = GetLanguages(); 1752 my %language_items = (); 1753 foreach my $language (@languages) 1754 { 1755 # There are three different sources where to find the downloadable installation sets. 1756 # 1. archive.apache.org for previously released versions. 1757 # 2. A local cache or repository directory that conceptually is a local copy of archive.apache.org 1758 # 3. The downloadable installation sets built in instsetoo_native/. 1759 1760 my $exe_basename = sprintf( 1761 "%s_%s_Win_x86_install_%s.exe", 1762 $context->{'product-name'}, 1763 $target_version, 1764 $language); 1765 my $url_template = sprintf( 1766 "http://archive.apache.org/dist/openoffice/%s/binaries/%%L/%s_%s_Win_x86_install_%%L.exe", 1767 $target_version, 1768 $context->{'product-name'}, 1769 $target_version); 1770 1771 my $item = undef; 1772 if ($target_version eq $variables->{PRODUCTVERSION}) 1773 { 1774 $item = GetReleaseItemForCurrentBuild($context, $language, $exe_basename); 1775 } 1776 else 1777 { 1778 $item = GetReleaseItemForOldBuild($context, $language, $exe_basename, $url_template); 1779 } 1780 1781 next unless defined $item; 1782 1783 $language_items{$language} = $item; 1784 $item_hash->{$language} = $item; 1785 $item_hash->{'upgrade-code'} = $item->{'upgrade-code'}; 1786 $item_hash->{'build-id'} = $item->{'build-id'}; 1787 $item_hash->{'url-template'} = $url_template; 1788 } 1789 1790 my @valid_languages = sort keys %language_items; 1791 $item_hash->{'languages'} = \@valid_languages; 1792 1793 $releases_list->Write($output_filename); 1794 1795 printf("\n\n"); 1796 printf("please copy '%s' to main/instsetoo_native/data\n", $output_filename); 1797 printf("and check in the modified file to the version control system\n"); 1798} 1799 1800 1801 1802 |
|
1550sub main () 1551{ 1552 installer::logger::SetupSimpleLogging(undef); 1553 my $context = ProcessCommandline(); | 1803sub main () 1804{ 1805 installer::logger::SetupSimpleLogging(undef); 1806 my $context = ProcessCommandline(); |
1807 die "ERROR: list file is not defined, please use --lst-file option" 1808 unless defined $context->{'lst-file'}; 1809 die "ERROR: product name is not defined, please use --product-name option" 1810 unless defined $context->{'product-name'}; 1811 |
|
1554 my ($variables, undef, undef) = installer::ziplist::read_openoffice_lst_file( 1555 $context->{'lst-file'}, 1556 $context->{'product-name'}, 1557 undef); 1558 DetermineVersions($context, $variables); 1559 1560 if ($context->{'command'} eq "create") 1561 { 1562 CreatePatch($context, $variables); 1563 } 1564 elsif ($context->{'command'} eq "apply") 1565 { 1566 ApplyPatch($context, $variables); 1567 } | 1812 my ($variables, undef, undef) = installer::ziplist::read_openoffice_lst_file( 1813 $context->{'lst-file'}, 1814 $context->{'product-name'}, 1815 undef); 1816 DetermineVersions($context, $variables); 1817 1818 if ($context->{'command'} eq "create") 1819 { 1820 CreatePatch($context, $variables); 1821 } 1822 elsif ($context->{'command'} eq "apply") 1823 { 1824 ApplyPatch($context, $variables); 1825 } |
1826 elsif ($context->{'command'} eq "update-releases-xml") 1827 { 1828 UpdateReleasesXML($context, $variables); 1829 } |
|
1568} 1569 1570 1571main(); | 1830} 1831 1832 1833main(); |