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/04 09:51:31 UTC

svn commit: r1547732 [3/4] - in /openoffice/trunk/main: instsetoo_native/data/ 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/modules/installer/windows/directory.pm
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/solenv/bin/modules/installer/windows/directory.pm?rev=1547732&r1=1547731&r2=1547732&view=diff
==============================================================================
--- openoffice/trunk/main/solenv/bin/modules/installer/windows/directory.pm (original)
+++ openoffice/trunk/main/solenv/bin/modules/installer/windows/directory.pm Wed Dec  4 08:51:30 2013
@@ -29,6 +29,7 @@ use installer::globals;
 use installer::pathanalyzer;
 use installer::windows::idtglobal;
 use installer::windows::msiglobal;
+use installer::scriptitems;
 
 use strict;
 
@@ -133,172 +134,305 @@ sub make_short_dir_version ($)
 	return $shortstring;
 }
 
-##############################################################
-# Adding unique directory names to the directory collection
-##############################################################
 
-sub create_unique_directorynames
+
+
+=head2 get_unique_name ($hostname, $unique_map, $shortdirhash, $shortdirhashreverse)
+
+    Return a long and a short unique name for the given $hostname.
+    Despite the function name and unlike the generation of unique
+    names for files, the returned names are not really unique.  Quite
+    the opposite.  The returned names are quaranteed to return the
+    same result for the same input.
+
+    The returned short name has at most length 70.
+    
+=cut
+sub get_unique_name ($$)
 {
-	my ($directoryref, $allvariables) = @_;
+    my ($hostname, $hostnamehash) = @_;
 
-	$installer::globals::officeinstalldirectoryset = 0;
+    # Make sure that we where not called for this hostname before.  Otherwise the other test would be triggered.
+    if (defined $hostnamehash->{$hostname})
+    {
+        installer::exiter::exit_program(
+            "ERROR: get_unique_name was already called for hostname ".$hostname,
+            "get_unique_name");
+    }
+    $hostnamehash->{$hostname} = 1;
+    
+    my $uniquename = $hostname;
 
-	my %completedirhashstep1 = ();
-	my %shortdirhash = ();
-	my %shortdirhashreverse = ();
-	my $infoline = "";
-	my $errorcount = 0;
+    $uniquename =~ s/^\s*//g;				# removing beginning white spaces
+    $uniquename =~ s/\s*$//g;				# removing ending white spaces
+    $uniquename =~ s/\s//g;					# removing white spaces
+    $uniquename =~ s/\_//g;					# removing existing underlines
+    $uniquename =~ s/\.//g;					# removing dots in directoryname
+    $uniquename =~ s/OpenOffice/OO/g;
+    
+    $uniquename =~ s/\Q$installer::globals::separator\E/\_/g;	# replacing slash and backslash with underline
+    
+    $uniquename =~ s/_registry/_rgy/g;
+    $uniquename =~ s/_registration/_rgn/g;
+    $uniquename =~ s/_extension/_ext/g;
+    $uniquename =~ s/_frame/_frm/g;
+    $uniquename =~ s/_table/_tbl/g;
+    $uniquename =~ s/_chart/_crt/g;
 
-	for ( my $i = 0; $i <= $#{$directoryref}; $i++ )
-	{
-		my $onedir = ${$directoryref}[$i];
-		my $uniquename = $onedir->{'HostName'};
+    my $short_uniquename = make_short_dir_version($uniquename);
 
-		my $styles = "";
-		if ( $onedir->{'Styles'} ) { $styles = $onedir->{'Styles'}; }
+    return ($uniquename, $short_uniquename);
+}
 
-		$uniquename =~ s/^\s*//g;				# removing beginning white spaces
-		$uniquename =~ s/\s*$//g;				# removing ending white spaces
-		$uniquename =~ s/\s//g;					# removing white spaces
-		$uniquename =~ s/\_//g;					# removing existing underlines
-		$uniquename =~ s/\.//g;					# removing dots in directoryname
-		$uniquename =~ s/OpenOffice/OO/g;
 
-		$uniquename =~ s/\Q$installer::globals::separator\E/\_/g;	# replacing slash and backslash with underline
 
-		$uniquename =~ s/_registry/_rgy/g;
-		$uniquename =~ s/_registration/_rgn/g;
-		$uniquename =~ s/_extension/_ext/g;
-		$uniquename =~ s/_frame/_frm/g;
-		$uniquename =~ s/_table/_tbl/g;
-		$uniquename =~ s/_chart/_crt/g;
 
-		# The names after this small changes must still be unique!
-		if ( exists($completedirhashstep1{$uniquename}) ) { installer::exiter::exit_program("ERROR: Error in packaging process. Unallowed modification of directory name, not unique (step 1): \"$uniquename\".", "create_unique_directorynames"); }
-		$completedirhashstep1{$uniquename} = 1;
+=head2 check_unique_directorynames($directories)
 
-		# Starting to make unique name for the parent and its directory
-		my $originaluniquename = $uniquename;
+    The one really important check is made in get_unique_name().  It
+    checks that get_unique_name() is not called twice for the same
+    directory host name.  The tests in this function contain the
+    legacy tests that basically only check if there where a collision
+    of the partial MD5 sum that is used to make the short unique names
+    unique.
 
-		$uniquename = make_short_dir_version($uniquename);
+    The maps $unique_map, $shortdirhash, $shortdirhashreverse are used
+    only to check that _different_ input names are mapped to different
+    results.  They are not used to influence the result.  That assumes
+    that this function is called only once for every directory
+    hostname.
+=cut
+sub check_unique_directorynames ($)
+{
+    my ($directories) = @_;
 
-		# Checking if the same directory already exists, but has another short version.
-		if (( exists($shortdirhash{$originaluniquename}) ) && ( $shortdirhash{$originaluniquename} ne $uniquename )) { installer::exiter::exit_program("ERROR: Error in packaging process. Unallowed modification of directory name, not unique (step 2A): \"$uniquename\".", "create_unique_directorynames"); }
+    my %completedirhashstep1 = ();
+	my %shortdirhash = ();
+	my %shortdirhashreverse = ();
 
-		# Also checking vice versa
-		# Checking if the same short directory already exists, but has another long version.
-		if (( exists($shortdirhashreverse{$uniquename}) ) && ( $shortdirhashreverse{$uniquename} ne $originaluniquename )) { installer::exiter::exit_program("ERROR: Error in packaging process. Unallowed modification of directory name, not unique (step 2B): \"$uniquename\".", "create_unique_directorynames"); }
+    # Check unique name of directories.
+    foreach my $directory (@$directories)
+    {
+        my ($long_uniquename, $short_uniquename) = ($directory->{'long_uniquename'}, $directory->{'uniquename'});
+        
+        # The names after this small changes must still be unique!
+        if (exists($completedirhashstep1{$long_uniquename}))
+        {
+            installer::exiter::exit_program(
+                sprintf("ERROR: Unallowed modification of directory name, not unique (step 1): \"%s\".",
+                    $short_uniquename),
+                "check_unique_directorynames");
+        }
+        $completedirhashstep1{$long_uniquename} = 1;
+
+
+        # Checking if the same directory already exists, but has another short version.
+        if (exists($shortdirhash{$long_uniquename})
+            && ( $shortdirhash{$long_uniquename} ne $short_uniquename ))
+        {
+            installer::exiter::exit_program(
+                sprintf(
+                    "ERROR: Unallowed modification of directory name, not unique (step 2A): \"%s\".",
+                    $short_uniquename),
+                "check_unique_directorynames");
+        }
+        $shortdirhash{$long_uniquename} = $short_uniquename;
+
+        # Also checking vice versa
+        # Checking if the same short directory already exists, but has another long version.
+        if (exists($shortdirhashreverse{$short_uniquename})
+            && ( $shortdirhashreverse{$short_uniquename} ne $long_uniquename ))
+        {
+            installer::exiter::exit_program(
+                sprintf(
+                    "ERROR: Unallowed modification of directory name, not unique (step 2B): \"%s\".",
+                    $short_uniquename),
+                "check_unique_directorynames");
+        }
+        $shortdirhashreverse{$short_uniquename} = $long_uniquename;
+    }
+
+    # Check unique name of parents
+    foreach my $directory (@$directories)
+    {
+        my ($long_uniquename, $short_uniquename)
+            = ($directory->{'long_uniqueparentname'}, $directory->{'uniqueparentname'});
+
+        # Again checking if the same directory already exists, but has another short version.
+        if (exists($shortdirhash{$long_uniquename})
+            && ( $shortdirhash{$long_uniquename} ne $short_uniquename ))
+        {
+            installer::exiter::exit_program(
+                sprintf(
+                    "ERROR: Unallowed modification of directory name, not unique (step 3A): \"%s\".",
+                    $short_uniquename),
+                "check_unique_directorynames");
+        }
+        $shortdirhash{$long_uniquename} = $short_uniquename;
+
+        # Also checking vice versa
+        # Checking if the same short directory already exists, but has another long version.
+        if (exists($shortdirhashreverse{$short_uniquename})
+            && ( $shortdirhashreverse{$short_uniquename} ne $long_uniquename ))
+        {
+            installer::exiter::exit_program(
+                sprintf(
+                    "ERROR: Unallowed modification of directory name, not unique (step 3B): \"%s\".",
+                    $short_uniquename),
+                "check_unique_directorynames");
+        }
+        $shortdirhashreverse{$short_uniquename} = $long_uniquename;
+    }
+}
 
-		# Creating assignment from long to short directory names
-		$shortdirhash{$originaluniquename} = $uniquename;
-		$shortdirhashreverse{$uniquename} = $originaluniquename;
 
-		# Important: The unique parent is generated from the string $originaluniquename (with the use of underlines).
 
-		my $uniqueparentname = $originaluniquename;
-		my $keepparent = 1;
 
-		if ( $uniqueparentname =~ /^\s*(.*)\_(.*?)\s*$/ )	# the underline is now the separator
-		{
-			$uniqueparentname = $1;
-			$keepparent = 0;
-		}
-		else
-		{
-			$uniqueparentname = $installer::globals::programfilesfolder;
-			$keepparent = 1;
-		}
+sub get_unique_parent_name ($$)
+{
+    my ($uniqueparentname, $styles) = @_;
+
+    my $keepparent = 1;
+
+    if ( $uniqueparentname =~ /^\s*(.*)\_(.*?)\s*$/ )	# the underline is now the separator
+    {
+        $uniqueparentname = $1;
+        $keepparent = 0;
+    }
+    else
+    {
+        $uniqueparentname = $installer::globals::programfilesfolder;
+        $keepparent = 1;
+    }
+
+    if ( $styles =~ /\bPROGRAMFILESFOLDER\b/ )
+    {
+        $uniqueparentname = $installer::globals::programfilesfolder;
+        $keepparent = 1;
+    }
+    if ( $styles =~ /\bCOMMONFILESFOLDER\b/ )
+    {
+        $uniqueparentname = $installer::globals::commonfilesfolder;
+        $keepparent = 1;
+    }
+    if ( $styles =~ /\bCOMMONAPPDATAFOLDER\b/ )
+    {
+        $uniqueparentname = $installer::globals::commonappdatafolder;
+        $keepparent = 1;
+    }
+    if ( $styles =~ /\bLOCALAPPDATAFOLDER\b/ )
+    {
+        $uniqueparentname = $installer::globals::localappdatafolder;
+        $keepparent = 1;
+    }
+    
+    if ( $styles =~ /\bSHAREPOINTPATH\b/ )
+    {
+        $uniqueparentname = "SHAREPOINTPATH";
+        $installer::globals::usesharepointpath = 1;
+        $keepparent = 1;
+    }
+
+    # also setting short directory name for the parent
+		
+    my $originaluniqueparentname = $uniqueparentname;
+
+    if ( ! $keepparent )
+    {
+        $uniqueparentname = make_short_dir_version($uniqueparentname);
+    }
 
-		if ( $styles =~ /\bPROGRAMFILESFOLDER\b/ )
-		{
-			$uniqueparentname = $installer::globals::programfilesfolder;
-			$keepparent = 1;
-		}
-		if ( $styles =~ /\bCOMMONFILESFOLDER\b/ )
-		{
-			$uniqueparentname = $installer::globals::commonfilesfolder;
-			$keepparent = 1;
-		}
-		if ( $styles =~ /\bCOMMONAPPDATAFOLDER\b/ )
-		{
-			$uniqueparentname = $installer::globals::commonappdatafolder;
-			$keepparent = 1;
-		}
-		if ( $styles =~ /\bLOCALAPPDATAFOLDER\b/ )
-		{
-			$uniqueparentname = $installer::globals::localappdatafolder;
-			$keepparent = 1;
-		}
+    return ($originaluniqueparentname, $uniqueparentname);
+}
 
-		if ( $styles =~ /\bSHAREPOINTPATH\b/ )
-		{
-			$uniqueparentname = "SHAREPOINTPATH";
-			$installer::globals::usesharepointpath = 1;
-			$keepparent = 1;
-		}
 
-		# also setting short directory name for the parent
-		
-		my $originaluniqueparentname = $uniqueparentname;
 
-		if ( ! $keepparent )
-		{
-			$uniqueparentname = make_short_dir_version($uniqueparentname);
-		}
 
-		# Again checking if the same directory already exists, but has another short version.
-		if (( exists($shortdirhash{$originaluniqueparentname}) ) && ( $shortdirhash{$originaluniqueparentname} ne $uniqueparentname )) { installer::exiter::exit_program("ERROR: Error in packaging process. Unallowed modification of directory name, not unique (step 3A): \"$uniqueparentname\".", "create_unique_directorynames"); }
+##############################################################
+# Adding unique directory names to the directory collection
+##############################################################
+
+sub create_unique_directorynames ($)
+{
+	my ($directories) = @_;
+
+	$installer::globals::officeinstalldirectoryset = 0;
+
+    my %hostnamehash = ();
+	my $infoline = "";
+	my $errorcount = 0;
+
+	foreach my $directory (@$directories)
+	{
+        next if defined $directory->{'uniquename'};
+
+        my $styles = $directory->{'Styles'} // "";
 
-		# Also checking vice versa
-		# Checking if the same short directory already exists, but has another long version.
-		if (( exists($shortdirhashreverse{$uniqueparentname}) ) && ( $shortdirhashreverse{$uniqueparentname} ne $originaluniqueparentname )) { installer::exiter::exit_program("ERROR: Error in packaging process. Unallowed modification of directory name, not unique (step 3B): \"$uniqueparentname\".", "create_unique_directorynames"); }
+		my ($originaluniquename, $uniquename) = get_unique_name(
+            $directory->{'HostName'},
+            \%hostnamehash);
+
+		my ($originaluniqueparentname, $uniqueparentname) = get_unique_parent_name(
+            $originaluniquename,
+            $styles);
 
-		$shortdirhash{$originaluniqueparentname} = $uniqueparentname;
-		$shortdirhashreverse{$uniqueparentname} = $originaluniqueparentname;
 		
 		# Hyphen not allowed in database
 		$uniquename =~ s/\-/\_/g;			# making "-" to "_"
 		$uniqueparentname =~ s/\-/\_/g;		# making "-" to "_"
 		
 		# And finally setting the values for the directories
-		$onedir->{'uniquename'} = $uniquename;
-		$onedir->{'uniqueparentname'} = $uniqueparentname;
-
+		$directory->{'uniquename'} = $uniquename;
+		$directory->{'uniqueparentname'} = $uniqueparentname;
+		$directory->{'long_uniquename'} = $originaluniquename;
+		$directory->{'long_uniqueparentname'} = $originaluniqueparentname;
+    }
+
+    # Find the installation directory.
+    foreach my $directory (@$directories)
+    {
+        next unless defined $directory->{'Styles'};
+        
 		# setting the installlocation directory
-		if ( $styles =~ /\bISINSTALLLOCATION\b/ )
-		{
-			if ( $installer::globals::installlocationdirectoryset ) { installer::exiter::exit_program("ERROR: Directory with flag ISINSTALLLOCATION alread set: \"$installer::globals::installlocationdirectory\".", "create_unique_directorynames"); }
-			$installer::globals::installlocationdirectory = $uniquename;
-			$installer::globals::installlocationdirectoryset = 1;
-		}
-		
-		# setting the sundirectory
-		if ( $styles =~ /\bSUNDIRECTORY\b/ )
-		{
-			if ( $installer::globals::vendordirectoryset ) { installer::exiter::exit_program("ERROR: Directory with flag SUNDIRECTORY alread set: \"$installer::globals::vendordirectory\".", "create_unique_directorynames"); }
-			$installer::globals::vendordirectory = $uniquename;
-			$installer::globals::vendordirectoryset = 1;
-		}
-	}	
+		next unless $directory->{'Styles'} =~ /\bISINSTALLLOCATION\b/;
+
+        if ( $installer::globals::installlocationdirectoryset )
+        {
+            installer::exiter::exit_program(
+                sprintf(
+                    "ERROR: Directory with flag ISINSTALLLOCATION alread set: \"%s\".",
+                    $installer::globals::installlocationdirectory),
+                "create_unique_directorynames");
+        }
+
+        $installer::globals::installlocationdirectory = $directory->{'uniquename'};
+        $installer::globals::installlocationdirectoryset = 1;
+    }
 }
 
+
+
+
 #####################################################
 # Adding ":." to selected default directory names
 #####################################################
 
-sub check_sourcedir_addon
+sub update_defaultdir ($$)
 {
 	my ( $onedir, $allvariableshashref ) = @_;
 	
-	if (($installer::globals::addchildprojects) ||
-		($installer::globals::patch) ||
-		($installer::globals::languagepack) || 
-		($allvariableshashref->{'CHANGETARGETDIR'}))
+	if ($installer::globals::addchildprojects
+        || $installer::globals::patch
+        || $installer::globals::languagepack
+        || $allvariableshashref->{'CHANGETARGETDIR'})
 	{
 		my $sourcediraddon = "\:\.";
-		$onedir->{'defaultdir'} = $onedir->{'defaultdir'} . $sourcediraddon;
+		return $onedir->{'defaultdir'} . $sourcediraddon;
 	}			
-	
+	else
+    {
+        return $onedir->{'defaultdir'};
+    }
 }
 
 #####################################################
@@ -310,7 +444,12 @@ sub set_installlocation_directory
 {
 	my ( $directoryref, $allvariableshashref ) = @_;
 	
-	if ( ! $installer::globals::installlocationdirectoryset ) { installer::exiter::exit_program("ERROR: Directory with flag ISINSTALLLOCATION not set!", "set_installlocation_directory"); }
+	if ( ! $installer::globals::installlocationdirectoryset )
+    {
+        installer::exiter::exit_program(
+            "ERROR: Directory with flag ISINSTALLLOCATION not set!",
+            "set_installlocation_directory");
+    }
 	
 	for ( my $i = 0; $i <= $#{$directoryref}; $i++ )
 	{
@@ -319,12 +458,12 @@ sub set_installlocation_directory
 		if ( $onedir->{'uniquename'} eq $installer::globals::installlocationdirectory )
 		{
 			$onedir->{'uniquename'} = "INSTALLLOCATION";
-			check_sourcedir_addon($onedir, $allvariableshashref);
+			$onedir->{'defaultdir'} = update_defaultdir($onedir, $allvariableshashref);
 		}
 		
 		if ( $onedir->{'uniquename'} eq $installer::globals::vendordirectory )
 		{
-			check_sourcedir_addon($onedir, $allvariableshashref);			
+			$onedir->{'defaultdir'} = update_defaultdir($onedir, $allvariableshashref);			
 		}
 		
 		if ( $onedir->{'uniqueparentname'} eq $installer::globals::installlocationdirectory )
@@ -349,6 +488,31 @@ sub get_last_directory_name
 	}
 }
 
+sub setup_global_font_directory_name ($)
+{
+	my ($directories) = @_;
+
+	foreach my $directory (@$directories)
+	{		
+        next unless defined $directory->{'Dir'};
+        next unless defined $directory->{'defaultdir'};
+
+        next if $directory->{'Dir'} ne "PREDEFINED_OSSYSTEMFONTDIR";
+        next if $directory->{'defaultdir'} ne $installer::globals::fontsdirhostname;
+
+        $installer::globals::fontsdirname = $installer::globals::fontsdirhostname;
+        $installer::globals::fontsdirparent = $directory->{'uniqueparentname'};
+
+        $installer::logger::Info->printf("%s, fdhn %s, dd %s, ipn %s, HN %s\n",
+            "PREDEFINED_OSSYSTEMFONTDIR",
+            $installer::globals::fontsdirhostname,
+            $directory->{'defaultdir'},
+            $directory->{'uniqueparentname'},
+            $directory->{'HostName'});
+        installer::scriptitems::print_script_item($directory);
+	}
+}
+
 #####################################################
 # Creating the defaultdir for the file Director.idt
 #####################################################
@@ -391,18 +555,6 @@ sub create_defaultdir_directorynames ($)
 		}
 
 		$onedir->{'defaultdir'} = $defaultdir;
-
-		my $fontdir = "";
-		if ( $onedir->{'Dir'} ) { $fontdir = $onedir->{'Dir'}; }
-
-		my $fontdefaultdir = "";
-		if ( $onedir->{'defaultdir'} ) { $fontdefaultdir = $onedir->{'defaultdir'}; }
-
-		if (( $fontdir eq "PREDEFINED_OSSYSTEMFONTDIR" ) && ( $fontdefaultdir eq $installer::globals::fontsdirhostname ))
-		{
-			$installer::globals::fontsdirname = $onedir->{'defaultdir'};
-			$installer::globals::fontsdirparent = $onedir->{'uniqueparentname'};
-		}
 	}
 }
 
@@ -410,23 +562,28 @@ sub create_defaultdir_directorynames ($)
 # Fill content into the directory table
 ###############################################
 
-sub create_directorytable_from_collection
+sub create_directorytable_from_collection ($$)
 {
 	my ($directorytableref, $directoryref) = @_;
 	
-	for ( my $i = 0; $i <= $#{$directoryref}; $i++ )
+	foreach my $onedir (@$directoryref)
 	{
-		my $onedir = ${$directoryref}[$i];
-		my $hostname = $onedir->{'HostName'};
-		my $dir = "";
-		
-		if ( $onedir->{'Dir'} ) { $dir = $onedir->{'Dir'}; }
-		
-		if (( $dir eq "PREDEFINED_PROGDIR" ) && ( $hostname eq "" )) { next; }	# removing files from root directory
-		
-		my $oneline = $onedir->{'uniquename'} . "\t" . $onedir->{'uniqueparentname'} . "\t" . $onedir->{'defaultdir'} . "\n";
+        # Remove entries for special directories.
+		if (defined $onedir->{'HostName'}
+            && $onedir->{'HostName'} eq ""
+            && defined $onedir->{'Dir'}
+            && $onedir->{'Dir'} eq "PREDEFINED_PROGDIR")
+        {
+            next;
+        }
+        
+		my $oneline = sprintf(
+            "%s\t%s\t%s\n",
+            $onedir->{'uniquename'},
+            $onedir->{'uniqueparentname'},
+            $onedir->{'defaultdir'});
 
-		push(@{$directorytableref}, $oneline);
+		push @{$directorytableref}, $oneline;
 	}
 }
 
@@ -434,19 +591,10 @@ sub create_directorytable_from_collectio
 # Defining the root installation structure
 ###############################################
 
-sub add_root_directories
+sub process_root_directories ($$)
 {
-	my ($directorytableref, $allvariableshashref) = @_;
+	my ($allvariableshashref, $functor) = @_;
 	
-#	my $sourcediraddon = "";
-#	if (($installer::globals::addchildprojects) ||
-#		($installer::globals::patch) ||
-#		($installer::globals::languagepack) || 
-#		($allvariableshashref->{'CHANGETARGETDIR'}))
-#	{
-#		$sourcediraddon = "\:\.";
-#	}
-
 	my $oneline = "";
 
 	if (( ! $installer::globals::patch ) && ( ! $installer::globals::languagepack ) && ( ! $allvariableshashref->{'DONTUSESTARTMENUFOLDER'} ))
@@ -474,76 +622,188 @@ sub add_root_directories
 			$realproductkey =~ s/\ /\_/g; 
 		}
 		
-		my $shortproductkey = installer::windows::idtglobal::make_eight_three_conform($productkey, "dir");		# third parameter not used
+		my $shortproductkey = installer::windows::idtglobal::make_eight_three_conform($productkey, "dir", undef);
 		$shortproductkey =~ s/\s/\_/g;									# changing empty space to underline
-			
-		$oneline = "$installer::globals::officemenufolder\t$installer::globals::programmenufolder\t$shortproductkey|$realproductkey\n";
-		push(@{$directorytableref}, $oneline);
-	}
-
-	$oneline = "TARGETDIR\t\tSourceDir\n";
-	push(@{$directorytableref}, $oneline);
-
-	$oneline = "$installer::globals::programfilesfolder\tTARGETDIR\t.\n";
-	push(@{$directorytableref}, $oneline);
-
-	$oneline = "$installer::globals::programmenufolder\tTARGETDIR\t.\n";
-	push(@{$directorytableref}, $oneline);			
-
-	$oneline = "$installer::globals::startupfolder\tTARGETDIR\t.\n";
-	push(@{$directorytableref}, $oneline);
 
-	$oneline = "$installer::globals::desktopfolder\tTARGETDIR\t.\n";
-	push(@{$directorytableref}, $oneline);
-
-	$oneline = "$installer::globals::startmenufolder\tTARGETDIR\t.\n";
-	push(@{$directorytableref}, $oneline);
-
-	$oneline = "$installer::globals::commonfilesfolder\tTARGETDIR\t.\n";
-	push(@{$directorytableref}, $oneline);
-
-	$oneline = "$installer::globals::commonappdatafolder\tTARGETDIR\t.\n";
-	push(@{$directorytableref}, $oneline);
+        &$functor(
+            $installer::globals::officemenufolder,
+            $installer::globals::programmenufolder,
+            $shortproductkey . "|". $realproductkey);
+	}
 
-	$oneline = "$installer::globals::localappdatafolder\tTARGETDIR\t.\n";
-	push(@{$directorytableref}, $oneline);
+	&$functor("TARGETDIR", "", "SourceDir");
+	&$functor($installer::globals::programfilesfolder, "TARGETDIR", ".");
+    &$functor($installer::globals::programmenufolder, "TARGETDIR", ".");
+    &$functor($installer::globals::startupfolder, "TARGETDIR", ".");
+	&$functor($installer::globals::desktopfolder, "TARGETDIR", ".");
+	&$functor($installer::globals::startmenufolder, "TARGETDIR", ".");
+	&$functor($installer::globals::commonfilesfolder, "TARGETDIR", ".");
+	&$functor($installer::globals::commonappdatafolder, "TARGETDIR", ".");
+	&$functor($installer::globals::localappdatafolder, "TARGETDIR", ".");
 		
 	if ( $installer::globals::usesharepointpath )
 	{
-		$oneline = "SHAREPOINTPATH\tTARGETDIR\t.\n";
-		push(@{$directorytableref}, $oneline);
+		&$functor("SHAREPOINTPATH", "TARGETDIR", ".");
 	}
 
-	$oneline = "$installer::globals::systemfolder\tTARGETDIR\t.\n";
-	push(@{$directorytableref}, $oneline);
+	&$functor($installer::globals::systemfolder, "TARGETDIR", ".");
 
 	my $localtemplatefoldername = $installer::globals::templatefoldername;
 	my $directorytableentry = $localtemplatefoldername;
 	my $shorttemplatefoldername = installer::windows::idtglobal::make_eight_three_conform($localtemplatefoldername, "dir");
-	if ( $shorttemplatefoldername ne $localtemplatefoldername ) { $directorytableentry = "$shorttemplatefoldername|$localtemplatefoldername"; }
-	$oneline = "$installer::globals::templatefolder\tTARGETDIR\t$directorytableentry\n";
-	push(@{$directorytableref}, $oneline);
+	if ( $shorttemplatefoldername ne $localtemplatefoldername )
+    {
+        $directorytableentry = $shorttemplatefoldername . "|" . $localtemplatefoldername;
+    }
+	&$functor($installer::globals::templatefolder, "TARGETDIR", $directorytableentry);
 
 	if ( $installer::globals::fontsdirname )
 	{
-		$oneline = "$installer::globals::fontsfolder\t$installer::globals::fontsdirparent\t$installer::globals::fontsfoldername\:$installer::globals::fontsdirname\n";
+		&$functor(
+             $installer::globals::fontsfolder,
+             $installer::globals::fontsdirparent,
+             $installer::globals::fontsfoldername . ":" . $installer::globals::fontsdirname);
 	}
 	else
 	{
-		$oneline = "$installer::globals::fontsfolder\tTARGETDIR\t$installer::globals::fontsfoldername\n";
+		&$functor(
+             $installer::globals::fontsfolder,
+             "TARGETDIR",
+             $installer::globals::fontsfoldername);
 	}
+}
+
+
 
-	push(@{$directorytableref}, $oneline);
 
+sub find_missing_directories ($$)
+{
+    my ($directories, $allvariableshashref) = @_;
+
+    # Set up the list of target directories.
+    my %target_directories = map {$_->{'uniquename'} => 1} @$directories;
+    # Add special directories.
+    process_root_directories(
+        $allvariableshashref,
+        sub($$$){
+            my ($uniquename, $parentname, $defaultdir) = @_;
+            $target_directories{$uniquename} = 1;
+        }
+    );
+
+    # Set up the list of source directories.
+    my $source_directory_map = $installer::globals::source_msi->GetDirectoryMap();
+    my $source_file_map = $installer::globals::source_msi->GetFileMap();
+    my %source_directories = map {$_->{'unique_name'} => $_} values %$source_directory_map;
+
+    # Find the missing source directories.
+    my @missing_directories = ();
+    foreach my $source_uniquename (keys %source_directories)
+    {
+        if ( ! $target_directories{$source_uniquename})
+        {
+            push @missing_directories, $source_directories{$source_uniquename};
+        }
+    }
+
+    # Report the missing directories.
+    $installer::logger::Info->printf("found %d missing directories\n", scalar @missing_directories);
+    my $index = 0;
+    foreach my $directory_item (@missing_directories)
+    {
+        # Print information about the directory.
+        $installer::logger::Info->printf("missing directory %d: %s\n",
+            ++$index,
+            $directory_item->{'full_target_long_name'});
+        while (my($key,$value) = each %$directory_item)
+        {
+            $installer::logger::Info->printf("    %s -> %s\n", $key, $value);
+        }
+
+        # Print the referencing files.
+        my @filenames = ();
+        while (my ($key,$value) = each %$source_file_map)
+        {
+            if ($value->{'directory'}->{'unique_name'} eq $directory_item->{'unique_name'})
+            {
+                push @filenames, $key;
+            }
+        }
+        $installer::logger::Info->printf("  referencing files are %s\n", join(", ", @filenames));        
+    }
+
+    foreach my $directory (@$directories)
+    {
+        $installer::logger::Lang->printf("target directory %s -> HN %s\n",
+            $directory->{'uniquename'},
+            $directory->{'HostName'});
+        installer::scriptitems::print_script_item($directory);
+    }
+
+    # Setup a map of directory uniquenames to verify that the new
+    # entries don't use unique names that are already in use.
+    my %unique_names = map {$_->{'uniquename'} => $_} @$directories;
+
+    # Create script items for the missing directories.
+    my @new_source_directories = ();
+    foreach my $source_directory_item (@missing_directories)
+    {
+        my $new_directory_item = {
+            'uniquename' => $source_directory_item->{'unique_name'},
+            'uniqueparentname' => $source_directory_item->{'parent'},
+            'defaultdir' => $source_directory_item->{'default_dir'},
+            'HostName' => $source_directory_item->{'full_target_long_name'},
+            'componentname' => $source_directory_item->{'component_name'},
+        };
+
+        if (defined $unique_names{$new_directory_item->{'uniquename'}})
+        {
+            installer::logger::PrintError("newly created directory entry collides with existing directory");
+            last;
+        }
+
+        push @new_source_directories, $new_directory_item;
+    }
+
+    return @new_source_directories;
 }
 
+
+
+
+sub prepare_directory_table_creation ($$)
+{
+	my ($directories, $allvariableshashref) = @_;
+
+    foreach my $directory (@$directories)
+    {
+        delete $directory->{'uniquename'};
+    }
+
+	overwrite_programfilesfolder($allvariableshashref);
+	create_unique_directorynames($directories);
+    check_unique_directorynames($directories);
+	create_defaultdir_directorynames($directories);	# only destdir!
+    setup_global_font_directory_name($directories);
+	set_installlocation_directory($directories, $allvariableshashref);
+
+    if ($installer::globals::is_release)
+    {
+        my @new_directories = find_missing_directories($directories, $allvariableshashref);
+        push @$directories, @new_directories;
+    }
+}
+
+
+
+
 ###############################################
 # Creating the file Director.idt dynamically
 ###############################################
 
-sub create_directory_table ($$$$)
+sub create_directory_table ($$$)
 {
-	my ($directoryref, $basedir, $allvariableshashref, $loggingdir) = @_;
+	my ($directoryref, $basedir, $allvariableshashref) = @_;
 
 	# Structure of the directory table:
 	# Directory Directory_Parent DefaultDir
@@ -556,14 +816,17 @@ sub create_directory_table ($$$$)
 	$installer::logger::Lang->add_timestamp("Performance Info: Directory Table start");
 
 	my @directorytable = ();
-	my $infoline;
-	
-	overwrite_programfilesfolder($allvariableshashref);
-	create_unique_directorynames($directoryref, $allvariableshashref);
-	create_defaultdir_directorynames($directoryref);	# only destdir!
-	set_installlocation_directory($directoryref, $allvariableshashref);
 	installer::windows::idtglobal::write_idt_header(\@directorytable, "directory");
-	add_root_directories(\@directorytable, $allvariableshashref);
+
+    # Add entries for the root directories (and a few special directories like that for fonts).
+    process_root_directories(
+        $allvariableshashref,
+        sub($$$){
+            push(@directorytable, join("\t", @_)."\n");
+        }
+    );
+
+    # Add entries for the non-root directories.
 	create_directorytable_from_collection(\@directorytable, $directoryref);
 
 	# Saving the file
@@ -575,4 +838,5 @@ sub create_directory_table ($$$$)
 	$installer::logger::Lang->add_timestamp("Performance Info: Directory Table end");
 }
 
+
 1;

Modified: openoffice/trunk/main/solenv/bin/modules/installer/windows/file.pm
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/solenv/bin/modules/installer/windows/file.pm?rev=1547732&r1=1547731&r2=1547732&view=diff
==============================================================================
--- openoffice/trunk/main/solenv/bin/modules/installer/windows/file.pm (original)
+++ openoffice/trunk/main/solenv/bin/modules/installer/windows/file.pm Wed Dec  4 08:51:30 2013
@@ -35,6 +35,11 @@ use installer::windows::font;
 use installer::windows::idtglobal;
 use installer::windows::msiglobal;
 use installer::windows::language;
+use installer::patch::InstallationSet;
+use installer::patch::FileSequenceList;
+use File::Basename;
+use File::Spec;
+use strict;
 
 ##########################################################################
 # Assigning one cabinet file to each file. This is requrired,
@@ -357,19 +362,23 @@ sub get_component_from_assigned_file
 # In most cases this is simply the filename.
 ####################################################################
 
-sub generate_unique_filename_for_filetable ($$)
+sub generate_unique_filename_for_filetable ($)
 {
-	my ($fileref, $component) = @_;
+	my ($oldname) = @_;
 
 	# This new filename has to be saved into $fileref, because this is needed to find the source.
 	# The filename sbasic.idx/OFFSETS is changed to OFFSETS, but OFFSETS is not unique.
 	# In this procedure names like OFFSETS5 are produced. And exactly this string has to be added to
 	# the array of all files.
 
-	my $uniquefilename = "";
-	my $counter = 0;
+	my $uniquefilename = $oldname;
+    if ( ! defined $uniquefilename || $uniquefilename eq "")
+    {
+        installer::logger::PrintError("file name does not exist or is empty, can not create unique name for it.");
+        die;
+        return;
+    }
 
-	if ( $fileref->{'Name'} ) { $uniquefilename = $fileref->{'Name'}; }
    	# making /registry/schema/org/openoffice/VCL.xcs to VCL.xcs
 	installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$uniquefilename);
 
@@ -398,6 +407,7 @@ sub generate_unique_filename_for_filetab
 		
 		my $uniquefilenamebase = $uniquefilename;
 		
+        my $counter = 0;
 		do
 		{
 			$counter++;
@@ -491,7 +501,7 @@ sub get_filesize
 
 sub get_fileversion
 {
-	my ($onefile, $allvariables, $styles) = @_;
+	my ($onefile, $allvariables) = @_;
 
 	my $fileversion = "";
 
@@ -532,6 +542,204 @@ sub get_fileversion
 	return $fileversion;
 }
 
+
+
+
+sub retrieve_sequence_and_uniquename ($$)
+{
+    my ($file_list, $source_data) = @_;
+
+    my @added_files = ();
+    
+    # Read the sequence numbers of the previous version.
+    if ($installer::globals::is_release)
+    {
+        foreach my $file (@$file_list)
+        {
+            # Use the source path of the file as key to retrieve sequence number and unique name.
+            # The source path is the part of the 'destination' without the first part.
+            # There is a special case when 'Dir' is PREDEFINED_OSSHELLNEWDIR.
+            my $source_path;
+            if (defined $file->{'Dir'} && $file->{'Dir'} eq "PREDEFINED_OSSHELLNEWDIR")
+            {
+                $source_path = $installer::globals::templatefoldername
+                    . $installer::globals::separator
+                    . $file->{'Name'};
+            }
+            else
+            {
+                $source_path = $file->{'destination'};
+                $source_path =~ s/^[^\/]+\///;
+            }
+            my ($sequence, $uniquename) = $source_data->get_sequence_and_unique_name($source_path);
+            if (defined $sequence && defined $uniquename)
+            {
+                $file->{'sequencenumber'} = $sequence;
+                $file->{'uniquename'} = $uniquename;
+            }
+            else
+            {
+                # No data found in the source release.  File has been added.
+                push @added_files, $file;
+            }
+        }
+    }
+
+    return @added_files;
+}
+
+
+
+
+=head2 assign_mssing_sequence_numbers ($file_list)
+
+    Assign sequence numbers where still missing.
+    
+    When we are preparing a patch then all files that have no sequence numbers
+    at this point are new.  Otherwise no file has a sequence number yet.
+    
+=cut
+sub assign_missing_sequence_numbers ($)
+{
+    my ($file_list) = @_;
+
+    # First, set up a hash on the sequence numbers that are already in use.
+    my %used_sequence_numbers = ();
+    foreach my $file (@$file_list)
+    {
+        next unless defined $file->{'sequencenumber'};
+        $used_sequence_numbers{$file->{'sequencenumber'}} = 1;
+    }
+
+    # Assign sequence numbers.  Try consecutive numbers, starting at 1.
+    my $current_sequence_number = 1;
+    foreach my $file (@$file_list)
+    {
+        # Skip over all files that already have sequence numbers.
+        next if defined $file->{'sequencenumber'};
+
+        # Find the next available number.
+        while (defined $used_sequence_numbers{$current_sequence_number})
+        {
+            ++$current_sequence_number;
+        }
+
+        # Use the number and mark it as used.
+        $file->{'sequencenumber'} = $current_sequence_number;
+        $used_sequence_numbers{$current_sequence_number} = 1;
+    }
+}
+
+
+
+
+sub create_items_for_missing_files ($$$)
+{
+    my ($missing_items, $msi, $directory_list) = @_;
+
+    # For creation of the FeatureComponent table (in a later step) we
+    # have to provide references from the file to component and
+    # modules (ie features).  Note that Each file belongs to exactly
+    # one component but one component can belong to multiple features.
+    my $component_to_features_map = create_feature_component_map($msi);
+    
+    my @new_files = ();
+    foreach my $row (@$missing_items)
+    {
+        $installer::logger::Info->printf("creating new file item for '%s'\n", $row->GetValue('File'));
+        my $file_item = create_script_item_for_deleted_file($row, $msi, $component_to_features_map);
+        push @new_files, $file_item;
+    }
+
+    return @new_files;
+}
+
+
+
+
+sub create_script_item_for_deleted_file ($$$)
+{
+    my ($file_row, $msi, $component_to_features_map) = @_;
+
+    my $uniquename = $file_row->GetValue('File');
+
+    my $file_map = $msi->GetFileMap();
+
+    my $directory_item = $file_map->{$uniquename}->{'directory'};
+    my $source_path = $directory_item->{'full_source_long_name'};
+    my $target_path = $directory_item->{'full_target_long_name'};
+    my $full_source_name = File::Spec->catfile(
+        installer::patch::InstallationSet::GetUnpackedCabPath(
+            $msi->{'version'},
+            $msi->{'is_current_version'},
+            $msi->{'language'},
+            $msi->{'package_format'},
+            $msi->{'product_name'}),
+        $source_path,
+        $uniquename);
+    my ($long_name, undef) = installer::patch::Msi::SplitLongShortName($file_row->GetValue("FileName"));
+    my $target_name = File::Spec->catfile($target_path, $long_name);
+    if ( ! -f $full_source_name)
+    {
+        installer::logger::PrintError("can not find file '%s' in previous version (tried '%s')\n",
+            $uniquename,
+            $full_source_name);
+        return undef;
+    }
+    my $cygwin_full_source_name = qx(cygpath -w '$full_source_name');
+    my $component_name = $file_row->GetValue('Component_');
+    my $module_names = join(",", @{$component_to_features_map->{$component_name}});
+    my $sequence_number = $file_row->GetValue('Sequence');
+
+    return {
+        'uniquename' => $uniquename,
+        'destination' => $target_name,
+        'componentname' => $component_name,
+        'modules' => $module_names,
+        'UnixRights' => 444,
+        'Name' => $long_name,
+        'sourcepath' => $full_source_name,
+        'cyg_sourcepath' => $cygwin_full_source_name,
+        'sequencenumber' => $sequence_number
+        };
+}
+
+
+
+
+=head2 create_feature_component_maps($msi)
+
+    Return a hash map that maps from component names to arrays of
+    feature names.  In most cases the array of features contains only
+    one element.  But there can be cases where the number is greater.
+
+=cut
+sub create_feature_component_map ($)
+{
+    my ($msi) = @_;
+
+    my $component_to_features_map = {};
+    my $feature_component_table = $msi->GetTable("FeatureComponents");
+    my $feature_column_index = $feature_component_table->GetColumnIndex("Feature_");
+    my $component_column_index = $feature_component_table->GetColumnIndex("Component_");
+    foreach my $row (@{$feature_component_table->GetAllRows()})
+    {
+        my $feature = $row->GetValue($feature_column_index);
+        my $component = $row->GetValue($component_column_index);
+        if ( ! defined $component_to_features_map->{$component})
+        {
+            $component_to_features_map->{$component} = [$feature];
+        }
+        else
+        {
+            push @{$component_to_features_map->{$component}}, $feature;
+        }
+    }
+
+    return $component_to_features_map;
+}
+
+
 #############################################
 # Returning the Windows language of a file
 #############################################
@@ -576,6 +784,7 @@ sub generate_registry_keypath
 	return $keypath;	
 }
 
+
 ###################################################################
 # Collecting further conditions for the component table.
 # This is used by multilayer products, to enable installation 
@@ -636,225 +845,344 @@ sub collect_shortnames_from_old_database
 	}
 }
 
-############################################
-# Creating the file File.idt dynamically
-############################################
 
-sub create_files_table ($$$$)
+sub process_language_conditions ($)
 {
-	my ($filesref, $allfilecomponentsref, $basedir, $allvariables) = @_;
-
-	$installer::logger::Lang->add_timestamp("Performance Info: File Table start");
-
-	# Structure of the files table:
-	# File Component_ FileName FileSize Version Language Attributes Sequence
-	# In this function, all components are created.
-	#
-	# $allfilecomponentsref is empty at the beginning
-
-	my $infoline;
+    my ($onefile) = @_;
+    
+    # Collecting all languages specific conditions
+    if ( $onefile->{'ismultilingual'} )
+    {
+        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");
+        }
 
-	my @allfiles = ();
-	my @filetable = ();
-	my @filehashtable = ();
-	my %allfilecomponents = ();
-	my $counter = 0;
+        if ( $onefile->{'specificlanguage'} eq "" )
+        {
+            installer::exiter::exit_program(
+                "ERROR: There is no specific language for file at language module: $onefile->{'gid'} !", "create_files_table");
+        }
+        my $locallanguage = $onefile->{'specificlanguage'};
+        my $property = "IS" . $onefile->{'windows_language'};
+        my $value = 1;
+        my $condition = $property . "=" . $value;
+        
+        $onefile->{'ComponentCondition'} = $condition;
 
-	if ( $^O =~ /cygwin/i ) { installer::worker::generate_cygwin_pathes($filesref); }
-	
-	# The filenames must be collected because of uniqueness
-	# 01-44-~1.DAT, 01-44-~2.DAT, ...
-	# my @shortnames = ();
-	my %shortnames = ();
-	
-	installer::windows::idtglobal::write_idt_header(\@filetable, "file");
-	installer::windows::idtglobal::write_idt_header(\@filehashtable, "filehash");
-	
-	for ( my $i = 0; $i <= $#{$filesref}; $i++ )
-	{
-		my %file = ();
+        if ( exists($installer::globals::componentcondition{$onefile->{'componentname'}}))
+        {
+            if ( $installer::globals::componentcondition{$onefile->{'componentname'}} ne $condition )
+            {
+                installer::exiter::exit_program(
+                    sprintf(
+                        "ERROR: There is already another component condition for file %s: \"%s\" and \"%s\" !",
+                        $onefile->{'gid'},
+                        $installer::globals::componentcondition{$onefile->{'componentname'}},
+                        $condition),
+                    "create_files_table");
+            }
+        }
+        else
+        {
+            $installer::globals::componentcondition{$onefile->{'componentname'}} = $condition;
+        }		
 
-		my $onefile = ${$filesref}[$i];	
+        # collecting all properties for table Property
+        if ( ! exists($installer::globals::languageproperties{$property}) )
+        {
+            $installer::globals::languageproperties{$property} = $value;
+        }
+    }
+}
 
-		my $styles = "";
-		if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; }
-		if (( $styles =~ /\bJAVAFILE\b/ ) && ( ! ($allvariables->{'JAVAPRODUCT'} ))) { next; }
 
-		$file{'Component_'} = get_file_component_name($onefile, $filesref);
-		$file{'File'} = generate_unique_filename_for_filetable($onefile, $file{'Component_'});
-	
-		$onefile->{'uniquename'} = $file{'File'};
-		$onefile->{'componentname'} = $file{'Component_'};
 
-		# Collecting all components
-		# if (!(installer::existence::exists_in_array($file{'Component_'}, $allfilecomponentsref))) { push(@{$allfilecomponentsref}, $file{'Component_'}); }
 
-		if ( ! exists($allfilecomponents{$file{'Component_'}}) ) { $allfilecomponents{$file{'Component_'}} = 1; }
+sub has_style ($$)
+{
+    my ($style_list_string, $style_name) = @_;
 
-		$file{'FileName'} = generate_filename_for_filetable($onefile, \%shortnames);
+    return 0 unless defined $style_list_string;
+    return $style_list_string =~ /\b$style_name\b/ ? 1 : 0;
+}
 
-		$file{'FileSize'} = get_filesize($onefile);
 
-		$file{'Version'} = get_fileversion($onefile, $allvariables, $styles);
 
-		$file{'Language'} = get_language_for_file($onefile);
-		
-		if ( $styles =~ /\bDONT_PACK\b/ ) { $file{'Attributes'} = "8192"; }
-		else { $file{'Attributes'} = "16384"; }
 
-		# $file{'Attributes'} = "16384"; 	# Sourcefile is packed
-		# $file{'Attributes'} = "8192"; 	# Sourcefile is unpacked
+sub prepare_file_table_creation ($$$)
+{
+    my ($file_list, $directory_list, $allvariables) = @_;
+    
+    if ( $^O =~ /cygwin/i )
+    {
+        installer::worker::generate_cygwin_pathes($file_list);
+    }
 
-		$installer::globals::insert_file_at_end = 0;
-		$counter++;
-		$file{'Sequence'} = $counter;
+    # Reset the fields 'sequencenumber' and 'uniquename'. They should not yet exist but better be sure.
+    foreach my $file (@$file_list)
+    {
+        delete $file->{'sequencenumber'};
+        delete $file->{'uniquename'};
+    }
 
-		$onefile->{'sequencenumber'} = $file{'Sequence'};
+    # Create FileSequenceList object for the old sequence data.
+    if (defined $installer::globals::source_msi)
+    {
+        my $previous_sequence_data = new installer::patch::FileSequenceList();
+        $previous_sequence_data->SetFromMsi($installer::globals::source_msi);
+        my @added_files = retrieve_sequence_and_uniquename($file_list, $previous_sequence_data);
+    
+        # Extract just the unique names.
+        my %target_unique_names = map {$_->{'uniquename'} => 1} @$file_list;
+        my @removed_items = $previous_sequence_data->get_removed_files(\%target_unique_names);
+
+        $installer::logger::Lang->printf(
+            "there are %d files that have been removed from source and %d files added\n",
+            scalar @removed_items,
+            scalar @added_files);
+
+        my $file_map = $installer::globals::source_msi->GetFileMap();
+        my $index = 0;
+        foreach my $removed_row (@removed_items)
+        {
+            $installer::logger::Lang->printf("    removed file %d: %s\n",
+                ++$index,
+                $removed_row->GetValue('File'));
+            my $directory = $file_map->{$removed_row->GetValue('File')}->{'directory'};
+            while (my ($key,$value) = each %$directory)
+            {
+                $installer::logger::Lang->printf("        %16s -> %s\n", $key, $value);
+            }
+        }
+        $index = 0;
+        foreach my $added_file (@added_files)
+        {
+            $installer::logger::Lang->printf("    added file %d: %s\n",
+                ++$index,
+                $added_file->{'uniquename'});
+            installer::scriptitems::print_script_item($added_file);
+        }
+        my @new_files = create_items_for_missing_files(
+            \@removed_items,
+            $installer::globals::source_msi,
+            $directory_list);
+        push @$file_list, @new_files;
+    }
+    assign_missing_sequence_numbers($file_list);
 
-		my $oneline = $file{'File'} . "\t" . $file{'Component_'} . "\t" . $file{'FileName'} . "\t" 
-				. $file{'FileSize'} . "\t" . $file{'Version'} . "\t" . $file{'Language'} . "\t"
-				. $file{'Attributes'} . "\t" . $file{'Sequence'} . "\n";
+    foreach my $file (@$file_list)
+	{
+        if ( ! defined $file->{'componentname'})
+        {
+            $file->{'componentname'} = get_file_component_name($file, $file_list);
+        }
+        if ( ! defined $file->{'uniquename'})
+        {
+            $file->{'uniquename'} = generate_unique_filename_for_filetable($file->{'Name'});
+        }
 	
-		push(@filetable, $oneline);
-
-		if ( ! $installer::globals::insert_file_at_end ) { push(@allfiles, $onefile); }
-
 		# Collecting all component conditions
-		if ( $onefile->{'ComponentCondition'} )
+		if ( $file->{'ComponentCondition'} )
 		{			
-			if ( ! exists($installer::globals::componentcondition{$file{'Component_'}}))
+			if ( ! exists($installer::globals::componentcondition{$file->{'componentname'}}))
 			{
-				$installer::globals::componentcondition{$file{'Component_'}} = $onefile->{'ComponentCondition'};
+				$installer::globals::componentcondition{$file->{'componentname'}}
+                = $file->{'ComponentCondition'};
 			}
 		}
-		
 		# Collecting also all tree conditions for multilayer products
-		get_tree_condition_for_component($onefile, $file{'Component_'});
+		get_tree_condition_for_component($file, $file->{'componentname'});
 
 		# Collecting all component names, that have flag VERSION_INDEPENDENT_COMP_ID
 		# This should be all components with constant API, for example URE
-		if ( $styles =~ /\bVERSION_INDEPENDENT_COMP_ID\b/ )
+		if (has_style($file->{'Styles'}, "VERSION_INDEPENDENT_COMP_ID"))
 		{
-			$installer::globals::base_independent_components{$onefile->{'componentname'}} = 1;
+			$installer::globals::base_independent_components{$file->{'componentname'}} = 1;
 		}
 
-		# Collecting all component ids, that are defined at files in scp project (should not be used anymore)
-		if ( $onefile->{'CompID'} )
-		{			
-			if ( ! exists($installer::globals::componentid{$onefile->{'componentname'}}))
-			{
-				$installer::globals::componentid{$onefile->{'componentname'}} = $onefile->{'CompID'};
-			}
-			else
-			{
-				if ( $installer::globals::componentid{$onefile->{'componentname'}} ne $onefile->{'CompID'} )
-				{
-					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");
-				}
-			}
-
-			# Also checking vice versa. Is this ComponentID already used? If yes, is the componentname the same?
-	
-			if ( ! exists($installer::globals::comparecomponentname{$onefile->{'CompID'}}))
-			{
-				$installer::globals::comparecomponentname{$onefile->{'CompID'}} = $onefile->{'componentname'};
-			}
-			else
-			{
-				if ( $installer::globals::comparecomponentname{$onefile->{'CompID'}} ne $onefile->{'componentname'} )
-				{
-					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");
-				}				
-			}
-		}
+        # Special handling for files in PREDEFINED_OSSHELLNEWDIR. These components
+		# need as KeyPath a RegistryItem in HKCU
+        if ($file->{'needs_user_registry_key'}
+            || (defined $file->{'Dir'} && $file->{'Dir'} =~ /\bPREDEFINED_OSSHELLNEWDIR\b/))
+		{
+			my $keypath = generate_registry_keypath($file);
+			$file->{'userregkeypath'} = $keypath;
+			push(@installer::globals::userregistrycollector, $file);
+			$installer::globals::addeduserregitrykeys = 1;
+		}	
 
-		# Collecting all language specific conditions
-		# if ( $onefile->{'haslanguagemodule'} )
-		if ( $onefile->{'ismultilingual'} )
-		{
-			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"); }
-
-			if ( $onefile->{'specificlanguage'} eq "" ) { installer::exiter::exit_program("ERROR: There is no specific language for file at language module: $onefile->{'gid'} !", "create_files_table"); }
-			my $locallanguage = $onefile->{'specificlanguage'};
-			my $property = "IS" . $file{'Language'};
-			my $value = 1;
-			my $condition = $property . "=" . $value;
-			
-			$onefile->{'ComponentCondition'} = $condition;
+		$file->{'windows_language'} = get_language_for_file($file);
 
-			if ( exists($installer::globals::componentcondition{$file{'Component_'}}))
-			{
-				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"); }
-			}
-			else
-			{
-				$installer::globals::componentcondition{$file{'Component_'}} = $condition;
-			}		
+        process_language_conditions($file);
+    }
 
-			# collecting all properties for table Property
-			if ( ! exists($installer::globals::languageproperties{$property}) ) { $installer::globals::languageproperties{$property} = $value; }
-		}
+    # The filenames must be collected because of uniqueness
+	# 01-44-~1.DAT, 01-44-~2.DAT, ...
+	my %shortnames = ();
+    foreach my $file (@$file_list)
+    {
+        $file->{'short_name'} = generate_filename_for_filetable($file, \%shortnames);
+    }
+}
 
-		if ( $installer::globals::prepare_winpatch )
-		{
-			my $path = $onefile->{'sourcepath'};
-			if ( $^O =~ /cygwin/i ) { $path = $onefile->{'cyg_sourcepath'}; }
 
-			open(FILE, $path) or die "ERROR: Can't open $path for creating file hash";
-			binmode(FILE);
-			my $hashinfo = pack("l", 20);
-			$hashinfo .= Digest::MD5->new->addfile(*FILE)->digest;
 
-			my @i = unpack ('x[l]l4', $hashinfo);
-			$oneline = $file{'File'} . "\t" .
-				"0" . "\t" .
-				$i[0] . "\t" .
-				$i[1] . "\t" .
-				$i[2] . "\t" .
-				$i[3] . "\n";
-			push (@filehashtable, $oneline);
-		}
 
-		# Saving the sequence number in a hash with uniquefilename as key.
-		# This is used for better performance in "save_packorder"
-		$installer::globals::uniquefilenamesequence{$onefile->{'uniquename'}} = $onefile->{'sequencenumber'};
-		
-		# Special handling for files in PREDEFINED_OSSHELLNEWDIR. These components
-		# need as KeyPath a RegistryItem in HKCU
-		my $destdir = "";
-		if ( $onefile->{'Dir'} ) { $destdir = $onefile->{'Dir'}; }
+sub create_file_table_data ($$)
+{
+    my ($file_list, $allvariables) = @_;
+    
+    my @file_table_data = ();
+	foreach my $file (@$file_list)
+	{
+        my $attributes;
+		if (has_style($file->{'Styles'}, "DONT_PACK"))
+        {
+            # Sourcefile is unpacked (msidbFileAttributesNoncompressed).
+            $attributes = "8192";
+        }
+		else
+        {
+            # Sourcefile is packed (msidbFileAttributesCompressed).
+            $attributes = "16384";
+        }
 
-		if (( $destdir =~ /\bPREDEFINED_OSSHELLNEWDIR\b/ ) || ( $onefile->{'needs_user_registry_key'} ))
-		{
-			my $keypath = generate_registry_keypath($onefile);
-			$onefile->{'userregkeypath'} = $keypath;
-			push(@installer::globals::userregistrycollector, $onefile);
-			$installer::globals::addeduserregitrykeys = 1;
-		}	
+        my $row_data = {
+            'File' => $file->{'uniquename'},
+            'Component_' => $file->{'componentname'},
+            'FileName' => $file->{'short_name'},
+            'FileSize' => get_filesize($file),
+            'Version' => get_fileversion($file, $allvariables),
+            'Language' => $file->{'windows_language'},
+            'Attributes' => $attributes,
+            'Sequence' => $file->{'sequencenumber'}
+            };
+        push @file_table_data, $row_data;
 	}
 
-	# putting content from %allfilecomponents to $allfilecomponentsref for later usage
-	foreach $localkey (keys %allfilecomponents ) { push( @{$allfilecomponentsref}, $localkey); }
+    return \@file_table_data;
+}
+
+
+
+
+sub collect_components ($)
+{
+    my ($file_list) = @_;
+    
+	my %components = ();
+    foreach my $file (@$file_list)
+    {
+        $components{$file->{'componentname'}} = 1;
+    }
+    return keys %components;
+}
+
+
+
+
+=head filter_files($file_list, $allvariables)
+
+    Filter out Java files when not building a Java product.
+
+    Is this still triggered?
+    
+=cut
+sub filter_files ($$)
+{
+    my ($file_list, $allvariables) = @_;
+
+    if ($allvariables->{'JAVAPRODUCT'})
+    {
+        return $file_list;
+    }
+    else
+    {
+        my @filtered_files = ();
+        foreach my $file (@$file_list)
+        {
+            if ( ! has_style($file->{'Styles'}, "JAVAFILE"))
+            {
+                push @filtered_files, $file;
+            }
+        }
+        return \@filtered_files;
+    }
+}
+
+
+
+
+# Structure of the files table:
+# File Component_ FileName FileSize Version Language Attributes Sequence
+sub create_file_table ($$)
+{
+    my ($file_table_data, $basedir) = @_;
+    
+    # Set up the 'File' table.
+	my @filetable = ();
+	installer::windows::idtglobal::write_idt_header(\@filetable, "file");
+    my @keys = ('File', 'Component_', 'FileName', 'FileSize', 'Version', 'Language', 'Attributes', 'Sequence');
+    my $index = 0;
+    foreach my $row_data (@$file_table_data)
+    {
+        ++$index;
+        my @values = map {$row_data->{$_}} @keys;
+        my $line = join("\t", @values) . "\n";
+		push(@filetable, $line);
+    }
 
-	my $filetablename = $basedir . $installer::globals::separator . "File.idt";
+    my $filetablename = $basedir . $installer::globals::separator . "File.idt";
 	installer::files::save_file($filetablename ,\@filetable);
 	$installer::logger::Lang->print("\n");
 	$installer::logger::Lang->printf("Created idt file: %s\n", $filetablename); 
+}
 
-	$installer::logger::Lang->add_timestamp("Performance Info: File Table end");
-	
-	my $filehashtablename = $basedir . $installer::globals::separator . "MsiFileHash.idt";
-	installer::files::save_file($filehashtablename ,\@filehashtable);
-	$installer::logger::Lang->print("\n");
-	$installer::logger::Lang->printf("Created idt file: %s\n", $filehashtablename);
 
-	# Now the new files can be added to the files collector (only in update packaging processes)
-	if ( $installer::globals::newfilesexist )
-	{
-		foreach my $seq (sort keys %installer::globals::newfilescollector) { push(@allfiles, $installer::globals::newfilescollector{$seq}) }
-	}
 
-	return \@allfiles;
+
+sub create_filehash_table ($$)
+{
+    my ($file_list, $basedir) = @_;
+
+    my @filehashtable = ();
+
+    if ( $installer::globals::prepare_winpatch )
+    {
+
+        installer::windows::idtglobal::write_idt_header(\@filehashtable, "filehash");
+
+        foreach my $file (@$file_list)
+        {
+            my $path = $file->{'sourcepath'};
+            if ($^O =~ /cygwin/i)
+            {
+                $path = $file->{'cyg_sourcepath'};
+            }
+
+            open(FILE, $path) or die "ERROR: Can't open $path for creating file hash";
+            binmode(FILE);
+            my $hashinfo = pack("l", 20);
+            $hashinfo .= Digest::MD5->new->addfile(*FILE)->digest;
+
+            my @i = unpack ('x[l]l4', $hashinfo);
+            my $oneline = join("\t",
+                (
+                    $file->{'uniquename'},
+                    "0",
+                    @i
+                ));
+            push (@filehashtable, $oneline . "\n");
+        }
+
+        my $filehashtablename = $basedir . $installer::globals::separator . "MsiFileHash.idt";
+        installer::files::save_file($filehashtablename ,\@filehashtable);
+        $installer::logger::Lang->print("\n");
+        $installer::logger::Lang->printf("Created idt file: %s\n", $filehashtablename);
+    }
 }
 
+
 1;

Modified: openoffice/trunk/main/solenv/bin/modules/installer/windows/msiglobal.pm
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/solenv/bin/modules/installer/windows/msiglobal.pm?rev=1547732&r1=1547731&r2=1547732&view=diff
==============================================================================
--- openoffice/trunk/main/solenv/bin/modules/installer/windows/msiglobal.pm (original)
+++ openoffice/trunk/main/solenv/bin/modules/installer/windows/msiglobal.pm Wed Dec  4 08:51:30 2013
@@ -37,6 +37,8 @@ use installer::systemactions;
 use installer::worker;
 use installer::windows::idtglobal;
 use installer::windows::language;
+use installer::patch::ReleasesList;
+
 use strict;
 
 ###########################################################################
@@ -498,11 +500,7 @@ sub get_packagecode_for_sis
 {
 	# always generating a new package code for each package
 
-	my $guidref = get_guid_list(1, 1);	# only one GUID shall be generated
-
-	${$guidref}[0] =~ s/\s*$//;		# removing ending spaces
-
-	my $guid = "\{" . ${$guidref}[0] . "\}";
+	my $guid = "\{" . create_guid() . "\}";
 
 	my $infoline = "PackageCode: $guid\n";
 	$installer::logger::Lang->print($infoline);
@@ -1127,47 +1125,19 @@ sub copy_child_projects_into_installset
 	}
 }
 
-#################################################################
-# Getting a list of GUID using uuidgen.exe.
-# This works only on Windows
-#################################################################
 
-sub get_guid_list
-{
-	my ($number, $log) = @_;
 
-	if ( $log ) { installer::logger::include_header_into_logfile("Generating $number GUID"); }
-	
-	my $uuidgen = "uuidgen.exe";		# Has to be in the path
-	
-	# "-c" for uppercase output
-	
-	# my $systemcall = "$uuidgen -n$number -c |";
-	my $systemcall = "$uuidgen -n$number |";
-	open (UUIDGEN, "$systemcall" ) or die("uuidgen is missing.");
-	my @uuidlist = <UUIDGEN>;
-	close (UUIDGEN);
+=head2 create_guid ()
 
-	my $infoline = "Systemcall: $systemcall\n";
-	if ( $log ) { $installer::logger::Lang->print($infoline); }
-	
-	my $comparenumber = $#uuidlist + 1;	
-	
-	if ( $comparenumber == $number )
-	{
-		$infoline = "Success: Executed $uuidgen successfully!\n";
-		if ( $log ) { $installer::logger::Lang->print($infoline); }
-	}
-	else
-	{
-		$infoline = "ERROR: Could not execute $uuidgen successfully!\n";
-		if ( $log ) { $installer::logger::Lang->print($infoline); }
-	}	
-
-	# uppercase, no longer "-c", because this is only supported in uuidgen.exe v.1.01
-	for ( my $i = 0; $i <= $#uuidlist; $i++ ) { $uuidlist[$i] = uc($uuidlist[$i]); }
-
-	return \@uuidlist;
+    Create a single UUID aka GUID via calling the external executable 'uuidgen'.
+    There are Perl modules for that, but do they exist on the build bots?
+    
+=cut
+sub create_guid ()
+{
+	my $uuid = qx("uuidgen");
+    $uuid =~ s/\s*$//;
+	return uc($uuid);
 }
 
 #################################################################
@@ -1188,6 +1158,9 @@ sub calculate_guid
 	# my $id = pack("A32", $digest);
 	my ($first, $second, $third, $fourth, $fifth) = unpack ('A8 A4 A4 A4 A12', $digest);
 	$guid = "$first-$second-$third-$fourth-$fifth";
+
+    $installer::logger::Lang->printf("guid for '%s' is %s\n",
+        $string, $guid);
 	
 	return $guid;
 }
@@ -1264,7 +1237,7 @@ sub create_new_component_file
 # This works only on Windows
 #################################################################
 
-sub set_uuid_into_component_table
+sub __set_uuid_into_component_table
 {
 	my ($idtdirbase, $allvariables) = @_;
 	
@@ -1303,19 +1276,32 @@ sub set_uuid_into_component_table
 			{
 				# Calculating new GUID with the help of the component name.
 				my $useooobaseversion = 1;
-				if ( exists($installer::globals::base_independent_components{$componentname})) { $useooobaseversion = 0; }
+				if ( exists($installer::globals::base_independent_components{$componentname}))
+                {
+                    $useooobaseversion = 0;
+                }
 				my $sourcestring = $componentname;
 
 				if ( $useooobaseversion )
 				{
-					if ( ! exists($allvariables->{'OOOBASEVERSION'}) ) { installer::exiter::exit_program("ERROR: Could not find variable \"OOOBASEVERSION\" (required value for GUID creation)!", "set_uuid_into_component_table"); }
+					if ( ! exists($allvariables->{'OOOBASEVERSION'}) )
+                    {
+                        installer::exiter::exit_program(
+                            "ERROR: Could not find variable \"OOOBASEVERSION\" (required value for GUID creation)!",
+                            "set_uuid_into_component_table");
+                    }
 					$sourcestring = $sourcestring . "_" . $allvariables->{'OOOBASEVERSION'};
 				}
 				$uuid = calculate_guid($sourcestring);
 				$counter++;
 
 				# checking, if there is a conflict with an already created guid
-				if ( exists($installer::globals::allcalculated_guids{$uuid}) ) { installer::exiter::exit_program("ERROR: \"$uuid\" was already created before!", "set_uuid_into_component_table"); }
+				if ( exists($installer::globals::allcalculated_guids{$uuid}) )
+                {
+                    installer::exiter::exit_program(
+                        "ERROR: \"$uuid\" was already created before!",
+                        "set_uuid_into_component_table");
+                }
 				$installer::globals::allcalculated_guids{$uuid} = 1;
 				$installer::globals::calculated_component_guids{$componentname} = $uuid;
 
@@ -1631,107 +1617,138 @@ sub execute_packaging
 	$installer::logger::Lang->print($infoline);	
 }
 
-###############################################################
-# Setting the global variables ProductCode and the UpgradeCode
-###############################################################
 
-sub set_global_code_variables ($$)
-{
-	my ($languagesref, $allvariableshashref) = @_;
+=head2 get_source_codes($languagesref)
 
-	# In the msi template directory a files "codes.txt" has to exist, in which the ProductCode
-	# and the UpgradeCode for the product are defined.
-	# The name "codes.txt" can be overwritten in Product definition with CODEFILENAME . 
-	# Default $installer::globals::codefilename is defined in parameter.pm.
-		
-	if ( $allvariableshashref->{'CODEFILENAME'} )
-	{
-		$installer::globals::codefilename = $installer::globals::idttemplatepath  . $installer::globals::separator . $allvariableshashref->{'CODEFILENAME'};
-		installer::files::check_file($installer::globals::codefilename);
-	} 
-
-	my $infoline = "Using Codes file: $installer::globals::codefilename \n";
-	$installer::logger::Lang->print($infoline);
-
-	my $codefile = installer::files::read_file($installer::globals::codefilename);
-
-	my $isopensource = 0;
-	if ( $allvariableshashref->{'OPENSOURCE'} ) { $isopensource = $allvariableshashref->{'OPENSOURCE'}; } 
+    Return product code and upgrade code from the source version.
+    When no source version is defined then return undef for both.
+    
+=cut
+sub get_source_codes ($)
+{
+    my ($languagesref) = @_;
+    
+    if ( ! defined $installer::globals::source_version)
+    {
+        return;
+    }
+
+    my $onelanguage = installer::languages::get_key_language($languagesref);
+
+    my $release_data = installer::patch::ReleasesList::Instance()
+        ->{$installer::globals::source_version}
+        ->{$installer::globals::packageformat};
+    if (defined $release_data)
+    {
+        my $language_data = $release_data->{$onelanguage};
+        if (defined $language_data)
+        {
+            $installer::logger::Lang->printf("source product code is %s\n", $language_data->{'product-code'});
+            $installer::logger::Lang->printf("source upgrade code is %s\n", $release_data->{'upgrade-code'});
+
+            return (
+                $language_data->{'product-code'},
+                $release_data->{'upgrade-code'}
+                );
+        }
+        else
+        {
+            $installer::logger::Info->printf(
+                "Warning: can not access information about previous version %s and language %s\n",
+                $installer::globals::source_version,
+                $onelanguage);
+            return (undef,undef);
+        }
+    }
+    else
+    {
+        $installer::logger::Info->printf("Warning: can not access information about previous version %s\n",
+            $installer::globals::source_version);
+        return (undef,undef);
+    }
+}
 
-	my $onelanguage = "";
-	 
-	if ( $#{$languagesref} > 0 )	# more than one language
-	{
-		if (( $installer::globals::added_english ) && ( $#{$languagesref} == 1 )) # only multilingual because of added English
-		{
-			$onelanguage = ${$languagesref}[1];  # setting the first language, that is not english
-		}
-		else
-		{
-			if (( ${$languagesref}[1] =~ /jp/ ) ||
-				( ${$languagesref}[1] =~ /ko/ ) ||
-				( ${$languagesref}[1] =~ /zh/ ))
-			{
-				$onelanguage = "multiasia";
-			}
-			else
-			{
-				$onelanguage = "multiwestern";
-			}
-		}
-	}
-	else	# only one language
-	{
-		$onelanguage = ${$languagesref}[0];
-	}
 
-	# ProductCode must not change, if Windows patches shall be applied
-	if ( $installer::globals::prepare_winpatch )
-	{	
-		# ProductCode has to be specified in each language
-		my $searchstring = "PRODUCTCODE";
-		my $codeblock = installer::windows::idtglobal::get_language_block_from_language_file($searchstring, $codefile);
-		$installer::globals::productcode = installer::windows::idtglobal::get_code_from_code_block($codeblock, $onelanguage);
-	} else {
-		my $guidref = get_guid_list(1, 1);	# only one GUID shall be generated
-		${$guidref}[0] =~ s/\s*$//;		# removing ending spaces
-		$installer::globals::productcode = "\{" . ${$guidref}[0] . "\}";
-	}
 
-	if ( $installer::globals::patch ) # patch upgrade codes are defined in soffice.lst
-	{
-		if ( $allvariableshashref->{'PATCHUPGRADECODE'} ) { $installer::globals::upgradecode = $allvariableshashref->{'PATCHUPGRADECODE'}; }
-		else { installer::exiter::exit_program("ERROR: PATCHUPGRADECODE not defined in list file!", "set_global_code_variables"); }
-	}
-	else
-	{ 
-		# UpgradeCode can take english as default, if not defined in specified language
 
-		my $searchstring = "UPGRADECODE";	# searching in the codes.txt file
-		my $codeblock = installer::windows::idtglobal::get_language_block_from_language_file($searchstring, $codefile);
-		$installer::globals::upgradecode = installer::windows::idtglobal::get_language_string_from_language_block($codeblock, $onelanguage, "");
-	}
-	
-	# if (( $installer::globals::productcode eq "" ) && ( ! $isopensource )) { installer::exiter::exit_program("ERROR: ProductCode for language $onelanguage not defined in $installer::globals::codefilename !", "set_global_code_variables"); }
-	if ( $installer::globals::upgradecode eq "" ) { installer::exiter::exit_program("ERROR: UpgradeCode not defined in $installer::globals::codefilename !", "set_global_code_variables"); }	
+=head2 set_global_code_variables ($languagesref, $allvariableshashref)
+
+    Determine values for the product code and upgrade code of the target version.
+
+    As perparation for building a Windows patch, certain conditions have to be fullfilled.
+     - The upgrade code changes from old to new version
+     - The product code remains the same
+     In order to inforce that we have to access information about the source version.
+
+    The resulting values are stored as global variables
+        $installer::globals::productcode
+        $installer::globals::upgradecode
+    and as variables in the given hash
+    	$allvariableshashref->{'PRODUCTCODE'}
+        $allvariableshashref->{'UPGRADECODE'}
 
-	$infoline = "Setting ProductCode to: $installer::globals::productcode \n";
-	$installer::logger::Lang->print($infoline);
-	$infoline = "Setting UpgradeCode to: $installer::globals::upgradecode \n";
-	$installer::logger::Lang->print($infoline);
+=cut
+sub set_global_code_variables ($$)
+{
+	my ($languagesref, $allvariableshashref) = @_;
 
-	# Adding both variables into the variables array 
+    my ($source_product_code, $source_upgrade_code) = get_source_codes($languagesref);
+    my ($target_product_code, $target_upgrade_code) = (undef, undef);
+    
+    if (defined $source_product_code && defined $source_upgrade_code)
+    {
+        if ($installer::globals::is_major_release)
+        {
+            # For a major release we have to change the product code.
+            $target_product_code = "{" . create_guid() . "}";
+            $installer::logger::Lang->printf("building a major release, created new product code %s\n",
+                $target_product_code);
+            
+            # Let's do a paranoia check that the new and the old guids are
+            # different.  In reality the new guid really has to be
+            # different from all other guids used for * codes, components,
+            # etc.
+            if ($target_product_code eq $source_product_code)
+            {
+                installer::logger::PrintError(
+                    "new GUID for product code is the same as the old product code but should be different.");
+            }
+        }
+        else
+        {
+            # For minor or micro releases we have to keeep the old product code.
+            $target_product_code = "{" . $source_product_code . "}";
+            $installer::logger::Lang->printf("building a minor or micro release, reusing product code %s\n",
+                $target_product_code);
+        }
+
+        $target_upgrade_code = "{" . create_guid() . "}";
+        # Again, just one test for paranoia.
+        if ($target_upgrade_code eq $source_upgrade_code)
+        {
+            installer::logger::PrintError(
+                "new GUID for upgrade code is the same as the old upgrade code but should be different.");
+        }
+    }
+    else
+    {
+        # There is no previous version with which to compare the product code.
+        # Just create two new uuids.
+        $target_product_code = "{" . create_guid() . "}";
+        $target_upgrade_code = "{" . create_guid() . "}";
+    }
+    
+    $installer::globals::productcode = $target_product_code;
+    $installer::globals::upgradecode = $target_upgrade_code;
+    $allvariableshashref->{'PRODUCTCODE'} = $target_product_code;
+	$allvariableshashref->{'UPGRADECODE'} = $target_upgrade_code;
 
-	$allvariableshashref->{'PRODUCTCODE'} = $installer::globals::productcode;
-	$allvariableshashref->{'UPGRADECODE'} = $installer::globals::upgradecode;
+	$installer::logger::Lang->printf("target product code is %s\n", $target_product_code);
+	$installer::logger::Lang->printf("target upgrade code is %s\n", $target_upgrade_code);
+}
 
-	$infoline = "Defined variable PRODUCTCODE: $installer::globals::productcode \n";
-	$installer::logger::Lang->print($infoline);
 
-	$infoline = "Defined variable UPGRADECODE: $installer::globals::upgradecode \n";
-	$installer::logger::Lang->print($infoline);
 
-}
 
 ###############################################################
 # Setting the product version used in property table and

Modified: openoffice/trunk/main/solenv/bin/modules/installer/windows/registry.pm
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/solenv/bin/modules/installer/windows/registry.pm?rev=1547732&r1=1547731&r2=1547732&view=diff
==============================================================================
--- openoffice/trunk/main/solenv/bin/modules/installer/windows/registry.pm (original)
+++ openoffice/trunk/main/solenv/bin/modules/installer/windows/registry.pm Wed Dec  4 08:51:30 2013
@@ -29,6 +29,8 @@ use installer::worker;
 use installer::windows::msiglobal;
 use installer::windows::idtglobal;
 
+use strict;
+
 #####################################################
 # Generating the component name from a registryitem
 #####################################################
@@ -284,25 +286,6 @@ sub get_registry_val64
 	return $value;
 }
 
-##############################################################
-# Returning component for registry table.
-##############################################################
-
-sub get_registry_component
-{
-	my ($registry, $allvariables) = @_;
-
-	# All registry items belonging to one module can
-	# be included into one component
-
-	my $componentname = get_registry_component_name($registry, $allvariables);
-
-	# saving componentname in the registryitem collector
-
-	$registry->{'componentname'} = $componentname;
-
-	return $componentname;
-}
 
 ######################################################
 # Adding the content of 
@@ -345,20 +328,13 @@ sub add_userregs_to_registry_table
 # Content: 
 # Registry Root Key Name Value Component_
 ######################################################
-
-sub create_registry_table
+sub prepare_registry_table ($$$)
 {
-	my ($registryref, $allregistrycomponentsref, $basedir, $languagesarrayref, $allvariableshashref) = @_;
+	my ($registryref, $languagesarrayref, $allvariableshashref) = @_;
 
     my %table_data = ();
 	foreach my $onelanguage (@$languagesarrayref)
 	{
-
-		my @registrytable = ();
-		my @reg64table = ();
-	
-		installer::windows::idtglobal::write_idt_header(\@registrytable, "registry");
-		installer::windows::idtglobal::write_idt_header(\@reg64table, "reg64");
         my $table_items = [];
 		foreach my $oneregistry (@$registryref)
 		{
@@ -381,12 +357,6 @@ sub create_registry_table
             $oneregistry->{'componentname'} = $component_name;
 			$registry{'Component_'} = $component_name;
 	
-			# Collecting all components
-			if (!(installer::existence::exists_in_array($registry{'Component_'}, $allregistrycomponentsref))) 
-			{
-				push(@{$allregistrycomponentsref}, $registry{'Component_'}); 
-			}
-
 			# Collecting all components with DONT_DELETE style
 			my $style = $oneregistry->{'Styles'} // "";
             $registry{'styles'} = $style;
@@ -420,14 +390,93 @@ sub create_registry_table
 				}
 			}
 
-			my $oneline = $registry{'Registry'} . "\t" . $registry{'Root'} . "\t" . $registry{'Key'} . "\t"
-						. $registry{'Name'} . "\t" . $registry{'Value'} . "\t" . $registry{'Component_'} . "\n";
+            push @$table_items, \%registry;
+		}
+        $table_data{$onelanguage} = $table_items;
+    }
+
+    return \%table_data;
+}
+
+
+
+
+sub collect_registry_components ($)
+{
+    my ($table_data) = @_;
+
+    my %components = ();
+    foreach my $language_data (values %$table_data)
+    {
+        foreach my $item (@$language_data)
+        {
+			$components{$item->{'Component_'}} = 1; 
+        }
+    }
+    return keys %components;
+}
+
+
 
-			my $oneline64 = $registry{'Registry'} . "\t" . $registry{'Root'} . "\t" . $registry{'Key'} . "\t"
-						. $registry{'Name'} . "\t" . $registry{'Val64'} . "\t" . $registry{'Component_'} . "\n";
 
-			if ( ! ( $style =~ /\bX64_ONLY\b/ )) { push(@registrytable, $oneline); }	# standard registry table for 32 Bit 
-			if (( $style =~ /\bX64\b/ ) || ( $style =~ /\bX64_ONLY\b/ )) { push(@reg64table , $oneline64); }
+sub translate_component_names ($$$)
+{
+    my ($translation_map, $registry_items, $table_data) = @_;
+
+    my $replacement_count = 0;
+    foreach my $item (@$registry_items)
+    {
+        my $translated_name = $translation_map->{$item->{'componentname'}};
+        if (defined $translated_name)
+        {
+            $item->{'componentname'} = $translated_name;
+            ++$replacement_count;
+        }
+    }
+    $installer::logger::Lang->printf("replaced %d component names in registry items\n", $replacement_count);
+
+    $replacement_count = 0;
+    foreach my $language_data (values %$table_data)
+    {
+        foreach my $item (@$language_data)
+        {
+            my $translated_name = $translation_map->{$item->{'Component_'}};
+            if (defined $translated_name)
+            {
+                $item->{'Component_'} = $translated_name;
+                ++$replacement_count;
+            }
+        }
+    }
+    $installer::logger::Lang->printf("replaced %d component names in registry table\n", $replacement_count);
+}
+
+
+
+
+sub create_registry_table_32 ($$$$)
+{
+	my ($basedir, $languagesarrayref, $allvariableshashref, $table_data) = @_;
+
+	foreach my $onelanguage (@$languagesarrayref)
+	{
+		my @registrytable = ();
+        installer::windows::idtglobal::write_idt_header(\@registrytable, "registry");
+
+		foreach my $item (@{$table_data->{$onelanguage}})
+		{
+			next if $item->{'styles'} =~ /\bX64_ONLY\b/;
+            
+			my $oneline = join("\t",
+                $item->{'Registry'},
+                $item->{'Root'},
+                $item->{'Key'},
+                $item->{'Name'},
+                $item->{'Value'},
+                $item->{'Component_'})
+                . "\n";
+
+            push(@registrytable, $oneline);
 		}
 
 		# If there are added user registry keys for files collected in
@@ -436,15 +485,47 @@ sub create_registry_table
 		# files in PREDEFINED_OSSHELLNEWDIR, because their component
 		# needs as KeyPath a RegistryItem in HKCU.
 
-		if ( $installer::globals::addeduserregitrykeys ) { add_userregs_to_registry_table(\@registrytable, $allvariableshashref); }
+		if ( $installer::globals::addeduserregitrykeys )
+        {
+            add_userregs_to_registry_table(\@registrytable, $allvariableshashref);
+        }
 
-		# Saving the file
-		
+		# Save the database file.		
 		my $registrytablename = $basedir . $installer::globals::separator . "Registry.idt" . "." . $onelanguage;
 		installer::files::save_file($registrytablename ,\@registrytable);
         $installer::logger::Lang->printf("Created idt file: %s\n", $registrytablename);
+	}
+}
+
+
+
+
+sub create_registry_table_64 ($$$$)
+{
+	my ($basedir, $languagesarrayref, $allvariableshashref, $table_data) = @_;
+
+	foreach my $onelanguage (@$languagesarrayref)
+	{
+        my @reg64table = ();
+		installer::windows::idtglobal::write_idt_header(\@reg64table, "reg64");
+		foreach my $item (@{$table_data->{$onelanguage}})
+        {
+			next unless $item->{'styles'} =~ /\b(X64|X64_ONLY)\b/;
+
+            my $oneline64 = join("\t",
+                $item->{'Registry'},
+                $item->{'Root'},
+                $item->{'Key'},
+                $item->{'Name'},
+                $item->{'Val64'},
+                $item->{'Component_'})
+                . "\n";
+
+            push(@reg64table , $oneline64);
+        }
 
-		$registrytablename = $basedir . $installer::globals::separator . "Reg64.idt" . "." . $onelanguage;
+        # Save the database file.
+		my $registrytablename = $basedir . $installer::globals::separator . "Reg64.idt" . "." . $onelanguage;
 		installer::files::save_file($registrytablename ,\@reg64table );
         $installer::logger::Lang->printf("Created idt file: %s\n", $registrytablename);
 	}