file.pm (1ba1fd99) | file.pm (9f91b7e3) |
---|---|
1#************************************************************** 2# 3# Licensed to the Apache Software Foundation (ASF) under one 4# or more contributor license agreements. See the NOTICE file 5# distributed with this work for additional information 6# regarding copyright ownership. The ASF licenses this file 7# to you under the Apache License, Version 2.0 (the 8# "License"); you may not use this file except in compliance --- 21 unchanged lines hidden (view full) --- 30use installer::globals; 31use installer::logger; 32use installer::pathanalyzer; 33use installer::worker; 34use installer::windows::font; 35use installer::windows::idtglobal; 36use installer::windows::msiglobal; 37use installer::windows::language; | 1#************************************************************** 2# 3# Licensed to the Apache Software Foundation (ASF) under one 4# or more contributor license agreements. See the NOTICE file 5# distributed with this work for additional information 6# regarding copyright ownership. The ASF licenses this file 7# to you under the Apache License, Version 2.0 (the 8# "License"); you may not use this file except in compliance --- 21 unchanged lines hidden (view full) --- 30use installer::globals; 31use installer::logger; 32use installer::pathanalyzer; 33use installer::worker; 34use installer::windows::font; 35use installer::windows::idtglobal; 36use installer::windows::msiglobal; 37use installer::windows::language; |
38use installer::patch::InstallationSet; 39use installer::patch::FileSequenceList; 40use File::Basename; 41use File::Spec; 42use strict; |
|
38 39########################################################################## 40# Assigning one cabinet file to each file. This is requrired, 41# if cabinet files shall be equivalent to packages. 42########################################################################## 43 44sub assign_cab_to_files 45{ --- 306 unchanged lines hidden (view full) --- 352 353#################################################################### 354# Generating the special filename for the database file File.idt 355# Sample: CONTEXTS, CONTEXTS1 356# This name has to be unique. 357# In most cases this is simply the filename. 358#################################################################### 359 | 43 44########################################################################## 45# Assigning one cabinet file to each file. This is requrired, 46# if cabinet files shall be equivalent to packages. 47########################################################################## 48 49sub assign_cab_to_files 50{ --- 306 unchanged lines hidden (view full) --- 357 358#################################################################### 359# Generating the special filename for the database file File.idt 360# Sample: CONTEXTS, CONTEXTS1 361# This name has to be unique. 362# In most cases this is simply the filename. 363#################################################################### 364 |
360sub generate_unique_filename_for_filetable ($$) | 365sub generate_unique_filename_for_filetable ($) |
361{ | 366{ |
362 my ($fileref, $component) = @_; | 367 my ($oldname) = @_; |
363 364 # This new filename has to be saved into $fileref, because this is needed to find the source. 365 # The filename sbasic.idx/OFFSETS is changed to OFFSETS, but OFFSETS is not unique. 366 # In this procedure names like OFFSETS5 are produced. And exactly this string has to be added to 367 # the array of all files. 368 | 368 369 # This new filename has to be saved into $fileref, because this is needed to find the source. 370 # The filename sbasic.idx/OFFSETS is changed to OFFSETS, but OFFSETS is not unique. 371 # In this procedure names like OFFSETS5 are produced. And exactly this string has to be added to 372 # the array of all files. 373 |
369 my $uniquefilename = ""; 370 my $counter = 0; | 374 my $uniquefilename = $oldname; 375 if ( ! defined $uniquefilename || $uniquefilename eq "") 376 { 377 installer::logger::PrintError("file name does not exist or is empty, can not create unique name for it."); 378 die; 379 return; 380 } |
371 | 381 |
372 if ( $fileref->{'Name'} ) { $uniquefilename = $fileref->{'Name'}; } | |
373 # making /registry/schema/org/openoffice/VCL.xcs to VCL.xcs 374 installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$uniquefilename); 375 376 $uniquefilename =~ s/\-/\_/g; # no "-" allowed 377 $uniquefilename =~ s/\@/\_/g; # no "@" allowed 378 $uniquefilename =~ s/\$/\_/g; # no "$" allowed 379 $uniquefilename =~ s/^\s*\./\_/g; # no "." at the beginning allowed allowed 380 $uniquefilename =~ s/^\s*\d/\_d/g; # no number at the beginning allowed allowed (even file "0.gif", replacing to "_d.gif") --- 12 unchanged lines hidden (view full) --- 393 394 if ( ! $newname ) 395 { 396 # adding a number until the name is really unique: OFFSETS, OFFSETS1, OFFSETS2, ... 397 # But attention: Making "abc.xcu" to "abc1.xcu" 398 399 my $uniquefilenamebase = $uniquefilename; 400 | 382 # making /registry/schema/org/openoffice/VCL.xcs to VCL.xcs 383 installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$uniquefilename); 384 385 $uniquefilename =~ s/\-/\_/g; # no "-" allowed 386 $uniquefilename =~ s/\@/\_/g; # no "@" allowed 387 $uniquefilename =~ s/\$/\_/g; # no "$" allowed 388 $uniquefilename =~ s/^\s*\./\_/g; # no "." at the beginning allowed allowed 389 $uniquefilename =~ s/^\s*\d/\_d/g; # no number at the beginning allowed allowed (even file "0.gif", replacing to "_d.gif") --- 12 unchanged lines hidden (view full) --- 402 403 if ( ! $newname ) 404 { 405 # adding a number until the name is really unique: OFFSETS, OFFSETS1, OFFSETS2, ... 406 # But attention: Making "abc.xcu" to "abc1.xcu" 407 408 my $uniquefilenamebase = $uniquefilename; 409 |
410 my $counter = 0; |
|
401 do 402 { 403 $counter++; 404 405 if ( $uniquefilenamebase =~ /\./ ) 406 { 407 $uniquefilename = $uniquefilenamebase; 408 $uniquefilename =~ s/\./$counter\./; --- 77 unchanged lines hidden (view full) --- 486 487############################################# 488# Returning the file version, if required 489# Sample: "8.0.1.8976"; 490############################################# 491 492sub get_fileversion 493{ | 411 do 412 { 413 $counter++; 414 415 if ( $uniquefilenamebase =~ /\./ ) 416 { 417 $uniquefilename = $uniquefilenamebase; 418 $uniquefilename =~ s/\./$counter\./; --- 77 unchanged lines hidden (view full) --- 496 497############################################# 498# Returning the file version, if required 499# Sample: "8.0.1.8976"; 500############################################# 501 502sub get_fileversion 503{ |
494 my ($onefile, $allvariables, $styles) = @_; | 504 my ($onefile, $allvariables) = @_; |
495 496 my $fileversion = ""; 497 498 if ( $allvariables->{'USE_FILEVERSION'} ) 499 { 500 if ( ! $allvariables->{'LIBRARYVERSION'} ) 501 { 502 installer::exiter::exit_program("ERROR: USE_FILEVERSION is set, but not LIBRARYVERSION", "get_fileversion"); --- 24 unchanged lines hidden (view full) --- 527 { 528 # Windows patches do not allow this version # -> who says so? 529 $fileversion = ""; 530 } 531 532 return $fileversion; 533} 534 | 505 506 my $fileversion = ""; 507 508 if ( $allvariables->{'USE_FILEVERSION'} ) 509 { 510 if ( ! $allvariables->{'LIBRARYVERSION'} ) 511 { 512 installer::exiter::exit_program("ERROR: USE_FILEVERSION is set, but not LIBRARYVERSION", "get_fileversion"); --- 24 unchanged lines hidden (view full) --- 537 { 538 # Windows patches do not allow this version # -> who says so? 539 $fileversion = ""; 540 } 541 542 return $fileversion; 543} 544 |
545 546 547 548sub retrieve_sequence_and_uniquename ($$) 549{ 550 my ($file_list, $source_data) = @_; 551 552 my @added_files = (); 553 554 # Read the sequence numbers of the previous version. 555 if ($installer::globals::is_release) 556 { 557 foreach my $file (@$file_list) 558 { 559 # Use the source path of the file as key to retrieve sequence number and unique name. 560 # The source path is the part of the 'destination' without the first part. 561 # There is a special case when 'Dir' is PREDEFINED_OSSHELLNEWDIR. 562 my $source_path; 563 if (defined $file->{'Dir'} && $file->{'Dir'} eq "PREDEFINED_OSSHELLNEWDIR") 564 { 565 $source_path = $installer::globals::templatefoldername 566 . $installer::globals::separator 567 . $file->{'Name'}; 568 } 569 else 570 { 571 $source_path = $file->{'destination'}; 572 $source_path =~ s/^[^\/]+\///; 573 } 574 my ($sequence, $uniquename) = $source_data->get_sequence_and_unique_name($source_path); 575 if (defined $sequence && defined $uniquename) 576 { 577 $file->{'sequencenumber'} = $sequence; 578 $file->{'uniquename'} = $uniquename; 579 } 580 else 581 { 582 # No data found in the source release. File has been added. 583 push @added_files, $file; 584 } 585 } 586 } 587 588 return @added_files; 589} 590 591 592 593 594=head2 assign_mssing_sequence_numbers ($file_list) 595 596 Assign sequence numbers where still missing. 597 598 When we are preparing a patch then all files that have no sequence numbers 599 at this point are new. Otherwise no file has a sequence number yet. 600 601=cut 602sub assign_missing_sequence_numbers ($) 603{ 604 my ($file_list) = @_; 605 606 # First, set up a hash on the sequence numbers that are already in use. 607 my %used_sequence_numbers = (); 608 foreach my $file (@$file_list) 609 { 610 next unless defined $file->{'sequencenumber'}; 611 $used_sequence_numbers{$file->{'sequencenumber'}} = 1; 612 } 613 614 # Assign sequence numbers. Try consecutive numbers, starting at 1. 615 my $current_sequence_number = 1; 616 foreach my $file (@$file_list) 617 { 618 # Skip over all files that already have sequence numbers. 619 next if defined $file->{'sequencenumber'}; 620 621 # Find the next available number. 622 while (defined $used_sequence_numbers{$current_sequence_number}) 623 { 624 ++$current_sequence_number; 625 } 626 627 # Use the number and mark it as used. 628 $file->{'sequencenumber'} = $current_sequence_number; 629 $used_sequence_numbers{$current_sequence_number} = 1; 630 } 631} 632 633 634 635 636sub create_items_for_missing_files ($$$) 637{ 638 my ($missing_items, $msi, $directory_list) = @_; 639 640 # For creation of the FeatureComponent table (in a later step) we 641 # have to provide references from the file to component and 642 # modules (ie features). Note that Each file belongs to exactly 643 # one component but one component can belong to multiple features. 644 my $component_to_features_map = create_feature_component_map($msi); 645 646 my @new_files = (); 647 foreach my $row (@$missing_items) 648 { 649 $installer::logger::Info->printf("creating new file item for '%s'\n", $row->GetValue('File')); 650 my $file_item = create_script_item_for_deleted_file($row, $msi, $component_to_features_map); 651 push @new_files, $file_item; 652 } 653 654 return @new_files; 655} 656 657 658 659 660sub create_script_item_for_deleted_file ($$$) 661{ 662 my ($file_row, $msi, $component_to_features_map) = @_; 663 664 my $uniquename = $file_row->GetValue('File'); 665 666 my $file_map = $msi->GetFileMap(); 667 668 my $directory_item = $file_map->{$uniquename}->{'directory'}; 669 my $source_path = $directory_item->{'full_source_long_name'}; 670 my $target_path = $directory_item->{'full_target_long_name'}; 671 my $full_source_name = File::Spec->catfile( 672 installer::patch::InstallationSet::GetUnpackedCabPath( 673 $msi->{'version'}, 674 $msi->{'is_current_version'}, 675 $msi->{'language'}, 676 $msi->{'package_format'}, 677 $msi->{'product_name'}), 678 $source_path, 679 $uniquename); 680 my ($long_name, undef) = installer::patch::Msi::SplitLongShortName($file_row->GetValue("FileName")); 681 my $target_name = File::Spec->catfile($target_path, $long_name); 682 if ( ! -f $full_source_name) 683 { 684 installer::logger::PrintError("can not find file '%s' in previous version (tried '%s')\n", 685 $uniquename, 686 $full_source_name); 687 return undef; 688 } 689 my $cygwin_full_source_name = qx(cygpath -w '$full_source_name'); 690 my $component_name = $file_row->GetValue('Component_'); 691 my $module_names = join(",", @{$component_to_features_map->{$component_name}}); 692 my $sequence_number = $file_row->GetValue('Sequence'); 693 694 return { 695 'uniquename' => $uniquename, 696 'destination' => $target_name, 697 'componentname' => $component_name, 698 'modules' => $module_names, 699 'UnixRights' => 444, 700 'Name' => $long_name, 701 'sourcepath' => $full_source_name, 702 'cyg_sourcepath' => $cygwin_full_source_name, 703 'sequencenumber' => $sequence_number 704 }; 705} 706 707 708 709 710=head2 create_feature_component_maps($msi) 711 712 Return a hash map that maps from component names to arrays of 713 feature names. In most cases the array of features contains only 714 one element. But there can be cases where the number is greater. 715 716=cut 717sub create_feature_component_map ($) 718{ 719 my ($msi) = @_; 720 721 my $component_to_features_map = {}; 722 my $feature_component_table = $msi->GetTable("FeatureComponents"); 723 my $feature_column_index = $feature_component_table->GetColumnIndex("Feature_"); 724 my $component_column_index = $feature_component_table->GetColumnIndex("Component_"); 725 foreach my $row (@{$feature_component_table->GetAllRows()}) 726 { 727 my $feature = $row->GetValue($feature_column_index); 728 my $component = $row->GetValue($component_column_index); 729 if ( ! defined $component_to_features_map->{$component}) 730 { 731 $component_to_features_map->{$component} = [$feature]; 732 } 733 else 734 { 735 push @{$component_to_features_map->{$component}}, $feature; 736 } 737 } 738 739 return $component_to_features_map; 740} 741 742 |
|
535############################################# 536# Returning the Windows language of a file 537############################################# 538 539sub get_language_for_file 540{ 541 my ($fileref) = @_; 542 --- 28 unchanged lines hidden (view full) --- 571 my $keypath = $onefile->{'Name'}; 572 $keypath =~ s/\.//g; 573 $keypath = lc($keypath); 574 $keypath = "userreg_" . $keypath; 575 576 return $keypath; 577} 578 | 743############################################# 744# Returning the Windows language of a file 745############################################# 746 747sub get_language_for_file 748{ 749 my ($fileref) = @_; 750 --- 28 unchanged lines hidden (view full) --- 779 my $keypath = $onefile->{'Name'}; 780 $keypath =~ s/\.//g; 781 $keypath = lc($keypath); 782 $keypath = "userreg_" . $keypath; 783 784 return $keypath; 785} 786 |
787 |
|
579################################################################### 580# Collecting further conditions for the component table. 581# This is used by multilayer products, to enable installation 582# of separate layers. 583################################################################### 584 585sub get_tree_condition_for_component 586{ --- 44 unchanged lines hidden (view full) --- 631 if ( $value =~ /^\s*(.*?)\;\s*(.*?)\s*$/ ) 632 { 633 my $shortstring = $2; 634 $shortnameshashref->{$shortstring} = 1; # adding the shortname to the array of all shortnames 635 } 636 } 637} 638 | 788################################################################### 789# Collecting further conditions for the component table. 790# This is used by multilayer products, to enable installation 791# of separate layers. 792################################################################### 793 794sub get_tree_condition_for_component 795{ --- 44 unchanged lines hidden (view full) --- 840 if ( $value =~ /^\s*(.*?)\;\s*(.*?)\s*$/ ) 841 { 842 my $shortstring = $2; 843 $shortnameshashref->{$shortstring} = 1; # adding the shortname to the array of all shortnames 844 } 845 } 846} 847 |
639############################################ 640# Creating the file File.idt dynamically 641############################################ | |
642 | 848 |
643sub create_files_table ($$$$) | 849sub process_language_conditions ($) |
644{ | 850{ |
645 my ($filesref, $allfilecomponentsref, $basedir, $allvariables) = @_; | 851 my ($onefile) = @_; 852 853 # Collecting all languages specific conditions 854 if ( $onefile->{'ismultilingual'} ) 855 { 856 if ( $onefile->{'ComponentCondition'} ) 857 { 858 installer::exiter::exit_program( 859 "ERROR: Cannot set language condition. There is already another component condition for file $onefile->{'gid'}: \"$onefile->{'ComponentCondition'}\" !", "create_files_table"); 860 } |
646 | 861 |
647 $installer::logger::Lang->add_timestamp("Performance Info: File Table start"); | 862 if ( $onefile->{'specificlanguage'} eq "" ) 863 { 864 installer::exiter::exit_program( 865 "ERROR: There is no specific language for file at language module: $onefile->{'gid'} !", "create_files_table"); 866 } 867 my $locallanguage = $onefile->{'specificlanguage'}; 868 my $property = "IS" . $onefile->{'windows_language'}; 869 my $value = 1; 870 my $condition = $property . "=" . $value; 871 872 $onefile->{'ComponentCondition'} = $condition; |
648 | 873 |
649 # Structure of the files table: 650 # File Component_ FileName FileSize Version Language Attributes Sequence 651 # In this function, all components are created. 652 # 653 # $allfilecomponentsref is empty at the beginning | 874 if ( exists($installer::globals::componentcondition{$onefile->{'componentname'}})) 875 { 876 if ( $installer::globals::componentcondition{$onefile->{'componentname'}} ne $condition ) 877 { 878 installer::exiter::exit_program( 879 sprintf( 880 "ERROR: There is already another component condition for file %s: \"%s\" and \"%s\" !", 881 $onefile->{'gid'}, 882 $installer::globals::componentcondition{$onefile->{'componentname'}}, 883 $condition), 884 "create_files_table"); 885 } 886 } 887 else 888 { 889 $installer::globals::componentcondition{$onefile->{'componentname'}} = $condition; 890 } |
654 | 891 |
655 my $infoline; | 892 # collecting all properties for table Property 893 if ( ! exists($installer::globals::languageproperties{$property}) ) 894 { 895 $installer::globals::languageproperties{$property} = $value; 896 } 897 } 898} |
656 | 899 |
657 my @allfiles = (); 658 my @filetable = (); 659 my @filehashtable = (); 660 my %allfilecomponents = (); 661 my $counter = 0; | |
662 | 900 |
663 if ( $^O =~ /cygwin/i ) { installer::worker::generate_cygwin_pathes($filesref); } 664 665 # The filenames must be collected because of uniqueness 666 # 01-44-~1.DAT, 01-44-~2.DAT, ... 667 # my @shortnames = (); 668 my %shortnames = (); 669 670 installer::windows::idtglobal::write_idt_header(\@filetable, "file"); 671 installer::windows::idtglobal::write_idt_header(\@filehashtable, "filehash"); 672 673 for ( my $i = 0; $i <= $#{$filesref}; $i++ ) 674 { 675 my %file = (); | |
676 | 901 |
677 my $onefile = ${$filesref}[$i]; | |
678 | 902 |
679 my $styles = ""; 680 if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; } 681 if (( $styles =~ /\bJAVAFILE\b/ ) && ( ! ($allvariables->{'JAVAPRODUCT'} ))) { next; } | 903sub has_style ($$) 904{ 905 my ($style_list_string, $style_name) = @_; |
682 | 906 |
683 $file{'Component_'} = get_file_component_name($onefile, $filesref); 684 $file{'File'} = generate_unique_filename_for_filetable($onefile, $file{'Component_'}); 685 686 $onefile->{'uniquename'} = $file{'File'}; 687 $onefile->{'componentname'} = $file{'Component_'}; | 907 return 0 unless defined $style_list_string; 908 return $style_list_string =~ /\b$style_name\b/ ? 1 : 0; 909} |
688 | 910 |
689 # Collecting all components 690 # if (!(installer::existence::exists_in_array($file{'Component_'}, $allfilecomponentsref))) { push(@{$allfilecomponentsref}, $file{'Component_'}); } | |
691 | 911 |
692 if ( ! exists($allfilecomponents{$file{'Component_'}}) ) { $allfilecomponents{$file{'Component_'}} = 1; } | |
693 | 912 |
694 $file{'FileName'} = generate_filename_for_filetable($onefile, \%shortnames); | |
695 | 913 |
696 $file{'FileSize'} = get_filesize($onefile); | 914sub prepare_file_table_creation ($$$) 915{ 916 my ($file_list, $directory_list, $allvariables) = @_; 917 918 if ( $^O =~ /cygwin/i ) 919 { 920 installer::worker::generate_cygwin_pathes($file_list); 921 } |
697 | 922 |
698 $file{'Version'} = get_fileversion($onefile, $allvariables, $styles); | 923 # Reset the fields 'sequencenumber' and 'uniquename'. They should not yet exist but better be sure. 924 foreach my $file (@$file_list) 925 { 926 delete $file->{'sequencenumber'}; 927 delete $file->{'uniquename'}; 928 } |
699 | 929 |
700 $file{'Language'} = get_language_for_file($onefile); 701 702 if ( $styles =~ /\bDONT_PACK\b/ ) { $file{'Attributes'} = "8192"; } 703 else { $file{'Attributes'} = "16384"; } | 930 # Create FileSequenceList object for the old sequence data. 931 if (defined $installer::globals::source_msi) 932 { 933 my $previous_sequence_data = new installer::patch::FileSequenceList(); 934 $previous_sequence_data->SetFromMsi($installer::globals::source_msi); 935 my @added_files = retrieve_sequence_and_uniquename($file_list, $previous_sequence_data); 936 937 # Extract just the unique names. 938 my %target_unique_names = map {$_->{'uniquename'} => 1} @$file_list; 939 my @removed_items = $previous_sequence_data->get_removed_files(\%target_unique_names); |
704 | 940 |
705 # $file{'Attributes'} = "16384"; # Sourcefile is packed 706 # $file{'Attributes'} = "8192"; # Sourcefile is unpacked | 941 $installer::logger::Lang->printf( 942 "there are %d files that have been removed from source and %d files added\n", 943 scalar @removed_items, 944 scalar @added_files); |
707 | 945 |
708 $installer::globals::insert_file_at_end = 0; 709 $counter++; 710 $file{'Sequence'} = $counter; | 946 my $file_map = $installer::globals::source_msi->GetFileMap(); 947 my $index = 0; 948 foreach my $removed_row (@removed_items) 949 { 950 $installer::logger::Lang->printf(" removed file %d: %s\n", 951 ++$index, 952 $removed_row->GetValue('File')); 953 my $directory = $file_map->{$removed_row->GetValue('File')}->{'directory'}; 954 while (my ($key,$value) = each %$directory) 955 { 956 $installer::logger::Lang->printf(" %16s -> %s\n", $key, $value); 957 } 958 } 959 $index = 0; 960 foreach my $added_file (@added_files) 961 { 962 $installer::logger::Lang->printf(" added file %d: %s\n", 963 ++$index, 964 $added_file->{'uniquename'}); 965 installer::scriptitems::print_script_item($added_file); 966 } 967 my @new_files = create_items_for_missing_files( 968 \@removed_items, 969 $installer::globals::source_msi, 970 $directory_list); 971 push @$file_list, @new_files; 972 } 973 assign_missing_sequence_numbers($file_list); |
711 | 974 |
712 $onefile->{'sequencenumber'} = $file{'Sequence'}; 713 714 my $oneline = $file{'File'} . "\t" . $file{'Component_'} . "\t" . $file{'FileName'} . "\t" 715 . $file{'FileSize'} . "\t" . $file{'Version'} . "\t" . $file{'Language'} . "\t" 716 . $file{'Attributes'} . "\t" . $file{'Sequence'} . "\n"; | 975 foreach my $file (@$file_list) 976 { 977 if ( ! defined $file->{'componentname'}) 978 { 979 $file->{'componentname'} = get_file_component_name($file, $file_list); 980 } 981 if ( ! defined $file->{'uniquename'}) 982 { 983 $file->{'uniquename'} = generate_unique_filename_for_filetable($file->{'Name'}); 984 } |
717 | 985 |
718 push(@filetable, $oneline); 719 720 if ( ! $installer::globals::insert_file_at_end ) { push(@allfiles, $onefile); } 721 | |
722 # Collecting all component conditions | 986 # Collecting all component conditions |
723 if ( $onefile->{'ComponentCondition'} ) | 987 if ( $file->{'ComponentCondition'} ) |
724 { | 988 { |
725 if ( ! exists($installer::globals::componentcondition{$file{'Component_'}})) | 989 if ( ! exists($installer::globals::componentcondition{$file->{'componentname'}})) |
726 { | 990 { |
727 $installer::globals::componentcondition{$file{'Component_'}} = $onefile->{'ComponentCondition'}; | 991 $installer::globals::componentcondition{$file->{'componentname'}} 992 = $file->{'ComponentCondition'}; |
728 } 729 } | 993 } 994 } |
730 | |
731 # Collecting also all tree conditions for multilayer products | 995 # Collecting also all tree conditions for multilayer products |
732 get_tree_condition_for_component($onefile, $file{'Component_'}); | 996 get_tree_condition_for_component($file, $file->{'componentname'}); |
733 734 # Collecting all component names, that have flag VERSION_INDEPENDENT_COMP_ID 735 # This should be all components with constant API, for example URE | 997 998 # Collecting all component names, that have flag VERSION_INDEPENDENT_COMP_ID 999 # This should be all components with constant API, for example URE |
736 if ( $styles =~ /\bVERSION_INDEPENDENT_COMP_ID\b/ ) | 1000 if (has_style($file->{'Styles'}, "VERSION_INDEPENDENT_COMP_ID")) |
737 { | 1001 { |
738 $installer::globals::base_independent_components{$onefile->{'componentname'}} = 1; | 1002 $installer::globals::base_independent_components{$file->{'componentname'}} = 1; |
739 } 740 | 1003 } 1004 |
741 # Collecting all component ids, that are defined at files in scp project (should not be used anymore) 742 if ( $onefile->{'CompID'} ) 743 { 744 if ( ! exists($installer::globals::componentid{$onefile->{'componentname'}})) 745 { 746 $installer::globals::componentid{$onefile->{'componentname'}} = $onefile->{'CompID'}; 747 } 748 else 749 { 750 if ( $installer::globals::componentid{$onefile->{'componentname'}} ne $onefile->{'CompID'} ) 751 { 752 installer::exiter::exit_program("ERROR: There is already a ComponentID for component \"$onefile->{'componentname'}\" : \"$installer::globals::componentid{$onefile->{'componentname'}}\" . File \"$onefile->{'gid'}\" uses \"$onefile->{'CompID'}\" !", "create_files_table"); 753 } 754 } 755 756 # Also checking vice versa. Is this ComponentID already used? If yes, is the componentname the same? 757 758 if ( ! exists($installer::globals::comparecomponentname{$onefile->{'CompID'}})) 759 { 760 $installer::globals::comparecomponentname{$onefile->{'CompID'}} = $onefile->{'componentname'}; 761 } 762 else 763 { 764 if ( $installer::globals::comparecomponentname{$onefile->{'CompID'}} ne $onefile->{'componentname'} ) 765 { 766 installer::exiter::exit_program("ERROR: There is already a component for ComponentID \"$onefile->{'CompID'}\" : \"$installer::globals::comparecomponentname{$onefile->{'CompID'}}\" . File \"$onefile->{'gid'}\" has same component id but is included in component \"$onefile->{'componentname'}\" !", "create_files_table"); 767 } 768 } 769 } 770 771 # Collecting all language specific conditions 772 # if ( $onefile->{'haslanguagemodule'} ) 773 if ( $onefile->{'ismultilingual'} ) | 1005 # Special handling for files in PREDEFINED_OSSHELLNEWDIR. These components 1006 # need as KeyPath a RegistryItem in HKCU 1007 if ($file->{'needs_user_registry_key'} 1008 || (defined $file->{'Dir'} && $file->{'Dir'} =~ /\bPREDEFINED_OSSHELLNEWDIR\b/)) |
774 { | 1009 { |
775 if ( $onefile->{'ComponentCondition'} ) { installer::exiter::exit_program("ERROR: Cannot set language condition. There is already another component condition for file $onefile->{'gid'}: \"$onefile->{'ComponentCondition'}\" !", "create_files_table"); } | 1010 my $keypath = generate_registry_keypath($file); 1011 $file->{'userregkeypath'} = $keypath; 1012 push(@installer::globals::userregistrycollector, $file); 1013 $installer::globals::addeduserregitrykeys = 1; 1014 } |
776 | 1015 |
777 if ( $onefile->{'specificlanguage'} eq "" ) { installer::exiter::exit_program("ERROR: There is no specific language for file at language module: $onefile->{'gid'} !", "create_files_table"); } 778 my $locallanguage = $onefile->{'specificlanguage'}; 779 my $property = "IS" . $file{'Language'}; 780 my $value = 1; 781 my $condition = $property . "=" . $value; 782 783 $onefile->{'ComponentCondition'} = $condition; | 1016 $file->{'windows_language'} = get_language_for_file($file); |
784 | 1017 |
785 if ( exists($installer::globals::componentcondition{$file{'Component_'}})) 786 { 787 if ( $installer::globals::componentcondition{$file{'Component_'}} ne $condition ) { installer::exiter::exit_program("ERROR: There is already another component condition for file $onefile->{'gid'}: \"$installer::globals::componentcondition{$file{'Component_'}}\" and \"$condition\" !", "create_files_table"); } 788 } 789 else 790 { 791 $installer::globals::componentcondition{$file{'Component_'}} = $condition; 792 } | 1018 process_language_conditions($file); 1019 } |
793 | 1020 |
794 # collecting all properties for table Property 795 if ( ! exists($installer::globals::languageproperties{$property}) ) { $installer::globals::languageproperties{$property} = $value; } 796 } | 1021 # The filenames must be collected because of uniqueness 1022 # 01-44-~1.DAT, 01-44-~2.DAT, ... 1023 my %shortnames = (); 1024 foreach my $file (@$file_list) 1025 { 1026 $file->{'short_name'} = generate_filename_for_filetable($file, \%shortnames); 1027 } 1028} |
797 | 1029 |
798 if ( $installer::globals::prepare_winpatch ) 799 { 800 my $path = $onefile->{'sourcepath'}; 801 if ( $^O =~ /cygwin/i ) { $path = $onefile->{'cyg_sourcepath'}; } | |
802 | 1030 |
803 open(FILE, $path) or die "ERROR: Can't open $path for creating file hash"; 804 binmode(FILE); 805 my $hashinfo = pack("l", 20); 806 $hashinfo .= Digest::MD5->new->addfile(*FILE)->digest; | |
807 | 1031 |
808 my @i = unpack ('x[l]l4', $hashinfo); 809 $oneline = $file{'File'} . "\t" . 810 "0" . "\t" . 811 $i[0] . "\t" . 812 $i[1] . "\t" . 813 $i[2] . "\t" . 814 $i[3] . "\n"; 815 push (@filehashtable, $oneline); 816 } | |
817 | 1032 |
818 # Saving the sequence number in a hash with uniquefilename as key. 819 # This is used for better performance in "save_packorder" 820 $installer::globals::uniquefilenamesequence{$onefile->{'uniquename'}} = $onefile->{'sequencenumber'}; 821 822 # Special handling for files in PREDEFINED_OSSHELLNEWDIR. These components 823 # need as KeyPath a RegistryItem in HKCU 824 my $destdir = ""; 825 if ( $onefile->{'Dir'} ) { $destdir = $onefile->{'Dir'}; } | 1033sub create_file_table_data ($$) 1034{ 1035 my ($file_list, $allvariables) = @_; 1036 1037 my @file_table_data = (); 1038 foreach my $file (@$file_list) 1039 { 1040 my $attributes; 1041 if (has_style($file->{'Styles'}, "DONT_PACK")) 1042 { 1043 # Sourcefile is unpacked (msidbFileAttributesNoncompressed). 1044 $attributes = "8192"; 1045 } 1046 else 1047 { 1048 # Sourcefile is packed (msidbFileAttributesCompressed). 1049 $attributes = "16384"; 1050 } |
826 | 1051 |
827 if (( $destdir =~ /\bPREDEFINED_OSSHELLNEWDIR\b/ ) || ( $onefile->{'needs_user_registry_key'} )) 828 { 829 my $keypath = generate_registry_keypath($onefile); 830 $onefile->{'userregkeypath'} = $keypath; 831 push(@installer::globals::userregistrycollector, $onefile); 832 $installer::globals::addeduserregitrykeys = 1; 833 } | 1052 my $row_data = { 1053 'File' => $file->{'uniquename'}, 1054 'Component_' => $file->{'componentname'}, 1055 'FileName' => $file->{'short_name'}, 1056 'FileSize' => get_filesize($file), 1057 'Version' => get_fileversion($file, $allvariables), 1058 'Language' => $file->{'windows_language'}, 1059 'Attributes' => $attributes, 1060 'Sequence' => $file->{'sequencenumber'} 1061 }; 1062 push @file_table_data, $row_data; |
834 } 835 | 1063 } 1064 |
836 # putting content from %allfilecomponents to $allfilecomponentsref for later usage 837 foreach $localkey (keys %allfilecomponents ) { push( @{$allfilecomponentsref}, $localkey); } | 1065 return \@file_table_data; 1066} |
838 | 1067 |
839 my $filetablename = $basedir . $installer::globals::separator . "File.idt"; | 1068 1069 1070 1071sub collect_components ($) 1072{ 1073 my ($file_list) = @_; 1074 1075 my %components = (); 1076 foreach my $file (@$file_list) 1077 { 1078 $components{$file->{'componentname'}} = 1; 1079 } 1080 return keys %components; 1081} 1082 1083 1084 1085 1086=head filter_files($file_list, $allvariables) 1087 1088 Filter out Java files when not building a Java product. 1089 1090 Is this still triggered? 1091 1092=cut 1093sub filter_files ($$) 1094{ 1095 my ($file_list, $allvariables) = @_; 1096 1097 if ($allvariables->{'JAVAPRODUCT'}) 1098 { 1099 return $file_list; 1100 } 1101 else 1102 { 1103 my @filtered_files = (); 1104 foreach my $file (@$file_list) 1105 { 1106 if ( ! has_style($file->{'Styles'}, "JAVAFILE")) 1107 { 1108 push @filtered_files, $file; 1109 } 1110 } 1111 return \@filtered_files; 1112 } 1113} 1114 1115 1116 1117 1118# Structure of the files table: 1119# File Component_ FileName FileSize Version Language Attributes Sequence 1120sub create_file_table ($$) 1121{ 1122 my ($file_table_data, $basedir) = @_; 1123 1124 # Set up the 'File' table. 1125 my @filetable = (); 1126 installer::windows::idtglobal::write_idt_header(\@filetable, "file"); 1127 my @keys = ('File', 'Component_', 'FileName', 'FileSize', 'Version', 'Language', 'Attributes', 'Sequence'); 1128 my $index = 0; 1129 foreach my $row_data (@$file_table_data) 1130 { 1131 ++$index; 1132 my @values = map {$row_data->{$_}} @keys; 1133 my $line = join("\t", @values) . "\n"; 1134 push(@filetable, $line); 1135 } 1136 1137 my $filetablename = $basedir . $installer::globals::separator . "File.idt"; |
840 installer::files::save_file($filetablename ,\@filetable); 841 $installer::logger::Lang->print("\n"); 842 $installer::logger::Lang->printf("Created idt file: %s\n", $filetablename); | 1138 installer::files::save_file($filetablename ,\@filetable); 1139 $installer::logger::Lang->print("\n"); 1140 $installer::logger::Lang->printf("Created idt file: %s\n", $filetablename); |
1141} |
|
843 | 1142 |
844 $installer::logger::Lang->add_timestamp("Performance Info: File Table end"); 845 846 my $filehashtablename = $basedir . $installer::globals::separator . "MsiFileHash.idt"; 847 installer::files::save_file($filehashtablename ,\@filehashtable); 848 $installer::logger::Lang->print("\n"); 849 $installer::logger::Lang->printf("Created idt file: %s\n", $filehashtablename); | |
850 | 1143 |
851 # Now the new files can be added to the files collector (only in update packaging processes) 852 if ( $installer::globals::newfilesexist ) 853 { 854 foreach my $seq (sort keys %installer::globals::newfilescollector) { push(@allfiles, $installer::globals::newfilescollector{$seq}) } 855 } | |
856 | 1144 |
857 return \@allfiles; | 1145 1146sub create_filehash_table ($$) 1147{ 1148 my ($file_list, $basedir) = @_; 1149 1150 my @filehashtable = (); 1151 1152 if ( $installer::globals::prepare_winpatch ) 1153 { 1154 1155 installer::windows::idtglobal::write_idt_header(\@filehashtable, "filehash"); 1156 1157 foreach my $file (@$file_list) 1158 { 1159 my $path = $file->{'sourcepath'}; 1160 if ($^O =~ /cygwin/i) 1161 { 1162 $path = $file->{'cyg_sourcepath'}; 1163 } 1164 1165 open(FILE, $path) or die "ERROR: Can't open $path for creating file hash"; 1166 binmode(FILE); 1167 my $hashinfo = pack("l", 20); 1168 $hashinfo .= Digest::MD5->new->addfile(*FILE)->digest; 1169 1170 my @i = unpack ('x[l]l4', $hashinfo); 1171 my $oneline = join("\t", 1172 ( 1173 $file->{'uniquename'}, 1174 "0", 1175 @i 1176 )); 1177 push (@filehashtable, $oneline . "\n"); 1178 } 1179 1180 my $filehashtablename = $basedir . $installer::globals::separator . "MsiFileHash.idt"; 1181 installer::files::save_file($filehashtablename ,\@filehashtable); 1182 $installer::logger::Lang->print("\n"); 1183 $installer::logger::Lang->printf("Created idt file: %s\n", $filehashtablename); 1184 } |
858} 859 | 1185} 1186 |
1187 |
|
8601; | 11881; |