bldsystemtools/commonbldutils/ReleaseNotes.pl
changeset 0 83f4b4db085c
child 1 d4b442d23379
--- /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 <<HEADING_EOF;
+<html>\n\n<head>\n<title>$ProductName</title>\n</head>\n\n
+<body bgcolor=\"#ffffff\" text=\"#000000\" link=\"#5F9F9F\" vlink=\"5F9F9F\">\n
+<font face=verdana,arial,helvetica size=4>\n\n<hr>\n\n
+<a name=\"list\"><h1><center>$ProductName</center></h1></a>
+<p><center>Created - $mday/$mon/$year</center>\n
+<p><center>----------------------------------------</center>\n
+<h2><center>GT Components</center></h2>\n
+HEADING_EOF
+
+foreach my $element(@ComponentAndSource)
+	{
+	my $Preform = 0;
+	my $ChangeCount = 0;
+	my $Exists = 0;
+	my $IsAFile = 0;
+	
+	if($element =~ /\*\*TECHVIEWCOMPONENTS\*\*/)
+		{
+		print OUTFILE "<h2><center>Techview Components</center></h2>\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/\&/&amp;/g;
+      		$line =~ s/\</&lt;/g;
+     		$line =~ s/\>/&gt;/g;
+      		$line =~ s/\"/&quot;/g;
+	      		
+			if($line =~ /^Change\s(\d+)\s/)
+				{
+				my $Change = $1;
+				
+				$ChangeExists = 0;
+				
+				$line =~ s|\s+by.*||;
+				if ($Preform) 
+          			{ 
+          			push @CompLines, "</pre>"; 
+          			$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, "<p><b>$line</b>";
+        			push @CompLines, "<pre>";
+    				}
+    			
+    			$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, "</pre>";
+			}
+		
+		#Populate the changed components array with all changed components
+		foreach my $entry(@ChangedComponents)
+			{
+			if($entry eq $CompName)
+				{
+				$Exists = 1;
+				}
+			}
+			
+		if($Exists == 0)
+			{
+			&PrintLines("<h2>$CompName</h2>",@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("<h2>New Components</h2>", join(", ", sort @NewComponents));
+	}
+	
+if (scalar @FinalUnchangedList)
+	{
+	if($Srcpath =~ m/deliver/i)
+		{
+		&PrintLines("<h2>Unchanged Components (Delivery)</h2>", join(", ", sort @FinalUnchangedList));
+		}
+	elsif($Srcpath =~ m/release/i)
+		{
+		&PrintLines("<h2>Unchanged Components</h2>", join(", ", sort @FinalUnchangedList));
+		}
+	else
+		{
+		&PrintLines("<h2>Unchanged Components (MCL)</h2>", join(", ", sort @FinalUnchangedList));
+		}
+	}
+
+&PrintLines("</BODY></HTML>");
+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 <Previous> <Current>\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 <<USAGE_EOF;
+
+Usage
+-----
+perl ReleaseNotes.pl <product> <codeline> <previous CL Num> <current CL Num>
+
+Generates an HTML document containing release notes for the specified product.
+
+<product> The product for which the release notes are to be generated
+eg
+  8.0, 8.1a, 8.1b, 9.0, 9.1
+
+
+<codeline> 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/<snapshot_number>
+  For Delivery (8.0) - //EPOC/deliver/product/8.0/2004/<snapshot_number>/src
+
+<previous CL Num> The changelist number of the previous external build
+
+<current CL Num> 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;
+	}
+
+
+
+
+