diff -r 000000000000 -r 83f4b4db085c bldsystemtools/commonbldutils/ReleaseNotes.pl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bldsystemtools/commonbldutils/ReleaseNotes.pl Tue Feb 02 01:39:43 2010 +0200 @@ -0,0 +1,580 @@ +#!perl + +# Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). +# All rights reserved. +# This component and the accompanying materials are made available +# under the terms of "Eclipse Public License v1.0" +# which accompanies this distribution, and is available +# at the URL "http://www.eclipse.org/legal/epl-v10.html". +# +# Initial Contributors: +# Nokia Corporation - initial contribution. +# +# Contributors: +# +# Description: +# GT and TV Release notes generator +# How this script works... +# 1.Creates a list of all GT and TV components with their MRP file locations at both the current and previous CL. +# 2.Iterates through the previous CL list for any components that are not in the current CL list and adds these to +# the currentCL list. +# 3.Runs a p4 print for each MRP file and stores each component and its source(s) to an array. Component names in uppercase +# and source lines in lowercase. +# 4.Iterates through this array extracting each component name and runs "p4 changes -l -s submitted" between the +# previous and current CL for each component source. +# 5.Outputs this data to a HTML file +# +# + +use strict; + +#----------------------------GLOBAL DEFINITIONS-------------------------------------# +my $Product = $ARGV[0]; +my $Srcpath = $ARGV[1]; +my $PrevCL = $ARGV[2]; #Previous external release changelist number +my $CurrentCL = $ARGV[3]; #Current external release changelist number + +my @PrevMrpComponents; #Array of Components at Previous changelist number +my @CurrMrpComponents; #Array of Components at Current changelist number +my @NewMrpComponents; #Array of Merged Components + +my @ComponentAndSource; #Array of all components and source +my @Components; #Array of component names + +my $GTfilename; #Location of GTComponents.txt +my $TVfilename; #Location of TVComponents.txt +my $GTcomponents; #List of all GTComponents and their MRP file locations +my $TVcomponents; #List of all TVComponents and their MRP file locations + +my $CurrentMrps; #List of all GT and TV components at the current CL number +my $PreviousMrps; #List of all GT and TV components at the previous CL number +my $Platform; #Platform of product specified, i.e. beech or cedar + +my @CompChange; #Array of component change information +my @CompLines; #Array of just component changes +my @CompChangelists; #Array of component changelist numbers + +my $CompName; #Component name +my $Topdir; #Directory of component source + +my @NochangeComponents; #Array of components which have not been changed (may contain duplicate components) +my @UnchangedComponents; #Array of non-duplicate components which have not been changed +my @ChangedComponents; #Array of components which have been changed +my @NewComponents; #Array of new components +my $ProductName; #Name of product + +my $ChangeExists; #Flag which indicates any duplicate changes for a component +my $NewComponent; #Flag which indicates if a component is new or not + +my %CodeLine; #Hash for holding main Codeline for each product + +my $Marker = "**TECHVIEWCOMPONENTS**\n"; #Marker for splitting GT and TV Components + +#-----------------------------------------------------------------------------------# + +#Check that correct number of arguments were specified by the user +#If not then print out Usage instructions to the command window +Usage() if (@ARGV!=4); + +#Check that the inputs are valid +CheckInputs(); + +#Assign codeline for product +%CodeLine = ( + "8.0" => "//EPOC/release/8.0", + "8.1a" => "//EPOC/release/8.1", + "8.1b" => "//EPOC/release/8.1", + "9.1" => "//EPOC/master", + "9.2" => "//EPOC/master", + ); + +#Create a list of all components and their MRP files at both the current and previous CL's +CreateMRPLists(); + +#Merge and process the lists +ProcessLists($PreviousMrps, $CurrentMrps); + +#Begin creation of release notes using the merged list of MRPs +$NewComponent = 0; +$NewComponent = 1 if ($PrevCL == 0); + +$PrevCL++; # inc changelist number so we don't include the very first submission - it would have been picked up in the last run of this script + +$ProductName = "Symbian_OS_v$Product Delivery Release Notes" if($Srcpath =~ m/deliver/i); +$ProductName = "Symbian_OS_v$Product Release Notes" if ($Srcpath =~ m/release/i); +if ($Srcpath =~ m/master/i) +{ + $ProductName = "Symbian_OS_v$Product MCL Release Notes"; +} + +my ( $s, $min, $hour, $mday, $mon, $year, $w, $y, $i)= localtime(time); +$year+= 1900; +$mon++; + +open OUTFILE, "> $ProductName.html" + or die "ERROR: Can't open $ProductName.html for output\n$!"; +print OUTFILE <\n\n\n$ProductName\n\n\n +\n +\n\n
\n\n +

$ProductName

+

Created - $mday/$mon/$year
\n +

----------------------------------------
\n +

GT Components

\n +HEADING_EOF + +foreach my $element(@ComponentAndSource) + { + my $Preform = 0; + my $ChangeCount = 0; + my $Exists = 0; + my $IsAFile = 0; + + if($element =~ /\*\*TECHVIEWCOMPONENTS\*\*/) + { + print OUTFILE "

Techview Components

\n"; + } + + if($element =~ /^([A-Z].*)/) #Look for component names in array + { + $CompName = $1; + @CompChangelists = (); + } + + elsif($element =~ /^([a-z].*)/) #Look for source directories in array + { + $Topdir = $1; + $Topdir =~ s/\s+$//; #drop any trailing spaces + + + if($Topdir =~ /.*\s+.*/) + { + $Topdir = "\"$Topdir\""; + } + + my $command = "p4 changes -l -s submitted $Srcpath/$Topdir...\@$PrevCL,$CurrentCL"; + @CompChange = `$command`; + die "ERROR: Could not execute: $command\n" if $?; + + foreach my $line(@CompChange) + { + if ($line !~ /\S/) { next; } # ignore lines with no text + chomp $line; + $line =~ s/\&/&/g; + $line =~ s/\/>/g; + $line =~ s/\"/"/g; + + if($line =~ /^Change\s(\d+)\s/) + { + my $Change = $1; + + $ChangeExists = 0; + + $line =~ s|\s+by.*||; + if ($Preform) + { + push @CompLines, ""; + $Preform = 0; + } + + #Check if this change has already been accounted for in this component + foreach my $ChangeList(@CompChangelists) + { + if($ChangeList == $Change) + { + $ChangeExists = 1; + } + } + + #If the change is not a duplicate then add it to the changes array and output the change + #to Relnotes. + if($ChangeExists == 0) + { + $ChangeCount+=1; + push @CompChangelists, $Change; + push @CompLines, "

$line"; + push @CompLines, "

";
+    				}
+    			
+    			$Preform = 1;
+        		next;
+				}
+				
+			$line =~ s/^\s//;                 # drop first leading whitespace
+   			$line =~ s/^\t/  /;               # shorten any leading tab
+      		
+   			if($ChangeExists == 0)
+   				{
+   				push @CompLines, $line;
+				}
+			}
+		
+		if ($ChangeCount == 0)
+   			{
+    		if ($NewComponent)
+    			{
+    			push @NewComponents, $CompName;
+    			}
+    		else
+    			{	
+    			push @NochangeComponents, $CompName;
+    			}
+    			next;
+    		}
+    		
+    	# Component with real change descriptions
+		if ($Preform)
+			{
+			push @CompLines, "
"; + } + + #Populate the changed components array with all changed components + foreach my $entry(@ChangedComponents) + { + if($entry eq $CompName) + { + $Exists = 1; + } + } + + if($Exists == 0) + { + &PrintLines("

$CompName

",@CompLines); + push @ChangedComponents, $CompName; + } + + else + { + &PrintLines("",@CompLines); + } + } + + @CompLines = (); + } + +#Get rid of any duplicate component entries in the Unchanged Components list. +for(my $ii = 0; $ii < @NochangeComponents; $ii++) + { + if($NochangeComponents[$ii] ne $NochangeComponents[$ii + 1]) + { + push @UnchangedComponents, $NochangeComponents[$ii]; + } + } + +#Check for components which have been changed but still appear in the unchanged components list. +#This can occur when a component has more than one one source. i.e.one source could be changed while the other source +#remains unchanged. +foreach my $changed(@ChangedComponents) + { + foreach my $unchanged(@UnchangedComponents) + { + if($changed eq $unchanged) + { + $unchanged = ""; #Empty this array element + } + } + } + +#Get rid of any empty elements in the unchanged component array +my @FinalUnchangedList; +foreach my $element(@UnchangedComponents) + { + if($element ne "") + { + push @FinalUnchangedList, $element; + } + } + +if (scalar @NewComponents) + { + &PrintLines("

New Components

", join(", ", sort @NewComponents)); + } + +if (scalar @FinalUnchangedList) + { + if($Srcpath =~ m/deliver/i) + { + &PrintLines("

Unchanged Components (Delivery)

", join(", ", sort @FinalUnchangedList)); + } + elsif($Srcpath =~ m/release/i) + { + &PrintLines("

Unchanged Components

", join(", ", sort @FinalUnchangedList)); + } + else + { + &PrintLines("

Unchanged Components (MCL)

", join(", ", sort @FinalUnchangedList)); + } + } + +&PrintLines(""); +close OUTFILE; + +#-------------------------------------------SUB-ROUTINES----------------------------------------------# + +# CheckInputs +# +# Outputs the required platform and an error message if CL numbers are input incorrectly by the user +# +# +sub CheckInputs + { + #Assign appropriate platform + if($Product eq "8.1a"||$Product eq "8.0") + { + $Platform = "beech"; + } + + elsif($Product eq "8.1b"||$Product eq "9.0"||$Product eq "9.1"||$Product eq "9.2") + { + $Platform = "cedar"; + } + + else + { + print "Product not recognised or not entered as first command line argument!!\n"; + exit 1; + } + + #Protect against CL numbers being input incorrectly + if($PrevCL >= $CurrentCL) + { + print "Changelist numbers must be entered in the order \n"; + exit 1; + } + + #Remove any trailing / from $Srcpath + $Srcpath =~ s|/$||; + } + +# CreateMRPLists +# +# Outputs two lists of components and their MRP file locations at the previous and current CL's +# + +sub CreateMRPLists + { + my $Prod; #Temporary variable for product. Needed because of 8.0a directory in Perforce + + #Change directory name to 8.0a if product is 8.0 + if($Product eq "8.0") + { + $Prod = "8.0a"; + } + else + { + $Prod = $Product; + } + + #Obtain GT and TV MRP File locations from Options.txt + my $command = "p4 print -q $CodeLine{$Product}/$Platform/product/tools/makecbr/files/$Prod/options.txt 2>&1"; + my $OptionsFile = `$command`; + die "ERROR: Could not execute: $command\n" if $?; + + my @OptionsFile = split /\n/m, $OptionsFile; + foreach my $line(@OptionsFile) + { + if($line =~ /^Techview component list:(.*)/i) + { + $TVfilename = $1; + $TVfilename =~ s|\\|\/|g; + $TVfilename =~ s|/src/.*?/|$CodeLine{$Product}/$Platform/|; + } + elsif($line =~ /^GT component list:(.*)/i) + { + $GTfilename = $1; + $GTfilename =~ s|\\|\/|g; + $GTfilename =~ s|/src/.*?/|$CodeLine{$Product}/$Platform/|; + } + } + + #Create List of Previous MRPs + my $PrevGT = "p4 print -q $GTfilename...\@$PrevCL 2>&1"; + $GTcomponents = `$PrevGT`; + die "ERROR: Could not execute: $PrevGT\n" if $?; + + my $PrevTV = "p4 print -q $TVfilename...\@$PrevCL 2>&1"; + $TVcomponents = `$PrevTV`; + die "ERROR: Could not execute: $PrevTV\n" if $?; + + $GTcomponents = $GTcomponents.$Marker; + $PreviousMrps = $GTcomponents.$TVcomponents; + + #Create List of Current MRPs + my $CurrGT = "p4 print -q $GTfilename...\@$CurrentCL 2>&1"; + $GTcomponents = `$CurrGT`; + die "ERROR: Could not execute: $CurrGT\n" if $?; + + my $CurrTV = "p4 print -q $TVfilename...\@$CurrentCL 2>&1"; + $TVcomponents = `$CurrTV`; + die "ERROR: Could not execute: $CurrTV\n" if $?; + + $GTcomponents = $GTcomponents.$Marker; + $CurrentMrps = $GTcomponents.$TVcomponents; + } + +# ProcessLists +# +# Inputs - Two lists of Components and their MRP file locations at the previous and current CL's +# +# Outputs a merged list containing all Components in uppercase and their sourcelines in lowercase +# +# Description +# This function creates a list of all components and their MRP files. The MRP files are then used +# to obtain the source for each component. This information is then input to an array in the form +# [COMPONENT1] [source] [COMPONENT2] [source] [source] [COMPONENT3] [source] .......... +# + +sub ProcessLists + { + if(@_ != 2) + { + print "Could not process MRP lists as both lists were not provided.\n"; + exit 1; + } + + my $PreviousMrps = shift; + my $CurrentMrps = shift; + my @MrpContents; + + #Do some slight modifications to source path for both lists + $PreviousMrps =~ s|\\|\/|g; + $PreviousMrps =~ s|/src/|$CodeLine{$Product}/|ig; + $PreviousMrps =~ s|/product/|$CodeLine{$Product}/$Platform/product/|ig; + + $CurrentMrps =~ s|\\|\/|g; + $CurrentMrps =~ s|/src/|$CodeLine{$Product}/|ig; + $CurrentMrps =~ s|/product/|$CodeLine{$Product}/$Platform/product/|ig; + + @PrevMrpComponents = split /\n/m, $PreviousMrps; + @CurrMrpComponents = split /\n/m, $CurrentMrps; + + foreach my $PrevComp(@PrevMrpComponents) + { + my $match = 0; + + #Compare component lists to ensure they contain the same components. + foreach my $CurrComp(@CurrMrpComponents) + { + if($PrevComp eq $CurrComp) + { + $match = 1; + } + } + + #If a component is found in the Previous list which isn't in the Current list, then insert it into the Current list + if($match == 0) + { + push @CurrMrpComponents, $PrevComp; + } + } + + #Use the MRP locations of each component to obtain the source for each component + foreach my $ComponentLine(@CurrMrpComponents) + { + if($ComponentLine =~ /.*\s+(.*)/) + { + my $MrpFile = $1; + + my $Temp = `p4 print -q $MrpFile 2>&1`; + + #If a component has been removed between the PrevCL and CurrentCL then its MRP file will + #only exist at the PrevCL + unless($Temp =~ /source/i) + { + $Temp = `p4 print -q $MrpFile\@$PrevCL 2>&1`; + } + + @MrpContents = split /\n+/m, $Temp; + } + elsif($ComponentLine =~ /\*\*TECHVIEWCOMPONENTS\*\*/) + { + push @MrpContents, $ComponentLine; + } + + #Construct an array containing components in uppercase followed by all their sourcelines in lowercase + foreach my $line(@MrpContents) + { + if($line =~ /^component\s+(.*)/i) + { + my $ComponentName = uc($1); + push @ComponentAndSource, $ComponentName; + } + + if($line =~ /^source\s+(.*)/i) + { + my $Source = lc($1); + $Source =~ s/\\/\//g; + $Source =~ s|/src/||; + $Source =~ s|/product/|$Platform/product|ig; + push @ComponentAndSource, $Source; + } + + if($line =~ /TECHVIEWCOMPONENTS/) + { + push @ComponentAndSource, $line; + } + } + } + } + +# PrintLines +# +# Input - An array containing text information +# +# Outputs each element of the input array seperated by a newline to the OUTFILE +# + +sub PrintLines + { + print OUTFILE join("\n",@_),"\n"; + } + +# Usage +# +# Outputs instructions on how to run this script +# + +sub Usage + { + print < + +Generates an HTML document containing release notes for the specified product. + + The product for which the release notes are to be generated +eg + 8.0, 8.1a, 8.1b, 9.0, 9.1 + + + The codeline on which the perl tool is to be run +eg + For MCL - //EPOC/master + For 8.0 - //EPOC/release/8.0 + For Delivery (MCL) - //EPOC/deliver/master/2004/ + For Delivery (8.0) - //EPOC/deliver/product/8.0/2004//src + + The changelist number of the previous external build + + The changelist number of the current external build candidate + + +Example for MCL codeline +------------------------ + +perl ReleaseNotes.pl 9.0 //EPOC/Master 438931 442567 + +This generates release notes in a file named +Symbian_OS_v9.0 MCL Release Notes.html + +USAGE_EOF + exit 1; + } + + + + +